* ext/openssl/ossl_ssl.c (ossl_sslctx_set_ssl_version):

new method OpenSSL::SSL::SSLContext#ssl_version to wrap
  SSL_CTX_set_ssl_version.

* ext/openssl/ossl_ssl.c (ossl_ssl_get_verify_result):
  new method OpenSSL::SSL::SSLSocket#verify_result to wrap
  SSL_get_verrify_result.

* ext/openssl/lib/openssl/ssl.rb (OpenSSL::SSL::SSLContext.build):
  new method to build OpenSSL::SSL::SSLContext with Hash parameters.
  this method provides safety default parameters than SSLContext.new.

* ext/openssl/lib/openssl/ssl.rb (OpenSSL::SSL.verify_cetificate_identity):
  new module function: pull out identity verification process
  from OpenSSL::SSL::SSLSocket#post_connection_check.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14270 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
gotoyuzo 2007-12-17 12:18:28 +00:00
parent d6a70c4bb7
commit 2c03835396
3 changed files with 189 additions and 65 deletions

View file

@ -20,6 +20,31 @@ require "fcntl"
module OpenSSL
module SSL
class SSLContext
class <<self
def build(params={})
default_params = {
:ssl_version => "SSLv23",
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
:ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
:options => OpenSSL::SSL::OP_ALL,
}
params = default_params.merge(params)
ctx = new()
params.each{|name, value| ctx.__send__("#{name}=", value) }
ctx.verify_mode ||= OpenSSL::SSL::VERIFY_NONE
if ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE
unless ctx.ca_file or ctx.ca_path or
ctx.cert_store or ctx.verify_callback
ctx.cert_store = OpenSSL::X509::Store.new
ctx.cert_store.set_default_paths
end
end
return ctx
end
end
end
module SocketForwarder
def addr
to_io.addr
@ -59,36 +84,43 @@ module OpenSSL
end
end
def verify_certificate_identity(cert, hostname)
should_verify_common_name = true
cert.extensions.each{|ext|
next if ext.oid != "subjectAltName"
ext.value.split(/,\s+/).each{|general_name|
if /\ADNS:(.*)/ =~ general_name
should_verify_common_name = false
reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
return true if /\A#{reg}\z/i =~ hostname
elsif /\AIP Address:(.*)/ =~ general_name
should_verify_common_name = false
return true if $1 == hostname
end
}
}
if should_verify_common_name
cert.subject.to_a.each{|oid, value|
if oid == "CN"
reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
return true if /\A#{reg}\z/i =~ hostname
end
}
end
return false
end
module_function :verify_certificate_identity
class SSLSocket
include Buffering
include SocketForwarder
include Nonblock
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"
reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
return true if /\A#{reg}\z/i =~ hostname
end
}
unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
raise SSLError, "hostname was not match with the server certificate"
end
raise SSLError, "hostname was not match with the server certificate"
return true
end
def session