From 206e43190b689b28b3d66113f9896e5fc687eb7b Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Mon, 17 Jun 2024 10:14:25 +0200 Subject: [PATCH 1/3] Add 'sigalgs=' method for setting accepted signature algorithms This adds OpenSSL::SSL::SSLContext#sigalgs= method and according unit tests to provide access to the OpenSSL SSL_CTX_set1_sigalgs_list() method. Using this method, authentication signature algorithms can be configured. --- ext/openssl/extconf.rb | 1 + ext/openssl/ossl_ssl.c | 33 +++++++++++++++++++++++++++++++++ test/openssl/test_ssl.rb | 30 ++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 8d2eac026..011c49f65 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -195,6 +195,7 @@ def find_openssl_library have_func("EVP_PKEY_check(NULL)", evp_h) have_func("EVP_PKEY_new_raw_private_key(0, NULL, (unsigned char *)\"\", 0)", evp_h) have_func("SSL_CTX_set_ciphersuites(NULL, \"\")", ssl_h) +have_func("SSL_CTX_set1_sigalgs(NULL, NULL, 0L)", ssl_h) # added in 3.0.0 have_func("SSL_set0_tmp_dh_pkey(NULL, NULL)", ssl_h) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 457630ddc..cd7f4878f 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1103,6 +1103,36 @@ ossl_sslctx_set_ciphersuites(VALUE self, VALUE v) } #endif +#ifdef HAVE_SSL_CTX_SET1_SIGALGS +/* + * call-seq: + * ctx.sigalgs = sigalgs_list -> sigalgs_list + * + * Sets the list of "supported signature algorithms" for this context. + * + * For a TLS client, the list is directly used in the supported + * signature algorithm list in the client hello message. For a server, + * the list is used by OpenSSL to determine the set of shared signature + * algorithms. OpenSSL will pick the most appropriate one from it. + */ +static VALUE +ossl_sslctx_set_sigalgs(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + + if (NIL_P(v)) + return v; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + + if (!SSL_CTX_set1_sigalgs_list(ctx, StringValueCStr(v))) + ossl_raise(eSSLError, "SSL_CTX_set1_sigalgs_list"); + + return v; +} +#endif + #ifndef OPENSSL_NO_DH /* * call-seq: @@ -2898,6 +2928,9 @@ Init_ossl_ssl(void) #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES rb_define_method(cSSLContext, "ciphersuites=", ossl_sslctx_set_ciphersuites, 1); #endif +#ifdef HAVE_SSL_CTX_SET1_SIGALGS + rb_define_method(cSSLContext, "sigalgs=", ossl_sslctx_set_sigalgs, 1); +#endif #ifndef OPENSSL_NO_DH rb_define_method(cSSLContext, "tmp_dh=", ossl_sslctx_set_tmp_dh, 1); #endif diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 1471b0cb3..b9d86f332 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -1755,6 +1755,36 @@ def test_ciphers_method_tls_connection end end + def test_sigalgs_method_nil_argument + ssl_ctx = OpenSSL::SSL::SSLContext.new + pend 'sigalgs= method is missing' unless ssl_ctx.respond_to?(:sigalgs=) + + assert_nothing_raised { ssl_ctx.sigalgs = nil } + end + + def test_sigalgs_method_frozen_object + ssl_ctx = OpenSSL::SSL::SSLContext.new + pend 'sigalgs= method is missing' unless ssl_ctx.respond_to?(:sigalgs=) + + ssl_ctx.freeze + assert_raise(FrozenError) { ssl_ctx.sigalgs = '"ECDSA+SHA256:RSA+SHA256"' } + end + + def test_sigalgs_method_valid_sigalgs + ssl_ctx = OpenSSL::SSL::SSLContext.new + pend 'sigalgs= method is missing' unless ssl_ctx.respond_to?(:sigalgs=) + + ssl_ctx.freeze + assert_raise(FrozenError) { ssl_ctx.sigalgs = '"ECDSA+SHA256:RSA+SHA256"' } + end + + def test_sigalgs_method_bogus_sigalgs + ssl_ctx = OpenSSL::SSL::SSLContext.new + pend 'sigalgs= method is missing' unless ssl_ctx.respond_to?(:sigalgs=) + + assert_raise(OpenSSL::SSL::SSLError) { ssl_ctx.sigalgs = 'BOGUS' } + end + def test_ciphers_method_nil_argument ssl_ctx = OpenSSL::SSL::SSLContext.new assert_nothing_raised { ssl_ctx.ciphers = nil } From 778d2324623acfc013d9b22855be036fbf503827 Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Wed, 7 Aug 2024 17:22:04 +0200 Subject: [PATCH 2/3] Refactoring to incorporate review feedback --- ext/openssl/ossl_ssl.c | 3 --- test/openssl/test_ssl.rb | 38 +++++++++++++++++++------------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index cd7f4878f..a77e038e1 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1120,9 +1120,6 @@ ossl_sslctx_set_sigalgs(VALUE self, VALUE v) { SSL_CTX *ctx; - if (NIL_P(v)) - return v; - rb_check_frozen(self); GetSSLCTX(self, ctx); diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index b9d86f332..18a9fb726 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -1736,25 +1736,6 @@ def test_ciphersuites_method_bogus_csuite ) { ssl_ctx.ciphersuites = 'BOGUS' } end - def test_ciphers_method_tls_connection - csuite = ['ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256, 256] - inputs = [csuite[0], [csuite[0]], [csuite]] - - start_server do |port| - inputs.each do |input| - cli_ctx = OpenSSL::SSL::SSLContext.new - cli_ctx.min_version = cli_ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION - cli_ctx.ciphers = input - - server_connect(port, cli_ctx) do |ssl| - assert_equal('TLSv1.2', ssl.ssl_version) - assert_equal(csuite[0], ssl.cipher[0]) - ssl.puts('abc'); assert_equal("abc\n", ssl.gets) - end - end - end - end - def test_sigalgs_method_nil_argument ssl_ctx = OpenSSL::SSL::SSLContext.new pend 'sigalgs= method is missing' unless ssl_ctx.respond_to?(:sigalgs=) @@ -1785,6 +1766,25 @@ def test_sigalgs_method_bogus_sigalgs assert_raise(OpenSSL::SSL::SSLError) { ssl_ctx.sigalgs = 'BOGUS' } end + def test_ciphers_method_tls_connection + csuite = ['ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256, 256] + inputs = [csuite[0], [csuite[0]], [csuite]] + + start_server do |port| + inputs.each do |input| + cli_ctx = OpenSSL::SSL::SSLContext.new + cli_ctx.min_version = cli_ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + cli_ctx.ciphers = input + + server_connect(port, cli_ctx) do |ssl| + assert_equal('TLSv1.2', ssl.ssl_version) + assert_equal(csuite[0], ssl.cipher[0]) + ssl.puts('abc'); assert_equal("abc\n", ssl.gets) + end + end + end + end + def test_ciphers_method_nil_argument ssl_ctx = OpenSSL::SSL::SSLContext.new assert_nothing_raised { ssl_ctx.ciphers = nil } From 2284cf1aa98f8fc61fb1bc94d3a6aac7a3b1bd2a Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Thu, 8 Aug 2024 09:59:10 +0200 Subject: [PATCH 3/3] Fix failing test for sigalgs=nil, since we now reject nil values --- test/openssl/test_ssl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 18a9fb726..fc6038ee7 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -1740,7 +1740,7 @@ def test_sigalgs_method_nil_argument ssl_ctx = OpenSSL::SSL::SSLContext.new pend 'sigalgs= method is missing' unless ssl_ctx.respond_to?(:sigalgs=) - assert_nothing_raised { ssl_ctx.sigalgs = nil } + assert_raise(TypeError) { ssl_ctx.sigalgs = nil } end def test_sigalgs_method_frozen_object