1 // Copyright 2012 The Chromium Authors
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 "net/dns/dns_response.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <string>
10 #include <vector>
11
12 #include "base/big_endian.h"
13 #include "base/check.h"
14 #include "base/containers/span.h"
15 #include "base/strings/string_piece.h"
16 #include "base/time/time.h"
17 #include "net/base/io_buffer.h"
18 #include "net/dns/dns_names_util.h"
19 #include "net/dns/dns_query.h"
20 #include "net/dns/dns_test_util.h"
21 #include "net/dns/public/dns_protocol.h"
22 #include "net/dns/record_rdata.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/abseil-cpp/absl/types/optional.h"
26
27 namespace net {
28
29 namespace {
30
TEST(DnsRecordParserTest,Constructor)31 TEST(DnsRecordParserTest, Constructor) {
32 const char data[] = { 0 };
33
34 EXPECT_FALSE(DnsRecordParser().IsValid());
35 EXPECT_TRUE(DnsRecordParser(data, 1, 0, 0).IsValid());
36 EXPECT_TRUE(DnsRecordParser(data, 1, 1, 0).IsValid());
37
38 EXPECT_FALSE(DnsRecordParser(data, 1, 0, 0).AtEnd());
39 EXPECT_TRUE(DnsRecordParser(data, 1, 1, 0).AtEnd());
40 }
41
TEST(DnsRecordParserTest,ReadName)42 TEST(DnsRecordParserTest, ReadName) {
43 const uint8_t data[] = {
44 // all labels "foo.example.com"
45 0x03, 'f', 'o', 'o', 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0x03, 'c',
46 'o', 'm',
47 // byte 0x10
48 0x00,
49 // byte 0x11
50 // part label, part pointer, "bar.example.com"
51 0x03, 'b', 'a', 'r', 0xc0, 0x04,
52 // byte 0x17
53 // all pointer to "bar.example.com", 2 jumps
54 0xc0, 0x11,
55 // byte 0x1a
56 };
57
58 std::string out;
59 DnsRecordParser parser(data, sizeof(data), 0, /*num_records=*/0);
60 ASSERT_TRUE(parser.IsValid());
61
62 EXPECT_EQ(0x11u, parser.ReadName(data + 0x00, &out));
63 EXPECT_EQ("foo.example.com", out);
64 // Check that the last "." is never stored.
65 out.clear();
66 EXPECT_EQ(0x1u, parser.ReadName(data + 0x10, &out));
67 EXPECT_EQ("", out);
68 out.clear();
69 EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, &out));
70 EXPECT_EQ("bar.example.com", out);
71 out.clear();
72 EXPECT_EQ(0x2u, parser.ReadName(data + 0x17, &out));
73 EXPECT_EQ("bar.example.com", out);
74
75 // Parse name without storing it.
76 EXPECT_EQ(0x11u, parser.ReadName(data + 0x00, nullptr));
77 EXPECT_EQ(0x1u, parser.ReadName(data + 0x10, nullptr));
78 EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, nullptr));
79 EXPECT_EQ(0x2u, parser.ReadName(data + 0x17, nullptr));
80
81 // Check that it works even if initial position is different.
82 parser = DnsRecordParser(data, sizeof(data), 0x12, /*num_records=*/0);
83 EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, nullptr));
84 }
85
TEST(DnsRecordParserTest,ReadNameFail)86 TEST(DnsRecordParserTest, ReadNameFail) {
87 const uint8_t data[] = {
88 // label length beyond packet
89 0x30, 'x', 'x', 0x00,
90 // pointer offset beyond packet
91 0xc0, 0x20,
92 // pointer loop
93 0xc0, 0x08, 0xc0, 0x06,
94 // incorrect label type (currently supports only direct and pointer)
95 0x80, 0x00,
96 // truncated name (missing root label)
97 0x02, 'x', 'x',
98 };
99
100 DnsRecordParser parser(data, sizeof(data), 0, /*num_records=*/0);
101 ASSERT_TRUE(parser.IsValid());
102
103 std::string out;
104 EXPECT_EQ(0u, parser.ReadName(data + 0x00, &out));
105 EXPECT_EQ(0u, parser.ReadName(data + 0x04, &out));
106 EXPECT_EQ(0u, parser.ReadName(data + 0x08, &out));
107 EXPECT_EQ(0u, parser.ReadName(data + 0x0a, &out));
108 EXPECT_EQ(0u, parser.ReadName(data + 0x0c, &out));
109 EXPECT_EQ(0u, parser.ReadName(data + 0x0e, &out));
110 }
111
112 // Returns an RFC 1034 style domain name with a length of |name_len|.
113 // Also writes the expected dotted string representation into |dotted_str|,
114 // which must be non-null.
BuildRfc1034Name(const size_t name_len,std::string * dotted_str)115 std::vector<uint8_t> BuildRfc1034Name(const size_t name_len,
116 std::string* dotted_str) {
117 // Impossible length. If length not zero, need at least 2 to allow label
118 // length and label contents.
119 CHECK_NE(name_len, 1u);
120
121 CHECK(dotted_str != nullptr);
122 auto ChoosePrintableCharLambda = [](uint8_t n) { return n % 26 + 'A'; };
123 const size_t max_label_len = 63;
124 std::vector<uint8_t> data;
125
126 dotted_str->clear();
127 while (data.size() < name_len) {
128 // Compute the size of the next label.
129 //
130 // No need to account for next label length because the final zero length is
131 // not considered included in overall length.
132 size_t label_len = std::min(name_len - data.size() - 1, max_label_len);
133 // Need to ensure the remainder is not 1 because that would leave room for a
134 // label length but not a label.
135 if (name_len - data.size() - label_len - 1 == 1) {
136 CHECK_GT(label_len, 1u);
137 label_len -= 1;
138 }
139
140 // Write the length octet
141 data.push_back(label_len);
142
143 // Write |label_len| bytes of label data
144 const size_t size_with_label = data.size() + label_len;
145 while (data.size() < size_with_label) {
146 const uint8_t chr = ChoosePrintableCharLambda(data.size());
147 data.push_back(chr);
148 dotted_str->push_back(chr);
149
150 CHECK(data.size() <= name_len);
151 }
152
153 // Write a trailing dot after every label
154 dotted_str->push_back('.');
155 }
156
157 // Omit the final dot
158 if (!dotted_str->empty())
159 dotted_str->pop_back();
160
161 CHECK(data.size() == name_len);
162
163 // Final zero-length label (not considered included in overall length).
164 data.push_back(0);
165
166 return data;
167 }
168
TEST(DnsRecordParserTest,ReadNameGoodLength)169 TEST(DnsRecordParserTest, ReadNameGoodLength) {
170 const size_t name_len_cases[] = {2, 10, 40, 250, 254, 255};
171
172 for (auto name_len : name_len_cases) {
173 std::string expected_name;
174 const std::vector<uint8_t> data_vector =
175 BuildRfc1034Name(name_len, &expected_name);
176 ASSERT_EQ(data_vector.size(), name_len + 1);
177 const uint8_t* data = data_vector.data();
178
179 DnsRecordParser parser(data, data_vector.size(), 0, /*num_records=*/0);
180 ASSERT_TRUE(parser.IsValid());
181
182 std::string out;
183 EXPECT_EQ(data_vector.size(), parser.ReadName(data, &out));
184 EXPECT_EQ(expected_name, out);
185 }
186 }
187
188 // Tests against incorrect name length validation, which is anti-pattern #3 from
189 // the "NAME:WRECK" report:
190 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsRecordParserTest,ReadNameTooLongFail)191 TEST(DnsRecordParserTest, ReadNameTooLongFail) {
192 const size_t name_len_cases[] = {256, 257, 258, 300, 10000};
193
194 for (auto name_len : name_len_cases) {
195 std::string expected_name;
196 const std::vector<uint8_t> data_vector =
197 BuildRfc1034Name(name_len, &expected_name);
198 ASSERT_EQ(data_vector.size(), name_len + 1);
199 const uint8_t* data = data_vector.data();
200
201 DnsRecordParser parser(data, data_vector.size(), 0, /*num_records=*/0);
202 ASSERT_TRUE(parser.IsValid());
203
204 std::string out;
205 EXPECT_EQ(0u, parser.ReadName(data, &out));
206 }
207 }
208
209 // Tests against incorrect name compression pointer validation, which is anti-
210 // pattern #6 from the "NAME:WRECK" report:
211 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsRecordParserTest,RejectsNamesWithLoops)212 TEST(DnsRecordParserTest, RejectsNamesWithLoops) {
213 const char kData[] =
214 "\003www\007example\300\031" // www.example with pointer to byte 25
215 "aaaaaaaaaaa" // Garbage data to spread things out.
216 "\003foo\300\004"; // foo with pointer to byte 4.
217
218 DnsRecordParser parser(kData, /*length=*/sizeof(kData) - 1, /*offset=*/0,
219 /*num_records=*/0);
220 ASSERT_TRUE(parser.IsValid());
221
222 std::string out;
223 EXPECT_EQ(0u, parser.ReadName(kData, &out));
224 }
225
226 // Tests against incorrect name compression pointer validation, which is anti-
227 // pattern #6 from the "NAME:WRECK" report:
228 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsRecordParserTest,RejectsNamesPointingOutsideData)229 TEST(DnsRecordParserTest, RejectsNamesPointingOutsideData) {
230 const char kData[] =
231 "\003www\007example\300\031"; // www.example with pointer to byte 25
232
233 DnsRecordParser parser(kData, /*length=*/sizeof(kData) - 1, /*offset=*/0,
234 /*num_records=*/0);
235 ASSERT_TRUE(parser.IsValid());
236
237 std::string out;
238 EXPECT_EQ(0u, parser.ReadName(kData, &out));
239 }
240
TEST(DnsRecordParserTest,ParsesValidPointer)241 TEST(DnsRecordParserTest, ParsesValidPointer) {
242 const char kData[] =
243 "\003www\007example\300\022" // www.example with pointer to byte 25.
244 "aaaa" // Garbage data to spread things out.
245 "\004test\000"; // .test
246
247 DnsRecordParser parser(kData, /*length=*/sizeof(kData) - 1, /*offset=*/0,
248 /*num_records=*/0);
249 ASSERT_TRUE(parser.IsValid());
250
251 std::string out;
252 EXPECT_EQ(14u, parser.ReadName(kData, &out));
253 EXPECT_EQ(out, "www.example.test");
254 }
255
256 // Per RFC 1035, section 4.1.4, the first 2 bits of a DNS name label determine
257 // if it is a length label (if the bytes are 00) or a pointer label (if the
258 // bytes are 11). It is a common DNS parsing bug to treat 01 or 10 as pointer
259 // labels, but these are reserved and invalid. Such labels should always result
260 // in DnsRecordParser rejecting the name.
261 //
262 // Tests against incorrect name compression pointer validation, which is anti-
263 // pattern #6 from the "NAME:WRECK" report:
264 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsRecordParserTest,RejectsNamesWithInvalidLabelTypeAsPointer)265 TEST(DnsRecordParserTest, RejectsNamesWithInvalidLabelTypeAsPointer) {
266 const char kData[] =
267 "\003www\007example\200\022" // www.example with invalid label as pointer
268 "aaaa" // Garbage data to spread things out.
269 "\004test\000"; // .test
270
271 DnsRecordParser parser(kData, /*length=*/sizeof(kData) - 1, /*offset=*/0,
272 /*num_records=*/0);
273 ASSERT_TRUE(parser.IsValid());
274
275 std::string out;
276 EXPECT_EQ(0u, parser.ReadName(kData, &out));
277 }
278
279 // Per RFC 1035, section 4.1.4, the first 2 bits of a DNS name label determine
280 // if it is a length label (if the bytes are 00) or a pointer label (if the
281 // bytes are 11). Such labels should always result in DnsRecordParser rejecting
282 // the name.
283 //
284 // Tests against incorrect name compression pointer validation, which is anti-
285 // pattern #6 from the "NAME:WRECK" report:
286 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsRecordParserTest,RejectsNamesWithInvalidLabelTypeAsLength)287 TEST(DnsRecordParserTest, RejectsNamesWithInvalidLabelTypeAsLength) {
288 const char kData[] =
289 "\003www\007example\104" // www.example with invalid label as length
290 "test\000"; // test. (in case \104 is interpreted as length=4)
291
292 // Append a bunch of zeroes to the buffer in case \104 is interpreted as a
293 // long length.
294 std::string data(kData, sizeof(kData) - 1);
295 data.append(256, '\000');
296
297 DnsRecordParser parser(data.data(), data.size(), /*offset=*/0,
298 /*num_records=*/0);
299 ASSERT_TRUE(parser.IsValid());
300
301 std::string out;
302 EXPECT_EQ(0u, parser.ReadName(data.data(), &out));
303 }
304
TEST(DnsRecordParserTest,ReadRecord)305 TEST(DnsRecordParserTest, ReadRecord) {
306 const uint8_t data[] = {
307 // Type CNAME record.
308 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm', 0x00, 0x00,
309 0x05, // TYPE is CNAME.
310 0x00, 0x01, // CLASS is IN.
311 0x00, 0x01, 0x24, 0x74, // TTL is 0x00012474.
312 0x00, 0x06, // RDLENGTH is 6 bytes.
313 0x03, 'f', 'o', 'o', // compressed name in record
314 0xc0, 0x00,
315 // Type A record.
316 0x03, 'b', 'a', 'r', // compressed owner name
317 0xc0, 0x00, 0x00, 0x01, // TYPE is A.
318 0x00, 0x01, // CLASS is IN.
319 0x00, 0x20, 0x13, 0x55, // TTL is 0x00201355.
320 0x00, 0x04, // RDLENGTH is 4 bytes.
321 0x7f, 0x02, 0x04, 0x01, // IP is 127.2.4.1
322 };
323
324 std::string out;
325 DnsRecordParser parser(data, sizeof(data), 0, /*num_records=*/2);
326
327 DnsResourceRecord record;
328 EXPECT_TRUE(parser.ReadRecord(&record));
329 EXPECT_EQ("example.com", record.name);
330 EXPECT_EQ(dns_protocol::kTypeCNAME, record.type);
331 EXPECT_EQ(dns_protocol::kClassIN, record.klass);
332 EXPECT_EQ(0x00012474u, record.ttl);
333 EXPECT_EQ(6u, record.rdata.length());
334 EXPECT_EQ(6u, parser.ReadName(record.rdata.data(), &out));
335 EXPECT_EQ("foo.example.com", out);
336 EXPECT_FALSE(parser.AtEnd());
337
338 EXPECT_TRUE(parser.ReadRecord(&record));
339 EXPECT_EQ("bar.example.com", record.name);
340 EXPECT_EQ(dns_protocol::kTypeA, record.type);
341 EXPECT_EQ(dns_protocol::kClassIN, record.klass);
342 EXPECT_EQ(0x00201355u, record.ttl);
343 EXPECT_EQ(4u, record.rdata.length());
344 EXPECT_EQ(base::StringPiece("\x7f\x02\x04\x01"), record.rdata);
345 EXPECT_TRUE(parser.AtEnd());
346
347 // Test truncated record.
348 parser = DnsRecordParser(data, sizeof(data) - 2, 0, /*num_records=*/2);
349 EXPECT_TRUE(parser.ReadRecord(&record));
350 EXPECT_FALSE(parser.AtEnd());
351 EXPECT_FALSE(parser.ReadRecord(&record));
352 }
353
TEST(DnsRecordParserTest,ReadsRecordWithLongName)354 TEST(DnsRecordParserTest, ReadsRecordWithLongName) {
355 std::string dotted_name;
356 const std::vector<uint8_t> dns_name =
357 BuildRfc1034Name(dns_protocol::kMaxNameLength, &dotted_name);
358
359 std::string data(reinterpret_cast<const char*>(dns_name.data()),
360 dns_name.size());
361 data.append(
362 "\x00\x01" // TYPE=A
363 "\x00\x01" // CLASS=IN
364 "\x00\x01\x51\x80" // TTL=1 day
365 "\x00\x04" // RDLENGTH=4 bytes
366 "\xc0\xa8\x00\x01", // 192.168.0.1
367 14);
368
369 DnsRecordParser parser(data.data(), data.size(), 0, /*num_records=*/1);
370
371 DnsResourceRecord record;
372 EXPECT_TRUE(parser.ReadRecord(&record));
373 }
374
375 // Tests against incorrect name length validation, which is anti-pattern #3 from
376 // the "NAME:WRECK" report:
377 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsRecordParserTest,RejectRecordWithTooLongName)378 TEST(DnsRecordParserTest, RejectRecordWithTooLongName) {
379 std::string dotted_name;
380 const std::vector<uint8_t> dns_name =
381 BuildRfc1034Name(dns_protocol::kMaxNameLength + 1, &dotted_name);
382
383 std::string data(reinterpret_cast<const char*>(dns_name.data()),
384 dns_name.size());
385 data.append(
386 "\x00\x01" // TYPE=A
387 "\x00\x01" // CLASS=IN
388 "\x00\x01\x51\x80" // TTL=1 day
389 "\x00\x04" // RDLENGTH=4 bytes
390 "\xc0\xa8\x00\x01", // 192.168.0.1
391 14);
392
393 DnsRecordParser parser(data.data(), data.size(), 0, /*num_records=*/1);
394
395 DnsResourceRecord record;
396 EXPECT_FALSE(parser.ReadRecord(&record));
397 }
398
399 // Test that a record cannot be parsed with a name extending past the end of the
400 // data.
401 // Tests against incorrect name length validation, which is anti-pattern #3 from
402 // the "NAME:WRECK" report:
403 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsRecordParserTest,RejectRecordWithNonendedName)404 TEST(DnsRecordParserTest, RejectRecordWithNonendedName) {
405 const char kNonendedName[] = "\003www\006google\006www";
406
407 DnsRecordParser parser(kNonendedName, sizeof(kNonendedName) - 1, 0,
408 /*num_records=*/1);
409
410 DnsResourceRecord record;
411 EXPECT_FALSE(parser.ReadRecord(&record));
412 }
413
414 // Test that a record cannot be parsed with a name without final null
415 // termination. Parsing should assume the name has not ended and find the first
416 // byte of the TYPE field instead, making the remainder of the record
417 // unparsable.
418 // Tests against incorrect name null termination, which is anti-pattern #4 from
419 // the "NAME:WRECK" report:
420 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsRecordParserTest,RejectRecordNameMissingNullTermination)421 TEST(DnsRecordParserTest, RejectRecordNameMissingNullTermination) {
422 const char kData[] =
423 "\003www\006google\004test" // Name without termination.
424 "\x00\x01" // TYPE=A
425 "\x00\x01" // CLASS=IN
426 "\x00\x01\x51\x80" // TTL=1 day
427 "\x00\x04" // RDLENGTH=4 bytes
428 "\xc0\xa8\x00\x01"; // 192.168.0.1
429
430 DnsRecordParser parser(kData, sizeof(kData) - 1, 0, /*num_records=*/1);
431
432 DnsResourceRecord record;
433 EXPECT_FALSE(parser.ReadRecord(&record));
434 }
435
436 // Test that no more records can be parsed once the claimed number of records
437 // have been parsed.
TEST(DnsRecordParserTest,RejectReadingTooManyRecords)438 TEST(DnsRecordParserTest, RejectReadingTooManyRecords) {
439 const char kData[] =
440 "\003www\006google\004test\000"
441 "\x00\x01" // TYPE=A
442 "\x00\x01" // CLASS=IN
443 "\x00\x01\x51\x80" // TTL=1 day
444 "\x00\x04" // RDLENGTH=4 bytes
445 "\xc0\xa8\x00\x01" // 192.168.0.1
446 "\003www\010chromium\004test\000"
447 "\x00\x01" // TYPE=A
448 "\x00\x01" // CLASS=IN
449 "\x00\x01\x51\x80" // TTL=1 day
450 "\x00\x04" // RDLENGTH=4 bytes
451 "\xc0\xa8\x00\x02"; // 192.168.0.2
452
453 DnsRecordParser parser(
454 kData, /*length=*/sizeof(kData) - 1, /*offset=*/0,
455 /*num_records=*/1); // Claim 1 record despite there being 2 in `kData`.
456
457 DnsResourceRecord record1;
458 EXPECT_TRUE(parser.ReadRecord(&record1));
459
460 // Expect second record cannot be parsed because only 1 was expected.
461 DnsResourceRecord record2;
462 EXPECT_FALSE(parser.ReadRecord(&record2));
463 }
464
465 // Test that no more records can be parsed once the end of the buffer is
466 // reached, even if more records are claimed.
TEST(DnsRecordParserTest,RejectReadingPastEnd)467 TEST(DnsRecordParserTest, RejectReadingPastEnd) {
468 const char kData[] =
469 "\003www\006google\004test\000"
470 "\x00\x01" // TYPE=A
471 "\x00\x01" // CLASS=IN
472 "\x00\x01\x51\x80" // TTL=1 day
473 "\x00\x04" // RDLENGTH=4 bytes
474 "\xc0\xa8\x00\x01" // 192.168.0.1
475 "\003www\010chromium\004test\000"
476 "\x00\x01" // TYPE=A
477 "\x00\x01" // CLASS=IN
478 "\x00\x01\x51\x80" // TTL=1 day
479 "\x00\x04" // RDLENGTH=4 bytes
480 "\xc0\xa8\x00\x02"; // 192.168.0.2
481
482 DnsRecordParser parser(
483 kData, /*length=*/sizeof(kData) - 1, /*offset=*/0,
484 /*num_records=*/3); // Claim 3 record despite there being 2 in `kData`.
485
486 DnsResourceRecord record;
487 EXPECT_TRUE(parser.ReadRecord(&record));
488 EXPECT_TRUE(parser.ReadRecord(&record));
489 EXPECT_FALSE(parser.ReadRecord(&record));
490 }
491
TEST(DnsResponseTest,InitParse)492 TEST(DnsResponseTest, InitParse) {
493 // This includes \0 at the end.
494 const char qname[] =
495 "\x0A"
496 "codereview"
497 "\x08"
498 "chromium"
499 "\x03"
500 "org";
501 // Compilers want to copy when binding temporary to const &, so must use heap.
502 auto query = std::make_unique<DnsQuery>(
503 0xcafe, base::as_bytes(base::make_span(qname)), dns_protocol::kTypeA);
504
505 const uint8_t response_data[] = {
506 // Header
507 0xca, 0xfe, // ID
508 0x81, 0x80, // Standard query response, RA, no error
509 0x00, 0x01, // 1 question
510 0x00, 0x02, // 2 RRs (answers)
511 0x00, 0x00, // 0 authority RRs
512 0x00, 0x01, // 1 additional RRs
513
514 // Question
515 // This part is echoed back from the respective query.
516 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', 0x08, 'c', 'h',
517 'r', 'o', 'm', 'i', 'u', 'm', 0x03, 'o', 'r', 'g', 0x00, 0x00,
518 0x01, // TYPE is A.
519 0x00, 0x01, // CLASS is IN.
520
521 // Answer 1
522 0xc0, 0x0c, // NAME is a pointer to name in Question section.
523 0x00, 0x05, // TYPE is CNAME.
524 0x00, 0x01, // CLASS is IN.
525 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
526 0x24, 0x74, 0x00, 0x12, // RDLENGTH is 18 bytes.
527 // ghs.l.google.com in DNS format.
528 0x03, 'g', 'h', 's', 0x01, 'l', 0x06, 'g', 'o', 'o', 'g', 'l', 'e', 0x03,
529 'c', 'o', 'm', 0x00,
530
531 // Answer 2
532 0xc0, 0x35, // NAME is a pointer to name in Answer 1.
533 0x00, 0x01, // TYPE is A.
534 0x00, 0x01, // CLASS is IN.
535 0x00, 0x00, // TTL (4 bytes) is 53 seconds.
536 0x00, 0x35, 0x00, 0x04, // RDLENGTH is 4 bytes.
537 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121
538 0x5f, 0x79,
539
540 // Additional 1
541 0x00, // NAME is empty (root domain).
542 0x00, 0x29, // TYPE is OPT.
543 0x10, 0x00, // CLASS is max UDP payload size (4096).
544 0x00, 0x00, 0x00, 0x00, // TTL (4 bytes) is rcode, version and flags.
545 0x00, 0x08, // RDLENGTH
546 0x00, 0xFF, // OPT code
547 0x00, 0x04, // OPT data size
548 0xDE, 0xAD, 0xBE, 0xEF // OPT data
549 };
550
551 DnsResponse resp;
552 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
553
554 EXPECT_FALSE(resp.id());
555
556 // Reject too short.
557 EXPECT_FALSE(resp.InitParse(query->io_buffer()->size() - 1, *query));
558 EXPECT_FALSE(resp.IsValid());
559 EXPECT_FALSE(resp.id());
560
561 // Reject wrong id.
562 std::unique_ptr<DnsQuery> other_query = query->CloneWithNewId(0xbeef);
563 EXPECT_FALSE(resp.InitParse(sizeof(response_data), *other_query));
564 EXPECT_FALSE(resp.IsValid());
565 EXPECT_THAT(resp.id(), testing::Optional(0xcafe));
566
567 // Reject wrong question.
568 auto wrong_query = std::make_unique<DnsQuery>(
569 0xcafe, base::as_bytes(base::make_span(qname)), dns_protocol::kTypeCNAME);
570 EXPECT_FALSE(resp.InitParse(sizeof(response_data), *wrong_query));
571 EXPECT_FALSE(resp.IsValid());
572 EXPECT_THAT(resp.id(), testing::Optional(0xcafe));
573
574 // Accept matching question.
575 EXPECT_TRUE(resp.InitParse(sizeof(response_data), *query));
576 EXPECT_TRUE(resp.IsValid());
577
578 // Check header access.
579 EXPECT_THAT(resp.id(), testing::Optional(0xcafe));
580 EXPECT_EQ(0x8180, resp.flags());
581 EXPECT_EQ(0x0, resp.rcode());
582 EXPECT_EQ(2u, resp.answer_count());
583 EXPECT_EQ(1u, resp.additional_answer_count());
584
585 // Check question access.
586 absl::optional<std::vector<uint8_t>> response_qname =
587 dns_names_util::DottedNameToNetwork(resp.GetSingleDottedName());
588 ASSERT_TRUE(response_qname.has_value());
589 EXPECT_THAT(query->qname(),
590 testing::ElementsAreArray(response_qname.value()));
591 EXPECT_EQ(query->qtype(), resp.GetSingleQType());
592 EXPECT_EQ("codereview.chromium.org", resp.GetSingleDottedName());
593
594 DnsResourceRecord record;
595 DnsRecordParser parser = resp.Parser();
596 EXPECT_TRUE(parser.ReadRecord(&record));
597 EXPECT_FALSE(parser.AtEnd());
598 EXPECT_TRUE(parser.ReadRecord(&record));
599 EXPECT_FALSE(parser.AtEnd());
600 EXPECT_TRUE(parser.ReadRecord(&record));
601 EXPECT_TRUE(parser.AtEnd());
602 EXPECT_FALSE(parser.ReadRecord(&record));
603 }
604
TEST(DnsResponseTest,InitParseInvalidFlags)605 TEST(DnsResponseTest, InitParseInvalidFlags) {
606 // This includes \0 at the end.
607 const char qname[] =
608 "\x0A"
609 "codereview"
610 "\x08"
611 "chromium"
612 "\x03"
613 "org";
614 // Compilers want to copy when binding temporary to const &, so must use heap.
615 auto query = std::make_unique<DnsQuery>(
616 0xcafe, base::as_bytes(base::make_span(qname)), dns_protocol::kTypeA);
617
618 const uint8_t response_data[] = {
619 // Header
620 0xca, 0xfe, // ID
621 0x01, 0x80, // RA, no error. Note the absence of the required QR bit.
622 0x00, 0x01, // 1 question
623 0x00, 0x01, // 1 RRs (answers)
624 0x00, 0x00, // 0 authority RRs
625 0x00, 0x00, // 0 additional RRs
626
627 // Question
628 // This part is echoed back from the respective query.
629 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', 0x08, 'c', 'h',
630 'r', 'o', 'm', 'i', 'u', 'm', 0x03, 'o', 'r', 'g', 0x00, 0x00,
631 0x01, // TYPE is A.
632 0x00, 0x01, // CLASS is IN.
633
634 // Answer 1
635 0xc0, 0x0c, // NAME is a pointer to name in Question section.
636 0x00, 0x05, // TYPE is CNAME.
637 0x00, 0x01, // CLASS is IN.
638 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
639 0x24, 0x74, 0x00, 0x12, // RDLENGTH is 18 bytes.
640 // ghs.l.google.com in DNS format.
641 0x03, 'g', 'h', 's', 0x01, 'l', 0x06, 'g', 'o', 'o', 'g', 'l', 'e', 0x03,
642 'c', 'o', 'm', 0x00,
643 };
644
645 DnsResponse resp;
646 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
647
648 EXPECT_FALSE(resp.InitParse(sizeof(response_data), *query));
649 EXPECT_FALSE(resp.IsValid());
650 EXPECT_THAT(resp.id(), testing::Optional(0xcafe));
651 }
652
TEST(DnsResponseTest,InitParseRejectsResponseWithoutQuestions)653 TEST(DnsResponseTest, InitParseRejectsResponseWithoutQuestions) {
654 const char kResponse[] =
655 "\x02\x45" // ID=581
656 "\x81\x80" // Standard query response, RA, no error
657 "\x00\x00" // 0 questions
658 "\x00\x01" // 1 answers
659 "\x00\x00" // 0 authority records
660 "\x00\x00" // 0 additional records
661 "\003www\006google\004test\000" // www.google.test
662 "\x00\x01" // TYPE=A
663 "\x00\x01" // CLASS=IN
664 "\x00\x00\x2a\x30" // TTL=3 hours
665 "\x00\x04" // RDLENGTH=4 bytes
666 "\xa0\xa0\xa0\xa0"; // 10.10.10.10
667
668 DnsResponse resp;
669 memcpy(resp.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
670
671 // Validate that the response is fine if not matching against a query.
672 ASSERT_TRUE(resp.InitParseWithoutQuery(sizeof(kResponse) - 1));
673
674 const char kQueryName[] = "\003www\006google\004test";
675 DnsQuery query(
676 /*id=*/581, base::as_bytes(base::make_span(kQueryName)),
677 dns_protocol::kTypeA);
678 EXPECT_FALSE(resp.InitParse(sizeof(kResponse) - 1, query));
679 }
680
TEST(DnsResponseTest,InitParseRejectsResponseWithTooManyQuestions)681 TEST(DnsResponseTest, InitParseRejectsResponseWithTooManyQuestions) {
682 const char kResponse[] =
683 "\x02\x46" // ID=582
684 "\x81\x80" // Standard query response, RA, no error
685 "\x00\x02" // 2 questions
686 "\x00\x00" // 0 answers
687 "\x00\x00" // 0 authority records
688 "\x00\x00" // 0 additional records
689 "\003www\006google\004test\000" // www.google.test
690 "\x00\x01" // TYPE=A
691 "\x00\x01" // CLASS=IN
692 "\003www\010chromium\004test\000" // www.chromium.test
693 "\x00\x01" // TYPE=A
694 "\x00\x01"; // CLASS=IN
695
696 DnsResponse resp;
697 memcpy(resp.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
698
699 // Validate that the response is fine if not matching against a query.
700 ASSERT_TRUE(resp.InitParseWithoutQuery(sizeof(kResponse) - 1));
701
702 const char kQueryName[] = "\003www\006google\004test";
703 DnsQuery query(
704 /*id=*/582, base::as_bytes(base::make_span(kQueryName)),
705 dns_protocol::kTypeA);
706 EXPECT_FALSE(resp.InitParse(sizeof(kResponse) - 1, query));
707 }
708
TEST(DnsResponseTest,InitParseWithoutQuery)709 TEST(DnsResponseTest, InitParseWithoutQuery) {
710 DnsResponse resp;
711 memcpy(resp.io_buffer()->data(), kT0ResponseDatagram,
712 sizeof(kT0ResponseDatagram));
713
714 // Accept matching question.
715 EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(kT0ResponseDatagram)));
716 EXPECT_TRUE(resp.IsValid());
717
718 // Check header access.
719 EXPECT_EQ(0x8180, resp.flags());
720 EXPECT_EQ(0x0, resp.rcode());
721 EXPECT_EQ(kT0RecordCount, resp.answer_count());
722
723 // Check question access.
724 EXPECT_EQ(kT0Qtype, resp.GetSingleQType());
725 EXPECT_EQ(kT0HostName, resp.GetSingleDottedName());
726
727 DnsResourceRecord record;
728 DnsRecordParser parser = resp.Parser();
729 for (unsigned i = 0; i < kT0RecordCount; i ++) {
730 EXPECT_FALSE(parser.AtEnd());
731 EXPECT_TRUE(parser.ReadRecord(&record));
732 }
733 EXPECT_TRUE(parser.AtEnd());
734 EXPECT_FALSE(parser.ReadRecord(&record));
735 }
736
TEST(DnsResponseTest,InitParseWithoutQueryNoQuestions)737 TEST(DnsResponseTest, InitParseWithoutQueryNoQuestions) {
738 const uint8_t response_data[] = {
739 // Header
740 0xca, 0xfe, // ID
741 0x81, 0x80, // Standard query response, RA, no error
742 0x00, 0x00, // No question
743 0x00, 0x01, // 2 RRs (answers)
744 0x00, 0x00, // 0 authority RRs
745 0x00, 0x00, // 0 additional RRs
746
747 // Answer 1
748 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', 0x08, 'c', 'h',
749 'r', 'o', 'm', 'i', 'u', 'm', 0x03, 'o', 'r', 'g', 0x00, 0x00,
750 0x01, // TYPE is A.
751 0x00, 0x01, // CLASS is IN.
752 0x00, 0x00, // TTL (4 bytes) is 53 seconds.
753 0x00, 0x35, 0x00, 0x04, // RDLENGTH is 4 bytes.
754 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121
755 0x5f, 0x79,
756 };
757
758 DnsResponse resp;
759 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
760
761 EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
762
763 // Check header access.
764 EXPECT_THAT(resp.id(), testing::Optional(0xcafe));
765 EXPECT_EQ(0x8180, resp.flags());
766 EXPECT_EQ(0x0, resp.rcode());
767 EXPECT_EQ(0u, resp.question_count());
768 EXPECT_EQ(0x1u, resp.answer_count());
769
770 EXPECT_THAT(resp.dotted_qnames(), testing::IsEmpty());
771 EXPECT_THAT(resp.qtypes(), testing::IsEmpty());
772
773 DnsResourceRecord record;
774 DnsRecordParser parser = resp.Parser();
775
776 EXPECT_FALSE(parser.AtEnd());
777 EXPECT_TRUE(parser.ReadRecord(&record));
778 EXPECT_EQ("codereview.chromium.org", record.name);
779 EXPECT_EQ(0x00000035u, record.ttl);
780 EXPECT_EQ(dns_protocol::kTypeA, record.type);
781
782 EXPECT_TRUE(parser.AtEnd());
783 EXPECT_FALSE(parser.ReadRecord(&record));
784 }
785
TEST(DnsResponseTest,InitParseWithoutQueryInvalidFlags)786 TEST(DnsResponseTest, InitParseWithoutQueryInvalidFlags) {
787 const uint8_t response_data[] = {
788 // Header
789 0xca, 0xfe, // ID
790 0x01, 0x80, // RA, no error. Note the absence of the required QR bit.
791 0x00, 0x00, // No question
792 0x00, 0x01, // 2 RRs (answers)
793 0x00, 0x00, // 0 authority RRs
794 0x00, 0x00, // 0 additional RRs
795
796 // Answer 1
797 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', 0x08, 'c', 'h',
798 'r', 'o', 'm', 'i', 'u', 'm', 0x03, 'o', 'r', 'g', 0x00, 0x00,
799 0x01, // TYPE is A.
800 0x00, 0x01, // CLASS is IN.
801 0x00, 0x00, // TTL (4 bytes) is 53 seconds.
802 0x00, 0x35, 0x00, 0x04, // RDLENGTH is 4 bytes.
803 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121
804 0x5f, 0x79,
805 };
806
807 DnsResponse resp;
808 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
809
810 EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(response_data)));
811 EXPECT_THAT(resp.id(), testing::Optional(0xcafe));
812 }
813
TEST(DnsResponseTest,InitParseWithoutQueryTwoQuestions)814 TEST(DnsResponseTest, InitParseWithoutQueryTwoQuestions) {
815 const uint8_t response_data[] = {
816 // Header
817 0xca,
818 0xfe, // ID
819 0x81,
820 0x80, // Standard query response, RA, no error
821 0x00,
822 0x02, // 2 questions
823 0x00,
824 0x01, // 2 RRs (answers)
825 0x00,
826 0x00, // 0 authority RRs
827 0x00,
828 0x00, // 0 additional RRs
829
830 // Question 1
831 0x0a,
832 'c',
833 'o',
834 'd',
835 'e',
836 'r',
837 'e',
838 'v',
839 'i',
840 'e',
841 'w',
842 0x08,
843 'c',
844 'h',
845 'r',
846 'o',
847 'm',
848 'i',
849 'u',
850 'm',
851 0x03,
852 'o',
853 'r',
854 'g',
855 0x00,
856 0x00,
857 0x01, // TYPE is A.
858 0x00,
859 0x01, // CLASS is IN.
860
861 // Question 2
862 0x0b,
863 'c',
864 'o',
865 'd',
866 'e',
867 'r',
868 'e',
869 'v',
870 'i',
871 'e',
872 'w',
873 '2',
874 0xc0,
875 0x17, // pointer to "chromium.org"
876 0x00,
877 0x01, // TYPE is A.
878 0x00,
879 0x01, // CLASS is IN.
880
881 // Answer 1
882 0xc0,
883 0x0c, // NAME is a pointer to name in Question section.
884 0x00,
885 0x01, // TYPE is A.
886 0x00,
887 0x01, // CLASS is IN.
888 0x00,
889 0x00, // TTL (4 bytes) is 53 seconds.
890 0x00,
891 0x35,
892 0x00,
893 0x04, // RDLENGTH is 4 bytes.
894 0x4a,
895 0x7d, // RDATA is the IP: 74.125.95.121
896 0x5f,
897 0x79,
898 };
899
900 DnsResponse resp;
901 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
902
903 EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
904
905 // Check header access.
906 EXPECT_EQ(0x8180, resp.flags());
907 EXPECT_EQ(0x0, resp.rcode());
908 EXPECT_EQ(2u, resp.question_count());
909 EXPECT_EQ(0x01u, resp.answer_count());
910
911 EXPECT_THAT(resp.dotted_qnames(),
912 testing::ElementsAre("codereview.chromium.org",
913 "codereview2.chromium.org"));
914 EXPECT_THAT(resp.qtypes(),
915 testing::ElementsAre(dns_protocol::kTypeA, dns_protocol::kTypeA));
916
917 DnsResourceRecord record;
918 DnsRecordParser parser = resp.Parser();
919
920 EXPECT_FALSE(parser.AtEnd());
921 EXPECT_TRUE(parser.ReadRecord(&record));
922 EXPECT_EQ("codereview.chromium.org", record.name);
923 EXPECT_EQ(0x35u, record.ttl);
924 EXPECT_EQ(dns_protocol::kTypeA, record.type);
925
926 EXPECT_TRUE(parser.AtEnd());
927 EXPECT_FALSE(parser.ReadRecord(&record));
928 }
929
TEST(DnsResponseTest,InitParseWithoutQueryPacketTooShort)930 TEST(DnsResponseTest, InitParseWithoutQueryPacketTooShort) {
931 const uint8_t response_data[] = {
932 // Header
933 0xca, 0xfe, // ID
934 0x81, 0x80, // Standard query response, RA, no error
935 0x00, 0x00, // No question
936 };
937
938 DnsResponse resp;
939 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
940
941 EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(response_data)));
942 }
943
TEST(DnsResponseTest,InitParseAllowsQuestionWithLongName)944 TEST(DnsResponseTest, InitParseAllowsQuestionWithLongName) {
945 const char kResponseHeader[] =
946 "\x02\x45" // ID=581
947 "\x81\x80" // Standard query response, RA, no error
948 "\x00\x01" // 1 question
949 "\x00\x00" // 0 answers
950 "\x00\x00" // 0 authority records
951 "\x00\x00"; // 0 additional records
952
953 std::string dotted_name;
954 const std::vector<uint8_t> dns_name =
955 BuildRfc1034Name(dns_protocol::kMaxNameLength, &dotted_name);
956
957 std::string response_data(kResponseHeader, sizeof(kResponseHeader) - 1);
958 response_data.append(reinterpret_cast<const char*>(dns_name.data()),
959 dns_name.size());
960 response_data.append(
961 "\x00\x01" // TYPE=A
962 "\x00\x01", // CLASS=IN)
963 4);
964
965 DnsResponse resp1;
966 memcpy(resp1.io_buffer()->data(), response_data.data(), response_data.size());
967
968 EXPECT_TRUE(resp1.InitParseWithoutQuery(response_data.size()));
969
970 DnsQuery query(581, dns_name, dns_protocol::kTypeA);
971
972 DnsResponse resp2(resp1.io_buffer(), response_data.size());
973 EXPECT_TRUE(resp2.InitParse(response_data.size(), query));
974 }
975
976 // Tests against incorrect name length validation, which is anti-pattern #3 from
977 // the "NAME:WRECK" report:
978 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsResponseTest,InitParseRejectsQuestionWithTooLongName)979 TEST(DnsResponseTest, InitParseRejectsQuestionWithTooLongName) {
980 const char kResponseHeader[] =
981 "\x02\x45" // ID=581
982 "\x81\x80" // Standard query response, RA, no error
983 "\x00\x01" // 1 question
984 "\x00\x00" // 0 answers
985 "\x00\x00" // 0 authority records
986 "\x00\x00"; // 0 additional records
987
988 std::string dotted_name;
989 const std::vector<uint8_t> dns_name =
990 BuildRfc1034Name(dns_protocol::kMaxNameLength + 1, &dotted_name);
991
992 std::string response_data(kResponseHeader, sizeof(kResponseHeader) - 1);
993 response_data.append(reinterpret_cast<const char*>(dns_name.data()),
994 dns_name.size());
995 response_data.append(
996 "\x00\x01" // TYPE=A
997 "\x00\x01", // CLASS=IN)
998 4);
999
1000 DnsResponse resp;
1001 memcpy(resp.io_buffer()->data(), response_data.data(), response_data.size());
1002
1003 EXPECT_FALSE(resp.InitParseWithoutQuery(response_data.size()));
1004
1005 // Note that `DnsQuery` disallows construction without a valid name, so
1006 // `InitParse()` can never be tested with a `query` that matches against a
1007 // too-long name in the response. Test with an arbitrary valid query name to
1008 // ensure no issues if this code is exercised after receiving a response with
1009 // a too-long name.
1010 const char kQueryName[] = "\005query\004test";
1011 DnsQuery query(
1012 /*id=*/581, base::as_bytes(base::make_span(kQueryName)),
1013 dns_protocol::kTypeA);
1014 EXPECT_FALSE(resp.InitParse(response_data.size(), query));
1015 }
1016
1017 // Test that `InitParse[...]()` rejects a response with a question name
1018 // extending past the end of the response.
1019 // Tests against incorrect name length validation, which is anti-pattern #3 from
1020 // the "NAME:WRECK" report:
1021 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsResponseTest,InitParseRejectsQuestionWithNonendedName)1022 TEST(DnsResponseTest, InitParseRejectsQuestionWithNonendedName) {
1023 const char kResponse[] =
1024 "\x02\x45" // ID
1025 "\x81\x80" // Standard query response, RA, no error
1026 "\x00\x01" // 1 question
1027 "\x00\x00" // 0 answers
1028 "\x00\x00" // 0 authority records
1029 "\x00\x00" // 0 additional records
1030 "\003www\006google\006test"; // Name extending past the end.
1031
1032 DnsResponse resp;
1033 memcpy(resp.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1034
1035 EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(kResponse) - 1));
1036
1037 const char kQueryName[] = "\003www\006google\006testtt";
1038 DnsQuery query(
1039 /*id=*/581, base::as_bytes(base::make_span(kQueryName)),
1040 dns_protocol::kTypeA);
1041 EXPECT_FALSE(resp.InitParse(sizeof(kResponse) - 1, query));
1042 }
1043
1044 // Test that `InitParse[...]()` rejects responses that do not contain at least
1045 // the claimed number of questions.
1046 // Tests against incorrect record count field validation, which is anti-pattern
1047 // #5 from the "NAME:WRECK" report:
1048 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsResponseTest,InitParseRejectsResponseWithMissingQuestions)1049 TEST(DnsResponseTest, InitParseRejectsResponseWithMissingQuestions) {
1050 const char kResponse[] =
1051 "\x02\x45" // ID
1052 "\x81\x80" // Standard query response, RA, no error
1053 "\x00\x03" // 3 questions
1054 "\x00\x00" // 0 answers
1055 "\x00\x00" // 0 authority records
1056 "\x00\x00" // 0 additional records
1057 "\003www\006google\004test\000" // www.google.test
1058 "\x00\x01" // TYPE=A
1059 "\x00\x01" // CLASS=IN
1060 "\003www\010chromium\004test\000" // www.chromium.test
1061 "\x00\x01" // TYPE=A
1062 "\x00\x01"; // CLASS=IN
1063 // Missing third question.
1064
1065 DnsResponse resp;
1066 memcpy(resp.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1067
1068 EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(kResponse) - 1));
1069
1070 const char kQueryName[] = "\003www\006google\004test";
1071 DnsQuery query(
1072 /*id=*/581, base::as_bytes(base::make_span(kQueryName)),
1073 dns_protocol::kTypeA);
1074 EXPECT_FALSE(resp.InitParse(sizeof(kResponse) - 1, query));
1075 }
1076
1077 // Test that a parsed DnsResponse only allows parsing the number of records
1078 // claimed in the response header.
1079 // Tests against incorrect record count field validation, which is anti-pattern
1080 // #5 from the "NAME:WRECK" report:
1081 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsResponseTest,ParserLimitedToNumClaimedRecords)1082 TEST(DnsResponseTest, ParserLimitedToNumClaimedRecords) {
1083 const char kResponse[] =
1084 "\x02\x45" // ID
1085 "\x81\x80" // Standard query response, RA, no error
1086 "\x00\x01" // 1 question
1087 "\x00\x01" // 1 answers
1088 "\x00\x02" // 2 authority records
1089 "\x00\x01" // 1 additional records
1090 "\003www\006google\004test\000"
1091 "\x00\x01" // TYPE=A
1092 "\x00\x01" // CLASS=IN
1093 // 6 total records.
1094 "\003www\006google\004test\000"
1095 "\x00\x01" // TYPE=A
1096 "\x00\x01" // CLASS=IN
1097 "\x00\x01\x51\x80" // TTL=1 day
1098 "\x00\x04" // RDLENGTH=4 bytes
1099 "\xc0\xa8\x00\x01" // 192.168.0.1
1100 "\003www\010chromium\004test\000"
1101 "\x00\x01" // TYPE=A
1102 "\x00\x01" // CLASS=IN
1103 "\x00\x01\x51\x80" // TTL=1 day
1104 "\x00\x04" // RDLENGTH=4 bytes
1105 "\xc0\xa8\x00\x02" // 192.168.0.2
1106 "\003www\007google1\004test\000"
1107 "\x00\x01" // TYPE=A
1108 "\x00\x01" // CLASS=IN
1109 "\x00\x01\x51\x80" // TTL=1 day
1110 "\x00\x04" // RDLENGTH=4 bytes
1111 "\xc0\xa8\x00\x03" // 192.168.0.3
1112 "\003www\011chromium1\004test\000"
1113 "\x00\x01" // TYPE=A
1114 "\x00\x01" // CLASS=IN
1115 "\x00\x01\x51\x80" // TTL=1 day
1116 "\x00\x04" // RDLENGTH=4 bytes
1117 "\xc0\xa8\x00\x04" // 192.168.0.4
1118 "\003www\007google2\004test\000"
1119 "\x00\x01" // TYPE=A
1120 "\x00\x01" // CLASS=IN
1121 "\x00\x01\x51\x80" // TTL=1 day
1122 "\x00\x04" // RDLENGTH=4 bytes
1123 "\xc0\xa8\x00\x05" // 192.168.0.5
1124 "\003www\011chromium2\004test\000"
1125 "\x00\x01" // TYPE=A
1126 "\x00\x01" // CLASS=IN
1127 "\x00\x01\x51\x80" // TTL=1 day
1128 "\x00\x04" // RDLENGTH=4 bytes
1129 "\xc0\xa8\x00\x06"; // 192.168.0.6
1130
1131 DnsResponse resp1;
1132 memcpy(resp1.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1133
1134 ASSERT_TRUE(resp1.InitParseWithoutQuery(sizeof(kResponse) - 1));
1135 DnsRecordParser parser1 = resp1.Parser();
1136 ASSERT_TRUE(parser1.IsValid());
1137
1138 // Response header only claims 4 records, so expect parser to only allow
1139 // parsing that many, ignoring extra records in the data.
1140 DnsResourceRecord record;
1141 EXPECT_TRUE(parser1.ReadRecord(&record));
1142 EXPECT_TRUE(parser1.ReadRecord(&record));
1143 EXPECT_TRUE(parser1.ReadRecord(&record));
1144 EXPECT_TRUE(parser1.ReadRecord(&record));
1145 EXPECT_FALSE(parser1.ReadRecord(&record));
1146 EXPECT_FALSE(parser1.ReadRecord(&record));
1147
1148 // Repeat using InitParse()
1149 DnsResponse resp2;
1150 memcpy(resp2.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1151
1152 const char kQueryName[] = "\003www\006google\004test";
1153 DnsQuery query(
1154 /*id=*/581, base::as_bytes(base::make_span(kQueryName)),
1155 dns_protocol::kTypeA);
1156
1157 ASSERT_TRUE(resp2.InitParse(sizeof(kResponse) - 1, query));
1158 DnsRecordParser parser2 = resp2.Parser();
1159 ASSERT_TRUE(parser2.IsValid());
1160
1161 // Response header only claims 4 records, so expect parser to only allow
1162 // parsing that many, ignoring extra records in the data.
1163 EXPECT_TRUE(parser2.ReadRecord(&record));
1164 EXPECT_TRUE(parser2.ReadRecord(&record));
1165 EXPECT_TRUE(parser2.ReadRecord(&record));
1166 EXPECT_TRUE(parser2.ReadRecord(&record));
1167 EXPECT_FALSE(parser2.ReadRecord(&record));
1168 EXPECT_FALSE(parser2.ReadRecord(&record));
1169 }
1170
1171 // Test that a parsed DnsResponse does not allow parsing past the end of the
1172 // input, even if more records are claimed in the response header.
1173 // Tests against incorrect record count field validation, which is anti-pattern
1174 // #5 from the "NAME:WRECK" report:
1175 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsResponseTest,ParserLimitedToBufferSize)1176 TEST(DnsResponseTest, ParserLimitedToBufferSize) {
1177 const char kResponse[] =
1178 "\x02\x45" // ID
1179 "\x81\x80" // Standard query response, RA, no error
1180 "\x00\x01" // 1 question
1181 "\x00\x01" // 1 answers
1182 "\x00\x02" // 2 authority records
1183 "\x00\x01" // 1 additional records
1184 "\003www\006google\004test\000"
1185 "\x00\x01" // TYPE=A
1186 "\x00\x01" // CLASS=IN
1187 // 2 total records.
1188 "\003www\006google\004test\000"
1189 "\x00\x01" // TYPE=A
1190 "\x00\x01" // CLASS=IN
1191 "\x00\x01\x51\x80" // TTL=1 day
1192 "\x00\x04" // RDLENGTH=4 bytes
1193 "\xc0\xa8\x00\x01" // 192.168.0.1
1194 "\003www\010chromium\004test\000"
1195 "\x00\x01" // TYPE=A
1196 "\x00\x01" // CLASS=IN
1197 "\x00\x01\x51\x80" // TTL=1 day
1198 "\x00\x04" // RDLENGTH=4 bytes
1199 "\xc0\xa8\x00\x02"; // 192.168.0.2
1200
1201 DnsResponse resp1;
1202 memcpy(resp1.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1203
1204 ASSERT_TRUE(resp1.InitParseWithoutQuery(sizeof(kResponse) - 1));
1205 DnsRecordParser parser1 = resp1.Parser();
1206 ASSERT_TRUE(parser1.IsValid());
1207
1208 // Response header claims 4 records, but only 2 present in input.
1209 DnsResourceRecord record;
1210 EXPECT_TRUE(parser1.ReadRecord(&record));
1211 EXPECT_TRUE(parser1.ReadRecord(&record));
1212 EXPECT_FALSE(parser1.ReadRecord(&record));
1213 EXPECT_FALSE(parser1.ReadRecord(&record));
1214
1215 // Repeat using InitParse()
1216 DnsResponse resp2;
1217 memcpy(resp2.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1218
1219 ASSERT_TRUE(resp2.InitParseWithoutQuery(sizeof(kResponse) - 1));
1220 DnsRecordParser parser2 = resp2.Parser();
1221 ASSERT_TRUE(parser2.IsValid());
1222
1223 // Response header claims 4 records, but only 2 present in input.
1224 EXPECT_TRUE(parser2.ReadRecord(&record));
1225 EXPECT_TRUE(parser2.ReadRecord(&record));
1226 EXPECT_FALSE(parser2.ReadRecord(&record));
1227 EXPECT_FALSE(parser2.ReadRecord(&record));
1228 }
1229
TEST(DnsResponseWriteTest,SingleARecordAnswer)1230 TEST(DnsResponseWriteTest, SingleARecordAnswer) {
1231 const uint8_t response_data[] = {
1232 0x12, 0x34, // ID
1233 0x84, 0x00, // flags, response with authoritative answer
1234 0x00, 0x00, // number of questions
1235 0x00, 0x01, // number of answer rr
1236 0x00, 0x00, // number of name server rr
1237 0x00, 0x00, // number of additional rr
1238 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1239 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1240 0x00, // null label
1241 0x00, 0x01, // type A Record
1242 0x00, 0x01, // class IN
1243 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
1244 0x00, 0x04, // rdlength, 32 bits
1245 0xc0, 0xa8, 0x00, 0x01, // 192.168.0.1
1246 };
1247 net::DnsResourceRecord answer;
1248 answer.name = "www.example.com";
1249 answer.type = dns_protocol::kTypeA;
1250 answer.klass = dns_protocol::kClassIN;
1251 answer.ttl = 120; // 120 seconds.
1252 answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1253 std::vector<DnsResourceRecord> answers(1, answer);
1254 DnsResponse response(0x1234 /* response_id */, true /* is_authoritative*/,
1255 answers, {} /* authority_records */,
1256 {} /* additional records */, absl::nullopt);
1257 ASSERT_NE(nullptr, response.io_buffer());
1258 EXPECT_TRUE(response.IsValid());
1259 std::string expected_response(reinterpret_cast<const char*>(response_data),
1260 sizeof(response_data));
1261 std::string actual_response(response.io_buffer()->data(),
1262 response.io_buffer_size());
1263 EXPECT_EQ(expected_response, actual_response);
1264 }
1265
TEST(DnsResponseWriteTest,SingleARecordAnswerWithFinalDotInName)1266 TEST(DnsResponseWriteTest, SingleARecordAnswerWithFinalDotInName) {
1267 const uint8_t response_data[] = {
1268 0x12, 0x34, // ID
1269 0x84, 0x00, // flags, response with authoritative answer
1270 0x00, 0x00, // number of questions
1271 0x00, 0x01, // number of answer rr
1272 0x00, 0x00, // number of name server rr
1273 0x00, 0x00, // number of additional rr
1274 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1275 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1276 0x00, // null label
1277 0x00, 0x01, // type A Record
1278 0x00, 0x01, // class IN
1279 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
1280 0x00, 0x04, // rdlength, 32 bits
1281 0xc0, 0xa8, 0x00, 0x01, // 192.168.0.1
1282 };
1283 net::DnsResourceRecord answer;
1284 answer.name = "www.example.com."; // FQDN with the final dot.
1285 answer.type = dns_protocol::kTypeA;
1286 answer.klass = dns_protocol::kClassIN;
1287 answer.ttl = 120; // 120 seconds.
1288 answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1289 std::vector<DnsResourceRecord> answers(1, answer);
1290 DnsResponse response(0x1234 /* response_id */, true /* is_authoritative*/,
1291 answers, {} /* authority_records */,
1292 {} /* additional records */, absl::nullopt);
1293 ASSERT_NE(nullptr, response.io_buffer());
1294 EXPECT_TRUE(response.IsValid());
1295 std::string expected_response(reinterpret_cast<const char*>(response_data),
1296 sizeof(response_data));
1297 std::string actual_response(response.io_buffer()->data(),
1298 response.io_buffer_size());
1299 EXPECT_EQ(expected_response, actual_response);
1300 }
1301
TEST(DnsResponseWriteTest,SingleARecordAnswerWithQuestion)1302 TEST(DnsResponseWriteTest, SingleARecordAnswerWithQuestion) {
1303 const uint8_t response_data[] = {
1304 0x12, 0x34, // ID
1305 0x84, 0x00, // flags, response with authoritative answer
1306 0x00, 0x01, // number of questions
1307 0x00, 0x01, // number of answer rr
1308 0x00, 0x00, // number of name server rr
1309 0x00, 0x00, // number of additional rr
1310 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1311 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1312 0x00, // null label
1313 0x00, 0x01, // type A Record
1314 0x00, 0x01, // class IN
1315 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1316 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1317 0x00, // null label
1318 0x00, 0x01, // type A Record
1319 0x00, 0x01, // class IN
1320 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
1321 0x00, 0x04, // rdlength, 32 bits
1322 0xc0, 0xa8, 0x00, 0x01, // 192.168.0.1
1323 };
1324 std::string dotted_name("www.example.com");
1325 absl::optional<std::vector<uint8_t>> dns_name =
1326 dns_names_util::DottedNameToNetwork(dotted_name);
1327 ASSERT_TRUE(dns_name.has_value());
1328
1329 OptRecordRdata opt_rdata;
1330 opt_rdata.AddOpt(
1331 OptRecordRdata::UnknownOpt::CreateForTesting(255, "\xde\xad\xbe\xef"));
1332
1333 absl::optional<DnsQuery> query;
1334 query.emplace(0x1234 /* id */, dns_name.value(), dns_protocol::kTypeA,
1335 &opt_rdata);
1336 net::DnsResourceRecord answer;
1337 answer.name = dotted_name;
1338 answer.type = dns_protocol::kTypeA;
1339 answer.klass = dns_protocol::kClassIN;
1340 answer.ttl = 120; // 120 seconds.
1341 answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1342 std::vector<DnsResourceRecord> answers(1, answer);
1343 DnsResponse response(0x1234 /* id */, true /* is_authoritative*/, answers,
1344 {} /* authority_records */, {} /* additional records */,
1345 query);
1346 ASSERT_NE(nullptr, response.io_buffer());
1347 EXPECT_TRUE(response.IsValid());
1348 std::string expected_response(reinterpret_cast<const char*>(response_data),
1349 sizeof(response_data));
1350 std::string actual_response(response.io_buffer()->data(),
1351 response.io_buffer_size());
1352 EXPECT_EQ(expected_response, actual_response);
1353 }
1354
TEST(DnsResponseWriteTest,SingleAnswerWithQuestionConstructedFromSizeInflatedQuery)1355 TEST(DnsResponseWriteTest,
1356 SingleAnswerWithQuestionConstructedFromSizeInflatedQuery) {
1357 const uint8_t response_data[] = {
1358 0x12, 0x34, // ID
1359 0x84, 0x00, // flags, response with authoritative answer
1360 0x00, 0x01, // number of questions
1361 0x00, 0x01, // number of answer rr
1362 0x00, 0x00, // number of name server rr
1363 0x00, 0x00, // number of additional rr
1364 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1365 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1366 0x00, // null label
1367 0x00, 0x01, // type A Record
1368 0x00, 0x01, // class IN
1369 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1370 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1371 0x00, // null label
1372 0x00, 0x01, // type A Record
1373 0x00, 0x01, // class IN
1374 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
1375 0x00, 0x04, // rdlength, 32 bits
1376 0xc0, 0xa8, 0x00, 0x01, // 192.168.0.1
1377 };
1378 std::string dotted_name("www.example.com");
1379 absl::optional<std::vector<uint8_t>> dns_name =
1380 dns_names_util::DottedNameToNetwork(dotted_name);
1381 ASSERT_TRUE(dns_name.has_value());
1382 size_t buf_size =
1383 sizeof(dns_protocol::Header) + dns_name.value().size() + 2 /* qtype */ +
1384 2 /* qclass */ +
1385 10 /* extra bytes that inflate the internal buffer of a query */;
1386 auto buf = base::MakeRefCounted<IOBufferWithSize>(buf_size);
1387 memset(buf->data(), 0, buf->size());
1388 base::BigEndianWriter writer(buf->data(), buf_size);
1389 writer.WriteU16(0x1234); // id
1390 writer.WriteU16(0); // flags, is query
1391 writer.WriteU16(1); // qdcount
1392 writer.WriteU16(0); // ancount
1393 writer.WriteU16(0); // nscount
1394 writer.WriteU16(0); // arcount
1395 writer.WriteBytes(dns_name.value().data(), dns_name.value().size()); // qname
1396 writer.WriteU16(dns_protocol::kTypeA); // qtype
1397 writer.WriteU16(dns_protocol::kClassIN); // qclass
1398 // buf contains 10 extra zero bytes.
1399 absl::optional<DnsQuery> query;
1400 query.emplace(buf);
1401 query->Parse(buf_size);
1402 net::DnsResourceRecord answer;
1403 answer.name = dotted_name;
1404 answer.type = dns_protocol::kTypeA;
1405 answer.klass = dns_protocol::kClassIN;
1406 answer.ttl = 120; // 120 seconds.
1407 answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1408 std::vector<DnsResourceRecord> answers(1, answer);
1409 DnsResponse response(0x1234 /* id */, true /* is_authoritative*/, answers,
1410 {} /* authority_records */, {} /* additional records */,
1411 query);
1412 ASSERT_NE(nullptr, response.io_buffer());
1413 EXPECT_TRUE(response.IsValid());
1414 std::string expected_response(reinterpret_cast<const char*>(response_data),
1415 sizeof(response_data));
1416 std::string actual_response(response.io_buffer()->data(),
1417 response.io_buffer_size());
1418 EXPECT_EQ(expected_response, actual_response);
1419 }
1420
TEST(DnsResponseWriteTest,SingleQuadARecordAnswer)1421 TEST(DnsResponseWriteTest, SingleQuadARecordAnswer) {
1422 const uint8_t response_data[] = {
1423 0x12, 0x34, // ID
1424 0x84, 0x00, // flags, response with authoritative answer
1425 0x00, 0x00, // number of questions
1426 0x00, 0x01, // number of answer rr
1427 0x00, 0x00, // number of name server rr
1428 0x00, 0x00, // number of additional rr
1429 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1430 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1431 0x00, // null label
1432 0x00, 0x1c, // type AAAA Record
1433 0x00, 0x01, // class IN
1434 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
1435 0x00, 0x10, // rdlength, 128 bits
1436 0xfd, 0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0x01, // fd12:3456:789a:1::1
1437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1438 };
1439 net::DnsResourceRecord answer;
1440 answer.name = "www.example.com";
1441 answer.type = dns_protocol::kTypeAAAA;
1442 answer.klass = dns_protocol::kClassIN;
1443 answer.ttl = 120; // 120 seconds.
1444 answer.SetOwnedRdata(std::string(
1445 "\xfd\x12\x34\x56\x78\x9a\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01", 16));
1446 std::vector<DnsResourceRecord> answers(1, answer);
1447 DnsResponse response(0x1234 /* id */, true /* is_authoritative*/, answers,
1448 {} /* authority_records */, {} /* additional records */,
1449 absl::nullopt);
1450 ASSERT_NE(nullptr, response.io_buffer());
1451 EXPECT_TRUE(response.IsValid());
1452 std::string expected_response(reinterpret_cast<const char*>(response_data),
1453 sizeof(response_data));
1454 std::string actual_response(response.io_buffer()->data(),
1455 response.io_buffer_size());
1456 EXPECT_EQ(expected_response, actual_response);
1457 }
1458
TEST(DnsResponseWriteTest,SingleARecordAnswerWithQuestionAndNsecAdditionalRecord)1459 TEST(DnsResponseWriteTest,
1460 SingleARecordAnswerWithQuestionAndNsecAdditionalRecord) {
1461 const uint8_t response_data[] = {
1462 0x12, 0x34, // ID
1463 0x84, 0x00, // flags, response with authoritative answer
1464 0x00, 0x01, // number of questions
1465 0x00, 0x01, // number of answer rr
1466 0x00, 0x00, // number of name server rr
1467 0x00, 0x01, // number of additional rr
1468 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1469 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1470 0x00, // null label
1471 0x00, 0x01, // type A Record
1472 0x00, 0x01, // class IN
1473 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1474 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1475 0x00, // null label
1476 0x00, 0x01, // type A Record
1477 0x00, 0x01, // class IN
1478 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
1479 0x00, 0x04, // rdlength, 32 bits
1480 0xc0, 0xa8, 0x00, 0x01, // 192.168.0.1
1481 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1482 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1483 0x00, // null label
1484 0x00, 0x2f, // type NSEC Record
1485 0x00, 0x01, // class IN
1486 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
1487 0x00, 0x05, // rdlength, 5 bytes
1488 0xc0, 0x0c, // pointer to the previous "www.example.com"
1489 0x00, 0x01, 0x40, // type bit map of type A: window block 0, bitmap
1490 // length 1, bitmap with bit 1 set
1491 };
1492 std::string dotted_name("www.example.com");
1493 absl::optional<std::vector<uint8_t>> dns_name =
1494 dns_names_util::DottedNameToNetwork(dotted_name);
1495 ASSERT_TRUE(dns_name.has_value());
1496 absl::optional<DnsQuery> query;
1497 query.emplace(0x1234 /* id */, dns_name.value(), dns_protocol::kTypeA);
1498 net::DnsResourceRecord answer;
1499 answer.name = dotted_name;
1500 answer.type = dns_protocol::kTypeA;
1501 answer.klass = dns_protocol::kClassIN;
1502 answer.ttl = 120; // 120 seconds.
1503 answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1504 std::vector<DnsResourceRecord> answers(1, answer);
1505 net::DnsResourceRecord additional_record;
1506 additional_record.name = dotted_name;
1507 additional_record.type = dns_protocol::kTypeNSEC;
1508 additional_record.klass = dns_protocol::kClassIN;
1509 additional_record.ttl = 120; // 120 seconds.
1510 // Bitmap for "www.example.com" with type A set.
1511 additional_record.SetOwnedRdata(std::string("\xc0\x0c\x00\x01\x40", 5));
1512 std::vector<DnsResourceRecord> additional_records(1, additional_record);
1513 DnsResponse response(0x1234 /* id */, true /* is_authoritative*/, answers,
1514 {} /* authority_records */, additional_records, query);
1515 ASSERT_NE(nullptr, response.io_buffer());
1516 EXPECT_TRUE(response.IsValid());
1517 std::string expected_response(reinterpret_cast<const char*>(response_data),
1518 sizeof(response_data));
1519 std::string actual_response(response.io_buffer()->data(),
1520 response.io_buffer_size());
1521 EXPECT_EQ(expected_response, actual_response);
1522 }
1523
TEST(DnsResponseWriteTest,TwoAnswersWithAAndQuadARecords)1524 TEST(DnsResponseWriteTest, TwoAnswersWithAAndQuadARecords) {
1525 const uint8_t response_data[] = {
1526 0x12, 0x34, // ID
1527 0x84, 0x00, // flags, response with authoritative answer
1528 0x00, 0x00, // number of questions
1529 0x00, 0x02, // number of answer rr
1530 0x00, 0x00, // number of name server rr
1531 0x00, 0x00, // number of additional rr
1532 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
1533 0x03, 'c', 'o', 'm',
1534 0x00, // null label
1535 0x00, 0x01, // type A Record
1536 0x00, 0x01, // class IN
1537 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
1538 0x00, 0x04, // rdlength, 32 bits
1539 0xc0, 0xa8, 0x00, 0x01, // 192.168.0.1
1540 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0x03, 'o', 'r', 'g',
1541 0x00, // null label
1542 0x00, 0x1c, // type AAAA Record
1543 0x00, 0x01, // class IN
1544 0x00, 0x00, 0x00, 0x3c, // TTL, 60 seconds
1545 0x00, 0x10, // rdlength, 128 bits
1546 0xfd, 0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0x01, // fd12:3456:789a:1::1
1547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1548 };
1549 net::DnsResourceRecord answer1;
1550 answer1.name = "www.example.com";
1551 answer1.type = dns_protocol::kTypeA;
1552 answer1.klass = dns_protocol::kClassIN;
1553 answer1.ttl = 120; // 120 seconds.
1554 answer1.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1555 net::DnsResourceRecord answer2;
1556 answer2.name = "example.org";
1557 answer2.type = dns_protocol::kTypeAAAA;
1558 answer2.klass = dns_protocol::kClassIN;
1559 answer2.ttl = 60;
1560 answer2.SetOwnedRdata(std::string(
1561 "\xfd\x12\x34\x56\x78\x9a\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01", 16));
1562 std::vector<DnsResourceRecord> answers(2);
1563 answers[0] = answer1;
1564 answers[1] = answer2;
1565 DnsResponse response(0x1234 /* id */, true /* is_authoritative*/, answers,
1566 {} /* authority_records */, {} /* additional records */,
1567 absl::nullopt);
1568 ASSERT_NE(nullptr, response.io_buffer());
1569 EXPECT_TRUE(response.IsValid());
1570 std::string expected_response(reinterpret_cast<const char*>(response_data),
1571 sizeof(response_data));
1572 std::string actual_response(response.io_buffer()->data(),
1573 response.io_buffer_size());
1574 EXPECT_EQ(expected_response, actual_response);
1575 }
1576
TEST(DnsResponseWriteTest,AnswerWithAuthorityRecord)1577 TEST(DnsResponseWriteTest, AnswerWithAuthorityRecord) {
1578 const uint8_t response_data[] = {
1579 0x12, 0x35, // ID
1580 0x84, 0x00, // flags, response with authoritative answer
1581 0x00, 0x00, // number of questions
1582 0x00, 0x00, // number of answer rr
1583 0x00, 0x01, // number of name server rr
1584 0x00, 0x00, // number of additional rr
1585 0x03, 'w', 'w', 'w', 0x07, 'e', 'x', 'a',
1586 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm',
1587 0x00, // null label
1588 0x00, 0x01, // type A Record
1589 0x00, 0x01, // class IN
1590 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
1591 0x00, 0x04, // rdlength, 32 bits
1592 0xc0, 0xa8, 0x00, 0x01, // 192.168.0.1
1593 };
1594 DnsResourceRecord record;
1595 record.name = "www.example.com";
1596 record.type = dns_protocol::kTypeA;
1597 record.klass = dns_protocol::kClassIN;
1598 record.ttl = 120; // 120 seconds.
1599 record.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1600 std::vector<DnsResourceRecord> authority_records(1, record);
1601 DnsResponse response(0x1235 /* response_id */, true /* is_authoritative*/,
1602 {} /* answers */, authority_records,
1603 {} /* additional records */, absl::nullopt);
1604 ASSERT_NE(nullptr, response.io_buffer());
1605 EXPECT_TRUE(response.IsValid());
1606 std::string expected_response(reinterpret_cast<const char*>(response_data),
1607 sizeof(response_data));
1608 std::string actual_response(response.io_buffer()->data(),
1609 response.io_buffer_size());
1610 EXPECT_EQ(expected_response, actual_response);
1611 }
1612
TEST(DnsResponseWriteTest,AnswerWithRcode)1613 TEST(DnsResponseWriteTest, AnswerWithRcode) {
1614 const uint8_t response_data[] = {
1615 0x12, 0x12, // ID
1616 0x80, 0x03, // flags (response with non-existent domain)
1617 0x00, 0x00, // number of questions
1618 0x00, 0x00, // number of answer rr
1619 0x00, 0x00, // number of name server rr
1620 0x00, 0x00, // number of additional rr
1621 };
1622 DnsResponse response(0x1212 /* response_id */, false /* is_authoritative*/,
1623 {} /* answers */, {} /* authority_records */,
1624 {} /* additional records */, absl::nullopt,
1625 dns_protocol::kRcodeNXDOMAIN);
1626 ASSERT_NE(nullptr, response.io_buffer());
1627 EXPECT_TRUE(response.IsValid());
1628 std::string expected_response(reinterpret_cast<const char*>(response_data),
1629 sizeof(response_data));
1630 std::string actual_response(response.io_buffer()->data(),
1631 response.io_buffer_size());
1632 EXPECT_EQ(expected_response, actual_response);
1633 EXPECT_EQ(dns_protocol::kRcodeNXDOMAIN, response.rcode());
1634 }
1635
1636 // CNAME answers are always allowed for any question.
TEST(DnsResponseWriteTest,AAAAQuestionAndCnameAnswer)1637 TEST(DnsResponseWriteTest, AAAAQuestionAndCnameAnswer) {
1638 const std::string kName = "www.example.com";
1639 absl::optional<std::vector<uint8_t>> dns_name =
1640 dns_names_util::DottedNameToNetwork(kName);
1641 ASSERT_TRUE(dns_name.has_value());
1642
1643 DnsResourceRecord answer;
1644 answer.name = kName;
1645 answer.type = dns_protocol::kTypeCNAME;
1646 answer.klass = dns_protocol::kClassIN;
1647 answer.ttl = 120; // 120 seconds.
1648 answer.SetOwnedRdata(
1649 std::string(reinterpret_cast<char*>(dns_name.value().data()),
1650 dns_name.value().size()));
1651 std::vector<DnsResourceRecord> answers(1, answer);
1652
1653 absl::optional<DnsQuery> query(absl::in_place, 114 /* id */, dns_name.value(),
1654 dns_protocol::kTypeAAAA);
1655
1656 DnsResponse response(114 /* response_id */, true /* is_authoritative*/,
1657 answers, {} /* authority_records */,
1658 {} /* additional records */, query);
1659
1660 EXPECT_TRUE(response.IsValid());
1661 }
1662
TEST(DnsResponseWriteTest,WrittenResponseCanBeParsed)1663 TEST(DnsResponseWriteTest, WrittenResponseCanBeParsed) {
1664 std::string dotted_name("www.example.com");
1665 net::DnsResourceRecord answer;
1666 answer.name = dotted_name;
1667 answer.type = dns_protocol::kTypeA;
1668 answer.klass = dns_protocol::kClassIN;
1669 answer.ttl = 120; // 120 seconds.
1670 answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1671 std::vector<DnsResourceRecord> answers(1, answer);
1672 net::DnsResourceRecord additional_record;
1673 additional_record.name = dotted_name;
1674 additional_record.type = dns_protocol::kTypeNSEC;
1675 additional_record.klass = dns_protocol::kClassIN;
1676 additional_record.ttl = 120; // 120 seconds.
1677 additional_record.SetOwnedRdata(std::string("\xc0\x0c\x00\x01\x04", 5));
1678 std::vector<DnsResourceRecord> additional_records(1, additional_record);
1679 DnsResponse response(0x1234 /* response_id */, true /* is_authoritative*/,
1680 answers, {} /* authority_records */, additional_records,
1681 absl::nullopt);
1682 ASSERT_NE(nullptr, response.io_buffer());
1683 EXPECT_TRUE(response.IsValid());
1684 EXPECT_THAT(response.id(), testing::Optional(0x1234));
1685 EXPECT_EQ(1u, response.answer_count());
1686 EXPECT_EQ(1u, response.additional_answer_count());
1687 auto parser = response.Parser();
1688 net::DnsResourceRecord parsed_record;
1689 EXPECT_TRUE(parser.ReadRecord(&parsed_record));
1690 // Answer with an A record.
1691 EXPECT_EQ(answer.name, parsed_record.name);
1692 EXPECT_EQ(answer.type, parsed_record.type);
1693 EXPECT_EQ(answer.klass, parsed_record.klass);
1694 EXPECT_EQ(answer.ttl, parsed_record.ttl);
1695 EXPECT_EQ(answer.owned_rdata, parsed_record.rdata);
1696 // Additional NSEC record.
1697 EXPECT_TRUE(parser.ReadRecord(&parsed_record));
1698 EXPECT_EQ(additional_record.name, parsed_record.name);
1699 EXPECT_EQ(additional_record.type, parsed_record.type);
1700 EXPECT_EQ(additional_record.klass, parsed_record.klass);
1701 EXPECT_EQ(additional_record.ttl, parsed_record.ttl);
1702 EXPECT_EQ(additional_record.owned_rdata, parsed_record.rdata);
1703 }
1704
TEST(DnsResponseWriteTest,CreateEmptyNoDataResponse)1705 TEST(DnsResponseWriteTest, CreateEmptyNoDataResponse) {
1706 DnsResponse response = DnsResponse::CreateEmptyNoDataResponse(
1707 /*id=*/4,
1708 /*is_authoritative=*/true,
1709 base::as_bytes(base::make_span("\x04name\x04test\x00")),
1710 dns_protocol::kTypeA);
1711
1712 EXPECT_TRUE(response.IsValid());
1713 EXPECT_THAT(response.id(), testing::Optional(4));
1714 EXPECT_TRUE(response.flags() & dns_protocol::kFlagAA);
1715 EXPECT_EQ(response.question_count(), 1u);
1716 EXPECT_EQ(response.answer_count(), 0u);
1717 EXPECT_EQ(response.authority_count(), 0u);
1718 EXPECT_EQ(response.additional_answer_count(), 0u);
1719
1720 EXPECT_THAT(response.qtypes(), testing::ElementsAre(dns_protocol::kTypeA));
1721 EXPECT_THAT(response.dotted_qnames(), testing::ElementsAre("name.test"));
1722 }
1723
1724 } // namespace
1725
1726 } // namespace net
1727