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/log_dns_client.h" | 5 #include "components/certificate_transparency/log_dns_client.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <numeric> | 8 #include <numeric> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
(...skipping 23 matching lines...) Expand all Loading... |
34 using ::testing::AllOf; | 34 using ::testing::AllOf; |
35 using ::testing::Eq; | 35 using ::testing::Eq; |
36 using ::testing::IsEmpty; | 36 using ::testing::IsEmpty; |
37 using ::testing::IsNull; | 37 using ::testing::IsNull; |
38 using ::testing::Le; | 38 using ::testing::Le; |
39 using ::testing::Not; | 39 using ::testing::Not; |
40 using ::testing::NotNull; | 40 using ::testing::NotNull; |
41 using net::test::IsError; | 41 using net::test::IsError; |
42 using net::test::IsOk; | 42 using net::test::IsOk; |
43 | 43 |
| 44 // Sample Merkle leaf hashes. |
44 const char* const kLeafHashes[] = { | 45 const char* const kLeafHashes[] = { |
45 "\x1f\x25\xe1\xca\xba\x4f\xf9\xb8\x27\x24\x83\x0f\xca\x60\xe4\xc2\xbe\xa8" | 46 "\x1f\x25\xe1\xca\xba\x4f\xf9\xb8\x27\x24\x83\x0f\xca\x60\xe4\xc2\xbe\xa8" |
46 "\xc3\xa9\x44\x1c\x27\xb0\xb4\x3e\x6a\x96\x94\xc7\xb8\x04", | 47 "\xc3\xa9\x44\x1c\x27\xb0\xb4\x3e\x6a\x96\x94\xc7\xb8\x04", |
47 "\x2c\x26\xb4\x6b\x68\xff\xc6\x8f\xf9\x9b\x45\x3c\x1d\x30\x41\x34\x13\x42" | 48 "\x2c\x26\xb4\x6b\x68\xff\xc6\x8f\xf9\x9b\x45\x3c\x1d\x30\x41\x34\x13\x42" |
48 "\x2d\x70\x64\x83\xbf\xa0\xf9\x8a\x5e\x88\x62\x66\xe7\xae", | 49 "\x2d\x70\x64\x83\xbf\xa0\xf9\x8a\x5e\x88\x62\x66\xe7\xae", |
49 "\xfc\xde\x2b\x2e\xdb\xa5\x6b\xf4\x08\x60\x1f\xb7\x21\xfe\x9b\x5c\x33\x8d" | 50 "\xfc\xde\x2b\x2e\xdb\xa5\x6b\xf4\x08\x60\x1f\xb7\x21\xfe\x9b\x5c\x33\x8d" |
50 "\x10\xee\x42\x9e\xa0\x4f\xae\x55\x11\xb6\x8f\xbf\x8f\xb9", | 51 "\x10\xee\x42\x9e\xa0\x4f\xae\x55\x11\xb6\x8f\xbf\x8f\xb9", |
51 }; | 52 }; |
52 | 53 |
53 // Assumes log domain is "ct.test" | 54 // DNS query names for looking up the leaf index associated with each hash in |
54 const char* const kBase32LeafHashes[] = { | 55 // |kLeafHashes|. Assumes the log domain is "ct.test". |
| 56 const char* const kLeafIndexQnames[] = { |
55 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", | 57 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", |
56 "FQTLI23I77DI76M3IU6B2MCBGQJUELLQMSB37IHZRJPIQYTG46XA.hash.ct.test.", | 58 "FQTLI23I77DI76M3IU6B2MCBGQJUELLQMSB37IHZRJPIQYTG46XA.hash.ct.test.", |
57 "7TPCWLW3UVV7ICDAD63SD7U3LQZY2EHOIKPKAT5OKUI3ND57R64Q.hash.ct.test.", | 59 "7TPCWLW3UVV7ICDAD63SD7U3LQZY2EHOIKPKAT5OKUI3ND57R64Q.hash.ct.test.", |
58 }; | 60 }; |
59 | 61 |
60 // Leaf indices and tree sizes for use with above leaf hashes. | 62 // Leaf indices and tree sizes for use with |kLeafHashes|. |
61 const uint64_t kLeafIndices[] = {0, 1, 2}; | 63 const uint64_t kLeafIndices[] = {0, 1, 2}; |
62 const uint64_t kTreeSizes[] = {100, 10000, 1000000}; | 64 const uint64_t kTreeSizes[] = {100, 10000, 1000000}; |
63 | 65 |
64 // Only 7 audit proof nodes can fit into a DNS response, because they are sent | 66 // Only 7 audit proof nodes can fit into a DNS response, because they are sent |
65 // in a TXT RDATA string, which has a maximum size of 255 bytes, and each node | 67 // in a TXT RDATA string, which has a maximum size of 255 bytes, and each node |
66 // is a SHA-256 hash (32 bytes), i.e. (255 / 32) == 7. | 68 // is a SHA-256 hash (32 bytes), i.e. (255 / 32) == 7. |
67 // This means audit proofs consisting of more than 7 nodes require multiple DNS | 69 // This means audit proofs consisting of more than 7 nodes require multiple DNS |
68 // requests to retrieve. | 70 // requests to retrieve. |
69 const size_t kMaxProofNodesPerDnsResponse = 7; | 71 const size_t kMaxProofNodesPerDnsResponse = 7; |
70 | 72 |
71 std::vector<std::string> GetSampleAuditProof(size_t length) { | 73 std::vector<std::string> GetSampleAuditProof(size_t length) { |
72 std::vector<std::string> audit_proof(length); | 74 std::vector<std::string> audit_proof(length); |
73 // Makes each node of the audit proof different, so that tests are able to | 75 // Makes each node of the audit proof different, so that tests are able to |
74 // confirm that the audit proof is reconstructed in the correct order. | 76 // confirm that the audit proof is reconstructed in the correct order. |
75 for (size_t i = 0; i < length; ++i) { | 77 for (size_t i = 0; i < length; ++i) { |
76 std::string node(crypto::kSHA256Length, '\0'); | 78 std::string node(crypto::kSHA256Length, '\0'); |
77 // Each node is 32 bytes, with each byte having a different value. | 79 // Each node is 32 bytes, with each byte having a different value. |
78 for (size_t j = 0; j < crypto::kSHA256Length; ++j) { | 80 for (size_t j = 0; j < crypto::kSHA256Length; ++j) { |
79 node[j] = static_cast<char>((-127 + i + j) % 128); | 81 node[j] = static_cast<char>((-127 + i + j) % 128); |
80 } | 82 } |
81 audit_proof[i].assign(std::move(node)); | 83 audit_proof[i].assign(std::move(node)); |
82 } | 84 } |
83 | 85 |
84 return audit_proof; | 86 return audit_proof; |
85 } | 87 } |
86 | 88 |
87 class MockLeafIndexCallback { | |
88 public: | |
89 MockLeafIndexCallback() : called_(false) {} | |
90 | |
91 bool called() const { return called_; } | |
92 int net_error() const { return net_error_; } | |
93 uint64_t leaf_index() const { return leaf_index_; } | |
94 | |
95 void Run(int net_error, uint64_t leaf_index) { | |
96 EXPECT_FALSE(called_); | |
97 called_ = true; | |
98 net_error_ = net_error; | |
99 leaf_index_ = leaf_index; | |
100 run_loop_.Quit(); | |
101 } | |
102 | |
103 LogDnsClient::LeafIndexCallback AsCallback() { | |
104 return base::Bind(&MockLeafIndexCallback::Run, base::Unretained(this)); | |
105 } | |
106 | |
107 void WaitUntilRun() { run_loop_.Run(); } | |
108 | |
109 private: | |
110 bool called_; | |
111 int net_error_; | |
112 uint64_t leaf_index_; | |
113 base::RunLoop run_loop_; | |
114 }; | |
115 | |
116 class MockAuditProofCallback { | 89 class MockAuditProofCallback { |
117 public: | 90 public: |
118 MockAuditProofCallback() : called_(false) {} | 91 MockAuditProofCallback() : called_(false) {} |
119 | 92 |
120 bool called() const { return called_; } | 93 bool called() const { return called_; } |
121 int net_error() const { return net_error_; } | 94 int net_error() const { return net_error_; } |
122 const net::ct::MerkleAuditProof* proof() const { return proof_.get(); } | 95 const net::ct::MerkleAuditProof* proof() const { return proof_.get(); } |
123 | 96 |
124 void Run(int net_error, std::unique_ptr<net::ct::MerkleAuditProof> proof) { | 97 void Run(int net_error, std::unique_ptr<net::ct::MerkleAuditProof> proof) { |
125 EXPECT_FALSE(called_); | 98 EXPECT_FALSE(called_); |
(...skipping 24 matching lines...) Expand all Loading... |
150 mock_dns_.InitializeDnsConfig(); | 123 mock_dns_.InitializeDnsConfig(); |
151 } | 124 } |
152 | 125 |
153 std::unique_ptr<LogDnsClient> CreateLogDnsClient( | 126 std::unique_ptr<LogDnsClient> CreateLogDnsClient( |
154 size_t max_concurrent_queries) { | 127 size_t max_concurrent_queries) { |
155 return base::MakeUnique<LogDnsClient>(mock_dns_.CreateDnsClient(), | 128 return base::MakeUnique<LogDnsClient>(mock_dns_.CreateDnsClient(), |
156 net::NetLogWithSource(), | 129 net::NetLogWithSource(), |
157 max_concurrent_queries); | 130 max_concurrent_queries); |
158 } | 131 } |
159 | 132 |
160 void QueryLeafIndexAsync(LogDnsClient* log_client, | |
161 base::StringPiece log_domain, | |
162 const char leaf_hash[crypto::kSHA256Length], | |
163 const LogDnsClient::LeafIndexCallback& callback) { | |
164 log_client->QueryLeafIndex(log_domain, leaf_hash, callback); | |
165 } | |
166 | |
167 // Convenience function for calling QueryLeafIndexAsync synchronously. | |
168 void QueryLeafIndex(base::StringPiece log_domain, | |
169 const char leaf_hash[crypto::kSHA256Length], | |
170 MockLeafIndexCallback* callback) { | |
171 std::unique_ptr<LogDnsClient> log_client = CreateLogDnsClient(0); | |
172 QueryLeafIndexAsync(log_client.get(), log_domain, leaf_hash, | |
173 callback->AsCallback()); | |
174 callback->WaitUntilRun(); | |
175 } | |
176 | |
177 void QueryAuditProofAsync(LogDnsClient* log_client, | 133 void QueryAuditProofAsync(LogDnsClient* log_client, |
178 base::StringPiece log_domain, | 134 const std::string& log_domain, |
179 uint64_t leaf_index, | 135 const char leaf_hash[crypto::kSHA256Length], |
180 uint64_t tree_size, | 136 uint64_t tree_size, |
181 const LogDnsClient::AuditProofCallback& callback) { | 137 const LogDnsClient::AuditProofCallback& callback) { |
182 log_client->QueryAuditProof(log_domain, leaf_index, tree_size, callback); | 138 log_client->QueryAuditProof(log_domain, leaf_hash, tree_size, callback); |
183 } | 139 } |
184 | 140 |
185 // Convenience function for calling QueryAuditProofAsync synchronously. | 141 // Convenience function for calling QueryAuditProofAsync synchronously. |
186 void QueryAuditProof(base::StringPiece log_domain, | 142 void QueryAuditProof(const std::string& log_domain, |
187 uint64_t leaf_index, | 143 const char leaf_hash[crypto::kSHA256Length], |
188 uint64_t tree_size, | 144 uint64_t tree_size, |
189 MockAuditProofCallback* callback) { | 145 MockAuditProofCallback* callback) { |
190 std::unique_ptr<LogDnsClient> log_client = CreateLogDnsClient(0); | 146 std::unique_ptr<LogDnsClient> log_client = CreateLogDnsClient(0); |
191 QueryAuditProofAsync(log_client.get(), log_domain, leaf_index, tree_size, | 147 QueryAuditProofAsync(log_client.get(), log_domain, leaf_hash, tree_size, |
192 callback->AsCallback()); | 148 callback->AsCallback()); |
193 callback->WaitUntilRun(); | 149 callback->WaitUntilRun(); |
194 } | 150 } |
195 | 151 |
196 // This will be the NetworkChangeNotifier singleton for the duration of the | 152 // This will be the NetworkChangeNotifier singleton for the duration of the |
197 // test. It is accessed statically by LogDnsClient. | 153 // test. It is accessed statically by LogDnsClient. |
198 std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; | 154 std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; |
199 // Queues and handles asynchronous DNS tasks. Indirectly used by LogDnsClient, | 155 // Queues and handles asynchronous DNS tasks. Indirectly used by LogDnsClient, |
200 // the underlying net::DnsClient, and NetworkChangeNotifier. | 156 // the underlying net::DnsClient, and NetworkChangeNotifier. |
201 base::MessageLoopForIO message_loop_; | 157 base::MessageLoopForIO message_loop_; |
202 // Allows mock DNS sockets to be setup. | 158 // Allows mock DNS sockets to be setup. |
203 MockLogDnsTraffic mock_dns_; | 159 MockLogDnsTraffic mock_dns_; |
204 }; | 160 }; |
205 | 161 |
206 TEST_P(LogDnsClientTest, QueryLeafIndex) { | 162 TEST_P(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) { |
207 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], 123456); | 163 mock_dns_.ExpectRequestAndErrorResponse(kLeafIndexQnames[0], |
208 | |
209 MockLeafIndexCallback callback; | |
210 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | |
211 ASSERT_TRUE(callback.called()); | |
212 EXPECT_THAT(callback.net_error(), IsOk()); | |
213 EXPECT_THAT(callback.leaf_index(), Eq(123456u)); | |
214 } | |
215 | |
216 TEST_P(LogDnsClientTest, QueryLeafIndexReportsThatLogDomainDoesNotExist) { | |
217 mock_dns_.ExpectRequestAndErrorResponse(kBase32LeafHashes[0], | |
218 net::dns_protocol::kRcodeNXDOMAIN); | 164 net::dns_protocol::kRcodeNXDOMAIN); |
219 | 165 |
220 MockLeafIndexCallback callback; | 166 MockAuditProofCallback callback; |
221 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | 167 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
222 ASSERT_TRUE(callback.called()); | 168 ASSERT_TRUE(callback.called()); |
223 EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); | 169 EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); |
224 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 170 EXPECT_THAT(callback.proof(), IsNull()); |
225 } | |
226 | |
227 TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerFailure) { | |
228 mock_dns_.ExpectRequestAndErrorResponse(kBase32LeafHashes[0], | |
229 net::dns_protocol::kRcodeSERVFAIL); | |
230 | |
231 MockLeafIndexCallback callback; | |
232 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | |
233 ASSERT_TRUE(callback.called()); | |
234 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); | |
235 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | |
236 } | |
237 | |
238 TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerRefusal) { | |
239 mock_dns_.ExpectRequestAndErrorResponse(kBase32LeafHashes[0], | |
240 net::dns_protocol::kRcodeREFUSED); | |
241 | |
242 MockLeafIndexCallback callback; | |
243 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | |
244 ASSERT_TRUE(callback.called()); | |
245 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); | |
246 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | |
247 } | 171 } |
248 | 172 |
249 TEST_P(LogDnsClientTest, | 173 TEST_P(LogDnsClientTest, |
250 QueryLeafIndexReportsMalformedResponseIfContainsNoStrings) { | 174 QueryAuditProofReportsServerFailuresDuringLeafIndexRequests) { |
251 mock_dns_.ExpectRequestAndResponse( | 175 mock_dns_.ExpectRequestAndErrorResponse(kLeafIndexQnames[0], |
252 kBase32LeafHashes[0], | 176 net::dns_protocol::kRcodeSERVFAIL); |
253 std::vector<base::StringPiece>()); | |
254 | 177 |
255 MockLeafIndexCallback callback; | 178 MockAuditProofCallback callback; |
256 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | 179 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
257 ASSERT_TRUE(callback.called()); | 180 ASSERT_TRUE(callback.called()); |
258 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 181 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); |
259 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 182 EXPECT_THAT(callback.proof(), IsNull()); |
260 } | 183 } |
261 | 184 |
262 TEST_P(LogDnsClientTest, | 185 TEST_P(LogDnsClientTest, |
263 QueryLeafIndexReportsMalformedResponseIfContainsMoreThanOneString) { | 186 QueryAuditProofReportsServerRefusalsDuringLeafIndexRequests) { |
264 mock_dns_.ExpectRequestAndResponse( | 187 mock_dns_.ExpectRequestAndErrorResponse(kLeafIndexQnames[0], |
265 kBase32LeafHashes[0], | 188 net::dns_protocol::kRcodeREFUSED); |
266 {"123456", "7"}); | |
267 | 189 |
268 MockLeafIndexCallback callback; | 190 MockAuditProofCallback callback; |
269 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | 191 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
270 ASSERT_TRUE(callback.called()); | 192 ASSERT_TRUE(callback.called()); |
271 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 193 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); |
272 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 194 EXPECT_THAT(callback.proof(), IsNull()); |
273 } | 195 } |
274 | 196 |
275 TEST_P(LogDnsClientTest, | 197 TEST_P(LogDnsClientTest, |
276 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsNotNumeric) { | 198 QueryAuditProofReportsMalformedResponseIfLeafIndexResponseContainsNoStrin
gs) { |
277 mock_dns_.ExpectRequestAndResponse(kBase32LeafHashes[0], {"foo"}); | 199 mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], |
| 200 std::vector<base::StringPiece>()); |
278 | 201 |
279 MockLeafIndexCallback callback; | 202 MockAuditProofCallback callback; |
280 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | 203 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
281 ASSERT_TRUE(callback.called()); | 204 ASSERT_TRUE(callback.called()); |
282 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 205 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
283 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 206 EXPECT_THAT(callback.proof(), IsNull()); |
284 } | 207 } |
285 | 208 |
286 TEST_P(LogDnsClientTest, | 209 TEST_P(LogDnsClientTest, |
287 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsFloatingPoint) { | 210 QueryAuditProofReportsMalformedResponseIfLeafIndexResponseContainsMoreTha
nOneString) { |
288 mock_dns_.ExpectRequestAndResponse(kBase32LeafHashes[0], {"123456.0"}); | 211 mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {"123456", "7"}); |
289 | 212 |
290 MockLeafIndexCallback callback; | 213 MockAuditProofCallback callback; |
291 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | 214 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
292 ASSERT_TRUE(callback.called()); | 215 ASSERT_TRUE(callback.called()); |
293 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 216 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
294 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 217 EXPECT_THAT(callback.proof(), IsNull()); |
295 } | 218 } |
296 | 219 |
297 TEST_P(LogDnsClientTest, | 220 TEST_P(LogDnsClientTest, |
298 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsEmpty) { | 221 QueryAuditProofReportsMalformedResponseIfLeafIndexIsNotNumeric) { |
299 mock_dns_.ExpectRequestAndResponse(kBase32LeafHashes[0], {""}); | 222 mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {"foo"}); |
300 | 223 |
301 MockLeafIndexCallback callback; | 224 MockAuditProofCallback callback; |
302 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | 225 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
303 ASSERT_TRUE(callback.called()); | 226 ASSERT_TRUE(callback.called()); |
304 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 227 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
305 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 228 EXPECT_THAT(callback.proof(), IsNull()); |
306 } | 229 } |
307 | 230 |
308 TEST_P(LogDnsClientTest, | 231 TEST_P(LogDnsClientTest, |
309 QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericPrefix) { | 232 QueryAuditProofReportsMalformedResponseIfLeafIndexIsFloatingPoint) { |
310 mock_dns_.ExpectRequestAndResponse(kBase32LeafHashes[0], {"foo123456"}); | 233 mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {"123456.0"}); |
311 | 234 |
312 MockLeafIndexCallback callback; | 235 MockAuditProofCallback callback; |
313 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | 236 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
314 ASSERT_TRUE(callback.called()); | 237 ASSERT_TRUE(callback.called()); |
315 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 238 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
316 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 239 EXPECT_THAT(callback.proof(), IsNull()); |
317 } | 240 } |
318 | 241 |
319 TEST_P(LogDnsClientTest, | 242 TEST_P(LogDnsClientTest, |
320 QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericSuffix) { | 243 QueryAuditProofReportsMalformedResponseIfLeafIndexIsEmpty) { |
321 mock_dns_.ExpectRequestAndResponse(kBase32LeafHashes[0], {"123456foo"}); | 244 mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {""}); |
322 | 245 |
323 MockLeafIndexCallback callback; | 246 MockAuditProofCallback callback; |
324 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | 247 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
325 ASSERT_TRUE(callback.called()); | 248 ASSERT_TRUE(callback.called()); |
326 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 249 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
327 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 250 EXPECT_THAT(callback.proof(), IsNull()); |
328 } | 251 } |
329 | 252 |
330 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsEmpty) { | 253 TEST_P(LogDnsClientTest, |
331 MockLeafIndexCallback callback; | 254 QueryAuditProofReportsMalformedResponseIfLeafIndexHasNonNumericPrefix) { |
332 QueryLeafIndex("", kLeafHashes[0], &callback); | 255 mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {"foo123456"}); |
| 256 |
| 257 MockAuditProofCallback callback; |
| 258 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
| 259 ASSERT_TRUE(callback.called()); |
| 260 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
| 261 EXPECT_THAT(callback.proof(), IsNull()); |
| 262 } |
| 263 |
| 264 TEST_P(LogDnsClientTest, |
| 265 QueryAuditProofReportsMalformedResponseIfLeafIndexHasNonNumericSuffix) { |
| 266 mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {"123456foo"}); |
| 267 |
| 268 MockAuditProofCallback callback; |
| 269 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
| 270 ASSERT_TRUE(callback.called()); |
| 271 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
| 272 EXPECT_THAT(callback.proof(), IsNull()); |
| 273 } |
| 274 |
| 275 TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLogDomainIsEmpty) { |
| 276 MockAuditProofCallback callback; |
| 277 QueryAuditProof("", kLeafHashes[0], kTreeSizes[0], &callback); |
333 ASSERT_TRUE(callback.called()); | 278 ASSERT_TRUE(callback.called()); |
334 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); | 279 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
335 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 280 EXPECT_THAT(callback.proof(), IsNull()); |
336 } | 281 } |
337 | 282 |
338 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsNull) { | 283 TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLeafHashIsInvalid) { |
339 MockLeafIndexCallback callback; | 284 MockAuditProofCallback callback; |
340 QueryLeafIndex(nullptr, kLeafHashes[0], &callback); | 285 QueryAuditProof("ct.test", "foo", kTreeSizes[0], &callback); |
341 ASSERT_TRUE(callback.called()); | 286 ASSERT_TRUE(callback.called()); |
342 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); | 287 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
343 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 288 EXPECT_THAT(callback.proof(), IsNull()); |
344 } | 289 } |
345 | 290 |
346 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsInvalid) { | 291 TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLeafHashIsEmpty) { |
347 MockLeafIndexCallback callback; | 292 MockAuditProofCallback callback; |
348 QueryLeafIndex("ct.test", "foo", &callback); | 293 QueryAuditProof("ct.test", "", kTreeSizes[0], &callback); |
349 ASSERT_TRUE(callback.called()); | 294 ASSERT_TRUE(callback.called()); |
350 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); | 295 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
351 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 296 EXPECT_THAT(callback.proof(), IsNull()); |
352 } | 297 } |
353 | 298 |
354 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsEmpty) { | 299 TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLeafHashIsNull) { |
355 MockLeafIndexCallback callback; | 300 MockAuditProofCallback callback; |
356 QueryLeafIndex("ct.test", "", &callback); | 301 QueryAuditProof("ct.test", nullptr, kTreeSizes[0], &callback); |
357 ASSERT_TRUE(callback.called()); | 302 ASSERT_TRUE(callback.called()); |
358 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); | 303 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
359 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 304 EXPECT_THAT(callback.proof(), IsNull()); |
360 } | 305 } |
361 | 306 |
362 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsNull) { | 307 TEST_P(LogDnsClientTest, |
363 MockLeafIndexCallback callback; | 308 QueryAuditProofReportsSocketErrorsDuringLeafIndexRequests) { |
364 QueryLeafIndex("ct.test", nullptr, &callback); | 309 mock_dns_.ExpectRequestAndSocketError(kLeafIndexQnames[0], |
| 310 net::ERR_CONNECTION_REFUSED); |
| 311 |
| 312 MockAuditProofCallback callback; |
| 313 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
365 ASSERT_TRUE(callback.called()); | 314 ASSERT_TRUE(callback.called()); |
366 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); | 315 EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); |
367 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 316 EXPECT_THAT(callback.proof(), IsNull()); |
368 } | 317 } |
369 | 318 |
370 TEST_P(LogDnsClientTest, QueryLeafIndexReportsSocketError) { | 319 TEST_P(LogDnsClientTest, |
371 mock_dns_.ExpectRequestAndSocketError(kBase32LeafHashes[0], | 320 QueryAuditProofReportsTimeoutsDuringLeafIndexRequests) { |
372 net::ERR_CONNECTION_REFUSED); | 321 mock_dns_.ExpectRequestAndTimeout(kLeafIndexQnames[0]); |
373 | 322 |
374 MockLeafIndexCallback callback; | 323 MockAuditProofCallback callback; |
375 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | 324 QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
376 ASSERT_TRUE(callback.called()); | |
377 EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); | |
378 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | |
379 } | |
380 | |
381 TEST_P(LogDnsClientTest, QueryLeafIndexReportsTimeout) { | |
382 mock_dns_.ExpectRequestAndTimeout(kBase32LeafHashes[0]); | |
383 | |
384 MockLeafIndexCallback callback; | |
385 QueryLeafIndex("ct.test", kLeafHashes[0], &callback); | |
386 ASSERT_TRUE(callback.called()); | 325 ASSERT_TRUE(callback.called()); |
387 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); | 326 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); |
388 EXPECT_THAT(callback.leaf_index(), Eq(0u)); | 327 EXPECT_THAT(callback.proof(), IsNull()); |
389 } | 328 } |
390 | 329 |
391 TEST_P(LogDnsClientTest, QueryAuditProof) { | 330 TEST_P(LogDnsClientTest, QueryAuditProof) { |
392 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); | 331 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); |
393 | 332 |
| 333 // Expect a leaf index query first, to map the leaf hash to a leaf index. |
| 334 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
| 335 |
394 // It takes a number of DNS requests to retrieve the entire |audit_proof| | 336 // It takes a number of DNS requests to retrieve the entire |audit_proof| |
395 // (see |kMaxProofNodesPerDnsResponse|). | 337 // (see |kMaxProofNodesPerDnsResponse|). |
396 for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); | 338 for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); |
397 nodes_begin += kMaxProofNodesPerDnsResponse) { | 339 nodes_begin += kMaxProofNodesPerDnsResponse) { |
398 const size_t nodes_end = std::min( | 340 const size_t nodes_end = std::min( |
399 nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); | 341 nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); |
400 | 342 |
401 mock_dns_.ExpectAuditProofRequestAndResponse( | 343 mock_dns_.ExpectAuditProofRequestAndResponse( |
402 base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), | 344 base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), |
403 audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end); | 345 audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end); |
404 } | 346 } |
405 | 347 |
406 MockAuditProofCallback callback; | 348 MockAuditProofCallback callback; |
407 QueryAuditProof("ct.test", 123456, 999999, &callback); | 349 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
408 ASSERT_TRUE(callback.called()); | 350 ASSERT_TRUE(callback.called()); |
409 EXPECT_THAT(callback.net_error(), IsOk()); | 351 EXPECT_THAT(callback.net_error(), IsOk()); |
410 ASSERT_THAT(callback.proof(), NotNull()); | 352 ASSERT_THAT(callback.proof(), NotNull()); |
411 EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u)); | 353 EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u)); |
412 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. | 354 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
413 // EXPECT_THAT(callback.proof()->tree_size, Eq(999999)); | 355 // EXPECT_THAT(callback.proof()->tree_size, Eq(999999)); |
414 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof)); | 356 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof)); |
415 } | 357 } |
416 | 358 |
417 TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) { | 359 TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) { |
418 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); | 360 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); |
419 | 361 |
| 362 // Expect a leaf index query first, to map the leaf hash to a leaf index. |
| 363 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
| 364 |
420 // Make some of the responses contain fewer proof nodes than they can hold. | 365 // Make some of the responses contain fewer proof nodes than they can hold. |
421 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", | 366 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", |
422 audit_proof.begin(), | 367 audit_proof.begin(), |
423 audit_proof.begin() + 1); | 368 audit_proof.begin() + 1); |
424 mock_dns_.ExpectAuditProofRequestAndResponse("1.123456.999999.tree.ct.test.", | 369 mock_dns_.ExpectAuditProofRequestAndResponse("1.123456.999999.tree.ct.test.", |
425 audit_proof.begin() + 1, | 370 audit_proof.begin() + 1, |
426 audit_proof.begin() + 3); | 371 audit_proof.begin() + 3); |
427 mock_dns_.ExpectAuditProofRequestAndResponse("3.123456.999999.tree.ct.test.", | 372 mock_dns_.ExpectAuditProofRequestAndResponse("3.123456.999999.tree.ct.test.", |
428 audit_proof.begin() + 3, | 373 audit_proof.begin() + 3, |
429 audit_proof.begin() + 6); | 374 audit_proof.begin() + 6); |
430 mock_dns_.ExpectAuditProofRequestAndResponse("6.123456.999999.tree.ct.test.", | 375 mock_dns_.ExpectAuditProofRequestAndResponse("6.123456.999999.tree.ct.test.", |
431 audit_proof.begin() + 6, | 376 audit_proof.begin() + 6, |
432 audit_proof.begin() + 10); | 377 audit_proof.begin() + 10); |
433 mock_dns_.ExpectAuditProofRequestAndResponse("10.123456.999999.tree.ct.test.", | 378 mock_dns_.ExpectAuditProofRequestAndResponse("10.123456.999999.tree.ct.test.", |
434 audit_proof.begin() + 10, | 379 audit_proof.begin() + 10, |
435 audit_proof.begin() + 13); | 380 audit_proof.begin() + 13); |
436 mock_dns_.ExpectAuditProofRequestAndResponse("13.123456.999999.tree.ct.test.", | 381 mock_dns_.ExpectAuditProofRequestAndResponse("13.123456.999999.tree.ct.test.", |
437 audit_proof.begin() + 13, | 382 audit_proof.begin() + 13, |
438 audit_proof.end()); | 383 audit_proof.end()); |
439 | 384 |
440 MockAuditProofCallback callback; | 385 MockAuditProofCallback callback; |
441 QueryAuditProof("ct.test", 123456, 999999, &callback); | 386 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
442 ASSERT_TRUE(callback.called()); | 387 ASSERT_TRUE(callback.called()); |
443 EXPECT_THAT(callback.net_error(), IsOk()); | 388 EXPECT_THAT(callback.net_error(), IsOk()); |
444 ASSERT_THAT(callback.proof(), NotNull()); | 389 ASSERT_THAT(callback.proof(), NotNull()); |
445 EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u)); | 390 EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u)); |
446 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. | 391 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
447 // EXPECT_THAT(callback.proof()->tree_size, Eq(999999)); | 392 // EXPECT_THAT(callback.proof()->tree_size, Eq(999999)); |
448 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof)); | 393 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof)); |
449 } | 394 } |
450 | 395 |
451 TEST_P(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) { | 396 TEST_P(LogDnsClientTest, |
| 397 QueryAuditProofReportsThatAuditProofQnameDoesNotExist) { |
| 398 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
452 mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", | 399 mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", |
453 net::dns_protocol::kRcodeNXDOMAIN); | 400 net::dns_protocol::kRcodeNXDOMAIN); |
454 | 401 |
455 MockAuditProofCallback callback; | 402 MockAuditProofCallback callback; |
456 QueryAuditProof("ct.test", 123456, 999999, &callback); | 403 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
457 ASSERT_TRUE(callback.called()); | 404 ASSERT_TRUE(callback.called()); |
458 EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); | 405 EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); |
459 EXPECT_THAT(callback.proof(), IsNull()); | 406 EXPECT_THAT(callback.proof(), IsNull()); |
460 } | 407 } |
461 | 408 |
462 TEST_P(LogDnsClientTest, QueryAuditProofReportsServerFailure) { | 409 TEST_P(LogDnsClientTest, |
| 410 QueryAuditProofReportsServerFailureDuringAuditProofRequests) { |
| 411 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
463 mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", | 412 mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", |
464 net::dns_protocol::kRcodeSERVFAIL); | 413 net::dns_protocol::kRcodeSERVFAIL); |
465 | 414 |
466 MockAuditProofCallback callback; | 415 MockAuditProofCallback callback; |
467 QueryAuditProof("ct.test", 123456, 999999, &callback); | 416 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
468 ASSERT_TRUE(callback.called()); | |
469 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); | |
470 EXPECT_THAT(callback.proof(), IsNull()); | |
471 } | |
472 | |
473 TEST_P(LogDnsClientTest, QueryAuditProofReportsServerRefusal) { | |
474 mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", | |
475 net::dns_protocol::kRcodeREFUSED); | |
476 | |
477 MockAuditProofCallback callback; | |
478 QueryAuditProof("ct.test", 123456, 999999, &callback); | |
479 ASSERT_TRUE(callback.called()); | 417 ASSERT_TRUE(callback.called()); |
480 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); | 418 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); |
481 EXPECT_THAT(callback.proof(), IsNull()); | 419 EXPECT_THAT(callback.proof(), IsNull()); |
482 } | 420 } |
483 | 421 |
484 TEST_P(LogDnsClientTest, | 422 TEST_P(LogDnsClientTest, |
485 QueryAuditProofReportsResponseMalformedIfContainsNoStrings) { | 423 QueryAuditProofReportsServerRefusalDuringAuditProofRequests) { |
| 424 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
| 425 mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", |
| 426 net::dns_protocol::kRcodeREFUSED); |
| 427 |
| 428 MockAuditProofCallback callback; |
| 429 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
| 430 ASSERT_TRUE(callback.called()); |
| 431 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); |
| 432 EXPECT_THAT(callback.proof(), IsNull()); |
| 433 } |
| 434 |
| 435 TEST_P(LogDnsClientTest, |
| 436 QueryAuditProofReportsResponseMalformedIfProofNodesResponseContainsNoStri
ngs) { |
| 437 // Expect a leaf index query first, to map the leaf hash to a leaf index. |
| 438 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
| 439 |
486 mock_dns_.ExpectRequestAndResponse("0.123456.999999.tree.ct.test.", | 440 mock_dns_.ExpectRequestAndResponse("0.123456.999999.tree.ct.test.", |
487 std::vector<base::StringPiece>()); | 441 std::vector<base::StringPiece>()); |
488 | 442 |
489 MockAuditProofCallback callback; | 443 MockAuditProofCallback callback; |
490 QueryAuditProof("ct.test", 123456, 999999, &callback); | 444 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
491 ASSERT_TRUE(callback.called()); | 445 ASSERT_TRUE(callback.called()); |
492 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 446 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
493 EXPECT_THAT(callback.proof(), IsNull()); | 447 EXPECT_THAT(callback.proof(), IsNull()); |
494 } | 448 } |
495 | 449 |
496 TEST_P(LogDnsClientTest, | 450 TEST_P(LogDnsClientTest, |
497 QueryAuditProofReportsResponseMalformedIfContainsMoreThanOneString) { | 451 QueryAuditProofReportsResponseMalformedIfProofNodesResponseContainsMoreTh
anOneString) { |
498 // The CT-over-DNS draft RFC states that the response will contain "exactly | 452 // The CT-over-DNS draft RFC states that the response will contain "exactly |
499 // one character-string." | 453 // one character-string." |
500 const std::vector<std::string> audit_proof = GetSampleAuditProof(10); | 454 const std::vector<std::string> audit_proof = GetSampleAuditProof(10); |
501 | 455 |
502 std::string first_chunk_of_proof = std::accumulate( | 456 std::string first_chunk_of_proof = std::accumulate( |
503 audit_proof.begin(), audit_proof.begin() + 7, std::string()); | 457 audit_proof.begin(), audit_proof.begin() + 7, std::string()); |
504 std::string second_chunk_of_proof = std::accumulate( | 458 std::string second_chunk_of_proof = std::accumulate( |
505 audit_proof.begin() + 7, audit_proof.end(), std::string()); | 459 audit_proof.begin() + 7, audit_proof.end(), std::string()); |
506 | 460 |
| 461 // Expect a leaf index query first, to map the leaf hash to a leaf index. |
| 462 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
| 463 |
507 mock_dns_.ExpectRequestAndResponse( | 464 mock_dns_.ExpectRequestAndResponse( |
508 "0.123456.999999.tree.ct.test.", | 465 "0.123456.999999.tree.ct.test.", |
509 {first_chunk_of_proof, second_chunk_of_proof}); | 466 {first_chunk_of_proof, second_chunk_of_proof}); |
510 | 467 |
511 MockAuditProofCallback callback; | 468 MockAuditProofCallback callback; |
512 QueryAuditProof("ct.test", 123456, 999999, &callback); | 469 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
513 ASSERT_TRUE(callback.called()); | 470 ASSERT_TRUE(callback.called()); |
514 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 471 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
515 EXPECT_THAT(callback.proof(), IsNull()); | 472 EXPECT_THAT(callback.proof(), IsNull()); |
516 } | 473 } |
517 | 474 |
518 TEST_P(LogDnsClientTest, | 475 TEST_P(LogDnsClientTest, |
519 QueryAuditProofReportsResponseMalformedIfNodeTooShort) { | 476 QueryAuditProofReportsResponseMalformedIfNodeTooShort) { |
520 // node is shorter than a SHA-256 hash (31 vs 32 bytes) | 477 // node is shorter than a SHA-256 hash (31 vs 32 bytes) |
521 const std::vector<std::string> audit_proof(1, std::string(31, 'a')); | 478 const std::vector<std::string> audit_proof(1, std::string(31, 'a')); |
522 | 479 |
| 480 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
523 mock_dns_.ExpectAuditProofRequestAndResponse( | 481 mock_dns_.ExpectAuditProofRequestAndResponse( |
524 "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end()); | 482 "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end()); |
525 | 483 |
526 MockAuditProofCallback callback; | 484 MockAuditProofCallback callback; |
527 QueryAuditProof("ct.test", 123456, 999999, &callback); | 485 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
528 ASSERT_TRUE(callback.called()); | 486 ASSERT_TRUE(callback.called()); |
529 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 487 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
530 EXPECT_THAT(callback.proof(), IsNull()); | 488 EXPECT_THAT(callback.proof(), IsNull()); |
531 } | 489 } |
532 | 490 |
533 TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfNodeTooLong) { | 491 TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfNodeTooLong) { |
534 // node is longer than a SHA-256 hash (33 vs 32 bytes) | 492 // node is longer than a SHA-256 hash (33 vs 32 bytes) |
535 const std::vector<std::string> audit_proof(1, std::string(33, 'a')); | 493 const std::vector<std::string> audit_proof(1, std::string(33, 'a')); |
536 | 494 |
| 495 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
537 mock_dns_.ExpectAuditProofRequestAndResponse( | 496 mock_dns_.ExpectAuditProofRequestAndResponse( |
538 "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end()); | 497 "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end()); |
539 | 498 |
540 MockAuditProofCallback callback; | 499 MockAuditProofCallback callback; |
541 QueryAuditProof("ct.test", 123456, 999999, &callback); | 500 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
542 ASSERT_TRUE(callback.called()); | 501 ASSERT_TRUE(callback.called()); |
543 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 502 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
544 EXPECT_THAT(callback.proof(), IsNull()); | 503 EXPECT_THAT(callback.proof(), IsNull()); |
545 } | 504 } |
546 | 505 |
547 TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfEmpty) { | 506 TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfEmpty) { |
548 const std::vector<std::string> audit_proof; | 507 const std::vector<std::string> audit_proof; |
549 | 508 |
| 509 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
550 mock_dns_.ExpectAuditProofRequestAndResponse( | 510 mock_dns_.ExpectAuditProofRequestAndResponse( |
551 "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end()); | 511 "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end()); |
552 | 512 |
553 MockAuditProofCallback callback; | 513 MockAuditProofCallback callback; |
554 QueryAuditProof("ct.test", 123456, 999999, &callback); | 514 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
555 ASSERT_TRUE(callback.called()); | 515 ASSERT_TRUE(callback.called()); |
556 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); | 516 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
557 EXPECT_THAT(callback.proof(), IsNull()); | 517 EXPECT_THAT(callback.proof(), IsNull()); |
558 } | 518 } |
559 | 519 |
560 TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLogDomainIsEmpty) { | |
561 MockAuditProofCallback callback; | |
562 QueryAuditProof("", 123456, 999999, &callback); | |
563 ASSERT_TRUE(callback.called()); | |
564 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); | |
565 EXPECT_THAT(callback.proof(), IsNull()); | |
566 } | |
567 | |
568 TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLogDomainIsNull) { | |
569 MockAuditProofCallback callback; | |
570 QueryAuditProof(nullptr, 123456, 999999, &callback); | |
571 ASSERT_TRUE(callback.called()); | |
572 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); | |
573 EXPECT_THAT(callback.proof(), IsNull()); | |
574 } | |
575 | |
576 TEST_P(LogDnsClientTest, | 520 TEST_P(LogDnsClientTest, |
577 QueryAuditProofReportsInvalidArgIfLeafIndexEqualToTreeSize) { | 521 QueryAuditProofReportsInvalidArgIfLeafIndexEqualToTreeSize) { |
| 522 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
| 523 |
578 MockAuditProofCallback callback; | 524 MockAuditProofCallback callback; |
579 QueryAuditProof("ct.test", 123456, 123456, &callback); | 525 QueryAuditProof("ct.test", kLeafHashes[0], 123456, &callback); |
580 ASSERT_TRUE(callback.called()); | 526 ASSERT_TRUE(callback.called()); |
581 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); | 527 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
582 EXPECT_THAT(callback.proof(), IsNull()); | 528 EXPECT_THAT(callback.proof(), IsNull()); |
583 } | 529 } |
584 | 530 |
585 TEST_P(LogDnsClientTest, | 531 TEST_P(LogDnsClientTest, |
586 QueryAuditProofReportsInvalidArgIfLeafIndexGreaterThanTreeSize) { | 532 QueryAuditProofReportsInvalidArgIfLeafIndexGreaterThanTreeSize) { |
| 533 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 999999); |
| 534 |
587 MockAuditProofCallback callback; | 535 MockAuditProofCallback callback; |
588 QueryAuditProof("ct.test", 999999, 123456, &callback); | 536 QueryAuditProof("ct.test", kLeafHashes[0], 123456, &callback); |
589 ASSERT_TRUE(callback.called()); | 537 ASSERT_TRUE(callback.called()); |
590 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); | 538 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
591 EXPECT_THAT(callback.proof(), IsNull()); | 539 EXPECT_THAT(callback.proof(), IsNull()); |
592 } | 540 } |
593 | 541 |
594 TEST_P(LogDnsClientTest, QueryAuditProofReportsSocketError) { | 542 TEST_P(LogDnsClientTest, |
| 543 QueryAuditProofReportsSocketErrorsDuringAuditProofRequests) { |
| 544 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
595 mock_dns_.ExpectRequestAndSocketError("0.123456.999999.tree.ct.test.", | 545 mock_dns_.ExpectRequestAndSocketError("0.123456.999999.tree.ct.test.", |
596 net::ERR_CONNECTION_REFUSED); | 546 net::ERR_CONNECTION_REFUSED); |
597 | 547 |
598 MockAuditProofCallback callback; | 548 MockAuditProofCallback callback; |
599 QueryAuditProof("ct.test", 123456, 999999, &callback); | 549 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
600 ASSERT_TRUE(callback.called()); | 550 ASSERT_TRUE(callback.called()); |
601 EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); | 551 EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); |
602 EXPECT_THAT(callback.proof(), IsNull()); | 552 EXPECT_THAT(callback.proof(), IsNull()); |
603 } | 553 } |
604 | 554 |
605 TEST_P(LogDnsClientTest, QueryAuditProofReportsTimeout) { | 555 TEST_P(LogDnsClientTest, |
| 556 QueryAuditProofReportsTimeoutsDuringAuditProofRequests) { |
| 557 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
606 mock_dns_.ExpectRequestAndTimeout("0.123456.999999.tree.ct.test."); | 558 mock_dns_.ExpectRequestAndTimeout("0.123456.999999.tree.ct.test."); |
607 | 559 |
608 MockAuditProofCallback callback; | 560 MockAuditProofCallback callback; |
609 QueryAuditProof("ct.test", 123456, 999999, &callback); | 561 QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
610 ASSERT_TRUE(callback.called()); | 562 ASSERT_TRUE(callback.called()); |
611 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); | 563 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); |
612 EXPECT_THAT(callback.proof(), IsNull()); | 564 EXPECT_THAT(callback.proof(), IsNull()); |
613 } | 565 } |
614 | 566 |
615 TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) { | 567 TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) { |
616 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); | 568 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); |
617 net::DnsClient* dns_client = tmp.get(); | 569 net::DnsClient* dns_client = tmp.get(); |
618 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource(), 0); | 570 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource(), 0); |
619 | 571 |
(...skipping 17 matching lines...) Expand all Loading... |
637 net::DnsConfig config(*dns_client->GetConfig()); | 589 net::DnsConfig config(*dns_client->GetConfig()); |
638 ASSERT_THAT(config.nameservers, Not(IsEmpty())); | 590 ASSERT_THAT(config.nameservers, Not(IsEmpty())); |
639 config.nameservers.clear(); // Makes config invalid | 591 config.nameservers.clear(); // Makes config invalid |
640 mock_dns_.SetDnsConfig(config); | 592 mock_dns_.SetDnsConfig(config); |
641 | 593 |
642 // Let the DNS config change propogate. | 594 // Let the DNS config change propogate. |
643 base::RunLoop().RunUntilIdle(); | 595 base::RunLoop().RunUntilIdle(); |
644 EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty())); | 596 EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty())); |
645 } | 597 } |
646 | 598 |
647 TEST_P(LogDnsClientTest, CanPerformLeafIndexQueriesInParallel) { | 599 // Test that changes to the DNS config after starting a query are adopted and |
648 // Test that leaf index queries can be performed in parallel. | 600 // that the query is not disrupted. |
649 constexpr size_t kNumOfParallelQueries = 3; | 601 TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigMidQuery) { |
650 ASSERT_THAT(kNumOfParallelQueries, AllOf(Le(arraysize(kLeafHashes)), | 602 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); |
651 Le(arraysize(kBase32LeafHashes)))) | |
652 << "Not enough test data for this many parallel queries"; | |
653 | 603 |
654 std::unique_ptr<LogDnsClient> log_client = | 604 // Expect a leaf index query first, to map the leaf hash to a leaf index. |
655 CreateLogDnsClient(kNumOfParallelQueries); | 605 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
656 MockLeafIndexCallback callbacks[kNumOfParallelQueries]; | |
657 | 606 |
658 // Expect multiple queries. | 607 // It takes a number of DNS requests to retrieve the entire |audit_proof| |
659 for (size_t i = 0; i < kNumOfParallelQueries; ++i) { | 608 // (see |kMaxProofNodesPerDnsResponse|). |
660 mock_dns_.ExpectLeafIndexRequestAndResponse( | 609 for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); |
661 kBase32LeafHashes[i], kLeafIndices[i]); | 610 nodes_begin += kMaxProofNodesPerDnsResponse) { |
| 611 const size_t nodes_end = std::min( |
| 612 nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); |
| 613 |
| 614 mock_dns_.ExpectAuditProofRequestAndResponse( |
| 615 base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), |
| 616 audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end); |
662 } | 617 } |
663 | 618 |
664 // Start the queries. | 619 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); |
665 for (size_t i = 0; i < kNumOfParallelQueries; ++i) { | 620 net::DnsClient* dns_client = tmp.get(); |
666 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[i], | 621 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource(), 0); |
667 callbacks[i].AsCallback()); | |
668 } | |
669 | 622 |
670 // Wait for each query to complete and check its results. | 623 // Start query. |
671 for (size_t i = 0; i < kNumOfParallelQueries; ++i) { | 624 MockAuditProofCallback callback; |
672 MockLeafIndexCallback& callback = callbacks[i]; | 625 QueryAuditProofAsync(&log_client, "ct.test", kLeafHashes[0], 999999, |
673 callback.WaitUntilRun(); | 626 callback.AsCallback()); |
674 | 627 |
675 SCOPED_TRACE(testing::Message() << "callbacks[" << i << "]"); | 628 // Get the current DNS config, modify it and broadcast the update. |
676 ASSERT_TRUE(callback.called()); | 629 net::DnsConfig config(*dns_client->GetConfig()); |
677 EXPECT_THAT(callback.net_error(), IsOk()); | 630 ASSERT_NE(123, config.attempts); |
678 EXPECT_THAT(callback.leaf_index(), Eq(kLeafIndices[i])); | 631 config.attempts = 123; |
679 } | 632 mock_dns_.SetDnsConfig(config); |
| 633 |
| 634 callback.WaitUntilRun(); |
| 635 // Check that the DNS changes propogated before the query completed. |
| 636 EXPECT_EQ(123, dns_client->GetConfig()->attempts); |
| 637 |
| 638 ASSERT_TRUE(callback.called()); |
| 639 EXPECT_THAT(callback.net_error(), IsOk()); |
| 640 ASSERT_THAT(callback.proof(), NotNull()); |
| 641 EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u)); |
| 642 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
| 643 // EXPECT_THAT(callback.proof()->tree_size, Eq(999999)); |
| 644 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof)); |
680 } | 645 } |
681 | 646 |
682 TEST_P(LogDnsClientTest, CanPerformAuditProofQueriesInParallel) { | 647 TEST_P(LogDnsClientTest, CanPerformQueriesInParallel) { |
683 // Check that 3 audit proof queries can be performed in parallel. | 648 // Check that 3 queries can be performed in parallel. |
684 constexpr size_t kNumOfParallelQueries = 3; | 649 constexpr size_t kNumOfParallelQueries = 3; |
685 ASSERT_THAT(kNumOfParallelQueries, | 650 ASSERT_THAT(kNumOfParallelQueries, |
686 AllOf(Le(arraysize(kLeafIndices)), Le(arraysize(kTreeSizes)))) | 651 AllOf(Le(arraysize(kLeafIndexQnames)), |
| 652 Le(arraysize(kLeafIndices)), Le(arraysize(kTreeSizes)))) |
687 << "Not enough test data for this many parallel queries"; | 653 << "Not enough test data for this many parallel queries"; |
688 | 654 |
689 std::unique_ptr<LogDnsClient> log_client = | 655 std::unique_ptr<LogDnsClient> log_client = |
690 CreateLogDnsClient(kNumOfParallelQueries); | 656 CreateLogDnsClient(kNumOfParallelQueries); |
691 MockAuditProofCallback callbacks[kNumOfParallelQueries]; | 657 MockAuditProofCallback callbacks[kNumOfParallelQueries]; |
692 | 658 |
693 // Each query should require one more DNS request than the last. | 659 // Expect multiple leaf index requests. |
694 // This helps to test that parallel queries do not intefere with each other, | 660 for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
695 // e.g. one query causing another to end prematurely. | 661 mock_dns_.ExpectLeafIndexRequestAndResponse( |
| 662 kLeafIndexQnames[i], kLeafIndices[i]); |
| 663 } |
| 664 |
| 665 // Make each query require one more audit proof request than the last, by |
| 666 // increasing the number of nodes in the audit proof by |
| 667 // kMaxProofNodesPerDnsResponse for each query. This helps to test that |
| 668 // parallel queries do not intefere with each other, e.g. one query causing |
| 669 // another to end prematurely. |
696 std::vector<std::string> audit_proofs[kNumOfParallelQueries]; | 670 std::vector<std::string> audit_proofs[kNumOfParallelQueries]; |
697 for (size_t query_i = 0; query_i < kNumOfParallelQueries; ++query_i) { | 671 for (size_t query_i = 0; query_i < kNumOfParallelQueries; ++query_i) { |
698 const size_t dns_requests_required = query_i + 1; | 672 const size_t dns_requests_required = query_i + 1; |
699 audit_proofs[query_i] = GetSampleAuditProof(dns_requests_required * | 673 audit_proofs[query_i] = GetSampleAuditProof(dns_requests_required * |
700 kMaxProofNodesPerDnsResponse); | 674 kMaxProofNodesPerDnsResponse); |
701 } | 675 } |
702 // The most DNS requests that are made by any of the above N queries is N. | 676 // The most DNS requests that are made by any of the above N queries is N. |
703 const size_t kMaxDnsRequestsPerQuery = kNumOfParallelQueries; | 677 const size_t kMaxDnsRequestsPerQuery = kNumOfParallelQueries; |
704 | 678 |
705 // Setup expectations for up to N DNS requests per query performed. | 679 // Setup expectations for up to N DNS requests per query performed. |
(...skipping 17 matching lines...) Expand all Loading... |
723 base::StringPrintf("%zu.%" PRIu64 ".%" PRIu64 ".tree.ct.test.", | 697 base::StringPrintf("%zu.%" PRIu64 ".%" PRIu64 ".tree.ct.test.", |
724 start_node, kLeafIndices[query_i], | 698 start_node, kLeafIndices[query_i], |
725 kTreeSizes[query_i]), | 699 kTreeSizes[query_i]), |
726 proof.begin() + start_node, proof.begin() + end_node); | 700 proof.begin() + start_node, proof.begin() + end_node); |
727 } | 701 } |
728 } | 702 } |
729 } | 703 } |
730 | 704 |
731 // Start the queries. | 705 // Start the queries. |
732 for (size_t i = 0; i < kNumOfParallelQueries; ++i) { | 706 for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
733 QueryAuditProofAsync(log_client.get(), "ct.test", kLeafIndices[i], | 707 QueryAuditProofAsync(log_client.get(), "ct.test", kLeafHashes[i], |
734 kTreeSizes[i], callbacks[i].AsCallback()); | 708 kTreeSizes[i], callbacks[i].AsCallback()); |
735 } | 709 } |
736 | 710 |
737 // Wait for each query to complete and check its results. | 711 // Wait for each query to complete and check its results. |
738 for (size_t i = 0; i < kNumOfParallelQueries; ++i) { | 712 for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
739 MockAuditProofCallback& callback = callbacks[i]; | 713 MockAuditProofCallback& callback = callbacks[i]; |
740 callbacks[i].WaitUntilRun(); | 714 callbacks[i].WaitUntilRun(); |
741 | 715 |
742 SCOPED_TRACE(testing::Message() << "callbacks[" << i << "]"); | 716 SCOPED_TRACE(testing::Message() << "callbacks[" << i << "]"); |
743 ASSERT_TRUE(callback.called()); | 717 ASSERT_TRUE(callback.called()); |
744 EXPECT_THAT(callback.net_error(), IsOk()); | 718 EXPECT_THAT(callback.net_error(), IsOk()); |
745 ASSERT_THAT(callback.proof(), NotNull()); | 719 ASSERT_THAT(callback.proof(), NotNull()); |
746 EXPECT_THAT(callback.proof()->leaf_index, Eq(kLeafIndices[i])); | 720 EXPECT_THAT(callback.proof()->leaf_index, Eq(kLeafIndices[i])); |
747 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. | 721 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
748 // EXPECT_THAT(callback.proof()->tree_size, kTreeSizes[i]); | 722 // EXPECT_THAT(callback.proof()->tree_size, kTreeSizes[i]); |
749 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proofs[i])); | 723 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proofs[i])); |
750 } | 724 } |
751 } | 725 } |
752 | 726 |
753 TEST_P(LogDnsClientTest, CanPerformLeafIndexAndAuditProofQueriesInParallel) { | 727 TEST_P(LogDnsClientTest, CanBeThrottledToOneQueryAtATime) { |
754 // Check that a leaf index and audit proof query can be performed in parallel. | 728 // Check that queries can be rate-limited to one at a time. |
755 constexpr size_t kNumOfParallelQueries = 2; | 729 // The second query, initiated while the first is in progress, should fail. |
756 std::unique_ptr<LogDnsClient> log_client = | |
757 CreateLogDnsClient(kNumOfParallelQueries); | |
758 MockLeafIndexCallback leaf_index_callback; | |
759 MockAuditProofCallback audit_proof_callback; | |
760 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); | 730 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); |
761 | 731 |
762 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], 123456); | 732 // Expect the first query to send leaf index and audit proof requests, but the |
763 | 733 // second should not due to throttling. |
764 // It should require 3 requests to collect the entire audit proof, as there is | 734 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
765 // only space for 7 nodes per TXT record. One node is 32 bytes long and the | |
766 // TXT RDATA can have a maximum length of 255 bytes (255 / 32). | |
767 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", | |
768 audit_proof.begin(), | |
769 audit_proof.begin() + 7); | |
770 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.", | |
771 audit_proof.begin() + 7, | |
772 audit_proof.begin() + 14); | |
773 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.", | |
774 audit_proof.begin() + 14, | |
775 audit_proof.end()); | |
776 | |
777 // Start the queries. | |
778 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[0], | |
779 leaf_index_callback.AsCallback()); | |
780 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999, | |
781 audit_proof_callback.AsCallback()); | |
782 | |
783 // Wait for the queries to complete, then check their results. | |
784 leaf_index_callback.WaitUntilRun(); | |
785 audit_proof_callback.WaitUntilRun(); | |
786 | |
787 ASSERT_TRUE(leaf_index_callback.called()); | |
788 EXPECT_THAT(leaf_index_callback.net_error(), IsOk()); | |
789 EXPECT_THAT(leaf_index_callback.leaf_index(), Eq(123456u)); | |
790 | |
791 ASSERT_TRUE(audit_proof_callback.called()); | |
792 EXPECT_THAT(audit_proof_callback.net_error(), IsOk()); | |
793 ASSERT_THAT(audit_proof_callback.proof(), NotNull()); | |
794 EXPECT_THAT(audit_proof_callback.proof()->leaf_index, Eq(123456u)); | |
795 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. | |
796 // EXPECT_THAT(audit_proof_callback.proof()->tree_size, Eq(999999)); | |
797 EXPECT_THAT(audit_proof_callback.proof()->nodes, Eq(audit_proof)); | |
798 } | |
799 | |
800 TEST_P(LogDnsClientTest, CanBeThrottledToOneLeafIndexQueryAtATime) { | |
801 // Check that leaf index queries can be rate-limited to one at a time. | |
802 // The second query, initiated while the first is in progress, should fail. | |
803 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], 123456); | |
804 | |
805 const size_t max_concurrent_queries = 1; | |
806 std::unique_ptr<LogDnsClient> log_client = | |
807 CreateLogDnsClient(max_concurrent_queries); | |
808 | |
809 // Start the queries. | |
810 MockLeafIndexCallback callback1; | |
811 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[0], | |
812 callback1.AsCallback()); | |
813 MockLeafIndexCallback callback2; | |
814 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[1], | |
815 callback2.AsCallback()); | |
816 | |
817 callback1.WaitUntilRun(); | |
818 callback2.WaitUntilRun(); | |
819 | |
820 // Check that the first query succeeded. | |
821 ASSERT_TRUE(callback1.called()); | |
822 EXPECT_THAT(callback1.net_error(), IsOk()); | |
823 EXPECT_THAT(callback1.leaf_index(), Eq(123456u)); | |
824 | |
825 // Check that the second query failed. | |
826 ASSERT_TRUE(callback2.called()); | |
827 EXPECT_THAT(callback2.net_error(), IsError(net::ERR_TEMPORARILY_THROTTLED)); | |
828 EXPECT_THAT(callback2.leaf_index(), Eq(0u)); | |
829 | |
830 // Try a third query, which should succeed now that the first is finished. | |
831 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[2], 666); | |
832 | |
833 MockLeafIndexCallback callback3; | |
834 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[2], | |
835 callback3.AsCallback()); | |
836 | |
837 callback3.WaitUntilRun(); | |
838 | |
839 // Check that the third query succeeded. | |
840 ASSERT_TRUE(callback3.called()); | |
841 EXPECT_THAT(callback3.net_error(), IsOk()); | |
842 EXPECT_THAT(callback3.leaf_index(), Eq(666u)); | |
843 } | |
844 | |
845 TEST_P(LogDnsClientTest, CanBeThrottledToOneAuditProofQueryAtATime) { | |
846 // Check that audit proof queries can be rate-limited to one at a time. | |
847 // The second query, initiated while the first is in progress, should fail. | |
848 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); | |
849 | 735 |
850 // It should require 3 requests to collect the entire audit proof, as there is | 736 // It should require 3 requests to collect the entire audit proof, as there is |
851 // only space for 7 nodes per TXT record. One node is 32 bytes long and the | 737 // only space for 7 nodes per TXT record. One node is 32 bytes long and the |
852 // TXT RDATA can have a maximum length of 255 bytes (255 / 32). | 738 // TXT RDATA can have a maximum length of 255 bytes (255 / 32). |
853 // Rate limiting should not interfere with these requests. | 739 // Rate limiting should not interfere with these requests. |
854 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", | 740 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", |
855 audit_proof.begin(), | 741 audit_proof.begin(), |
856 audit_proof.begin() + 7); | 742 audit_proof.begin() + 7); |
857 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.", | 743 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.", |
858 audit_proof.begin() + 7, | 744 audit_proof.begin() + 7, |
859 audit_proof.begin() + 14); | 745 audit_proof.begin() + 14); |
860 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.", | 746 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.", |
861 audit_proof.begin() + 14, | 747 audit_proof.begin() + 14, |
862 audit_proof.end()); | 748 audit_proof.end()); |
863 | 749 |
864 const size_t max_concurrent_queries = 1; | 750 const size_t kMaxConcurrentQueries = 1; |
865 std::unique_ptr<LogDnsClient> log_client = | 751 std::unique_ptr<LogDnsClient> log_client = |
866 CreateLogDnsClient(max_concurrent_queries); | 752 CreateLogDnsClient(kMaxConcurrentQueries); |
867 | 753 |
868 // Start the queries. | 754 // Start the queries. |
869 MockAuditProofCallback callback1; | 755 MockAuditProofCallback callback1; |
870 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999, | 756 QueryAuditProofAsync(log_client.get(), "ct.test", kLeafHashes[0], 999999, |
871 callback1.AsCallback()); | 757 callback1.AsCallback()); |
872 MockAuditProofCallback callback2; | 758 MockAuditProofCallback callback2; |
873 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999, | 759 QueryAuditProofAsync(log_client.get(), "ct.test", kLeafHashes[1], 999999, |
874 callback2.AsCallback()); | 760 callback2.AsCallback()); |
875 | 761 |
876 callback1.WaitUntilRun(); | 762 callback1.WaitUntilRun(); |
877 callback2.WaitUntilRun(); | 763 callback2.WaitUntilRun(); |
878 | 764 |
879 // Check that the first query succeeded. | 765 // Check that the first query succeeded. |
880 ASSERT_TRUE(callback1.called()); | 766 ASSERT_TRUE(callback1.called()); |
881 EXPECT_THAT(callback1.net_error(), IsOk()); | 767 EXPECT_THAT(callback1.net_error(), IsOk()); |
882 ASSERT_THAT(callback1.proof(), NotNull()); | 768 ASSERT_THAT(callback1.proof(), NotNull()); |
883 EXPECT_THAT(callback1.proof()->leaf_index, Eq(123456u)); | 769 EXPECT_THAT(callback1.proof()->leaf_index, Eq(123456u)); |
884 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. | 770 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
885 // EXPECT_THAT(callback1.proof()->tree_size, Eq(999999)); | 771 // EXPECT_THAT(callback1.proof()->tree_size, Eq(999999)); |
886 EXPECT_THAT(callback1.proof()->nodes, Eq(audit_proof)); | 772 EXPECT_THAT(callback1.proof()->nodes, Eq(audit_proof)); |
887 | 773 |
888 // Check that the second query failed. | 774 // Check that the second query failed. |
889 ASSERT_TRUE(callback2.called()); | 775 ASSERT_TRUE(callback2.called()); |
890 EXPECT_THAT(callback2.net_error(), IsError(net::ERR_TEMPORARILY_THROTTLED)); | 776 EXPECT_THAT(callback2.net_error(), IsError(net::ERR_TEMPORARILY_THROTTLED)); |
891 EXPECT_THAT(callback2.proof(), IsNull()); | 777 EXPECT_THAT(callback2.proof(), IsNull()); |
892 | 778 |
893 // Try a third query, which should succeed now that the first is finished. | 779 // Try a third query, which should succeed now that the first is finished. |
894 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", | 780 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[2], 666); |
| 781 mock_dns_.ExpectAuditProofRequestAndResponse("0.666.999999.tree.ct.test.", |
895 audit_proof.begin(), | 782 audit_proof.begin(), |
896 audit_proof.begin() + 7); | 783 audit_proof.begin() + 7); |
897 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.", | 784 mock_dns_.ExpectAuditProofRequestAndResponse("7.666.999999.tree.ct.test.", |
898 audit_proof.begin() + 7, | 785 audit_proof.begin() + 7, |
899 audit_proof.begin() + 14); | 786 audit_proof.begin() + 14); |
900 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.", | 787 mock_dns_.ExpectAuditProofRequestAndResponse("14.666.999999.tree.ct.test.", |
901 audit_proof.begin() + 14, | 788 audit_proof.begin() + 14, |
902 audit_proof.end()); | 789 audit_proof.end()); |
903 | 790 |
904 MockAuditProofCallback callback3; | 791 MockAuditProofCallback callback3; |
905 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999, | 792 QueryAuditProofAsync(log_client.get(), "ct.test", kLeafHashes[2], 999999, |
906 callback3.AsCallback()); | 793 callback3.AsCallback()); |
907 | 794 |
908 callback3.WaitUntilRun(); | 795 callback3.WaitUntilRun(); |
909 | 796 |
910 // Check that the third query succeeded. | 797 // Check that the third query succeeded. |
911 ASSERT_TRUE(callback3.called()); | 798 ASSERT_TRUE(callback3.called()); |
912 EXPECT_THAT(callback3.net_error(), IsOk()); | 799 EXPECT_THAT(callback3.net_error(), IsOk()); |
913 ASSERT_THAT(callback3.proof(), NotNull()); | 800 ASSERT_THAT(callback3.proof(), NotNull()); |
914 EXPECT_THAT(callback3.proof()->leaf_index, Eq(123456u)); | 801 EXPECT_THAT(callback3.proof()->leaf_index, Eq(666u)); |
915 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. | 802 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
916 // EXPECT_THAT(callback3.proof()->tree_size, Eq(999999)); | 803 // EXPECT_THAT(callback3.proof()->tree_size, Eq(999999)); |
917 EXPECT_THAT(callback3.proof()->nodes, Eq(audit_proof)); | 804 EXPECT_THAT(callback3.proof()->nodes, Eq(audit_proof)); |
918 } | 805 } |
919 | 806 |
920 TEST_P(LogDnsClientTest, ThrottlingAppliesAcrossQueryTypes) { | |
921 // Check that queries can be rate-limited to one at a time, regardless of the | |
922 // type of query. The second query, initiated while the first is in progress, | |
923 // should fail. | |
924 mock_dns_.ExpectLeafIndexRequestAndResponse( | |
925 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", | |
926 123456); | |
927 | |
928 const size_t max_concurrent_queries = 1; | |
929 std::unique_ptr<LogDnsClient> log_client = | |
930 CreateLogDnsClient(max_concurrent_queries); | |
931 | |
932 // Start the queries. | |
933 MockLeafIndexCallback leaf_index_callback; | |
934 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[0], | |
935 leaf_index_callback.AsCallback()); | |
936 MockAuditProofCallback audit_proof_callback; | |
937 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999, | |
938 audit_proof_callback.AsCallback()); | |
939 | |
940 leaf_index_callback.WaitUntilRun(); | |
941 audit_proof_callback.WaitUntilRun(); | |
942 | |
943 // Check that the first query succeeded. | |
944 ASSERT_TRUE(leaf_index_callback.called()); | |
945 EXPECT_THAT(leaf_index_callback.net_error(), IsOk()); | |
946 EXPECT_THAT(leaf_index_callback.leaf_index(), Eq(123456u)); | |
947 | |
948 // Check that the second query failed. | |
949 ASSERT_TRUE(audit_proof_callback.called()); | |
950 EXPECT_THAT(audit_proof_callback.net_error(), | |
951 IsError(net::ERR_TEMPORARILY_THROTTLED)); | |
952 EXPECT_THAT(audit_proof_callback.proof(), IsNull()); | |
953 } | |
954 | |
955 INSTANTIATE_TEST_CASE_P(ReadMode, | 807 INSTANTIATE_TEST_CASE_P(ReadMode, |
956 LogDnsClientTest, | 808 LogDnsClientTest, |
957 ::testing::Values(net::IoMode::ASYNC, | 809 ::testing::Values(net::IoMode::ASYNC, |
958 net::IoMode::SYNCHRONOUS)); | 810 net::IoMode::SYNCHRONOUS)); |
959 | 811 |
960 } // namespace | 812 } // namespace |
961 } // namespace certificate_transparency | 813 } // namespace certificate_transparency |
OLD | NEW |