|
1 | 1 | # coding: US-ASCII
|
2 | 2 | require File.expand_path('../test_helper', File.dirname(__FILE__))
|
| 3 | +require File.expand_path('../ssl/test_helper', File.dirname(__FILE__)) |
3 | 4 |
|
4 | 5 | class TestX509Store < TestCase
|
5 | 6 |
|
@@ -80,7 +81,7 @@ def test_use_non_existing_cert_file
|
80 | 81 | assert ! store.verify(@cert)
|
81 | 82 | end
|
82 | 83 |
|
83 |
| - def test_verfy_with_wrong_argument |
| 84 | + def test_verify_with_wrong_argument |
84 | 85 | store = OpenSSL::X509::Store.new
|
85 | 86 | assert_raise(TypeError) { store.verify( 'not a cert object' ) }
|
86 | 87 | end
|
@@ -151,4 +152,175 @@ def test_adding_pem_to_store
|
151 | 152 | end
|
152 | 153 | end
|
153 | 154 |
|
| 155 | + def test_verify |
| 156 | + @rsa1024 = OpenSSL::PKey::RSA.new SSLTestHelper::TEST_KEY_RSA1024 # OpenSSL::TestUtils::TEST_KEY_RSA1024 |
| 157 | + @rsa2048 = OpenSSL::PKey::RSA.new SSLTestHelper::TEST_KEY_RSA2048 # OpenSSL::TestUtils::TEST_KEY_RSA2048 |
| 158 | + @dsa256 = OpenSSL::PKey::DSA.new SSLTestHelper::TEST_KEY_DSA256 # OpenSSL::TestUtils::TEST_KEY_DSA256 |
| 159 | + @dsa512 = OpenSSL::PKey::DSA.new SSLTestHelper::TEST_KEY_DSA512 # OpenSSL::TestUtils::TEST_KEY_DSA512 |
| 160 | + @ca1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA1") |
| 161 | + @ca2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA2") |
| 162 | + @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1") |
| 163 | + @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2") |
| 164 | + |
| 165 | + now = Time.at(Time.now.to_i) |
| 166 | + ca_exts = [ |
| 167 | + ["basicConstraints","CA:TRUE",true], |
| 168 | + ["keyUsage","cRLSign,keyCertSign",true], |
| 169 | + ] |
| 170 | + ee_exts = [ |
| 171 | + ["keyUsage","keyEncipherment,digitalSignature",true], |
| 172 | + ] |
| 173 | + ca1_cert = issue_cert(@ca1, @rsa2048, 1, now, now+3600, ca_exts, |
| 174 | + nil, nil, OpenSSL::Digest::SHA1.new) |
| 175 | + ca2_cert = issue_cert(@ca2, @rsa1024, 2, now, now+1800, ca_exts, |
| 176 | + ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) |
| 177 | + ee1_cert = issue_cert(@ee1, @dsa256, 10, now, now+1800, ee_exts, |
| 178 | + ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) |
| 179 | + ee2_cert = issue_cert(@ee2, @dsa512, 20, now, now+1800, ee_exts, |
| 180 | + ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) |
| 181 | + ee3_cert = issue_cert(@ee2, @dsa512, 30, now-100, now-1, ee_exts, |
| 182 | + ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) |
| 183 | + ee4_cert = issue_cert(@ee2, @dsa512, 40, now+1000, now+2000, ee_exts, |
| 184 | + ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) |
| 185 | + |
| 186 | + revoke_info = [] |
| 187 | + crl1 = issue_crl(revoke_info, 1, now, now+1800, [], |
| 188 | + ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) |
| 189 | + revoke_info = [ [2, now, 1], ] |
| 190 | + crl1_2 = issue_crl(revoke_info, 2, now, now+1800, [], |
| 191 | + ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) |
| 192 | + revoke_info = [ [20, now, 1], ] |
| 193 | + crl2 = issue_crl(revoke_info, 1, now, now+1800, [], |
| 194 | + ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) |
| 195 | + revoke_info = [] |
| 196 | + crl2_2 = issue_crl(revoke_info, 2, now-100, now-1, [], |
| 197 | + ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) |
| 198 | + |
| 199 | + assert_equal(true, ca1_cert.verify(ca1_cert.public_key)) # self signed |
| 200 | + assert_equal(true, ca2_cert.verify(ca1_cert.public_key)) # issued by ca1 |
| 201 | + assert_equal(true, ee1_cert.verify(ca2_cert.public_key)) # issued by ca2 |
| 202 | + assert_equal(true, ee2_cert.verify(ca2_cert.public_key)) # issued by ca2 |
| 203 | + assert_equal(true, ee3_cert.verify(ca2_cert.public_key)) # issued by ca2 |
| 204 | + assert_equal(true, crl1.verify(ca1_cert.public_key)) # issued by ca1 |
| 205 | + assert_equal(true, crl1_2.verify(ca1_cert.public_key)) # issued by ca1 |
| 206 | + assert_equal(true, crl2.verify(ca2_cert.public_key)) # issued by ca2 |
| 207 | + assert_equal(true, crl2_2.verify(ca2_cert.public_key)) # issued by ca2 |
| 208 | + |
| 209 | + store = OpenSSL::X509::Store.new |
| 210 | + assert_equal(false, store.verify(ca1_cert)) |
| 211 | + assert_not_equal(OpenSSL::X509::V_OK, store.error) |
| 212 | + |
| 213 | + assert_equal(false, store.verify(ca2_cert)) |
| 214 | + assert_not_equal(OpenSSL::X509::V_OK, store.error) |
| 215 | + |
| 216 | + store.add_cert(ca1_cert) |
| 217 | + assert_equal(true, store.verify(ca2_cert)) |
| 218 | + assert_equal(OpenSSL::X509::V_OK, store.error) |
| 219 | + assert_equal("ok", store.error_string) |
| 220 | + chain = store.chain |
| 221 | + assert_equal(2, chain.size) |
| 222 | + assert_equal(@ca2.to_der, chain[0].subject.to_der) |
| 223 | + assert_equal(@ca1.to_der, chain[1].subject.to_der) |
| 224 | + |
| 225 | + store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT |
| 226 | + assert_equal(false, store.verify(ca2_cert)) |
| 227 | + assert_not_equal(OpenSSL::X509::V_OK, store.error) |
| 228 | + |
| 229 | + store.purpose = OpenSSL::X509::PURPOSE_CRL_SIGN |
| 230 | + assert_equal(true, store.verify(ca2_cert)) |
| 231 | + assert_equal(OpenSSL::X509::V_OK, store.error) |
| 232 | + |
| 233 | + store.add_cert(ca2_cert) |
| 234 | + store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT |
| 235 | + assert_equal(true, store.verify(ee1_cert)) |
| 236 | + assert_equal(true, store.verify(ee2_cert)) |
| 237 | + assert_equal(OpenSSL::X509::V_OK, store.error) |
| 238 | + assert_equal("ok", store.error_string) |
| 239 | + chain = store.chain |
| 240 | + assert_equal(3, chain.size) |
| 241 | + assert_equal(@ee2.to_der, chain[0].subject.to_der) |
| 242 | + assert_equal(@ca2.to_der, chain[1].subject.to_der) |
| 243 | + assert_equal(@ca1.to_der, chain[2].subject.to_der) |
| 244 | + assert_equal(false, store.verify(ee3_cert)) |
| 245 | + assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) |
| 246 | + assert_match(/expire/i, store.error_string) |
| 247 | + assert_equal(false, store.verify(ee4_cert)) |
| 248 | + assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error) |
| 249 | + assert_match(/not yet valid/i, store.error_string) |
| 250 | + |
| 251 | + store = OpenSSL::X509::Store.new |
| 252 | + store.add_cert(ca1_cert) |
| 253 | + store.add_cert(ca2_cert) |
| 254 | + store.time = now + 1500 |
| 255 | + assert_equal(true, store.verify(ca1_cert)) |
| 256 | + assert_equal(true, store.verify(ca2_cert)) |
| 257 | + assert_equal(true, store.verify(ee4_cert)) |
| 258 | + store.time = now + 1900 |
| 259 | + assert_equal(true, store.verify(ca1_cert)) |
| 260 | + assert_equal(false, store.verify(ca2_cert)) |
| 261 | + assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) |
| 262 | + assert_equal(false, store.verify(ee4_cert)) |
| 263 | + assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) |
| 264 | + store.time = now + 4000 |
| 265 | + assert_equal(false, store.verify(ee1_cert)) |
| 266 | + assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) |
| 267 | + assert_equal(false, store.verify(ee4_cert)) |
| 268 | + assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) |
| 269 | + |
| 270 | + # the underlying X509 struct caches the result of the last |
| 271 | + # verification for signature and not-before. so the following code |
| 272 | + # rebuilds new objects to avoid site effect. |
| 273 | + store.time = Time.now - 4000 |
| 274 | + assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ca2_cert))) |
| 275 | + assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error) |
| 276 | + assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ee1_cert))) |
| 277 | + assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error) |
| 278 | + |
| 279 | + return unless defined?(OpenSSL::X509::V_FLAG_CRL_CHECK) |
| 280 | + |
| 281 | + store = OpenSSL::X509::Store.new |
| 282 | + store.purpose = OpenSSL::X509::PURPOSE_ANY |
| 283 | + store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK |
| 284 | + store.add_cert(ca1_cert) |
| 285 | + store.add_crl(crl1) # revoke no cert |
| 286 | + store.add_crl(crl2) # revoke ee2_cert |
| 287 | + assert_equal(true, store.verify(ca1_cert)) |
| 288 | + assert_equal(true, store.verify(ca2_cert)) |
| 289 | + assert_equal(true, store.verify(ee1_cert, [ca2_cert])) |
| 290 | + assert_equal(false, store.verify(ee2_cert, [ca2_cert])) |
| 291 | + |
| 292 | + store = OpenSSL::X509::Store.new |
| 293 | + store.purpose = OpenSSL::X509::PURPOSE_ANY |
| 294 | + store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK |
| 295 | + store.add_cert(ca1_cert) |
| 296 | + store.add_crl(crl1_2) # revoke ca2_cert |
| 297 | + store.add_crl(crl2) # revoke ee2_cert |
| 298 | + assert_equal(true, store.verify(ca1_cert)) |
| 299 | + assert_equal(false, store.verify(ca2_cert)) |
| 300 | + assert_equal(true, store.verify(ee1_cert, [ca2_cert]), |
| 301 | + "This test is expected to be success with OpenSSL 0.9.7c or later.") |
| 302 | + assert_equal(false, store.verify(ee2_cert, [ca2_cert])) |
| 303 | + |
| 304 | + store.flags = |
| 305 | + OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL |
| 306 | + assert_equal(true, store.verify(ca1_cert)) |
| 307 | + assert_equal(false, store.verify(ca2_cert)) |
| 308 | + assert_equal(false, store.verify(ee1_cert, [ca2_cert])) |
| 309 | + assert_equal(false, store.verify(ee2_cert, [ca2_cert])) |
| 310 | + |
| 311 | + store = OpenSSL::X509::Store.new |
| 312 | + store.purpose = OpenSSL::X509::PURPOSE_ANY |
| 313 | + store.flags = |
| 314 | + OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL |
| 315 | + store.add_cert(ca1_cert) |
| 316 | + store.add_cert(ca2_cert) |
| 317 | + store.add_crl(crl1) |
| 318 | + store.add_crl(crl2_2) # issued by ca2 but expired. |
| 319 | + assert_equal(true, store.verify(ca1_cert)) |
| 320 | + assert_equal(true, store.verify(ca2_cert)) |
| 321 | + assert_equal(false, store.verify(ee1_cert)) |
| 322 | + assert_equal(OpenSSL::X509::V_ERR_CRL_HAS_EXPIRED, store.error) |
| 323 | + assert_equal(false, store.verify(ee2_cert)) |
| 324 | + end |
| 325 | + |
154 | 326 | end
|
0 commit comments