| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/certificate_transparency/single_tree_tracker.h" | 5 #include "components/certificate_transparency/single_tree_tracker.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
| 13 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/string_piece.h" | 14 #include "base/strings/string_piece.h" |
| 14 #include "base/test/histogram_tester.h" | 15 #include "base/test/histogram_tester.h" |
| 15 #include "components/base32/base32.h" | 16 #include "components/base32/base32.h" |
| 16 #include "components/certificate_transparency/log_dns_client.h" | 17 #include "components/certificate_transparency/log_dns_client.h" |
| 17 #include "components/certificate_transparency/mock_log_dns_traffic.h" | 18 #include "components/certificate_transparency/mock_log_dns_traffic.h" |
| 18 #include "crypto/sha2.h" | 19 #include "crypto/sha2.h" |
| 19 #include "net/base/network_change_notifier.h" | 20 #include "net/base/network_change_notifier.h" |
| 20 #include "net/cert/ct_log_verifier.h" | 21 #include "net/cert/ct_log_verifier.h" |
| 21 #include "net/cert/ct_serialization.h" | 22 #include "net/cert/ct_serialization.h" |
| 22 #include "net/cert/merkle_tree_leaf.h" | 23 #include "net/cert/merkle_tree_leaf.h" |
| 23 #include "net/cert/signed_certificate_timestamp.h" | 24 #include "net/cert/signed_certificate_timestamp.h" |
| 24 #include "net/cert/signed_tree_head.h" | 25 #include "net/cert/signed_tree_head.h" |
| 25 #include "net/cert/x509_certificate.h" | 26 #include "net/cert/x509_certificate.h" |
| 26 #include "net/dns/dns_client.h" | 27 #include "net/dns/dns_client.h" |
| 27 #include "net/log/net_log.h" | 28 #include "net/log/net_log.h" |
| 29 #include "net/log/test_net_log.h" |
| 30 #include "net/log/test_net_log_util.h" |
| 28 #include "net/test/ct_test_util.h" | 31 #include "net/test/ct_test_util.h" |
| 29 #include "testing/gtest/include/gtest/gtest.h" | 32 #include "testing/gtest/include/gtest/gtest.h" |
| 30 | 33 |
| 31 using net::ct::SignedCertificateTimestamp; | 34 using net::ct::SignedCertificateTimestamp; |
| 32 using net::ct::SignedTreeHead; | 35 using net::ct::SignedTreeHead; |
| 33 using net::ct::GetSampleSignedTreeHead; | 36 using net::ct::GetSampleSignedTreeHead; |
| 34 using net::ct::GetTestPublicKeyId; | 37 using net::ct::GetTestPublicKeyId; |
| 35 using net::ct::GetTestPublicKey; | 38 using net::ct::GetTestPublicKey; |
| 36 using net::ct::kSthRootHashLength; | 39 using net::ct::kSthRootHashLength; |
| 37 using net::ct::GetX509CertSCT; | 40 using net::ct::GetX509CertSCT; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 | 81 |
| 79 scoped_refptr<SignedCertificateTimestamp> GetSCT() { | 82 scoped_refptr<SignedCertificateTimestamp> GetSCT() { |
| 80 scoped_refptr<SignedCertificateTimestamp> sct; | 83 scoped_refptr<SignedCertificateTimestamp> sct; |
| 81 | 84 |
| 82 // TODO(eranm): Move setting of the origin field to ct_test_util.cc | 85 // TODO(eranm): Move setting of the origin field to ct_test_util.cc |
| 83 GetX509CertSCT(&sct); | 86 GetX509CertSCT(&sct); |
| 84 sct->origin = SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE; | 87 sct->origin = SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE; |
| 85 return sct; | 88 return sct; |
| 86 } | 89 } |
| 87 | 90 |
| 88 std::string Base32LeafHash(const net::X509Certificate* cert, | 91 std::string LeafHash(const net::X509Certificate* cert, |
| 89 const SignedCertificateTimestamp* sct) { | 92 const SignedCertificateTimestamp* sct) { |
| 90 net::ct::MerkleTreeLeaf leaf; | 93 net::ct::MerkleTreeLeaf leaf; |
| 91 if (!GetMerkleTreeLeaf(cert, sct, &leaf)) | 94 if (!GetMerkleTreeLeaf(cert, sct, &leaf)) |
| 92 return std::string(); | 95 return std::string(); |
| 93 | 96 |
| 94 std::string leaf_hash; | 97 std::string leaf_hash; |
| 95 if (!HashMerkleTreeLeaf(leaf, &leaf_hash)) | 98 if (!HashMerkleTreeLeaf(leaf, &leaf_hash)) |
| 96 return std::string(); | 99 return std::string(); |
| 97 | 100 |
| 101 return leaf_hash; |
| 102 } |
| 103 |
| 104 std::string Base32LeafHash(const net::X509Certificate* cert, |
| 105 const SignedCertificateTimestamp* sct) { |
| 106 std::string leaf_hash = LeafHash(cert, sct); |
| 107 if (leaf_hash.empty()) |
| 108 return std::string(); |
| 109 |
| 98 return base32::Base32Encode(leaf_hash, | 110 return base32::Base32Encode(leaf_hash, |
| 99 base32::Base32EncodePolicy::OMIT_PADDING); | 111 base32::Base32EncodePolicy::OMIT_PADDING); |
| 100 } | 112 } |
| 101 | 113 |
| 102 // Fills in |sth| for a tree of size 2, where the root hash is a hash of | 114 // Fills in |sth| for a tree of size 2, where the root hash is a hash of |
| 103 // the test SCT (from GetX509CertSCT) and another entry, | 115 // the test SCT (from GetX509CertSCT) and another entry, |
| 104 // whose hash is '0a' 32 times. | 116 // whose hash is '0a' 32 times. |
| 105 bool GetSignedTreeHeadForTreeOfSize2(SignedTreeHead* sth) { | 117 bool GetSignedTreeHeadForTreeOfSize2(SignedTreeHead* sth) { |
| 106 sth->version = SignedTreeHead::V1; | 118 sth->version = SignedTreeHead::V1; |
| 107 // Timestamp is after the timestamp of the test SCT (GetX509CertSCT) | 119 // Timestamp is after the timestamp of the test SCT (GetX509CertSCT) |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 cert_sct_->origin = SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE; | 179 cert_sct_->origin = SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE; |
| 168 | 180 |
| 169 net_change_notifier_ = | 181 net_change_notifier_ = |
| 170 base::WrapUnique(net::NetworkChangeNotifier::CreateMock()); | 182 base::WrapUnique(net::NetworkChangeNotifier::CreateMock()); |
| 171 mock_dns_.InitializeDnsConfig(); | 183 mock_dns_.InitializeDnsConfig(); |
| 172 } | 184 } |
| 173 | 185 |
| 174 protected: | 186 protected: |
| 175 void CreateTreeTracker() { | 187 void CreateTreeTracker() { |
| 176 log_dns_client_ = base::MakeUnique<LogDnsClient>( | 188 log_dns_client_ = base::MakeUnique<LogDnsClient>( |
| 177 mock_dns_.CreateDnsClient(), net_log_, 1); | 189 mock_dns_.CreateDnsClient(), net_log_with_source_, 1); |
| 178 | 190 |
| 179 tree_tracker_ = | 191 tree_tracker_ = base::MakeUnique<SingleTreeTracker>( |
| 180 base::MakeUnique<SingleTreeTracker>(log_, log_dns_client_.get()); | 192 log_, log_dns_client_.get(), &net_log_); |
| 181 } | 193 } |
| 182 | 194 |
| 183 void CreateTreeTrackerWithDefaultDnsExpectation() { | 195 void CreateTreeTrackerWithDefaultDnsExpectation() { |
| 184 // Default to throttling requests as it means observed log entries will | 196 // Default to throttling requests as it means observed log entries will |
| 185 // be frozen in a pending state, simplifying testing of the | 197 // be frozen in a pending state, simplifying testing of the |
| 186 // SingleTreeTracker. | 198 // SingleTreeTracker. |
| 187 ASSERT_TRUE(ExpectLeafIndexRequestAndThrottle(chain_, cert_sct_)); | 199 ASSERT_TRUE(ExpectLeafIndexRequestAndThrottle(chain_, cert_sct_)); |
| 188 CreateTreeTracker(); | 200 CreateTreeTracker(); |
| 189 } | 201 } |
| 190 | 202 |
| 191 // Configured the |mock_dns_| to expect a request for the leaf index | 203 // Configured the |mock_dns_| to expect a request for the leaf index |
| 192 // and have th mock DNS client throttle it. | 204 // and have th mock DNS client throttle it. |
| 193 bool ExpectLeafIndexRequestAndThrottle( | 205 bool ExpectLeafIndexRequestAndThrottle( |
| 194 const scoped_refptr<net::X509Certificate>& chain, | 206 const scoped_refptr<net::X509Certificate>& chain, |
| 195 const scoped_refptr<SignedCertificateTimestamp>& sct) { | 207 const scoped_refptr<SignedCertificateTimestamp>& sct) { |
| 196 return mock_dns_.ExpectRequestAndSocketError( | 208 return mock_dns_.ExpectRequestAndSocketError( |
| 197 Base32LeafHash(chain.get(), sct.get()) + ".hash." + kDNSRequestSuffix, | 209 Base32LeafHash(chain.get(), sct.get()) + ".hash." + kDNSRequestSuffix, |
| 198 net::Error::ERR_TEMPORARILY_THROTTLED); | 210 net::Error::ERR_TEMPORARILY_THROTTLED); |
| 199 } | 211 } |
| 200 | 212 |
| 213 bool MatchAuditingResultInNetLog(net::TestNetLog& net_log, |
| 214 std::string expected_leaf_hash, |
| 215 bool expected_success) { |
| 216 net::TestNetLogEntry::List entries; |
| 217 |
| 218 net_log.GetEntries(&entries); |
| 219 if (entries.size() == 0) |
| 220 return false; |
| 221 |
| 222 size_t pos = net::ExpectLogContainsSomewhere( |
| 223 entries, 0, net::NetLogEventType::CT_LOG_ENTRY_AUDITED, |
| 224 net::NetLogEventPhase::NONE); |
| 225 |
| 226 const net::TestNetLogEntry& logged_entry = entries[pos]; |
| 227 |
| 228 std::string logged_log_id, logged_leaf_hash; |
| 229 if (!logged_entry.GetStringValue("log_id", &logged_log_id) || |
| 230 !logged_entry.GetStringValue("log_entry", &logged_leaf_hash)) |
| 231 return false; |
| 232 |
| 233 if (base::HexEncode(GetTestPublicKeyId().data(), |
| 234 GetTestPublicKeyId().size()) != logged_log_id) |
| 235 return false; |
| 236 |
| 237 if (base::HexEncode(expected_leaf_hash.data(), expected_leaf_hash.size()) != |
| 238 logged_leaf_hash) |
| 239 return false; |
| 240 |
| 241 bool logged_success; |
| 242 if (!logged_entry.GetBooleanValue("success", &logged_success)) |
| 243 return false; |
| 244 |
| 245 return logged_success == expected_success; |
| 246 } |
| 247 |
| 201 base::MessageLoopForIO message_loop_; | 248 base::MessageLoopForIO message_loop_; |
| 202 MockLogDnsTraffic mock_dns_; | 249 MockLogDnsTraffic mock_dns_; |
| 203 scoped_refptr<const net::CTLogVerifier> log_; | 250 scoped_refptr<const net::CTLogVerifier> log_; |
| 204 std::unique_ptr<net::NetworkChangeNotifier> net_change_notifier_; | 251 std::unique_ptr<net::NetworkChangeNotifier> net_change_notifier_; |
| 205 std::unique_ptr<LogDnsClient> log_dns_client_; | 252 std::unique_ptr<LogDnsClient> log_dns_client_; |
| 206 std::unique_ptr<SingleTreeTracker> tree_tracker_; | 253 std::unique_ptr<SingleTreeTracker> tree_tracker_; |
| 207 scoped_refptr<net::X509Certificate> chain_; | 254 scoped_refptr<net::X509Certificate> chain_; |
| 208 scoped_refptr<SignedCertificateTimestamp> cert_sct_; | 255 scoped_refptr<SignedCertificateTimestamp> cert_sct_; |
| 209 net::NetLogWithSource net_log_; | 256 net::TestNetLog net_log_; |
| 257 net::NetLogWithSource net_log_with_source_; |
| 210 }; | 258 }; |
| 211 | 259 |
| 212 // Test that an SCT is classified as pending for a newer STH if the | 260 // Test that an SCT is classified as pending for a newer STH if the |
| 213 // SingleTreeTracker has not seen any STHs so far. | 261 // SingleTreeTracker has not seen any STHs so far. |
| 214 TEST_F(SingleTreeTrackerTest, CorrectlyClassifiesUnobservedSCTNoSTH) { | 262 TEST_F(SingleTreeTrackerTest, CorrectlyClassifiesUnobservedSCTNoSTH) { |
| 215 CreateTreeTrackerWithDefaultDnsExpectation(); | 263 CreateTreeTrackerWithDefaultDnsExpectation(); |
| 216 | 264 |
| 217 base::HistogramTester histograms; | 265 base::HistogramTester histograms; |
| 218 // First make sure the SCT has not been observed at all. | 266 // First make sure the SCT has not been observed at all. |
| 219 EXPECT_EQ( | 267 EXPECT_EQ( |
| 220 SingleTreeTracker::SCT_NOT_OBSERVED, | 268 SingleTreeTracker::SCT_NOT_OBSERVED, |
| 221 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); | 269 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); |
| 222 | 270 |
| 223 tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get()); | 271 tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get()); |
| 224 | 272 |
| 225 // Since no STH was provided to the tree_tracker_ the status should be that | 273 // Since no STH was provided to the tree_tracker_ the status should be that |
| 226 // the SCT is pending a newer STH. | 274 // the SCT is pending a newer STH. |
| 227 EXPECT_EQ( | 275 EXPECT_EQ( |
| 228 SingleTreeTracker::SCT_PENDING_NEWER_STH, | 276 SingleTreeTracker::SCT_PENDING_NEWER_STH, |
| 229 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); | 277 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); |
| 230 | 278 |
| 231 // Expect logging of a value indicating a valid STH is required. | 279 // Expect logging of a value indicating a valid STH is required. |
| 232 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); | 280 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); |
| 233 histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 0, 1); | 281 histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 0, 1); |
| 282 EXPECT_EQ(0u, net_log_.GetSize()); |
| 234 } | 283 } |
| 235 | 284 |
| 236 // Test that an SCT is classified as pending an inclusion check if the | 285 // Test that an SCT is classified as pending an inclusion check if the |
| 237 // SingleTreeTracker has a fresh-enough STH to check inclusion against. | 286 // SingleTreeTracker has a fresh-enough STH to check inclusion against. |
| 238 TEST_F(SingleTreeTrackerTest, CorrectlyClassifiesUnobservedSCTWithRecentSTH) { | 287 TEST_F(SingleTreeTrackerTest, CorrectlyClassifiesUnobservedSCTWithRecentSTH) { |
| 239 CreateTreeTrackerWithDefaultDnsExpectation(); | 288 CreateTreeTrackerWithDefaultDnsExpectation(); |
| 240 | 289 |
| 241 base::HistogramTester histograms; | 290 base::HistogramTester histograms; |
| 242 // Provide an STH to the tree_tracker_. | 291 // Provide an STH to the tree_tracker_. |
| 243 SignedTreeHead sth; | 292 SignedTreeHead sth; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 259 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); | 308 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); |
| 260 | 309 |
| 261 // Exactly one value should be logged, indicating the SCT can be checked for | 310 // Exactly one value should be logged, indicating the SCT can be checked for |
| 262 // inclusion, as |tree_tracker_| did have a valid STH when it was notified | 311 // inclusion, as |tree_tracker_| did have a valid STH when it was notified |
| 263 // of a new SCT. | 312 // of a new SCT. |
| 264 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); | 313 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); |
| 265 histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 2, 1); | 314 histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 2, 1); |
| 266 // Nothing should be logged in the result histogram since inclusion check | 315 // Nothing should be logged in the result histogram since inclusion check |
| 267 // didn't finish. | 316 // didn't finish. |
| 268 histograms.ExpectTotalCount(kInclusionCheckResultHistogramName, 0); | 317 histograms.ExpectTotalCount(kInclusionCheckResultHistogramName, 0); |
| 318 EXPECT_EQ(0u, net_log_.GetSize()); |
| 269 } | 319 } |
| 270 | 320 |
| 271 // Test that the SingleTreeTracker correctly queues verified SCTs for inclusion | 321 // Test that the SingleTreeTracker correctly queues verified SCTs for inclusion |
| 272 // checking such that, upon receiving a fresh STH, it changes the SCT's status | 322 // checking such that, upon receiving a fresh STH, it changes the SCT's status |
| 273 // from pending newer STH to pending inclusion check. | 323 // from pending newer STH to pending inclusion check. |
| 274 TEST_F(SingleTreeTrackerTest, CorrectlyUpdatesSCTStatusOnNewSTH) { | 324 TEST_F(SingleTreeTrackerTest, CorrectlyUpdatesSCTStatusOnNewSTH) { |
| 275 CreateTreeTrackerWithDefaultDnsExpectation(); | 325 CreateTreeTrackerWithDefaultDnsExpectation(); |
| 276 | 326 |
| 277 base::HistogramTester histograms; | 327 base::HistogramTester histograms; |
| 278 // Report an observed SCT and make sure it's in the pending newer STH | 328 // Report an observed SCT and make sure it's in the pending newer STH |
| (...skipping 10 matching lines...) Expand all Loading... |
| 289 tree_tracker_->NewSTHObserved(sth); | 339 tree_tracker_->NewSTHObserved(sth); |
| 290 | 340 |
| 291 // Test that its status has changed. | 341 // Test that its status has changed. |
| 292 EXPECT_EQ( | 342 EXPECT_EQ( |
| 293 SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, | 343 SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, |
| 294 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); | 344 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); |
| 295 // Check that no additional UMA was logged for this case as the histogram is | 345 // Check that no additional UMA was logged for this case as the histogram is |
| 296 // only supposed to measure the state of newly-observed SCTs, not pending | 346 // only supposed to measure the state of newly-observed SCTs, not pending |
| 297 // ones. | 347 // ones. |
| 298 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); | 348 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); |
| 349 EXPECT_EQ(0u, net_log_.GetSize()); |
| 299 } | 350 } |
| 300 | 351 |
| 301 // Test that the SingleTreeTracker does not change an SCT's status if an STH | 352 // Test that the SingleTreeTracker does not change an SCT's status if an STH |
| 302 // from the log it was issued by is observed, but that STH is too old to check | 353 // from the log it was issued by is observed, but that STH is too old to check |
| 303 // inclusion against. | 354 // inclusion against. |
| 304 TEST_F(SingleTreeTrackerTest, DoesNotUpdatesSCTStatusOnOldSTH) { | 355 TEST_F(SingleTreeTrackerTest, DoesNotUpdatesSCTStatusOnOldSTH) { |
| 305 CreateTreeTrackerWithDefaultDnsExpectation(); | 356 CreateTreeTrackerWithDefaultDnsExpectation(); |
| 306 | 357 |
| 307 // Notify of an SCT and make sure it's in the 'pending newer STH' state. | 358 // Notify of an SCT and make sure it's in the 'pending newer STH' state. |
| 308 tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get()); | 359 tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get()); |
| 309 EXPECT_EQ( | 360 EXPECT_EQ( |
| 310 SingleTreeTracker::SCT_PENDING_NEWER_STH, | 361 SingleTreeTracker::SCT_PENDING_NEWER_STH, |
| 311 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); | 362 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); |
| 312 | 363 |
| 313 // Provide an old STH for the same log. | 364 // Provide an old STH for the same log. |
| 314 SignedTreeHead sth; | 365 SignedTreeHead sth; |
| 315 GetOldSignedTreeHead(&sth); | 366 GetOldSignedTreeHead(&sth); |
| 316 tree_tracker_->NewSTHObserved(sth); | 367 tree_tracker_->NewSTHObserved(sth); |
| 317 | 368 |
| 318 // Make sure the SCT's state hasn't changed. | 369 // Make sure the SCT's state hasn't changed. |
| 319 EXPECT_EQ( | 370 EXPECT_EQ( |
| 320 SingleTreeTracker::SCT_PENDING_NEWER_STH, | 371 SingleTreeTracker::SCT_PENDING_NEWER_STH, |
| 321 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); | 372 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); |
| 373 EXPECT_EQ(0u, net_log_.GetSize()); |
| 322 } | 374 } |
| 323 | 375 |
| 324 // Test that the SingleTreeTracker correctly logs that an SCT is pending a new | 376 // Test that the SingleTreeTracker correctly logs that an SCT is pending a new |
| 325 // STH, when it has a valid STH, but the observed SCT is not covered by the | 377 // STH, when it has a valid STH, but the observed SCT is not covered by the |
| 326 // STH. | 378 // STH. |
| 327 TEST_F(SingleTreeTrackerTest, LogsUMAForNewSCTAndOldSTH) { | 379 TEST_F(SingleTreeTrackerTest, LogsUMAForNewSCTAndOldSTH) { |
| 328 CreateTreeTrackerWithDefaultDnsExpectation(); | 380 CreateTreeTrackerWithDefaultDnsExpectation(); |
| 329 | 381 |
| 330 base::HistogramTester histograms; | 382 base::HistogramTester histograms; |
| 331 // Provide an old STH for the same log. | 383 // Provide an old STH for the same log. |
| 332 SignedTreeHead sth; | 384 SignedTreeHead sth; |
| 333 GetOldSignedTreeHead(&sth); | 385 GetOldSignedTreeHead(&sth); |
| 334 tree_tracker_->NewSTHObserved(sth); | 386 tree_tracker_->NewSTHObserved(sth); |
| 335 | 387 |
| 336 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 0); | 388 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 0); |
| 337 | 389 |
| 338 // Notify of an SCT and make sure it's in the 'pending newer STH' state. | 390 // Notify of an SCT and make sure it's in the 'pending newer STH' state. |
| 339 tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get()); | 391 tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get()); |
| 340 | 392 |
| 341 // Exactly one value should be logged, indicating the SCT cannot be checked | 393 // Exactly one value should be logged, indicating the SCT cannot be checked |
| 342 // for inclusion as the STH is too old. | 394 // for inclusion as the STH is too old. |
| 343 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); | 395 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); |
| 344 histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 1, 1); | 396 histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 1, 1); |
| 397 EXPECT_EQ(0u, net_log_.GetSize()); |
| 345 } | 398 } |
| 346 | 399 |
| 347 // Test that an entry transitions to the "not found" state if the LogDnsClient | 400 // Test that an entry transitions to the "not found" state if the LogDnsClient |
| 348 // fails to get a leaf index. | 401 // fails to get a leaf index. |
| 349 TEST_F(SingleTreeTrackerTest, TestEntryNotPendingAfterLeafIndexFetchFailure) { | 402 TEST_F(SingleTreeTrackerTest, TestEntryNotPendingAfterLeafIndexFetchFailure) { |
| 350 ASSERT_TRUE(mock_dns_.ExpectRequestAndSocketError( | 403 ASSERT_TRUE(mock_dns_.ExpectRequestAndSocketError( |
| 351 Base32LeafHash(chain_.get(), cert_sct_.get()) + ".hash." + | 404 Base32LeafHash(chain_.get(), cert_sct_.get()) + ".hash." + |
| 352 kDNSRequestSuffix, | 405 kDNSRequestSuffix, |
| 353 net::Error::ERR_FAILED)); | 406 net::Error::ERR_FAILED)); |
| 354 | 407 |
| 355 CreateTreeTracker(); | 408 CreateTreeTracker(); |
| 356 | 409 |
| 357 tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get()); | 410 tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get()); |
| 358 EXPECT_EQ( | 411 EXPECT_EQ( |
| 359 SingleTreeTracker::SCT_PENDING_NEWER_STH, | 412 SingleTreeTracker::SCT_PENDING_NEWER_STH, |
| 360 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); | 413 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); |
| 361 | 414 |
| 362 // Provide with a fresh STH | 415 // Provide with a fresh STH |
| 363 SignedTreeHead sth; | 416 SignedTreeHead sth; |
| 364 GetSampleSignedTreeHead(&sth); | 417 GetSampleSignedTreeHead(&sth); |
| 365 tree_tracker_->NewSTHObserved(sth); | 418 tree_tracker_->NewSTHObserved(sth); |
| 366 base::RunLoop().RunUntilIdle(); | 419 base::RunLoop().RunUntilIdle(); |
| 367 | 420 |
| 368 EXPECT_EQ( | 421 EXPECT_EQ( |
| 369 SingleTreeTracker::SCT_NOT_OBSERVED, | 422 SingleTreeTracker::SCT_NOT_OBSERVED, |
| 370 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); | 423 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); |
| 424 // There should have been one NetLog event, logged with failure. |
| 425 EXPECT_TRUE(MatchAuditingResultInNetLog( |
| 426 net_log_, LeafHash(chain_.get(), cert_sct_.get()), false)); |
| 371 } | 427 } |
| 372 | 428 |
| 373 // Test that an entry transitions to the "not found" state if the LogDnsClient | 429 // Test that an entry transitions to the "not found" state if the LogDnsClient |
| 374 // succeeds to get a leaf index but fails to get an inclusion proof. | 430 // succeeds to get a leaf index but fails to get an inclusion proof. |
| 375 TEST_F(SingleTreeTrackerTest, TestEntryNotPendingAfterInclusionCheckFailure) { | 431 TEST_F(SingleTreeTrackerTest, TestEntryNotPendingAfterInclusionCheckFailure) { |
| 376 // Return 12 as the index of this leaf. | 432 // Return 12 as the index of this leaf. |
| 377 ASSERT_TRUE(mock_dns_.ExpectLeafIndexRequestAndResponse( | 433 ASSERT_TRUE(mock_dns_.ExpectLeafIndexRequestAndResponse( |
| 378 Base32LeafHash(chain_.get(), cert_sct_.get()) + ".hash." + | 434 Base32LeafHash(chain_.get(), cert_sct_.get()) + ".hash." + |
| 379 kDNSRequestSuffix, | 435 kDNSRequestSuffix, |
| 380 12)); | 436 12)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 394 | 450 |
| 395 // Provide with a fresh STH | 451 // Provide with a fresh STH |
| 396 SignedTreeHead sth; | 452 SignedTreeHead sth; |
| 397 GetSampleSignedTreeHead(&sth); | 453 GetSampleSignedTreeHead(&sth); |
| 398 tree_tracker_->NewSTHObserved(sth); | 454 tree_tracker_->NewSTHObserved(sth); |
| 399 base::RunLoop().RunUntilIdle(); | 455 base::RunLoop().RunUntilIdle(); |
| 400 | 456 |
| 401 EXPECT_EQ( | 457 EXPECT_EQ( |
| 402 SingleTreeTracker::SCT_NOT_OBSERVED, | 458 SingleTreeTracker::SCT_NOT_OBSERVED, |
| 403 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); | 459 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); |
| 460 // There should have been one NetLog event, logged with failure. |
| 461 EXPECT_TRUE(MatchAuditingResultInNetLog( |
| 462 net_log_, LeafHash(chain_.get(), cert_sct_.get()), false)); |
| 404 } | 463 } |
| 405 | 464 |
| 406 // Test that an entry transitions to the "included" state if the LogDnsClient | 465 // Test that an entry transitions to the "included" state if the LogDnsClient |
| 407 // succeeds to get a leaf index and an inclusion proof. | 466 // succeeds to get a leaf index and an inclusion proof. |
| 408 TEST_F(SingleTreeTrackerTest, TestEntryIncludedAfterInclusionCheckSuccess) { | 467 TEST_F(SingleTreeTrackerTest, TestEntryIncludedAfterInclusionCheckSuccess) { |
| 409 std::vector<std::string> audit_proof; | 468 std::vector<std::string> audit_proof; |
| 410 FillVectorWithValidAuditProofForTreeOfSize2(&audit_proof); | 469 FillVectorWithValidAuditProofForTreeOfSize2(&audit_proof); |
| 411 | 470 |
| 412 // Return 0 as the index for this leaf, so the proof provided | 471 // Return 0 as the index for this leaf, so the proof provided |
| 413 // later on would verify. | 472 // later on would verify. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 433 SignedTreeHead sth; | 492 SignedTreeHead sth; |
| 434 ASSERT_TRUE(GetSignedTreeHeadForTreeOfSize2(&sth)); | 493 ASSERT_TRUE(GetSignedTreeHeadForTreeOfSize2(&sth)); |
| 435 ASSERT_TRUE(log_->VerifySignedTreeHead(sth)); | 494 ASSERT_TRUE(log_->VerifySignedTreeHead(sth)); |
| 436 | 495 |
| 437 tree_tracker_->NewSTHObserved(sth); | 496 tree_tracker_->NewSTHObserved(sth); |
| 438 base::RunLoop().RunUntilIdle(); | 497 base::RunLoop().RunUntilIdle(); |
| 439 | 498 |
| 440 EXPECT_EQ( | 499 EXPECT_EQ( |
| 441 SingleTreeTracker::SCT_INCLUDED_IN_LOG, | 500 SingleTreeTracker::SCT_INCLUDED_IN_LOG, |
| 442 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); | 501 tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); |
| 502 // There should have been one NetLog event, with success logged. |
| 503 EXPECT_TRUE(MatchAuditingResultInNetLog( |
| 504 net_log_, LeafHash(chain_.get(), cert_sct_.get()), true)); |
| 443 } | 505 } |
| 444 | 506 |
| 445 // Test that pending entries transition states correctly according to the | 507 // Test that pending entries transition states correctly according to the |
| 446 // STHs provided: | 508 // STHs provided: |
| 447 // * Start without an STH. | 509 // * Start without an STH. |
| 448 // * Add a collection of entries with mixed timestamps (i.e. SCTs not added | 510 // * Add a collection of entries with mixed timestamps (i.e. SCTs not added |
| 449 // in the order of their timestamps). | 511 // in the order of their timestamps). |
| 450 // * Provide an STH that covers some of the entries, test these are audited. | 512 // * Provide an STH that covers some of the entries, test these are audited. |
| 451 // * Provide another STH that covers more of the entries, test that the entries | 513 // * Provide another STH that covers more of the entries, test that the entries |
| 452 // already audited are not audited again and that those that need to be | 514 // already audited are not audited again and that those that need to be |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 // inclusion, as |tree_tracker_| did have a valid STH when it was notified | 714 // inclusion, as |tree_tracker_| did have a valid STH when it was notified |
| 653 // of a new SCT. | 715 // of a new SCT. |
| 654 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); | 716 histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); |
| 655 histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 2, 1); | 717 histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 2, 1); |
| 656 // Failure due to DNS configuration should be logged in the result histogram. | 718 // Failure due to DNS configuration should be logged in the result histogram. |
| 657 histograms.ExpectTotalCount(kInclusionCheckResultHistogramName, 1); | 719 histograms.ExpectTotalCount(kInclusionCheckResultHistogramName, 1); |
| 658 histograms.ExpectBucketCount(kInclusionCheckResultHistogramName, 3, 1); | 720 histograms.ExpectBucketCount(kInclusionCheckResultHistogramName, 3, 1); |
| 659 } | 721 } |
| 660 | 722 |
| 661 } // namespace certificate_transparency | 723 } // namespace certificate_transparency |
| OLD | NEW |