httpx 0.19.1 → 0.19.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,199 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright (c) 2004-2013 Cotag Media
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is furnished
10
- # to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in all
13
- # copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
- #
23
-
24
- class HTTPX::TLS
25
- class Context
26
-
27
- # Based on information from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
28
- CIPHERS = "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"
29
- SESSION = "ruby-tls"
30
-
31
- ALPN_LOOKUP = ::Concurrent::Map.new
32
- ALPN_Select_CB = FFI::Function.new(:int, [
33
- # array of str, unit8 out,uint8 in, *arg
34
- :pointer, :pointer, :pointer, :string, :uint, :pointer
35
- ]) do |ssl_p, out, outlen, inp, inlen, _arg|
36
- ssl = Box::InstanceLookup[ssl_p.address]
37
- return SSL::SSL_TLSEXT_ERR_ALERT_FATAL unless ssl
38
-
39
- protos = ssl.context.alpn_str
40
- status = SSL.SSL_select_next_proto(out, outlen, protos, protos.length, inp, inlen)
41
- ssl.alpn_negotiated
42
-
43
- case status
44
- when SSL::OPENSSL_NPN_UNSUPPORTED
45
- SSL::SSL_TLSEXT_ERR_ALERT_FATAL
46
- when SSL::OPENSSL_NPN_NEGOTIATED
47
- SSL::SSL_TLSEXT_ERR_OK
48
- when SSL::OPENSSL_NPN_NO_OVERLAP
49
- SSL::SSL_TLSEXT_ERR_ALERT_WARNING
50
- end
51
- end
52
-
53
- attr_reader :is_server, :ssl_ctx, :alpn_set, :alpn_str
54
-
55
- def initialize(server, options = {})
56
- @is_server = server
57
-
58
- if @is_server
59
- @ssl_ctx = SSL.SSL_CTX_new(SSL.TLS_server_method)
60
- set_private_key(options[:private_key] || SSL::DEFAULT_PRIVATE)
61
- set_certificate(options[:cert_chain] || SSL::DEFAULT_CERT)
62
- set_client_ca(options[:client_ca])
63
- else
64
- @ssl_ctx = SSL.SSL_CTX_new(SSL.TLS_client_method)
65
- end
66
-
67
- SSL.SSL_CTX_set_options(@ssl_ctx, SSL::SSL_OP_ALL)
68
- SSL.SSL_CTX_set_mode(@ssl_ctx, SSL::SSL_MODE_RELEASE_BUFFERS)
69
-
70
- SSL.SSL_CTX_set_cipher_list(@ssl_ctx, options[:ciphers] || CIPHERS)
71
-
72
- set_min_version(options[:version])
73
-
74
- if @is_server
75
- SSL.SSL_CTX_sess_set_cache_size(@ssl_ctx, 128)
76
- SSL.SSL_CTX_set_session_id_context(@ssl_ctx, SESSION, 8)
77
- else
78
- set_private_key(options[:private_key])
79
- set_certificate(options[:cert_chain])
80
- end
81
- set_alpn_negotiation(options[:protocols])
82
- end
83
-
84
- def cleanup
85
- return unless @ssl_ctx
86
-
87
- SSL.SSL_CTX_free(@ssl_ctx)
88
- @ssl_ctx = nil
89
- end
90
-
91
- def add_server_name_indication
92
- raise Error, "only valid for server mode context" unless @is_server
93
-
94
- SSL.SSL_CTX_set_tlsext_servername_callback(@ssl_ctx, ServerNameCB)
95
- end
96
-
97
- ServerNameCB = FFI::Function.new(:int, %i[pointer pointer pointer]) do |ssl, _, _|
98
- ruby_ssl = Box::InstanceLookup[ssl.address]
99
- return SSL::SSL_TLSEXT_ERR_NOACK unless ruby_ssl
100
-
101
- ctx = ruby_ssl.hosts[SSL.SSL_get_servername(ssl, SSL::TLSEXT_NAMETYPE_host_name)]
102
- if ctx
103
- SSL.SSL_set_SSL_CTX(ssl, ctx.ssl_ctx)
104
- SSL::SSL_TLSEXT_ERR_OK
105
- else
106
- SSL::SSL_TLSEXT_ERR_ALERT_FATAL
107
- end
108
- end
109
-
110
- private
111
-
112
- def self.build_alpn_string(protos)
113
- protos.reduce("".b) do |buffer, proto|
114
- buffer << proto.bytesize
115
- buffer << proto
116
- end
117
- end
118
-
119
- # Version can be one of:
120
- # :SSL3, :TLS1, :TLS1_1, :TLS1_2, :TLS1_3, :TLS_MAX
121
- if SSL::VERSION_SUPPORTED
122
-
123
- def set_min_version(version)
124
- return unless version
125
-
126
- num = SSL.const_get("#{version}_VERSION")
127
- SSL.SSL_CTX_set_min_proto_version(@ssl_ctx, num) == 1
128
- rescue NameError
129
- raise Error, "#{version} is unsupported"
130
- end
131
-
132
- else
133
- def set_min_version(_version); end
134
- end
135
-
136
- if SSL::ALPN_SUPPORTED
137
- def set_alpn_negotiation(protocols)
138
- @alpn_set = false
139
- return unless protocols
140
-
141
- if @is_server
142
- @alpn_str = Context.build_alpn_string(protocols)
143
- SSL.SSL_CTX_set_alpn_select_cb(@ssl_ctx, ALPN_Select_CB, nil)
144
- @alpn_set = true
145
- else
146
- protocols = Context.build_alpn_string(protocols)
147
- @alpn_set = SSL.SSL_CTX_set_alpn_protos(@ssl_ctx, protocols, protocols.length) == 0
148
- end
149
- end
150
- else
151
- def set_alpn_negotiation(_protocols); end
152
- end
153
-
154
- def set_private_key(key)
155
- err = if key.is_a? FFI::Pointer
156
- SSL.SSL_CTX_use_PrivateKey(@ssl_ctx, key)
157
- elsif key && File.file?(key)
158
- SSL.SSL_CTX_use_PrivateKey_file(@ssl_ctx, key, SSL_FILETYPE_PEM)
159
- else
160
- 1
161
- end
162
-
163
- # Check for errors
164
- if err <= 0
165
- # TODO: : ERR_print_errors_fp or ERR_print_errors
166
- # So we can properly log the issue
167
- cleanup
168
- raise Error, "invalid private key or file not found"
169
- end
170
- end
171
-
172
- def set_certificate(cert)
173
- err = if cert.is_a? FFI::Pointer
174
- SSL.SSL_CTX_use_certificate(@ssl_ctx, cert)
175
- elsif cert && File.file?(cert)
176
- SSL.SSL_CTX_use_certificate_chain_file(@ssl_ctx, cert)
177
- else
178
- 1
179
- end
180
-
181
- if err <= 0
182
- cleanup
183
- raise Error, "invalid certificate or file not found"
184
- end
185
- end
186
-
187
- def set_client_ca(ca)
188
- return unless ca
189
-
190
- if File.file?(ca) && (ca_ptr = SSL.SSL_load_client_CA_file(ca))
191
- # there is no error checking provided by SSL_CTX_set_client_CA_list
192
- SSL.SSL_CTX_set_client_CA_list(@ssl_ctx, ca_ptr)
193
- else
194
- cleanup
195
- raise Error, "invalid ca certificate or file not found"
196
- end
197
- end
198
- end
199
- end
@@ -1,390 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "ffi"
4
- require "ffi-compiler/loader"
5
- require "concurrent"
6
-
7
- # Copyright (c) 2004-2013 Cotag Media
8
- #
9
- # Permission is hereby granted, free of charge, to any person obtaining a copy
10
- # of this software and associated documentation files (the "Software"), to deal
11
- # in the Software without restriction, including without limitation the rights
12
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
- # copies of the Software, and to permit persons to whom the Software is furnished
14
- # to do so, subject to the following conditions:
15
- #
16
- # The above copyright notice and this permission notice shall be included in all
17
- # copies or substantial portions of the Software.
18
- #
19
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
- # THE SOFTWARE.
26
- #
27
-
28
- module HTTPX::TLS::SSL
29
- Error = HTTPX::TLS::Error
30
-
31
- extend FFI::Library
32
-
33
- if FFI::Platform.windows?
34
- begin
35
- ffi_lib "libeay32", "ssleay32"
36
- rescue LoadError
37
- ffi_lib "libcrypto-1_1-x64", "libssl-1_1-x64"
38
- end
39
- else
40
- ffi_lib "ssl"
41
- end
42
-
43
- # Common structures
44
- typedef :pointer, :user_data
45
- typedef :pointer, :bio
46
- typedef :pointer, :evp_key
47
- typedef :pointer, :evp_key_pointer
48
- typedef :pointer, :x509
49
- typedef :pointer, :x509_pointer
50
- typedef :pointer, :ssl
51
- typedef :pointer, :cipher
52
- typedef :pointer, :ssl_ctx
53
- typedef :int, :buffer_length
54
- typedef :int, :pass_length
55
- typedef :int, :read_write_flag
56
-
57
- SSL_ST_OK = 0x03
58
- begin
59
- attach_function :SSL_library_init, [], :int
60
- attach_function :SSL_load_error_strings, [], :void
61
- attach_function :ERR_load_crypto_strings, [], :void
62
-
63
- attach_function :SSL_state, [:ssl], :int
64
- def self.is_init_finished(ssl)
65
- SSL_state(ssl) == SSL_ST_OK
66
- end
67
-
68
- OPENSSL_V1_1 = false
69
- rescue FFI::NotFoundError
70
- OPENSSL_V1_1 = true
71
- OPENSSL_INIT_LOAD_SSL_STRINGS = 0x200000
72
- OPENSSL_INIT_NO_LOAD_SSL_STRINGS = 0x100000
73
- attach_function :OPENSSL_init_ssl, %i[uint64 pointer], :int
74
-
75
- attach_function :SSL_get_state, [:ssl], :int
76
- attach_function :SSL_is_init_finished, [:ssl], :bool
77
-
78
- def self.is_init_finished(ssl)
79
- SSL_is_init_finished(ssl)
80
- end
81
- end
82
-
83
- # Multi-threaded support
84
- # callback :locking_cb, [:int, :int, :string, :int], :void
85
- # callback :thread_id_cb, [], :ulong
86
- # attach_function :CRYPTO_num_locks, [], :int
87
- # attach_function :CRYPTO_set_locking_callback, [:locking_cb], :void
88
- # attach_function :CRYPTO_set_id_callback, [:thread_id_cb], :void
89
-
90
- # InitializeDefaultCredentials
91
- attach_function :BIO_new_mem_buf, %i[string buffer_length], :bio
92
- attach_function :EVP_PKEY_free, [:evp_key], :void
93
-
94
- callback :pem_password_cb, %i[pointer buffer_length read_write_flag user_data], :pass_length
95
- attach_function :PEM_read_bio_PrivateKey, %i[bio evp_key_pointer pem_password_cb user_data], :evp_key
96
-
97
- attach_function :X509_free, [:x509], :void
98
- attach_function :PEM_read_bio_X509, %i[bio x509_pointer pem_password_cb user_data], :x509
99
-
100
- attach_function :BIO_free, [:bio], :int
101
-
102
- # GetPeerCert
103
- attach_function :SSL_get_peer_certificate, [:ssl], :x509
104
-
105
- # PutPlaintext
106
- attach_function :SSL_write, %i[ssl buffer_in buffer_length], :int
107
- attach_function :SSL_get_error, %i[ssl int], :int
108
-
109
- # GetCiphertext
110
- attach_function :BIO_read, %i[bio buffer_out buffer_length], :int
111
-
112
- # CanGetCiphertext
113
- attach_function :BIO_ctrl, %i[bio int long pointer], :long
114
- BIO_CTRL_PENDING = 10 # opt - is their more data buffered?
115
- def self.BIO_pending(bio)
116
- BIO_ctrl(bio, BIO_CTRL_PENDING, 0, nil)
117
- end
118
-
119
- # GetPlaintext
120
- attach_function :SSL_accept, [:ssl], :int
121
- attach_function :SSL_read, %i[ssl buffer_out buffer_length], :int
122
- attach_function :SSL_pending, [:ssl], :int
123
-
124
- # PutCiphertext
125
- attach_function :BIO_write, %i[bio buffer_in buffer_length], :int
126
-
127
- # Deconstructor
128
- attach_function :SSL_get_shutdown, [:ssl], :int
129
- attach_function :SSL_shutdown, [:ssl], :int
130
- attach_function :SSL_clear, [:ssl], :void
131
- attach_function :SSL_free, [:ssl], :void
132
-
133
- # Constructor
134
- attach_function :BIO_s_mem, [], :pointer
135
- attach_function :BIO_new, [:pointer], :bio
136
- attach_function :SSL_new, [:ssl_ctx], :ssl
137
- # r, w
138
- attach_function :SSL_set_bio, %i[ssl bio bio], :void
139
-
140
- attach_function :SSL_set_ex_data, %i[ssl int string], :int
141
- callback :verify_callback, %i[int x509], :int
142
- attach_function :SSL_set_verify, %i[ssl int verify_callback], :void
143
- attach_function :SSL_CTX_set_verify, %i[ssl int verify_callback], :void
144
- attach_function :SSL_get_verify_result, %i[ssl], :long
145
- attach_function :SSL_connect, [:ssl], :int
146
-
147
- # Verify callback
148
- X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2
149
- X509_V_ERR_HOSTNAME_MISMATCH = 62
150
- X509_V_ERR_CERT_REJECTED = 28
151
- attach_function :X509_STORE_CTX_get_current_cert, [:pointer], :x509
152
- attach_function :SSL_get_ex_data_X509_STORE_CTX_idx, [], :int
153
- attach_function :X509_STORE_CTX_get_ex_data, %i[pointer int], :ssl
154
- attach_function :X509_STORE_CTX_get_error_depth, %i[x509], :int
155
- attach_function :PEM_write_bio_X509, %i[bio x509], :bool
156
- attach_function :X509_verify_cert_error_string, %i[long], :string
157
- attach_function :X509_STORE_CTX_set_error, %i[ssl_ctx long], :void
158
-
159
- # SSL Context Class
160
- # OpenSSL before 1.1.0 do not have these methods
161
- # https://www.openssl.org/docs/man1.1.0/ssl/TLSv1_2_server_method.html
162
- begin
163
- attach_function :TLS_server_method, [], :pointer
164
- attach_function :TLS_client_method, [], :pointer
165
- rescue FFI::NotFoundError
166
- attach_function :SSLv23_server_method, [], :pointer
167
- attach_function :SSLv23_client_method, [], :pointer
168
-
169
- def self.TLS_server_method
170
- self.SSLv23_server_method
171
- end
172
-
173
- def self.TLS_client_method
174
- self.SSLv23_client_method
175
- end
176
- end
177
-
178
- # Version can be one of:
179
- # :SSL3, :TLS1, :TLS1_1, :TLS1_2, :TLS1_3, :TLS_MAX
180
- begin
181
- attach_function :SSL_get_version, %i[ssl], :string
182
- attach_function :SSL_get_current_cipher, %i[ssl], :cipher
183
- attach_function :SSL_CIPHER_get_name, %i[cipher], :string
184
- attach_function :SSL_CTX_set_min_proto_version, %i[ssl_ctx int], :int
185
- attach_function :SSL_CTX_set_max_proto_version, %i[ssl_ctx int], :int
186
-
187
- VERSION_SUPPORTED = true
188
-
189
- SSL3_VERSION = 0x0300
190
- TLS1_VERSION = 0x0301
191
- TLS1_1_VERSION = 0x0302
192
- TLS1_2_VERSION = 0x0303
193
- TLS1_3_VERSION = 0x0304
194
- TLS_MAX_VERSION = TLS1_3_VERSION
195
- ANY_VERSION = 0
196
- rescue FFI::NotFoundError
197
- VERSION_SUPPORTED = false
198
- end
199
-
200
- def self.get_version(ssl)
201
- SSL_get_version(ssl)
202
- end
203
-
204
- def self.get_current_cipher(ssl)
205
- cipher = SSL_get_current_cipher(ssl)
206
- SSL_CIPHER_get_name(cipher)
207
- end
208
-
209
- attach_function :SSL_CTX_new, [:pointer], :ssl_ctx
210
-
211
- attach_function :SSL_CTX_ctrl, %i[ssl_ctx int ulong pointer], :long
212
- SSL_CTRL_OPTIONS = 32
213
- def self.SSL_CTX_set_options(ssl_ctx, op)
214
- SSL_CTX_ctrl(ssl_ctx, SSL_CTRL_OPTIONS, op, nil)
215
- end
216
- SSL_CTRL_MODE = 33
217
- def self.SSL_CTX_set_mode(ssl_ctx, op)
218
- SSL_CTX_ctrl(ssl_ctx, SSL_CTRL_MODE, op, nil)
219
- end
220
- SSL_CTRL_SET_SESS_CACHE_SIZE = 42
221
- def self.SSL_CTX_sess_set_cache_size(ssl_ctx, op)
222
- SSL_CTX_ctrl(ssl_ctx, SSL_CTRL_SET_SESS_CACHE_SIZE, op, nil)
223
- end
224
-
225
- attach_function :SSL_ctrl, %i[ssl int long pointer], :long
226
- SSL_CTRL_SET_TLSEXT_HOSTNAME = 55
227
-
228
- def self.SSL_set_tlsext_host_name(ssl, host_name)
229
- name_ptr = FFI::MemoryPointer.from_string(host_name)
230
- raise Error, "error setting SNI hostname" if SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, name_ptr).zero?
231
- end
232
-
233
- # Server Name Indication (SNI) Support
234
- # NOTE:: We've hard coded the callback here (SSL defines a NULL callback)
235
- callback :ssl_servername_cb, %i[ssl pointer pointer], :int
236
- attach_function :SSL_CTX_callback_ctrl, %i[ssl_ctx int ssl_servername_cb], :long
237
- SSL_CTRL_SET_TLSEXT_SERVERNAME_CB = 53
238
- def self.SSL_CTX_set_tlsext_servername_callback(ctx, callback)
239
- SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, callback)
240
- end
241
-
242
- attach_function :SSL_get_servername, %i[ssl int], :string
243
- TLSEXT_NAMETYPE_host_name = 0
244
-
245
- attach_function :SSL_set_SSL_CTX, %i[ssl ssl_ctx], :ssl_ctx
246
-
247
- SSL_TLSEXT_ERR_OK = 0
248
- SSL_TLSEXT_ERR_ALERT_WARNING = 1
249
- SSL_TLSEXT_ERR_ALERT_FATAL = 2
250
- SSL_TLSEXT_ERR_NOACK = 3
251
-
252
- attach_function :SSL_CTX_use_PrivateKey_file, %i[ssl_ctx string int], :int, :blocking => true
253
- attach_function :SSL_CTX_use_PrivateKey, %i[ssl_ctx pointer], :int
254
- attach_function :ERR_print_errors_fp, [:pointer], :void # Pointer == File Handle
255
- attach_function :SSL_CTX_use_certificate_chain_file, %i[ssl_ctx string], :int, :blocking => true
256
- attach_function :SSL_CTX_use_certificate, %i[ssl_ctx x509], :int
257
- attach_function :SSL_CTX_set_cipher_list, %i[ssl_ctx string], :int
258
- attach_function :SSL_CTX_set_session_id_context, %i[ssl_ctx string buffer_length], :int
259
- attach_function :SSL_load_client_CA_file, [:string], :pointer
260
- attach_function :SSL_CTX_set_client_CA_list, %i[ssl_ctx pointer], :void
261
- attach_function :SSL_CTX_load_verify_locations, %i[ssl_ctx pointer], :int, :blocking => true
262
-
263
- # OpenSSL before 1.0.2 do not have these methods
264
- begin
265
- attach_function :SSL_CTX_set_alpn_protos, %i[ssl_ctx string uint], :int
266
-
267
- OPENSSL_NPN_UNSUPPORTED = 0
268
- OPENSSL_NPN_NEGOTIATED = 1
269
- OPENSSL_NPN_NO_OVERLAP = 2
270
-
271
- attach_function :SSL_select_next_proto, %i[pointer pointer string uint string uint], :int
272
-
273
- # array of str, unit8 out,uint8 in, *arg
274
- callback :alpn_select_cb, %i[ssl pointer pointer string uint pointer], :int
275
- attach_function :SSL_CTX_set_alpn_select_cb, %i[ssl_ctx alpn_select_cb pointer], :void
276
-
277
- attach_function :SSL_get0_alpn_selected, %i[ssl pointer pointer], :void
278
- ALPN_SUPPORTED = true
279
- rescue FFI::NotFoundError
280
- ALPN_SUPPORTED = false
281
- end
282
-
283
- # Deconstructor
284
- attach_function :SSL_CTX_free, [:ssl_ctx], :void
285
-
286
- PrivateMaterials = <<~KEYSTR
287
- -----BEGIN RSA PRIVATE KEY-----
288
- MIICXAIBAAKBgQDCYYhcw6cGRbhBVShKmbWm7UVsEoBnUf0cCh8AX+MKhMxwVDWV
289
- Igdskntn3cSJjRtmgVJHIK0lpb/FYHQB93Ohpd9/Z18pDmovfFF9nDbFF0t39hJ/
290
- AqSzFB3GiVPoFFZJEE1vJqh+3jzsSF5K56bZ6azz38VlZgXeSozNW5bXkQIDAQAB
291
- AoGALA89gIFcr6BIBo8N5fL3aNHpZXjAICtGav+kTUpuxSiaym9cAeTHuAVv8Xgk
292
- H2Wbq11uz+6JMLpkQJH/WZ7EV59DPOicXrp0Imr73F3EXBfR7t2EQDYHPMthOA1D
293
- I9EtCzvV608Ze90hiJ7E3guGrGppZfJ+eUWCPgy8CZH1vRECQQDv67rwV/oU1aDo
294
- 6/+d5nqjeW6mWkGqTnUU96jXap8EIw6B+0cUKskwx6mHJv+tEMM2748ZY7b0yBlg
295
- w4KDghbFAkEAz2h8PjSJG55LwqmXih1RONSgdN9hjB12LwXL1CaDh7/lkEhq0PlK
296
- PCAUwQSdM17Sl0Xxm2CZiekTSlwmHrtqXQJAF3+8QJwtV2sRJp8u2zVe37IeH1cJ
297
- xXeHyjTzqZ2803fnjN2iuZvzNr7noOA1/Kp+pFvUZUU5/0G2Ep8zolPUjQJAFA7k
298
- xRdLkzIx3XeNQjwnmLlncyYPRv+qaE3FMpUu7zftuZBnVCJnvXzUxP3vPgKTlzGa
299
- dg5XivDRfsV+okY5uQJBAMV4FesUuLQVEKb6lMs7rzZwpeGQhFDRfywJzfom2TLn
300
- 2RdJQQ3dcgnhdVDgt5o1qkmsqQh8uJrJ9SdyLIaZQIc=
301
- -----END RSA PRIVATE KEY-----
302
- -----BEGIN CERTIFICATE-----
303
- MIID6TCCA1KgAwIBAgIJANm4W/Tzs+s+MA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD
304
- VQQGEwJVUzERMA8GA1UECBMITmV3IFlvcmsxETAPBgNVBAcTCE5ldyBZb3JrMRYw
305
- FAYDVQQKEw1TdGVhbWhlYXQubmV0MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEdMBsG
306
- A1UEAxMUb3BlbmNhLnN0ZWFtaGVhdC5uZXQxKDAmBgkqhkiG9w0BCQEWGWVuZ2lu
307
- ZWVyaW5nQHN0ZWFtaGVhdC5uZXQwHhcNMDYwNTA1MTcwNjAzWhcNMjQwMjIwMTcw
308
- NjAzWjCBqjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQH
309
- EwhOZXcgWW9yazEWMBQGA1UEChMNU3RlYW1oZWF0Lm5ldDEUMBIGA1UECxMLRW5n
310
- aW5lZXJpbmcxHTAbBgNVBAMTFG9wZW5jYS5zdGVhbWhlYXQubmV0MSgwJgYJKoZI
311
- hvcNAQkBFhllbmdpbmVlcmluZ0BzdGVhbWhlYXQubmV0MIGfMA0GCSqGSIb3DQEB
312
- AQUAA4GNADCBiQKBgQDCYYhcw6cGRbhBVShKmbWm7UVsEoBnUf0cCh8AX+MKhMxw
313
- VDWVIgdskntn3cSJjRtmgVJHIK0lpb/FYHQB93Ohpd9/Z18pDmovfFF9nDbFF0t3
314
- 9hJ/AqSzFB3GiVPoFFZJEE1vJqh+3jzsSF5K56bZ6azz38VlZgXeSozNW5bXkQID
315
- AQABo4IBEzCCAQ8wHQYDVR0OBBYEFPJvPd1Fcmd8o/Tm88r+NjYPICCkMIHfBgNV
316
- HSMEgdcwgdSAFPJvPd1Fcmd8o/Tm88r+NjYPICCkoYGwpIGtMIGqMQswCQYDVQQG
317
- EwJVUzERMA8GA1UECBMITmV3IFlvcmsxETAPBgNVBAcTCE5ldyBZb3JrMRYwFAYD
318
- VQQKEw1TdGVhbWhlYXQubmV0MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEdMBsGA1UE
319
- AxMUb3BlbmNhLnN0ZWFtaGVhdC5uZXQxKDAmBgkqhkiG9w0BCQEWGWVuZ2luZWVy
320
- aW5nQHN0ZWFtaGVhdC5uZXSCCQDZuFv087PrPjAMBgNVHRMEBTADAQH/MA0GCSqG
321
- SIb3DQEBBQUAA4GBAC1CXey/4UoLgJiwcEMDxOvW74plks23090iziFIlGgcIhk0
322
- Df6hTAs7H3MWww62ddvR8l07AWfSzSP5L6mDsbvq7EmQsmPODwb6C+i2aF3EDL8j
323
- uw73m4YIGI0Zw2XdBpiOGkx2H56Kya6mJJe/5XORZedh1wpI7zki01tHYbcy
324
- -----END CERTIFICATE-----
325
- KEYSTR
326
-
327
- BuiltinPasswdCB = FFI::Function.new(:int, %i[pointer int int pointer]) do |buffer, _len, _flag, _data|
328
- buffer.write_string("kittycat")
329
- 8
330
- end
331
-
332
- # Save RAM by releasing read and write buffers when they're empty
333
- SSL_MODE_RELEASE_BUFFERS = 0x00000010
334
- SSL_OP_ALL = 0x80000BFF
335
- SSL_FILETYPE_PEM = 1
336
-
337
- # Locking isn't provided as long as all writes are done on the same thread.
338
- # This is my main use case. Happy to enable it if someone requires it and can
339
- # get it to work on MRI Ruby (Currently only works on JRuby and Rubinius)
340
- # as MRI callbacks occur on a thread pool?
341
-
342
- # CRYPTO_LOCK = 0x1
343
- # LockingCB = FFI::Function.new(:void, [:int, :int, :string, :int]) do |mode, type, file, line|
344
- # if (mode & CRYPTO_LOCK) != 0
345
- # SSL_LOCKS[type].lock
346
- # else
347
- # Unlock a lock
348
- # SSL_LOCKS[type].unlock
349
- # end
350
- # end
351
- # ThreadIdCB = FFI::Function.new(:ulong, []) do
352
- # Thread.current.object_id
353
- # end
354
-
355
- # INIT CODE
356
- @init_required ||= false
357
- unless @init_required
358
- if OPENSSL_V1_1
359
- self.OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, ::FFI::Pointer::NULL)
360
- else
361
- self.SSL_load_error_strings
362
- self.SSL_library_init
363
- self.ERR_load_crypto_strings
364
- end
365
-
366
- # Setup multi-threaded support
367
- # SSL_LOCKS = []
368
- # num_locks = self.CRYPTO_num_locks
369
- # num_locks.times { SSL_LOCKS << Mutex.new }
370
-
371
- # self.CRYPTO_set_locking_callback(LockingCB)
372
- # self.CRYPTO_set_id_callback(ThreadIdCB)
373
-
374
- bio = self.BIO_new_mem_buf(PrivateMaterials, PrivateMaterials.bytesize)
375
-
376
- # Get the private key structure
377
- pointer = FFI::MemoryPointer.new(:pointer)
378
- self.PEM_read_bio_PrivateKey(bio, pointer, BuiltinPasswdCB, nil)
379
- DEFAULT_PRIVATE = pointer.get_pointer(0)
380
-
381
- # Get the certificate structure
382
- pointer = FFI::MemoryPointer.new(:pointer)
383
- self.PEM_read_bio_X509(bio, pointer, nil, nil)
384
- DEFAULT_CERT = pointer.get_pointer(0)
385
-
386
- self.BIO_free(bio)
387
-
388
- @init_required = true
389
- end
390
- end