mirror of
https://github.com/ruby/ruby.git
synced 2025-09-22 20:14:02 +02:00
* 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:
parent
d6a70c4bb7
commit
2c03835396
3 changed files with 189 additions and 65 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue