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 <algorithm> | 7 #include <algorithm> |
8 #include <numeric> | 8 #include <numeric> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "net/dns/dns_protocol.h" | 25 #include "net/dns/dns_protocol.h" |
26 #include "net/log/net_log.h" | 26 #include "net/log/net_log.h" |
27 #include "net/socket/socket_test_util.h" | 27 #include "net/socket/socket_test_util.h" |
28 #include "net/test/gtest_util.h" | 28 #include "net/test/gtest_util.h" |
29 #include "testing/gmock/include/gmock/gmock.h" | 29 #include "testing/gmock/include/gmock/gmock.h" |
30 #include "testing/gtest/include/gtest/gtest.h" | 30 #include "testing/gtest/include/gtest/gtest.h" |
31 | 31 |
32 namespace certificate_transparency { | 32 namespace certificate_transparency { |
33 namespace { | 33 namespace { |
34 | 34 |
| 35 using ::testing::IsEmpty; |
35 using ::testing::IsNull; | 36 using ::testing::IsNull; |
| 37 using ::testing::Not; |
36 using ::testing::NotNull; | 38 using ::testing::NotNull; |
37 using net::test::IsError; | 39 using net::test::IsError; |
38 using net::test::IsOk; | 40 using net::test::IsOk; |
39 | 41 |
40 constexpr char kLeafHash[] = | 42 constexpr char kLeafHash[] = |
41 "\x1f\x25\xe1\xca\xba\x4f\xf9\xb8\x27\x24\x83\x0f\xca\x60\xe4\xc2\xbe\xa8" | 43 "\x1f\x25\xe1\xca\xba\x4f\xf9\xb8\x27\x24\x83\x0f\xca\x60\xe4\xc2\xbe\xa8" |
42 "\xc3\xa9\x44\x1c\x27\xb0\xb4\x3e\x6a\x96\x94\xc7\xb8\x04"; | 44 "\xc3\xa9\x44\x1c\x27\xb0\xb4\x3e\x6a\x96\x94\xc7\xb8\x04"; |
43 | 45 |
| 46 // Necessary to expose SetDnsConfig for testing. |
| 47 class DnsChangeNotifier : public net::NetworkChangeNotifier { |
| 48 public: |
| 49 static void SetInitialDnsConfig(const net::DnsConfig& config) { |
| 50 net::NetworkChangeNotifier::SetInitialDnsConfig(config); |
| 51 } |
| 52 |
| 53 static void SetDnsConfig(const net::DnsConfig& config) { |
| 54 net::NetworkChangeNotifier::SetDnsConfig(config); |
| 55 } |
| 56 }; |
| 57 |
44 // Always return min, to simplify testing. | 58 // Always return min, to simplify testing. |
45 // This should result in the DNS query ID always being 0. | 59 // This should result in the DNS query ID always being 0. |
46 int FakeRandInt(int min, int max) { | 60 int FakeRandInt(int min, int max) { |
47 return min; | 61 return min; |
48 } | 62 } |
49 | 63 |
50 std::vector<char> CreateDnsTxtRequest(base::StringPiece qname) { | 64 std::vector<char> CreateDnsTxtRequest(base::StringPiece qname) { |
51 std::string encoded_qname; | 65 std::string encoded_qname; |
52 EXPECT_TRUE(net::DNSDomainFromDot(qname, &encoded_qname)); | 66 EXPECT_TRUE(net::DNSDomainFromDot(qname, &encoded_qname)); |
53 | 67 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 | 266 |
253 DISALLOW_COPY_AND_ASSIGN(MockSocketData); | 267 DISALLOW_COPY_AND_ASSIGN(MockSocketData); |
254 }; | 268 }; |
255 | 269 |
256 const net::MockRead MockSocketData::eof_(net::SYNCHRONOUS, | 270 const net::MockRead MockSocketData::eof_(net::SYNCHRONOUS, |
257 net::ERR_IO_PENDING, | 271 net::ERR_IO_PENDING, |
258 2); | 272 2); |
259 | 273 |
260 class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> { | 274 class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> { |
261 protected: | 275 protected: |
262 LogDnsClientTest() { | 276 LogDnsClientTest() : |
| 277 network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) { |
| 278 net::DnsConfig dns_config; |
263 // Use an invalid nameserver address. This prevents the tests accidentally | 279 // Use an invalid nameserver address. This prevents the tests accidentally |
264 // sending real DNS queries. The mock sockets don't care that the address | 280 // sending real DNS queries. The mock sockets don't care that the address |
265 // is invalid. | 281 // is invalid. |
266 dns_config_.nameservers.push_back(net::IPEndPoint()); | 282 dns_config.nameservers.push_back(net::IPEndPoint()); |
267 // Don't attempt retransmissions - just fail. | 283 // Don't attempt retransmissions - just fail. |
268 dns_config_.attempts = 1; | 284 dns_config.attempts = 1; |
269 // This ensures timeouts are long enough for memory tests. | 285 // This ensures timeouts are long enough for memory tests. |
270 dns_config_.timeout = TestTimeouts::action_timeout(); | 286 dns_config.timeout = TestTimeouts::action_timeout(); |
271 // Simplify testing - don't require random numbers for the source port. | 287 // Simplify testing - don't require random numbers for the source port. |
272 // This means our FakeRandInt function should only be called to get query | 288 // This means our FakeRandInt function should only be called to get query |
273 // IDs. | 289 // IDs. |
274 dns_config_.randomize_ports = false; | 290 dns_config.randomize_ports = false; |
| 291 |
| 292 DnsChangeNotifier::SetInitialDnsConfig(dns_config); |
275 } | 293 } |
276 | 294 |
277 void ExpectRequestAndErrorResponse(base::StringPiece qname, uint8_t rcode) { | 295 void ExpectRequestAndErrorResponse(base::StringPiece qname, uint8_t rcode) { |
278 std::vector<char> request = CreateDnsTxtRequest(qname); | 296 std::vector<char> request = CreateDnsTxtRequest(qname); |
279 std::vector<char> response = CreateDnsErrorResponse(request, rcode); | 297 std::vector<char> response = CreateDnsErrorResponse(request, rcode); |
280 | 298 |
281 mock_socket_data_.emplace_back(new MockSocketData(request, response)); | 299 mock_socket_data_.emplace_back(new MockSocketData(request, response)); |
282 mock_socket_data_.back()->SetReadMode(GetParam()); | 300 mock_socket_data_.back()->SetReadMode(GetParam()); |
283 mock_socket_data_.back()->AddToFactory(&socket_factory_); | 301 mock_socket_data_.back()->AddToFactory(&socket_factory_); |
284 } | 302 } |
285 | 303 |
286 void ExpectRequestAndSocketError(base::StringPiece qname, int net_error) { | 304 void ExpectRequestAndSocketError(base::StringPiece qname, int net_error) { |
287 std::vector<char> request = CreateDnsTxtRequest(qname); | 305 std::vector<char> request = CreateDnsTxtRequest(qname); |
288 | 306 |
289 mock_socket_data_.emplace_back(new MockSocketData(request, net_error)); | 307 mock_socket_data_.emplace_back(new MockSocketData(request, net_error)); |
290 mock_socket_data_.back()->SetReadMode(GetParam()); | 308 mock_socket_data_.back()->SetReadMode(GetParam()); |
291 mock_socket_data_.back()->AddToFactory(&socket_factory_); | 309 mock_socket_data_.back()->AddToFactory(&socket_factory_); |
292 } | 310 } |
293 | 311 |
294 void ExpectRequestAndTimeout(base::StringPiece qname) { | 312 void ExpectRequestAndTimeout(base::StringPiece qname) { |
295 std::vector<char> request = CreateDnsTxtRequest(qname); | 313 std::vector<char> request = CreateDnsTxtRequest(qname); |
296 | 314 |
297 mock_socket_data_.emplace_back(new MockSocketData(request)); | 315 mock_socket_data_.emplace_back(new MockSocketData(request)); |
298 mock_socket_data_.back()->SetReadMode(GetParam()); | 316 mock_socket_data_.back()->SetReadMode(GetParam()); |
299 mock_socket_data_.back()->AddToFactory(&socket_factory_); | 317 mock_socket_data_.back()->AddToFactory(&socket_factory_); |
300 | 318 |
301 // Speed up timeout tests. | 319 // Speed up timeout tests. |
302 dns_config_.timeout = TestTimeouts::tiny_timeout(); | 320 net::DnsConfig dns_config; |
| 321 DnsChangeNotifier::GetDnsConfig(&dns_config); |
| 322 dns_config.timeout = TestTimeouts::tiny_timeout(); |
| 323 DnsChangeNotifier::SetDnsConfig(dns_config); |
303 } | 324 } |
304 | 325 |
305 void ExpectLeafIndexRequestAndResponse(base::StringPiece qname, | 326 void ExpectLeafIndexRequestAndResponse(base::StringPiece qname, |
306 base::StringPiece leaf_index) { | 327 base::StringPiece leaf_index) { |
307 // Prepend size to leaf_index to create the query answer (rdata) | 328 // Prepend size to leaf_index to create the query answer (rdata) |
308 ASSERT_LE(leaf_index.size(), 0xFFul); // size must fit into a single byte | 329 ASSERT_LE(leaf_index.size(), 0xFFul); // size must fit into a single byte |
309 std::string answer = leaf_index.as_string(); | 330 std::string answer = leaf_index.as_string(); |
310 answer.insert(answer.begin(), static_cast<char>(leaf_index.size())); | 331 answer.insert(answer.begin(), static_cast<char>(leaf_index.size())); |
311 | 332 |
312 ExpectRequestAndResponse(qname, answer); | 333 ExpectRequestAndResponse(qname, answer); |
(...skipping 12 matching lines...) Expand all Loading... |
325 proof.insert(proof.begin(), static_cast<char>(proof.size())); | 346 proof.insert(proof.begin(), static_cast<char>(proof.size())); |
326 | 347 |
327 ExpectRequestAndResponse(qname, proof); | 348 ExpectRequestAndResponse(qname, proof); |
328 } | 349 } |
329 | 350 |
330 void QueryLeafIndex(base::StringPiece log_domain, | 351 void QueryLeafIndex(base::StringPiece log_domain, |
331 base::StringPiece leaf_hash, | 352 base::StringPiece leaf_hash, |
332 MockLeafIndexCallback* callback) { | 353 MockLeafIndexCallback* callback) { |
333 std::unique_ptr<net::DnsClient> dns_client = CreateDnsClient(); | 354 std::unique_ptr<net::DnsClient> dns_client = CreateDnsClient(); |
334 LogDnsClient log_client(std::move(dns_client), net::BoundNetLog()); | 355 LogDnsClient log_client(std::move(dns_client), net::BoundNetLog()); |
| 356 net::NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigReadForTests(); |
335 | 357 |
336 log_client.QueryLeafIndex(log_domain, leaf_hash, callback->AsCallback()); | 358 log_client.QueryLeafIndex(log_domain, leaf_hash, callback->AsCallback()); |
337 callback->WaitUntilRun(); | 359 callback->WaitUntilRun(); |
338 } | 360 } |
339 | 361 |
340 void QueryAuditProof(base::StringPiece log_domain, | 362 void QueryAuditProof(base::StringPiece log_domain, |
341 uint64_t leaf_index, | 363 uint64_t leaf_index, |
342 uint64_t tree_size, | 364 uint64_t tree_size, |
343 MockAuditProofCallback* callback) { | 365 MockAuditProofCallback* callback) { |
344 std::unique_ptr<net::DnsClient> dns_client = CreateDnsClient(); | 366 std::unique_ptr<net::DnsClient> dns_client = CreateDnsClient(); |
345 LogDnsClient log_client(std::move(dns_client), net::BoundNetLog()); | 367 LogDnsClient log_client(std::move(dns_client), net::BoundNetLog()); |
| 368 net::NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigReadForTests(); |
346 | 369 |
347 log_client.QueryAuditProof(log_domain, leaf_index, tree_size, | 370 log_client.QueryAuditProof(log_domain, leaf_index, tree_size, |
348 callback->AsCallback()); | 371 callback->AsCallback()); |
349 callback->WaitUntilRun(); | 372 callback->WaitUntilRun(); |
350 } | 373 } |
351 | 374 |
| 375 std::unique_ptr<net::DnsClient> CreateDnsClient() { |
| 376 return net::DnsClient::CreateClientForTesting(nullptr, &socket_factory_, |
| 377 base::Bind(&FakeRandInt)); |
| 378 } |
| 379 |
352 private: | 380 private: |
353 std::unique_ptr<net::DnsClient> CreateDnsClient() { | |
354 std::unique_ptr<net::DnsClient> client = | |
355 net::DnsClient::CreateClientForTesting(nullptr, &socket_factory_, | |
356 base::Bind(&FakeRandInt)); | |
357 client->SetConfig(dns_config_); | |
358 return client; | |
359 } | |
360 | 381 |
361 void ExpectRequestAndResponse(base::StringPiece qname, | 382 void ExpectRequestAndResponse(base::StringPiece qname, |
362 base::StringPiece answer) { | 383 base::StringPiece answer) { |
363 std::vector<char> request = CreateDnsTxtRequest(qname); | 384 std::vector<char> request = CreateDnsTxtRequest(qname); |
364 std::vector<char> response = CreateDnsTxtResponse(request, answer); | 385 std::vector<char> response = CreateDnsTxtResponse(request, answer); |
365 | 386 |
366 mock_socket_data_.emplace_back(new MockSocketData(request, response)); | 387 mock_socket_data_.emplace_back(new MockSocketData(request, response)); |
367 mock_socket_data_.back()->SetReadMode(GetParam()); | 388 mock_socket_data_.back()->SetReadMode(GetParam()); |
368 mock_socket_data_.back()->AddToFactory(&socket_factory_); | 389 mock_socket_data_.back()->AddToFactory(&socket_factory_); |
369 } | 390 } |
370 | 391 |
371 net::DnsConfig dns_config_; | 392 // This will be the NetworkChangeNotifier singleton for the duration of the |
| 393 // test. It is accessed statically by LogDnsClient. |
| 394 std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; |
| 395 // Queues and handles asynchronous DNS tasks. Indirectly used by LogDnsClient, |
| 396 // the underlying net::DnsClient, and NetworkChangeNotifier. |
372 base::MessageLoopForIO message_loop_; | 397 base::MessageLoopForIO message_loop_; |
| 398 // One MockSocketData for each socket that is created. This corresponds to one |
| 399 // for each DNS request sent. |
373 std::vector<std::unique_ptr<MockSocketData>> mock_socket_data_; | 400 std::vector<std::unique_ptr<MockSocketData>> mock_socket_data_; |
| 401 // Provides as many mock sockets as there are entries in |mock_socket_data_|. |
374 net::MockClientSocketFactory socket_factory_; | 402 net::MockClientSocketFactory socket_factory_; |
375 }; | 403 }; |
376 | 404 |
377 TEST_P(LogDnsClientTest, QueryLeafIndex) { | 405 TEST_P(LogDnsClientTest, QueryLeafIndex) { |
378 ExpectLeafIndexRequestAndResponse( | 406 ExpectLeafIndexRequestAndResponse( |
379 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", | 407 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", |
380 "123456"); | 408 "123456"); |
381 | 409 |
382 MockLeafIndexCallback callback; | 410 MockLeafIndexCallback callback; |
383 QueryLeafIndex("ct.test", kLeafHash, &callback); | 411 QueryLeafIndex("ct.test", kLeafHash, &callback); |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 TEST_P(LogDnsClientTest, QueryAuditProofReportsTimeout) { | 758 TEST_P(LogDnsClientTest, QueryAuditProofReportsTimeout) { |
731 ExpectRequestAndTimeout("0.123456.999999.tree.ct.test."); | 759 ExpectRequestAndTimeout("0.123456.999999.tree.ct.test."); |
732 | 760 |
733 MockAuditProofCallback callback; | 761 MockAuditProofCallback callback; |
734 QueryAuditProof("ct.test", 123456, 999999, &callback); | 762 QueryAuditProof("ct.test", 123456, 999999, &callback); |
735 ASSERT_TRUE(callback.called()); | 763 ASSERT_TRUE(callback.called()); |
736 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); | 764 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); |
737 EXPECT_THAT(callback.proof(), IsNull()); | 765 EXPECT_THAT(callback.proof(), IsNull()); |
738 } | 766 } |
739 | 767 |
| 768 TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) { |
| 769 std::unique_ptr<net::DnsClient> tmp = CreateDnsClient(); |
| 770 net::DnsClient* dns_client = tmp.get(); |
| 771 LogDnsClient log_client(std::move(tmp), net::BoundNetLog()); |
| 772 |
| 773 // Get the current DNS config, modify it and broadcast the update. |
| 774 net::DnsConfig config(*dns_client->GetConfig()); |
| 775 ASSERT_NE(123, config.attempts); |
| 776 config.attempts = 123; |
| 777 DnsChangeNotifier::SetDnsConfig(config); |
| 778 |
| 779 // Let the DNS config change propogate. |
| 780 base::RunLoop().RunUntilIdle(); |
| 781 EXPECT_EQ(123, dns_client->GetConfig()->attempts); |
| 782 } |
| 783 |
| 784 TEST_P(LogDnsClientTest, IgnoresLatestDnsConfigIfInvalid) { |
| 785 std::unique_ptr<net::DnsClient> tmp = CreateDnsClient(); |
| 786 net::DnsClient* dns_client = tmp.get(); |
| 787 LogDnsClient log_client(std::move(tmp), net::BoundNetLog()); |
| 788 |
| 789 // Get the current DNS config, modify it and broadcast the update. |
| 790 net::DnsConfig config(*dns_client->GetConfig()); |
| 791 ASSERT_THAT(config.nameservers, Not(IsEmpty())); |
| 792 config.nameservers.clear(); // Makes config invalid |
| 793 DnsChangeNotifier::SetDnsConfig(config); |
| 794 |
| 795 // Let the DNS config change propogate. |
| 796 base::RunLoop().RunUntilIdle(); |
| 797 EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty())); |
| 798 } |
| 799 |
740 INSTANTIATE_TEST_CASE_P(ReadMode, | 800 INSTANTIATE_TEST_CASE_P(ReadMode, |
741 LogDnsClientTest, | 801 LogDnsClientTest, |
742 ::testing::Values(net::IoMode::ASYNC, | 802 ::testing::Values(net::IoMode::ASYNC, |
743 net::IoMode::SYNCHRONOUS)); | 803 net::IoMode::SYNCHRONOUS)); |
744 | 804 |
745 } // namespace | 805 } // namespace |
746 } // namespace certificate_transparency | 806 } // namespace certificate_transparency |
OLD | NEW |