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