From a6da77c9e95aab3be9f4553e94eea605bd95d2eb Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Fri, 28 Feb 2025 12:23:27 +0900 Subject: [PATCH] [ruby/openssl] ssl: fix tests using TLS 1.1 or older Commit https://github.com/ruby/openssl/commit/aa7f03e18f26 broke test_minmax_version and test_fallback_scsv on systems using OpenSSL 1.1.1 with a system-wide configuration file that specifies MinProtocol=TLSv1.2. http://rubyci.s3.amazonaws.com/debian11/ruby-master/log/20250228T003003Z.fail.html.gz http://rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20250228T003003Z.fail.html.gz These test cases were already broken before the commit, but they were being skipped because check_supported_protocol_versions failed to detect TLS 1.1 support. To avoid affected by the configuration file, explicitly reset SSLContext#min_version when TLS 1.1 or older is required. The test cases are also broken with OpenSSL 3.0 or later, but this is not currently visible because it still fails to detect TLS 1.1 support. This is caused by the default SSLContext#security_level value, as OpenSSL 3.0 changed TLS 1.1 to be disabled at level 1. https://github.com/ruby/openssl/commit/6d0ea81b5e --- test/openssl/test_ssl.rb | 45 +++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 5fc5665135..f1ce0b5dfc 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -1248,12 +1248,16 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase supported = [] ctx_proc = proc { |ctx| + # The default security level is 1 in OpenSSL <= 3.1, 2 in OpenSSL >= 3.2 + # In OpenSSL >= 3.0, TLS 1.1 or older is disabled at level 1 + ctx.security_level = 0 # 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.security_level = 0 ctx.min_version = ctx.max_version = ver server_connect(port, ctx) { |ssl| ssl.puts "abc"; assert_equal "abc\n", ssl.gets @@ -1304,11 +1308,15 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase # Server enables a single version supported.each do |ver| - ctx_proc = proc { |ctx| ctx.min_version = ctx.max_version = ver } + ctx_proc = proc { |ctx| + ctx.security_level = 0 + ctx.min_version = ctx.max_version = ver + } start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port| supported.each do |cver| # Client enables a single version ctx1 = OpenSSL::SSL::SSLContext.new + ctx1.security_level = 0 ctx1.min_version = ctx1.max_version = cver if ver == cver server_connect(port, ctx1) { |ssl| @@ -1323,6 +1331,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase if cver <= OpenSSL::SSL::TLS1_2_VERSION # Client enables a single version using #ssl_version= ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.security_level = 0 ctx2.ssl_version = vmap[cver][:method] if ver == cver server_connect(port, ctx2) { |ssl| @@ -1337,6 +1346,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase # Client enables all supported versions ctx3 = OpenSSL::SSL::SSLContext.new + ctx3.security_level = 0 ctx3.min_version = ctx3.max_version = nil server_connect(port, ctx3) { |ssl| assert_equal vmap[ver][:name], ssl.ssl_version @@ -1351,12 +1361,17 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase # Server sets min_version (earliest is disabled) sver = supported[1] - ctx_proc = proc { |ctx| ctx.min_version = sver } + ctx_proc = proc { |ctx| + ctx.security_level = 0 + ctx.min_version = sver + } start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port| supported.each do |cver| # Client sets min_version ctx1 = OpenSSL::SSL::SSLContext.new + ctx1.security_level = 0 ctx1.min_version = cver + ctx1.max_version = 0 server_connect(port, ctx1) { |ssl| assert_equal vmap[supported.last][:name], ssl.ssl_version ssl.puts "abc"; assert_equal "abc\n", ssl.gets @@ -1364,6 +1379,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase # Client sets max_version ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.security_level = 0 + ctx2.min_version = 0 ctx2.max_version = cver if cver >= sver server_connect(port, ctx2) { |ssl| @@ -1378,7 +1395,11 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase # Server sets max_version (latest is disabled) sver = supported[-2] - ctx_proc = proc { |ctx| ctx.max_version = sver } + ctx_proc = proc { |ctx| + ctx.security_level = 0 + ctx.min_version = 0 + ctx.max_version = sver + } start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port| supported.each do |cver| # Client sets min_version @@ -1395,6 +1416,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase # Client sets max_version ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.security_level = 0 + ctx2.min_version = 0 ctx2.max_version = cver server_connect(port, ctx2) { |ssl| if cver >= sver @@ -1771,11 +1794,11 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase def test_fallback_scsv supported = check_supported_protocol_versions - return unless supported.include?(OpenSSL::SSL::TLS1_1_VERSION) && - supported.include?(OpenSSL::SSL::TLS1_2_VERSION) + unless supported.include?(OpenSSL::SSL::TLS1_1_VERSION) + omit "TLS 1.1 support is required to run this test case" + end - pend "Fallback SCSV is not supported" unless \ - OpenSSL::SSL::SSLContext.method_defined?(:enable_fallback_scsv) + omit "Fallback SCSV is not supported" if libressl? start_server do |port| ctx = OpenSSL::SSL::SSLContext.new @@ -1786,11 +1809,15 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end ctx_proc = proc { |ctx| + ctx.security_level = 0 + ctx.min_version = 0 ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION } start_server(ctx_proc: ctx_proc) do |port| ctx = OpenSSL::SSL::SSLContext.new ctx.enable_fallback_scsv + ctx.security_level = 0 + ctx.min_version = 0 ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION # Here is OK too # TLS1.2 not supported, fallback to TLS1.1 and signaling the fallback @@ -1808,11 +1835,15 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase # Otherwise, this test fails when using openssl 1.1.1 (or later) that supports TLS1.3. # TODO: We may need another test for TLS1.3 because it seems to have a different mechanism. ctx1 = OpenSSL::SSL::SSLContext.new + ctx1.security_level = 0 + ctx1.min_version = 0 ctx1.max_version = OpenSSL::SSL::TLS1_2_VERSION s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) ctx2 = OpenSSL::SSL::SSLContext.new ctx2.enable_fallback_scsv + ctx2.security_level = 0 + ctx2.min_version = 0 ctx2.max_version = OpenSSL::SSL::TLS1_1_VERSION s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) # AWS-LC has slightly different error messages in all-caps.