libtls 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,112 @@
1
+ require 'libtls/raw'
2
+ require 'libtls/exn'
3
+
4
+ module LibTLS
5
+ ##
6
+ # A TLS configuration
7
+ #
8
+ # This object is an abstraction over the libtls configuration. It can be used
9
+ # as a shorthand for configuring the struct tls context.
10
+ #
11
+ # config = LibTLS::Config.new(
12
+ # ca_path: '/etc/ssl',
13
+ # key_mem: [key_ptr, 512]
14
+ # )
15
+ # LibTLS::Raw.tls_configure(ctx, config.as_raw)
16
+ # config.free
17
+ class Config
18
+ ##
19
+ # Keys that can be configured
20
+ #
21
+ # This is derived from the +tls_config_set_*+ functions in {LibTLS::Raw}.
22
+ VALID_SET_CONFIGS = %i(
23
+ ca_file ca_path ca_mem cert_file cert_mem ciphers dheparams ecdhecurve
24
+ key_file key_mem protocols verify_depth
25
+ )
26
+
27
+ ##
28
+ # Return a new instance of Config
29
+ #
30
+ # @param [Hash] config_hash the Ruby representation of the configuration. The
31
+ # keys are any of {VALID_SET_CONFIGS}; the value is either a scalar value,
32
+ # or an array. The array is splatted into the appropriate C function.
33
+ #
34
+ # @option config_hash [String] ca_file The filename used to load a file containing
35
+ # the root certificates. (_Client_)
36
+ # @option config_hash [String] ca_path The path (directory) which should be
37
+ # searched for root certificates. (_Client_)
38
+ # @option config_hash [[FFI::Pointer, Fixnum]] ca_mem Set the root certificates
39
+ # directly from memory. (_Client_)
40
+ # @option config_hash [String] cert_file Set file from which the public
41
+ # certificate will be read. (_Client_ _and_ _server_)
42
+ # @option config_hash [[FFI::Pointer, Fixnum]] cert_mem Set the public
43
+ # certificate directly from memory. (_Client_ _and_ _server_)
44
+ # @option config_hash [String] ciphers Set the list of ciphers that may be
45
+ # used. (_Client_ _and_ _server_)
46
+ # @option config_hash [String] dheparams Set the dheparams option to either
47
+ # "none" (0), "auto" (-1), or "legacy" (1024). The default is "none".
48
+ # (_Server_)
49
+ # @option config_hash [String] ecdhecurve Set the ecdhecurve option to one of
50
+ # "none" (+NID_undef+), "auto" (-1), or any NID value understood by
51
+ # OBJ_txt2nid (3). (_Server_)
52
+ # @option config_hash [String] keyfile Set the file from which the private
53
+ # key will be read. (_Server_)
54
+ # @option config_hash [[FFI::Pointer, Fixnum]] key_mem Directly set the
55
+ # private key from memory. (_Server_)
56
+ # @option config_hash [Fixnum] protocols Sets which versions of the protocol
57
+ # may be used, as documented in {LibTLS::Raw#tls_config_set_protocols}.
58
+ # (_Client_ _and_ _server_)
59
+ # @option config_hash [Fixnum] verify_depth Set the verify depth as
60
+ # documented under SSL_CTX_set_verify_depth(3). (_Client_)
61
+ def initialize(config_hash)
62
+ @config_hash = config_hash
63
+ end
64
+
65
+ ##
66
+ # Convert this object into the C representation
67
+ #
68
+ # This builds a struct tls_config pointer, sets the values on it as dictated
69
+ # by the hash passed in, and returns the struct tls_config pointer.
70
+ #
71
+ # The return value must be freed using {#free}.
72
+ #
73
+ # @return [FFI::Pointer] the completed struct tls_config pointer
74
+ # @raise [LibTLS::UnknownCError] if +tls_config_new+ or the appropriate
75
+ # +tls_config_set_*+ fails
76
+ def as_raw
77
+ @raw_config ||= buld_raw_config
78
+ end
79
+
80
+ ##
81
+ # Release any memory held on to by the C library
82
+ #
83
+ # This method must be called when finished.
84
+ def free
85
+ LibTLS::Raw.tls_config_free(as_raw)
86
+ end
87
+
88
+ private
89
+
90
+ def buld_raw_config
91
+ if (raw = LibTLS::Raw.tls_config_new).null?
92
+ raise LibTLS::UnknownCError, "tls_config_new"
93
+ end
94
+
95
+ valid_config_hash.each do |key, value|
96
+ ret = LibTLS::Raw.send("tls_config_set_#{key}", raw, *value)
97
+
98
+ if ret && ret < 0
99
+ raise LibTLS::UnknownCError, "tls_config_set_#{key}"
100
+ end
101
+ end
102
+
103
+ raw
104
+ end
105
+
106
+ def valid_config_hash
107
+ @config_hash.select do |key, value|
108
+ VALID_SET_CONFIGS.include?(key)
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,22 @@
1
+ module LibTLS
2
+ ##
3
+ # An unknown error occured in the libtls library
4
+ #
5
+ # This exception is raised when a non-TLS issue occurs in the libtls library.
6
+ # If possible, it might be useful to inspect +errno+ when you rescue this
7
+ # exception.
8
+ class UnknownCError < RuntimeError
9
+ ##
10
+ # A description of the error
11
+ #
12
+ # This description contains the C function name.
13
+ def to_s
14
+ "#{super.to_s} failed"
15
+ end
16
+ end
17
+
18
+ ##
19
+ # A known error occured in the libtls library
20
+ class CError < RuntimeError
21
+ end
22
+ end
@@ -0,0 +1,759 @@
1
+ require 'ffi'
2
+
3
+ module LibTLS
4
+ ##
5
+ # Direct access to C functions
6
+ #
7
+ # This module encapsulates the communication between Ruby and the C libtls
8
+ # library.
9
+ #
10
+ # We recommend that you consider the object-oriented API in {LibTLS::Client}
11
+ # and {LibTLS::Server} before reaching for these functions. However, not all
12
+ # functions are accessible via those two classes.
13
+ #
14
+ # The {LibTLS::Server}, {LibTLS::Client}, and {LibTLS::OpenedClient}
15
+ # instances provide access to the +FFI::Pointer+ that is used by functions in
16
+ # this module, so that you can mostly use the OO interface but directly access
17
+ # the C functions when needed.
18
+ #
19
+ # Using functions from here means that you are familiar with the tls_init(3)
20
+ # man page and the +FFI::MemoryPointer+ class.
21
+ #
22
+ # Much of the documentation in this file is taken from the tls_init(3) man
23
+ # page. Such documentation is copyright 2014 Ted Unangst, licensed under the
24
+ # ISC license.
25
+ module Raw
26
+ extend FFI::Library
27
+
28
+ ffi_lib "libtls.so"
29
+
30
+ ##
31
+ # The version of the libtls API.
32
+ TLS_API = 20141031
33
+
34
+ ##
35
+ # Select the TLS 1.0 protocol
36
+ TLS_PROTOCOL_TLSv1_0 = (1 << 1)
37
+ ##
38
+ # Select the TLS 1.1 protocol
39
+ TLS_PROTOCOL_TLSv1_1 = (1 << 2)
40
+ ##
41
+ # Select the TLS 1.2 protocol
42
+ TLS_PROTOCOL_TLSv1_2 = (1 << 3)
43
+ ##
44
+ # Select any TLS 1.x protocol
45
+ TLS_PROTOCOL_TLSv1 = \
46
+ TLS_PROTOCOL_TLSv1_0 | TLS_PROTOCOL_TLSv1_1 | TLS_PROTOCOL_TLSv1_2
47
+
48
+ ##
49
+ # Select any TLS protocol of any version
50
+ TLS_PROTOCOLS_ALL = TLS_PROTOCOL_TLSv1
51
+ ##
52
+ # Select the default, suggested TLS protocol
53
+ #
54
+ # Do not use any protocol except this one unless you understand why you are
55
+ # doing so.
56
+ TLS_PROTOCOLS_DEFAULT = TLS_PROTOCOL_TLSv1_2
57
+
58
+ ##
59
+ # A read operation is necessary to continue
60
+ TLS_READ_AGAIN = -2
61
+ ##
62
+ # A write operation is necessary to continue
63
+ TLS_WRITE_AGAIN = -3
64
+
65
+ ##
66
+ # @!method tls_init()
67
+ #
68
+ # Initialize the libtls library
69
+ #
70
+ # The +tls_init+ function should be called once before any function is used.
71
+ # It may be called more than once, but not concurrently.
72
+ #
73
+ # @return [Fixnum] 0 on success, -1 on error
74
+ attach_function :tls_init, [], :int
75
+
76
+ ##
77
+ # @!method tls_error(ctx)
78
+ #
79
+ # Produce the error message on the context
80
+ #
81
+ # The +tls_error+ function may be used to retrieve a string containing more
82
+ # information about the most recent error.
83
+ #
84
+ # @param ctx [FFI::Pointer] the TLS context
85
+ # @return [String] the error message for the most recent error
86
+ attach_function :tls_error, [:pointer], :string
87
+
88
+ ##
89
+ # @!group Create and free configuration objects
90
+ # @!method tls_config_new()
91
+ #
92
+ # Produce a new +tls_config+ context
93
+ #
94
+ # Before a connection is created, a configuration must be created. The
95
+ # +tls_config_new+ function returns a new default configuration that can be
96
+ # used for future connections. Several functions exist to change the
97
+ # options of the configuration; see below.
98
+ #
99
+ # @return [FFI::Pointer] a +tls_config+ context or +FFI::Pointer::NULL+ on
100
+ # failure. Check using +#null?+.
101
+ attach_function :tls_config_new, [], :pointer
102
+ # @!endgroup
103
+
104
+ ##
105
+ # @!group Create and free configuration objects
106
+ # @!method tls_config_free(config)
107
+ #
108
+ # Free the +tls_config+ object
109
+ #
110
+ # When no more contexts are to be created, the +tls_config+ object should be
111
+ # freed by calling +tls_config_free+.
112
+ #
113
+ # @param config [FFI::Pointer] the TLS config
114
+ # @return [nil] +void+
115
+ attach_function :tls_config_free, [:pointer], :void
116
+ # @!endgroup
117
+
118
+ ##
119
+ # @!method tls_config_parse_protocols(protocols, protostr)
120
+ #
121
+ # Parse a protocol string into a bitmask
122
+ #
123
+ # The +tls_config_parse_protocols+ function parses a protocol string and
124
+ # returns the corresponding value via the +protocols+ argument. This value
125
+ # can then be passed to the {#tls_config_set_protocols} function. The
126
+ # protocol string is a comma or colon separated list of keywords. Valid
127
+ # keywords are +tlsv1.0+, +tlsv1.1+, +tlsv1.2+, +all+ (all supported
128
+ # protocols), +default+ (an alias for +secure+), +legacy+ (an alias for
129
+ # +all+) and +secure+ (currently TLSv1.2 only). If a value has a negative
130
+ # prefix (in the form of a leading exclamation mark) then it is removed
131
+ # from the list of available protocols, rather than being added to it.
132
+ #
133
+ # @param protocols [FFI::Pointer] a +uint32_t+ pointer to store the parse
134
+ # result
135
+ # @param protostr [String] the protocol string
136
+ # @return [Fixnum] 0 on success, -1 on error
137
+ #
138
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
139
+ attach_function :tls_config_parse_protocols, [:uint32_t, :string], :int
140
+
141
+ ##
142
+ # @!group Client configuration
143
+ # @!method tls_config_set_ca_file(config, ca_file)
144
+ #
145
+ # Use the given file as the certificate authority file
146
+ #
147
+ # +tls_config_set_ca_file+ sets the filename used to load a file containing
148
+ # the root certificates.
149
+ #
150
+ # This applies to clients.
151
+ #
152
+ # @param config [FFI::Pointer] the TLS config
153
+ # @param ca_file [String] absolute path to the file containing the root
154
+ # certificates
155
+ # @return [Fixnum] 0 on success, -1 on error
156
+ attach_function :tls_config_set_ca_file, [:pointer, :string], :int
157
+
158
+ ##
159
+ # @!method tls_config_set_ca_path(config, ca_path)
160
+ #
161
+ # Use the directory specified to find the root certificate file
162
+ #
163
+ # +tls_config_set_ca_path+ sets the path (directory) which should be
164
+ # searched for root certificates.
165
+ #
166
+ # This applies to clients.
167
+ #
168
+ # @param config [FFI::Pointer] the TLS config
169
+ # @param ca_path [String] absolute path to the directory containing the
170
+ # root certificates
171
+ # @return [Fixnum] 0 on success, -1 on error
172
+ #
173
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
174
+ attach_function :tls_config_set_ca_path, [:pointer, :string], :int
175
+
176
+ ##
177
+ # @!method tls_config_set_ca_mem(config, cert, len)
178
+ #
179
+ # Use the root certicate from memory
180
+ #
181
+ # +tls_config_set_ca_mem+ sets the root certificates directly from memory.
182
+ #
183
+ # This applies to clients.
184
+ #
185
+ # @param config [FFI::Pointer] the TLS config
186
+ # @param cert [FFI::Pointer] uint8_t pointer to the cert
187
+ # @param len [Fixnum] number of bytes in the cert
188
+ # @return [Fixnum] 0 on success, -1 on error
189
+ #
190
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
191
+ attach_function :tls_config_set_ca_mem, [:pointer, :pointer, :size_t], :int
192
+ # @!endgroup
193
+
194
+ ##
195
+ # @!group Client and server configuration
196
+ # @!method tls_config_set_cert_file(config, cert_file)
197
+ #
198
+ # Use the given file as the certficate file
199
+ #
200
+ # +tls_config_set_ca_file+ sets sets file from which the public certificate
201
+ # will be read.
202
+ #
203
+ # This applies to clients and servers.
204
+ #
205
+ # @param config [FFI::Pointer] the TLS config
206
+ # @param cert_file [String] absolute path to the file containing the public
207
+ # certificate
208
+ # @return [Fixnum] 0 on success, -1 on error
209
+ attach_function :tls_config_set_cert_file, [:pointer, :string], :int
210
+
211
+ ##
212
+ # @!method tls_config_set_cert_mem(config, cert, len)
213
+ #
214
+ # Use the given file as the public certificate
215
+ #
216
+ # +tls_config_set_cert_mem+ sets the public certificate directly from
217
+ # memory.
218
+ #
219
+ # This applies to clients and servers.
220
+ #
221
+ # @param config [FFI::Pointer] the TLS config
222
+ # @param cert [FFI::Pointer] uint8_t pointer to the cert
223
+ # @param len [Fixnum] number of bytes in the cert
224
+ # @return [Fixnum] 0 on success, -1 on error
225
+ #
226
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
227
+ attach_function :tls_config_set_cert_mem, [:pointer, :pointer, :size_t], :int
228
+ # @!endgroup
229
+
230
+ ##
231
+ # @!group Client and server configuration
232
+ # @!method tls_config_set_ciphers(config, ciphers)
233
+ #
234
+ # Use the given list of ciphers
235
+ #
236
+ # +tls_config_set_ciphers+ sets the list of ciphers that may be used.
237
+ #
238
+ # This applies to clients and servers.
239
+ #
240
+ # @param config [FFI::Pointer] the TLS config
241
+ # @param ciphers [String] a list of ciphers to use
242
+ # @return [Fixnum] 0 on success, -1 on error
243
+ attach_function :tls_config_set_ciphers, [:pointer, :string], :int
244
+ # @!endgroup
245
+
246
+ ##
247
+ # @!group Server configuration
248
+ # @!method tls_config_set_dheparams(config, params)
249
+ #
250
+ # Tune the dheparams
251
+ #
252
+ # This applies to servers.
253
+ #
254
+ # @param config [FFI::Pointer] the TLS config
255
+ # @param params [String] one of "none" (0), "auto" (-1), or "legacy"
256
+ # (1024). The default is "none".
257
+ # @return [Fixnum] 0 on success, -1 on error
258
+ #
259
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
260
+ attach_function :tls_config_set_dheparams, [:pointer, :string], :int
261
+
262
+ ##
263
+ # @!method tls_config_set_ecdhecurve(config, name)
264
+ #
265
+ # Use the specified EC DHE curve
266
+ #
267
+ # This applies to servers.
268
+ #
269
+ # @param config [FFI::Pointer] the TLS config
270
+ # @param name one of "none" (+NID_undef+), "auto" (-1), or any NID value
271
+ # understood by OBJ_txt2nid (3).
272
+ # @return [Fixnum] 0 on success, -1 on error
273
+ #
274
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
275
+ attach_function :tls_config_set_ecdhecurve, [:pointer, :string], :int
276
+
277
+ ##
278
+ # @!method tls_config_set_key_file(config, key_file)
279
+ #
280
+ # Set the private key via an absolute file path
281
+ #
282
+ # +tls_config_set_key_file+ sets the file from which the private key will
283
+ # be read.
284
+ #
285
+ # This applies to servers.
286
+ #
287
+ # @param config [FFI::Pointer] the TLS config
288
+ # @param key_file [String] absolute path to a private key in a file
289
+ # @return [Fixnum] 0 on success, -1 on error
290
+ attach_function :tls_config_set_key_file, [:pointer, :string], :int
291
+
292
+ ##
293
+ # @!method tls_config_set_key_mem(config, key, len)
294
+ #
295
+ # Set the private key via a value in memory
296
+ #
297
+ # +tls_config_set_key_mem+ directly sets the private key from memory.
298
+ #
299
+ # This applies to servers.
300
+ #
301
+ # @param config [FFI::Pointer] the TLS config
302
+ # @param key [FFI::Pointer] a uint8_t pointer to the key
303
+ # @param len [Fixnum] number of bytes in the key
304
+ # @return [Fixnum] 0 on success, -1 on error
305
+ #
306
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
307
+ attach_function :tls_config_set_key_mem, [:pointer, :pointer, :size_t], :int
308
+ # @!endgroup
309
+
310
+ ##
311
+ # @!group Client and server configuration
312
+ # @!method tls_config_set_protocols(config, protocols)
313
+ #
314
+ # Select which protocols are to be used
315
+ #
316
+ # +tls_config_set_protocols+ sets which versions of the protocol may be
317
+ # used. Possible values are the bitwise OR of:
318
+ #
319
+ # - {TLS_PROTOCOL_TLSv1_0}
320
+ # - {TLS_PROTOCOL_TLSv1_1}
321
+ # - {TLS_PROTOCOL_TLSv1_2}
322
+ #
323
+ # Additionally, the values {TLS_PROTOCOL_TLSv1} (TLSv1.0, TLSv1.1 and
324
+ # TLSv1.2), {TLS_PROTOCOLS_ALL} (all supported protocols) and
325
+ # {TLS_PROTOCOLS_DEFAULT} (TLSv1.2 only) may be used.
326
+ #
327
+ # This applies to clients and servers.
328
+ #
329
+ # @param config [FFI::Pointer] the TLS config
330
+ # @param protocols [Fixnum] bitmask of the protocols to select
331
+ # @return [nil] +void+
332
+ attach_function :tls_config_set_protocols, [:pointer, :uint], :void
333
+ # @!endgroup
334
+
335
+ ##
336
+ # @!group Client configuration
337
+ # @!method tls_config_set_verify_depth(config, verify_depth)
338
+ #
339
+ # Set the maximum depth for the certificate chain
340
+ #
341
+ # See SSL_CTX_set_verify_depth(3) for details.
342
+ #
343
+ # This applies to clients.
344
+ #
345
+ # @param config [FFI::Pointer] the TLS config
346
+ # @param verify_depth [Fixnum] the maximum depth for certificate chain
347
+ # verification
348
+ # @return [nil] +void+
349
+ #
350
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
351
+ attach_function :tls_config_set_verify_depth, [:pointer, :int], :void
352
+ # @!endgroup
353
+
354
+ ##
355
+ # @!group Server configuration
356
+ # @!method tls_config_clear_keys(config)
357
+ #
358
+ # Clear secret keys from memory
359
+ #
360
+ # +tls_config_clear_keys+ clears any secret keys from memory.
361
+ #
362
+ # This applies to servers.
363
+ #
364
+ # @param config [FFI::Pointer] the TLS config
365
+ # @return [nil] +void+
366
+ #
367
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
368
+ attach_function :tls_config_clear_keys, [:pointer], :void
369
+ # @!endgroup
370
+
371
+ ##
372
+ # @!group Client configuration
373
+ # @!method tls_config_insecure_noverifycert(config)
374
+ #
375
+ # Insecurely disable certficate verification
376
+ #
377
+ # +tls_config_insecure_noverifycert+ disables certificate verification. Be
378
+ # extremely careful when using this option.
379
+ #
380
+ # This applies to clients.
381
+ #
382
+ # @param config [FFI::Pointer] the TLS config
383
+ # @return [nil] +void+
384
+ #
385
+ # @note This method should not be used, and is therefore untested.
386
+ attach_function :tls_config_insecure_noverifycert, [:pointer], :void
387
+
388
+ ##
389
+ # @!method tls_config_insecure_noverifyname(config)
390
+ #
391
+ # Insecurely disable server name verification
392
+ #
393
+ # +tls_config_insecure_noverifyname+ disables server name verification. Be
394
+ # careful when using this option.
395
+ #
396
+ # This applies to clients.
397
+ #
398
+ # @param config [FFI::Pointer] the TLS config
399
+ # @return [nil] +void+
400
+ #
401
+ # @note This method should not be used, and is therefore untested.
402
+ attach_function :tls_config_insecure_noverifyname, [:pointer], :void
403
+
404
+ ##
405
+ # @!method tls_config_verify(config)
406
+ #
407
+ # Restore default verification
408
+ #
409
+ # +tls_config_verify+ reenables server name and certificate verification.
410
+ #
411
+ # This applies to clients.
412
+ #
413
+ # @param config [FFI::Pointer] the TLS config
414
+ # @return [nil] +void+
415
+ #
416
+ # @note While this method is fine, getting to this state is not. This
417
+ # method is therefore untested.
418
+ attach_function :tls_config_verify, [:pointer], :void
419
+ # @!endgroup
420
+
421
+ ##
422
+ # @!group Client and server configuration
423
+ # @!method tls_load_file(file, len, password)
424
+ #
425
+ # Load a certificate or key
426
+ #
427
+ # +tls_load_file+ loads a certificate or key from disk into memory to be
428
+ # loaded with {#tls_config_set_ca_mem}, {#tls_config_set_cert_mem} or
429
+ # {#tls_config_set_key_mem}. A private key will be decrypted if the
430
+ # optional +password+ argument is specified.
431
+ #
432
+ # This applies to clients and servers.
433
+ #
434
+ # @param file [String] the absolute filename
435
+ # @param len [FFI::Pointer] pointer to a +size_t+ storing the number of
436
+ # bytes loaded
437
+ # @param password [String] either +FFI::Pointer::NULL+ or the password for
438
+ # the private key
439
+ # @return [FFI::Pointer] pointer to +uint8_t+, the key
440
+ #
441
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
442
+ attach_function :tls_load_file, [:string, :pointer, :string], :pointer
443
+ # @!endgroup
444
+
445
+ ##
446
+ # @!group Create, prepare, and free a connection context
447
+ # @!method tls_client()
448
+ #
449
+ # Create a client context
450
+ #
451
+ # A tls connection is represented as a context. A new context is created by
452
+ # either the {#tls_client} or {#tls_server} functions. The context can then
453
+ # be configured with the function {#tls_configure}. The same +tls_config+
454
+ # object can be used to configure multiple contexts.
455
+ #
456
+ # +tls_client+ creates a new tls context for client connections.
457
+ #
458
+ # @return [FFI::Pointer] a +tls+ context or +FFI::Pointer::NULL+ on
459
+ # failure. Check using +#null?+.
460
+ attach_function :tls_client, [], :pointer
461
+
462
+ ##
463
+ # @!method tls_server()
464
+ #
465
+ # Create a server context
466
+ #
467
+ # A tls connection is represented as a context. A new context is created by
468
+ # either the {#tls_client} or {#tls_server} functions. The context can then
469
+ # be configured with the function {#tls_configure}. The same +tls_config+
470
+ # object can be used to configure multiple contexts.
471
+ #
472
+ # +tls_server+ creates a new tls context for server connections.
473
+ #
474
+ # @return [FFI::Pointer] a +tls+ context or +FFI::Pointer::NULL+ on
475
+ # failure. Check using +#null?+.
476
+ attach_function :tls_server, [], :pointer
477
+
478
+ ##
479
+ # @!method tls_configure(ctx, config)
480
+ #
481
+ # Apply the configuration to the context
482
+ #
483
+ # +tls_configure+ readies a tls context for use by applying the
484
+ # configuration options.
485
+ #
486
+ # The same +tls_config+ object can be used to configure multiple contexts.
487
+ #
488
+ # @param ctx [FFI::Pointer] a TLS context
489
+ # @param config [FFI::Pointer] the TLS config
490
+ # @return [Fixnum] 0 on success, -1 on error
491
+ attach_function :tls_configure, [:pointer, :pointer], :int
492
+
493
+ ##
494
+ # @!method tls_reset(ctx)
495
+ #
496
+ # Reset a context to a newly-initialized state
497
+ #
498
+ # @param ctx [FFI::Pointer] a TLS context
499
+ # @return [nil] +void+
500
+ #
501
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
502
+ attach_function :tls_reset, [:pointer], :void
503
+
504
+ ##
505
+ # @!method tls_close(ctx)
506
+ #
507
+ # Close the TLS connection
508
+ #
509
+ # After use, a +tls+ context should be closed with +tls_close+, and then
510
+ # freed by calling {#tls_free}. When no more contexts are to be created, the
511
+ # +tls_config+ object should be freed by calling {#tls_config_free}.
512
+ #
513
+ # +tls_close+ closes a connection after use. If the connection was
514
+ # established using +#tls_connect_fds+, only the TLS layer will be closed
515
+ # and it is the caller's responsibility to close the file descriptors.
516
+ #
517
+ # @param ctx [FFI::Pointer] a TLS context
518
+ # @return [Fixnum] 0 on success, -1 on error, {TLS_READ_AGAIN} if a read
519
+ # opreation is necessary to continue, {TLS_WRITE_AGAIN} if a write
520
+ # operation is necessary to continue. In case of a {TLS_READ_AGAIN} or
521
+ # {TLS_WRITE_AGAIN}, the caller should repeat the call.
522
+ attach_function :tls_close, [:pointer], :int
523
+
524
+ ##
525
+ # @!method tls_free(ctx)
526
+ #
527
+ # Free memory for the TLS context
528
+ #
529
+ # After use, a +tls+ context should be closed with +tls_close+, and then
530
+ # freed by calling {#tls_free}. When no more contexts are to be created, the
531
+ # +tls_config+ object should be freed by calling {#tls_config_free}.
532
+ #
533
+ # +tls_free+ frees a tls context after use.
534
+ #
535
+ # @param ctx [FFI::Pointer] a TLS context
536
+ attach_function :tls_free, [:pointer], :void
537
+ # @!endgroup
538
+
539
+ ##
540
+ # @!group Initiate a connection and perform I/O
541
+ # @!method tls_connect(ctx, host, port)
542
+ #
543
+ # Open a TLS connection to the +host+ and +port+
544
+ #
545
+ # A client connection is initiated after configuration by calling
546
+ # +tls_connect+. This function will create a new socket, connect to the
547
+ # specified host and port, and then establish a secure connection.
548
+ #
549
+ # +tls_connect+ connects a client context to the server named by host. The
550
+ # port may be numeric or a service name. If it is +FFI::Pointer::NULL+ then
551
+ # a host of the format "hostname:port" is permitted.
552
+ #
553
+ # @param ctx [FFI::Pointer] a TLS context
554
+ # @param host [String] the server to connect to, as an IPv4 address, an
555
+ # IPv6 address, anything that can be resolved by +getaddrinfo+.
556
+ # @param port [String] the port as a number, service name, or NULL pointer.
557
+ # If it is a NULL pointer, the host is parsed for the port number.
558
+ # @return [Fixnum] 0 on success, -1 on error, {TLS_READ_AGAIN} if a read
559
+ # opreation is necessary to continue, {TLS_WRITE_AGAIN} if a write
560
+ # operation is necessary to continue. In case of a {TLS_READ_AGAIN} or
561
+ # {TLS_WRITE_AGAIN}, the caller should repeat the call.
562
+ attach_function :tls_connect, [:pointer, :string, :string], :int
563
+
564
+ ##
565
+ # @!method tls_connect_fds(ctx, fd_read, fd_write, servername)
566
+ #
567
+ # Upgrade an existing connection to secure
568
+ #
569
+ # +tls_connect_fds+ connects a client context to a pair of existing file
570
+ # descriptors.
571
+ #
572
+ # @param ctx [FFI::Pointer] a TLS context
573
+ # @param fd_read [Fixnum] the read file descriptor
574
+ # @param fd_write [Fixnum] the write file descriptor
575
+ # @param servername [String] the name of the server, as matched in the
576
+ # certificate
577
+ # @return [Fixnum] 0 on success, -1 on error, {TLS_READ_AGAIN} if a read
578
+ # opreation is necessary to continue, {TLS_WRITE_AGAIN} if a write
579
+ # operation is necessary to continue. In case of a {TLS_READ_AGAIN} or
580
+ # {TLS_WRITE_AGAIN}, the caller should repeat the call.
581
+ #
582
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
583
+ attach_function :tls_connect_fds, [:pointer, :int, :int, :string], :int
584
+
585
+ ##
586
+ # @!method tls_connect_servername(ctx, host, port, servername)
587
+ #
588
+ # Open a TLS connection to the +host+ and +port+, verifying against
589
+ # +servername+
590
+ #
591
+ # The +tls_connect_servername+ function has the same behaviour as
592
+ # {#tls_connect}, however the name to use for verification is explicitly
593
+ # provided, rather than being inferred from the host value.
594
+ #
595
+ # @param ctx [FFI::Pointer] a TLS context
596
+ # @param host [String] the server to connect to, as an IPv4 address, an
597
+ # IPv6 address, anything that can be resolved by +getaddrinfo+.
598
+ # @param port [String] the port as a number, service name, or NULL pointer.
599
+ # If it is a NULL pointer, the host is parsed for the port number.
600
+ # @param servername [String] the server name to verify the certificate
601
+ # against
602
+ # @return [Fixnum] 0 on success, -1 on error, {TLS_READ_AGAIN} if a read
603
+ # opreation is necessary to continue, {TLS_WRITE_AGAIN} if a write
604
+ # operation is necessary to continue. In case of a {TLS_READ_AGAIN} or
605
+ # {TLS_WRITE_AGAIN}, the caller should repeat the call.
606
+ #
607
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
608
+ attach_function :tls_connect_servername,
609
+ [:pointer, :string, :string, :string], :int
610
+
611
+ ##
612
+ # @!method tls_connect_socket(ctx, s, servername)
613
+ #
614
+ # Upgrade an existing socket
615
+ #
616
+ # +tls_connect_socket+ connects a client context to an already established
617
+ # socket connection.
618
+ #
619
+ # @param ctx [FFI::Pointer] a TLS context
620
+ # @param s [Fixnum] the file descriptor for a socket
621
+ # @param servername [String] the server name to verify the certificate
622
+ # against
623
+ # @return [Fixnum] 0 on success, -1 on error, {TLS_READ_AGAIN} if a read
624
+ # opreation is necessary to continue, {TLS_WRITE_AGAIN} if a write
625
+ # operation is necessary to continue. In case of a {TLS_READ_AGAIN} or
626
+ # {TLS_WRITE_AGAIN}, the caller should repeat the call.
627
+ #
628
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
629
+ attach_function :tls_connect_socket, [:pointer, :int, :string], :int
630
+
631
+ ##
632
+ # @!method tls_accept_fds(ctx, cctx, fd_read, fd_write)
633
+ #
634
+ # Perform the TLS handshake on an established pair of file descriptors
635
+ #
636
+ # +tls_accept_fds+ creates a new context suitable for reading and writing
637
+ # on an existing pair of file descriptors and returns it in +*cctx+. A
638
+ # configured server context should be passed in +ctx+ and +*cctx+ should be
639
+ # initialized to NULL.
640
+ #
641
+ # @see #tls_accept_socket
642
+ #
643
+ # @param ctx [FFI::Pointer] a TLS context
644
+ # @param cctx [FFI::Pointer] a reference to a TLS context
645
+ # @param fd_read [Fixnum] the read file descriptor
646
+ # @param fd_write [Fixnum] the write file descriptor
647
+ # @return [Fixnum] 0 on success, -1 on error, {TLS_READ_AGAIN} if a read
648
+ # opreation is necessary to continue, {TLS_WRITE_AGAIN} if a write
649
+ # operation is necessary to continue. In case of a {TLS_READ_AGAIN} or
650
+ # {TLS_WRITE_AGAIN}, the caller should repeat the call.
651
+ #
652
+ # @todo This is untested. Please {https://github.com/mike-burns/libtls.rb#contributing contribute a patch}.
653
+ attach_function :tls_accept_fds, [:pointer, :pointer, :int, :int], :int
654
+
655
+ ##
656
+ # @!method tls_accept_socket(ctx, cctx, socket)
657
+ #
658
+ # Perform the TLS handshake on an established socket
659
+ #
660
+ # A server can accept a new client connection by calling
661
+ # +tls_accept_socket+ on an already established socket connection.
662
+ #
663
+ # +tls_accept_socket+ creates a new context suitable for reading and
664
+ # writing on an already established socket connection and returns it in
665
+ # +*cctx+. A configured server context should be passed in +ctx+ and
666
+ # +*cctx+ should be initialized to +NULL+.
667
+ #
668
+ # The pattern looks like this:
669
+ #
670
+ # cctx_ptr = FFI::MemoryPointer.new(:pointer)
671
+ # LibTLS::Raw.tls_accept_socket(ctx, cctx_ptr, client_sock.fileno)
672
+ # cctx = cctx_ptr.read_pointer
673
+ #
674
+ # @param ctx [FFI::Pointer] a TLS context
675
+ # @param cctx [FFI::Pointer] a reference to a TLS context
676
+ # @param socket [Int] the file descriptor of an established socket that is
677
+ # connected to a client. Use +Socket#fileno+ to get the file descriptor
678
+ # of a Socket instance.
679
+ # @return [Fixnum] 0 on success, -1 on error, {TLS_READ_AGAIN} if a read
680
+ # opreation is necessary to continue, {TLS_WRITE_AGAIN} if a write
681
+ # operation is necessary to continue. In case of a {TLS_READ_AGAIN} or
682
+ # {TLS_WRITE_AGAIN}, the caller should repeat the call.
683
+ attach_function :tls_accept_socket, [:pointer, :pointer, :int], :int
684
+
685
+ ##
686
+ # @!method tls_read(ctx, buf, buflen, outlen)
687
+ #
688
+ # Read from the socket
689
+ #
690
+ # +tls_read+ reads +buflen+ bytes of data from the socket into +buf+. The
691
+ # amount of data read is returned in +outlen+.
692
+ #
693
+ # The pattern is as follows:
694
+ #
695
+ #
696
+ # READ_LEN = 1024
697
+ # FFI::MemoryPointer.new(:size_t) do |outlen|
698
+ # FFI::MemoryPointer.new(:uchar, READ_LEN, true) do |buf|
699
+ # loop do
700
+ # if LibTLS::Raw.tls_read(ctx, buf, READ_LEN, outlen) < 0
701
+ # raise LibTLS::CError, "tls_read: #{LibTLS::Raw.tls_error(ctx)}"
702
+ # end
703
+ #
704
+ # do_something_with( buf.get_string(0, outlen.get_int(0)) )
705
+ #
706
+ # if READ_LEN > outlen.get_int(0)
707
+ # break
708
+ # end
709
+ # end
710
+ # end
711
+ # end
712
+ #
713
+ # @param ctx [FFI::Pointer] a TLS context
714
+ # @param buf [FFI::Pointer] allocated memory for a +buflen+ number of
715
+ # +uchars+
716
+ # @param buflen [Fixnum] the number of bytes to read
717
+ # @param outlen [FFI::Pointer] the number of bytes read
718
+ # @return [Fixnum] 0 on success, -1 on error, {TLS_READ_AGAIN} if a read
719
+ # opreation is necessary to continue, {TLS_WRITE_AGAIN} if a write
720
+ # operation is necessary to continue. In the case of a {TLS_READ_AGAIN} the
721
+ # caller should repeat the call. In the case of a {TLS_WRITE_AGAIN}, the
722
+ # caller should call {#tls_write}.
723
+ attach_function :tls_read, [:pointer, :pointer, :size_t, :pointer], :int
724
+
725
+ ##
726
+ # @!method tls_write(ctx, buf, buflen, outlen)
727
+ #
728
+ # Write data to the socket
729
+ #
730
+ # +tls_write+ writes +buflen+ bytes of data from +buf+ to the socket. The
731
+ # amount of data written is returned in +outlen+.
732
+ #
733
+ # The pattern is as follows:
734
+ #
735
+ # STR = "HELLO\r\n"
736
+ #
737
+ # FFI::MemoryPointer.new(:size_t) do |outlen|
738
+ # FFI::MemoryPointer.new(:uchar, STR.length + 1) do |str_ptr|
739
+ # str_ptr.put_string(0, STR)
740
+ #
741
+ # if LibTLS::Raw.tls_write(ctx, str_ptr, STR.length, outlen) < 0
742
+ # raise LibTLS::CError, "tls_write: #{LibTLS::Raw.tls_error(ctx)}"
743
+ # end
744
+ # end
745
+ # end
746
+ #
747
+ # @param ctx [FFI::Pointer] a TLS context
748
+ # @param buf [FFI::Pointer] a pointer to the string of +uchar+s
749
+ # @param buflen [Fixnum] the number of bytes to write
750
+ # @param outlen [FFI::Pointer] the number of bytes written
751
+ # @return [Fixnum] 0 on success, -1 on error, {TLS_READ_AGAIN} if a read
752
+ # opreation is necessary to continue, {TLS_WRITE_AGAIN} if a write
753
+ # operation is necessary to continue. In the case of a {TLS_READ_AGAIN} the
754
+ # caller should call {#tls_read}. In the case of a {TLS_WRITE_AGAIN}, the
755
+ # caller should repeat the call.
756
+ attach_function :tls_write, [:pointer, :pointer, :size_t, :pointer], :int
757
+ # @!endgroup
758
+ end
759
+ end