Chromium Code Reviews| 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()) { | |
|
Eran Messeri
2016/07/21 14:16:24
Please document the reason for the existence of th
Rob Percival
2016/07/21 14:45:10
Done.
| |
| 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 std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; |
| 372 base::MessageLoopForIO message_loop_; | 393 base::MessageLoopForIO message_loop_; |
| 373 std::vector<std::unique_ptr<MockSocketData>> mock_socket_data_; | 394 std::vector<std::unique_ptr<MockSocketData>> mock_socket_data_; |
| 374 net::MockClientSocketFactory socket_factory_; | 395 net::MockClientSocketFactory socket_factory_; |
| 375 }; | 396 }; |
| 376 | 397 |
| 377 TEST_P(LogDnsClientTest, QueryLeafIndex) { | 398 TEST_P(LogDnsClientTest, QueryLeafIndex) { |
| 378 ExpectLeafIndexRequestAndResponse( | 399 ExpectLeafIndexRequestAndResponse( |
| 379 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", | 400 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", |
| 380 "123456"); | 401 "123456"); |
| 381 | 402 |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 730 TEST_P(LogDnsClientTest, QueryAuditProofReportsTimeout) { | 751 TEST_P(LogDnsClientTest, QueryAuditProofReportsTimeout) { |
| 731 ExpectRequestAndTimeout("0.123456.999999.tree.ct.test."); | 752 ExpectRequestAndTimeout("0.123456.999999.tree.ct.test."); |
| 732 | 753 |
| 733 MockAuditProofCallback callback; | 754 MockAuditProofCallback callback; |
| 734 QueryAuditProof("ct.test", 123456, 999999, &callback); | 755 QueryAuditProof("ct.test", 123456, 999999, &callback); |
| 735 ASSERT_TRUE(callback.called()); | 756 ASSERT_TRUE(callback.called()); |
| 736 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); | 757 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); |
| 737 EXPECT_THAT(callback.proof(), IsNull()); | 758 EXPECT_THAT(callback.proof(), IsNull()); |
| 738 } | 759 } |
| 739 | 760 |
| 761 TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) { | |
| 762 std::unique_ptr<net::DnsClient> tmp = CreateDnsClient(); | |
| 763 net::DnsClient* dns_client = tmp.get(); | |
| 764 LogDnsClient log_client(std::move(tmp), net::BoundNetLog()); | |
| 765 | |
| 766 // Get the current DNS config, modify it and broadcast the update. | |
| 767 net::DnsConfig config(*dns_client->GetConfig()); | |
| 768 ASSERT_NE(123, config.attempts); | |
| 769 config.attempts = 123; | |
| 770 DnsChangeNotifier::SetDnsConfig(config); | |
| 771 | |
| 772 // Let the DNS config change propogate. | |
| 773 base::RunLoop().RunUntilIdle(); | |
| 774 EXPECT_EQ(123, dns_client->GetConfig()->attempts); | |
| 775 } | |
| 776 | |
| 777 TEST_P(LogDnsClientTest, IgnoresLatestDnsConfigIfInvalid) { | |
| 778 std::unique_ptr<net::DnsClient> tmp = CreateDnsClient(); | |
| 779 net::DnsClient* dns_client = tmp.get(); | |
| 780 LogDnsClient log_client(std::move(tmp), net::BoundNetLog()); | |
| 781 | |
| 782 // Get the current DNS config, modify it and broadcast the update. | |
| 783 net::DnsConfig config(*dns_client->GetConfig()); | |
| 784 ASSERT_THAT(config.nameservers, Not(IsEmpty())); | |
| 785 config.nameservers.clear(); // Makes config invalid | |
| 786 DnsChangeNotifier::SetDnsConfig(config); | |
| 787 | |
| 788 // Let the DNS config change propogate. | |
| 789 base::RunLoop().RunUntilIdle(); | |
| 790 EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty())); | |
| 791 } | |
| 792 | |
| 740 INSTANTIATE_TEST_CASE_P(ReadMode, | 793 INSTANTIATE_TEST_CASE_P(ReadMode, |
| 741 LogDnsClientTest, | 794 LogDnsClientTest, |
| 742 ::testing::Values(net::IoMode::ASYNC, | 795 ::testing::Values(net::IoMode::ASYNC, |
| 743 net::IoMode::SYNCHRONOUS)); | 796 net::IoMode::SYNCHRONOUS)); |
| 744 | 797 |
| 745 } // namespace | 798 } // namespace |
| 746 } // namespace certificate_transparency | 799 } // namespace certificate_transparency |
| OLD | NEW |