From ef50f971ef7db5ee6f3c5f53c1b5e1646b6196a4 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 13 Dec 2025 17:43:08 +0900 Subject: [PATCH 1/2] Remove webrick from Gemfile GitHub PR https://github.com/ruby/net-http/pull/180 removed the WEBrick usage in net/http tests. --- Gemfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Gemfile b/Gemfile index 78b50ffc..39549fee 100644 --- a/Gemfile +++ b/Gemfile @@ -5,4 +5,3 @@ gemspec gem "rake" gem "test-unit" gem "test-unit-ruby-core" -gem "webrick" From 35c1745a2602f73036661a0bb070e989c33a0052 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 13 Dec 2025 17:30:21 +0900 Subject: [PATCH 2/2] Refactor HTTPS tests This contains various improvements in tests for openssl integration: - Remove DHE parameters from test servers. OpenSSL is almost always compiled with ECC support nowadays and will prefer ECDHE over DHE. - Remove an outdated omission for a bug in OpenSSL 1.1.0h released in 2018. None of our CI systems use this specific OpenSSL version. - Use top-level return to skip tests if openssl is unavailable. - Refactor tests for Net::HTTP#verify_callback. --- test/net/fixtures/dhparams.pem | 29 -------------- test/net/http/test_https.rb | 66 +++++++++++-------------------- test/net/http/test_https_proxy.rb | 16 ++------ test/net/http/utils.rb | 3 +- 4 files changed, 26 insertions(+), 88 deletions(-) delete mode 100644 test/net/fixtures/dhparams.pem diff --git a/test/net/fixtures/dhparams.pem b/test/net/fixtures/dhparams.pem deleted file mode 100644 index 389285bf..00000000 --- a/test/net/fixtures/dhparams.pem +++ /dev/null @@ -1,29 +0,0 @@ - DH Parameters: (2048 bit) - prime: - 00:ec:4e:a4:06:b6:22:ca:f9:8a:00:cc:d0:ee:2f: - 16:bf:05:64:f5:8f:fe:7f:c4:bb:b0:24:cd:ef:5d: - 8a:90:ad:dc:a9:dd:63:84:90:d8:25:ba:d8:78:d5: - 77:91:42:0a:84:fc:56:1e:13:9b:1c:aa:43:d5:1f: - 38:52:92:fe:b3:66:f9:e7:e8:8c:77:a1:a6:2f:b3: - 98:98:d2:13:fc:57:1c:2a:14:dc:bd:e6:9b:54:19: - 99:4f:ce:81:64:a6:32:7f:8e:61:50:5f:45:3a:e5: - 0c:f7:13:f3:b8:ad:d5:77:ca:09:42:f7:d8:30:27: - 7b:2c:f0:b4:b5:a0:04:96:34:0b:47:81:1d:7f:c1: - 3a:62:86:8e:7d:f8:13:7f:9a:b1:8b:09:23:9e:55: - 59:41:cd:f0:86:09:c4:b7:d1:69:54:cb:d0:f5:e9: - 27:c9:e1:81:e4:a1:df:6b:20:1c:df:e8:54:02:f2: - 37:fc:2a:f7:d5:b3:6f:79:7e:70:22:78:79:18:3c: - 75:14:68:4a:05:9f:ac:d4:7f:9a:79:db:9d:0a:6e: - ec:0a:04:70:bf:c9:4a:59:81:a2:1f:33:9b:4a:66: - bc:03:ce:8a:1b:e3:03:ec:ba:39:26:ab:90:dc:39: - 41:a1:d8:f7:20:3c:8f:af:12:2f:f7:a9:6f:44:f1: - 6d:03 - generator: 2 (0x2) ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEA7E6kBrYiyvmKAMzQ7i8WvwVk9Y/+f8S7sCTN712KkK3cqd1jhJDY -JbrYeNV3kUIKhPxWHhObHKpD1R84UpL+s2b55+iMd6GmL7OYmNIT/FccKhTcveab -VBmZT86BZKYyf45hUF9FOuUM9xPzuK3Vd8oJQvfYMCd7LPC0taAEljQLR4Edf8E6 -YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 -1bNveX5wInh5GDx1FGhKBZ+s1H+aedudCm7sCgRwv8lKWYGiHzObSma8A86KG+MD -7Lo5JquQ3DlBodj3IDyPrxIv96lvRPFtAwIBAg== ------END DH PARAMETERS----- diff --git a/test/net/http/test_https.rb b/test/net/http/test_https.rb index e860c874..55b9eb31 100644 --- a/test/net/http/test_https.rb +++ b/test/net/http/test_https.rb @@ -7,6 +7,8 @@ # should skip this test end +return unless defined?(OpenSSL::SSL) + class TestNetHTTPS < Test::Unit::TestCase include TestNetHTTPUtils @@ -19,7 +21,6 @@ def self.read_fixture(key) 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 @@ def self.read_fixture(key) '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 @@ def test_get_SNI 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 @@ def test_get_SNI_proxy 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 @@ def test_get_SNI_failure 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 @@ def test_post 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 @@ -165,9 +135,6 @@ def test_session_reuse 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 @@ -240,6 +207,21 @@ def test_certificate_verify_failure assert_match(/certificate verify failed/, ex.message) end + def test_verify_callback + http = Net::HTTP.new(HOST, config("port")) + http.use_ssl = true + http.cert_store = TEST_STORE + certs = [] + http.verify_callback = Proc.new {|preverify_ok, store_ctx| + certs << store_ctx.current_cert + preverify_ok + } + 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 bug4246 = "expected the SSL connection to have timed out but have not. [ruby-core:34203]" @@ -275,9 +257,7 @@ def test_max_version 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| } @@ -286,7 +266,7 @@ def test_max_version assert_match(re_msg, ex.message) end -end if defined?(OpenSSL::SSL) +end class TestNetHTTPSIdentityVerifyFailure < Test::Unit::TestCase include TestNetHTTPUtils @@ -300,7 +280,6 @@ def self.read_fixture(key) 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 = { @@ -310,7 +289,6 @@ def self.read_fixture(key) 'ssl_enable' => true, 'ssl_certificate' => SERVER_CERT, 'ssl_private_key' => SERVER_KEY, - 'ssl_tmp_dh_callback' => proc { DHPARAMS }, } def test_identity_verify_failure @@ -326,4 +304,4 @@ def test_identity_verify_failure re_msg = /certificate verify failed|hostname \"#{HOST_IP}\" does not match/ assert_match(re_msg, ex.message) end -end if defined?(OpenSSL::SSL) +end diff --git a/test/net/http/test_https_proxy.rb b/test/net/http/test_https_proxy.rb index f4c6aa0b..237c16e6 100644 --- a/test/net/http/test_https_proxy.rb +++ b/test/net/http/test_https_proxy.rb @@ -5,14 +5,10 @@ end require 'test/unit' +return unless defined?(OpenSSL::SSL) + class HTTPSProxyTest < Test::Unit::TestCase def test_https_proxy_authentication - begin - OpenSSL - rescue LoadError - omit 'autoload problem. see [ruby-dev:45021][Bug #5786]' - end - TCPServer.open("127.0.0.1", 0) {|serv| _, port, _, _ = serv.addr client_thread = Thread.new { @@ -50,12 +46,6 @@ def read_fixture(key) end def test_https_proxy_ssl_connection - begin - OpenSSL - rescue LoadError - omit 'autoload problem. see [ruby-dev:45021][Bug #5786]' - end - TCPServer.open("127.0.0.1", 0) {|tcpserver| ctx = OpenSSL::SSL::SSLContext.new ctx.key = OpenSSL::PKey.read(read_fixture("server.key")) @@ -91,4 +81,4 @@ def test_https_proxy_ssl_connection assert_join_threads([client_thread, server_thread]) } end -end if defined?(OpenSSL) +end diff --git a/test/net/http/utils.rb b/test/net/http/utils.rb index 067cca02..0b9e440e 100644 --- a/test/net/http/utils.rb +++ b/test/net/http/utils.rb @@ -1,6 +1,5 @@ # frozen_string_literal: false require 'socket' -require 'openssl' module TestNetHTTPUtils @@ -14,10 +13,10 @@ def initialize(config, &block) @procs = {} if @config['ssl_enable'] + require 'openssl' context = OpenSSL::SSL::SSLContext.new context.cert = @config['ssl_certificate'] context.key = @config['ssl_private_key'] - context.tmp_dh_callback = @config['ssl_tmp_dh_callback'] @ssl_server = OpenSSL::SSL::SSLServer.new(@server, context) end