diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2016-08-09 14:09:16 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2017-11-22 09:46:42 +0900 |
commit | 6ce04c96c8ac823107b2d1560f5cedb9bc61cdb0 (patch) | |
tree | 210e1f51f51acdc3b95dbb49b573bc979b382493 /test | |
parent | 125ab881c6ded7b9d9a122471ce128e29eee16b4 (diff) | |
download | ruby-openssl-6ce04c96c8ac823107b2d1560f5cedb9bc61cdb0.tar.gz |
ssl: add SSLContext#add_certificate
Add a new method to add a certificate, a corresponding private key, and
extra CA certificates at once.
This has two advantages over the existing {cert,key,extra_cert_chain}
attributes:
1. We can notice the problem with the certificate and/or the private
key. Since the existing attributes are simple instance variables,
they aren't set to the SSL_CTX until #setup which usually happens
on the first connection.
2. For the same reason, existing attributes allowed only one
certificate for a context, even though OpenSSL itself is capable of
handling multiple certificates and selecting the most appropriate
one according to the cipher suite selected.
The documentation for the existing attributes are updated to recommend
using #add_certificate.
Diffstat (limited to 'test')
-rw-r--r-- | test/test_ssl.rb | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/test/test_ssl.rb b/test/test_ssl.rb index ab6382d7..1b665cc9 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -54,6 +54,87 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase } end + def test_add_certificate + ctx_proc = -> ctx { + # Unset values set by start_server + ctx.cert = ctx.key = ctx.extra_chain_cert = nil + ctx.add_certificate(@svr_cert, @svr_key, [@ca_cert]) # RSA + } + start_server(ctx_proc: ctx_proc) do |port| + server_connect(port) { |ssl| + assert_equal @svr_cert.subject, ssl.peer_cert.subject + assert_equal [@svr_cert.subject, @ca_cert.subject], + ssl.peer_cert_chain.map(&:subject) + } + end + end + + def test_add_certificate_multiple_certs + pend "EC is not supported" unless defined?(OpenSSL::PKey::EC) + pend "TLS 1.2 is not supported" unless tls12_supported? + + # SSL_CTX_set0_chain() is needed for setting multiple certificate chains + add0_chain_supported = openssl?(1, 0, 2) + + if add0_chain_supported + ca2_key = Fixtures.pkey("rsa1024") + ca2_exts = [ + ["basicConstraints", "CA:TRUE", true], + ["keyUsage", "cRLSign, keyCertSign", true], + ] + ca2_dn = OpenSSL::X509::Name.parse_rfc2253("CN=CA2") + ca2_cert = issue_cert(ca2_dn, ca2_key, 123, ca2_exts, nil, nil) + else + # Use the same CA as @svr_cert + ca2_key = @ca_key; ca2_cert = @ca_cert + end + + ecdsa_key = Fixtures.pkey("p256") + exts = [ + ["keyUsage", "digitalSignature", false], + ] + ecdsa_dn = OpenSSL::X509::Name.parse_rfc2253("CN=localhost2") + ecdsa_cert = issue_cert(ecdsa_dn, ecdsa_key, 456, exts, ca2_cert, ca2_key) + + if !add0_chain_supported + # Testing the warning emitted when 'extra' chain is replaced + tctx = OpenSSL::SSL::SSLContext.new + tctx.add_certificate(@svr_cert, @svr_key, [@ca_cert]) + assert_warning(/set0_chain/) { + tctx.add_certificate(ecdsa_cert, ecdsa_key, [ca2_cert]) + } + end + + ctx_proc = -> ctx { + # Unset values set by start_server + ctx.cert = ctx.key = ctx.extra_chain_cert = nil + ctx.ecdh_curves = "P-256" unless openssl?(1, 0, 2) + ctx.add_certificate(@svr_cert, @svr_key, [@ca_cert]) # RSA + EnvUtil.suppress_warning do # !add0_chain_supported + ctx.add_certificate(ecdsa_cert, ecdsa_key, [ca2_cert]) + end + } + start_server(ctx_proc: ctx_proc) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.max_version = :TLS1_2 # TODO: We need this to force certificate type + ctx.ciphers = "aECDSA" + server_connect(port, ctx) { |ssl| + assert_equal ecdsa_cert.subject, ssl.peer_cert.subject + assert_equal [ecdsa_cert.subject, ca2_cert.subject], + ssl.peer_cert_chain.map(&:subject) + } + + ctx = OpenSSL::SSL::SSLContext.new + ctx.max_version = :TLS1_2 + ctx.ciphers = "aRSA" + server_connect(port, ctx) { |ssl| + assert_equal @svr_cert.subject, ssl.peer_cert.subject + assert_equal [@svr_cert.subject, @ca_cert.subject], + ssl.peer_cert_chain.map(&:subject) + } + end + end + def test_sysread_and_syswrite start_server { |port| server_connect(port) { |ssl| |