| 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 |