diff options
| author | Kazuki Yamaguchi <k@rhe.jp> | 2025-02-27 22:56:33 +0900 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2025-02-27 17:18:02 +0000 |
| commit | d4b8da66ca9533782d2fed9762783c3e560f2998 (patch) | |
| tree | ca86dcdf784f400be5178bdbad4e16bba0effc27 | |
| parent | c0f3dcf7958b07e7d2cf008770594bd9c656fb51 (diff) | |
[ruby/openssl] ssl: refactor check_supported_protocol_versions
As reported in <https://github.com/ruby/ruby/pull/12823>,
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
| -rw-r--r-- | test/openssl/test_ssl.rb | 40 |
1 files 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 |
