[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
This commit is contained in:
Kazuki Yamaguchi 2025-02-27 22:56:33 +09:00 committed by git
parent c0f3dcf795
commit d4b8da66ca

View File

@ -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
# 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|
begin
server_connect(port) { |ssl|
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
}
rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET
else
supported << ver
rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET
end
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