OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/base/cert_verifier.h" |
| 6 |
| 7 #include "base/callback.h" |
| 8 #include "base/file_path.h" |
| 9 #include "base/stringprintf.h" |
| 10 #include "net/base/cert_test_util.h" |
| 11 #include "net/base/net_errors.h" |
| 12 #include "net/base/test_completion_callback.h" |
| 13 #include "net/base/x509_certificate.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 |
| 16 namespace net { |
| 17 |
| 18 class TestTimeService : public CertVerifier::TimeService { |
| 19 public: |
| 20 // CertVerifier::TimeService methods: |
| 21 virtual base::Time Now() { return current_time_; } |
| 22 |
| 23 void set_current_time(base::Time now) { current_time_ = now; } |
| 24 |
| 25 private: |
| 26 base::Time current_time_; |
| 27 }; |
| 28 |
| 29 class CertVerifierTest : public testing::Test { |
| 30 }; |
| 31 |
| 32 class ExplodingCallback : public CallbackRunner<Tuple1<int> > { |
| 33 public: |
| 34 virtual void RunWithParams(const Tuple1<int>& params) { |
| 35 FAIL(); |
| 36 } |
| 37 }; |
| 38 |
| 39 // Tests a cache hit, which should results in synchronous completion. |
| 40 TEST_F(CertVerifierTest, CacheHit) { |
| 41 TestTimeService* time_service = new TestTimeService; |
| 42 base::Time current_time = base::Time::Now(); |
| 43 time_service->set_current_time(current_time); |
| 44 CertVerifier verifier(time_service); |
| 45 |
| 46 FilePath certs_dir = GetTestCertsDirectory(); |
| 47 scoped_refptr<X509Certificate> google_cert( |
| 48 ImportCertFromFile(certs_dir, "google.single.der")); |
| 49 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); |
| 50 |
| 51 int error; |
| 52 CertVerifyResult verify_result; |
| 53 TestCompletionCallback callback; |
| 54 CertVerifier::RequestHandle request_handle; |
| 55 |
| 56 error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, |
| 57 &callback, &request_handle); |
| 58 ASSERT_EQ(ERR_IO_PENDING, error); |
| 59 ASSERT_TRUE(request_handle != NULL); |
| 60 error = callback.WaitForResult(); |
| 61 ASSERT_TRUE(IsCertificateError(error)); |
| 62 ASSERT_EQ(1u, verifier.requests()); |
| 63 ASSERT_EQ(0u, verifier.cache_hits()); |
| 64 ASSERT_EQ(0u, verifier.inflight_joins()); |
| 65 |
| 66 error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, |
| 67 &callback, &request_handle); |
| 68 // Synchronous completion. |
| 69 ASSERT_NE(ERR_IO_PENDING, error); |
| 70 ASSERT_TRUE(IsCertificateError(error)); |
| 71 ASSERT_TRUE(request_handle == NULL); |
| 72 ASSERT_EQ(2u, verifier.requests()); |
| 73 ASSERT_EQ(1u, verifier.cache_hits()); |
| 74 ASSERT_EQ(0u, verifier.inflight_joins()); |
| 75 } |
| 76 |
| 77 // Tests an inflight join. |
| 78 TEST_F(CertVerifierTest, InflightJoin) { |
| 79 TestTimeService* time_service = new TestTimeService; |
| 80 base::Time current_time = base::Time::Now(); |
| 81 time_service->set_current_time(current_time); |
| 82 CertVerifier verifier(time_service); |
| 83 |
| 84 FilePath certs_dir = GetTestCertsDirectory(); |
| 85 scoped_refptr<X509Certificate> google_cert( |
| 86 ImportCertFromFile(certs_dir, "google.single.der")); |
| 87 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); |
| 88 |
| 89 int error; |
| 90 CertVerifyResult verify_result; |
| 91 TestCompletionCallback callback; |
| 92 CertVerifier::RequestHandle request_handle; |
| 93 CertVerifyResult verify_result2; |
| 94 TestCompletionCallback callback2; |
| 95 CertVerifier::RequestHandle request_handle2; |
| 96 |
| 97 error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, |
| 98 &callback, &request_handle); |
| 99 ASSERT_EQ(ERR_IO_PENDING, error); |
| 100 ASSERT_TRUE(request_handle != NULL); |
| 101 error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result2, |
| 102 &callback2, &request_handle2); |
| 103 ASSERT_EQ(ERR_IO_PENDING, error); |
| 104 ASSERT_TRUE(request_handle2 != NULL); |
| 105 error = callback.WaitForResult(); |
| 106 ASSERT_TRUE(IsCertificateError(error)); |
| 107 error = callback2.WaitForResult(); |
| 108 ASSERT_TRUE(IsCertificateError(error)); |
| 109 ASSERT_EQ(2u, verifier.requests()); |
| 110 ASSERT_EQ(0u, verifier.cache_hits()); |
| 111 ASSERT_EQ(1u, verifier.inflight_joins()); |
| 112 } |
| 113 |
| 114 // Tests cache entry expiration. |
| 115 TEST_F(CertVerifierTest, ExpiredCacheEntry) { |
| 116 TestTimeService* time_service = new TestTimeService; |
| 117 base::Time current_time = base::Time::Now(); |
| 118 time_service->set_current_time(current_time); |
| 119 CertVerifier verifier(time_service); |
| 120 |
| 121 FilePath certs_dir = GetTestCertsDirectory(); |
| 122 scoped_refptr<X509Certificate> google_cert( |
| 123 ImportCertFromFile(certs_dir, "google.single.der")); |
| 124 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); |
| 125 |
| 126 int error; |
| 127 CertVerifyResult verify_result; |
| 128 TestCompletionCallback callback; |
| 129 CertVerifier::RequestHandle request_handle; |
| 130 |
| 131 error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, |
| 132 &callback, &request_handle); |
| 133 ASSERT_EQ(ERR_IO_PENDING, error); |
| 134 ASSERT_TRUE(request_handle != NULL); |
| 135 error = callback.WaitForResult(); |
| 136 ASSERT_TRUE(IsCertificateError(error)); |
| 137 ASSERT_EQ(1u, verifier.requests()); |
| 138 ASSERT_EQ(0u, verifier.cache_hits()); |
| 139 ASSERT_EQ(0u, verifier.inflight_joins()); |
| 140 |
| 141 // Before expiration, should have a cache hit. |
| 142 error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, |
| 143 &callback, &request_handle); |
| 144 // Synchronous completion. |
| 145 ASSERT_NE(ERR_IO_PENDING, error); |
| 146 ASSERT_TRUE(IsCertificateError(error)); |
| 147 ASSERT_TRUE(request_handle == NULL); |
| 148 ASSERT_EQ(2u, verifier.requests()); |
| 149 ASSERT_EQ(1u, verifier.cache_hits()); |
| 150 ASSERT_EQ(0u, verifier.inflight_joins()); |
| 151 |
| 152 // After expiration, should not have a cache hit. |
| 153 ASSERT_EQ(1u, verifier.GetCacheSize()); |
| 154 current_time += base::TimeDelta::FromMinutes(60); |
| 155 time_service->set_current_time(current_time); |
| 156 error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, |
| 157 &callback, &request_handle); |
| 158 ASSERT_EQ(ERR_IO_PENDING, error); |
| 159 ASSERT_TRUE(request_handle != NULL); |
| 160 ASSERT_EQ(0u, verifier.GetCacheSize()); |
| 161 error = callback.WaitForResult(); |
| 162 ASSERT_TRUE(IsCertificateError(error)); |
| 163 ASSERT_EQ(3u, verifier.requests()); |
| 164 ASSERT_EQ(1u, verifier.cache_hits()); |
| 165 ASSERT_EQ(0u, verifier.inflight_joins()); |
| 166 } |
| 167 |
| 168 // Tests a full cache. |
| 169 TEST_F(CertVerifierTest, FullCache) { |
| 170 TestTimeService* time_service = new TestTimeService; |
| 171 base::Time current_time = base::Time::Now(); |
| 172 time_service->set_current_time(current_time); |
| 173 CertVerifier verifier(time_service); |
| 174 |
| 175 FilePath certs_dir = GetTestCertsDirectory(); |
| 176 scoped_refptr<X509Certificate> google_cert( |
| 177 ImportCertFromFile(certs_dir, "google.single.der")); |
| 178 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); |
| 179 |
| 180 int error; |
| 181 CertVerifyResult verify_result; |
| 182 TestCompletionCallback callback; |
| 183 CertVerifier::RequestHandle request_handle; |
| 184 |
| 185 error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, |
| 186 &callback, &request_handle); |
| 187 ASSERT_EQ(ERR_IO_PENDING, error); |
| 188 ASSERT_TRUE(request_handle != NULL); |
| 189 error = callback.WaitForResult(); |
| 190 ASSERT_TRUE(IsCertificateError(error)); |
| 191 ASSERT_EQ(1u, verifier.requests()); |
| 192 ASSERT_EQ(0u, verifier.cache_hits()); |
| 193 ASSERT_EQ(0u, verifier.inflight_joins()); |
| 194 |
| 195 const unsigned kCacheSize = 256; |
| 196 |
| 197 for (unsigned i = 0; i < kCacheSize; i++) { |
| 198 std::string hostname = base::StringPrintf("www%d.example.com", i + 1); |
| 199 error = verifier.Verify(google_cert, hostname, 0, &verify_result, |
| 200 &callback, &request_handle); |
| 201 ASSERT_EQ(ERR_IO_PENDING, error); |
| 202 ASSERT_TRUE(request_handle != NULL); |
| 203 error = callback.WaitForResult(); |
| 204 ASSERT_TRUE(IsCertificateError(error)); |
| 205 } |
| 206 ASSERT_EQ(kCacheSize + 1, verifier.requests()); |
| 207 ASSERT_EQ(0u, verifier.cache_hits()); |
| 208 ASSERT_EQ(0u, verifier.inflight_joins()); |
| 209 |
| 210 ASSERT_EQ(kCacheSize, verifier.GetCacheSize()); |
| 211 current_time += base::TimeDelta::FromMinutes(60); |
| 212 time_service->set_current_time(current_time); |
| 213 error = verifier.Verify(google_cert, "www999.example.com", 0, &verify_result, |
| 214 &callback, &request_handle); |
| 215 ASSERT_EQ(ERR_IO_PENDING, error); |
| 216 ASSERT_TRUE(request_handle != NULL); |
| 217 ASSERT_EQ(kCacheSize, verifier.GetCacheSize()); |
| 218 error = callback.WaitForResult(); |
| 219 ASSERT_EQ(1u, verifier.GetCacheSize()); |
| 220 ASSERT_TRUE(IsCertificateError(error)); |
| 221 ASSERT_EQ(kCacheSize + 2, verifier.requests()); |
| 222 ASSERT_EQ(0u, verifier.cache_hits()); |
| 223 ASSERT_EQ(0u, verifier.inflight_joins()); |
| 224 } |
| 225 |
| 226 // Tests that the callback of a canceled request is never made. |
| 227 TEST_F(CertVerifierTest, CancelRequest) { |
| 228 CertVerifier verifier; |
| 229 |
| 230 FilePath certs_dir = GetTestCertsDirectory(); |
| 231 scoped_refptr<X509Certificate> google_cert( |
| 232 ImportCertFromFile(certs_dir, "google.single.der")); |
| 233 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); |
| 234 |
| 235 int error; |
| 236 CertVerifyResult verify_result; |
| 237 ExplodingCallback exploding_callback; |
| 238 CertVerifier::RequestHandle request_handle; |
| 239 |
| 240 error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, |
| 241 &exploding_callback, &request_handle); |
| 242 ASSERT_EQ(ERR_IO_PENDING, error); |
| 243 ASSERT_TRUE(request_handle != NULL); |
| 244 verifier.CancelRequest(request_handle); |
| 245 |
| 246 // Issue a few more requests to the worker pool and wait for their |
| 247 // completion, so that the task of the canceled request (which runs on a |
| 248 // worker thread) is likely to complete by the end of this test. |
| 249 TestCompletionCallback callback; |
| 250 for (int i = 0; i < 5; ++i) { |
| 251 error = verifier.Verify(google_cert, "www2.example.com", 0, &verify_result, |
| 252 &callback, &request_handle); |
| 253 ASSERT_EQ(ERR_IO_PENDING, error); |
| 254 ASSERT_TRUE(request_handle != NULL); |
| 255 error = callback.WaitForResult(); |
| 256 verifier.ClearCache(); |
| 257 } |
| 258 } |
| 259 |
| 260 } // namespace net |
OLD | NEW |