Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: components/certificate_transparency/log_dns_client.cc

Issue 2331923003: Allow LogDnsClient queries to be rate-limited (Closed)
Patch Set: Set LogDnsClient max_concurrent_queries via constructor param Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/log_dns_client.h" 5 #include "components/certificate_transparency/log_dns_client.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 for (size_t i = 0; i < audit_path.size(); i += crypto::kSHA256Length) { 75 for (size_t i = 0; i < audit_path.size(); i += crypto::kSHA256Length) {
76 proof->nodes.push_back(audit_path.substr(i, crypto::kSHA256Length)); 76 proof->nodes.push_back(audit_path.substr(i, crypto::kSHA256Length));
77 } 77 }
78 78
79 return true; 79 return true;
80 } 80 }
81 81
82 } // namespace 82 } // namespace
83 83
84 LogDnsClient::LogDnsClient(std::unique_ptr<net::DnsClient> dns_client, 84 LogDnsClient::LogDnsClient(std::unique_ptr<net::DnsClient> dns_client,
85 const net::BoundNetLog& net_log) 85 const net::BoundNetLog& net_log,
86 size_t max_concurrent_queries)
86 : dns_client_(std::move(dns_client)), 87 : dns_client_(std::move(dns_client)),
87 net_log_(net_log), 88 net_log_(net_log),
89 max_concurrent_queries_(max_concurrent_queries),
88 weak_ptr_factory_(this) { 90 weak_ptr_factory_(this) {
89 CHECK(dns_client_); 91 CHECK(dns_client_);
90 net::NetworkChangeNotifier::AddDNSObserver(this); 92 net::NetworkChangeNotifier::AddDNSObserver(this);
91 UpdateDnsConfig(); 93 UpdateDnsConfig();
92 } 94 }
93 95
94 LogDnsClient::~LogDnsClient() { 96 LogDnsClient::~LogDnsClient() {
95 net::NetworkChangeNotifier::RemoveDNSObserver(this); 97 net::NetworkChangeNotifier::RemoveDNSObserver(this);
96 } 98 }
97 99
98 void LogDnsClient::OnDNSChanged() { 100 void LogDnsClient::OnDNSChanged() {
99 UpdateDnsConfig(); 101 UpdateDnsConfig();
100 } 102 }
101 103
102 void LogDnsClient::OnInitialDNSConfigRead() { 104 void LogDnsClient::OnInitialDNSConfigRead() {
103 UpdateDnsConfig(); 105 UpdateDnsConfig();
104 } 106 }
105 107
106 void LogDnsClient::QueryLeafIndex(base::StringPiece domain_for_log, 108 void LogDnsClient::QueryLeafIndex(base::StringPiece domain_for_log,
107 base::StringPiece leaf_hash, 109 base::StringPiece leaf_hash,
108 const LeafIndexCallback& callback) { 110 const LeafIndexCallback& callback) {
109 if (domain_for_log.empty() || leaf_hash.size() != crypto::kSHA256Length) { 111 if (domain_for_log.empty() || leaf_hash.size() != crypto::kSHA256Length) {
110 base::ThreadTaskRunnerHandle::Get()->PostTask( 112 base::ThreadTaskRunnerHandle::Get()->PostTask(
111 FROM_HERE, base::Bind(callback, net::Error::ERR_INVALID_ARGUMENT, 0)); 113 FROM_HERE, base::Bind(callback, net::Error::ERR_INVALID_ARGUMENT, 0));
112 return; 114 return;
113 } 115 }
114 116
117 if (HasMaxConcurrentQueriesInProgress()) {
118 base::ThreadTaskRunnerHandle::Get()->PostTask(
119 FROM_HERE,
120 base::Bind(callback, net::Error::ERR_TEMPORARILY_THROTTLED, 0));
Ryan Sleevi 2016/09/12 18:12:43 The downside to this approach is that it forces a
Rob Percival 2016/09/13 14:06:31 I originally began implementing this class using t
121 return;
122 }
123
115 std::string encoded_leaf_hash = 124 std::string encoded_leaf_hash =
116 base32::Base32Encode(leaf_hash, base32::Base32EncodePolicy::OMIT_PADDING); 125 base32::Base32Encode(leaf_hash, base32::Base32EncodePolicy::OMIT_PADDING);
117 DCHECK_EQ(encoded_leaf_hash.size(), 52u); 126 DCHECK_EQ(encoded_leaf_hash.size(), 52u);
118 127
119 net::DnsTransactionFactory* factory = dns_client_->GetTransactionFactory(); 128 net::DnsTransactionFactory* factory = dns_client_->GetTransactionFactory();
120 if (factory == nullptr) { 129 if (factory == nullptr) {
121 base::ThreadTaskRunnerHandle::Get()->PostTask( 130 base::ThreadTaskRunnerHandle::Get()->PostTask(
122 FROM_HERE, 131 FROM_HERE,
123 base::Bind(callback, net::Error::ERR_NAME_RESOLUTION_FAILED, 0)); 132 base::Bind(callback, net::Error::ERR_NAME_RESOLUTION_FAILED, 0));
124 return; 133 return;
(...skipping 14 matching lines...) Expand all
139 } 148 }
140 149
141 // The performance of this could be improved by sending all of the expected 150 // The performance of this could be improved by sending all of the expected
142 // queries up front. Each response can contain a maximum of 7 audit path nodes, 151 // queries up front. Each response can contain a maximum of 7 audit path nodes,
143 // so for an audit proof of size 20, it could send 3 queries (for nodes 0-6, 152 // so for an audit proof of size 20, it could send 3 queries (for nodes 0-6,
144 // 7-13 and 14-19) immediately. Currently, it sends only the first and then, 153 // 7-13 and 14-19) immediately. Currently, it sends only the first and then,
145 // based on the number of nodes received, sends the next query. The complexity 154 // based on the number of nodes received, sends the next query. The complexity
146 // of the code would increase though, as it would need to detect gaps in the 155 // of the code would increase though, as it would need to detect gaps in the
147 // audit proof caused by the server not responding with the anticipated number 156 // audit proof caused by the server not responding with the anticipated number
148 // of nodes. Ownership of the proof would need to change, as it would be shared 157 // of nodes. Ownership of the proof would need to change, as it would be shared
149 // between simultaneous DNS transactions. 158 // between simultaneous DNS transactions. Throttling of queries would also need
159 // to take into account this increase in parallelism.
150 void LogDnsClient::QueryAuditProof(base::StringPiece domain_for_log, 160 void LogDnsClient::QueryAuditProof(base::StringPiece domain_for_log,
151 uint64_t leaf_index, 161 uint64_t leaf_index,
152 uint64_t tree_size, 162 uint64_t tree_size,
153 const AuditProofCallback& callback) { 163 const AuditProofCallback& callback) {
154 if (domain_for_log.empty() || leaf_index >= tree_size) { 164 if (domain_for_log.empty() || leaf_index >= tree_size) {
155 base::ThreadTaskRunnerHandle::Get()->PostTask( 165 base::ThreadTaskRunnerHandle::Get()->PostTask(
156 FROM_HERE, 166 FROM_HERE,
157 base::Bind(callback, net::Error::ERR_INVALID_ARGUMENT, nullptr)); 167 base::Bind(callback, net::Error::ERR_INVALID_ARGUMENT, nullptr));
158 return; 168 return;
159 } 169 }
160 170
171 if (HasMaxConcurrentQueriesInProgress()) {
172 base::ThreadTaskRunnerHandle::Get()->PostTask(
173 FROM_HERE,
174 base::Bind(callback, net::Error::ERR_TEMPORARILY_THROTTLED, nullptr));
175 return;
176 }
177
161 std::unique_ptr<net::ct::MerkleAuditProof> proof( 178 std::unique_ptr<net::ct::MerkleAuditProof> proof(
162 new net::ct::MerkleAuditProof); 179 new net::ct::MerkleAuditProof);
163 proof->leaf_index = leaf_index; 180 proof->leaf_index = leaf_index;
164 // TODO(robpercival): Once a "tree_size" field is added to MerkleAuditProof, 181 // TODO(robpercival): Once a "tree_size" field is added to MerkleAuditProof,
165 // pass |tree_size| to QueryAuditProofNodes using that. 182 // pass |tree_size| to QueryAuditProofNodes using that.
166 183
167 // Query for the first batch of audit proof nodes (i.e. starting from 0). 184 // Query for the first batch of audit proof nodes (i.e. starting from 0).
168 QueryAuditProofNodes(std::move(proof), domain_for_log, tree_size, 0, 185 QueryAuditProofNodes(std::move(proof), domain_for_log, tree_size, 0,
169 callback); 186 callback);
170 } 187 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 QueryAuditProofNodes(std::move(proof), domain_for_log, tree_size, 314 QueryAuditProofNodes(std::move(proof), domain_for_log, tree_size,
298 audit_path_nodes_received, query.callback); 315 audit_path_nodes_received, query.callback);
299 return; 316 return;
300 } 317 }
301 318
302 base::ThreadTaskRunnerHandle::Get()->PostTask( 319 base::ThreadTaskRunnerHandle::Get()->PostTask(
303 FROM_HERE, 320 FROM_HERE,
304 base::Bind(query.callback, net::OK, base::Passed(std::move(proof)))); 321 base::Bind(query.callback, net::OK, base::Passed(std::move(proof))));
305 } 322 }
306 323
324 bool LogDnsClient::HasMaxConcurrentQueriesInProgress() const {
325 const size_t queries_in_progress =
326 leaf_index_queries_.size() + audit_proof_queries_.size();
327
328 return max_concurrent_queries_ != 0 &&
329 queries_in_progress >= max_concurrent_queries_;
330 }
331
307 void LogDnsClient::UpdateDnsConfig() { 332 void LogDnsClient::UpdateDnsConfig() {
308 net::DnsConfig config; 333 net::DnsConfig config;
309 net::NetworkChangeNotifier::GetDnsConfig(&config); 334 net::NetworkChangeNotifier::GetDnsConfig(&config);
310 if (config.IsValid()) 335 if (config.IsValid())
311 dns_client_->SetConfig(config); 336 dns_client_->SetConfig(config);
312 } 337 }
313 338
314 } // namespace certificate_transparency 339 } // namespace certificate_transparency
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698