Skip to content

Commit 73aeeea

Browse files
committed
move openss/ssl.rb under jopenssl22 and make jopenssl21 version point there
1 parent e976331 commit 73aeeea

2 files changed

Lines changed: 194 additions & 193 deletions

File tree

lib/jopenssl21/openssl/ssl.rb

Lines changed: 1 addition & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -1,193 +1 @@
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' # used by OpenSSL::SSL::Nonblock (if loaded)
19-
20-
module OpenSSL
21-
module SSL
22-
23-
# FIXME: Using the old non-ASN1 logic here because our ASN1 appears to
24-
# return the wrong types for some decoded objects.
25-
# @see https://github.com/jruby/jruby/issues/1102
26-
# @private
27-
def verify_certificate_identity(cert, hostname)
28-
should_verify_common_name = true
29-
cert.extensions.each { |ext|
30-
next if ext.oid != "subjectAltName"
31-
ext.value.split(/,\s+/).each { |general_name|
32-
# MRI 1.9.3 (since we parse ASN.1 differently)
33-
# when 2 # dNSName in GeneralName (RFC5280)
34-
if /\ADNS:(.*)/ =~ general_name
35-
should_verify_common_name = false
36-
return true if verify_hostname(hostname, $1)
37-
# MRI 1.9.3 (since we parse ASN.1 differently)
38-
# when 7 # iPAddress in GeneralName (RFC5280)
39-
elsif /\AIP(?: Address)?:(.*)/ =~ general_name
40-
should_verify_common_name = false
41-
return true if $1 == hostname
42-
# NOTE: bellow logic makes little sense as we read exts differently
43-
#value = $1 # follows GENERAL_NAME_print() in x509v3/v3_alt.c
44-
#if value.size == 4
45-
# return true if value.unpack('C*').join('.') == hostname
46-
#elsif value.size == 16
47-
# return true if value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname
48-
#end
49-
end
50-
}
51-
}
52-
if should_verify_common_name
53-
cert.subject.to_a.each { |oid, value|
54-
if oid == "CN"
55-
return true if verify_hostname(hostname, value)
56-
end
57-
}
58-
end
59-
return false
60-
end
61-
module_function :verify_certificate_identity
62-
63-
def verify_hostname(hostname, san) # :nodoc:
64-
# RFC 5280, IA5String is limited to the set of ASCII characters
65-
return false unless san.ascii_only?
66-
return false unless hostname.ascii_only?
67-
68-
# See RFC 6125, section 6.4.1
69-
# Matching is case-insensitive.
70-
san_parts = san.downcase.split(".")
71-
72-
# TODO: this behavior should probably be more strict
73-
return san == hostname if san_parts.size < 2
74-
75-
# Matching is case-insensitive.
76-
host_parts = hostname.downcase.split(".")
77-
78-
# RFC 6125, section 6.4.3, subitem 2.
79-
# If the wildcard character is the only character of the left-most
80-
# label in the presented identifier, the client SHOULD NOT compare
81-
# against anything but the left-most label of the reference
82-
# identifier (e.g., *.example.com would match foo.example.com but
83-
# not bar.foo.example.com or example.com).
84-
return false unless san_parts.size == host_parts.size
85-
86-
# RFC 6125, section 6.4.3, subitem 1.
87-
# The client SHOULD NOT attempt to match a presented identifier in
88-
# which the wildcard character comprises a label other than the
89-
# left-most label (e.g., do not match bar.*.example.net).
90-
return false unless verify_wildcard(host_parts.shift, san_parts.shift)
91-
92-
san_parts.join(".") == host_parts.join(".")
93-
end
94-
module_function :verify_hostname
95-
96-
def verify_wildcard(domain_component, san_component) # :nodoc:
97-
parts = san_component.split("*", -1)
98-
99-
return false if parts.size > 2
100-
return san_component == domain_component if parts.size == 1
101-
102-
# RFC 6125, section 6.4.3, subitem 3.
103-
# The client SHOULD NOT attempt to match a presented identifier
104-
# where the wildcard character is embedded within an A-label or
105-
# U-label of an internationalized domain name.
106-
return false if domain_component.start_with?("xn--") && san_component != "*"
107-
108-
parts[0].length + parts[1].length < domain_component.length &&
109-
domain_component.start_with?(parts[0]) &&
110-
domain_component.end_with?(parts[1])
111-
end
112-
module_function :verify_wildcard
113-
114-
class SSLSocket
115-
include Buffering
116-
include SocketForwarder
117-
include Nonblock
118-
119-
##
120-
# Perform hostname verification after an SSL connection is established
121-
#
122-
# This method MUST be called after calling #connect to ensure that the
123-
# hostname of a remote peer has been verified.
124-
def post_connection_check(hostname)
125-
unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
126-
raise SSLError, "hostname \"#{hostname}\" does not match the server certificate"
127-
end
128-
return true
129-
end
130-
131-
end
132-
133-
##
134-
# SSLServer represents a TCP/IP server socket with Secure Sockets Layer.
135-
class SSLServer
136-
include SocketForwarder
137-
# When true then #accept works exactly the same as TCPServer#accept
138-
attr_accessor :start_immediately
139-
140-
# Creates a new instance of SSLServer.
141-
# * +srv+ is an instance of TCPServer.
142-
# * +ctx+ is an instance of OpenSSL::SSL::SSLContext.
143-
def initialize(svr, ctx)
144-
@svr = svr
145-
@ctx = ctx
146-
unless ctx.session_id_context
147-
# see #6137 - session id may not exceed 32 bytes
148-
prng = ::Random.new($0.hash)
149-
session_id = prng.bytes(16).unpack('H*')[0]
150-
@ctx.session_id_context = session_id
151-
end
152-
@start_immediately = true
153-
end
154-
155-
# Returns the TCPServer passed to the SSLServer when initialized.
156-
def to_io
157-
@svr
158-
end
159-
160-
# See TCPServer#listen for details.
161-
def listen(backlog=5)
162-
@svr.listen(backlog)
163-
end
164-
165-
# See BasicSocket#shutdown for details.
166-
def shutdown(how=Socket::SHUT_RDWR)
167-
@svr.shutdown(how)
168-
end
169-
170-
# Works similar to TCPServer#accept.
171-
def accept
172-
# Socket#accept returns [socket, addrinfo].
173-
# TCPServer#accept returns a socket.
174-
# The following comma strips addrinfo.
175-
sock, = @svr.accept
176-
begin
177-
ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
178-
ssl.sync_close = true
179-
ssl.accept if @start_immediately
180-
ssl
181-
rescue SSLError => ex
182-
sock.close
183-
raise ex
184-
end
185-
end
186-
187-
# See IO#close for details.
188-
def close
189-
@svr.close
190-
end
191-
end
192-
end
193-
end
1+
load 'jopenssl22/openssl/ssl.rb'

lib/jopenssl22/openssl/ssl.rb

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
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' # used by OpenSSL::SSL::Nonblock (if loaded)
19+
20+
module OpenSSL
21+
module SSL
22+
23+
# FIXME: Using the old non-ASN1 logic here because our ASN1 appears to
24+
# return the wrong types for some decoded objects.
25+
# @see https://github.com/jruby/jruby/issues/1102
26+
# @private
27+
def verify_certificate_identity(cert, hostname)
28+
should_verify_common_name = true
29+
cert.extensions.each { |ext|
30+
next if ext.oid != "subjectAltName"
31+
ext.value.split(/,\s+/).each { |general_name|
32+
# MRI 1.9.3 (since we parse ASN.1 differently)
33+
# when 2 # dNSName in GeneralName (RFC5280)
34+
if /\ADNS:(.*)/ =~ general_name
35+
should_verify_common_name = false
36+
return true if verify_hostname(hostname, $1)
37+
# MRI 1.9.3 (since we parse ASN.1 differently)
38+
# when 7 # iPAddress in GeneralName (RFC5280)
39+
elsif /\AIP(?: Address)?:(.*)/ =~ general_name
40+
should_verify_common_name = false
41+
return true if $1 == hostname
42+
# NOTE: bellow logic makes little sense as we read exts differently
43+
#value = $1 # follows GENERAL_NAME_print() in x509v3/v3_alt.c
44+
#if value.size == 4
45+
# return true if value.unpack('C*').join('.') == hostname
46+
#elsif value.size == 16
47+
# return true if value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname
48+
#end
49+
end
50+
}
51+
}
52+
if should_verify_common_name
53+
cert.subject.to_a.each { |oid, value|
54+
if oid == "CN"
55+
return true if verify_hostname(hostname, value)
56+
end
57+
}
58+
end
59+
return false
60+
end
61+
module_function :verify_certificate_identity
62+
63+
def verify_hostname(hostname, san) # :nodoc:
64+
# RFC 5280, IA5String is limited to the set of ASCII characters
65+
return false unless san.ascii_only?
66+
return false unless hostname.ascii_only?
67+
68+
# See RFC 6125, section 6.4.1
69+
# Matching is case-insensitive.
70+
san_parts = san.downcase.split(".")
71+
72+
# TODO: this behavior should probably be more strict
73+
return san == hostname if san_parts.size < 2
74+
75+
# Matching is case-insensitive.
76+
host_parts = hostname.downcase.split(".")
77+
78+
# RFC 6125, section 6.4.3, subitem 2.
79+
# If the wildcard character is the only character of the left-most
80+
# label in the presented identifier, the client SHOULD NOT compare
81+
# against anything but the left-most label of the reference
82+
# identifier (e.g., *.example.com would match foo.example.com but
83+
# not bar.foo.example.com or example.com).
84+
return false unless san_parts.size == host_parts.size
85+
86+
# RFC 6125, section 6.4.3, subitem 1.
87+
# The client SHOULD NOT attempt to match a presented identifier in
88+
# which the wildcard character comprises a label other than the
89+
# left-most label (e.g., do not match bar.*.example.net).
90+
return false unless verify_wildcard(host_parts.shift, san_parts.shift)
91+
92+
san_parts.join(".") == host_parts.join(".")
93+
end
94+
module_function :verify_hostname
95+
96+
def verify_wildcard(domain_component, san_component) # :nodoc:
97+
parts = san_component.split("*", -1)
98+
99+
return false if parts.size > 2
100+
return san_component == domain_component if parts.size == 1
101+
102+
# RFC 6125, section 6.4.3, subitem 3.
103+
# The client SHOULD NOT attempt to match a presented identifier
104+
# where the wildcard character is embedded within an A-label or
105+
# U-label of an internationalized domain name.
106+
return false if domain_component.start_with?("xn--") && san_component != "*"
107+
108+
parts[0].length + parts[1].length < domain_component.length &&
109+
domain_component.start_with?(parts[0]) &&
110+
domain_component.end_with?(parts[1])
111+
end
112+
module_function :verify_wildcard
113+
114+
class SSLSocket
115+
include Buffering
116+
include SocketForwarder
117+
include Nonblock
118+
119+
##
120+
# Perform hostname verification after an SSL connection is established
121+
#
122+
# This method MUST be called after calling #connect to ensure that the
123+
# hostname of a remote peer has been verified.
124+
def post_connection_check(hostname)
125+
unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
126+
raise SSLError, "hostname \"#{hostname}\" does not match the server certificate"
127+
end
128+
return true
129+
end
130+
131+
end
132+
133+
##
134+
# SSLServer represents a TCP/IP server socket with Secure Sockets Layer.
135+
class SSLServer
136+
include SocketForwarder
137+
# When true then #accept works exactly the same as TCPServer#accept
138+
attr_accessor :start_immediately
139+
140+
# Creates a new instance of SSLServer.
141+
# * +srv+ is an instance of TCPServer.
142+
# * +ctx+ is an instance of OpenSSL::SSL::SSLContext.
143+
def initialize(svr, ctx)
144+
@svr = svr
145+
@ctx = ctx
146+
unless ctx.session_id_context
147+
# see #6137 - session id may not exceed 32 bytes
148+
prng = ::Random.new($0.hash)
149+
session_id = prng.bytes(16).unpack('H*')[0]
150+
@ctx.session_id_context = session_id
151+
end
152+
@start_immediately = true
153+
end
154+
155+
# Returns the TCPServer passed to the SSLServer when initialized.
156+
def to_io
157+
@svr
158+
end
159+
160+
# See TCPServer#listen for details.
161+
def listen(backlog=5)
162+
@svr.listen(backlog)
163+
end
164+
165+
# See BasicSocket#shutdown for details.
166+
def shutdown(how=Socket::SHUT_RDWR)
167+
@svr.shutdown(how)
168+
end
169+
170+
# Works similar to TCPServer#accept.
171+
def accept
172+
# Socket#accept returns [socket, addrinfo].
173+
# TCPServer#accept returns a socket.
174+
# The following comma strips addrinfo.
175+
sock, = @svr.accept
176+
begin
177+
ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
178+
ssl.sync_close = true
179+
ssl.accept if @start_immediately
180+
ssl
181+
rescue SSLError => ex
182+
sock.close
183+
raise ex
184+
end
185+
end
186+
187+
# See IO#close for details.
188+
def close
189+
@svr.close
190+
end
191+
end
192+
end
193+
end

0 commit comments

Comments
 (0)