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

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

Issue 2331923003: Allow LogDnsClient queries to be rate-limited (Closed)
Patch Set: 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 : dns_client_(std::move(dns_client)), 86 : dns_client_(std::move(dns_client)),
87 net_log_(net_log), 87 net_log_(net_log),
88 max_concurrent_queries_(0),
88 weak_ptr_factory_(this) { 89 weak_ptr_factory_(this) {
89 CHECK(dns_client_); 90 CHECK(dns_client_);
90 net::NetworkChangeNotifier::AddDNSObserver(this); 91 net::NetworkChangeNotifier::AddDNSObserver(this);
91 UpdateDnsConfig(); 92 UpdateDnsConfig();
92 } 93 }
93 94
94 LogDnsClient::~LogDnsClient() { 95 LogDnsClient::~LogDnsClient() {
95 net::NetworkChangeNotifier::RemoveDNSObserver(this); 96 net::NetworkChangeNotifier::RemoveDNSObserver(this);
96 } 97 }
97 98
98 void LogDnsClient::OnDNSChanged() { 99 void LogDnsClient::OnDNSChanged() {
99 UpdateDnsConfig(); 100 UpdateDnsConfig();
100 } 101 }
101 102
102 void LogDnsClient::OnInitialDNSConfigRead() { 103 void LogDnsClient::OnInitialDNSConfigRead() {
103 UpdateDnsConfig(); 104 UpdateDnsConfig();
104 } 105 }
105 106
106 void LogDnsClient::QueryLeafIndex(base::StringPiece domain_for_log, 107 void LogDnsClient::QueryLeafIndex(base::StringPiece domain_for_log,
107 base::StringPiece leaf_hash, 108 base::StringPiece leaf_hash,
108 const LeafIndexCallback& callback) { 109 const LeafIndexCallback& callback) {
109 if (domain_for_log.empty() || leaf_hash.size() != crypto::kSHA256Length) { 110 if (domain_for_log.empty() || leaf_hash.size() != crypto::kSHA256Length) {
110 base::ThreadTaskRunnerHandle::Get()->PostTask( 111 base::ThreadTaskRunnerHandle::Get()->PostTask(
111 FROM_HERE, base::Bind(callback, net::Error::ERR_INVALID_ARGUMENT, 0)); 112 FROM_HERE, base::Bind(callback, net::Error::ERR_INVALID_ARGUMENT, 0));
112 return; 113 return;
113 } 114 }
114 115
116 if (HasMaxConcurrentQueriesInProgress()) {
117 base::ThreadTaskRunnerHandle::Get()->PostTask(
Eran Messeri 2016/09/12 13:26:48 Rather than invoke the callback, I suggest returni
Rob Percival 2016/09/12 17:26:24 Would you suggest the other errors that can be ret
Eran Messeri 2016/09/14 23:25:42 Yes, I would suggest other errors are also returne
118 FROM_HERE,
119 base::Bind(callback, net::Error::ERR_TEMPORARILY_THROTTLED, 0));
120 return;
121 }
122
115 std::string encoded_leaf_hash = 123 std::string encoded_leaf_hash =
116 base32::Base32Encode(leaf_hash, base32::Base32EncodePolicy::OMIT_PADDING); 124 base32::Base32Encode(leaf_hash, base32::Base32EncodePolicy::OMIT_PADDING);
117 DCHECK_EQ(encoded_leaf_hash.size(), 52u); 125 DCHECK_EQ(encoded_leaf_hash.size(), 52u);
118 126
119 net::DnsTransactionFactory* factory = dns_client_->GetTransactionFactory(); 127 net::DnsTransactionFactory* factory = dns_client_->GetTransactionFactory();
120 if (factory == nullptr) { 128 if (factory == nullptr) {
121 base::ThreadTaskRunnerHandle::Get()->PostTask( 129 base::ThreadTaskRunnerHandle::Get()->PostTask(
122 FROM_HERE, 130 FROM_HERE,
123 base::Bind(callback, net::Error::ERR_NAME_RESOLUTION_FAILED, 0)); 131 base::Bind(callback, net::Error::ERR_NAME_RESOLUTION_FAILED, 0));
124 return; 132 return;
(...skipping 14 matching lines...) Expand all
139 } 147 }
140 148
141 // The performance of this could be improved by sending all of the expected 149 // 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, 150 // 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, 151 // 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, 152 // 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 153 // 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 154 // 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 155 // 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 156 // of nodes. Ownership of the proof would need to change, as it would be shared
149 // between simultaneous DNS transactions. 157 // between simultaneous DNS transactions. Throttling of queries would also need
158 // to take into account this increase in parallelism.
150 void LogDnsClient::QueryAuditProof(base::StringPiece domain_for_log, 159 void LogDnsClient::QueryAuditProof(base::StringPiece domain_for_log,
151 uint64_t leaf_index, 160 uint64_t leaf_index,
152 uint64_t tree_size, 161 uint64_t tree_size,
153 const AuditProofCallback& callback) { 162 const AuditProofCallback& callback) {
154 if (domain_for_log.empty() || leaf_index >= tree_size) { 163 if (domain_for_log.empty() || leaf_index >= tree_size) {
155 base::ThreadTaskRunnerHandle::Get()->PostTask( 164 base::ThreadTaskRunnerHandle::Get()->PostTask(
156 FROM_HERE, 165 FROM_HERE,
157 base::Bind(callback, net::Error::ERR_INVALID_ARGUMENT, nullptr)); 166 base::Bind(callback, net::Error::ERR_INVALID_ARGUMENT, nullptr));
158 return; 167 return;
159 } 168 }
160 169
170 if (HasMaxConcurrentQueriesInProgress()) {
171 base::ThreadTaskRunnerHandle::Get()->PostTask(
172 FROM_HERE,
173 base::Bind(callback, net::Error::ERR_TEMPORARILY_THROTTLED, nullptr));
174 return;
175 }
176
161 std::unique_ptr<net::ct::MerkleAuditProof> proof( 177 std::unique_ptr<net::ct::MerkleAuditProof> proof(
162 new net::ct::MerkleAuditProof); 178 new net::ct::MerkleAuditProof);
163 proof->leaf_index = leaf_index; 179 proof->leaf_index = leaf_index;
164 // TODO(robpercival): Once a "tree_size" field is added to MerkleAuditProof, 180 // TODO(robpercival): Once a "tree_size" field is added to MerkleAuditProof,
165 // pass |tree_size| to QueryAuditProofNodes using that. 181 // pass |tree_size| to QueryAuditProofNodes using that.
166 182
167 // Query for the first batch of audit proof nodes (i.e. starting from 0). 183 // 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, 184 QueryAuditProofNodes(std::move(proof), domain_for_log, tree_size, 0,
169 callback); 185 callback);
170 } 186 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 QueryAuditProofNodes(std::move(proof), domain_for_log, tree_size, 313 QueryAuditProofNodes(std::move(proof), domain_for_log, tree_size,
298 audit_path_nodes_received, query.callback); 314 audit_path_nodes_received, query.callback);
299 return; 315 return;
300 } 316 }
301 317
302 base::ThreadTaskRunnerHandle::Get()->PostTask( 318 base::ThreadTaskRunnerHandle::Get()->PostTask(
303 FROM_HERE, 319 FROM_HERE,
304 base::Bind(query.callback, net::OK, base::Passed(std::move(proof)))); 320 base::Bind(query.callback, net::OK, base::Passed(std::move(proof))));
305 } 321 }
306 322
323 bool LogDnsClient::HasMaxConcurrentQueriesInProgress() const {
324 const size_t queries_in_progress =
325 leaf_index_queries_.size() + audit_proof_queries_.size();
326
327 return max_concurrent_queries_ != 0 &&
328 queries_in_progress >= max_concurrent_queries_;
329 }
330
307 void LogDnsClient::UpdateDnsConfig() { 331 void LogDnsClient::UpdateDnsConfig() {
308 net::DnsConfig config; 332 net::DnsConfig config;
309 net::NetworkChangeNotifier::GetDnsConfig(&config); 333 net::NetworkChangeNotifier::GetDnsConfig(&config);
310 if (config.IsValid()) 334 if (config.IsValid())
311 dns_client_->SetConfig(config); 335 dns_client_->SetConfig(config);
312 } 336 }
313 337
314 } // namespace certificate_transparency 338 } // namespace certificate_transparency
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698