From d4b8da66ca9533782d2fed9762783c3e560f2998 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Thu, 27 Feb 2025 22:56:33 +0900 Subject: [PATCH] [ruby/openssl] ssl: refactor check_supported_protocol_versions As reported in , check_supported_protocol_versions is unstable and occasionally fails with Errno::ECONNABORTED during SSLSocket#connect on Windows. When the server-side SSLContext specifies an unsupported SSL/TLS protocol version, start_server accepts a TCP connection but closes it without reading ClientHello, as SSLSocket#accept immediately raises an exception. With Winsock, this can cause the client-side SSLSocket#connect to raise Errno::ECONNABORTED. While the simplest fix is to add rescue Errno::ECONNABORTED, this method can be simplified. Instead, let's set up a server that accepts all protocol versions and test client connections with different settings. https://github.com/ruby/openssl/commit/aa7f03e18f --- test/openssl/test_ssl.rb | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index c0ac7b0052..5fc5665135 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -1244,32 +1244,28 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase OpenSSL::SSL::TLS1_1_VERSION, OpenSSL::SSL::TLS1_2_VERSION, OpenSSL::SSL::TLS1_3_VERSION, - ].compact + ] - # Prepare for testing & do sanity check supported = [] - possible_versions.each do |ver| - catch(:unsupported) { - ctx_proc = proc { |ctx| - begin - ctx.min_version = ctx.max_version = ver - rescue ArgumentError, OpenSSL::SSL::SSLError - throw :unsupported - end + ctx_proc = proc { |ctx| + # Explicitly reset them to avoid influenced by OPENSSL_CONF + ctx.min_version = ctx.max_version = nil + } + start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| + possible_versions.each do |ver| + ctx = OpenSSL::SSL::SSLContext.new + ctx.min_version = ctx.max_version = ver + server_connect(port, ctx) { |ssl| + ssl.puts "abc"; assert_equal "abc\n", ssl.gets } - start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| - begin - server_connect(port) { |ssl| - ssl.puts "abc"; assert_equal "abc\n", ssl.gets - } - rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET - else - supported << ver - end - end - } + supported << ver + rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET + end end - assert_not_empty supported + + # Sanity check: in our test suite we assume these are always supported + assert_include(supported, OpenSSL::SSL::TLS1_2_VERSION) + assert_include(supported, OpenSSL::SSL::TLS1_3_VERSION) supported end