| Index: components/certificate_transparency/mock_log_dns_traffic.cc
|
| diff --git a/components/certificate_transparency/mock_log_dns_traffic.cc b/components/certificate_transparency/mock_log_dns_traffic.cc
|
| index 7a616592caf4b01ebaeced556e79bb4e8c9d352f..646125bb26d670d325f3c9f35997d0ac7441d4e4 100644
|
| --- a/components/certificate_transparency/mock_log_dns_traffic.cc
|
| +++ b/components/certificate_transparency/mock_log_dns_traffic.cc
|
| @@ -43,41 +43,50 @@ class DnsChangeNotifier : public net::NetworkChangeNotifier {
|
| // This should result in the DNS query ID always being 0.
|
| int FakeRandInt(int min, int max) {
|
| return min;
|
| }
|
|
|
| -std::vector<char> CreateDnsTxtRequest(base::StringPiece qname) {
|
| +bool CreateDnsTxtRequest(base::StringPiece qname, std::vector<char>* request) {
|
| std::string encoded_qname;
|
| - CHECK(net::DNSDomainFromDot(qname, &encoded_qname));
|
| + if (!net::DNSDomainFromDot(qname, &encoded_qname)) {
|
| + // |qname| is an invalid domain name.
|
| + return false;
|
| + }
|
|
|
| // DNS query section:
|
| // N bytes - qname
|
| // 2 bytes - record type
|
| // 2 bytes - record class
|
| // Total = N + 4 bytes
|
| const size_t query_section_size = encoded_qname.size() + 4;
|
|
|
| - std::vector<char> request(sizeof(net::dns_protocol::Header) +
|
| - query_section_size);
|
| - base::BigEndianWriter writer(request.data(), request.size());
|
| + request->resize(sizeof(net::dns_protocol::Header) + query_section_size);
|
| + base::BigEndianWriter writer(request->data(), request->size());
|
|
|
| // Header
|
| net::dns_protocol::Header header = {};
|
| header.flags = base::HostToNet16(net::dns_protocol::kFlagRD);
|
| header.qdcount = base::HostToNet16(1);
|
| - CHECK(writer.WriteBytes(&header, sizeof(header)));
|
| - // Query section
|
| - CHECK(writer.WriteBytes(encoded_qname.data(), encoded_qname.size()));
|
| - CHECK(writer.WriteU16(net::dns_protocol::kTypeTXT));
|
| - CHECK(writer.WriteU16(net::dns_protocol::kClassIN));
|
| - CHECK_EQ(0, writer.remaining());
|
|
|
| - return request;
|
| + if (!writer.WriteBytes(&header, sizeof(header)) ||
|
| + !writer.WriteBytes(encoded_qname.data(), encoded_qname.size()) ||
|
| + !writer.WriteU16(net::dns_protocol::kTypeTXT) ||
|
| + !writer.WriteU16(net::dns_protocol::kClassIN)) {
|
| + return false;
|
| + }
|
| +
|
| + if (writer.remaining() != 0) {
|
| + // Less than the expected amount of data was written.
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| }
|
|
|
| -std::vector<char> CreateDnsTxtResponse(const std::vector<char>& request,
|
| - base::StringPiece answer) {
|
| +bool CreateDnsTxtResponse(const std::vector<char>& request,
|
| + base::StringPiece answer,
|
| + std::vector<char>* response) {
|
| // DNS answers section:
|
| // 2 bytes - qname pointer
|
| // 2 bytes - record type
|
| // 2 bytes - record class
|
| // 4 bytes - time-to-live
|
| @@ -85,44 +94,52 @@ std::vector<char> CreateDnsTxtResponse(const std::vector<char>& request,
|
| // N bytes - answer
|
| // Total = 12 + N bytes
|
| const size_t answers_section_size = 12 + answer.size();
|
| constexpr uint32_t ttl = 86400; // seconds
|
|
|
| - std::vector<char> response(request.size() + answers_section_size);
|
| - std::copy(request.begin(), request.end(), response.begin());
|
| + response->resize(request.size() + answers_section_size);
|
| + std::copy(request.begin(), request.end(), response->begin());
|
| +
|
| // Modify the header
|
| net::dns_protocol::Header* header =
|
| - reinterpret_cast<net::dns_protocol::Header*>(response.data());
|
| + reinterpret_cast<net::dns_protocol::Header*>(response->data());
|
| header->ancount = base::HostToNet16(1);
|
| header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse);
|
|
|
| + // The qname is at the start of the query section (just after the header).
|
| + const uint8_t qname_ptr = sizeof(*header);
|
| +
|
| // Write the answer section
|
| - base::BigEndianWriter writer(response.data() + request.size(),
|
| - response.size() - request.size());
|
| - CHECK(writer.WriteU8(0xc0)); // qname is a pointer
|
| - CHECK(writer.WriteU8(
|
| - sizeof(*header))); // address of qname (start of query section)
|
| - CHECK(writer.WriteU16(net::dns_protocol::kTypeTXT));
|
| - CHECK(writer.WriteU16(net::dns_protocol::kClassIN));
|
| - CHECK(writer.WriteU32(ttl));
|
| - CHECK(writer.WriteU16(answer.size()));
|
| - CHECK(writer.WriteBytes(answer.data(), answer.size()));
|
| - CHECK_EQ(0, writer.remaining());
|
| + base::BigEndianWriter writer(response->data() + request.size(),
|
| + response->size() - request.size());
|
| + if (!writer.WriteU8(net::dns_protocol::kLabelPointer) ||
|
| + !writer.WriteU8(qname_ptr) ||
|
| + !writer.WriteU16(net::dns_protocol::kTypeTXT) ||
|
| + !writer.WriteU16(net::dns_protocol::kClassIN) || !writer.WriteU32(ttl) ||
|
| + !writer.WriteU16(answer.size()) ||
|
| + !writer.WriteBytes(answer.data(), answer.size())) {
|
| + return false;
|
| + }
|
|
|
| - return response;
|
| + if (writer.remaining() != 0) {
|
| + // Less than the expected amount of data was written.
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| }
|
|
|
| -std::vector<char> CreateDnsErrorResponse(const std::vector<char>& request,
|
| - uint8_t rcode) {
|
| - std::vector<char> response(request);
|
| +bool CreateDnsErrorResponse(const std::vector<char>& request,
|
| + uint8_t rcode,
|
| + std::vector<char>* response) {
|
| + *response = request;
|
| // Modify the header
|
| net::dns_protocol::Header* header =
|
| - reinterpret_cast<net::dns_protocol::Header*>(response.data());
|
| + reinterpret_cast<net::dns_protocol::Header*>(response->data());
|
| header->ancount = base::HostToNet16(1);
|
| header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse | rcode);
|
| -
|
| - return response;
|
| + return true;
|
| }
|
|
|
| } // namespace
|
|
|
| // A container for all of the data needed for simulating a socket.
|
| @@ -185,15 +202,11 @@ class MockLogDnsTraffic::MockSocketData {
|
|
|
| // Encapsulates the data that is expected to be written to a socket.
|
| net::MockWrite expected_write_;
|
|
|
| // Encapsulates the data/error that should be returned when reading from a
|
| - // socket. The second "expected" read is a sentinel that causes socket reads
|
| - // beyond the first to hang until they timeout. This results in better
|
| - // test failure messages (rather than a CHECK-fail due to a socket read
|
| - // overrunning the MockRead array) and behaviour more like a real socket when
|
| - // an unexpected second socket read occurs.
|
| + // socket. The second "expected" read is a sentinel (see |kNoMoreData|).
|
| net::MockRead expected_reads_[2];
|
|
|
| // Holds pointers to |expected_write_| and |expected_reads_|. This is what is
|
| // added to net::MockClientSocketFactory to prepare a mock socket.
|
| net::SequencedSocketData socket_data_;
|
| @@ -203,58 +216,90 @@ class MockLogDnsTraffic::MockSocketData {
|
|
|
| MockLogDnsTraffic::MockLogDnsTraffic() : socket_read_mode_(net::ASYNC) {}
|
|
|
| MockLogDnsTraffic::~MockLogDnsTraffic() {}
|
|
|
| -void MockLogDnsTraffic::ExpectRequestAndErrorResponse(base::StringPiece qname,
|
| +bool MockLogDnsTraffic::ExpectRequestAndErrorResponse(base::StringPiece qname,
|
| uint8_t rcode) {
|
| - std::vector<char> request = CreateDnsTxtRequest(qname);
|
| - EmplaceMockSocketData(CreateDnsTxtRequest(qname),
|
| - CreateDnsErrorResponse(request, rcode));
|
| + std::vector<char> request;
|
| + if (!CreateDnsTxtRequest(qname, &request)) {
|
| + return false;
|
| + }
|
| +
|
| + std::vector<char> response;
|
| + if (!CreateDnsErrorResponse(request, rcode, &response)) {
|
| + return false;
|
| + }
|
| +
|
| + EmplaceMockSocketData(request, response);
|
| + return true;
|
| }
|
|
|
| -void MockLogDnsTraffic::ExpectRequestAndSocketError(base::StringPiece qname,
|
| +bool MockLogDnsTraffic::ExpectRequestAndSocketError(base::StringPiece qname,
|
| net::Error error) {
|
| - EmplaceMockSocketData(CreateDnsTxtRequest(qname), error);
|
| + std::vector<char> request;
|
| + if (!CreateDnsTxtRequest(qname, &request)) {
|
| + return false;
|
| + }
|
| +
|
| + EmplaceMockSocketData(request, error);
|
| + return true;
|
| }
|
|
|
| -void MockLogDnsTraffic::ExpectRequestAndTimeout(base::StringPiece qname) {
|
| - EmplaceMockSocketData(CreateDnsTxtRequest(qname));
|
| +bool MockLogDnsTraffic::ExpectRequestAndTimeout(base::StringPiece qname) {
|
| + std::vector<char> request;
|
| + if (!CreateDnsTxtRequest(qname, &request)) {
|
| + return false;
|
| + }
|
| +
|
| + EmplaceMockSocketData(request);
|
|
|
| // Speed up timeout tests.
|
| SetDnsTimeout(TestTimeouts::tiny_timeout());
|
| +
|
| + return true;
|
| }
|
|
|
| -void MockLogDnsTraffic::ExpectRequestAndResponse(
|
| +bool MockLogDnsTraffic::ExpectRequestAndResponse(
|
| base::StringPiece qname,
|
| const std::vector<base::StringPiece>& txt_strings) {
|
| std::string answer;
|
| for (base::StringPiece str : txt_strings) {
|
| // The size of the string must precede it. The size must fit into 1 byte.
|
| answer.insert(answer.end(), base::checked_cast<uint8_t>(str.size()));
|
| str.AppendToString(&answer);
|
| }
|
|
|
| - std::vector<char> request = CreateDnsTxtRequest(qname);
|
| - EmplaceMockSocketData(request, CreateDnsTxtResponse(request, answer));
|
| + std::vector<char> request;
|
| + if (!CreateDnsTxtRequest(qname, &request)) {
|
| + return false;
|
| + }
|
| +
|
| + std::vector<char> response;
|
| + if (!CreateDnsTxtResponse(request, answer, &response)) {
|
| + return false;
|
| + }
|
| +
|
| + EmplaceMockSocketData(request, response);
|
| + return true;
|
| }
|
|
|
| -void MockLogDnsTraffic::ExpectLeafIndexRequestAndResponse(
|
| +bool MockLogDnsTraffic::ExpectLeafIndexRequestAndResponse(
|
| base::StringPiece qname,
|
| uint64_t leaf_index) {
|
| - ExpectRequestAndResponse(qname, { base::Uint64ToString(leaf_index) });
|
| + return ExpectRequestAndResponse(qname, {base::Uint64ToString(leaf_index)});
|
| }
|
|
|
| -void MockLogDnsTraffic::ExpectAuditProofRequestAndResponse(
|
| +bool MockLogDnsTraffic::ExpectAuditProofRequestAndResponse(
|
| base::StringPiece qname,
|
| std::vector<std::string>::const_iterator audit_path_start,
|
| std::vector<std::string>::const_iterator audit_path_end) {
|
| // Join nodes in the audit path into a single string.
|
| std::string proof =
|
| std::accumulate(audit_path_start, audit_path_end, std::string());
|
|
|
| - ExpectRequestAndResponse(qname, { proof });
|
| + return ExpectRequestAndResponse(qname, {proof});
|
| }
|
|
|
| void MockLogDnsTraffic::InitializeDnsConfig() {
|
| net::DnsConfig dns_config;
|
| // Use an invalid nameserver address. This prevents the tests accidentally
|
|
|