Add #verify_hostname= and #verify_hostname to skip hostname verification (#2858)

According to https://github.com/ruby/openssl/pull/60,

> Currently an user who wants to do the hostname verification needs to
call SSLSocket#post_connection_check explicitly after the TLS connection
is established.

if an user who wants to skip the hostname verification,
SSLSocket#post_connection_check doesn't need to be called

https://bugs.ruby-lang.org/issues/16555
This commit is contained in:
Yuta Iwama 2020-01-23 17:23:17 +09:00 коммит произвёл NARUSE, Yui
Родитель 890200e85e
Коммит be6931f7f7
2 изменённых файлов: 34 добавлений и 3 удалений

Просмотреть файл

@ -844,6 +844,7 @@ module Net #:nodoc:
:@verify_callback, :@verify_callback,
:@verify_depth, :@verify_depth,
:@verify_mode, :@verify_mode,
:@verify_hostname,
] ]
SSL_ATTRIBUTES = [ SSL_ATTRIBUTES = [
:ca_file, :ca_file,
@ -859,6 +860,7 @@ module Net #:nodoc:
:verify_callback, :verify_callback,
:verify_depth, :verify_depth,
:verify_mode, :verify_mode,
:verify_hostname,
] ]
# Sets path of a CA certification file in PEM format. # Sets path of a CA certification file in PEM format.
@ -908,6 +910,10 @@ module Net #:nodoc:
# OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER are acceptable. # OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER are acceptable.
attr_accessor :verify_mode attr_accessor :verify_mode
# Sets to check the server certificate is valid for the hostname.
# See OpenSSL::SSL::SSLContext#verify_hostname=
attr_accessor :verify_hostname
# Returns the X.509 certificates the server presented. # Returns the X.509 certificates the server presented.
def peer_cert def peer_cert
if not use_ssl? or not @socket if not use_ssl? or not @socket
@ -986,9 +992,11 @@ module Net #:nodoc:
ssl_parameters = Hash.new ssl_parameters = Hash.new
iv_list = instance_variables iv_list = instance_variables
SSL_IVNAMES.each_with_index do |ivname, i| SSL_IVNAMES.each_with_index do |ivname, i|
if iv_list.include?(ivname) and if iv_list.include?(ivname)
value = instance_variable_get(ivname) value = instance_variable_get(ivname)
ssl_parameters[SSL_ATTRIBUTES[i]] = value if value unless value.nil?
ssl_parameters[SSL_ATTRIBUTES[i]] = value
end
end end
end end
@ssl_context = OpenSSL::SSL::SSLContext.new @ssl_context = OpenSSL::SSL::SSLContext.new
@ -1007,7 +1015,7 @@ module Net #:nodoc:
s.session = @ssl_session s.session = @ssl_session
end end
ssl_socket_connect(s, @open_timeout) ssl_socket_connect(s, @open_timeout)
if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && @ssl_context.verify_hostname
s.post_connection_check(@address) s.post_connection_check(@address)
end end
D "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}" D "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"

Просмотреть файл

@ -204,6 +204,29 @@ class TestNetHTTPS < Test::Unit::TestCase
skip $! skip $!
end end
def test_skip_hostname_verfiction
TestNetHTTPUtils.clean_http_proxy_env do
http = Net::HTTP.new('invalid_servername', config('port'))
http.ipaddr = config('host')
http.use_ssl = true
http.cert_store = TEST_STORE
http.verify_hostname = false
assert_nothing_raised { http.start }
end
end
def test_fail_if_verify_hostname_is_true
TestNetHTTPUtils.clean_http_proxy_env do
http = Net::HTTP.new('invalid_servername', config('port'))
http.ipaddr = config('host')
http.use_ssl = true
http.cert_store = TEST_STORE
http.verify_hostname = true
@log_tester = lambda { |_| }
assert_raise(OpenSSL::SSL::SSLError) { http.start }
end
end
def test_certificate_verify_failure def test_certificate_verify_failure
http = Net::HTTP.new("localhost", config("port")) http = Net::HTTP.new("localhost", config("port"))
http.use_ssl = true http.use_ssl = true