From 773d2362ff3e02e2250dbddb4690277f872e3903 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Tue, 17 Jan 2017 15:36:48 +0900 Subject: [PATCH 01/15] Backport "Merge branch 'topic/test-memory-leak'" to maint * topic/test-memory-leak: Enable OSSL_MDEBUG on CI builds Add OpenSSL.print_mem_leaks test: prepare test PKey instances on demand test: let OpenSSL::TestCase include OpenSSL::TestUtils Don't define main() when built with --enable-debug (cherry picked from commit 5c586acc387834ab4e09260937dc21064fc59de4) Note that fix for new test cases that use the old constants removed by this is squashed in. --- appveyor.yml | 4 +- docker-compose.yml | 3 +- ext/openssl/ossl.c | 109 +++++++++++++++++++++-- test/fixtures/pkey/dh1024.pem | 5 ++ test/fixtures/pkey/dsa1024.pem | 12 +++ test/fixtures/pkey/dsa256.pem | 8 ++ test/fixtures/pkey/dsa512.pem | 8 ++ test/fixtures/pkey/p256.pem | 5 ++ test/fixtures/pkey/rsa1024.pem | 15 ++++ test/fixtures/pkey/rsa2048.pem | 27 ++++++ test/test_asn1.rb | 2 +- test/test_ns_spki.rb | 4 +- test/test_ocsp.rb | 8 +- test/test_pair.rb | 6 +- test/test_pkcs12.rb | 43 +++++---- test/test_pkcs7.rb | 8 +- test/test_pkey_dh.rb | 21 +++-- test/test_pkey_dsa.rb | 62 ++++++------- test/test_pkey_ec.rb | 46 +++++----- test/test_pkey_rsa.rb | 73 +++++++-------- test/test_ssl.rb | 16 ++-- test/test_x509cert.rb | 12 +-- test/test_x509crl.rb | 16 +--- test/test_x509req.rb | 8 +- test/test_x509store.rb | 16 +--- test/utils.rb | 158 +++++++++------------------------ 26 files changed, 386 insertions(+), 309 deletions(-) create mode 100644 test/fixtures/pkey/dh1024.pem create mode 100644 test/fixtures/pkey/dsa1024.pem create mode 100644 test/fixtures/pkey/dsa256.pem create mode 100644 test/fixtures/pkey/dsa512.pem create mode 100644 test/fixtures/pkey/p256.pem create mode 100644 test/fixtures/pkey/rsa1024.pem create mode 100644 test/fixtures/pkey/rsa2048.pem diff --git a/appveyor.yml b/appveyor.yml index 70ccc40d5..9ff363fce 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,9 +17,9 @@ install: - openssl version - rake install_dependencies build_script: - - rake -rdevkit compile -- --with-openssl-dir=%openssl_dir% + - rake -rdevkit compile -- --with-openssl-dir=%openssl_dir% --enable-debug test_script: - - rake test + - rake test OSSL_MDEBUG=1 deploy: off environment: matrix: diff --git a/docker-compose.yml b/docker-compose.yml index 4289654c7..da21bbeef 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,11 +3,10 @@ compile: &defaults environment: RUBY_VERSION: OPENSSL_VERSION: - MDEBUG: command: rake compile test: <<: *defaults - command: rake compile test + command: rake compile test OSSL_MDEBUG=1 -- --enable-debug debug: <<: *defaults command: /bin/bash diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index c22966df5..4eacc64a4 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -414,6 +414,72 @@ ossl_fips_mode_set(VALUE self, VALUE enabled) #endif } +#if defined(OSSL_DEBUG) +#if !defined(LIBRESSL_VERSION_NUMBER) && \ + (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \ + defined(CRYPTO_malloc_debug_init)) +/* + * call-seq: + * OpenSSL.mem_check_start -> nil + * + * Calls CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON). Starts tracking memory + * allocations. See also OpenSSL.print_mem_leaks. + * + * This is available only when built with a capable OpenSSL and --enable-debug + * configure option. + */ +static VALUE +mem_check_start(VALUE self) +{ + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + return Qnil; +} + +/* + * call-seq: + * OpenSSL.print_mem_leaks -> true | false + * + * For debugging the Ruby/OpenSSL library. Calls CRYPTO_mem_leaks_fp(stderr). + * Prints detected memory leaks to standard error. This cleans the global state + * up thus you cannot use any methods of the library after calling this. + * + * Returns true if leaks detected, false otherwise. + * + * This is available only when built with a capable OpenSSL and --enable-debug + * configure option. + * + * === Example + * OpenSSL.mem_check_start + * NOT_GCED = OpenSSL::PKey::RSA.new(256) + * + * END { + * GC.start + * OpenSSL.print_mem_leaks # will print the leakage + * } + */ +static VALUE +print_mem_leaks(VALUE self) +{ +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + int ret; +#endif + + BN_CTX_free(ossl_bn_ctx); + ossl_bn_ctx = NULL; + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + ret = CRYPTO_mem_leaks_fp(stderr); + if (ret < 0) + ossl_raise(eOSSLError, "CRYPTO_mem_leaks_fp"); + return ret ? Qfalse : Qtrue; +#else + CRYPTO_mem_leaks_fp(stderr); + return Qnil; +#endif +} +#endif +#endif + #if !defined(HAVE_OPENSSL_110_THREADING_API) /** * Stores locks needed for OpenSSL thread safety @@ -1114,15 +1180,40 @@ Init_openssl(void) Init_ossl_ocsp(); Init_ossl_engine(); Init_ossl_asn1(); -} #if defined(OSSL_DEBUG) -/* - * Check if all symbols are OK with 'make LDSHARED=gcc all' - */ -int -main(int argc, char *argv[]) -{ - return 0; + /* + * For debugging Ruby/OpenSSL. Enable only when built with --enable-debug + */ +#if !defined(LIBRESSL_VERSION_NUMBER) && \ + (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \ + defined(CRYPTO_malloc_debug_init)) + rb_define_module_function(mOSSL, "mem_check_start", mem_check_start, 0); + rb_define_module_function(mOSSL, "print_mem_leaks", print_mem_leaks, 0); + +#if defined(CRYPTO_malloc_debug_init) /* <= 1.0.2 */ + CRYPTO_malloc_debug_init(); +#endif + +#if defined(V_CRYPTO_MDEBUG_ALL) /* <= 1.0.2 */ + CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000 /* <= 1.0.2 */ + { + int i; + /* + * See crypto/ex_data.c; call def_get_class() immediately to avoid + * allocations. 15 is the maximum number that is used as the class index + * in OpenSSL 1.0.2. + */ + for (i = 0; i <= 15; i++) { + if (CRYPTO_get_ex_new_index(i, 0, (void *)"ossl-mdebug-dummy", 0, 0, 0) < 0) + rb_raise(rb_eRuntimeError, "CRYPTO_get_ex_new_index for " + "class index %d failed", i); + } + } +#endif +#endif +#endif } -#endif /* OSSL_DEBUG */ diff --git a/test/fixtures/pkey/dh1024.pem b/test/fixtures/pkey/dh1024.pem new file mode 100644 index 000000000..f99c757f2 --- /dev/null +++ b/test/fixtures/pkey/dh1024.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0 +pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG +AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC +-----END DH PARAMETERS----- diff --git a/test/fixtures/pkey/dsa1024.pem b/test/fixtures/pkey/dsa1024.pem new file mode 100644 index 000000000..1bf498895 --- /dev/null +++ b/test/fixtures/pkey/dsa1024.pem @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBugIBAAKBgQCH9aAoXvWWThIjkA6D+nI1F9ksF9iDq594rkiGNOT9sPDOdB+n +D+qeeeeloRlj19ymCSADPI0ZLRgkchkAEnY2RnqnhHOjVf/roGgRbW+iQDMbQ9wa +/pvc6/fAbsu1goE1hBYjm98/sZEeXavj8tR56IXnjF1b6Nx0+sgeUKFKEQIVAMiz +4BJUFeTtddyM4uadBM7HKLPRAoGAZdLBSYNGiij7vAjesF5mGUKTIgPd+JKuBEDx +OaBclsgfdoyoF/TMOkIty+PVlYD+//Vl2xnoUEIRaMXHwHfm0r2xUX++oeRaSScg +YizJdUxe5jvBuBszGPRc/mGpb9YvP0sB+FL1KmuxYmdODfCe51zl8uM/CVhouJ3w +DjmRGscCgYAuFlfC7p+e8huCKydfcv/beftqjewiOPpQ3u5uI6KPCtCJPpDhs3+4 +IihH2cPsAlqwGF4tlibW1+/z/OZ1AZinPK3y7b2jSJASEaPeEltVzB92hcd1khk2 +jTYcmSsV4VddplOPK9czytR/GbbibxsrhhgZUbd8LPbvIgaiadJ1PgIUBnJ/5vN2 +CVArsEzlPUCbohPvZnE= +-----END DSA PRIVATE KEY----- diff --git a/test/fixtures/pkey/dsa256.pem b/test/fixtures/pkey/dsa256.pem new file mode 100644 index 000000000..d9a407f73 --- /dev/null +++ b/test/fixtures/pkey/dsa256.pem @@ -0,0 +1,8 @@ +-----BEGIN DSA PRIVATE KEY----- +MIH3AgEAAkEAhk2libbY2a8y2Pt21+YPYGZeW6wzaW2yfj5oiClXro9XMR7XWLkE +9B7XxLNFCS2gmCCdMsMW1HulaHtLFQmB2wIVAM43JZrcgpu6ajZ01VkLc93gu/Ed +AkAOhujZrrKV5CzBKutKLb0GVyVWmdC7InoNSMZEeGU72rT96IjM59YzoqmD0pGM +3I1o4cGqg1D1DfM1rQlnN1eSAkBq6xXfEDwJ1mLNxF6q8Zm/ugFYWR5xcX/3wFiT +b4+EjHP/DbNh9Vm5wcfnDBJ1zKvrMEf2xqngYdrV/3CiGJeKAhRvL57QvJZcQGvn +ISNX5cMzFHRW3Q== +-----END DSA PRIVATE KEY----- diff --git a/test/fixtures/pkey/dsa512.pem b/test/fixtures/pkey/dsa512.pem new file mode 100644 index 000000000..962c41cc6 --- /dev/null +++ b/test/fixtures/pkey/dsa512.pem @@ -0,0 +1,8 @@ +-----BEGIN DSA PRIVATE KEY----- +MIH4AgEAAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgTYiEEHaOYhkIxv0Ok +RZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB4DZGH7UyarcaGy6D +AkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqoji3/lHdKoVdTQNuR +S/m6DlCwhjRjiQ/lBRgCLCcaAkEAjN891JBjzpMj4bWgsACmMggFf57DS0Ti+5++ +Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxXoXi9OAIUBG98h4tilg6S +55jreJD3Se3slps= +-----END DSA PRIVATE KEY----- diff --git a/test/fixtures/pkey/p256.pem b/test/fixtures/pkey/p256.pem new file mode 100644 index 000000000..97c97d9f9 --- /dev/null +++ b/test/fixtures/pkey/p256.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49 +AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt +CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg== +-----END EC PRIVATE KEY----- diff --git a/test/fixtures/pkey/rsa1024.pem b/test/fixtures/pkey/rsa1024.pem new file mode 100644 index 000000000..464de074b --- /dev/null +++ b/test/fixtures/pkey/rsa1024.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7Cx +aKPERYHsk4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbCz0layNqHyywQEVLFmp1cpIt/ +Q3geLv8ZD9pihowKJDyMDiN6ArYUmZczvW4976MU3+l54E6lF/JfFEU5hwIDAQAB +AoGBAKSl/MQarye1yOysqX6P8fDFQt68VvtXkNmlSiKOGuzyho0M+UVSFcs6k1L0 +maDE25AMZUiGzuWHyaU55d7RXDgeskDMakD1v6ZejYtxJkSXbETOTLDwUWTn618T +gnb17tU1jktUtU67xK/08i/XodlgnQhs6VoHTuCh3Hu77O6RAkEA7+gxqBuZR572 +74/akiW/SuXm0SXPEviyO1MuSRwtI87B02D0qgV8D1UHRm4AhMnJ8MCs1809kMQE +JiQUCrp9mQJBANlt2ngBO14us6NnhuAseFDTBzCHXwUUu1YKHpMMmxpnGqaldGgX +sOZB3lgJsT9VlGf3YGYdkLTNVbogQKlKpB8CQQDiSwkb4vyQfDe8/NpU5Not0fII +8jsDUCb+opWUTMmfbxWRR3FBNu8wnym/m19N4fFj8LqYzHX4KY0oVPu6qvJxAkEA +wa5snNekFcqONLIE4G5cosrIrb74sqL8GbGb+KuTAprzj5z1K8Bm0UW9lTjVDjDi +qRYgZfZSL+x1P/54+xTFSwJAY1FxA/N3QPCXCjPh5YqFxAMQs2VVYTfg+t0MEcJD +dPMQD5JX6g5HKnHFg2mZtoXQrWmJSn7p8GJK8yNTopEErA== +-----END RSA PRIVATE KEY----- diff --git a/test/fixtures/pkey/rsa2048.pem b/test/fixtures/pkey/rsa2048.pem new file mode 100644 index 000000000..ac89cd88e --- /dev/null +++ b/test/fixtures/pkey/rsa2048.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN +s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign +4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D +kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl +NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J +DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb +I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq +PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V +seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0 +Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc +VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW +wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G +0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj +XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb +aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n +h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw +Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k +IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb +v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId +U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr +vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS +Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC +9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41 +gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG +4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw== +-----END RSA PRIVATE KEY----- diff --git a/test/test_asn1.rb b/test/test_asn1.rb index 91ae2cfd0..5accb0071 100644 --- a/test/test_asn1.rb +++ b/test/test_asn1.rb @@ -4,7 +4,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase def test_decode subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA") - key = OpenSSL::TestUtils::TEST_KEY_RSA1024 + key = Fixtures.pkey("rsa1024") now = Time.at(Time.now.to_i) # suppress usec s = 0xdeadbeafdeadbeafdeadbeafdeadbeaf exts = [ diff --git a/test/test_ns_spki.rb b/test/test_ns_spki.rb index ac34613fc..58e0f6498 100644 --- a/test/test_ns_spki.rb +++ b/test/test_ns_spki.rb @@ -17,8 +17,8 @@ def setup end def test_build_data - key1 = OpenSSL::TestUtils::TEST_KEY_RSA1024 - key2 = OpenSSL::TestUtils::TEST_KEY_RSA2048 + key1 = Fixtures.pkey("rsa1024") + key2 = Fixtures.pkey("rsa2048") spki = OpenSSL::Netscape::SPKI.new spki.challenge = "RandomString" spki.public_key = key1.public_key diff --git a/test/test_ocsp.rb b/test/test_ocsp.rb index 8881f25dd..865bb5230 100644 --- a/test/test_ocsp.rb +++ b/test/test_ocsp.rb @@ -13,7 +13,7 @@ def setup # @cert2 @ocsp_cert ca_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA") - @ca_key = OpenSSL::TestUtils::TEST_KEY_RSA1024 + @ca_key = Fixtures.pkey("rsa1024") ca_exts = [ ["basicConstraints", "CA:TRUE", true], ["keyUsage", "cRLSign,keyCertSign", true], @@ -22,7 +22,7 @@ def setup ca_subj, @ca_key, 1, ca_exts, nil, nil) cert_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA2") - @cert_key = OpenSSL::TestUtils::TEST_KEY_RSA1024 + @cert_key = Fixtures.pkey("rsa1024") cert_exts = [ ["basicConstraints", "CA:TRUE", true], ["keyUsage", "cRLSign,keyCertSign", true], @@ -31,14 +31,14 @@ def setup cert_subj, @cert_key, 5, cert_exts, @ca_cert, @ca_key) cert2_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCert") - @cert2_key = OpenSSL::TestUtils::TEST_KEY_RSA1024 + @cert2_key = Fixtures.pkey("rsa1024") cert2_exts = [ ] @cert2 = OpenSSL::TestUtils.issue_cert( cert2_subj, @cert2_key, 10, cert2_exts, @cert, @cert_key) ocsp_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCAOCSP") - @ocsp_key = OpenSSL::TestUtils::TEST_KEY_RSA2048 + @ocsp_key = Fixtures.pkey("rsa2048") ocsp_exts = [ ["extendedKeyUsage", "OCSPSigning", true], ] diff --git a/test/test_pair.rb b/test/test_pair.rb index 9a5205f81..81a55cbe0 100644 --- a/test/test_pair.rb +++ b/test/test_pair.rb @@ -13,7 +13,7 @@ def server ctx = OpenSSL::SSL::SSLContext.new() ctx.ciphers = "ADH" ctx.security_level = 0 - ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } + ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") } tcps = create_tcp_server(host, port) ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) return ssls @@ -356,7 +356,7 @@ 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 } + ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") } sock1, sock2 = tcp_pair @@ -406,7 +406,7 @@ 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 } + ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") } sock1, sock2 = tcp_pair diff --git a/test/test_pkcs12.rb b/test/test_pkcs12.rb index 403718b94..308882341 100644 --- a/test/test_pkcs12.rb +++ b/test/test_pkcs12.rb @@ -5,8 +5,6 @@ module OpenSSL class TestPKCS12 < OpenSSL::TestCase - include OpenSSL::TestUtils - def setup super ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") @@ -16,7 +14,7 @@ def setup ["subjectKeyIdentifier","hash",false], ["authorityKeyIdentifier","keyid:always",false], ] - @cacert = issue_cert(ca, TEST_KEY_RSA2048, 1, ca_exts, nil, nil) + @cacert = issue_cert(ca, Fixtures.pkey("rsa2048"), 1, ca_exts, nil, nil) inter_ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Intermediate CA") inter_ca_key = OpenSSL::PKey.read <<-_EOS_ @@ -36,25 +34,26 @@ def setup Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= -----END RSA PRIVATE KEY----- _EOS_ - @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, TEST_KEY_RSA2048) + @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, Fixtures.pkey("rsa2048")) exts = [ ["keyUsage","digitalSignature",true], ["subjectKeyIdentifier","hash",false], ] ee = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Ruby PKCS12 Test Certificate") - @mycert = issue_cert(ee, TEST_KEY_RSA1024, 3, exts, @inter_cacert, inter_ca_key) + @mykey = Fixtures.pkey("rsa1024") + @mycert = issue_cert(ee, @mykey, 3, exts, @inter_cacert, inter_ca_key) end def test_create pkcs12 = OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert ) - assert_equal @mycert, pkcs12.certificate - assert_equal TEST_KEY_RSA1024, pkcs12.key + assert_equal @mycert.to_der, pkcs12.certificate.to_der + assert_equal @mykey.to_der, pkcs12.key.to_der assert_nil pkcs12.ca_certs end @@ -62,11 +61,11 @@ def test_create_no_pass pkcs12 = OpenSSL::PKCS12.create( nil, "hello", - TEST_KEY_RSA1024, + @mykey, @mycert ) - assert_equal @mycert, pkcs12.certificate - assert_equal TEST_KEY_RSA1024, pkcs12.key + assert_equal @mycert.to_der, pkcs12.certificate.to_der + assert_equal @mykey.to_der, pkcs12.key.to_der assert_nil pkcs12.ca_certs decoded = OpenSSL::PKCS12.new(pkcs12.to_der) @@ -79,7 +78,7 @@ def test_create_with_chain pkcs12 = OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, chain ) @@ -94,7 +93,7 @@ def test_create_with_chain_decode pkcs12 = OpenSSL::PKCS12.create( passwd, "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, chain ) @@ -104,7 +103,7 @@ def test_create_with_chain_decode assert_include_cert @cacert, decoded.ca_certs assert_include_cert @inter_cacert, decoded.ca_certs assert_cert @mycert, decoded.certificate - assert_equal TEST_KEY_RSA1024.to_der, decoded.key.to_der + assert_equal @mykey.to_der, decoded.key.to_der end def test_create_with_bad_nid @@ -112,7 +111,7 @@ def test_create_with_bad_nid OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, [], "foo" @@ -124,7 +123,7 @@ def test_create_with_itr OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, [], nil, @@ -136,7 +135,7 @@ def test_create_with_itr OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, [], nil, @@ -150,7 +149,7 @@ def test_create_with_mac_itr OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, [], nil, @@ -163,7 +162,7 @@ def test_create_with_mac_itr OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, [], nil, @@ -216,7 +215,7 @@ def test_new_with_one_key_and_one_cert EOF p12 = OpenSSL::PKCS12.new(str, "abc123") - assert_equal TEST_KEY_RSA1024.to_der, p12.key.to_der + assert_equal @mykey.to_der, p12.key.to_der assert_equal @mycert.subject.to_der, p12.certificate.subject.to_der assert_equal [], Array(p12.ca_certs) end @@ -275,13 +274,13 @@ def test_new_with_no_certs EOF p12 = OpenSSL::PKCS12.new(str, "abc123") - assert_equal TEST_KEY_RSA1024.to_der, p12.key.to_der + assert_equal @mykey.to_der, p12.key.to_der assert_equal nil, p12.certificate assert_equal [], Array(p12.ca_certs) end def test_dup - p12 = OpenSSL::PKCS12.create("pass", "name", TEST_KEY_RSA1024, @mycert) + p12 = OpenSSL::PKCS12.create("pass", "name", @mykey, @mycert) assert_equal p12.to_der, p12.dup.to_der end diff --git a/test/test_pkcs7.rb b/test/test_pkcs7.rb index 321915546..026fe8479 100644 --- a/test/test_pkcs7.rb +++ b/test/test_pkcs7.rb @@ -6,8 +6,8 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase def setup super - @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 - @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 + @rsa1024 = Fixtures.pkey("rsa1024") + @rsa2048 = Fixtures.pkey("rsa2048") ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1") ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2") @@ -28,10 +28,6 @@ def setup @ee2_cert = issue_cert(ee2, @rsa1024, 3, ee_exts, @ca_cert, @rsa2048) end - def issue_cert(*args) - OpenSSL::TestUtils.issue_cert(*args) - end - def test_signed store = OpenSSL::X509::Store.new store.add_cert(@ca_cert) diff --git a/test/test_pkey_dh.rb b/test/test_pkey_dh.rb index 470c952e2..fb7138139 100644 --- a/test/test_pkey_dh.rb +++ b/test/test_pkey_dh.rb @@ -4,8 +4,6 @@ if defined?(OpenSSL::TestUtils) class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase - DH1024 = OpenSSL::TestUtils::TEST_KEY_DH1024 - NEW_KEYLEN = 256 def test_DEFAULT_parameters @@ -37,12 +35,13 @@ def test_new_break end def test_DHparams + dh1024 = Fixtures.pkey_dh("dh1024") asn1 = OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(DH1024.p), - OpenSSL::ASN1::Integer(DH1024.g) + OpenSSL::ASN1::Integer(dh1024.p), + OpenSSL::ASN1::Integer(dh1024.g) ]) key = OpenSSL::PKey::DH.new(asn1.to_der) - assert_same_dh dup_public(DH1024), key + assert_same_dh dup_public(dh1024), key pem = <<~EOF -----BEGIN DH PARAMETERS----- @@ -52,14 +51,14 @@ def test_DHparams -----END DH PARAMETERS----- EOF key = OpenSSL::PKey::DH.new(pem) - assert_same_dh dup_public(DH1024), key + assert_same_dh dup_public(dh1024), key - assert_equal asn1.to_der, DH1024.to_der - assert_equal pem, DH1024.export + assert_equal asn1.to_der, dh1024.to_der + assert_equal pem, dh1024.export end def test_public_key - dh = OpenSSL::TestUtils::TEST_KEY_DH1024 + dh = Fixtures.pkey_dh("dh1024") public_key = dh.public_key assert_no_key(public_key) #implies public_key.public? is false! assert_equal(dh.to_der, public_key.to_der) @@ -67,14 +66,14 @@ def test_public_key end def test_generate_key - dh = OpenSSL::TestUtils::TEST_KEY_DH1024.public_key # creates a copy + dh = Fixtures.pkey_dh("dh1024").public_key # creates a copy assert_no_key(dh) dh.generate_key! assert_key(dh) end def test_key_exchange - dh = OpenSSL::TestUtils::TEST_KEY_DH1024 + dh = Fixtures.pkey_dh("dh1024") dh2 = dh.public_key dh.generate_key! dh2.generate_key! diff --git a/test/test_pkey_dsa.rb b/test/test_pkey_dsa.rb index a4ccd1d8f..0019c8aec 100644 --- a/test/test_pkey_dsa.rb +++ b/test/test_pkey_dsa.rb @@ -5,8 +5,6 @@ if defined?(OpenSSL::TestUtils) class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase - DSA512 = OpenSSL::TestUtils::TEST_KEY_DSA512 - def test_private key = OpenSSL::PKey::DSA.new(256) assert(key.private?) @@ -37,27 +35,28 @@ def test_new_break end def test_sign_verify + dsa512 = Fixtures.pkey("dsa512") data = "Sign me!" if defined?(OpenSSL::Digest::DSS1) - signature = DSA512.sign(OpenSSL::Digest::DSS1.new, data) - assert_equal true, DSA512.verify(OpenSSL::Digest::DSS1.new, signature, data) + signature = dsa512.sign(OpenSSL::Digest::DSS1.new, data) + assert_equal true, dsa512.verify(OpenSSL::Digest::DSS1.new, signature, data) end return if OpenSSL::OPENSSL_VERSION_NUMBER <= 0x010000000 - signature = DSA512.sign("SHA1", data) - assert_equal true, DSA512.verify("SHA1", signature, data) + signature = dsa512.sign("SHA1", data) + assert_equal true, dsa512.verify("SHA1", signature, data) signature0 = (<<~'end;').unpack("m")[0] MCwCFH5h40plgU5Fh0Z4wvEEpz0eE9SnAhRPbkRB8ggsN/vsSEYMXvJwjGg/ 6g== end; - assert_equal true, DSA512.verify("SHA256", signature0, data) + assert_equal true, dsa512.verify("SHA256", signature0, data) signature1 = signature0.succ - assert_equal false, DSA512.verify("SHA256", signature1, data) + assert_equal false, dsa512.verify("SHA256", signature1, data) end def test_sys_sign_verify - key = OpenSSL::TestUtils::TEST_KEY_DSA256 + key = Fixtures.pkey("dsa256") data = 'Sign me!' digest = OpenSSL::Digest::SHA1.digest(data) sig = key.syssign(digest) @@ -66,17 +65,18 @@ def test_sys_sign_verify def test_DSAPrivateKey # OpenSSL DSAPrivateKey format; similar to RSAPrivateKey + dsa512 = Fixtures.pkey("dsa512") asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(0), - OpenSSL::ASN1::Integer(DSA512.p), - OpenSSL::ASN1::Integer(DSA512.q), - OpenSSL::ASN1::Integer(DSA512.g), - OpenSSL::ASN1::Integer(DSA512.pub_key), - OpenSSL::ASN1::Integer(DSA512.priv_key) + OpenSSL::ASN1::Integer(dsa512.p), + OpenSSL::ASN1::Integer(dsa512.q), + OpenSSL::ASN1::Integer(dsa512.g), + OpenSSL::ASN1::Integer(dsa512.pub_key), + OpenSSL::ASN1::Integer(dsa512.priv_key) ]) key = OpenSSL::PKey::DSA.new(asn1.to_der) assert_predicate key, :private? - assert_same_dsa DSA512, key + assert_same_dsa dsa512, key pem = <<~EOF -----BEGIN DSA PRIVATE KEY----- @@ -89,14 +89,15 @@ def test_DSAPrivateKey -----END DSA PRIVATE KEY----- EOF key = OpenSSL::PKey::DSA.new(pem) - assert_same_dsa DSA512, key + assert_same_dsa dsa512, key - assert_equal asn1.to_der, DSA512.to_der - assert_equal pem, DSA512.export + assert_equal asn1.to_der, dsa512.to_der + assert_equal pem, dsa512.export end def test_DSAPrivateKey_encrypted # key = abcdef + dsa512 = Fixtures.pkey("dsa512") pem = <<~EOF -----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED @@ -111,35 +112,36 @@ def test_DSAPrivateKey_encrypted -----END DSA PRIVATE KEY----- EOF key = OpenSSL::PKey::DSA.new(pem, "abcdef") - assert_same_dsa DSA512, key + assert_same_dsa dsa512, key key = OpenSSL::PKey::DSA.new(pem) { "abcdef" } - assert_same_dsa DSA512, key + assert_same_dsa dsa512, key cipher = OpenSSL::Cipher.new("aes-128-cbc") - exported = DSA512.to_pem(cipher, "abcdef\0\1") - assert_same_dsa DSA512, OpenSSL::PKey::DSA.new(exported, "abcdef\0\1") + exported = dsa512.to_pem(cipher, "abcdef\0\1") + assert_same_dsa dsa512, OpenSSL::PKey::DSA.new(exported, "abcdef\0\1") assert_raise(OpenSSL::PKey::DSAError) { OpenSSL::PKey::DSA.new(exported, "abcdef") } end def test_PUBKEY + dsa512 = Fixtures.pkey("dsa512") asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::ObjectId("DSA"), OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(DSA512.p), - OpenSSL::ASN1::Integer(DSA512.q), - OpenSSL::ASN1::Integer(DSA512.g) + OpenSSL::ASN1::Integer(dsa512.p), + OpenSSL::ASN1::Integer(dsa512.q), + OpenSSL::ASN1::Integer(dsa512.g) ]) ]), OpenSSL::ASN1::BitString( - OpenSSL::ASN1::Integer(DSA512.pub_key).to_der + OpenSSL::ASN1::Integer(dsa512.pub_key).to_der ) ]) key = OpenSSL::PKey::DSA.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_dsa dup_public(DSA512), key + assert_same_dsa dup_public(dsa512), key pem = <<~EOF -----BEGIN PUBLIC KEY----- @@ -152,10 +154,10 @@ def test_PUBKEY -----END PUBLIC KEY----- EOF key = OpenSSL::PKey::DSA.new(pem) - assert_same_dsa dup_public(DSA512), key + assert_same_dsa dup_public(dsa512), key - assert_equal asn1.to_der, dup_public(DSA512).to_der - assert_equal pem, dup_public(DSA512).export + assert_equal asn1.to_der, dup_public(dsa512).to_der + assert_equal pem, dup_public(dsa512).export end def test_read_DSAPublicKey_pem diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb index c549d9c67..8119b77cc 100644 --- a/test/test_pkey_ec.rb +++ b/test/test_pkey_ec.rb @@ -4,8 +4,6 @@ if defined?(OpenSSL::TestUtils) && defined?(OpenSSL::PKey::EC) class OpenSSL::TestEC < OpenSSL::PKeyTestCase - P256 = OpenSSL::TestUtils::TEST_KEY_EC_P256V1 - def test_ec_key builtin_curves = OpenSSL::PKey::EC.builtin_curves assert_not_empty builtin_curves @@ -74,17 +72,18 @@ def test_check_key end def test_sign_verify + p256 = Fixtures.pkey("p256") data = "Sign me!" - signature = P256.sign("SHA1", data) - assert_equal true, P256.verify("SHA1", signature, data) + signature = p256.sign("SHA1", data) + assert_equal true, p256.verify("SHA1", signature, data) signature0 = (<<~'end;').unpack("m")[0] MEQCIEOTY/hD7eI8a0qlzxkIt8LLZ8uwiaSfVbjX2dPAvN11AiAQdCYx56Fq QdBp1B4sxJoA8jvODMMklMyBKVmudboA6A== end; - assert_equal true, P256.verify("SHA256", signature0, data) + assert_equal true, p256.verify("SHA256", signature0, data) signature1 = signature0.succ - assert_equal false, P256.verify("SHA256", signature1, data) + assert_equal false, p256.verify("SHA256", signature1, data) end def test_dsa_sign_verify @@ -124,21 +123,22 @@ def test_dh_compute_key end def test_ECPrivateKey + p256 = Fixtures.pkey("p256") asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(1), - OpenSSL::ASN1::OctetString(P256.private_key.to_s(2)), + OpenSSL::ASN1::OctetString(p256.private_key.to_s(2)), OpenSSL::ASN1::ASN1Data.new( [OpenSSL::ASN1::ObjectId("prime256v1")], 0, :CONTEXT_SPECIFIC ), OpenSSL::ASN1::ASN1Data.new( - [OpenSSL::ASN1::BitString(P256.public_key.to_bn.to_s(2))], + [OpenSSL::ASN1::BitString(p256.public_key.to_bn.to_s(2))], 1, :CONTEXT_SPECIFIC ) ]) key = OpenSSL::PKey::EC.new(asn1.to_der) assert_predicate key, :private? - assert_same_ec P256, key + assert_same_ec p256, key pem = <<~EOF -----BEGIN EC PRIVATE KEY----- @@ -148,13 +148,14 @@ def test_ECPrivateKey -----END EC PRIVATE KEY----- EOF key = OpenSSL::PKey::EC.new(pem) - assert_same_ec P256, key + assert_same_ec p256, key - assert_equal asn1.to_der, P256.to_der - assert_equal pem, P256.export + assert_equal asn1.to_der, p256.to_der + assert_equal pem, p256.export end def test_ECPrivateKey_encrypted + p256 = Fixtures.pkey("p256") # key = abcdef pem = <<~EOF -----BEGIN EC PRIVATE KEY----- @@ -167,31 +168,32 @@ def test_ECPrivateKey_encrypted -----END EC PRIVATE KEY----- EOF key = OpenSSL::PKey::EC.new(pem, "abcdef") - assert_same_ec P256, key + assert_same_ec p256, key key = OpenSSL::PKey::EC.new(pem) { "abcdef" } - assert_same_ec P256, key + assert_same_ec p256, key cipher = OpenSSL::Cipher.new("aes-128-cbc") - exported = P256.to_pem(cipher, "abcdef\0\1") - assert_same_ec P256, OpenSSL::PKey::EC.new(exported, "abcdef\0\1") + exported = p256.to_pem(cipher, "abcdef\0\1") + assert_same_ec p256, OpenSSL::PKey::EC.new(exported, "abcdef\0\1") assert_raise(OpenSSL::PKey::ECError) { OpenSSL::PKey::EC.new(exported, "abcdef") } end def test_PUBKEY + p256 = Fixtures.pkey("p256") asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::ObjectId("id-ecPublicKey"), OpenSSL::ASN1::ObjectId("prime256v1") ]), OpenSSL::ASN1::BitString( - P256.public_key.to_bn.to_s(2) + p256.public_key.to_bn.to_s(2) ) ]) key = OpenSSL::PKey::EC.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_ec dup_public(P256), key + assert_same_ec dup_public(p256), key pem = <<~EOF -----BEGIN PUBLIC KEY----- @@ -200,10 +202,10 @@ def test_PUBKEY -----END PUBLIC KEY----- EOF key = OpenSSL::PKey::EC.new(pem) - assert_same_ec dup_public(P256), key + assert_same_ec dup_public(p256), key - assert_equal asn1.to_der, dup_public(P256).to_der - assert_equal pem, dup_public(P256).export + assert_equal asn1.to_der, dup_public(p256).to_der + assert_equal pem, dup_public(p256).export end def test_ec_group @@ -305,7 +307,7 @@ def test_ec_point_mul raise if $!.message !~ /unsupported field/ end - p256_key = P256 + p256_key = Fixtures.pkey("p256") p256_g = p256_key.group assert_equal(p256_key.public_key, p256_g.generator.mul(p256_key.private_key)) diff --git a/test/test_pkey_rsa.rb b/test/test_pkey_rsa.rb index 93760f747..d603b7acc 100644 --- a/test/test_pkey_rsa.rb +++ b/test/test_pkey_rsa.rb @@ -5,8 +5,6 @@ if defined?(OpenSSL::TestUtils) class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase - RSA1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 - def test_padding key = OpenSSL::PKey::RSA.new(512, 3) @@ -71,22 +69,23 @@ def test_new_break end def test_sign_verify + rsa1024 = Fixtures.pkey("rsa1024") data = "Sign me!" - signature = RSA1024.sign("SHA1", data) - assert_equal true, RSA1024.verify("SHA1", signature, data) + signature = rsa1024.sign("SHA1", data) + assert_equal true, rsa1024.verify("SHA1", signature, data) signature0 = (<<~'end;').unpack("m")[0] oLCgbprPvfhM4pjFQiDTFeWI9Sk+Og7Nh9TmIZ/xSxf2CGXQrptlwo7NQ28+ WA6YQo8jPH4hSuyWIM4Gz4qRYiYRkl5TDMUYob94zm8Si1HxEiS9354tzvqS zS8MLW2BtNPuTubMxTItHGTnOzo9sUg0LAHVFt8kHG2NfKAw/gQ= end; - assert_equal true, RSA1024.verify("SHA256", signature0, data) + assert_equal true, rsa1024.verify("SHA256", signature0, data) signature1 = signature0.succ - assert_equal false, RSA1024.verify("SHA256", signature1, data) + assert_equal false, rsa1024.verify("SHA256", signature1, data) end def test_digest_state_irrelevant_sign - key = RSA1024 + key = Fixtures.pkey("rsa1024") digest1 = OpenSSL::Digest::SHA1.new digest2 = OpenSSL::Digest::SHA1.new data = 'Sign me!' @@ -97,7 +96,7 @@ def test_digest_state_irrelevant_sign end def test_digest_state_irrelevant_verify - key = RSA1024 + key = Fixtures.pkey("rsa1024") digest1 = OpenSSL::Digest::SHA1.new digest2 = OpenSSL::Digest::SHA1.new data = 'Sign me!' @@ -116,20 +115,21 @@ def test_verify_empty_rsa end def test_RSAPrivateKey + rsa1024 = Fixtures.pkey("rsa1024") asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(0), - OpenSSL::ASN1::Integer(RSA1024.n), - OpenSSL::ASN1::Integer(RSA1024.e), - OpenSSL::ASN1::Integer(RSA1024.d), - OpenSSL::ASN1::Integer(RSA1024.p), - OpenSSL::ASN1::Integer(RSA1024.q), - OpenSSL::ASN1::Integer(RSA1024.dmp1), - OpenSSL::ASN1::Integer(RSA1024.dmq1), - OpenSSL::ASN1::Integer(RSA1024.iqmp) + OpenSSL::ASN1::Integer(rsa1024.n), + OpenSSL::ASN1::Integer(rsa1024.e), + OpenSSL::ASN1::Integer(rsa1024.d), + OpenSSL::ASN1::Integer(rsa1024.p), + OpenSSL::ASN1::Integer(rsa1024.q), + OpenSSL::ASN1::Integer(rsa1024.dmp1), + OpenSSL::ASN1::Integer(rsa1024.dmq1), + OpenSSL::ASN1::Integer(rsa1024.iqmp) ]) key = OpenSSL::PKey::RSA.new(asn1.to_der) assert_predicate key, :private? - assert_same_rsa RSA1024, key + assert_same_rsa rsa1024, key pem = <<~EOF -----BEGIN RSA PRIVATE KEY----- @@ -149,13 +149,14 @@ def test_RSAPrivateKey -----END RSA PRIVATE KEY----- EOF key = OpenSSL::PKey::RSA.new(pem) - assert_same_rsa RSA1024, key + assert_same_rsa rsa1024, key - assert_equal asn1.to_der, RSA1024.to_der - assert_equal pem, RSA1024.export + assert_equal asn1.to_der, rsa1024.to_der + assert_equal pem, rsa1024.export end def test_RSAPrivateKey_encrypted + rsa1024 = Fixtures.pkey("rsa1024") # key = abcdef pem = <<~EOF -----BEGIN RSA PRIVATE KEY----- @@ -178,26 +179,27 @@ def test_RSAPrivateKey_encrypted -----END RSA PRIVATE KEY----- EOF key = OpenSSL::PKey::RSA.new(pem, "abcdef") - assert_same_rsa RSA1024, key + assert_same_rsa rsa1024, key key = OpenSSL::PKey::RSA.new(pem) { "abcdef" } - assert_same_rsa RSA1024, key + assert_same_rsa rsa1024, key cipher = OpenSSL::Cipher.new("aes-128-cbc") - exported = RSA1024.to_pem(cipher, "abcdef\0\1") - assert_same_rsa RSA1024, OpenSSL::PKey::RSA.new(exported, "abcdef\0\1") + exported = rsa1024.to_pem(cipher, "abcdef\0\1") + assert_same_rsa rsa1024, OpenSSL::PKey::RSA.new(exported, "abcdef\0\1") assert_raise(OpenSSL::PKey::RSAError) { OpenSSL::PKey::RSA.new(exported, "abcdef") } end def test_RSAPublicKey + rsa1024 = Fixtures.pkey("rsa1024") asn1 = OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(RSA1024.n), - OpenSSL::ASN1::Integer(RSA1024.e) + OpenSSL::ASN1::Integer(rsa1024.n), + OpenSSL::ASN1::Integer(rsa1024.e) ]) key = OpenSSL::PKey::RSA.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_rsa dup_public(RSA1024), key + assert_same_rsa dup_public(rsa1024), key pem = <<~EOF -----BEGIN RSA PUBLIC KEY----- @@ -207,10 +209,11 @@ def test_RSAPublicKey -----END RSA PUBLIC KEY----- EOF key = OpenSSL::PKey::RSA.new(pem) - assert_same_rsa dup_public(RSA1024), key + assert_same_rsa dup_public(rsa1024), key end def test_PUBKEY + rsa1024 = Fixtures.pkey("rsa1024") asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::ObjectId("rsaEncryption"), @@ -218,14 +221,14 @@ def test_PUBKEY ]), OpenSSL::ASN1::BitString( OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(RSA1024.n), - OpenSSL::ASN1::Integer(RSA1024.e) + OpenSSL::ASN1::Integer(rsa1024.n), + OpenSSL::ASN1::Integer(rsa1024.e) ]).to_der ) ]) key = OpenSSL::PKey::RSA.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_rsa dup_public(RSA1024), key + assert_same_rsa dup_public(rsa1024), key pem = <<~EOF -----BEGIN PUBLIC KEY----- @@ -236,14 +239,14 @@ def test_PUBKEY -----END PUBLIC KEY----- EOF key = OpenSSL::PKey::RSA.new(pem) - assert_same_rsa dup_public(RSA1024), key + assert_same_rsa dup_public(rsa1024), key - assert_equal asn1.to_der, dup_public(RSA1024).to_der - assert_equal pem, dup_public(RSA1024).export + assert_equal asn1.to_der, dup_public(rsa1024).to_der + assert_equal pem, dup_public(rsa1024).export end def test_pem_passwd - key = RSA1024 + key = Fixtures.pkey("rsa1024") pem3c = key.to_pem("aes-128-cbc", "key") assert_match (/ENCRYPTED/), pem3c assert_equal key.to_der, OpenSSL::PKey.read(pem3c, "key").to_der diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 8c65df953..31168b80b 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -625,7 +625,7 @@ def socketpair def test_tlsext_hostname ctx3 = OpenSSL::SSL::SSLContext.new ctx3.ciphers = "ADH" - ctx3.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } + ctx3.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } ctx3.security_level = 0 assert_not_predicate ctx3, :frozen? @@ -675,7 +675,7 @@ def test_servername_cb_raises_an_exception_on_unknown_objects ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "aNULL" - ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } + ctx2.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } ctx2.security_level = 0 ctx2.servername_cb = lambda { |args| Object.new } @@ -1051,7 +1051,7 @@ def test_close_and_socket_close_while_connecting # test it doesn't cause a segmentation fault ctx = OpenSSL::SSL::SSLContext.new ctx.ciphers = "aNULL" - ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } + ctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } ctx.security_level = 0 sock1, sock2 = socketpair @@ -1106,14 +1106,14 @@ def test_dh_callback ctx.ciphers = "DH:!NULL" ctx.tmp_dh_callback = ->(*args) { called = true - OpenSSL::TestUtils::TEST_KEY_DH1024 + Fixtures.pkey_dh("dh1024") } } start_server(ctx_proc: ctx_proc) do |server, port| server_connect(port) { |ssl| assert called, "dh callback should be called" if ssl.respond_to?(:tmp_key) - assert_equal OpenSSL::TestUtils::TEST_KEY_DH1024.to_der, ssl.tmp_key.to_der + assert_equal Fixtures.pkey_dh("dh1024").to_der, ssl.tmp_key.to_der end } end @@ -1226,10 +1226,10 @@ def test_security_level return end assert_equal(1, ctx.security_level) - # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = OpenSSL::TestUtils::TEST_KEY_DSA512 } - # ctx.key = OpenSSL::TestUtils::TEST_KEY_RSA1024 + # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = Fixtures.pkey("dsa512") } + # ctx.key = Fixtures.pkey("rsa1024") # ctx.security_level = 2 - # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = OpenSSL::TestUtils::TEST_KEY_RSA1024 } + # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = Fixtures.pkey("rsa1024") } pend "FIXME: SSLContext#key= currently does not raise because SSL_CTX_use_certificate() is delayed" end diff --git a/test/test_x509cert.rb b/test/test_x509cert.rb index 5b2e712d2..03650402f 100644 --- a/test/test_x509cert.rb +++ b/test/test_x509cert.rb @@ -6,18 +6,14 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase def setup super - @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 - @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 - @dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256 - @dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512 + @rsa1024 = Fixtures.pkey("rsa1024") + @rsa2048 = Fixtures.pkey("rsa2048") + @dsa256 = Fixtures.pkey("dsa256") + @dsa512 = Fixtures.pkey("dsa512") @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1") end - def issue_cert(*args) - OpenSSL::TestUtils.issue_cert(*args) - end - def test_serial [1, 2**32, 2**100].each{|s| cert = issue_cert(@ca, @rsa2048, s, [], nil, nil) diff --git a/test/test_x509crl.rb b/test/test_x509crl.rb index 44dfffc95..7d55e3c1c 100644 --- a/test/test_x509crl.rb +++ b/test/test_x509crl.rb @@ -6,23 +6,15 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase def setup super - @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 - @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 - @dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256 - @dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512 + @rsa1024 = Fixtures.pkey("rsa1024") + @rsa2048 = Fixtures.pkey("rsa2048") + @dsa256 = Fixtures.pkey("dsa256") + @dsa512 = Fixtures.pkey("dsa512") @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1") @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2") end - def issue_crl(*args) - OpenSSL::TestUtils.issue_crl(*args) - end - - def issue_cert(*args) - OpenSSL::TestUtils.issue_cert(*args) - end - def test_basic now = Time.at(Time.now.to_i) diff --git a/test/test_x509req.rb b/test/test_x509req.rb index 585dda1bc..fcc3e2f10 100644 --- a/test/test_x509req.rb +++ b/test/test_x509req.rb @@ -6,10 +6,10 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase def setup super - @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 - @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 - @dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256 - @dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512 + @rsa1024 = Fixtures.pkey("rsa1024") + @rsa2048 = Fixtures.pkey("rsa2048") + @dsa256 = Fixtures.pkey("dsa256") + @dsa512 = Fixtures.pkey("dsa512") @dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=GOTOU Yuuzou") end diff --git a/test/test_x509store.rb b/test/test_x509store.rb index c45233aae..983437e7d 100644 --- a/test/test_x509store.rb +++ b/test/test_x509store.rb @@ -6,10 +6,10 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase def setup super - @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 - @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 - @dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256 - @dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512 + @rsa1024 = Fixtures.pkey("rsa1024") + @rsa2048 = Fixtures.pkey("rsa2048") + @dsa256 = Fixtures.pkey("dsa256") + @dsa512 = Fixtures.pkey("dsa512") @ca1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA1") @ca2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA2") @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1") @@ -26,14 +26,6 @@ def test_nosegv_on_cleanup ctx.verify end - def issue_cert(*args) - OpenSSL::TestUtils.issue_cert(*args) - end - - def issue_crl(*args) - OpenSSL::TestUtils.issue_crl(*args) - end - def test_add_file ca_exts = [ ["basicConstraints", "CA:TRUE", true], diff --git a/test/utils.rb b/test/utils.rb index bbc9c7efc..4a7d4faa8 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -9,6 +9,26 @@ rescue LoadError end +# Compile OpenSSL with crypto-mdebug and run this test suite with OSSL_MDEBUG=1 +# environment variable to enable memory leak check. +if ENV["OSSL_MDEBUG"] == "1" + if OpenSSL.respond_to?(:print_mem_leaks) + OpenSSL.mem_check_start + + END { + GC.start + case OpenSSL.print_mem_leaks + when nil + warn "mdebug: check what is printed" + when true + raise "mdebug: memory leaks detected" + end + } + else + warn "OSSL_MDEBUG=1 is specified but OpenSSL is not built with crypto-mdebug" + end +end + require "test/unit" require 'tempfile' require "rbconfig" @@ -16,113 +36,24 @@ require "envutil" module OpenSSL::TestUtils - TEST_KEY_RSA1024 = OpenSSL::PKey::RSA.new <<-_end_of_pem_ ------BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7Cx -aKPERYHsk4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbCz0layNqHyywQEVLFmp1cpIt/ -Q3geLv8ZD9pihowKJDyMDiN6ArYUmZczvW4976MU3+l54E6lF/JfFEU5hwIDAQAB -AoGBAKSl/MQarye1yOysqX6P8fDFQt68VvtXkNmlSiKOGuzyho0M+UVSFcs6k1L0 -maDE25AMZUiGzuWHyaU55d7RXDgeskDMakD1v6ZejYtxJkSXbETOTLDwUWTn618T -gnb17tU1jktUtU67xK/08i/XodlgnQhs6VoHTuCh3Hu77O6RAkEA7+gxqBuZR572 -74/akiW/SuXm0SXPEviyO1MuSRwtI87B02D0qgV8D1UHRm4AhMnJ8MCs1809kMQE -JiQUCrp9mQJBANlt2ngBO14us6NnhuAseFDTBzCHXwUUu1YKHpMMmxpnGqaldGgX -sOZB3lgJsT9VlGf3YGYdkLTNVbogQKlKpB8CQQDiSwkb4vyQfDe8/NpU5Not0fII -8jsDUCb+opWUTMmfbxWRR3FBNu8wnym/m19N4fFj8LqYzHX4KY0oVPu6qvJxAkEA -wa5snNekFcqONLIE4G5cosrIrb74sqL8GbGb+KuTAprzj5z1K8Bm0UW9lTjVDjDi -qRYgZfZSL+x1P/54+xTFSwJAY1FxA/N3QPCXCjPh5YqFxAMQs2VVYTfg+t0MEcJD -dPMQD5JX6g5HKnHFg2mZtoXQrWmJSn7p8GJK8yNTopEErA== ------END RSA PRIVATE KEY----- - _end_of_pem_ - - TEST_KEY_RSA2048 = OpenSSL::PKey::RSA.new <<-_end_of_pem_ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN -s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign -4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D -kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl -NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J -DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb -I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq -PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V -seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0 -Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc -VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW -wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G -0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj -XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb -aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n -h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw -Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k -IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb -v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId -U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr -vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS -Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC -9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41 -gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG -4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw== ------END RSA PRIVATE KEY----- - _end_of_pem_ - - TEST_KEY_DSA256 = OpenSSL::PKey::DSA.new <<-_end_of_pem_ ------BEGIN DSA PRIVATE KEY----- -MIH3AgEAAkEAhk2libbY2a8y2Pt21+YPYGZeW6wzaW2yfj5oiClXro9XMR7XWLkE -9B7XxLNFCS2gmCCdMsMW1HulaHtLFQmB2wIVAM43JZrcgpu6ajZ01VkLc93gu/Ed -AkAOhujZrrKV5CzBKutKLb0GVyVWmdC7InoNSMZEeGU72rT96IjM59YzoqmD0pGM -3I1o4cGqg1D1DfM1rQlnN1eSAkBq6xXfEDwJ1mLNxF6q8Zm/ugFYWR5xcX/3wFiT -b4+EjHP/DbNh9Vm5wcfnDBJ1zKvrMEf2xqngYdrV/3CiGJeKAhRvL57QvJZcQGvn -ISNX5cMzFHRW3Q== ------END DSA PRIVATE KEY----- - _end_of_pem_ - - TEST_KEY_DSA512 = OpenSSL::PKey::DSA.new <<-_end_of_pem_ ------BEGIN DSA PRIVATE KEY----- -MIH4AgEAAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgTYiEEHaOYhkIxv0Ok -RZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB4DZGH7UyarcaGy6D -AkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqoji3/lHdKoVdTQNuR -S/m6DlCwhjRjiQ/lBRgCLCcaAkEAjN891JBjzpMj4bWgsACmMggFf57DS0Ti+5++ -Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxXoXi9OAIUBG98h4tilg6S -55jreJD3Se3slps= ------END DSA PRIVATE KEY----- - _end_of_pem_ - - TEST_KEY_DSA1024 = OpenSSL::PKey::DSA.new <<-_end_of_pem_ ------BEGIN DSA PRIVATE KEY----- -MIIBugIBAAKBgQCH9aAoXvWWThIjkA6D+nI1F9ksF9iDq594rkiGNOT9sPDOdB+n -D+qeeeeloRlj19ymCSADPI0ZLRgkchkAEnY2RnqnhHOjVf/roGgRbW+iQDMbQ9wa -/pvc6/fAbsu1goE1hBYjm98/sZEeXavj8tR56IXnjF1b6Nx0+sgeUKFKEQIVAMiz -4BJUFeTtddyM4uadBM7HKLPRAoGAZdLBSYNGiij7vAjesF5mGUKTIgPd+JKuBEDx -OaBclsgfdoyoF/TMOkIty+PVlYD+//Vl2xnoUEIRaMXHwHfm0r2xUX++oeRaSScg -YizJdUxe5jvBuBszGPRc/mGpb9YvP0sB+FL1KmuxYmdODfCe51zl8uM/CVhouJ3w -DjmRGscCgYAuFlfC7p+e8huCKydfcv/beftqjewiOPpQ3u5uI6KPCtCJPpDhs3+4 -IihH2cPsAlqwGF4tlibW1+/z/OZ1AZinPK3y7b2jSJASEaPeEltVzB92hcd1khk2 -jTYcmSsV4VddplOPK9czytR/GbbibxsrhhgZUbd8LPbvIgaiadJ1PgIUBnJ/5vN2 -CVArsEzlPUCbohPvZnE= ------END DSA PRIVATE KEY----- - _end_of_pem_ - -if defined?(OpenSSL::PKey::EC) - - TEST_KEY_EC_P256V1 = OpenSSL::PKey::EC.new <<-_end_of_pem_ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49 -AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt -CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg== ------END EC PRIVATE KEY----- - _end_of_pem_ + module Fixtures + module_function -end + def pkey(name) + OpenSSL::PKey.read(read_file("pkey", name)) + end - TEST_KEY_DH1024 = OpenSSL::PKey::DH.new <<-_end_of_pem_ ------BEGIN DH PARAMETERS----- -MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0 -pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG -AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC ------END DH PARAMETERS----- - _end_of_pem_ + def pkey_dh(name) + # DH parameters can be read by OpenSSL::PKey.read atm + OpenSSL::PKey::DH.new(read_file("pkey", name)) + end - TEST_KEY_DH1024.set_key(OpenSSL::BN.new("556AF1598AE69899867CEBA9F29CE4862B884C2B43C9019EA0231908F6EFA785E3C462A6ECB16DF676866E997FFB72B487DC7967C58C3CA38CE974473BF19B2AA5DCBF102735572EBA6F353F6F0BBE7FF1DE1B07FE1381A355C275C33405004317F9491B5955F191F6615A63B30E55A027FB88A1A4B25608E09EEE68A7DF32D", 16), - OpenSSL::BN.new("48561834C67E65FFD2A9B47F41E5E78FDC95C387428FDB1E4B0188B64D1643C3A8D3455B945B7E8C4D166010C7C2CE23BFB9BEF43D0348FE7FA5284B0225E7FE1537546D114E3D8A4411B9B9351AB451E1A358F50ED61B1F00DA29336EEBBD649980AC86D76AF8BBB065298C2052672EEF3EF13AB47A15275FC2836F3AC74CEA", 16)) + def read_file(category, name) + @file_cache ||= {} + @file_cache[[category, name]] ||= + File.read(File.join(__dir__, "fixtures", category, name + ".pem")) + end + end DSA_SIGNATURE_DIGEST = OpenSSL::OPENSSL_VERSION_NUMBER > 0x10000000 ? OpenSSL::Digest::SHA1 : @@ -201,6 +132,9 @@ def silent end class OpenSSL::TestCase < Test::Unit::TestCase + include OpenSSL::TestUtils + extend OpenSSL::TestUtils + def setup if ENV["OSSL_GC_STRESS"] == "1" GC.stress = true @@ -222,9 +156,9 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase def setup super - @ca_key = OpenSSL::TestUtils::TEST_KEY_RSA2048 - @svr_key = OpenSSL::TestUtils::TEST_KEY_RSA1024 - @cli_key = OpenSSL::TestUtils::TEST_KEY_DSA1024 + @ca_key = Fixtures.pkey("rsa2048") + @svr_key = Fixtures.pkey("rsa1024") + @cli_key = Fixtures.pkey("dsa1024") @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") @@ -241,14 +175,6 @@ def setup @server = nil end - def issue_cert(*arg) - OpenSSL::TestUtils.issue_cert(*arg) - end - - def issue_crl(*arg) - OpenSSL::TestUtils.issue_crl(*arg) - end - def readwrite_loop(ctx, ssl) while line = ssl.gets ssl.write(line) @@ -298,7 +224,7 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true ctx.cert_store = store ctx.cert = @svr_cert ctx.key = @svr_key - ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } + ctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } begin ctx.ecdh_curves = "P-256" rescue NotImplementedError From aa03e3ac99bbf33d07a7fc24cff199ebd5dbe266 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Thu, 24 Aug 2017 20:55:38 +0900 Subject: [PATCH 02/15] Rakefile: let sync:to_ruby know about test/openssl/fixtures --- Rakefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index 3350157b2..0cbfd272e 100644 --- a/Rakefile +++ b/Rakefile @@ -58,11 +58,12 @@ namespace :sync do paths = [ ["ext/openssl/", "ext/openssl/"], + ["lib/", "ext/openssl/lib/"], + ["sample/", "sample/openssl/"], + ["test/fixtures/", "test/openssl/fixtures/"], ["test/utils.rb", "test/openssl/"], ["test/ut_eof.rb", "test/openssl/"], ["test/test_*", "test/openssl/"], - ["lib/", "ext/openssl/lib/"], - ["sample/", "sample/openssl/"], ["History.md", "ext/openssl/"], ] paths.each do |src, dst| From 134bff1bafd1d0a781a1ac0d4fcbebd963f9c241 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sun, 13 Aug 2017 22:36:25 +0900 Subject: [PATCH 03/15] test: fix formatting Fix wrong nesting in test/utils.rb. Remove unnecessary requires. Wrap the code with 'if defined?(OpenSSL::TestUtils) ~ end' and avoid class definition with modifier if. --- test/test_asn1.rb | 5 +- test/test_buffering.rb | 7 +- test/test_config.rb | 6 +- test/test_engine.rb | 6 +- test/test_hmac.rb | 6 +- test/test_pair.rb | 4 +- test/test_pkcs5.rb | 6 +- test/test_pkey_dsa.rb | 1 - test/test_pkey_rsa.rb | 3 +- test/test_random.rb | 6 +- test/ut_eof.rb | 4 + test/utils.rb | 295 +++++++++++++++++++++-------------------- 12 files changed, 185 insertions(+), 164 deletions(-) diff --git a/test/test_asn1.rb b/test/test_asn1.rb index 5accb0071..55cb1f0be 100644 --- a/test/test_asn1.rb +++ b/test/test_asn1.rb @@ -1,6 +1,8 @@ # frozen_string_literal: false require_relative 'utils' +if defined?(OpenSSL::TestUtils) + class OpenSSL::TestASN1 < OpenSSL::TestCase def test_decode subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA") @@ -582,5 +584,6 @@ def assert_universal(tag, asn1) end assert_equal(:UNIVERSAL, asn1.tag_class) end +end -end if defined?(OpenSSL::TestUtils) +end diff --git a/test/test_buffering.rb b/test/test_buffering.rb index f85353fc6..08735adda 100644 --- a/test/test_buffering.rb +++ b/test/test_buffering.rb @@ -1,9 +1,9 @@ # frozen_string_literal: false require_relative 'utils' -require 'stringio' -class OpenSSL::TestBuffering < OpenSSL::TestCase +if defined?(OpenSSL::TestUtils) +class OpenSSL::TestBuffering < OpenSSL::TestCase class IO include OpenSSL::Buffering @@ -85,5 +85,6 @@ def test_each_byte end assert_equal([97, 98, 99], res) end +end -end if defined?(OpenSSL::TestUtils) +end diff --git a/test/test_config.rb b/test/test_config.rb index 786bce9d2..cc314335f 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -1,6 +1,8 @@ # frozen_string_literal: false require_relative 'utils' +if defined?(OpenSSL::TestUtils) + class OpenSSL::TestConfig < OpenSSL::TestCase def setup super @@ -297,4 +299,6 @@ def test_clone @it['newsection'] = {'a' => 'b'} assert_not_equal(@it.sections.sort, c.sections.sort) end -end if defined?(OpenSSL::TestUtils) +end + +end diff --git a/test/test_engine.rb b/test/test_engine.rb index 75e45eb7f..634350465 100644 --- a/test/test_engine.rb +++ b/test/test_engine.rb @@ -1,8 +1,9 @@ # frozen_string_literal: false require_relative 'utils' -class OpenSSL::TestEngine < OpenSSL::TestCase +if defined?(OpenSSL::TestUtils) && defined?(OpenSSL::Engine) +class OpenSSL::TestEngine < OpenSSL::TestCase def test_engines_free # [ruby-dev:44173] with_openssl <<-'end;' OpenSSL::Engine.load("openssl") @@ -95,5 +96,6 @@ def crypt_data(data, key, mode) cipher.update(data) + cipher.final end end +end -end if defined?(OpenSSL::TestUtils) && defined?(OpenSSL::Engine) +end diff --git a/test/test_hmac.rb b/test/test_hmac.rb index dbde97d9c..4d06e4765 100644 --- a/test/test_hmac.rb +++ b/test/test_hmac.rb @@ -1,6 +1,8 @@ # frozen_string_literal: false require_relative 'utils' +if defined?(OpenSSL::TestUtils) + class OpenSSL::TestHMAC < OpenSSL::TestCase def test_hmac # RFC 2202 2. Test Cases for HMAC-MD5 @@ -37,4 +39,6 @@ def test_reset_keep_key second = h1.update("test").hexdigest assert_equal first, second end -end if defined?(OpenSSL::TestUtils) +end + +end diff --git a/test/test_pair.rb b/test/test_pair.rb index 81a55cbe0..570309afd 100644 --- a/test/test_pair.rb +++ b/test/test_pair.rb @@ -1,11 +1,9 @@ # frozen_string_literal: false require_relative 'utils' +require_relative 'ut_eof' if defined?(OpenSSL::TestUtils) -require 'socket' -require_relative 'ut_eof' - module OpenSSL::SSLPairM def server host = "127.0.0.1" diff --git a/test/test_pkcs5.rb b/test/test_pkcs5.rb index ad8132c26..0919b9ce6 100644 --- a/test/test_pkcs5.rb +++ b/test/test_pkcs5.rb @@ -1,8 +1,9 @@ # frozen_string_literal: false require_relative 'utils' -class OpenSSL::TestPKCS5 < OpenSSL::TestCase +if defined?(OpenSSL::TestUtils) +class OpenSSL::TestPKCS5 < OpenSSL::TestCase def test_pbkdf2_hmac_sha1_rfc6070_c_1_len_20 p ="password" s = "salt" @@ -94,5 +95,6 @@ def test_pbkdf2_hmac_sha256_c_20000_len_32 value2 = OpenSSL::PKCS5.pbkdf2_hmac(p, s, c, dk_len, digest) assert_equal(value1, value2) end if OpenSSL::PKCS5.respond_to?(:pbkdf2_hmac) +end -end if defined?(OpenSSL::TestUtils) +end diff --git a/test/test_pkey_dsa.rb b/test/test_pkey_dsa.rb index 0019c8aec..3fb4dc4c7 100644 --- a/test/test_pkey_dsa.rb +++ b/test/test_pkey_dsa.rb @@ -1,6 +1,5 @@ # frozen_string_literal: false require_relative 'utils' -require 'base64' if defined?(OpenSSL::TestUtils) diff --git a/test/test_pkey_rsa.rb b/test/test_pkey_rsa.rb index d603b7acc..c12055633 100644 --- a/test/test_pkey_rsa.rb +++ b/test/test_pkey_rsa.rb @@ -1,6 +1,5 @@ # frozen_string_literal: false -require_relative 'utils' -require 'base64' +require_relative "utils" if defined?(OpenSSL::TestUtils) diff --git a/test/test_random.rb b/test/test_random.rb index 607946192..c0160f9a7 100644 --- a/test/test_random.rb +++ b/test/test_random.rb @@ -1,6 +1,8 @@ # frozen_string_literal: false require_relative "utils" +if defined?(OpenSSL::TestUtils) + class OpenSSL::TestRandom < OpenSSL::TestCase def test_random_bytes assert_equal("", OpenSSL::Random.random_bytes(0)) @@ -12,4 +14,6 @@ def test_pseudo_bytes assert_equal("", OpenSSL::Random.pseudo_bytes(0)) assert_equal(12, OpenSSL::Random.pseudo_bytes(12).bytesize) end if OpenSSL::Random.methods.include?(:pseudo_bytes) -end if defined?(OpenSSL::TestCase) +end + +end diff --git a/test/ut_eof.rb b/test/ut_eof.rb index 6de41c4a7..a49ad5133 100644 --- a/test/ut_eof.rb +++ b/test/ut_eof.rb @@ -1,6 +1,8 @@ # frozen_string_literal: false require 'test/unit' +if defined?(OpenSSL::TestUtils) + module OpenSSL::TestEOF def test_eof_0 open_file("") {|f| @@ -127,3 +129,5 @@ def test_eof_1_seek end end end + +end diff --git a/test/utils.rb b/test/utils.rb index 4a7d4faa8..6da02f696 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -30,11 +30,12 @@ end require "test/unit" -require 'tempfile' -require "rbconfig" +require "tempfile" require "socket" require "envutil" +if defined?(OpenSSL) && OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10000000 + module OpenSSL::TestUtils module Fixtures module_function @@ -130,177 +131,177 @@ def silent $VERBOSE = back end end +end - class OpenSSL::TestCase < Test::Unit::TestCase - include OpenSSL::TestUtils - extend OpenSSL::TestUtils +class OpenSSL::TestCase < Test::Unit::TestCase + include OpenSSL::TestUtils + extend OpenSSL::TestUtils - def setup - if ENV["OSSL_GC_STRESS"] == "1" - GC.stress = true - end + def setup + if ENV["OSSL_GC_STRESS"] == "1" + GC.stress = true end + end - def teardown - if ENV["OSSL_GC_STRESS"] == "1" - GC.stress = false - end - # OpenSSL error stack must be empty - assert_equal([], OpenSSL.errors) + def teardown + if ENV["OSSL_GC_STRESS"] == "1" + GC.stress = false end + # OpenSSL error stack must be empty + assert_equal([], OpenSSL.errors) end +end - class OpenSSL::SSLTestCase < OpenSSL::TestCase - RUBY = EnvUtil.rubybin - ITERATIONS = ($0 == __FILE__) ? 100 : 10 - - def setup - super - @ca_key = Fixtures.pkey("rsa2048") - @svr_key = Fixtures.pkey("rsa1024") - @cli_key = Fixtures.pkey("dsa1024") - @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") - @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") - @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") - ca_exts = [ - ["basicConstraints","CA:TRUE",true], - ["keyUsage","cRLSign,keyCertSign",true], - ] - ee_exts = [ - ["keyUsage","keyEncipherment,digitalSignature",true], - ] - @ca_cert = issue_cert(@ca, @ca_key, 1, ca_exts, nil, nil) - @svr_cert = issue_cert(@svr, @svr_key, 2, ee_exts, @ca_cert, @ca_key) - @cli_cert = issue_cert(@cli, @cli_key, 3, ee_exts, @ca_cert, @ca_key) - @server = nil - end +class OpenSSL::SSLTestCase < OpenSSL::TestCase + RUBY = EnvUtil.rubybin + ITERATIONS = ($0 == __FILE__) ? 100 : 10 - def readwrite_loop(ctx, ssl) - while line = ssl.gets - ssl.write(line) - end - rescue OpenSSL::SSL::SSLError - rescue IOError - ensure - ssl.close rescue nil + def setup + super + @ca_key = Fixtures.pkey("rsa2048") + @svr_key = Fixtures.pkey("rsa1024") + @cli_key = Fixtures.pkey("dsa1024") + @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") + @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") + @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") + ca_exts = [ + ["basicConstraints","CA:TRUE",true], + ["keyUsage","cRLSign,keyCertSign",true], + ] + ee_exts = [ + ["keyUsage","keyEncipherment,digitalSignature",true], + ] + @ca_cert = issue_cert(@ca, @ca_key, 1, ca_exts, nil, nil) + @svr_cert = issue_cert(@svr, @svr_key, 2, ee_exts, @ca_cert, @ca_key) + @cli_cert = issue_cert(@cli, @cli_key, 3, ee_exts, @ca_cert, @ca_key) + @server = nil + end + + def readwrite_loop(ctx, ssl) + while line = ssl.gets + ssl.write(line) end + rescue OpenSSL::SSL::SSLError + rescue IOError + ensure + ssl.close rescue nil + end - def server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads) - loop do - ssl = nil - begin - readable, = IO.select([ssls, stop_pipe_r]) - if readable.include? stop_pipe_r - return - end - ssl = ssls.accept - rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET - if ignore_listener_error - retry - else - raise - end + def server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads) + loop do + ssl = nil + begin + readable, = IO.select([ssls, stop_pipe_r]) + if readable.include? stop_pipe_r + return end - - th = Thread.start do - server_proc.call(ctx, ssl) + ssl = ssls.accept + rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET + if ignore_listener_error + retry + else + raise end - threads << th end - rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET - if !ignore_listener_error - raise + + th = Thread.start do + server_proc.call(ctx, ssl) end + threads << th + end + rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET + if !ignore_listener_error + raise end + end - def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true, - ctx_proc: nil, server_proc: method(:readwrite_loop), - ignore_listener_error: false, &block) - IO.pipe {|stop_pipe_r, stop_pipe_w| - store = OpenSSL::X509::Store.new - store.add_cert(@ca_cert) - store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT - ctx = OpenSSL::SSL::SSLContext.new - ctx.cert_store = store - ctx.cert = @svr_cert - ctx.key = @svr_key - ctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } - begin - ctx.ecdh_curves = "P-256" - rescue NotImplementedError - end - ctx.verify_mode = verify_mode - ctx_proc.call(ctx) if ctx_proc - - Socket.do_not_reverse_lookup = true - tcps = nil - tcps = TCPServer.new("127.0.0.1", 0) - port = tcps.connect_address.ip_port - - ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) - ssls.start_immediately = start_immediately - - threads = [] - begin - server = Thread.new do - begin - server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads) - ensure - tcps.close - end + def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true, + ctx_proc: nil, server_proc: method(:readwrite_loop), + ignore_listener_error: false, &block) + IO.pipe {|stop_pipe_r, stop_pipe_w| + store = OpenSSL::X509::Store.new + store.add_cert(@ca_cert) + store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT + ctx = OpenSSL::SSL::SSLContext.new + ctx.cert_store = store + ctx.cert = @svr_cert + ctx.key = @svr_key + ctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } + begin + ctx.ecdh_curves = "P-256" + rescue NotImplementedError + end + ctx.verify_mode = verify_mode + ctx_proc.call(ctx) if ctx_proc + + Socket.do_not_reverse_lookup = true + tcps = nil + tcps = TCPServer.new("127.0.0.1", 0) + port = tcps.connect_address.ip_port + + ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) + ssls.start_immediately = start_immediately + + threads = [] + begin + server = Thread.new do + begin + server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads) + ensure + tcps.close end - threads.unshift server + end + threads.unshift server - $stderr.printf("SSL server started: pid=%d port=%d\n", $$, port) if $DEBUG + $stderr.printf("SSL server started: pid=%d port=%d\n", $$, port) if $DEBUG - client = Thread.new do - begin - block.call(server, port.to_i) - ensure - stop_pipe_w.close - end + client = Thread.new do + begin + block.call(server, port.to_i) + ensure + stop_pipe_w.close end - threads.unshift client - ensure - assert_join_threads(threads) end - } - end + threads.unshift client + ensure + assert_join_threads(threads) + end + } end +end - class OpenSSL::PKeyTestCase < OpenSSL::TestCase - def check_component(base, test, keys) - keys.each { |comp| - assert_equal base.send(comp), test.send(comp) - } - end +class OpenSSL::PKeyTestCase < OpenSSL::TestCase + def check_component(base, test, keys) + keys.each { |comp| + assert_equal base.send(comp), test.send(comp) + } + end - def dup_public(key) - case key - when OpenSSL::PKey::RSA - rsa = OpenSSL::PKey::RSA.new - rsa.set_key(key.n, key.e, nil) - rsa - when OpenSSL::PKey::DSA - dsa = OpenSSL::PKey::DSA.new - dsa.set_pqg(key.p, key.q, key.g) - dsa.set_key(key.pub_key, nil) - dsa - when OpenSSL::PKey::DH - dh = OpenSSL::PKey::DH.new - dh.set_pqg(key.p, nil, key.g) - dh + def dup_public(key) + case key + when OpenSSL::PKey::RSA + rsa = OpenSSL::PKey::RSA.new + rsa.set_key(key.n, key.e, nil) + rsa + when OpenSSL::PKey::DSA + dsa = OpenSSL::PKey::DSA.new + dsa.set_pqg(key.p, key.q, key.g) + dsa.set_key(key.pub_key, nil) + dsa + when OpenSSL::PKey::DH + dh = OpenSSL::PKey::DH.new + dh.set_pqg(key.p, nil, key.g) + dh + else + if defined?(OpenSSL::PKey::EC) && OpenSSL::PKey::EC === key + ec = OpenSSL::PKey::EC.new(key.group) + ec.public_key = key.public_key + ec else - if defined?(OpenSSL::PKey::EC) && OpenSSL::PKey::EC === key - ec = OpenSSL::PKey::EC.new(key.group) - ec.public_key = key.public_key - ec - else - raise "unknown key type" - end + raise "unknown key type" end end end +end -end if defined?(OpenSSL::OPENSSL_LIBRARY_VERSION) and - /\AOpenSSL +0\./ !~ OpenSSL::OPENSSL_LIBRARY_VERSION +end From 94f62a7de6ebdeb7c99e7e1b313872c03a84712a Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sun, 13 Aug 2017 23:04:42 +0900 Subject: [PATCH 04/15] test/utils: remove OpenSSL::TestUtils.silent Use EnvUtil.suppress_warning instead. We have started to use it already, and the name 'suppress_warning' expresses what it does more clearly. --- test/test_config.rb | 6 +++--- test/test_ssl.rb | 4 ++-- test/utils.rb | 9 --------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/test/test_config.rb b/test/test_config.rb index cc314335f..99dcc4972 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -173,7 +173,7 @@ def test_get_value_ENV def test_value # suppress deprecation warnings - OpenSSL::TestUtils.silent do + EnvUtil.suppress_warning do assert_equal('CA_default', @it.value('ca', 'default_ca')) assert_equal(nil, @it.value('ca', 'no such key')) assert_equal(nil, @it.value('no such section', 'no such key')) @@ -186,7 +186,7 @@ def test_value end def test_value_ENV - OpenSSL::TestUtils.silent do + EnvUtil.suppress_warning do key = ENV.keys.first assert_not_nil(key) # make sure we have at least one ENV var. assert_equal(ENV[key], @it.value('ENV', key)) @@ -201,7 +201,7 @@ def test_aref end def test_section - OpenSSL::TestUtils.silent do + EnvUtil.suppress_warning do assert_equal({'HOME' => '.'}, @it.section('default')) assert_equal({'dir' => './demoCA', 'certs' => './certs'}, @it.section('CA_default')) assert_equal({}, @it.section('no_such_section')) diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 31168b80b..e3a10c34a 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -187,7 +187,7 @@ def test_client_ca end def test_read_nonblock_without_session - OpenSSL::TestUtils.silent do + EnvUtil.suppress_warning do start_server(start_immediately: false) { |server, port| sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) @@ -332,7 +332,7 @@ def test_exception_in_verify_callback_is_ignored ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) ssl.sync_close = true begin - OpenSSL::TestUtils.silent do + EnvUtil.suppress_warning do # SSLError, not RuntimeError assert_raise(OpenSSL::SSL::SSLError) { ssl.connect } end diff --git a/test/utils.rb b/test/utils.rb index 6da02f696..a672b916f 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -122,15 +122,6 @@ def get_subject_key_id(cert) pkvalue = publickey.value OpenSSL::Digest::SHA1.hexdigest(pkvalue).scan(/../).join(":").upcase end - - def silent - begin - back, $VERBOSE = $VERBOSE, nil - yield - ensure - $VERBOSE = back - end - end end class OpenSSL::TestCase < Test::Unit::TestCase From 36dc23f65026e4374851aae511b0ff3a39143dfe Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 23 Aug 2017 13:21:41 +0900 Subject: [PATCH 05/15] test/utils: add SSLTestCase#tls12_supported? Add a method that returns whether the OpenSSL supports TLS 1.2 or not. This will be useful for test cases that are specific to TLS ~1.2. --- test/utils.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/utils.rb b/test/utils.rb index a672b916f..0bcdf3f72 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -168,6 +168,10 @@ def setup @server = nil end + def tls12_supported? + OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) + end + def readwrite_loop(ctx, ssl) while line = ssl.gets ssl.write(line) From 6f16135eb52b2460f2ff6a447def285878567077 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sun, 13 Aug 2017 22:53:45 +0900 Subject: [PATCH 06/15] test/utils: have start_server yield only the port number The block passed to start_server is invoked with two arguments, the running thread object for the server and the automatically-selected port number. The first argument is completely useless and actually is not used anywhere. --- test/test_ssl.rb | 94 ++++++++++++++++++++-------------------- test/test_ssl_session.rb | 12 ++--- test/utils.rb | 2 +- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/test/test_ssl.rb b/test/test_ssl.rb index e3a10c34a..32879b7dc 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -35,7 +35,7 @@ def test_ssl_with_server_cert readwrite_loop(ctx, ssl) } - start_server(ctx_proc: ctx_proc, server_proc: server_proc) { |server, port| + start_server(ctx_proc: ctx_proc, server_proc: server_proc) { |port| begin sock = TCPSocket.new("127.0.0.1", port) ctx = OpenSSL::SSL::SSLContext.new @@ -56,7 +56,7 @@ def test_ssl_with_server_cert end def test_sysread_and_syswrite - start_server { |server, port| + start_server { |port| server_connect(port) { |ssl| str = "x" * 100 + "\n" ssl.syswrite(str) @@ -72,7 +72,7 @@ def test_sysread_and_syswrite end def test_sync_close - start_server { |server, port| + start_server { |port| begin sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) @@ -97,7 +97,7 @@ def test_sync_close end def test_copy_stream - start_server do |server, port| + start_server do |port| server_connect(port) do |ssl| IO.pipe do |r, w| str = "hello world\n" @@ -112,7 +112,7 @@ def test_copy_stream def test_client_auth_failure vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT - start_server(verify_mode: vflag, ignore_listener_error: true) { |server, port| + start_server(verify_mode: vflag, ignore_listener_error: true) { |port| sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) ssl.sync_close = true @@ -126,7 +126,7 @@ def test_client_auth_failure def test_client_auth_success vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT - start_server(verify_mode: vflag) { |server, port| + start_server(verify_mode: vflag) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.key = @cli_key ctx.cert = @cli_cert @@ -153,7 +153,7 @@ def test_client_auth_success def test_client_auth_public_key vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT - start_server(verify_mode: vflag, ignore_listener_error: true) do |server, port| + start_server(verify_mode: vflag, ignore_listener_error: true) do |port| assert_raise(ArgumentError) { ctx = OpenSSL::SSL::SSLContext.new ctx.key = @cli_key.public_key @@ -175,7 +175,7 @@ def test_client_ca end vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT - start_server(verify_mode: vflag, ctx_proc: ctx_proc) { |server, port| + start_server(verify_mode: vflag, ctx_proc: ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new client_ca_from_server = nil ctx.client_cert_cb = Proc.new do |sslconn| @@ -188,7 +188,7 @@ def test_client_ca def test_read_nonblock_without_session EnvUtil.suppress_warning do - start_server(start_immediately: false) { |server, port| + start_server(start_immediately: false) { |port| sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) ssl.sync_close = true @@ -225,7 +225,7 @@ def test_starttls EnvUtil.suppress_warning do # read/write on not started session start_server(start_immediately: false, - server_proc: server_proc) { |server, port| + server_proc: server_proc) { |port| begin sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) @@ -248,7 +248,7 @@ def test_starttls end def test_parallel - start_server { |server, port| + start_server { |port| ssls = [] 10.times{ sock = TCPSocket.new("127.0.0.1", port) @@ -269,7 +269,7 @@ def test_parallel end def test_verify_result - start_server(ignore_listener_error: true) { |server, port| + start_server(ignore_listener_error: true) { |port| sock = TCPSocket.new("127.0.0.1", port) ctx = OpenSSL::SSL::SSLContext.new ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER @@ -283,7 +283,7 @@ def test_verify_result end } - start_server { |server, port| + start_server { |port| sock = TCPSocket.new("127.0.0.1", port) ctx = OpenSSL::SSL::SSLContext.new ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER @@ -301,7 +301,7 @@ def test_verify_result end } - start_server(ignore_listener_error: true) { |server, port| + start_server(ignore_listener_error: true) { |port| sock = TCPSocket.new("127.0.0.1", port) ctx = OpenSSL::SSL::SSLContext.new ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER @@ -321,7 +321,7 @@ def test_verify_result end def test_exception_in_verify_callback_is_ignored - start_server(ignore_listener_error: true) { |server, port| + start_server(ignore_listener_error: true) { |port| sock = TCPSocket.new("127.0.0.1", port) ctx = OpenSSL::SSL::SSLContext.new ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER @@ -364,7 +364,7 @@ def test_post_connect_check_with_anon_ciphers ctx.security_level = 0 } - start_server(ctx_proc: ctx_proc) { |server, port| + start_server(ctx_proc: ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.ciphers = "aNULL" ctx.security_level = 0 @@ -379,7 +379,7 @@ def test_post_connect_check_with_anon_ciphers def test_post_connection_check sslerr = OpenSSL::SSL::SSLError - start_server { |server, port| + start_server { |port| server_connect(port) { |ssl| assert_raise(sslerr){ssl.post_connection_check("localhost.localdomain")} assert_raise(sslerr){ssl.post_connection_check("127.0.0.1")} @@ -400,7 +400,7 @@ def test_post_connection_check ["subjectAltName","IP:127.0.0.1",false], ] @svr_cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key) - start_server { |server, port| + start_server { |port| server_connect(port) { |ssl| assert(ssl.post_connection_check("localhost.localdomain")) assert(ssl.post_connection_check("127.0.0.1")) @@ -420,7 +420,7 @@ def test_post_connection_check ["subjectAltName","DNS:*.localdomain",false], ] @svr_cert = issue_cert(@svr, @svr_key, 5, exts, @ca_cert, @ca_key) - start_server { |server, port| + start_server { |port| server_connect(port) { |ssl| assert(ssl.post_connection_check("localhost.localdomain")) assert_raise(sslerr){ssl.post_connection_check("127.0.0.1")} @@ -642,7 +642,7 @@ def test_tlsext_hostname end } } - start_server(ctx_proc: ctx_proc) do |server, port| + start_server(ctx_proc: ctx_proc) do |port| ctx = OpenSSL::SSL::SSLContext.new ctx.ciphers = "ALL" ctx.security_level = 0 @@ -716,7 +716,7 @@ def test_verify_hostname_on_connect ctx.key = @svr_key } - start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |server, port| + start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| ctx = OpenSSL::SSL::SSLContext.new ctx.verify_hostname = true ctx.cert_store = OpenSSL::X509::Store.new @@ -765,7 +765,7 @@ def test_multibyte_read_write assert_equal(num_written, raw_size) ssl.close } - start_server(server_proc: server_proc) { |server, port| + start_server(server_proc: server_proc) { |port| server_connect(port) { |ssl| str = auml * i num_written = ssl.write(str) @@ -781,7 +781,7 @@ def test_unset_OP_ALL # But it also degrades gracefully, so keep it ctx.options = OpenSSL::SSL::OP_ALL } - start_server(ctx_proc: ctx_proc) { |server, port| + start_server(ctx_proc: ctx_proc) { |port| server_connect(port) { |ssl| ssl.puts('hello') assert_equal("hello\n", ssl.gets) @@ -793,7 +793,7 @@ def test_unset_OP_ALL def test_forbid_ssl_v3_for_client ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv3 } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.ssl_version = :SSLv3 assert_handshake_error { server_connect(port, ctx) } @@ -801,7 +801,7 @@ def test_forbid_ssl_v3_for_client end def test_forbid_ssl_v3_from_server - start_server_version(:SSLv3) { |server, port| + start_server_version(:SSLv3) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv3 assert_handshake_error { server_connect(port, ctx) } @@ -813,14 +813,14 @@ def test_forbid_ssl_v3_from_server if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_1) && OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1) def test_tls_v1_1 - start_server_version(:TLSv1_1) { |server, port| + start_server_version(:TLSv1_1) { |port| server_connect(port) { |ssl| assert_equal("TLSv1.1", ssl.ssl_version) } } end def test_forbid_tls_v1_for_client ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1 } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.ssl_version = :TLSv1 assert_handshake_error { server_connect(port, ctx) } @@ -828,7 +828,7 @@ def test_forbid_tls_v1_for_client end def test_forbid_tls_v1_from_server - start_server_version(:TLSv1) { |server, port| + start_server_version(:TLSv1) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1 assert_handshake_error { server_connect(port, ctx) } @@ -840,7 +840,7 @@ def test_forbid_tls_v1_from_server if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_1) def test_tls_v1_2 - start_server_version(:TLSv1_2) { |server, port| + start_server_version(:TLSv1_2) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.ssl_version = :TLSv1_2_client server_connect(port, ctx) { |ssl| assert_equal("TLSv1.2", ssl.ssl_version) } @@ -849,7 +849,7 @@ def test_tls_v1_2 def test_forbid_tls_v1_1_for_client ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_1 } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.ssl_version = :TLSv1_1 assert_handshake_error { server_connect(port, ctx) } @@ -857,7 +857,7 @@ def test_forbid_tls_v1_1_for_client end if defined?(OpenSSL::SSL::OP_NO_TLSv1_1) def test_forbid_tls_v1_1_from_server - start_server_version(:TLSv1_1) { |server, port| + start_server_version(:TLSv1_1) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_1 assert_handshake_error { server_connect(port, ctx) } @@ -866,7 +866,7 @@ def test_forbid_tls_v1_1_from_server def test_forbid_tls_v1_2_for_client ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_2 } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.ssl_version = :TLSv1_2 assert_handshake_error { server_connect(port, ctx) } @@ -874,7 +874,7 @@ def test_forbid_tls_v1_2_for_client end if defined?(OpenSSL::SSL::OP_NO_TLSv1_2) def test_forbid_tls_v1_2_from_server - start_server_version(:TLSv1_2) { |server, port| + start_server_version(:TLSv1_2) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_2 assert_handshake_error { server_connect(port, ctx) } @@ -887,7 +887,7 @@ def test_renegotiation_cb num_handshakes = 0 renegotiation_cb = Proc.new { |ssl| num_handshakes += 1 } ctx_proc = Proc.new { |ctx| ctx.renegotiation_cb = renegotiation_cb } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| server_connect(port) { |ssl| assert_equal(1, num_handshakes) } @@ -903,7 +903,7 @@ def test_alpn_protocol_selection_ary } ctx.alpn_protocols = advertised } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.alpn_protocols = advertised server_connect(port, ctx) { |ssl| @@ -949,7 +949,7 @@ def test_alpn_protocol_selection_cancel def test_npn_protocol_selection_ary advertised = ["http/1.1", "spdy/2"] ctx_proc = Proc.new { |ctx| ctx.npn_protocols = advertised } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| selector = lambda { |which| ctx = OpenSSL::SSL::SSLContext.new ctx.npn_select_cb = -> (protocols) { protocols.send(which) } @@ -969,7 +969,7 @@ def advertised.each yield "spdy/2" end ctx_proc = Proc.new { |ctx| ctx.npn_protocols = advertised } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| selector = lambda { |selected, which| ctx = OpenSSL::SSL::SSLContext.new ctx.npn_select_cb = -> (protocols) { protocols.to_a.send(which) } @@ -984,7 +984,7 @@ def advertised.each def test_npn_protocol_selection_cancel ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.npn_select_cb = -> (protocols) { raise RuntimeError.new } assert_raise(RuntimeError) { server_connect(port, ctx) } @@ -993,7 +993,7 @@ def test_npn_protocol_selection_cancel def test_npn_advertised_protocol_too_long ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["a" * 256] } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.npn_select_cb = -> (protocols) { protocols.first } assert_handshake_error { server_connect(port, ctx) } @@ -1002,7 +1002,7 @@ def test_npn_advertised_protocol_too_long def test_npn_selected_protocol_too_long ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] } - start_server_version(:SSLv23, ctx_proc) { |server, port| + start_server_version(:SSLv23, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.npn_select_cb = -> (protocols) { "a" * 256 } assert_handshake_error { server_connect(port, ctx) } @@ -1013,7 +1013,7 @@ def test_npn_selected_protocol_too_long def test_invalid_shutdown_by_gc assert_nothing_raised { - start_server { |server, port| + start_server { |port| 10.times { sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) @@ -1026,7 +1026,7 @@ def test_invalid_shutdown_by_gc end def test_close_after_socket_close - start_server { |server, port| + start_server { |port| sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) ssl.sync_close = true @@ -1080,7 +1080,7 @@ def test_get_ephemeral_key 'AES128-SHA' => nil } conf_proc = Proc.new { |ctx| ctx.ciphers = 'ALL' } - start_server(ctx_proc: conf_proc) do |server, port| + start_server(ctx_proc: conf_proc) do |port| ciphers.each do |cipher, ephemeral| ctx = OpenSSL::SSL::SSLContext.new begin @@ -1109,7 +1109,7 @@ def test_dh_callback Fixtures.pkey_dh("dh1024") } } - start_server(ctx_proc: ctx_proc) do |server, port| + start_server(ctx_proc: ctx_proc) do |port| server_connect(port) { |ssl| assert called, "dh callback should be called" if ssl.respond_to?(:tmp_key) @@ -1124,7 +1124,7 @@ def test_connect_works_when_setting_dh_callback_to_nil ctx.ciphers = "DH:!NULL" # use DH ctx.tmp_dh_callback = nil } - start_server(ctx_proc: ctx_proc) do |server, port| + start_server(ctx_proc: ctx_proc) do |port| EnvUtil.suppress_warning { # uses default callback assert_nothing_raised { server_connect(port) { } @@ -1187,7 +1187,7 @@ def test_ecdh_curves end ctx.ecdh_curves = "P-384:P-521" } - start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |server, port| + start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| ctx = OpenSSL::SSL::SSLContext.new ctx.ecdh_curves = "P-256:P-384" # disable P-521 for OpenSSL >= 1.0.2 @@ -1248,7 +1248,7 @@ def test_dup def test_freeze_calls_setup bug = "[ruby/openssl#85]" - start_server(ignore_listener_error: true) { |server, port| + start_server(ignore_listener_error: true) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER ctx.freeze diff --git a/test/test_ssl_session.rb b/test/test_ssl_session.rb index 7a99dca5e..d4a8941b4 100644 --- a/test/test_ssl_session.rb +++ b/test/test_ssl_session.rb @@ -27,7 +27,7 @@ def test_session_equals -----END SSL SESSION PARAMETERS----- SESSION - start_server(ignore_listener_error: true) { |_, port| + start_server(ignore_listener_error: true) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT ctx.session_id_context = self.object_id.to_s @@ -46,7 +46,7 @@ def test_session_equals def test_session Timeout.timeout(5) do - start_server do |server, port| + start_server do |port| sock = TCPSocket.new("127.0.0.1", port) ctx = OpenSSL::SSL::SSLContext.new ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) @@ -154,7 +154,7 @@ def test_session_exts_read def test_client_session last_session = nil - start_server do |server, port| + start_server do |port| 2.times do sock = TCPSocket.new("127.0.0.1", port) ctx = OpenSSL::SSL::SSLContext.new @@ -235,7 +235,7 @@ def test_server_session end first_session = nil - start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |server, port| + start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |port| 10.times do |i| sock = TCPSocket.new("127.0.0.1", port) ctx = OpenSSL::SSL::SSLContext.new @@ -283,7 +283,7 @@ def test_ctx_client_session_cb # any resulting value is OK (ignored) } - start_server do |server, port| + start_server do |port| sock = TCPSocket.new("127.0.0.1", port) begin ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) @@ -342,7 +342,7 @@ def test_ctx_server_session_cb c.session_cache_stats readwrite_loop(c, ssl) } - start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |server, port| + start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |port| last_client_session = nil 3.times do sock = TCPSocket.new("127.0.0.1", port) diff --git a/test/utils.rb b/test/utils.rb index 0bcdf3f72..8e5fc55ba 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -252,7 +252,7 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true client = Thread.new do begin - block.call(server, port.to_i) + block.call(port) ensure stop_pipe_w.close end From a0019110ddc97d3a46b99dc822b520f41afae687 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sun, 13 Aug 2017 22:53:45 +0900 Subject: [PATCH 07/15] test/utils: do not set ecdh_curves in start_server An assumption in OpenSSL::TestSSL#test_get_ephemeral_key is that the ephemeral key type is always EVP_PKEY_EC when negotiated with an ECDHE cipher suite. This is not true if X25519 is chosen. The test is passing because we happen to fix the group to P-256 in start_server, but let's make it explicit. --- test/test_ssl.rb | 70 ++++++++++++++++++++++++++++++++---------------- test/utils.rb | 4 --- 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 32879b7dc..418365a40 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -1072,30 +1072,54 @@ def test_close_and_socket_close_while_connecting end def test_get_ephemeral_key - return unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key) - pkey = OpenSSL::PKey - ciphers = { - 'ECDHE-RSA-AES128-SHA' => (pkey::EC if defined?(pkey::EC)), - 'DHE-RSA-AES128-SHA' => (pkey::DH if defined?(pkey::DH)), - 'AES128-SHA' => nil - } - conf_proc = Proc.new { |ctx| ctx.ciphers = 'ALL' } - start_server(ctx_proc: conf_proc) do |port| - ciphers.each do |cipher, ephemeral| + # OpenSSL >= 1.0.2 + unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key) + pend "SSL_get_server_tmp_key() is not supported" + end + + if tls12_supported? + # kRSA + ctx_proc1 = proc { |ctx| + ctx.ssl_version = :TLSv1_2 + ctx.ciphers = "kRSA" + } + start_server(ctx_proc: ctx_proc1) do |port| ctx = OpenSSL::SSL::SSLContext.new - begin - ctx.ciphers = cipher - rescue OpenSSL::SSL::SSLError => e - next if /no cipher match/ =~ e.message - raise - end - server_connect(port, ctx) do |ssl| - if ephemeral - assert_instance_of(ephemeral, ssl.tmp_key) - else - assert_nil(ssl.tmp_key) - end - end + ctx.ssl_version = :TLSv1_2 + ctx.ciphers = "kRSA" + server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key } + end + end + + if defined?(OpenSSL::PKey::DH) && tls12_supported? + # DHE + # TODO: How to test this with TLS 1.3? + ctx_proc2 = proc { |ctx| + ctx.ssl_version = :TLSv1_2 + ctx.ciphers = "EDH" + } + start_server(ctx_proc: ctx_proc2) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.ssl_version = :TLSv1_2 + ctx.ciphers = "EDH" + server_connect(port, ctx) { |ssl| + assert_instance_of OpenSSL::PKey::DH, ssl.tmp_key + } + end + end + + if defined?(OpenSSL::PKey::EC) + # ECDHE + ctx_proc3 = proc { |ctx| + ctx.ciphers = "DEFAULT:!kRSA:!kEDH" + ctx.ecdh_curves = "P-256" + } + start_server(ctx_proc: ctx_proc3) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.ciphers = "DEFAULT:!kRSA:!kEDH" + server_connect(port, ctx) { |ssl| + assert_instance_of OpenSSL::PKey::EC, ssl.tmp_key + } end end end diff --git a/test/utils.rb b/test/utils.rb index 8e5fc55ba..2f2701af2 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -222,10 +222,6 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true ctx.cert = @svr_cert ctx.key = @svr_key ctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } - begin - ctx.ecdh_curves = "P-256" - rescue NotImplementedError - end ctx.verify_mode = verify_mode ctx_proc.call(ctx) if ctx_proc From 81f3efcbc5837af5e918ace44d8034e6c5ac0fb7 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sun, 5 Feb 2017 00:03:39 +0900 Subject: [PATCH 08/15] test/utils: let server_loop close socket Close the socket by server_loop rather than by server_proc. This reduces code duplication. --- test/test_ssl.rb | 22 ++++++++-------------- test/utils.rb | 17 +++++++---------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 418365a40..3917793e0 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -206,21 +206,16 @@ def test_read_nonblock_without_session def test_starttls server_proc = -> (ctx, ssl) { - begin - while line = ssl.gets - if line =~ /^STARTTLS$/ - ssl.write("x") - ssl.flush - ssl.accept - next - end - ssl.write(line) + while line = ssl.gets + if line =~ /^STARTTLS$/ + ssl.write("x") + ssl.flush + ssl.accept + break end - rescue OpenSSL::SSL::SSLError - rescue IOError - ensure - ssl.close rescue nil + ssl.write(line) end + readwrite_loop(ctx, ssl) } EnvUtil.suppress_warning do # read/write on not started session @@ -763,7 +758,6 @@ def test_multibyte_read_write cmp.force_encoding(Encoding::UTF_8) assert_equal(str, cmp) assert_equal(num_written, raw_size) - ssl.close } start_server(server_proc: server_proc) { |port| server_connect(port) { |ssl| diff --git a/test/utils.rb b/test/utils.rb index 2f2701af2..8038db7c7 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -176,10 +176,6 @@ def readwrite_loop(ctx, ssl) while line = ssl.gets ssl.write(line) end - rescue OpenSSL::SSL::SSLError - rescue IOError - ensure - ssl.close rescue nil end def server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads) @@ -191,7 +187,8 @@ def server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, thre return end ssl = ssls.accept - rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET + rescue OpenSSL::SSL::SSLError, IOError, Errno::EBADF, Errno::EINVAL, + Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET if ignore_listener_error retry else @@ -200,14 +197,14 @@ def server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, thre end th = Thread.start do - server_proc.call(ctx, ssl) + begin + server_proc.call(ctx, ssl) + ensure + ssl.close + end end threads << th end - rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET - if !ignore_listener_error - raise - end end def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true, From 8fea1ed5ede36a5b7269698a0718b186fb101fbf Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 14 Aug 2017 01:12:09 +0900 Subject: [PATCH 09/15] test/utils: improve error handling in start_server start_server can hang if the given block exits before closing sockets that the block opens. While this is a carelessness of the caller, we can do a better job. --- test/utils.rb | 76 ++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/test/utils.rb b/test/utils.rb index 8038db7c7..6d5511644 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -178,35 +178,6 @@ def readwrite_loop(ctx, ssl) end end - def server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads) - loop do - ssl = nil - begin - readable, = IO.select([ssls, stop_pipe_r]) - if readable.include? stop_pipe_r - return - end - ssl = ssls.accept - rescue OpenSSL::SSL::SSLError, IOError, Errno::EBADF, Errno::EINVAL, - Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET - if ignore_listener_error - retry - else - raise - end - end - - th = Thread.start do - begin - server_proc.call(ctx, ssl) - ensure - ssl.close - end - end - threads << th - end - end - def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true, ctx_proc: nil, server_proc: method(:readwrite_loop), ignore_listener_error: false, &block) @@ -223,7 +194,6 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true ctx_proc.call(ctx) if ctx_proc Socket.do_not_reverse_lookup = true - tcps = nil tcps = TCPServer.new("127.0.0.1", 0) port = tcps.connect_address.ip_port @@ -232,26 +202,58 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true threads = [] begin - server = Thread.new do + server_thread = Thread.new do begin - server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads) + loop do + begin + readable, = IO.select([ssls, stop_pipe_r]) + break if readable.include? stop_pipe_r + ssl = ssls.accept + rescue OpenSSL::SSL::SSLError, IOError, Errno::EBADF, Errno::EINVAL, + Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET + retry if ignore_listener_error + raise + end + + th = Thread.new do + begin + server_proc.call(ctx, ssl) + ensure + ssl.close + end + true + end + threads << th + end ensure tcps.close end end - threads.unshift server - $stderr.printf("SSL server started: pid=%d port=%d\n", $$, port) if $DEBUG - - client = Thread.new do + client_thread = Thread.new do begin block.call(port) ensure + # Stop accepting new connection stop_pipe_w.close + server_thread.join end end - threads.unshift client + threads.unshift client_thread ensure + # Terminate existing connections. If a thread did 'pend', re-raise it. + pend = nil + threads.each { |th| + begin + th.join(10) or + th.raise(RuntimeError, "[start_server] thread did not exit in 10 secs") + rescue (defined?(MiniTest::Skip) ? MiniTest::Skip : Test::Unit::PendedError) + # MiniTest::Skip is for the Ruby tree + pend = $! + rescue Exception + end + } + raise pend if pend assert_join_threads(threads) end } From 9e2b5dc78a4e123425b4ff5eb30e64dd37ad9fb8 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sun, 13 Aug 2017 23:26:12 +0900 Subject: [PATCH 10/15] test/utils: add OpenSSL::TestUtils.openssl? and .libressl? Add methods that check whether the running OpenSSL is an OpenSSL or a LibreSSL, and optionally check whether the version is newer or equal to the given version number. --- test/test_digest.rb | 65 ++++++++++++++++------------------------ test/test_ocsp.rb | 2 +- test/test_pkey_dsa.rb | 2 +- test/test_ssl.rb | 7 ++--- test/test_ssl_session.rb | 2 +- test/test_x509name.rb | 1 - test/test_x509store.rb | 16 +++------- test/utils.rb | 13 ++++++++ 8 files changed, 49 insertions(+), 59 deletions(-) diff --git a/test/test_digest.rb b/test/test_digest.rb index 9891d99ae..c8817395b 100644 --- a/test/test_digest.rb +++ b/test/test_digest.rb @@ -54,13 +54,10 @@ def test_reset end def test_digest_constants - algs = %w(MD4 MD5 RIPEMD160 SHA1) - if OpenSSL::OPENSSL_VERSION_NUMBER < 0x10100000 + algs = %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512) + if !libressl? && !openssl?(1, 1, 0) algs += %w(DSS1 SHA) end - if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000 - algs += %w(SHA224 SHA256 SHA384 SHA512) - end algs.each do |alg| assert_not_nil(OpenSSL::Digest.new(alg)) klass = OpenSSL::Digest.const_get(alg) @@ -73,34 +70,32 @@ def test_digest_by_oid_and_name check_digest(OpenSSL::ASN1::ObjectId.new("SHA1")) end - if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000 - def encode16(str) - str.unpack("H*").first - end + def encode16(str) + str.unpack("H*").first + end - def test_098_features - sha224_a = "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5" - sha256_a = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" - sha384_a = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31" - sha512_a = "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75" - - assert_equal(sha224_a, OpenSSL::Digest::SHA224.hexdigest("a")) - assert_equal(sha256_a, OpenSSL::Digest::SHA256.hexdigest("a")) - assert_equal(sha384_a, OpenSSL::Digest::SHA384.hexdigest("a")) - assert_equal(sha512_a, OpenSSL::Digest::SHA512.hexdigest("a")) - - assert_equal(sha224_a, encode16(OpenSSL::Digest::SHA224.digest("a"))) - assert_equal(sha256_a, encode16(OpenSSL::Digest::SHA256.digest("a"))) - assert_equal(sha384_a, encode16(OpenSSL::Digest::SHA384.digest("a"))) - assert_equal(sha512_a, encode16(OpenSSL::Digest::SHA512.digest("a"))) - end + def test_sha2 + sha224_a = "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5" + sha256_a = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" + sha384_a = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31" + sha512_a = "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75" + + assert_equal(sha224_a, OpenSSL::Digest::SHA224.hexdigest("a")) + assert_equal(sha256_a, OpenSSL::Digest::SHA256.hexdigest("a")) + assert_equal(sha384_a, OpenSSL::Digest::SHA384.hexdigest("a")) + assert_equal(sha512_a, OpenSSL::Digest::SHA512.hexdigest("a")) + + assert_equal(sha224_a, encode16(OpenSSL::Digest::SHA224.digest("a"))) + assert_equal(sha256_a, encode16(OpenSSL::Digest::SHA256.digest("a"))) + assert_equal(sha384_a, encode16(OpenSSL::Digest::SHA384.digest("a"))) + assert_equal(sha512_a, encode16(OpenSSL::Digest::SHA512.digest("a"))) + end - def test_digest_by_oid_and_name_sha2 - check_digest(OpenSSL::ASN1::ObjectId.new("SHA224")) - check_digest(OpenSSL::ASN1::ObjectId.new("SHA256")) - check_digest(OpenSSL::ASN1::ObjectId.new("SHA384")) - check_digest(OpenSSL::ASN1::ObjectId.new("SHA512")) - end + def test_digest_by_oid_and_name_sha2 + check_digest(OpenSSL::ASN1::ObjectId.new("SHA224")) + check_digest(OpenSSL::ASN1::ObjectId.new("SHA256")) + check_digest(OpenSSL::ASN1::ObjectId.new("SHA384")) + check_digest(OpenSSL::ASN1::ObjectId.new("SHA512")) end def test_openssl_digest @@ -121,14 +116,6 @@ def check_digest(oid) d = OpenSSL::Digest.new(oid.oid) assert_not_nil(d) end - - def libressl? - OpenSSL::OPENSSL_VERSION.include?('LibreSSL') - end - - def version_since(verary) - (OpenSSL::OPENSSL_LIBRARY_VERSION.scan(/\d+/).map(&:to_i) <=> verary) != -1 - end end end diff --git a/test/test_ocsp.rb b/test/test_ocsp.rb index 865bb5230..0440634ab 100644 --- a/test/test_ocsp.rb +++ b/test/test_ocsp.rb @@ -122,7 +122,7 @@ def test_request_sign_verify assert_equal true, req.verify([@cert], store, OpenSSL::OCSP::NOINTERN) ret = req.verify([@cert], store) - if ret || OpenSSL::OPENSSL_VERSION =~ /OpenSSL/ && OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000 + if ret || openssl?(1, 0, 2) || libressl?(2, 4, 2) assert_equal true, ret else # RT2560; OCSP_request_verify() does not find signer cert from 'certs' when diff --git a/test/test_pkey_dsa.rb b/test/test_pkey_dsa.rb index 3fb4dc4c7..474f23888 100644 --- a/test/test_pkey_dsa.rb +++ b/test/test_pkey_dsa.rb @@ -41,7 +41,7 @@ def test_sign_verify assert_equal true, dsa512.verify(OpenSSL::Digest::DSS1.new, signature, data) end - return if OpenSSL::OPENSSL_VERSION_NUMBER <= 0x010000000 + return unless openssl?(1, 0, 0) signature = dsa512.sign("SHA1", data) assert_equal true, dsa512.verify("SHA1", signature, data) diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 3917793e0..872dd2267 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -839,7 +839,7 @@ def test_tls_v1_2 ctx.ssl_version = :TLSv1_2_client server_connect(port, ctx) { |ssl| assert_equal("TLSv1.2", ssl.ssl_version) } } - end if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 + end def test_forbid_tls_v1_1_for_client ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_1 } @@ -888,7 +888,7 @@ def test_renegotiation_cb } end -if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000 +if openssl?(1, 0, 2) || libressl? def test_alpn_protocol_selection_ary advertised = ["http/1.1", "spdy/2"] ctx_proc = Proc.new { |ctx| @@ -1216,8 +1216,7 @@ def test_ecdh_curves end } - if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000 && - !OpenSSL::OPENSSL_VERSION.include?("LibreSSL") + if openssl?(1, 0, 2) || libressl?(2, 5, 1) ctx = OpenSSL::SSL::SSLContext.new ctx.ecdh_curves = "P-256" diff --git a/test/test_ssl_session.rb b/test/test_ssl_session.rb index d4a8941b4..aadbc3b7c 100644 --- a/test/test_ssl_session.rb +++ b/test/test_ssl_session.rb @@ -150,7 +150,7 @@ def test_session_timeout def test_session_exts_read assert(OpenSSL::SSL::Session.new(DUMMY_SESSION)) - end if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x009080bf + end def test_client_session last_session = nil diff --git a/test/test_x509name.rb b/test/test_x509name.rb index 60e8ddb8a..c1dacf4fa 100644 --- a/test/test_x509name.rb +++ b/test/test_x509name.rb @@ -306,7 +306,6 @@ def test_add_entry end def test_add_entry_street - return if OpenSSL::OPENSSL_VERSION_NUMBER < 0x009080df # 0.9.8m # openssl/crypto/objects/obj_mac.h 1.83 dn = [ ["DC", "org"], diff --git a/test/test_x509store.rb b/test/test_x509store.rb index 983437e7d..b40534c6d 100644 --- a/test/test_x509store.rb +++ b/test/test_x509store.rb @@ -209,7 +209,7 @@ def test_verify end def test_set_errors - return if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000 + return if openssl?(1, 1, 0) || libressl? now = Time.now ca1_cert = issue_cert(@ca1, @rsa2048, 1, [], nil, nil) store = OpenSSL::X509::Store.new @@ -225,17 +225,9 @@ def test_set_errors crl2 = issue_crl(revoke_info, 2, now+1800, now+3600, [], ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) store.add_crl(crl1) - if /0\.9\.8.*-rhel/ =~ OpenSSL::OPENSSL_VERSION - # RedHat is distributing a patched version of OpenSSL that allows - # multiple CRL for a key (multi-crl.patch) - assert_nothing_raised do - store.add_crl(crl2) # add CRL issued by same CA twice. - end - else - assert_raise(OpenSSL::X509::StoreError){ - store.add_crl(crl2) # add CRL issued by same CA twice. - } - end + assert_raise(OpenSSL::X509::StoreError){ + store.add_crl(crl2) # add CRL issued by same CA twice. + } end def test_dup diff --git a/test/utils.rb b/test/utils.rb index 6d5511644..b6cca79e1 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -122,6 +122,19 @@ def get_subject_key_id(cert) pkvalue = publickey.value OpenSSL::Digest::SHA1.hexdigest(pkvalue).scan(/../).join(":").upcase end + + def openssl?(major = nil, minor = nil, fix = nil, patch = 0) + return false if OpenSSL::OPENSSL_VERSION.include?("LibreSSL") + return true unless major + OpenSSL::OPENSSL_VERSION_NUMBER >= + major * 0x10000000 + minor * 0x100000 + fix * 0x1000 + patch * 0x10 + end + + def libressl?(major = nil, minor = nil, fix = nil) + version = OpenSSL::OPENSSL_VERSION.scan(/LibreSSL (\d+)\.(\d+)\.(\d+).*/)[0] + return false unless version + !major || (version.map(&:to_i) <=> [major, minor, fix]) >= 0 + end end class OpenSSL::TestCase < Test::Unit::TestCase From c24c56b84abb068f1aeda7ee7acb216ecf3fa335 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 14 Aug 2017 01:21:31 +0900 Subject: [PATCH 11/15] test/utils: do not use DSA certificates in SSL tests LibreSSL 2.6.1 removed DSA support from its SSL code. Also, TLS 1.3 will not support DSA certificates. Use an RSA certificate as the client certificate in the tests, too. --- test/utils.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils.rb b/test/utils.rb index b6cca79e1..4331d8bd8 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -164,7 +164,7 @@ def setup super @ca_key = Fixtures.pkey("rsa2048") @svr_key = Fixtures.pkey("rsa1024") - @cli_key = Fixtures.pkey("dsa1024") + @cli_key = Fixtures.pkey("rsa2048") @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") From ac482b7ca7505c50ac7d5d84a32ae4dc0c5ea438 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 23 Aug 2017 20:28:11 +0900 Subject: [PATCH 12/15] test/test_ssl: remove test_invalid_shutdown_by_gc The very patch that added this test case made the dfree function not send close_notify alert when an SSLSocket is being GCed. Anyway, the new OSSL_GC_STRESS option added by 6ee4b285036e ("test: run test cases under GC.stress if OSSL_GC_STRESS is specified", 2016-12-04) will cover this kind of issues. --- test/test_ssl.rb | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 872dd2267..452e7c476 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -1005,20 +1005,6 @@ def test_npn_selected_protocol_too_long end - def test_invalid_shutdown_by_gc - assert_nothing_raised { - start_server { |port| - 10.times { - sock = TCPSocket.new("127.0.0.1", port) - ssl = OpenSSL::SSL::SSLSocket.new(sock) - GC.start - ssl.connect - sock.close - } - } - } - end - def test_close_after_socket_close start_server { |port| sock = TCPSocket.new("127.0.0.1", port) From 6c62ffbee925c27ed5252ceab298658a54dd9563 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Thu, 24 Aug 2017 16:30:53 +0900 Subject: [PATCH 13/15] test/test_ssl: move test_multibyte_read_write to test_pair --- test/test_pair.rb | 21 +++++++++++++++++++++ test/test_ssl.rb | 24 ------------------------ 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/test/test_pair.rb b/test/test_pair.rb index 570309afd..52a90018c 100644 --- a/test/test_pair.rb +++ b/test/test_pair.rb @@ -187,6 +187,27 @@ def test_puts_empty } end + def test_multibyte_read_write + # German a umlaut + auml = [%w{ C3 A4 }.join('')].pack('H*') + auml.force_encoding(Encoding::UTF_8) + bsize = auml.bytesize + + ssl_pair { |s1, s2| + assert_equal bsize, s1.write(auml) + read = s2.read(bsize) + assert_equal Encoding::ASCII_8BIT, read.encoding + assert_equal bsize, read.bytesize + assert_equal auml, read.force_encoding(Encoding::UTF_8) + + s1.puts(auml) + read = s2.gets + assert_equal Encoding::ASCII_8BIT, read.encoding + assert_equal bsize + 1, read.bytesize + assert_equal auml + "\n", read.force_encoding(Encoding::UTF_8) + } + end + def test_read_nonblock ssl_pair {|s1, s2| err = nil diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 452e7c476..ac739429a 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -744,30 +744,6 @@ def test_verify_hostname_on_connect end end - def test_multibyte_read_write - #German a umlaut - auml = [%w{ C3 A4 }.join('')].pack('H*') - auml.force_encoding(Encoding::UTF_8) - - [10, 1000, 100000].each {|i| - str = nil - num_written = nil - server_proc = Proc.new {|ctx, ssl| - cmp = ssl.read - raw_size = cmp.size - cmp.force_encoding(Encoding::UTF_8) - assert_equal(str, cmp) - assert_equal(num_written, raw_size) - } - start_server(server_proc: server_proc) { |port| - server_connect(port) { |ssl| - str = auml * i - num_written = ssl.write(str) - } - } - } - end - def test_unset_OP_ALL ctx_proc = Proc.new { |ctx| # If OP_DONT_INSERT_EMPTY_FRAGMENTS is not defined, this test is From 315b65090a15261f79b8c251f60f3621957fdb20 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 23 Aug 2017 11:35:24 +0900 Subject: [PATCH 14/15] test/test_ssl_session: rearrange tests Use TLS 1.2 explicitly where needed, since TLS 1.3 will remove session ID based session resumption. --- test/test_ssl_session.rb | 397 +++++++++++++++++++-------------------- 1 file changed, 196 insertions(+), 201 deletions(-) diff --git a/test/test_ssl_session.rb b/test/test_ssl_session.rb index aadbc3b7c..9d0e5a2db 100644 --- a/test/test_ssl_session.rb +++ b/test/test_ssl_session.rb @@ -4,54 +4,12 @@ if defined?(OpenSSL::TestUtils) class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase - def test_session_equals - session = OpenSSL::SSL::Session.new <<-SESSION ------BEGIN SSL SESSION PARAMETERS----- -MIIDFgIBAQICAwEEAgA5BCCY3pW6iTkPoD5SENuztz/gZjhvey6XnHbsxd22k0Ol -dgQw8uaN3hCRnlhoIKPWInCFzrp/tQsDRFs9jDjc9pwpy/oKHmJdQQMQA1g8FYnO -gpdVoQYCBE52ikKiBAICASyjggKOMIICijCCAXKgAwIBAgIBAjANBgkqhkiG9w0B -AQUFADA9MRMwEQYKCZImiZPyLGQBGRYDb3JnMRkwFwYKCZImiZPyLGQBGRYJcnVi -eS1sYW5nMQswCQYDVQQDDAJDQTAeFw0xMTA5MTkwMDE4MTBaFw0xMTA5MTkwMDQ4 -MTBaMEQxEzARBgoJkiaJk/IsZAEZFgNvcmcxGTAXBgoJkiaJk/IsZAEZFglydWJ5 -LWxhbmcxEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAy8LEsNRApz7U/j5DoB4XBgO9Z8Atv5y/OVQRp0ag8Tqo1YewsWijxEWB -7JOATwpBN267U4T1nPZIxxEEO7n/WNa2ws9JWsjah8ssEBFSxZqdXKSLf0N4Hi7/ -GQ/aYoaMCiQ8jA4jegK2FJmXM71uPe+jFN/peeBOpRfyXxRFOYcCAwEAAaMSMBAw -DgYDVR0PAQH/BAQDAgWgMA0GCSqGSIb3DQEBBQUAA4IBAQARC7GP7InX1t7VEXz2 -I8RI57S0/HSJL4fDIYP3zFpitHX1PZeo+7XuzMilvPjjBo/ky9Jzo8TYiY+N+JEz -mY/A/zPA4ZsJ7KYj6/FEdIc/vRlS0CvsbClbNjw1jl/PoB2FLr2b3uuBcZEsyZeP -yq154ijq37Ajf8K5Mi5FgshoP41BPtRPj+VVf61rv1IcEnNWdDCS6DR4XsaNC+zt -G6AqCqkytIXWRuDw6n6vYLF3A/tn2sldLo7/scY0PMDNbo63O/LTxkDHmPhSkD68 -8m9SsMeTR+RCiDEZWFPVcAH/8mDfi+5k8uN3qS+gOU/PPrmHGgl5ykiSFgqs4v61 -tddwpBAEDjcwMzA5NTYzMTU1MzAwpQMCARM= ------END SSL SESSION PARAMETERS----- - SESSION - - start_server(ignore_listener_error: true) { |port| - ctx = OpenSSL::SSL::SSLContext.new - ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT - ctx.session_id_context = self.object_id.to_s - - sock = TCPSocket.new '127.0.0.1', port - begin - ssl = OpenSSL::SSL::SSLSocket.new sock, ctx - ssl.session = session - - assert_equal session, ssl.session - ensure - sock.close - end - } - end - def test_session - Timeout.timeout(5) do - start_server do |port| - sock = TCPSocket.new("127.0.0.1", port) - ctx = OpenSSL::SSL::SSLContext.new - ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) - ssl.sync_close = true - ssl.connect + pend "TLS 1.2 is not supported" unless tls12_supported? + + ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 } + start_server(ctx_proc: ctx_proc) do |port| + server_connect_with_session(port, nil, nil) { |ssl| session = ssl.session assert(session == OpenSSL::SSL::Session.new(session.to_pem)) assert(session == OpenSSL::SSL::Session.new(ssl)) @@ -68,8 +26,7 @@ def test_session pem.gsub!(/-----(BEGIN|END) SSL SESSION PARAMETERS-----/, '').gsub!(/[\r\n]+/m, '') assert_equal(session.to_der, pem.unpack('m*')[0]) assert_not_nil(session.to_text) - ssl.close - end + } end end @@ -152,220 +109,243 @@ def test_session_exts_read assert(OpenSSL::SSL::Session.new(DUMMY_SESSION)) end - def test_client_session - last_session = nil - start_server do |port| - 2.times do - sock = TCPSocket.new("127.0.0.1", port) - ctx = OpenSSL::SSL::SSLContext.new - ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) - ssl.sync_close = true - ssl.session = last_session if last_session - ssl.connect + def test_resumption + non_resumable = nil + start_server { |port| + server_connect_with_session(port, nil, nil) { |ssl| + non_resumable = ssl.session + } + } - session = ssl.session - if last_session - assert(ssl.session_reused?) - assert_equal(session.id, last_session.id) - assert_equal(session.to_pem, last_session.to_pem) - assert_equal(session.to_der, last_session.to_der) - # Older version of OpenSSL may not be consistent. Look up which versions later. - assert_equal(session.to_text, last_session.to_text) - else - assert(!ssl.session_reused?) - end - last_session = session + ctx_proc = proc { |ctx| + ctx.options &= ~OpenSSL::SSL::OP_NO_TICKET + # Disable server-side session cache which is enabled by default + ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF + } + start_server(ctx_proc: ctx_proc) do |port| + sess1 = server_connect_with_session(port, nil, nil) { |ssl| + ssl.puts("abc"); assert_equal "abc\n", ssl.gets + assert_equal false, ssl.session_reused? + ssl.session + } - str = "x" * 100 + "\n" - ssl.puts(str) - assert_equal(str, ssl.gets) + server_connect_with_session(port, nil, non_resumable) { |ssl| + ssl.puts("abc"); assert_equal "abc\n", ssl.gets + assert_equal false, ssl.session_reused? + } - ssl.close - end + server_connect_with_session(port, nil, sess1) { |ssl| + ssl.puts("abc"); assert_equal "abc\n", ssl.gets + assert_equal true, ssl.session_reused? + } end end - def test_server_session - connections = 0 - saved_session = nil + def test_server_session_cache + pend "TLS 1.2 is not supported" unless tls12_supported? - ctx_proc = Proc.new do |ctx, ssl| -# add test for session callbacks here + ctx_proc = Proc.new do |ctx| + ctx.ssl_version = :TLSv1_2 + ctx.options |= OpenSSL::SSL::OP_NO_TICKET end + connections = nil + saved_session = nil server_proc = Proc.new do |ctx, ssl| - session = ssl.session stats = ctx.session_cache_stats case connections when 0 - assert_equal(stats[:cache_num], 1) - assert_equal(stats[:cache_hits], 0) - assert_equal(stats[:cache_misses], 0) - assert(!ssl.session_reused?) + assert_equal false, ssl.session_reused? + assert_equal 1, stats[:cache_num] + assert_equal 0, stats[:cache_hits] + assert_equal 0, stats[:cache_misses] when 1 - assert_equal(stats[:cache_num], 1) - assert_equal(stats[:cache_hits], 1) - assert_equal(stats[:cache_misses], 0) - assert(ssl.session_reused?) - ctx.session_remove(session) - saved_session = session.to_der + assert_equal true, ssl.session_reused? + assert_equal 1, stats[:cache_num] + assert_equal 1, stats[:cache_hits] + assert_equal 0, stats[:cache_misses] + + saved_session = ssl.session + assert_equal true, ctx.session_remove(ssl.session) when 2 - assert_equal(stats[:cache_num], 1) - assert_equal(stats[:cache_hits], 1) - assert_equal(stats[:cache_misses], 1) - assert(!ssl.session_reused?) - ctx.session_add(OpenSSL::SSL::Session.new(saved_session)) + assert_equal false, ssl.session_reused? + assert_equal 1, stats[:cache_num] + assert_equal 1, stats[:cache_hits] + assert_equal 1, stats[:cache_misses] + + assert_equal true, ctx.session_add(saved_session.dup) when 3 - assert_equal(stats[:cache_num], 2) - assert_equal(stats[:cache_hits], 2) - assert_equal(stats[:cache_misses], 1) - assert(ssl.session_reused?) + assert_equal true, ssl.session_reused? + assert_equal 2, stats[:cache_num] + assert_equal 2, stats[:cache_hits] + assert_equal 1, stats[:cache_misses] + ctx.flush_sessions(Time.now + 10000) when 4 - assert_equal(stats[:cache_num], 1) - assert_equal(stats[:cache_hits], 2) - assert_equal(stats[:cache_misses], 2) - assert(!ssl.session_reused?) - ctx.session_add(OpenSSL::SSL::Session.new(saved_session)) + assert_equal false, ssl.session_reused? + assert_equal 1, stats[:cache_num] + assert_equal 2, stats[:cache_hits] + assert_equal 2, stats[:cache_misses] + + assert_equal true, ctx.session_add(saved_session.dup) end - connections += 1 readwrite_loop(ctx, ssl) end - first_session = nil start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |port| + first_session = nil 10.times do |i| - sock = TCPSocket.new("127.0.0.1", port) - ctx = OpenSSL::SSL::SSLContext.new - # disable RFC4507 support - ctx.options = OpenSSL::SSL::OP_NO_TICKET - ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) - ssl.sync_close = true - ssl.session = first_session if first_session - ssl.connect - - session = ssl.session - if first_session - case i - when 1; assert(ssl.session_reused?) - when 2; assert(!ssl.session_reused?) - when 3; assert(ssl.session_reused?) - when 4; assert(!ssl.session_reused?) - when 5..10; assert(ssl.session_reused?) + connections = i + server_connect_with_session(port, nil, first_session) { |ssl| + ssl.puts("abc"); assert_equal "abc\n", ssl.gets + first_session ||= ssl.session + + case connections + when 0; + when 1; assert_equal true, ssl.session_reused? + when 2; assert_equal false, ssl.session_reused? + when 3; assert_equal true, ssl.session_reused? + when 4; assert_equal false, ssl.session_reused? + when 5..9; assert_equal true, ssl.session_reused? end - end - first_session ||= session - - str = "x" * 100 + "\n" - ssl.puts(str) - assert_equal(str, ssl.gets) - - ssl.close + } end end end def test_ctx_client_session_cb - called = {} - ctx = OpenSSL::SSL::SSLContext.new - ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT - - ctx.session_new_cb = lambda { |ary| - sock, sess = ary - called[:new] = [sock, sess] - } + pend "TLS 1.2 is not supported" unless tls12_supported? - ctx.session_remove_cb = lambda { |ary| - ctx, sess = ary - called[:remove] = [ctx, sess] - # any resulting value is OK (ignored) - } + ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 } + start_server(ctx_proc: ctx_proc) do |port| + called = {} + ctx = OpenSSL::SSL::SSLContext.new + ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT + ctx.session_new_cb = lambda { |ary| + sock, sess = ary + called[:new] = [sock, sess] + } + ctx.session_remove_cb = lambda { |ary| + ctx, sess = ary + called[:remove] = [ctx, sess] + # any resulting value is OK (ignored) + } - start_server do |port| - sock = TCPSocket.new("127.0.0.1", port) - begin - ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) - ssl.sync_close = true - ssl.connect + server_connect_with_session(port, ctx, nil) { |ssl| assert_equal(1, ctx.session_cache_stats[:cache_num]) assert_equal(1, ctx.session_cache_stats[:connect_good]) assert_equal([ssl, ssl.session], called[:new]) assert(ctx.session_remove(ssl.session)) assert(!ctx.session_remove(ssl.session)) assert_equal([ctx, ssl.session], called[:remove]) - ssl.close - ensure - sock.close if !sock.closed? - end + } end end def test_ctx_server_session_cb - called = {} + pend "TLS 1.2 is not supported" unless tls12_supported? - ctx_proc = Proc.new { |ctx, ssl| - ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_SERVER - ctx.options = OpenSSL::SSL::OP_NO_TICKET - last_server_session = nil + connections = nil + called = {} + sctx = nil + ctx_proc = Proc.new { |ctx| + sctx = ctx + ctx.ssl_version = :TLSv1_2 + ctx.options |= OpenSSL::SSL::OP_NO_TICKET # get_cb is called whenever a client proposed to resume a session but # the session could not be found in the internal session cache. + last_server_session = nil ctx.session_get_cb = lambda { |ary| - sess, data = ary - if last_server_session - called[:get2] = [sess, data] - last_server_session + _sess, data = ary + called[:get] = data + + if connections == 2 + last_server_session.dup else - called[:get1] = [sess, data] - last_server_session = sess nil end } ctx.session_new_cb = lambda { |ary| - sock, sess = ary - called[:new] = [sock, sess] - # SSL server doesn't cache sessions so get_cb is called next time. - ctx.session_remove(sess) + _sock, sess = ary + called[:new] = sess + last_server_session = sess } ctx.session_remove_cb = lambda { |ary| - ctx, sess = ary - called[:remove] = [ctx, sess] + _ctx, sess = ary + called[:remove] = sess } } - - server_proc = Proc.new { |c, ssl| - ssl.session - c.session_cache_stats - readwrite_loop(c, ssl) - } - start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |port| - last_client_session = nil - 3.times do - sock = TCPSocket.new("127.0.0.1", port) - begin - ssl = OpenSSL::SSL::SSLSocket.new(sock, OpenSSL::SSL::SSLContext.new()) - ssl.sync_close = true - ssl.session = last_client_session if last_client_session - ssl.connect - last_client_session = ssl.session - ssl.close - Timeout.timeout(5) do - Thread.pass until called.key?(:new) - assert(called.delete(:new)) - Thread.pass until called.key?(:remove) - assert(called.delete(:remove)) - end - ensure - sock.close if !sock.closed? + start_server(ctx_proc: ctx_proc) do |port| + connections = 0 + sess0 = server_connect_with_session(port, nil, nil) { |ssl| + ssl.puts("abc"); assert_equal "abc\n", ssl.gets + assert_equal false, ssl.session_reused? + ssl.session + } + assert_nil called[:get] + assert_not_nil called[:new] + assert_equal sess0.id, called[:new].id + assert_nil called[:remove] + called.clear + + # Internal cache hit + connections = 1 + server_connect_with_session(port, nil, sess0.dup) { |ssl| + ssl.puts("abc"); assert_equal "abc\n", ssl.gets + assert_equal true, ssl.session_reused? + ssl.session + } + assert_nil called[:get] + assert_nil called[:new] + assert_nil called[:remove] + called.clear + + sctx.flush_sessions(Time.now + 10000) + assert_not_nil called[:remove] + assert_equal sess0.id, called[:remove].id + called.clear + + # External cache hit + connections = 2 + sess2 = server_connect_with_session(port, nil, sess0.dup) { |ssl| + ssl.puts("abc"); assert_equal "abc\n", ssl.gets + if !ssl.session_reused? && openssl?(1, 1, 0) && !openssl?(1, 1, 0, 7) + # OpenSSL >= 1.1.0, < 1.1.0g + pend "External session cache is not working; " \ + "see https://github.com/openssl/openssl/pull/4014" end - end + assert_equal true, ssl.session_reused? + ssl.session + } + assert_equal sess0.id, sess2.id + assert_equal sess0.id, called[:get] + assert_nil called[:new] + assert_nil called[:remove] + called.clear + + sctx.flush_sessions(Time.now + 10000) + assert_not_nil called[:remove] + assert_equal sess0.id, called[:remove].id + called.clear + + # Cache miss + connections = 3 + sess3 = server_connect_with_session(port, nil, sess0.dup) { |ssl| + ssl.puts("abc"); assert_equal "abc\n", ssl.gets + assert_equal false, ssl.session_reused? + ssl.session + } + assert_not_equal sess0.id, sess3.id + assert_equal sess0.id, called[:get] + assert_not_nil called[:new] + assert_equal sess3.id, called[:new].id + assert_nil called[:remove] end - assert(called[:get1]) - assert(called[:get2]) end def test_dup @@ -373,6 +353,21 @@ def test_dup sess_dup = sess_orig.dup assert_equal(sess_orig.to_der, sess_dup.to_der) end + + private + + def server_connect_with_session(port, ctx = nil, sess = nil) + sock = TCPSocket.new("127.0.0.1", port) + ctx ||= OpenSSL::SSL::SSLContext.new + ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) + ssl.session = sess if sess + ssl.sync_close = true + ssl.connect + yield ssl if block_given? + ensure + ssl&.close + sock&.close + end end end From e3a30506367508790494f9242f7392deeb1b3c9c Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 23 Aug 2017 11:37:57 +0900 Subject: [PATCH 15/15] test/test_pair, test/test_ssl: fix for TLS 1.3 Fix test cases failing with TLS 1.3-enabled OpenSSL master. --- test/test_pair.rb | 102 ++++++++++------------ test/test_ssl.rb | 209 ++++++++++++++++++++-------------------------- 2 files changed, 135 insertions(+), 176 deletions(-) diff --git a/test/test_pair.rb b/test/test_pair.rb index 52a90018c..2fb7726de 100644 --- a/test/test_pair.rb +++ b/test/test_pair.rb @@ -5,55 +5,41 @@ if defined?(OpenSSL::TestUtils) module OpenSSL::SSLPairM - def server - host = "127.0.0.1" - port = 0 - ctx = OpenSSL::SSL::SSLContext.new() - ctx.ciphers = "ADH" - ctx.security_level = 0 - ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") } - tcps = create_tcp_server(host, port) - ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) - return ssls + def setup + svr_dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") + ee_exts = [ + ["keyUsage", "keyEncipherment,digitalSignature", true], + ] + @svr_key = OpenSSL::TestUtils::Fixtures.pkey("rsa1024") + @svr_cert = issue_cert(svr_dn, @svr_key, 1, ee_exts, nil, nil) end - def client(port) + def ssl_pair 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 - ssl.sync_close = true - ssl - end + tcps = create_tcp_server(host, 0) + port = tcps.connect_address.ip_port - def ssl_pair - ssls = server th = Thread.new { + sctx = OpenSSL::SSL::SSLContext.new + sctx.cert = @svr_cert + sctx.key = @svr_key + sctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") } + ssls = OpenSSL::SSL::SSLServer.new(tcps, sctx) ns = ssls.accept ssls.close ns } - port = ssls.to_io.local_address.ip_port - c = client(port) + + tcpc = create_tcp_client(host, port) + c = OpenSSL::SSL::SSLSocket.new(tcpc) + c.connect s = th.value - if block_given? - begin - yield c, s - ensure - c.close unless c.closed? - s.close unless s.closed? - end - else - return c, s - end + + yield c, s ensure - if th&.alive? - th.kill - th.join - end + tcpc&.close + tcps&.close + s&.close end end @@ -83,23 +69,27 @@ def create_tcp_client(host, port) module OpenSSL::TestEOF1M def open_file(content) - s1, s2 = ssl_pair - th = Thread.new { s2 << content; s2.close } - yield s1 - ensure - th.join if th - s1.close + ssl_pair { |s1, s2| + begin + th = Thread.new { s2 << content; s2.close } + yield s1 + ensure + th&.join + end + } end end module OpenSSL::TestEOF2M def open_file(content) - s1, s2 = ssl_pair - th = Thread.new { s1 << content; s1.close } - yield s2 - ensure - th.join if th - s2.close + ssl_pair { |s1, s2| + begin + th = Thread.new { s1 << content; s1.close } + yield s2 + ensure + th&.join + end + } end end @@ -373,8 +363,8 @@ def tcp_pair def test_connect_accept_nonblock_no_exception ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.ciphers = "ADH" - ctx2.security_level = 0 + ctx2.cert = @svr_cert + ctx2.key = @svr_key ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") } sock1, sock2 = tcp_pair @@ -384,8 +374,6 @@ def test_connect_accept_nonblock_no_exception assert_equal :wait_readable, accepted ctx1 = OpenSSL::SSL::SSLContext.new - ctx1.ciphers = "ADH" - ctx1.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) th = Thread.new do rets = [] @@ -423,8 +411,8 @@ def test_connect_accept_nonblock_no_exception def test_connect_accept_nonblock ctx = OpenSSL::SSL::SSLContext.new() - ctx.ciphers = "ADH" - ctx.security_level = 0 + ctx.cert = @svr_cert + ctx.key = @svr_key ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") } sock1, sock2 = tcp_pair @@ -447,8 +435,6 @@ def test_connect_accept_nonblock 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/test_ssl.rb b/test/test_ssl.rb index ac739429a..9c959b273 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -113,14 +113,9 @@ def test_copy_stream def test_client_auth_failure vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT start_server(verify_mode: vflag, ignore_listener_error: true) { |port| - sock = TCPSocket.new("127.0.0.1", port) - ssl = OpenSSL::SSL::SSLSocket.new(sock) - ssl.sync_close = true - begin - assert_handshake_error { ssl.connect } - ensure - ssl.close - end + assert_handshake_error { + server_connect(port) { |ssl| ssl.puts("abc"); ssl.gets } + } } end @@ -158,14 +153,16 @@ def test_client_auth_public_key ctx = OpenSSL::SSL::SSLContext.new ctx.key = @cli_key.public_key ctx.cert = @cli_cert - server_connect(port, ctx) { } + server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets } } ctx = OpenSSL::SSL::SSLContext.new ctx.client_cert_cb = Proc.new{ |ssl| [@cli_cert, @cli_key.public_key] } - assert_handshake_error { server_connect(port, ctx) } + assert_handshake_error { + server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets } + } end end @@ -354,13 +351,17 @@ def test_sslctx_set_params end def test_post_connect_check_with_anon_ciphers + pend "TLS 1.2 is not supported" unless tls12_supported? + ctx_proc = -> ctx { + ctx.ssl_version = :TLSv1_2 ctx.ciphers = "aNULL" ctx.security_level = 0 } start_server(ctx_proc: ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new + ctx.ssl_version = :TLSv1_2 ctx.ciphers = "aNULL" ctx.security_level = 0 server_connect(port, ctx) { |ssl| @@ -618,48 +619,44 @@ def socketpair end def test_tlsext_hostname - ctx3 = OpenSSL::SSL::SSLContext.new - ctx3.ciphers = "ADH" - ctx3.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } - ctx3.security_level = 0 - assert_not_predicate ctx3, :frozen? + fooctx = OpenSSL::SSL::SSLContext.new + fooctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } + fooctx.cert = @cli_cert + fooctx.key = @cli_key - ctx_proc = -> ctx { - ctx.ciphers = "ALL:!aNULL" + ctx_proc = proc { |ctx| ctx.servername_cb = proc { |ssl, servername| case servername when "foo.example.com" - ctx3 + fooctx when "bar.example.com" nil else - raise "unknown hostname" + raise "unreachable" end } } start_server(ctx_proc: ctx_proc) do |port| - ctx = OpenSSL::SSL::SSLContext.new - ctx.ciphers = "ALL" - ctx.security_level = 0 - sock = TCPSocket.new("127.0.0.1", port) begin - ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) + ssl = OpenSSL::SSL::SSLSocket.new(sock) ssl.hostname = "foo.example.com" ssl.connect - assert_match (/^ADH-/), ssl.cipher[0], "the context returned by servername_cb is used" - assert_predicate ctx3, :frozen? + assert_equal @cli_cert.serial, ssl.peer_cert.serial + assert_predicate fooctx, :frozen? ensure + ssl&.close sock.close end sock = TCPSocket.new("127.0.0.1", port) begin - ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) + ssl = OpenSSL::SSL::SSLSocket.new(sock) ssl.hostname = "bar.example.com" ssl.connect - assert_not_match (/^A(EC)?DH-/), ssl.cipher[0], "the original context is used" + assert_equal @svr_cert.serial, ssl.peer_cert.serial ensure + ssl&.close sock.close end end @@ -669,9 +666,9 @@ def test_servername_cb_raises_an_exception_on_unknown_objects hostname = 'example.org' ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.ciphers = "aNULL" + ctx2.cert = @svr_cert + ctx2.key = @svr_key ctx2.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } - ctx2.security_level = 0 ctx2.servername_cb = lambda { |args| Object.new } sock1, sock2 = socketpair @@ -679,8 +676,6 @@ def test_servername_cb_raises_an_exception_on_unknown_objects s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) ctx1 = OpenSSL::SSL::SSLContext.new - ctx1.ciphers = "aNULL" - ctx1.security_level = 0 s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) s1.hostname = hostname @@ -886,14 +881,12 @@ def test_alpn_protocol_selection_cancel sock1, sock2 = socketpair ctx1 = OpenSSL::SSL::SSLContext.new - ctx1.ciphers = "aNULL" - ctx1.security_level = 0 + ctx1.cert = @svr_cert + ctx1.key = @svr_key ctx1.alpn_select_cb = -> (protocols) { nil } ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.ciphers = "aNULL" - ctx2.security_level = 0 ctx2.alpn_protocols = ["http/1.1"] ssl2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) @@ -912,14 +905,14 @@ def test_alpn_protocol_selection_cancel end end -if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 && - OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) - # NPN may be disabled by OpenSSL configure option - def test_npn_protocol_selection_ary + pend "TLS 1.2 is not supported" unless tls12_supported? + pend "NPN is not supported" unless \ + OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) + advertised = ["http/1.1", "spdy/2"] - ctx_proc = Proc.new { |ctx| ctx.npn_protocols = advertised } - start_server_version(:SSLv23, ctx_proc) { |port| + ctx_proc = proc { |ctx| ctx.npn_protocols = advertised } + start_server_version(:TLSv1_2, ctx_proc) { |port| selector = lambda { |which| ctx = OpenSSL::SSL::SSLContext.new ctx.npn_select_cb = -> (protocols) { protocols.send(which) } @@ -933,13 +926,17 @@ def test_npn_protocol_selection_ary end def test_npn_protocol_selection_enum + pend "TLS 1.2 is not supported" unless tls12_supported? + pend "NPN is not supported" unless \ + OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) + advertised = Object.new def advertised.each yield "http/1.1" yield "spdy/2" end ctx_proc = Proc.new { |ctx| ctx.npn_protocols = advertised } - start_server_version(:SSLv23, ctx_proc) { |port| + start_server_version(:TLSv1_2, ctx_proc) { |port| selector = lambda { |selected, which| ctx = OpenSSL::SSL::SSLContext.new ctx.npn_select_cb = -> (protocols) { protocols.to_a.send(which) } @@ -953,8 +950,12 @@ def advertised.each end def test_npn_protocol_selection_cancel + pend "TLS 1.2 is not supported" unless tls12_supported? + pend "NPN is not supported" unless \ + OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) + ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] } - start_server_version(:SSLv23, ctx_proc) { |port| + start_server_version(:TLSv1_2, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.npn_select_cb = -> (protocols) { raise RuntimeError.new } assert_raise(RuntimeError) { server_connect(port, ctx) } @@ -962,8 +963,12 @@ def test_npn_protocol_selection_cancel end def test_npn_advertised_protocol_too_long + pend "TLS 1.2 is not supported" unless tls12_supported? + pend "NPN is not supported" unless \ + OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) + ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["a" * 256] } - start_server_version(:SSLv23, ctx_proc) { |port| + start_server_version(:TLSv1_2, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.npn_select_cb = -> (protocols) { protocols.first } assert_handshake_error { server_connect(port, ctx) } @@ -971,18 +976,23 @@ def test_npn_advertised_protocol_too_long end def test_npn_selected_protocol_too_long + pend "TLS 1.2 is not supported" unless tls12_supported? + pend "NPN is not supported" unless \ + OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) + ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] } - start_server_version(:SSLv23, ctx_proc) { |port| + start_server_version(:TLSv1_2, ctx_proc) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.npn_select_cb = -> (protocols) { "a" * 256 } assert_handshake_error { server_connect(port, ctx) } } end -end - def test_close_after_socket_close - start_server { |port| + server_proc = proc { |ctx, ssl| + # Do nothing + } + start_server(server_proc: server_proc) { |port| sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) ssl.sync_close = true @@ -1003,30 +1013,6 @@ def test_sync_close_without_connect } end - def test_close_and_socket_close_while_connecting - # test it doesn't cause a segmentation fault - ctx = OpenSSL::SSL::SSLContext.new - ctx.ciphers = "aNULL" - ctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") } - ctx.security_level = 0 - - sock1, sock2 = socketpair - ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx) - ssl2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx) - - t = Thread.new { ssl1.connect } - ssl2.accept - - ssl1.close - sock1.close - t.value rescue nil - ensure - ssl1.close if ssl1 - ssl2.close if ssl2 - sock1.close if sock1 - sock2.close if sock2 - end - def test_get_ephemeral_key # OpenSSL >= 1.0.2 unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key) @@ -1081,8 +1067,11 @@ def test_get_ephemeral_key end def test_dh_callback + pend "TLS 1.2 is not supported" unless tls12_supported? + called = false ctx_proc = -> ctx { + ctx.ssl_version = :TLSv1_2 ctx.ciphers = "DH:!NULL" ctx.tmp_dh_callback = ->(*args) { called = true @@ -1100,7 +1089,10 @@ def test_dh_callback end def test_connect_works_when_setting_dh_callback_to_nil + pend "TLS 1.2 is not supported" unless tls12_supported? + ctx_proc = -> ctx { + ctx.ssl_version = :TLSv1_2 ctx.ciphers = "DH:!NULL" # use DH ctx.tmp_dh_callback = nil } @@ -1113,58 +1105,34 @@ def test_connect_works_when_setting_dh_callback_to_nil end end - def test_ecdh_callback - return unless OpenSSL::SSL::SSLContext.instance_methods.include?(:tmp_ecdh_callback) + def test_tmp_ecdh_callback + pend "EC is disabled" unless defined?(OpenSSL::PKey::EC) + pend "tmp_ecdh_callback is not supported" unless \ + OpenSSL::SSL::SSLContext.method_defined?(:tmp_ecdh_callback) + EnvUtil.suppress_warning do # tmp_ecdh_callback is deprecated (2016-05) - begin - called = false - ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.ciphers = "ECDH" - # OpenSSL 1.1.0 doesn't have tmp_ecdh_callback so this shouldn't be required - ctx2.security_level = 0 - ctx2.tmp_ecdh_callback = ->(*args) { + called = false + ctx_proc = -> ctx { + ctx.ciphers = "DEFAULT:!kRSA:!kEDH" + ctx.tmp_ecdh_callback = -> (*args) { called = true OpenSSL::PKey::EC.new "prime256v1" } - - sock1, sock2 = socketpair - - s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) - ctx1 = OpenSSL::SSL::SSLContext.new - ctx1.ciphers = "ECDH" - ctx1.security_level = 0 - - s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) - th = Thread.new do - s1.connect - end - - s2.accept - assert called, 'ecdh callback should be called' - rescue OpenSSL::SSL::SSLError => e - if e.message =~ /no cipher match/ - pend "ECDH cipher not supported." - else - raise e - end - ensure - th.join if th - s1.close if s1 - s2.close if s2 - sock1.close if sock1 - sock2.close if sock2 + } + start_server(ctx_proc: ctx_proc) do |port| + server_connect(port) { |s| + assert called, "tmp_ecdh_callback should be called" + } end end end def test_ecdh_curves + pend "EC is disabled" unless defined?(OpenSSL::PKey::EC) + ctx_proc = -> ctx { - begin - ctx.ciphers = "ECDH:!NULL" - rescue OpenSSL::SSL::SSLError - pend "ECDH is not enabled in this OpenSSL" if $!.message =~ /no cipher match/ - raise - end + # Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3 + ctx.ciphers = "DEFAULT:!kRSA:!kEDH" ctx.ecdh_curves = "P-384:P-521" } start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| @@ -1172,9 +1140,14 @@ def test_ecdh_curves ctx.ecdh_curves = "P-256:P-384" # disable P-521 for OpenSSL >= 1.0.2 server_connect(port, ctx) { |ssl| - assert ssl.cipher[0].start_with?("ECDH"), "ECDH should be used" - if ssl.respond_to?(:tmp_key) + cs = ssl.cipher[0] + if /\ATLS/ =~ cs # Is TLS 1.3 is used? assert_equal "secp384r1", ssl.tmp_key.group.curve_name + else + assert_match (/\AECDH/), cs + if ssl.respond_to?(:tmp_key) + assert_equal "secp384r1", ssl.tmp_key.group.curve_name + end end } @@ -1253,7 +1226,7 @@ def start_server_version(version, ctx_proc = nil, ) end - def server_connect(port, ctx=nil) + def server_connect(port, ctx = nil) sock = TCPSocket.new("127.0.0.1", port) ssl = ctx ? OpenSSL::SSL::SSLSocket.new(sock, ctx) : OpenSSL::SSL::SSLSocket.new(sock) ssl.sync_close = true