diff options
Diffstat (limited to 'test/net/http/test_https.rb')
| -rw-r--r-- | test/net/http/test_https.rb | 139 |
1 files changed, 77 insertions, 62 deletions
diff --git a/test/net/http/test_https.rb b/test/net/http/test_https.rb index 72a69af1a5..f5b21b901f 100644 --- a/test/net/http/test_https.rb +++ b/test/net/http/test_https.rb @@ -7,6 +7,8 @@ rescue LoadError # should skip this test end +return unless defined?(OpenSSL::SSL) + class TestNetHTTPS < Test::Unit::TestCase include TestNetHTTPUtils @@ -19,7 +21,6 @@ class TestNetHTTPS < Test::Unit::TestCase CA_CERT = OpenSSL::X509::Certificate.new(read_fixture("cacert.pem")) SERVER_KEY = OpenSSL::PKey.read(read_fixture("server.key")) SERVER_CERT = OpenSSL::X509::Certificate.new(read_fixture("server.crt")) - DHPARAMS = OpenSSL::PKey::DH.new(read_fixture("dhparams.pem")) TEST_STORE = OpenSSL::X509::Store.new.tap {|s| s.add_cert(CA_CERT) } CONFIG = { @@ -29,25 +30,16 @@ class TestNetHTTPS < Test::Unit::TestCase 'ssl_enable' => true, 'ssl_certificate' => SERVER_CERT, 'ssl_private_key' => SERVER_KEY, - 'ssl_tmp_dh_callback' => proc { DHPARAMS }, } def test_get http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE - certs = [] - http.verify_callback = Proc.new do |preverify_ok, store_ctx| - certs << store_ctx.current_cert - preverify_ok - end http.request_get("/") {|res| assert_equal($test_net_http_data, res.body) + assert_equal(SERVER_CERT.to_der, http.peer_cert.to_der) } - # TODO: OpenSSL 1.1.1h seems to yield only SERVER_CERT; need to check the incompatibility - certs.zip([CA_CERT, SERVER_CERT][-certs.size..-1]) do |actual, expected| - assert_equal(expected.to_der, actual.to_der) - end end def test_get_SNI @@ -55,18 +47,10 @@ class TestNetHTTPS < Test::Unit::TestCase http.ipaddr = config('host') http.use_ssl = true http.cert_store = TEST_STORE - certs = [] - http.verify_callback = Proc.new do |preverify_ok, store_ctx| - certs << store_ctx.current_cert - preverify_ok - end http.request_get("/") {|res| assert_equal($test_net_http_data, res.body) + assert_equal(SERVER_CERT.to_der, http.peer_cert.to_der) } - # TODO: OpenSSL 1.1.1h seems to yield only SERVER_CERT; need to check the incompatibility - certs.zip([CA_CERT, SERVER_CERT][-certs.size..-1]) do |actual, expected| - assert_equal(expected.to_der, actual.to_der) - end end def test_get_SNI_proxy @@ -78,11 +62,6 @@ class TestNetHTTPS < Test::Unit::TestCase http.ipaddr = "192.0.2.1" http.use_ssl = true http.cert_store = TEST_STORE - certs = [] - http.verify_callback = Proc.new do |preverify_ok, store_ctx| - certs << store_ctx.current_cert - preverify_ok - end begin http.start rescue EOFError @@ -114,11 +93,6 @@ class TestNetHTTPS < Test::Unit::TestCase http.ipaddr = config('host') http.use_ssl = true http.cert_store = TEST_STORE - certs = [] - http.verify_callback = Proc.new do |preverify_ok, store_ctx| - certs << store_ctx.current_cert - preverify_ok - end @log_tester = lambda {|_| } assert_raise(OpenSSL::SSL::SSLError){ http.start } end @@ -135,10 +109,6 @@ class TestNetHTTPS < Test::Unit::TestCase end def test_session_reuse - # FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h. - # See https://github.com/openssl/openssl/pull/5967 for details. - omit if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('OpenSSL 1.1.0h') - http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE @@ -148,7 +118,7 @@ class TestNetHTTPS < Test::Unit::TestCase # support session resuse. Limiting the version to the TLSv1.2 stack allows # this test to continue to work on LibreSSL 3.2+. LibreSSL may eventually # support session reuse, but there are no current plans to do so. - http.ssl_version = :TLSv1 + http.ssl_version = :TLSv1_2 end http.start @@ -165,23 +135,20 @@ class TestNetHTTPS < Test::Unit::TestCase end def test_session_reuse_but_expire - # FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h. - omit if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('OpenSSL 1.1.0h') - http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE - http.ssl_timeout = -1 + http.ssl_timeout = 1 http.start http.get("/") http.finish - + sleep 1.25 http.start http.get("/") socket = http.instance_variable_get(:@socket).io - assert_equal false, socket.session_reused? + assert_equal false, socket.session_reused?, "NOTE: OpenSSL library version is #{OpenSSL::OPENSSL_LIBRARY_VERSION}" http.finish end @@ -238,27 +205,21 @@ class TestNetHTTPS < Test::Unit::TestCase http.request_get("/") {|res| } } assert_match(/certificate verify failed/, ex.message) - unless /mswin|mingw/ =~ RUBY_PLATFORM - # on Windows, Errno::ECONNRESET will be raised, and it'll be eaten by - # WEBrick - @log_tester = lambda {|log| - assert_equal(1, log.length) - assert_match(/ERROR OpenSSL::SSL::SSLError:/, log[0]) - } - end end - def test_identity_verify_failure - # the certificate's subject has CN=localhost - http = Net::HTTP.new(HOST_IP, config("port")) + def test_verify_callback + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE - @log_tester = lambda {|_| } - ex = assert_raise(OpenSSL::SSL::SSLError){ - http.request_get("/") {|res| } + certs = [] + http.verify_callback = Proc.new {|preverify_ok, store_ctx| + certs << store_ctx.current_cert + preverify_ok } - re_msg = /certificate verify failed|hostname \"#{HOST_IP}\" does not match/ - assert_match(re_msg, ex.message) + http.request_get("/") {|res| + assert_equal($test_net_http_data, res.body) + } + assert_equal(SERVER_CERT.to_der, certs.last.to_der) end def test_timeout_during_SSL_handshake @@ -293,12 +254,10 @@ class TestNetHTTPS < Test::Unit::TestCase end def test_max_version - http = Net::HTTP.new(HOST_IP, config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.max_version = :SSL2 - http.verify_callback = Proc.new do |preverify_ok, store_ctx| - true - end + http.cert_store = TEST_STORE @log_tester = lambda {|_| } ex = assert_raise(OpenSSL::SSL::SSLError){ http.request_get("/") {|res| } @@ -307,4 +266,60 @@ class TestNetHTTPS < Test::Unit::TestCase assert_match(re_msg, ex.message) end -end if defined?(OpenSSL::SSL) + def test_ractor + assert_ractor(<<~RUBY, require: 'net/https') + expected = #{$test_net_http_data.dump}.b + ret = Ractor.new { + host = #{HOST.dump} + port = #{config('port')} + ca_cert_pem = #{CA_CERT.to_pem.dump} + cert_store = OpenSSL::X509::Store.new.tap { |s| + s.add_cert(OpenSSL::X509::Certificate.new(ca_cert_pem)) + } + Net::HTTP.start(host, port, use_ssl: true, cert_store: cert_store) { |http| + res = http.get('/') + res.body + } + }.value + assert_equal expected, ret + RUBY + end if defined?(Ractor) && Ractor.method_defined?(:value) +end + +class TestNetHTTPSIdentityVerifyFailure < Test::Unit::TestCase + include TestNetHTTPUtils + + def self.read_fixture(key) + File.read(File.expand_path("../fixtures/#{key}", __dir__)) + end + + HOST = 'localhost' + HOST_IP = '127.0.0.1' + CA_CERT = OpenSSL::X509::Certificate.new(read_fixture("cacert.pem")) + SERVER_KEY = OpenSSL::PKey.read(read_fixture("server.key")) + SERVER_CERT = OpenSSL::X509::Certificate.new(read_fixture("server.crt")) + TEST_STORE = OpenSSL::X509::Store.new.tap {|s| s.add_cert(CA_CERT) } + + CONFIG = { + 'host' => HOST_IP, + 'proxy_host' => nil, + 'proxy_port' => nil, + 'ssl_enable' => true, + 'ssl_certificate' => SERVER_CERT, + 'ssl_private_key' => SERVER_KEY, + } + + def test_identity_verify_failure + # the certificate's subject has CN=localhost + http = Net::HTTP.new(HOST_IP, config("port")) + http.use_ssl = true + http.cert_store = TEST_STORE + @log_tester = lambda {|_| } + ex = assert_raise(OpenSSL::SSL::SSLError){ + http.request_get("/") {|res| } + sleep 0.5 + } + re_msg = /certificate verify failed|hostname \"#{HOST_IP}\" does not match/ + assert_match(re_msg, ex.message) + end +end |
