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 // Tests that a canceled request is not leaked. 261 TEST_F(CertVerifierTest, CancelRequestThenQuit) { 262 CertVerifier verifier; 263 264 FilePath certs_dir = GetTestCertsDirectory(); 265 scoped_refptr<X509Certificate> google_cert( 266 ImportCertFromFile(certs_dir, "google.single.der")); 267 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); 268 269 int error; 270 CertVerifyResult verify_result; 271 TestCompletionCallback callback; 272 CertVerifier::RequestHandle request_handle; 273 274 error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, 275 &callback, &request_handle); 276 ASSERT_EQ(ERR_IO_PENDING, error); 277 ASSERT_TRUE(request_handle != NULL); 278 verifier.CancelRequest(request_handle); 279 // Destroy |verifier| by going out of scope. 280 } 281 282 } // namespace net 283