summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--ext/openssl/lib/openssl/ssl.rb26
-rw-r--r--test/openssl/test_ssl.rb49
3 files changed, 80 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index ffeef81d3b..c26f05560e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Mon Feb 14 13:12:38 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/lib/openssl/ssl.rb
+ (OpenSSL::SSL::SSLSocket#post_connection_check): new method.
+
Mon Feb 14 00:40:49 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
* lib/ddrb/drb.rb (InvokeMethod.perform): pass DRb info to sub thread.
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index 629109a1de..9c31fa73cd 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -52,6 +52,32 @@ module OpenSSL
class SSLSocket
include Buffering
include SocketForwarder
+
+ def post_connection_check(hostname)
+ check_common_name = true
+ cert = peer_cert
+ cert.extensions.each{|ext|
+ next if ext.oid != "subjectAltName"
+ ext.value.split(/,\s+/).each{|general_name|
+ if /\ADNS:(.*)/ =~ general_name
+ check_common_name = false
+ reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
+ return true if /\A#{reg}\z/i =~ hostname
+ elsif /\AIP Address:(.*)/ =~ general_name
+ check_common_name = false
+ return true if $1 == hostname
+ end
+ }
+ }
+ if check_common_name
+ cert.subject.to_a.each{|oid, value|
+ if oid == "CN" && value.casecmp(hostname) == 0
+ return true
+ end
+ }
+ end
+ raise SSLError, "hostname not match"
+ end
end
class SSLServer
diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
index 699563691e..abc9859484 100644
--- a/test/openssl/test_ssl.rb
+++ b/test/openssl/test_ssl.rb
@@ -194,6 +194,55 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
ssls.each{|ssl| ssl.close }
}
end
+
+ def test_post_connection_check
+ sslerr = OpenSSL::SSL::SSLError
+
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|s, p|
+ sock = TCPSocket.new("127.0.0.1", p)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.connect
+ assert_raises(sslerr){ssl.post_connection_check("localhost.localdomain")}
+ assert_raises(sslerr){ssl.post_connection_check("127.0.0.1")}
+ assert(ssl.post_connection_check("localhost"))
+ assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+ }
+
+ now = Time.now
+ exts = [
+ ["keyUsage","keyEncipherment,digitalSignature",true],
+ ["subjectAltName","DNS:localhost.localdomain",false],
+ ["subjectAltName","IP:127.0.0.1",false],
+ ]
+ @svr_cert = issue_cert(@svr, @svr_key, 4, now, now+1800, exts,
+ @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|s, p|
+ sock = TCPSocket.new("127.0.0.1", p)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.connect
+ assert(ssl.post_connection_check("localhost.localdomain"))
+ assert(ssl.post_connection_check("127.0.0.1"))
+ assert_raises(sslerr){ssl.post_connection_check("localhost")}
+ assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+ }
+
+ now = Time.now
+ exts = [
+ ["keyUsage","keyEncipherment,digitalSignature",true],
+ ["subjectAltName","DNS:*.localdomain",false],
+ ]
+ @svr_cert = issue_cert(@svr, @svr_key, 5, now, now+1800, exts,
+ @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|s, p|
+ sock = TCPSocket.new("127.0.0.1", p)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.connect
+ assert(ssl.post_connection_check("localhost.localdomain"))
+ assert_raises(sslerr){ssl.post_connection_check("127.0.0.1")}
+ assert_raises(sslerr){ssl.post_connection_check("localhost")}
+ assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+ }
+ end
end
end