jruby-openssl 0.9.12-java → 0.9.13-java
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.
- checksums.yaml +4 -4
- data/Rakefile +6 -3
- data/lib/jopenssl.jar +0 -0
- data/lib/jopenssl/load.rb +3 -1
- data/lib/jopenssl/version.rb +8 -3
- data/lib/jopenssl22/openssl/ssl.rb +155 -18
- data/lib/jopenssl23/openssl.rb +19 -0
- data/lib/jopenssl23/openssl/bn.rb +37 -0
- data/lib/jopenssl23/openssl/buffering.rb +453 -0
- data/lib/jopenssl23/openssl/cipher.rb +22 -0
- data/lib/jopenssl23/openssl/config.rb +473 -0
- data/lib/jopenssl23/openssl/digest.rb +48 -0
- data/lib/jopenssl23/openssl/pkey.rb +37 -0
- data/lib/jopenssl23/openssl/ssl.rb +425 -0
- data/lib/jopenssl23/openssl/x509.rb +133 -0
- data/lib/openssl/bn.rb +3 -1
- data/lib/openssl/buffering.rb +3 -1
- data/lib/openssl/cipher.rb +3 -1
- data/lib/openssl/config.rb +3 -1
- data/lib/openssl/digest.rb +3 -1
- data/lib/openssl/pkcs7.rb +2 -6
- data/lib/openssl/pkey.rb +5 -0
- data/lib/openssl/ssl-internal.rb +2 -4
- data/lib/openssl/ssl.rb +3 -1
- data/lib/openssl/x509-internal.rb +2 -4
- data/lib/openssl/x509.rb +3 -1
- metadata +26 -16
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
#--
|
3
|
+
# = Ruby-space predefined Digest subclasses
|
4
|
+
#
|
5
|
+
# = Info
|
6
|
+
# 'OpenSSL for Ruby 2' project
|
7
|
+
# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# = Licence
|
11
|
+
# This program is licensed under the same licence as Ruby.
|
12
|
+
# (See the file 'LICENCE'.)
|
13
|
+
#++
|
14
|
+
|
15
|
+
module OpenSSL
|
16
|
+
class Digest
|
17
|
+
# Deprecated.
|
18
|
+
#
|
19
|
+
# This class is only provided for backwards compatibility.
|
20
|
+
class Digest < Digest # :nodoc:
|
21
|
+
# Deprecated.
|
22
|
+
#
|
23
|
+
# See OpenSSL::Digest.new
|
24
|
+
def initialize(*args)
|
25
|
+
warn('Digest::Digest is deprecated; use Digest')
|
26
|
+
super(*args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end # Digest
|
31
|
+
|
32
|
+
# Returns a Digest subclass by +name+.
|
33
|
+
#
|
34
|
+
# require 'openssl'
|
35
|
+
#
|
36
|
+
# OpenSSL::Digest("MD5")
|
37
|
+
# # => OpenSSL::Digest::MD5
|
38
|
+
#
|
39
|
+
# Digest("Foo")
|
40
|
+
# # => NameError: wrong constant name Foo
|
41
|
+
|
42
|
+
def Digest(name)
|
43
|
+
OpenSSL::Digest.const_get(name)
|
44
|
+
end
|
45
|
+
|
46
|
+
module_function :Digest
|
47
|
+
|
48
|
+
end # OpenSSL
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
module OpenSSL
|
3
|
+
module PKey
|
4
|
+
if defined?(OpenSSL::PKey::DH)
|
5
|
+
|
6
|
+
class DH
|
7
|
+
DEFAULT_512 = new <<-_end_of_pem_
|
8
|
+
-----BEGIN DH PARAMETERS-----
|
9
|
+
MEYCQQD0zXHljRg/mJ9PYLACLv58Cd8VxBxxY7oEuCeURMiTqEhMym16rhhKgZG2
|
10
|
+
zk2O9uUIBIxSj+NKMURHGaFKyIvLAgEC
|
11
|
+
-----END DH PARAMETERS-----
|
12
|
+
_end_of_pem_
|
13
|
+
|
14
|
+
DEFAULT_1024 = new <<-_end_of_pem_
|
15
|
+
-----BEGIN DH PARAMETERS-----
|
16
|
+
MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ
|
17
|
+
AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR
|
18
|
+
T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC
|
19
|
+
-----END DH PARAMETERS-----
|
20
|
+
_end_of_pem_
|
21
|
+
end
|
22
|
+
|
23
|
+
DEFAULT_TMP_DH_CALLBACK = lambda { |ctx, is_export, keylen|
|
24
|
+
warn "using default DH parameters." if $VERBOSE
|
25
|
+
case keylen
|
26
|
+
when 512 then OpenSSL::PKey::DH::DEFAULT_512
|
27
|
+
when 1024 then OpenSSL::PKey::DH::DEFAULT_1024
|
28
|
+
else
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
}
|
32
|
+
|
33
|
+
else
|
34
|
+
DEFAULT_TMP_DH_CALLBACK = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,425 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
=begin
|
3
|
+
= Info
|
4
|
+
'OpenSSL for Ruby 2' project
|
5
|
+
Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
|
6
|
+
All rights reserved.
|
7
|
+
|
8
|
+
= Licence
|
9
|
+
This program is licensed under the same licence as Ruby.
|
10
|
+
(See the file 'LICENCE'.)
|
11
|
+
=end
|
12
|
+
|
13
|
+
require "openssl/buffering"
|
14
|
+
require "io/nonblock"
|
15
|
+
|
16
|
+
module OpenSSL
|
17
|
+
module SSL
|
18
|
+
class SSLContext
|
19
|
+
DEFAULT_PARAMS = {
|
20
|
+
:ssl_version => "SSLv23",
|
21
|
+
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
|
22
|
+
:ciphers => %w{
|
23
|
+
ECDHE-ECDSA-AES128-GCM-SHA256
|
24
|
+
ECDHE-RSA-AES128-GCM-SHA256
|
25
|
+
ECDHE-ECDSA-AES256-GCM-SHA384
|
26
|
+
ECDHE-RSA-AES256-GCM-SHA384
|
27
|
+
DHE-RSA-AES128-GCM-SHA256
|
28
|
+
DHE-DSS-AES128-GCM-SHA256
|
29
|
+
DHE-RSA-AES256-GCM-SHA384
|
30
|
+
DHE-DSS-AES256-GCM-SHA384
|
31
|
+
ECDHE-ECDSA-AES128-SHA256
|
32
|
+
ECDHE-RSA-AES128-SHA256
|
33
|
+
ECDHE-ECDSA-AES128-SHA
|
34
|
+
ECDHE-RSA-AES128-SHA
|
35
|
+
ECDHE-ECDSA-AES256-SHA384
|
36
|
+
ECDHE-RSA-AES256-SHA384
|
37
|
+
ECDHE-ECDSA-AES256-SHA
|
38
|
+
ECDHE-RSA-AES256-SHA
|
39
|
+
DHE-RSA-AES128-SHA256
|
40
|
+
DHE-RSA-AES256-SHA256
|
41
|
+
DHE-RSA-AES128-SHA
|
42
|
+
DHE-RSA-AES256-SHA
|
43
|
+
DHE-DSS-AES128-SHA256
|
44
|
+
DHE-DSS-AES256-SHA256
|
45
|
+
DHE-DSS-AES128-SHA
|
46
|
+
DHE-DSS-AES256-SHA
|
47
|
+
AES128-GCM-SHA256
|
48
|
+
AES256-GCM-SHA384
|
49
|
+
AES128-SHA256
|
50
|
+
AES256-SHA256
|
51
|
+
AES128-SHA
|
52
|
+
AES256-SHA
|
53
|
+
ECDHE-ECDSA-RC4-SHA
|
54
|
+
ECDHE-RSA-RC4-SHA
|
55
|
+
RC4-SHA
|
56
|
+
}.join(":"),
|
57
|
+
:options => -> {
|
58
|
+
opts = OpenSSL::SSL::OP_ALL
|
59
|
+
opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
60
|
+
opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
|
61
|
+
opts |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
|
62
|
+
opts |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
|
63
|
+
opts
|
64
|
+
}.call
|
65
|
+
} unless const_defined? :DEFAULT_PARAMS # JRuby does it in Java
|
66
|
+
|
67
|
+
unless const_defined? :DEFAULT_CERT_STORE # JRuby specific
|
68
|
+
DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
|
69
|
+
DEFAULT_CERT_STORE.set_default_paths
|
70
|
+
if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
|
71
|
+
DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
INIT_VARS = ["cert", "key", "client_ca", "ca_file", "ca_path",
|
76
|
+
"timeout", "verify_mode", "verify_depth", "renegotiation_cb",
|
77
|
+
"verify_callback", "cert_store", "extra_chain_cert",
|
78
|
+
"client_cert_cb", "session_id_context", "tmp_dh_callback",
|
79
|
+
"session_get_cb", "session_new_cb", "session_remove_cb",
|
80
|
+
"tmp_ecdh_callback", "servername_cb", "npn_protocols",
|
81
|
+
"alpn_protocols", "alpn_select_cb",
|
82
|
+
"npn_select_cb"].map { |x| "@#{x}" }
|
83
|
+
|
84
|
+
# A callback invoked when DH parameters are required.
|
85
|
+
#
|
86
|
+
# The callback is invoked with the Session for the key exchange, an
|
87
|
+
# flag indicating the use of an export cipher and the keylength
|
88
|
+
# required.
|
89
|
+
#
|
90
|
+
# The callback must return an OpenSSL::PKey::DH instance of the correct
|
91
|
+
# key length.
|
92
|
+
|
93
|
+
attr_accessor :tmp_dh_callback
|
94
|
+
|
95
|
+
#if ExtConfig::HAVE_TLSEXT_HOST_NAME
|
96
|
+
# A callback invoked at connect time to distinguish between multiple
|
97
|
+
# server names.
|
98
|
+
#
|
99
|
+
# The callback is invoked with an SSLSocket and a server name. The
|
100
|
+
# callback must return an SSLContext for the server name or nil.
|
101
|
+
attr_accessor :servername_cb
|
102
|
+
#end
|
103
|
+
|
104
|
+
# call-seq:
|
105
|
+
# SSLContext.new => ctx
|
106
|
+
# SSLContext.new(:TLSv1) => ctx
|
107
|
+
# SSLContext.new("SSLv23_client") => ctx
|
108
|
+
#
|
109
|
+
# You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
|
110
|
+
def initialize(version = nil)
|
111
|
+
INIT_VARS.each { |v| instance_variable_set v, nil }
|
112
|
+
self.options = self.options | OpenSSL::SSL::OP_ALL
|
113
|
+
return unless version
|
114
|
+
self.ssl_version = version
|
115
|
+
end unless defined? JRUBY_VERSION # JRuby: handled in "native" Java
|
116
|
+
|
117
|
+
##
|
118
|
+
# Sets the parameters for this SSL context to the values in +params+.
|
119
|
+
# The keys in +params+ must be assignment methods on SSLContext.
|
120
|
+
#
|
121
|
+
# If the verify_mode is not VERIFY_NONE and ca_file, ca_path and
|
122
|
+
# cert_store are not set then the system default certificate store is
|
123
|
+
# used.
|
124
|
+
|
125
|
+
def set_params(params={})
|
126
|
+
params = DEFAULT_PARAMS.merge(params)
|
127
|
+
params.each{|name, value| self.__send__("#{name}=", value) }
|
128
|
+
if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
|
129
|
+
unless self.ca_file or self.ca_path or self.cert_store
|
130
|
+
self.cert_store = DEFAULT_CERT_STORE
|
131
|
+
end
|
132
|
+
end
|
133
|
+
return params
|
134
|
+
end unless method_defined? :set_params # JRuby: hooked up in "native" Java
|
135
|
+
end
|
136
|
+
|
137
|
+
module SocketForwarder
|
138
|
+
def addr
|
139
|
+
to_io.addr
|
140
|
+
end
|
141
|
+
|
142
|
+
def peeraddr
|
143
|
+
to_io.peeraddr
|
144
|
+
end
|
145
|
+
|
146
|
+
def setsockopt(level, optname, optval)
|
147
|
+
to_io.setsockopt(level, optname, optval)
|
148
|
+
end
|
149
|
+
|
150
|
+
def getsockopt(level, optname)
|
151
|
+
to_io.getsockopt(level, optname)
|
152
|
+
end
|
153
|
+
|
154
|
+
def fcntl(*args)
|
155
|
+
to_io.fcntl(*args)
|
156
|
+
end
|
157
|
+
|
158
|
+
def closed?
|
159
|
+
to_io.closed?
|
160
|
+
end
|
161
|
+
|
162
|
+
def do_not_reverse_lookup=(flag)
|
163
|
+
to_io.do_not_reverse_lookup = flag
|
164
|
+
end
|
165
|
+
end unless const_defined? :SocketForwarder # JRuby: hooked up in "native" Java
|
166
|
+
|
167
|
+
def verify_certificate_identity(cert, hostname)
|
168
|
+
should_verify_common_name = true
|
169
|
+
cert.extensions.each{|ext|
|
170
|
+
next if ext.oid != "subjectAltName"
|
171
|
+
ext.value.split(/,\s+/).each { |general_name|
|
172
|
+
#case san.tag
|
173
|
+
# MRI 2.2.3 (JRuby parses ASN.1 differently)
|
174
|
+
#when 2 # dNSName in GeneralName (RFC5280)
|
175
|
+
if /\ADNS:(.*)/ =~ general_name
|
176
|
+
should_verify_common_name = false
|
177
|
+
return true if verify_hostname(hostname, $1)
|
178
|
+
# MRI 2.2.3 (JRuby parses ASN.1 differently)
|
179
|
+
#when 7 # iPAddress in GeneralName (RFC5280)
|
180
|
+
elsif /\AIP(?: Address)?:(.*)/ =~ general_name
|
181
|
+
should_verify_common_name = false
|
182
|
+
return true if $1 == hostname
|
183
|
+
# NOTE: bellow logic makes little sense JRuby reads exts differently
|
184
|
+
# follows GENERAL_NAME_print() in x509v3/v3_alt.c
|
185
|
+
#if san.value.size == 4
|
186
|
+
# return true if san.value.unpack('C*').join('.') == hostname
|
187
|
+
#elsif san.value.size == 16
|
188
|
+
# return true if san.value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname
|
189
|
+
#end
|
190
|
+
end
|
191
|
+
}
|
192
|
+
}
|
193
|
+
if should_verify_common_name
|
194
|
+
cert.subject.to_a.each{|oid, value|
|
195
|
+
if oid == "CN"
|
196
|
+
return true if verify_hostname(hostname, value)
|
197
|
+
end
|
198
|
+
}
|
199
|
+
end
|
200
|
+
return false
|
201
|
+
end
|
202
|
+
module_function :verify_certificate_identity
|
203
|
+
|
204
|
+
def verify_hostname(hostname, san) # :nodoc:
|
205
|
+
# RFC 5280, IA5String is limited to the set of ASCII characters
|
206
|
+
return false unless san.ascii_only?
|
207
|
+
return false unless hostname.ascii_only?
|
208
|
+
|
209
|
+
# See RFC 6125, section 6.4.1
|
210
|
+
# Matching is case-insensitive.
|
211
|
+
san_parts = san.downcase.split(".")
|
212
|
+
|
213
|
+
# TODO: this behavior should probably be more strict
|
214
|
+
return san == hostname if san_parts.size < 2
|
215
|
+
|
216
|
+
# Matching is case-insensitive.
|
217
|
+
host_parts = hostname.downcase.split(".")
|
218
|
+
|
219
|
+
# RFC 6125, section 6.4.3, subitem 2.
|
220
|
+
# If the wildcard character is the only character of the left-most
|
221
|
+
# label in the presented identifier, the client SHOULD NOT compare
|
222
|
+
# against anything but the left-most label of the reference
|
223
|
+
# identifier (e.g., *.example.com would match foo.example.com but
|
224
|
+
# not bar.foo.example.com or example.com).
|
225
|
+
return false unless san_parts.size == host_parts.size
|
226
|
+
|
227
|
+
# RFC 6125, section 6.4.3, subitem 1.
|
228
|
+
# The client SHOULD NOT attempt to match a presented identifier in
|
229
|
+
# which the wildcard character comprises a label other than the
|
230
|
+
# left-most label (e.g., do not match bar.*.example.net).
|
231
|
+
return false unless verify_wildcard(host_parts.shift, san_parts.shift)
|
232
|
+
|
233
|
+
san_parts.join(".") == host_parts.join(".")
|
234
|
+
end
|
235
|
+
module_function :verify_hostname
|
236
|
+
|
237
|
+
def verify_wildcard(domain_component, san_component) # :nodoc:
|
238
|
+
parts = san_component.split("*", -1)
|
239
|
+
|
240
|
+
return false if parts.size > 2
|
241
|
+
return san_component == domain_component if parts.size == 1
|
242
|
+
|
243
|
+
# RFC 6125, section 6.4.3, subitem 3.
|
244
|
+
# The client SHOULD NOT attempt to match a presented identifier
|
245
|
+
# where the wildcard character is embedded within an A-label or
|
246
|
+
# U-label of an internationalized domain name.
|
247
|
+
return false if domain_component.start_with?("xn--") && san_component != "*"
|
248
|
+
|
249
|
+
parts[0].length + parts[1].length < domain_component.length &&
|
250
|
+
domain_component.start_with?(parts[0]) &&
|
251
|
+
domain_component.end_with?(parts[1])
|
252
|
+
end
|
253
|
+
module_function :verify_wildcard
|
254
|
+
|
255
|
+
class SSLSocket
|
256
|
+
include Buffering
|
257
|
+
include SocketForwarder
|
258
|
+
|
259
|
+
if ExtConfig::OPENSSL_NO_SOCK
|
260
|
+
def initialize(io, ctx = nil); raise NotImplementedError; end
|
261
|
+
else
|
262
|
+
if ExtConfig::HAVE_TLSEXT_HOST_NAME
|
263
|
+
attr_accessor :hostname
|
264
|
+
end
|
265
|
+
|
266
|
+
attr_reader :io, :context
|
267
|
+
attr_accessor :sync_close
|
268
|
+
alias :to_io :io
|
269
|
+
|
270
|
+
# call-seq:
|
271
|
+
# SSLSocket.new(io) => aSSLSocket
|
272
|
+
# SSLSocket.new(io, ctx) => aSSLSocket
|
273
|
+
#
|
274
|
+
# Creates a new SSL socket from +io+ which must be a real ruby object (not an
|
275
|
+
# IO-like object that responds to read/write).
|
276
|
+
#
|
277
|
+
# If +ctx+ is provided the SSL Sockets initial params will be taken from
|
278
|
+
# the context.
|
279
|
+
#
|
280
|
+
# The OpenSSL::Buffering module provides additional IO methods.
|
281
|
+
#
|
282
|
+
# This method will freeze the SSLContext if one is provided;
|
283
|
+
# however, session management is still allowed in the frozen SSLContext.
|
284
|
+
|
285
|
+
def initialize(io, context = OpenSSL::SSL::SSLContext.new)
|
286
|
+
@io = io
|
287
|
+
@context = context
|
288
|
+
@sync_close = false
|
289
|
+
@hostname = nil
|
290
|
+
@io.nonblock = true if @io.respond_to?(:nonblock=)
|
291
|
+
context.setup
|
292
|
+
super()
|
293
|
+
end
|
294
|
+
end unless defined? JRUBY_VERSION # JRuby: handled in "native" Java
|
295
|
+
|
296
|
+
# call-seq:
|
297
|
+
# ssl.sysclose => nil
|
298
|
+
#
|
299
|
+
# Shuts down the SSL connection and prepares it for another connection.
|
300
|
+
def sysclose
|
301
|
+
return if closed?
|
302
|
+
stop
|
303
|
+
io.close if sync_close
|
304
|
+
end unless defined? JRUBY_VERSION # JRuby: handled in "native" Java
|
305
|
+
|
306
|
+
##
|
307
|
+
# Perform hostname verification after an SSL connection is established
|
308
|
+
#
|
309
|
+
# This method MUST be called after calling #connect to ensure that the
|
310
|
+
# hostname of a remote peer has been verified.
|
311
|
+
def post_connection_check(hostname)
|
312
|
+
if peer_cert.nil?
|
313
|
+
msg = "Peer verification enabled, but no certificate received."
|
314
|
+
if using_anon_cipher?
|
315
|
+
msg += " Anonymous cipher suite #{cipher[0]} was negotiated. Anonymous suites must be disabled to use peer verification."
|
316
|
+
end
|
317
|
+
raise SSLError, msg
|
318
|
+
end
|
319
|
+
|
320
|
+
unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
|
321
|
+
raise SSLError, "hostname \"#{hostname}\" does not match the server certificate"
|
322
|
+
end
|
323
|
+
return true
|
324
|
+
end
|
325
|
+
|
326
|
+
#def session
|
327
|
+
# SSL::Session.new(self)
|
328
|
+
#rescue SSL::Session::SessionError
|
329
|
+
# nil
|
330
|
+
#end
|
331
|
+
|
332
|
+
private
|
333
|
+
|
334
|
+
def using_anon_cipher?
|
335
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
336
|
+
ctx.ciphers = "aNULL"
|
337
|
+
ctx.ciphers.include?(cipher)
|
338
|
+
end
|
339
|
+
|
340
|
+
def client_cert_cb
|
341
|
+
@context.client_cert_cb
|
342
|
+
end
|
343
|
+
|
344
|
+
def tmp_dh_callback
|
345
|
+
@context.tmp_dh_callback || OpenSSL::PKey::DEFAULT_TMP_DH_CALLBACK
|
346
|
+
end
|
347
|
+
|
348
|
+
def tmp_ecdh_callback
|
349
|
+
@context.tmp_ecdh_callback
|
350
|
+
end
|
351
|
+
|
352
|
+
def session_new_cb
|
353
|
+
@context.session_new_cb
|
354
|
+
end
|
355
|
+
|
356
|
+
def session_get_cb
|
357
|
+
@context.session_get_cb
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
##
|
362
|
+
# SSLServer represents a TCP/IP server socket with Secure Sockets Layer.
|
363
|
+
class SSLServer
|
364
|
+
include SocketForwarder
|
365
|
+
# When true then #accept works exactly the same as TCPServer#accept
|
366
|
+
attr_accessor :start_immediately
|
367
|
+
|
368
|
+
# Creates a new instance of SSLServer.
|
369
|
+
# * +srv+ is an instance of TCPServer.
|
370
|
+
# * +ctx+ is an instance of OpenSSL::SSL::SSLContext.
|
371
|
+
def initialize(svr, ctx)
|
372
|
+
@svr = svr
|
373
|
+
@ctx = ctx
|
374
|
+
unless ctx.session_id_context
|
375
|
+
# see #6137 - session id may not exceed 32 bytes
|
376
|
+
prng = ::Random.new($0.hash)
|
377
|
+
session_id = prng.bytes(16).unpack('H*')[0]
|
378
|
+
@ctx.session_id_context = session_id
|
379
|
+
end
|
380
|
+
@start_immediately = true
|
381
|
+
end
|
382
|
+
|
383
|
+
# Returns the TCPServer passed to the SSLServer when initialized.
|
384
|
+
def to_io
|
385
|
+
@svr
|
386
|
+
end
|
387
|
+
|
388
|
+
# See TCPServer#listen for details.
|
389
|
+
def listen(backlog=5)
|
390
|
+
@svr.listen(backlog)
|
391
|
+
end
|
392
|
+
|
393
|
+
# See BasicSocket#shutdown for details.
|
394
|
+
def shutdown(how=Socket::SHUT_RDWR)
|
395
|
+
@svr.shutdown(how)
|
396
|
+
end
|
397
|
+
|
398
|
+
# Works similar to TCPServer#accept.
|
399
|
+
def accept
|
400
|
+
# Socket#accept returns [socket, addrinfo].
|
401
|
+
# TCPServer#accept returns a socket.
|
402
|
+
# The following comma strips addrinfo.
|
403
|
+
sock, = @svr.accept
|
404
|
+
begin
|
405
|
+
ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
|
406
|
+
ssl.sync_close = true
|
407
|
+
ssl.accept if @start_immediately
|
408
|
+
ssl
|
409
|
+
rescue Exception => ex
|
410
|
+
if ssl
|
411
|
+
ssl.close
|
412
|
+
else
|
413
|
+
sock.close
|
414
|
+
end
|
415
|
+
raise ex
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
# See IO#close for details.
|
420
|
+
def close
|
421
|
+
@svr.close
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
425
|
+
end
|