Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: components/certificate_transparency/mock_log_dns_traffic.cc

Issue 2149973003: Extracts CT DNS test utilities into a standalone class (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase and integrate Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/certificate_transparency/mock_log_dns_traffic.h"
6
7 #include <algorithm>
8 #include <numeric>
9 #include <vector>
10
11 #include "base/big_endian.h"
12 #include "base/sys_byteorder.h"
13 #include "base/test/test_timeouts.h"
14 #include "net/dns/dns_client.h"
15 #include "net/dns/dns_protocol.h"
16 #include "net/dns/dns_util.h"
17 #include "net/socket/socket_test_util.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace certificate_transparency {
21
22 namespace {
23
24 // Necessary to expose SetDnsConfig for testing.
25 class DnsChangeNotifier : public net::NetworkChangeNotifier {
26 public:
27 static void SetInitialDnsConfig(const net::DnsConfig& config) {
28 net::NetworkChangeNotifier::SetInitialDnsConfig(config);
29 }
30
31 static void SetDnsConfig(const net::DnsConfig& config) {
32 net::NetworkChangeNotifier::SetDnsConfig(config);
33 }
34 };
35
36 // Always return min, to simplify testing.
37 // This should result in the DNS query ID always being 0.
38 int FakeRandInt(int min, int max) {
39 return min;
40 }
41
42 std::vector<char> CreateDnsTxtRequest(base::StringPiece qname) {
43 std::string encoded_qname;
44 EXPECT_TRUE(net::DNSDomainFromDot(qname, &encoded_qname));
45
46 // DNS query section:
47 // N bytes - qname
48 // 2 bytes - record type
49 // 2 bytes - record class
50 // Total = N + 4 bytes
51 const size_t query_section_size = encoded_qname.size() + 4;
52
53 std::vector<char> request(sizeof(net::dns_protocol::Header) +
54 query_section_size);
55 base::BigEndianWriter writer(request.data(), request.size());
56
57 // Header
58 net::dns_protocol::Header header = {};
59 header.flags = base::HostToNet16(net::dns_protocol::kFlagRD);
60 header.qdcount = base::HostToNet16(1);
61 EXPECT_TRUE(writer.WriteBytes(&header, sizeof(header)));
62 // Query section
63 EXPECT_TRUE(writer.WriteBytes(encoded_qname.data(), encoded_qname.size()));
64 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kTypeTXT));
65 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kClassIN));
66 EXPECT_EQ(0, writer.remaining());
67
68 return request;
69 }
70
71 std::vector<char> CreateDnsTxtResponse(const std::vector<char>& request,
72 base::StringPiece answer) {
73 // DNS answers section:
74 // 2 bytes - qname pointer
75 // 2 bytes - record type
76 // 2 bytes - record class
77 // 4 bytes - time-to-live
78 // 2 bytes - size of answer (N)
79 // N bytes - answer
80 // Total = 12 + N bytes
81 const size_t answers_section_size = 12 + answer.size();
82 constexpr uint32_t ttl = 86400; // seconds
83
84 std::vector<char> response(request.size() + answers_section_size);
85 std::copy(request.begin(), request.end(), response.begin());
86 // Modify the header
87 net::dns_protocol::Header* header =
88 reinterpret_cast<net::dns_protocol::Header*>(response.data());
89 header->ancount = base::HostToNet16(1);
90 header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse);
91
92 // Write the answer section
93 base::BigEndianWriter writer(response.data() + request.size(),
94 response.size() - request.size());
95 EXPECT_TRUE(writer.WriteU8(0xc0)); // qname is a pointer
96 EXPECT_TRUE(writer.WriteU8(
97 sizeof(*header))); // address of qname (start of query section)
98 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kTypeTXT));
99 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kClassIN));
100 EXPECT_TRUE(writer.WriteU32(ttl));
101 EXPECT_TRUE(writer.WriteU16(answer.size()));
102 EXPECT_TRUE(writer.WriteBytes(answer.data(), answer.size()));
103 EXPECT_EQ(0, writer.remaining());
104
105 return response;
106 }
107
108 std::vector<char> CreateDnsErrorResponse(const std::vector<char>& request,
109 uint8_t rcode) {
110 std::vector<char> response(request);
111 // Modify the header
112 net::dns_protocol::Header* header =
113 reinterpret_cast<net::dns_protocol::Header*>(response.data());
114 header->ancount = base::HostToNet16(1);
115 header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse | rcode);
116
117 return response;
118 }
119
120 } // namespace
121
122 namespace internal {
123
124 MockSocketData::MockSocketData(const std::vector<char>& write,
125 const std::vector<char>& read)
126 : expected_write_payload_(write),
127 expected_read_payload_(read),
128 expected_write_(net::SYNCHRONOUS,
129 expected_write_payload_.data(),
130 expected_write_payload_.size(),
131 0),
132 expected_reads_{net::MockRead(net::ASYNC,
133 expected_read_payload_.data(),
134 expected_read_payload_.size(),
135 1),
136 no_more_data_},
137 socket_data_(expected_reads_, 2, &expected_write_, 1) {}
138
139 MockSocketData::MockSocketData(const std::vector<char>& write, int net_error)
140 : expected_write_payload_(write),
141 expected_write_(net::SYNCHRONOUS,
142 expected_write_payload_.data(),
143 expected_write_payload_.size(),
144 0),
145 expected_reads_{net::MockRead(net::ASYNC, net_error, 1), no_more_data_},
146 socket_data_(expected_reads_, 2, &expected_write_, 1) {}
147
148 MockSocketData::MockSocketData(const std::vector<char>& write)
149 : expected_write_payload_(write),
150 expected_write_(net::SYNCHRONOUS,
151 expected_write_payload_.data(),
152 expected_write_payload_.size(),
153 0),
154 expected_reads_{net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING, 1),
155 no_more_data_},
156 socket_data_(expected_reads_, 2, &expected_write_, 1) {}
157
158 MockSocketData::~MockSocketData() {}
159
160 void MockSocketData::AddToFactory(
161 net::MockClientSocketFactory* socket_factory) {
162 socket_factory->AddSocketDataProvider(&socket_data_);
163 }
164
165 const net::MockRead MockSocketData::no_more_data_(net::SYNCHRONOUS,
166 net::ERR_IO_PENDING,
167 2);
168
169 } // namespace internal
170
171 using internal::MockSocketData;
172
173 MockLogDnsTraffic::MockLogDnsTraffic() : socket_read_mode_(net::ASYNC) {}
174
175 MockLogDnsTraffic::~MockLogDnsTraffic() {}
176
177 void MockLogDnsTraffic::ExpectRequestAndErrorResponse(base::StringPiece qname,
178 uint8_t rcode) {
179 std::vector<char> request = CreateDnsTxtRequest(qname);
180 EmplaceMockSocketData(CreateDnsTxtRequest(qname),
181 CreateDnsErrorResponse(request, rcode));
182 }
183
184 void MockLogDnsTraffic::ExpectRequestAndSocketError(base::StringPiece qname,
185 int net_error) {
186 EmplaceMockSocketData(CreateDnsTxtRequest(qname), net_error);
187 }
188
189 void MockLogDnsTraffic::ExpectRequestAndTimeout(base::StringPiece qname) {
190 EmplaceMockSocketData(CreateDnsTxtRequest(qname));
191
192 // Speed up timeout tests.
193 SetDnsTimeout(TestTimeouts::tiny_timeout());
194 }
195
196 void MockLogDnsTraffic::ExpectLeafIndexRequestAndResponse(
197 base::StringPiece qname,
198 base::StringPiece leaf_index) {
199 // Prepend size to leaf_index to create the query answer (rdata)
200 ASSERT_LE(leaf_index.size(), 0xFFul); // size must fit into a single byte
201 std::string answer = leaf_index.as_string();
202 answer.insert(answer.begin(), static_cast<char>(leaf_index.size()));
203
204 ExpectRequestAndResponse(qname, answer);
205 }
206
207 void MockLogDnsTraffic::ExpectAuditProofRequestAndResponse(
208 base::StringPiece qname,
209 std::vector<std::string>::const_iterator audit_path_start,
210 std::vector<std::string>::const_iterator audit_path_end) {
211 // Join nodes in the audit path into a single string.
212 std::string proof =
213 std::accumulate(audit_path_start, audit_path_end, std::string());
214
215 // Prepend size to proof to create the query answer (rdata)
216 ASSERT_LE(proof.size(), 0xFFul); // size must fit into a single byte
217 proof.insert(proof.begin(), static_cast<char>(proof.size()));
218
219 ExpectRequestAndResponse(qname, proof);
220 }
221
222 void MockLogDnsTraffic::InitializeDnsConfig() {
223 net::DnsConfig dns_config;
224 // Use an invalid nameserver address. This prevents the tests accidentally
225 // sending real DNS queries. The mock sockets don't care that the address
226 // is invalid.
227 dns_config.nameservers.push_back(net::IPEndPoint());
228 // Don't attempt retransmissions - just fail.
229 dns_config.attempts = 1;
230 // This ensures timeouts are long enough for memory tests.
231 dns_config.timeout = TestTimeouts::action_timeout();
232 // Simplify testing - don't require random numbers for the source port.
233 // This means our FakeRandInt function should only be called to get query
234 // IDs.
235 dns_config.randomize_ports = false;
236
237 DnsChangeNotifier::SetInitialDnsConfig(dns_config);
238 }
239
240 void MockLogDnsTraffic::SetDnsConfig(const net::DnsConfig& config) {
241 DnsChangeNotifier::SetDnsConfig(config);
242 }
243
244 std::unique_ptr<net::DnsClient> MockLogDnsTraffic::CreateDnsClient() {
245 return net::DnsClient::CreateClientForTesting(nullptr, &socket_factory_,
246 base::Bind(&FakeRandInt));
247 }
248
249 void MockLogDnsTraffic::ExpectRequestAndResponse(base::StringPiece qname,
250 base::StringPiece answer) {
251 std::vector<char> request = CreateDnsTxtRequest(qname);
252 EmplaceMockSocketData(request, CreateDnsTxtResponse(request, answer));
253 }
254
255 template <typename... Args>
256 void MockLogDnsTraffic::EmplaceMockSocketData(Args&&... args) {
257 mock_socket_data_.emplace_back(
258 new MockSocketData(std::forward<Args>(args)...));
259 mock_socket_data_.back()->SetReadMode(socket_read_mode_);
260 mock_socket_data_.back()->AddToFactory(&socket_factory_);
261 }
262
263 void MockLogDnsTraffic::SetDnsTimeout(const base::TimeDelta& timeout) {
264 net::DnsConfig dns_config;
265 DnsChangeNotifier::GetDnsConfig(&dns_config);
266 dns_config.timeout = timeout;
267 DnsChangeNotifier::SetDnsConfig(dns_config);
268 }
269
270 } // namespace certificate_transparency
OLDNEW
« no previous file with comments | « components/certificate_transparency/mock_log_dns_traffic.h ('k') | components/components_tests.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698