1require_relative "utils" 2 3if defined?(OpenSSL) 4 5class OpenSSL::TestX509Store < Test::Unit::TestCase 6 def setup 7 @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 8 @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 9 @dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256 10 @dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512 11 @ca1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA1") 12 @ca2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA2") 13 @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1") 14 @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2") 15 end 16 17 def teardown 18 end 19 20 def test_nosegv_on_cleanup 21 cert = OpenSSL::X509::Certificate.new 22 store = OpenSSL::X509::Store.new 23 ctx = OpenSSL::X509::StoreContext.new(store, cert, []) 24 ctx.cleanup 25 ctx.verify 26 end 27 28 def issue_cert(*args) 29 OpenSSL::TestUtils.issue_cert(*args) 30 end 31 32 def issue_crl(*args) 33 OpenSSL::TestUtils.issue_crl(*args) 34 end 35 36 def test_verify 37 now = Time.at(Time.now.to_i) 38 ca_exts = [ 39 ["basicConstraints","CA:TRUE",true], 40 ["keyUsage","cRLSign,keyCertSign",true], 41 ] 42 ee_exts = [ 43 ["keyUsage","keyEncipherment,digitalSignature",true], 44 ] 45 ca1_cert = issue_cert(@ca1, @rsa2048, 1, now, now+3600, ca_exts, 46 nil, nil, OpenSSL::Digest::SHA1.new) 47 ca2_cert = issue_cert(@ca2, @rsa1024, 2, now, now+1800, ca_exts, 48 ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) 49 ee1_cert = issue_cert(@ee1, @dsa256, 10, now, now+1800, ee_exts, 50 ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) 51 ee2_cert = issue_cert(@ee2, @dsa512, 20, now, now+1800, ee_exts, 52 ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) 53 ee3_cert = issue_cert(@ee2, @dsa512, 30, now-100, now-1, ee_exts, 54 ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) 55 ee4_cert = issue_cert(@ee2, @dsa512, 40, now+1000, now+2000, ee_exts, 56 ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) 57 58 revoke_info = [] 59 crl1 = issue_crl(revoke_info, 1, now, now+1800, [], 60 ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) 61 revoke_info = [ [2, now, 1], ] 62 crl1_2 = issue_crl(revoke_info, 2, now, now+1800, [], 63 ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) 64 revoke_info = [ [20, now, 1], ] 65 crl2 = issue_crl(revoke_info, 1, now, now+1800, [], 66 ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) 67 revoke_info = [] 68 crl2_2 = issue_crl(revoke_info, 2, now-100, now-1, [], 69 ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) 70 71 assert_equal(true, ca1_cert.verify(ca1_cert.public_key)) # self signed 72 assert_equal(true, ca2_cert.verify(ca1_cert.public_key)) # issued by ca1 73 assert_equal(true, ee1_cert.verify(ca2_cert.public_key)) # issued by ca2 74 assert_equal(true, ee2_cert.verify(ca2_cert.public_key)) # issued by ca2 75 assert_equal(true, ee3_cert.verify(ca2_cert.public_key)) # issued by ca2 76 assert_equal(true, crl1.verify(ca1_cert.public_key)) # issued by ca1 77 assert_equal(true, crl1_2.verify(ca1_cert.public_key)) # issued by ca1 78 assert_equal(true, crl2.verify(ca2_cert.public_key)) # issued by ca2 79 assert_equal(true, crl2_2.verify(ca2_cert.public_key)) # issued by ca2 80 81 store = OpenSSL::X509::Store.new 82 assert_equal(false, store.verify(ca1_cert)) 83 assert_not_equal(OpenSSL::X509::V_OK, store.error) 84 85 assert_equal(false, store.verify(ca2_cert)) 86 assert_not_equal(OpenSSL::X509::V_OK, store.error) 87 88 store.add_cert(ca1_cert) 89 assert_equal(true, store.verify(ca2_cert)) 90 assert_equal(OpenSSL::X509::V_OK, store.error) 91 assert_equal("ok", store.error_string) 92 chain = store.chain 93 assert_equal(2, chain.size) 94 assert_equal(@ca2.to_der, chain[0].subject.to_der) 95 assert_equal(@ca1.to_der, chain[1].subject.to_der) 96 97 store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT 98 assert_equal(false, store.verify(ca2_cert)) 99 assert_not_equal(OpenSSL::X509::V_OK, store.error) 100 101 store.purpose = OpenSSL::X509::PURPOSE_CRL_SIGN 102 assert_equal(true, store.verify(ca2_cert)) 103 assert_equal(OpenSSL::X509::V_OK, store.error) 104 105 store.add_cert(ca2_cert) 106 store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT 107 assert_equal(true, store.verify(ee1_cert)) 108 assert_equal(true, store.verify(ee2_cert)) 109 assert_equal(OpenSSL::X509::V_OK, store.error) 110 assert_equal("ok", store.error_string) 111 chain = store.chain 112 assert_equal(3, chain.size) 113 assert_equal(@ee2.to_der, chain[0].subject.to_der) 114 assert_equal(@ca2.to_der, chain[1].subject.to_der) 115 assert_equal(@ca1.to_der, chain[2].subject.to_der) 116 assert_equal(false, store.verify(ee3_cert)) 117 assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) 118 assert_match(/expire/i, store.error_string) 119 assert_equal(false, store.verify(ee4_cert)) 120 assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error) 121 assert_match(/not yet valid/i, store.error_string) 122 123 store = OpenSSL::X509::Store.new 124 store.add_cert(ca1_cert) 125 store.add_cert(ca2_cert) 126 store.time = now + 1500 127 assert_equal(true, store.verify(ca1_cert)) 128 assert_equal(true, store.verify(ca2_cert)) 129 assert_equal(true, store.verify(ee4_cert)) 130 store.time = now + 1900 131 assert_equal(true, store.verify(ca1_cert)) 132 assert_equal(false, store.verify(ca2_cert)) 133 assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) 134 assert_equal(false, store.verify(ee4_cert)) 135 assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) 136 store.time = now + 4000 137 assert_equal(false, store.verify(ee1_cert)) 138 assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) 139 assert_equal(false, store.verify(ee4_cert)) 140 assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) 141 142 # the underlying X509 struct caches the result of the last 143 # verification for signature and not-before. so the following code 144 # rebuilds new objects to avoid site effect. 145 store.time = Time.now - 4000 146 assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ca2_cert))) 147 assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error) 148 assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ee1_cert))) 149 assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error) 150 151 return unless defined?(OpenSSL::X509::V_FLAG_CRL_CHECK) 152 153 store = OpenSSL::X509::Store.new 154 store.purpose = OpenSSL::X509::PURPOSE_ANY 155 store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK 156 store.add_cert(ca1_cert) 157 store.add_crl(crl1) # revoke no cert 158 store.add_crl(crl2) # revoke ee2_cert 159 assert_equal(true, store.verify(ca1_cert)) 160 assert_equal(true, store.verify(ca2_cert)) 161 assert_equal(true, store.verify(ee1_cert, [ca2_cert])) 162 assert_equal(false, store.verify(ee2_cert, [ca2_cert])) 163 164 store = OpenSSL::X509::Store.new 165 store.purpose = OpenSSL::X509::PURPOSE_ANY 166 store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK 167 store.add_cert(ca1_cert) 168 store.add_crl(crl1_2) # revoke ca2_cert 169 store.add_crl(crl2) # revoke ee2_cert 170 assert_equal(true, store.verify(ca1_cert)) 171 assert_equal(false, store.verify(ca2_cert)) 172 assert_equal(true, store.verify(ee1_cert, [ca2_cert]), 173 "This test is expected to be success with OpenSSL 0.9.7c or later.") 174 assert_equal(false, store.verify(ee2_cert, [ca2_cert])) 175 176 store.flags = 177 OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL 178 assert_equal(true, store.verify(ca1_cert)) 179 assert_equal(false, store.verify(ca2_cert)) 180 assert_equal(false, store.verify(ee1_cert, [ca2_cert])) 181 assert_equal(false, store.verify(ee2_cert, [ca2_cert])) 182 183 store = OpenSSL::X509::Store.new 184 store.purpose = OpenSSL::X509::PURPOSE_ANY 185 store.flags = 186 OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL 187 store.add_cert(ca1_cert) 188 store.add_cert(ca2_cert) 189 store.add_crl(crl1) 190 store.add_crl(crl2_2) # issued by ca2 but expired. 191 assert_equal(true, store.verify(ca1_cert)) 192 assert_equal(true, store.verify(ca2_cert)) 193 assert_equal(false, store.verify(ee1_cert)) 194 assert_equal(OpenSSL::X509::V_ERR_CRL_HAS_EXPIRED, store.error) 195 assert_equal(false, store.verify(ee2_cert)) 196 end 197 198 def test_set_errors 199 now = Time.now 200 ca1_cert = issue_cert(@ca1, @rsa2048, 1, now, now+3600, [], 201 nil, nil, OpenSSL::Digest::SHA1.new) 202 store = OpenSSL::X509::Store.new 203 store.add_cert(ca1_cert) 204 assert_raise(OpenSSL::X509::StoreError){ 205 store.add_cert(ca1_cert) # add same certificate twice 206 } 207 208 revoke_info = [] 209 crl1 = issue_crl(revoke_info, 1, now, now+1800, [], 210 ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) 211 revoke_info = [ [2, now, 1], ] 212 crl2 = issue_crl(revoke_info, 2, now+1800, now+3600, [], 213 ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) 214 store.add_crl(crl1) 215 if /0\.9\.8.*-rhel/ =~ OpenSSL::OPENSSL_VERSION 216 # RedHat is distributing a patched version of OpenSSL that allows 217 # multiple CRL for a key (multi-crl.patch) 218 assert_nothing_raised do 219 store.add_crl(crl2) # add CRL issued by same CA twice. 220 end 221 else 222 assert_raise(OpenSSL::X509::StoreError){ 223 store.add_crl(crl2) # add CRL issued by same CA twice. 224 } 225 end 226 end 227end 228 229end 230