rubysl-openssl 0.0.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +0 -1
  3. data/.travis.yml +7 -0
  4. data/README.md +2 -2
  5. data/Rakefile +0 -1
  6. data/ext/rubysl/openssl/extconf.h +50 -0
  7. data/ext/rubysl/openssl/extconf.rb +144 -0
  8. data/ext/rubysl/openssl/openssl_missing.c +343 -0
  9. data/ext/rubysl/openssl/openssl_missing.h +191 -0
  10. data/ext/rubysl/openssl/ossl.c +552 -0
  11. data/ext/rubysl/openssl/ossl.h +233 -0
  12. data/ext/rubysl/openssl/ossl_asn1.c +1160 -0
  13. data/ext/rubysl/openssl/ossl_asn1.h +59 -0
  14. data/ext/rubysl/openssl/ossl_bio.c +86 -0
  15. data/ext/rubysl/openssl/ossl_bio.h +21 -0
  16. data/ext/rubysl/openssl/ossl_bn.c +852 -0
  17. data/ext/rubysl/openssl/ossl_bn.h +25 -0
  18. data/ext/rubysl/openssl/ossl_cipher.c +569 -0
  19. data/ext/rubysl/openssl/ossl_cipher.h +22 -0
  20. data/ext/rubysl/openssl/ossl_config.c +75 -0
  21. data/ext/rubysl/openssl/ossl_config.h +22 -0
  22. data/ext/rubysl/openssl/ossl_digest.c +259 -0
  23. data/ext/rubysl/openssl/ossl_digest.h +22 -0
  24. data/ext/rubysl/openssl/ossl_engine.c +411 -0
  25. data/ext/rubysl/openssl/ossl_engine.h +20 -0
  26. data/ext/rubysl/openssl/ossl_hmac.c +268 -0
  27. data/ext/rubysl/openssl/ossl_hmac.h +19 -0
  28. data/ext/rubysl/openssl/ossl_ns_spki.c +257 -0
  29. data/ext/rubysl/openssl/ossl_ns_spki.h +21 -0
  30. data/ext/rubysl/openssl/ossl_ocsp.c +769 -0
  31. data/ext/rubysl/openssl/ossl_ocsp.h +24 -0
  32. data/ext/rubysl/openssl/ossl_pkcs12.c +210 -0
  33. data/ext/rubysl/openssl/ossl_pkcs12.h +15 -0
  34. data/ext/rubysl/openssl/ossl_pkcs5.c +99 -0
  35. data/ext/rubysl/openssl/ossl_pkcs5.h +6 -0
  36. data/ext/rubysl/openssl/ossl_pkcs7.c +1039 -0
  37. data/ext/rubysl/openssl/ossl_pkcs7.h +22 -0
  38. data/ext/rubysl/openssl/ossl_pkey.c +240 -0
  39. data/ext/rubysl/openssl/ossl_pkey.h +141 -0
  40. data/ext/rubysl/openssl/ossl_pkey_dh.c +532 -0
  41. data/ext/rubysl/openssl/ossl_pkey_dsa.c +484 -0
  42. data/ext/rubysl/openssl/ossl_pkey_ec.c +1593 -0
  43. data/ext/rubysl/openssl/ossl_pkey_rsa.c +593 -0
  44. data/ext/rubysl/openssl/ossl_rand.c +202 -0
  45. data/ext/rubysl/openssl/ossl_rand.h +20 -0
  46. data/ext/rubysl/openssl/ossl_ssl.c +1484 -0
  47. data/ext/rubysl/openssl/ossl_ssl.h +36 -0
  48. data/ext/rubysl/openssl/ossl_ssl_session.c +307 -0
  49. data/ext/rubysl/openssl/ossl_version.h +16 -0
  50. data/ext/rubysl/openssl/ossl_x509.c +104 -0
  51. data/ext/rubysl/openssl/ossl_x509.h +114 -0
  52. data/ext/rubysl/openssl/ossl_x509attr.c +274 -0
  53. data/ext/rubysl/openssl/ossl_x509cert.c +764 -0
  54. data/ext/rubysl/openssl/ossl_x509crl.c +535 -0
  55. data/ext/rubysl/openssl/ossl_x509ext.c +458 -0
  56. data/ext/rubysl/openssl/ossl_x509name.c +399 -0
  57. data/ext/rubysl/openssl/ossl_x509req.c +466 -0
  58. data/ext/rubysl/openssl/ossl_x509revoked.c +229 -0
  59. data/ext/rubysl/openssl/ossl_x509store.c +625 -0
  60. data/ext/rubysl/openssl/ruby_missing.h +41 -0
  61. data/lib/openssl.rb +1 -0
  62. data/lib/openssl/bn.rb +35 -0
  63. data/lib/openssl/buffering.rb +241 -0
  64. data/lib/openssl/cipher.rb +65 -0
  65. data/lib/openssl/config.rb +316 -0
  66. data/lib/openssl/digest.rb +61 -0
  67. data/lib/openssl/net/ftptls.rb +53 -0
  68. data/lib/openssl/net/telnets.rb +251 -0
  69. data/lib/openssl/pkcs7.rb +25 -0
  70. data/lib/openssl/ssl-internal.rb +187 -0
  71. data/lib/openssl/ssl.rb +1 -0
  72. data/lib/openssl/x509-internal.rb +153 -0
  73. data/lib/openssl/x509.rb +1 -0
  74. data/lib/rubysl/openssl.rb +28 -0
  75. data/lib/rubysl/openssl/version.rb +5 -0
  76. data/rubysl-openssl.gemspec +19 -18
  77. data/spec/cipher_spec.rb +16 -0
  78. data/spec/config/freeze_spec.rb +17 -0
  79. data/spec/hmac/digest_spec.rb +15 -0
  80. data/spec/hmac/hexdigest_spec.rb +15 -0
  81. data/spec/random/pseudo_bytes_spec.rb +5 -0
  82. data/spec/random/random_bytes_spec.rb +5 -0
  83. data/spec/random/shared/random_bytes.rb +28 -0
  84. data/spec/shared/constants.rb +11 -0
  85. data/spec/x509/name/parse_spec.rb +47 -0
  86. metadata +153 -89
  87. data/lib/rubysl-openssl.rb +0 -7
  88. data/lib/rubysl-openssl/version.rb +0 -5
@@ -0,0 +1,61 @@
1
+ =begin
2
+ = $RCSfile$ -- Ruby-space predefined Digest subclasses
3
+
4
+ = Info
5
+ 'OpenSSL for Ruby 2' project
6
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
7
+ All rights reserved.
8
+
9
+ = Licence
10
+ This program is licenced under the same licence as Ruby.
11
+ (See the file 'LICENCE'.)
12
+
13
+ = Version
14
+ $Id: digest.rb 28004 2010-05-24 23:58:49Z shyouhei $
15
+ =end
16
+
17
+ ##
18
+ # Should we care what if somebody require this file directly?
19
+ #require 'openssl'
20
+
21
+ module OpenSSL
22
+ class Digest
23
+
24
+ alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
25
+ if OPENSSL_VERSION_NUMBER > 0x00908000
26
+ alg += %w(SHA224 SHA256 SHA384 SHA512)
27
+ end
28
+
29
+ def self.digest(name, data)
30
+ super(data, name)
31
+ end
32
+
33
+ alg.each{|name|
34
+ klass = Class.new(Digest){
35
+ define_method(:initialize){|*data|
36
+ if data.length > 1
37
+ raise ArgumentError,
38
+ "wrong number of arguments (#{data.length} for 1)"
39
+ end
40
+ super(name, data.first)
41
+ }
42
+ }
43
+ singleton = (class << klass; self; end)
44
+ singleton.class_eval{
45
+ define_method(:digest){|data| Digest.digest(name, data) }
46
+ define_method(:hexdigest){|data| Digest.hexdigest(name, data) }
47
+ }
48
+ const_set(name, klass)
49
+ }
50
+
51
+ # This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future.
52
+ class Digest < Digest
53
+ def initialize(*args)
54
+ # add warning
55
+ super(*args)
56
+ end
57
+ end
58
+
59
+ end # Digest
60
+ end # OpenSSL
61
+
@@ -0,0 +1,53 @@
1
+ =begin
2
+ = $RCSfile$ -- SSL/TLS enhancement for Net::HTTP.
3
+
4
+ = Info
5
+ 'OpenSSL for Ruby 2' project
6
+ Copyright (C) 2003 Blaz Grilc <farmer@gmx.co.uk>
7
+ All rights reserved.
8
+
9
+ = Licence
10
+ This program is licenced under the same licence as Ruby.
11
+ (See the file 'LICENCE'.)
12
+
13
+ = Requirements
14
+
15
+ = Version
16
+ $Id: ftptls.rb 13657 2007-10-08 11:16:54Z gotoyuzo $
17
+
18
+ = Notes
19
+ Tested on FreeBSD 5-CURRENT and 4-STABLE
20
+ - ruby 1.6.8 (2003-01-17) [i386-freebsd5]
21
+ - OpenSSL 0.9.7a Feb 19 2003
22
+ - ruby-openssl-0.2.0.p0
23
+ tested on ftp server: glftpd 1.30
24
+ =end
25
+
26
+ require 'socket'
27
+ require 'openssl'
28
+ require 'net/ftp'
29
+
30
+ module Net
31
+ class FTPTLS < FTP
32
+ def connect(host, port=FTP_PORT)
33
+ @hostname = host
34
+ super
35
+ end
36
+
37
+ def login(user = "anonymous", passwd = nil, acct = nil)
38
+ store = OpenSSL::X509::Store.new
39
+ store.set_default_paths
40
+ ctx = OpenSSL::SSL::SSLContext.new('SSLv23')
41
+ ctx.cert_store = store
42
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
43
+ ctx.key = nil
44
+ ctx.cert = nil
45
+ voidcmd("AUTH TLS")
46
+ @sock = OpenSSL::SSL::SSLSocket.new(@sock, ctx)
47
+ @sock.connect
48
+ @sock.post_connection_check(@hostname)
49
+ super(user, passwd, acct)
50
+ voidcmd("PBSZ 0")
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,251 @@
1
+ =begin
2
+ = $RCSfile$ -- SSL/TLS enhancement for Net::Telnet.
3
+
4
+ = Info
5
+ 'OpenSSL for Ruby 2' project
6
+ Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
7
+ All rights reserved.
8
+
9
+ = Licence
10
+ This program is licenced under the same licence as Ruby.
11
+ (See the file 'LICENCE'.)
12
+
13
+ = Version
14
+ $Id: telnets.rb 13657 2007-10-08 11:16:54Z gotoyuzo $
15
+
16
+ 2001/11/06: Contiributed to Ruby/OpenSSL project.
17
+
18
+ == class Net::Telnet
19
+
20
+ This class will initiate SSL/TLS session automaticaly if the server
21
+ sent OPT_STARTTLS. Some options are added for SSL/TLS.
22
+
23
+ host = Net::Telnet::new({
24
+ "Host" => "localhost",
25
+ "Port" => "telnets",
26
+ ## follows are new options.
27
+ 'CertFile' => "user.crt",
28
+ 'KeyFile' => "user.key",
29
+ 'CAFile' => "/some/where/certs/casert.pem",
30
+ 'CAPath' => "/some/where/caserts",
31
+ 'VerifyMode' => SSL::VERIFY_PEER,
32
+ 'VerifyCallback' => verify_proc
33
+ })
34
+
35
+ Or, the new options ('Cert', 'Key' and 'CACert') are available from
36
+ Michal Rokos's OpenSSL module.
37
+
38
+ cert_data = File.open("user.crt"){|io| io.read }
39
+ pkey_data = File.open("user.key"){|io| io.read }
40
+ cacert_data = File.open("your_ca.pem"){|io| io.read }
41
+ host = Net::Telnet::new({
42
+ "Host" => "localhost",
43
+ "Port" => "telnets",
44
+ 'Cert' => OpenSSL::X509::Certificate.new(cert_data)
45
+ 'Key' => OpenSSL::PKey::RSA.new(pkey_data)
46
+ 'CACert' => OpenSSL::X509::Certificate.new(cacert_data)
47
+ 'CAFile' => "/some/where/certs/casert.pem",
48
+ 'CAPath' => "/some/where/caserts",
49
+ 'VerifyMode' => SSL::VERIFY_PEER,
50
+ 'VerifyCallback' => verify_proc
51
+ })
52
+
53
+ This class is expected to be a superset of usual Net::Telnet.
54
+ =end
55
+
56
+ require "net/telnet"
57
+ require "openssl"
58
+
59
+ module Net
60
+ class Telnet
61
+ attr_reader :ssl
62
+
63
+ OPT_STARTTLS = 46.chr # "\056" # "\x2e" # Start TLS
64
+ TLS_FOLLOWS = 1.chr # "\001" # "\x01" # FOLLOWS (for STARTTLS)
65
+
66
+ alias preprocess_orig preprocess
67
+
68
+ def ssl?; @ssl; end
69
+
70
+ def preprocess(string)
71
+ # combine CR+NULL into CR
72
+ string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"]
73
+
74
+ # combine EOL into "\n"
75
+ string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"]
76
+
77
+ string.gsub(/#{IAC}(
78
+ [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]|
79
+ [#{DO}#{DONT}#{WILL}#{WONT}][#{OPT_BINARY}-#{OPT_EXOPL}]|
80
+ #{SB}[#{OPT_BINARY}-#{OPT_EXOPL}]
81
+ (#{IAC}#{IAC}|[^#{IAC}])+#{IAC}#{SE}
82
+ )/xno) do
83
+ if IAC == $1 # handle escaped IAC characters
84
+ IAC
85
+ elsif AYT == $1 # respond to "IAC AYT" (are you there)
86
+ self.write("nobody here but us pigeons" + EOL)
87
+ ''
88
+ elsif DO[0] == $1[0] # respond to "IAC DO x"
89
+ if OPT_BINARY[0] == $1[1]
90
+ @telnet_option["BINARY"] = true
91
+ self.write(IAC + WILL + OPT_BINARY)
92
+ elsif OPT_STARTTLS[0] == $1[1]
93
+ self.write(IAC + WILL + OPT_STARTTLS)
94
+ self.write(IAC + SB + OPT_STARTTLS + TLS_FOLLOWS + IAC + SE)
95
+ else
96
+ self.write(IAC + WONT + $1[1..1])
97
+ end
98
+ ''
99
+ elsif DONT[0] == $1[0] # respond to "IAC DON'T x" with "IAC WON'T x"
100
+ self.write(IAC + WONT + $1[1..1])
101
+ ''
102
+ elsif WILL[0] == $1[0] # respond to "IAC WILL x"
103
+ if OPT_BINARY[0] == $1[1]
104
+ self.write(IAC + DO + OPT_BINARY)
105
+ elsif OPT_ECHO[0] == $1[1]
106
+ self.write(IAC + DO + OPT_ECHO)
107
+ elsif OPT_SGA[0] == $1[1]
108
+ @telnet_option["SGA"] = true
109
+ self.write(IAC + DO + OPT_SGA)
110
+ else
111
+ self.write(IAC + DONT + $1[1..1])
112
+ end
113
+ ''
114
+ elsif WONT[0] == $1[0] # respond to "IAC WON'T x"
115
+ if OPT_ECHO[0] == $1[1]
116
+ self.write(IAC + DONT + OPT_ECHO)
117
+ elsif OPT_SGA[0] == $1[1]
118
+ @telnet_option["SGA"] = false
119
+ self.write(IAC + DONT + OPT_SGA)
120
+ else
121
+ self.write(IAC + DONT + $1[1..1])
122
+ end
123
+ ''
124
+ elsif SB[0] == $1[0] # respond to "IAC SB xxx IAC SE"
125
+ if OPT_STARTTLS[0] == $1[1] && TLS_FOLLOWS[0] == $2[0]
126
+ @sock = OpenSSL::SSL::SSLSocket.new(@sock)
127
+ @sock.cert = @options['Cert'] unless @sock.cert
128
+ @sock.key = @options['Key'] unless @sock.key
129
+ @sock.ca_cert = @options['CACert']
130
+ @sock.ca_file = @options['CAFile']
131
+ @sock.ca_path = @options['CAPath']
132
+ @sock.timeout = @options['Timeout']
133
+ @sock.verify_mode = @options['VerifyMode']
134
+ @sock.verify_callback = @options['VerifyCallback']
135
+ @sock.verify_depth = @options['VerifyDepth']
136
+ @sock.connect
137
+ if @options['VerifyMode'] != OpenSSL::SSL::VERIFY_NONE
138
+ @sock.post_connection_check(@options['Host'])
139
+ end
140
+ @ssl = true
141
+ end
142
+ ''
143
+ else
144
+ ''
145
+ end
146
+ end
147
+ end # preprocess
148
+
149
+ alias waitfor_org waitfor
150
+
151
+ def waitfor(options)
152
+ time_out = @options["Timeout"]
153
+ waittime = @options["Waittime"]
154
+
155
+ if options.kind_of?(Hash)
156
+ prompt = if options.has_key?("Match")
157
+ options["Match"]
158
+ elsif options.has_key?("Prompt")
159
+ options["Prompt"]
160
+ elsif options.has_key?("String")
161
+ Regexp.new( Regexp.quote(options["String"]) )
162
+ end
163
+ time_out = options["Timeout"] if options.has_key?("Timeout")
164
+ waittime = options["Waittime"] if options.has_key?("Waittime")
165
+ else
166
+ prompt = options
167
+ end
168
+
169
+ if time_out == false
170
+ time_out = nil
171
+ end
172
+
173
+ line = ''
174
+ buf = ''
175
+ @rest = '' unless @rest
176
+
177
+ until(prompt === line and not IO::select([@sock], nil, nil, waittime))
178
+ unless IO::select([@sock], nil, nil, time_out)
179
+ raise TimeoutError, "timed-out; wait for the next data"
180
+ end
181
+ begin
182
+ c = @rest + @sock.sysread(1024 * 1024)
183
+ @dumplog.log_dump('<', c) if @options.has_key?("Dump_log")
184
+ if @options["Telnetmode"]
185
+ pos = 0
186
+ catch(:next){
187
+ while true
188
+ case c[pos]
189
+ when IAC[0]
190
+ case c[pos+1]
191
+ when DO[0], DONT[0], WILL[0], WONT[0]
192
+ throw :next unless c[pos+2]
193
+ pos += 3
194
+ when SB[0]
195
+ ret = detect_sub_negotiation(c, pos)
196
+ throw :next unless ret
197
+ pos = ret
198
+ when nil
199
+ throw :next
200
+ else
201
+ pos += 2
202
+ end
203
+ when nil
204
+ throw :next
205
+ else
206
+ pos += 1
207
+ end
208
+ end
209
+ }
210
+
211
+ buf = preprocess(c[0...pos])
212
+ @rest = c[pos..-1]
213
+ end
214
+ @log.print(buf) if @options.has_key?("Output_log")
215
+ line.concat(buf)
216
+ yield buf if block_given?
217
+ rescue EOFError # End of file reached
218
+ if line == ''
219
+ line = nil
220
+ yield nil if block_given?
221
+ end
222
+ break
223
+ end
224
+ end
225
+ line
226
+ end
227
+
228
+ private
229
+
230
+ def detect_sub_negotiation(data, pos)
231
+ return nil if data.length < pos+6 # IAC SB x param IAC SE
232
+ pos += 3
233
+ while true
234
+ case data[pos]
235
+ when IAC[0]
236
+ if data[pos+1] == SE[0]
237
+ pos += 2
238
+ return pos
239
+ else
240
+ pos += 2
241
+ end
242
+ when nil
243
+ return nil
244
+ else
245
+ pos += 1
246
+ end
247
+ end
248
+ end
249
+
250
+ end
251
+ end
@@ -0,0 +1,25 @@
1
+ =begin
2
+ = $RCSfile$ -- PKCS7
3
+
4
+ = Licence
5
+ This program is licenced under the same licence as Ruby.
6
+ (See the file 'LICENCE'.)
7
+
8
+ = Version
9
+ $Id: digest.rb 12148 2007-04-05 05:59:22Z technorama $
10
+ =end
11
+
12
+ module OpenSSL
13
+ class PKCS7
14
+ # This class is only provided for backwards compatibility. Use OpenSSL::PKCS7 in the future.
15
+ class PKCS7 < PKCS7
16
+ def initialize(*args)
17
+ super(*args)
18
+
19
+ warn("Warning: OpenSSL::PKCS7::PKCS7 is deprecated after Ruby 1.9; use OpenSSL::PKCS7 instead")
20
+ end
21
+ end
22
+
23
+ end # PKCS7
24
+ end # OpenSSL
25
+
@@ -0,0 +1,187 @@
1
+ =begin
2
+ = $RCSfile$ -- Ruby-space definitions that completes C-space funcs for SSL
3
+
4
+ = Info
5
+ 'OpenSSL for Ruby 2' project
6
+ Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
7
+ All rights reserved.
8
+
9
+ = Licence
10
+ This program is licenced under the same licence as Ruby.
11
+ (See the file 'LICENCE'.)
12
+
13
+ = Version
14
+ $Id$
15
+ =end
16
+
17
+ require "openssl/buffering"
18
+ require "fcntl"
19
+
20
+ module OpenSSL
21
+ module SSL
22
+ class SSLContext
23
+ DEFAULT_PARAMS = {
24
+ :ssl_version => "SSLv23",
25
+ :verify_mode => OpenSSL::SSL::VERIFY_PEER,
26
+ :ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
27
+ :options => OpenSSL::SSL::OP_ALL,
28
+ }
29
+
30
+ DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
31
+ DEFAULT_CERT_STORE.set_default_paths
32
+ if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
33
+ DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
34
+ end
35
+
36
+ def set_params(params={})
37
+ params = DEFAULT_PARAMS.merge(params)
38
+ # ssl_version need to be set at first.
39
+ self.ssl_version = params.delete(:ssl_version)
40
+ params.each{|name, value| self.__send__("#{name}=", value) }
41
+ if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
42
+ unless self.ca_file or self.ca_path or self.cert_store
43
+ self.cert_store = DEFAULT_CERT_STORE
44
+ end
45
+ end
46
+ return params
47
+ end
48
+ end
49
+
50
+ module SocketForwarder
51
+ def addr
52
+ to_io.addr
53
+ end
54
+
55
+ def peeraddr
56
+ to_io.peeraddr
57
+ end
58
+
59
+ def setsockopt(level, optname, optval)
60
+ to_io.setsockopt(level, optname, optval)
61
+ end
62
+
63
+ def getsockopt(level, optname)
64
+ to_io.getsockopt(level, optname)
65
+ end
66
+
67
+ def fcntl(*args)
68
+ to_io.fcntl(*args)
69
+ end
70
+
71
+ def closed?
72
+ to_io.closed?
73
+ end
74
+
75
+ def do_not_reverse_lookup=(flag)
76
+ to_io.do_not_reverse_lookup = flag
77
+ end
78
+ end
79
+
80
+ module Nonblock
81
+ def initialize(*args)
82
+ flag = File::NONBLOCK
83
+ flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
84
+ @io.fcntl(Fcntl::F_SETFL, flag)
85
+ super
86
+ end
87
+ end
88
+
89
+ def verify_certificate_identity(cert, hostname)
90
+ should_verify_common_name = true
91
+ cert.extensions.each{|ext|
92
+ next if ext.oid != "subjectAltName"
93
+ ostr = OpenSSL::ASN1.decode(ext.to_der).value.last
94
+ sequence = OpenSSL::ASN1.decode(ostr.value)
95
+ sequence.value.each{|san|
96
+ case san.tag
97
+ when 2 # dNSName in GeneralName (RFC5280)
98
+ should_verify_common_name = false
99
+ reg = Regexp.escape(san.value).gsub(/\\\*/, "[^.]+")
100
+ return true if /\A#{reg}\z/i =~ hostname
101
+ when 7 # iPAddress in GeneralName (RFC5280)
102
+ should_verify_common_name = false
103
+ # follows GENERAL_NAME_print() in x509v3/v3_alt.c
104
+ if san.value.size == 4
105
+ return true if san.value.unpack('C*').join('.') == hostname
106
+ elsif san.value.size == 16
107
+ return true if san.value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname
108
+ end
109
+ end
110
+ }
111
+ }
112
+ if should_verify_common_name
113
+ cert.subject.to_a.each{|oid, value|
114
+ if oid == "CN"
115
+ reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
116
+ return true if /\A#{reg}\z/i =~ hostname
117
+ end
118
+ }
119
+ end
120
+ return false
121
+ end
122
+ module_function :verify_certificate_identity
123
+
124
+ class SSLSocket
125
+ include Buffering
126
+ include SocketForwarder
127
+ include Nonblock
128
+
129
+ def post_connection_check(hostname)
130
+ unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
131
+ raise SSLError, "hostname was not match with the server certificate"
132
+ end
133
+ return true
134
+ end
135
+
136
+ def session
137
+ SSL::Session.new(self)
138
+ rescue SSL::Session::SessionError
139
+ nil
140
+ end
141
+ end
142
+
143
+ class SSLServer
144
+ include SocketForwarder
145
+ attr_accessor :start_immediately
146
+
147
+ def initialize(svr, ctx)
148
+ @svr = svr
149
+ @ctx = ctx
150
+ unless ctx.session_id_context
151
+ session_id = OpenSSL::Digest::MD5.hexdigest($0)
152
+ @ctx.session_id_context = session_id
153
+ end
154
+ @start_immediately = true
155
+ end
156
+
157
+ def to_io
158
+ @svr
159
+ end
160
+
161
+ def listen(backlog=5)
162
+ @svr.listen(backlog)
163
+ end
164
+
165
+ def shutdown(how=Socket::SHUT_RDWR)
166
+ @svr.shutdown(how)
167
+ end
168
+
169
+ def accept
170
+ sock = @svr.accept
171
+ begin
172
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
173
+ ssl.sync_close = true
174
+ ssl.accept if @start_immediately
175
+ ssl
176
+ rescue SSLError => ex
177
+ sock.close
178
+ raise ex
179
+ end
180
+ end
181
+
182
+ def close
183
+ @svr.close
184
+ end
185
+ end
186
+ end
187
+ end