OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "components/certificate_transparency/tree_state_tracker.h" |
| 6 |
| 7 #include "base/strings/string_number_conversions.h" |
| 8 #include "base/thread_task_runner_handle.h" |
| 9 #include "components/certificate_transparency/log_proof_fetcher.h" |
| 10 #include "content/public/browser/browser_thread.h" |
| 11 #include "net/cert/ct_log_verifier.h" |
| 12 #include "net/cert/signed_certificate_timestamp.h" |
| 13 #include "net/cert/signed_tree_head.h" |
| 14 #include "net/cert/x509_certificate.h" |
| 15 |
| 16 namespace certificate_transparency { |
| 17 |
| 18 TreeStateTracker::TreeStateTracker( |
| 19 scoped_ptr<LogProofFetcher> fetcher, |
| 20 const std::vector<scoped_refptr<net::CTLogVerifier>>& ct_logs) |
| 21 : fetcher_(fetcher.Pass()) { |
| 22 for (auto it = ct_logs.begin(); it != ct_logs.end(); ++it) { |
| 23 scoped_refptr<net::CTLogVerifier> log(*it); |
| 24 ct_logs_[log->key_id()] = log; |
| 25 } |
| 26 content::BrowserThread::PostAfterStartupTask( |
| 27 FROM_HERE, base::ThreadTaskRunnerHandle::Get(), |
| 28 base::Bind(&TreeStateTracker::RefreshSTHs, base::Unretained(this))); |
| 29 } |
| 30 |
| 31 TreeStateTracker::~TreeStateTracker() {} |
| 32 |
| 33 void TreeStateTracker::OnSCTVerified( |
| 34 net::X509Certificate* cert, |
| 35 const net::ct::SignedCertificateTimestamp* sct) { |
| 36 VLOG(0) << "Verified SCT observed."; |
| 37 const auto& it = verified_sths_.find(sct->log_id); |
| 38 std::string log_id_hex = |
| 39 base::HexEncode(sct->log_id.data(), sct->log_id.size()); |
| 40 if (it == verified_sths_.end()) { |
| 41 VLOG(0) << "No STH found for log " << log_id_hex; |
| 42 // TODO(eranm): Enqueue SCT for inclusion check later. |
| 43 return; |
| 44 } |
| 45 |
| 46 VLOG(0) << "Found STH for log " << log_id_hex; |
| 47 const net::ct::SignedTreeHead& sth(it->second); |
| 48 if (sth.timestamp > sct->timestamp) { |
| 49 VLOG(0) << "STH timestamp (" << sth.timestamp << ") is newer than SCT " |
| 50 << "timestamp (" << sct->timestamp << "), could check inclusion."; |
| 51 // TODO(eranm): Perform actual inclusion check. |
| 52 } else { |
| 53 VLOG(0) << "STH timestamp (" << sth.timestamp << ") is OLDER than SCT " |
| 54 << "timestamp (" << sct->timestamp << "), need fresh STH."; |
| 55 // TODO(eranm): Enqueue SCT for inclusion check later. |
| 56 } |
| 57 } |
| 58 |
| 59 void TreeStateTracker::RefreshSTHs() { |
| 60 // TODO(eranm): Verify that base::Unretained usage here is fine since |
| 61 // this class owns the fetcher and the fetcher, when deleted, will delete |
| 62 // all pending requests, so this class always outlives the fetcher. |
| 63 LogProofFetcher::SignedTreeHeadFetchedCallback success_callback = |
| 64 base::Bind(&TreeStateTracker::OnSTHFetched, base::Unretained(this)); |
| 65 LogProofFetcher::FetchFailedCallback error_callback = base::Bind( |
| 66 &TreeStateTracker::OnSTHFetchingFailed, base::Unretained(this)); |
| 67 for (auto it = ct_logs_.begin(); it != ct_logs_.end(); ++it) { |
| 68 VLOG(0) << "Fetching STH for log " << it->second.get()->description(); |
| 69 net::CTLogVerifier* log(it->second.get()); |
| 70 fetcher_->FetchSignedTreeHead(log->url(), log->key_id(), success_callback, |
| 71 error_callback); |
| 72 } |
| 73 } |
| 74 |
| 75 void TreeStateTracker::OnSTHFetched( |
| 76 const std::string& log_id, |
| 77 const net::ct::SignedTreeHead& unverified_sth) { |
| 78 VLOG(0) << "Received unverified sth."; |
| 79 auto it = ct_logs_.find(log_id); |
| 80 if (it == ct_logs_.end()) { |
| 81 VLOG(0) << "STH is for unknown log!."; |
| 82 return; |
| 83 } |
| 84 |
| 85 net::CTLogVerifier* log(it->second.get()); |
| 86 if (!log->VerifySignedTreeHead(unverified_sth)) { |
| 87 VLOG(0) << "STH is for " << log->url() << " could not be verified."; |
| 88 return; |
| 89 } |
| 90 VLOG(0) << "Signature for STH from " << log->url() << " for tree size " |
| 91 << unverified_sth.tree_size << " verified."; |
| 92 |
| 93 if (verified_sths_.find(log_id) == verified_sths_.end()) { |
| 94 // No STHs currently known for this log, consider this one |
| 95 // as verified. |
| 96 verified_sths_[log_id] = unverified_sth; |
| 97 } else { |
| 98 // TODO(eranm): Request a consistency proof. |
| 99 sths_pending_consistency_check_[log_id] = unverified_sth; |
| 100 } |
| 101 } |
| 102 |
| 103 void TreeStateTracker::OnSTHFetchingFailed(const std::string& log_id, |
| 104 int net_error, |
| 105 int http_response_code) { |
| 106 const auto& it = ct_logs_.find(log_id); |
| 107 if (it == ct_logs_.end()) { |
| 108 VLOG(0) << "STH fetch failure for unknown log!."; |
| 109 return; |
| 110 } |
| 111 |
| 112 net::CTLogVerifier* log(it->second.get()); |
| 113 // TODO(eranm): UMA |
| 114 VLOG(0) << "Fetching of STH from " << log->description() << " failed because " |
| 115 << net_error << " " << http_response_code; |
| 116 } |
| 117 |
| 118 } // namespace certificate_transparency |
OLD | NEW |