[前][次][番号順一覧][スレッド一覧]

ruby-changes:65567

From: Kazuki <ko1@a...>
Date: Tue, 16 Mar 2021 20:39:14 +0900 (JST)
Subject: [ruby-changes:65567] d4ad1e71ca (master): [ruby/openssl] test/openssl/test_x509stoRe: break up test_verify

https://git.ruby-lang.org/ruby.git/commit/?id=d4ad1e71ca

From d4ad1e71ca6c1b58e5ea1b518e406a0251ca812f Mon Sep 17 00:00:00 2001
From: Kazuki Yamaguchi <k@r...>
Date: Tue, 11 Aug 2020 18:52:37 +0900
Subject: [ruby/openssl] test/openssl/test_x509store: break up test_verify

The test case is huge and too complex. Break it up into separate test
cases for better documentation.

https://github.com/ruby/openssl/commit/61012df03b
---
 test/openssl/test_x509store.rb | 339 +++++++++++++++++++++++++++--------------
 1 file changed, 227 insertions(+), 112 deletions(-)

diff --git a/test/openssl/test_x509store.rb b/test/openssl/test_x509store.rb
index 4b02e66..57a3e79 100644
--- a/test/openssl/test_x509store.rb
+++ b/test/openssl/test_x509store.rb
@@ -65,159 +65,274 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase https://github.com/ruby/ruby/blob/trunk/test/openssl/test_x509store.rb#L65
     tmpfile and tmpfile.close!
   end
 
-  def test_verify
-    # OpenSSL uses time(2) while Time.now uses clock_gettime(CLOCK_REALTIME),
-    # and there may be difference.
-    now = Time.now - 3
+  def test_verify_simple
     ca_exts = [
-      ["basicConstraints","CA:TRUE",true],
-      ["keyUsage","cRLSign,keyCertSign",true],
+      ["basicConstraints", "CA:TRUE", true],
+      ["keyUsage", "cRLSign,keyCertSign", true],
     ]
+    ca1 = OpenSSL::X509::Name.parse_rfc2253("CN=Root CA")
+    ca1_key = Fixtures.pkey("rsa-1")
+    ca1_cert = issue_cert(ca1, ca1_key, 1, ca_exts, nil, nil)
+    ca2 = OpenSSL::X509::Name.parse_rfc2253("CN=Intermediate CA")
+    ca2_key = Fixtures.pkey("rsa-2")
+    ca2_cert = issue_cert(ca2, ca2_key, 2, ca_exts, ca1_cert, ca1_key)
+
     ee_exts = [
-      ["keyUsage","keyEncipherment,digitalSignature",true],
+      ["keyUsage", "keyEncipherment,digitalSignature", true],
     ]
-    ca1_cert = issue_cert(@ca1, @rsa2048, 1, ca_exts, nil, nil)
-    ca2_cert = issue_cert(@ca2, @rsa1024, 2, ca_exts, ca1_cert, @rsa2048,
-                          not_after: now+1800)
-    ee1_cert = issue_cert(@ee1, @dsa256, 10, ee_exts, ca2_cert, @rsa1024)
-    ee2_cert = issue_cert(@ee2, @dsa512, 20, ee_exts, ca2_cert, @rsa1024)
-    ee3_cert = issue_cert(@ee2, @dsa512, 30,  ee_exts, ca2_cert, @rsa1024,
-                          not_before: now-100, not_after: now-50)
-    ee4_cert = issue_cert(@ee2, @dsa512, 40, ee_exts, ca2_cert, @rsa1024,
-                          not_before: now+1000, not_after: now+2000,)
-
-    revoke_info = []
-    crl1   = issue_crl(revoke_info, 1, now, now+1800, [],
-                       ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
-    revoke_info = [ [2, now, 1], ]
-    crl1_2 = issue_crl(revoke_info, 2, now, now+1800, [],
-                       ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
-    revoke_info = [ [20, now, 1], ]
-    crl2   = issue_crl(revoke_info, 1, now, now+1800, [],
-                       ca2_cert, @rsa1024, OpenSSL::Digest.new('SHA1'))
-    revoke_info = []
-    crl2_2 = issue_crl(revoke_info, 2, now-100, now-1, [],
-                       ca2_cert, @rsa1024, OpenSSL::Digest.new('SHA1'))
-
-    assert_equal(true, ca1_cert.verify(ca1_cert.public_key))   # self signed
-    assert_equal(true, ca2_cert.verify(ca1_cert.public_key))   # issued by ca1
-    assert_equal(true, ee1_cert.verify(ca2_cert.public_key))   # issued by ca2
-    assert_equal(true, ee2_cert.verify(ca2_cert.public_key))   # issued by ca2
-    assert_equal(true, ee3_cert.verify(ca2_cert.public_key))   # issued by ca2
-    assert_equal(true, crl1.verify(ca1_cert.public_key))       # issued by ca1
-    assert_equal(true, crl1_2.verify(ca1_cert.public_key))     # issued by ca1
-    assert_equal(true, crl2.verify(ca2_cert.public_key))       # issued by ca2
-    assert_equal(true, crl2_2.verify(ca2_cert.public_key))     # issued by ca2
+    ee1 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 1")
+    ee1_key = Fixtures.pkey("rsa-3")
+    ee1_cert = issue_cert(ee1, ee1_key, 10, ee_exts, ca2_cert, ca2_key)
 
+    # Nothing trusted
     store = OpenSSL::X509::Store.new
-    assert_equal(false, store.verify(ca1_cert))
-    assert_not_equal(OpenSSL::X509::V_OK, store.error)
+    assert_equal(false, store.verify(ee1_cert, [ca2_cert, ca1_cert]))
+    assert_equal(OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN, store.error)
+    assert_match(/self.signed/i, store.error_string)
 
-    assert_equal(false, store.verify(ca2_cert))
-    assert_not_equal(OpenSSL::X509::V_OK, store.error)
+    # CA1 trusted, CA2 missing
+    store = OpenSSL::X509::Store.new
+    store.add_cert(ca1_cert)
+    assert_equal(false, store.verify(ee1_cert))
+    assert_equal(OpenSSL::X509::V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, store.error)
 
+    # CA1 trusted, CA2 supplied
+    store = OpenSSL::X509::Store.new
     store.add_cert(ca1_cert)
-    assert_equal(true, store.verify(ca2_cert))
+    assert_equal(true, store.verify(ee1_cert, [ca2_cert]))
+    assert_match(/ok/i, store.error_string)
     assert_equal(OpenSSL::X509::V_OK, store.error)
-    assert_equal("ok", store.error_string)
-    chain = store.chain
-    assert_equal(2, chain.size)
-    assert_equal(@ca2.to_der, chain[0].subject.to_der)
-    assert_equal(@ca1.to_der, chain[1].subject.to_der)
+    assert_equal([ee1_cert, ca2_cert, ca1_cert], store.chain)
+  end
 
-    store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
-    assert_equal(false, store.verify(ca2_cert))
-    assert_not_equal(OpenSSL::X509::V_OK, store.error)
+  def test_verify_callback
+    ca_exts = [
+      ["basicConstraints", "CA:TRUE", true],
+      ["keyUsage", "cRLSign,keyCertSign", true],
+    ]
+    ca1 = OpenSSL::X509::Name.parse_rfc2253("CN=Root CA")
+    ca1_key = Fixtures.pkey("rsa-1")
+    ca1_cert = issue_cert(ca1, ca1_key, 1, ca_exts, nil, nil)
+    ca2 = OpenSSL::X509::Name.parse_rfc2253("CN=Intermediate CA")
+    ca2_key = Fixtures.pkey("rsa-2")
+    ca2_cert = issue_cert(ca2, ca2_key, 2, ca_exts, ca1_cert, ca1_key)
 
-    store.purpose = OpenSSL::X509::PURPOSE_CRL_SIGN
-    assert_equal(true, store.verify(ca2_cert))
-    assert_equal(OpenSSL::X509::V_OK, store.error)
+    ee_exts = [
+      ["keyUsage", "keyEncipherment,digitalSignature", true],
+    ]
+    ee1 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 1")
+    ee1_key = Fixtures.pkey("rsa-3")
+    ee1_cert = issue_cert(ee1, ee1_key, 10, ee_exts, ca2_cert, ca2_key)
 
-    store.add_cert(ca2_cert)
-    store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
-    assert_equal(true, store.verify(ee1_cert))
-    assert_equal(true, store.verify(ee2_cert))
-    assert_equal(OpenSSL::X509::V_OK, store.error)
-    assert_equal("ok", store.error_string)
-    chain = store.chain
-    assert_equal(3, chain.size)
-    assert_equal(@ee2.to_der, chain[0].subject.to_der)
-    assert_equal(@ca2.to_der, chain[1].subject.to_der)
-    assert_equal(@ca1.to_der, chain[2].subject.to_der)
-    assert_equal(false, store.verify(ee3_cert), "now=#{now.inspect} Time.now=#{Time.now.inspect} store=#{store.inspect} ee3_cert=#{ee3_cert.inspect}")
-    assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
-    assert_match(/expire/i, store.error_string)
-    assert_equal(false, store.verify(ee4_cert))
-    assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error)
-    assert_match(/not yet valid/i, store.error_string)
+    # verify_callback on X509::Store is called with proper arguments
+    cb_calls = []
+    store = OpenSSL::X509::Store.new
+    store.verify_callback = -> (preverify_ok, sctx) {
+      cb_calls << [preverify_ok, sctx.current_cert]
+      preverify_ok
+    }
+    store.add_cert(ca1_cert)
+    assert_equal(true, store.verify(ee1_cert, [ca2_cert]))
+    assert_equal(3, cb_calls.size)
+    assert_equal([true, ca1_cert], cb_calls[0])
+    assert_equal([true, ca2_cert], cb_calls[1])
+    assert_equal([true, ee1_cert], cb_calls[2])
 
+    # verify_callback can change verification result
+    store = OpenSSL::X509::Store.new
+    store.verify_callback = -> (preverify_ok, sctx) {
+      next preverify_ok if sctx.current_cert != ee1_cert
+      sctx.error = OpenSSL::X509::V_ERR_APPLICATION_VERIFICATION
+      false
+    }
+    store.add_cert(ca1_cert)
+    assert_equal(false, store.verify(ee1_cert, [ca2_cert]))
+    assert_equal(OpenSSL::X509::V_ERR_APPLICATION_VERIFICATION, store.error)
+
+    # Exception raised by verify_callback is currently suppressed, and is
+    # treated as a non-truthy return (with warning)
+    store = OpenSSL::X509::Store.new
+    store.verify_callback = -> (preverify_ok, sctx) {
+      raise "suppressed"
+    }
+    store.add_cert(ca1_cert)
+    assert_warning(/exception in verify_callback/) {
+      assert_equal(false, store.verify(ee1_cert, [ca2_cert]))
+    }
+
+    # The block given to X509::Store#verify replaces it
+    called = nil
+    store = OpenSSL::X509::Store.new
+    store.verify_callback = -> (preverify_ok, sctx) { called = :store; preverify_ok }
+    store.add_cert(ca1_cert)
+    blk = proc { |preverify_ok, sctx| called = :block; preverify_ok }
+    assert_equal(true, store.verify(ee1_cert, [ca2_cert], &blk))
+    assert_equal(:block, called)
+  end
+
+  def test_verify_purpose
+    ca_exts = [
+      ["basicConstraints", "CA:TRUE", true],
+      ["keyUsage", "cRLSign,keyCertSign", true],
+    ]
+    ca1 = OpenSSL::X509::Name.parse_rfc2253("CN=Root CA")
+    ca1_key = Fixtures.pkey("rsa-1")
+    ca1_cert = issue_cert(ca1, ca1_key, 1, ca_exts, nil, nil)
+
+    ee_exts = [
+      ["keyUsage", "keyEncipherment,digitalSignature", true],
+    ]
+    ee1 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 1")
+    ee1_key = Fixtures.pkey("rsa-3")
+    ee1_cert = issue_cert(ee1, ee1_key, 10, ee_exts, ca1_cert, ca1_key)
+
+    # Purpose not set
     store = OpenSSL::X509::Store.new
     store.add_cert(ca1_cert)
-    store.add_cert(ca2_cert)
-    store.time = now + 1500
     assert_equal(true, store.verify(ca1_cert))
-    assert_equal(true, store.verify(ca2_cert))
-    assert_equal(true, store.verify(ee4_cert))
-    store.time = now + 1900
+    assert_equal(true, store.verify(ee1_cert))
+
+     (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]