diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2016-05-31 23:25:07 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2016-06-06 11:29:39 +0900 |
commit | 62e5c73e03eb780a23d551672bea7ec92b0047ac (patch) | |
tree | da0b603f4e3c45d55b5e85e65d8a5e0a4c258ca9 | |
parent | 3d47d055b304de38da732ee9895933580ed98bd6 (diff) | |
download | ruby-62e5c73e03eb780a23d551672bea7ec92b0047ac.tar.gz |
ext/openssl: add SSLContext#security_level, #security_level=
OpenSSL 1.1.0 introduced "security level" and these methods deal with
it.
This patch includes many test changes: setting the level to 0.
The default security level is 1 and this prohibits aNULL ciphers.
-rw-r--r-- | ext/openssl/extconf.rb | 1 | ||||
-rw-r--r-- | ext/openssl/ossl_ssl.c | 62 | ||||
-rw-r--r-- | test/openssl/test_pair.rb | 12 | ||||
-rw-r--r-- | test/openssl/test_ssl.rb | 12 | ||||
-rw-r--r-- | test/openssl/utils.rb | 1 |
5 files changed, 88 insertions, 0 deletions
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index f5a6d8e87c..0b93aacbb2 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -146,6 +146,7 @@ have_func("SSL_SESSION_up_ref") have_func("EVP_PKEY_up_ref") OpenSSL.check_func_or_macro("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed OpenSSL.check_func_or_macro("SSL_CTX_set_min_proto_version", "openssl/ssl.h") +have_func("SSL_CTX_get_security_level") Logging::message "=== Checking done. ===\n" diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index f0b8d80cb4..d9dd4b5c9f 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1074,6 +1074,66 @@ ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg) #endif /* + * call-seq: + * ctx.security_level => 0, .., 5 + * + * The security level for this context. This is new in OpenSSL 1.1.0 and + * always returns 0 if using older OpenSSL. + */ +static VALUE +ossl_sslctx_get_security_level(VALUE self) +{ + SSL_CTX *ctx; + int i; + + GetSSLCTX(self, ctx); + if (!ctx) { + rb_warning("SSL_CTX is not initialized."); + return Qnil; + } + +#if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL) + i = SSL_CTX_get_security_level(ctx); +#else + i = 0; +#endif + return INT2FIX(i); +} + +/* + * call-seq: + * ctx.security_level = 0 + * ctx.security_level = 5 + * + * Sets the security level for this context. This is new in OpenSSL 1.1.0. + * If using older OpenSSL, setting a value other than 0 raises + * NotImplementedError. + * + * See the manpage of SSL_CTX_set_security_level(3) for details. + */ +static VALUE +ossl_sslctx_set_security_level(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + + rb_check_frozen(self); + + GetSSLCTX(self, ctx); + if (!ctx) + ossl_raise(eSSLError, "SSL_CTX is not initialized."); + +#if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL) + SSL_CTX_set_security_level(ctx, NUM2INT(v)); +#else + if (NUM2INT(v) != 0) + ossl_raise(rb_eNotImpError, "setting security level != 0 is not " + "supported in this version of OpenSSL"); +#endif + + return v; +} + +/* * call-seq: * ctx.session_add(session) -> true | false * @@ -2388,6 +2448,8 @@ Init_ossl_ssl(void) rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0); rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1); rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1); + rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0); + rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1); rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0); diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb index 86aa2798d7..4d4de1de9e 100644 --- a/test/openssl/test_pair.rb +++ b/test/openssl/test_pair.rb @@ -12,6 +12,7 @@ module OpenSSL::SSLPairM port = 0 ctx = OpenSSL::SSL::SSLContext.new() ctx.ciphers = "ADH" + ctx.security_level = 0 ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } tcps = create_tcp_server(host, port) ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) @@ -22,6 +23,7 @@ module OpenSSL::SSLPairM host = "127.0.0.1" ctx = OpenSSL::SSL::SSLContext.new() ctx.ciphers = "ADH" + ctx.security_level = 0 s = create_tcp_client(host, port) ssl = OpenSSL::SSL::SSLSocket.new(s, ctx) ssl.connect @@ -324,6 +326,7 @@ module OpenSSL::TestPairM def test_connect_works_when_setting_dh_callback_to_nil ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "DH" + ctx2.security_level = 0 ctx2.tmp_dh_callback = nil sock1, sock2 = tcp_pair s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) @@ -331,6 +334,7 @@ module OpenSSL::TestPairM ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "DH" + ctx1.security_level = 0 ctx1.tmp_dh_callback = nil s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) t = Thread.new { s1.connect } @@ -350,12 +354,14 @@ module OpenSSL::TestPairM def test_connect_without_setting_dh_callback ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "DH" + ctx2.security_level = 0 sock1, sock2 = tcp_pair s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) accepted = s2.accept_nonblock(exception: false) ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "DH" + ctx1.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) t = Thread.new { s1.connect } @@ -426,11 +432,13 @@ module OpenSSL::TestPairM ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "ECDH" ctx1.ecdh_curves = "P-384:P-521" + ctx1.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "ECDH" ctx2.ecdh_curves = "P-256:P-384" + ctx2.security_level = 0 s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) th = Thread.new { s1.accept } @@ -451,6 +459,7 @@ module OpenSSL::TestPairM def test_connect_accept_nonblock_no_exception ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "ADH" + ctx2.security_level = 0 ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } sock1, sock2 = tcp_pair @@ -461,6 +470,7 @@ module OpenSSL::TestPairM ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "ADH" + ctx1.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) th = Thread.new do rets = [] @@ -499,6 +509,7 @@ module OpenSSL::TestPairM def test_connect_accept_nonblock ctx = OpenSSL::SSL::SSLContext.new() ctx.ciphers = "ADH" + ctx.security_level = 0 ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } sock1, sock2 = tcp_pair @@ -522,6 +533,7 @@ module OpenSSL::TestPairM sleep 0.1 ctx = OpenSSL::SSL::SSLContext.new() ctx.ciphers = "ADH" + ctx.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx) begin sleep 0.2 diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 9a717a4256..51f9e3d62d 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -424,6 +424,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase start_server(OpenSSL::SSL::VERIFY_NONE, true, {use_anon_cipher: true}){|server, port| ctx = OpenSSL::SSL::SSLContext.new ctx.ciphers = "aNULL" + ctx.security_level = 0 server_connect(port, ctx) { |ssl| msg = "Peer verification enabled, but no certificate received. Anonymous cipher suite " \ "ADH-AES256-GCM-SHA384 was negotiated. Anonymous suites must be disabled to use peer verification." @@ -687,6 +688,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx3 = OpenSSL::SSL::SSLContext.new ctx3.ciphers = "DH" + ctx3.security_level = 0 ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "DH" @@ -698,6 +700,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "DH" + ctx1.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) s1.hostname = hostname @@ -720,6 +723,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "DH" + ctx2.security_level = 0 ctx2.servername_cb = lambda { |args| Object.new } sock1, sock2 = socketpair @@ -728,6 +732,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "DH" + ctx1.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) s1.hostname = hostname @@ -752,6 +757,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx3 = OpenSSL::SSL::SSLContext.new ctx3.ciphers = "DH" + ctx3.security_level = 0 assert_not_predicate ctx3, :frozen? ctx2 = OpenSSL::SSL::SSLContext.new @@ -764,6 +770,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "DH" + ctx1.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) s1.hostname = hostname @@ -785,6 +792,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "DH" + ctx2.security_level = 0 ctx2.servername_cb = lambda { |args| nil } sock1, sock2 = socketpair @@ -793,6 +801,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "DH" + ctx1.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) s1.hostname = hostname @@ -815,6 +824,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "DH" + ctx2.security_level = 0 ctx2.servername_cb = lambda do |args| cb_socket = args[0] lambda_called = args[1] @@ -827,6 +837,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "DH" + ctx1.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) s1.hostname = hostname @@ -1171,6 +1182,7 @@ end # test it doesn't cause a segmentation fault ctx = OpenSSL::SSL::SSLContext.new ctx.ciphers = "aNULL" + ctx.security_level = 0 sock1, sock2 = socketpair ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx) diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb index 82a018aabb..dff5b0cf4d 100644 --- a/test/openssl/utils.rb +++ b/test/openssl/utils.rb @@ -277,6 +277,7 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT ctx = OpenSSL::SSL::SSLContext.new ctx.ciphers = "ADH-AES256-GCM-SHA384" if use_anon_cipher + ctx.security_level = 0 if use_anon_cipher ctx.cert_store = store #ctx.extra_chain_cert = [ ca_cert ] ctx.cert = @svr_cert |