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 |