libtls 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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