xref: /aosp_15_r20/external/cronet/net/dns/dns_response_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 <optional>
10 #include <string>
11 #include <string_view>
12 #include <vector>
13 
14 #include "base/check.h"
15 #include "base/containers/span.h"
16 #include "base/containers/span_writer.h"
17 #include "base/time/time.h"
18 #include "net/base/io_buffer.h"
19 #include "net/dns/dns_names_util.h"
20 #include "net/dns/dns_query.h"
21 #include "net/dns/dns_test_util.h"
22 #include "net/dns/public/dns_protocol.h"
23 #include "net/dns/record_rdata.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.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, 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(std::string_view("\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>(0xcafe, base::as_byte_span(qname),
503                                           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_byte_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   std::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>(0xcafe, base::as_byte_span(qname),
616                                           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_byte_span(kQueryName), dns_protocol::kTypeA);
677   EXPECT_FALSE(resp.InitParse(sizeof(kResponse) - 1, query));
678 }
679 
TEST(DnsResponseTest,InitParseRejectsResponseWithTooManyQuestions)680 TEST(DnsResponseTest, InitParseRejectsResponseWithTooManyQuestions) {
681   const char kResponse[] =
682       "\x02\x46"                       // ID=582
683       "\x81\x80"                       // Standard query response, RA, no error
684       "\x00\x02"                       // 2 questions
685       "\x00\x00"                       // 0 answers
686       "\x00\x00"                       // 0 authority records
687       "\x00\x00"                       // 0 additional records
688       "\003www\006google\004test\000"  // www.google.test
689       "\x00\x01"                       // TYPE=A
690       "\x00\x01"                       // CLASS=IN
691       "\003www\010chromium\004test\000"  // www.chromium.test
692       "\x00\x01"                         // TYPE=A
693       "\x00\x01";                        // CLASS=IN
694 
695   DnsResponse resp;
696   memcpy(resp.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
697 
698   // Validate that the response is fine if not matching against a query.
699   ASSERT_TRUE(resp.InitParseWithoutQuery(sizeof(kResponse) - 1));
700 
701   const char kQueryName[] = "\003www\006google\004test";
702   DnsQuery query(
703       /*id=*/582, base::as_byte_span(kQueryName), dns_protocol::kTypeA);
704   EXPECT_FALSE(resp.InitParse(sizeof(kResponse) - 1, query));
705 }
706 
TEST(DnsResponseTest,InitParseWithoutQuery)707 TEST(DnsResponseTest, InitParseWithoutQuery) {
708   DnsResponse resp;
709   memcpy(resp.io_buffer()->data(), kT0ResponseDatagram,
710          sizeof(kT0ResponseDatagram));
711 
712   // Accept matching question.
713   EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(kT0ResponseDatagram)));
714   EXPECT_TRUE(resp.IsValid());
715 
716   // Check header access.
717   EXPECT_EQ(0x8180, resp.flags());
718   EXPECT_EQ(0x0, resp.rcode());
719   EXPECT_EQ(kT0RecordCount, resp.answer_count());
720 
721   // Check question access.
722   EXPECT_EQ(kT0Qtype, resp.GetSingleQType());
723   EXPECT_EQ(kT0HostName, resp.GetSingleDottedName());
724 
725   DnsResourceRecord record;
726   DnsRecordParser parser = resp.Parser();
727   for (unsigned i = 0; i < kT0RecordCount; i ++) {
728     EXPECT_FALSE(parser.AtEnd());
729     EXPECT_TRUE(parser.ReadRecord(&record));
730   }
731   EXPECT_TRUE(parser.AtEnd());
732   EXPECT_FALSE(parser.ReadRecord(&record));
733 }
734 
TEST(DnsResponseTest,InitParseWithoutQueryNoQuestions)735 TEST(DnsResponseTest, InitParseWithoutQueryNoQuestions) {
736   const uint8_t response_data[] = {
737       // Header
738       0xca, 0xfe,  // ID
739       0x81, 0x80,  // Standard query response, RA, no error
740       0x00, 0x00,  // No question
741       0x00, 0x01,  // 2 RRs (answers)
742       0x00, 0x00,  // 0 authority RRs
743       0x00, 0x00,  // 0 additional RRs
744 
745       // Answer 1
746       0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', 0x08, 'c', 'h',
747       'r', 'o', 'm', 'i', 'u', 'm', 0x03, 'o', 'r', 'g', 0x00, 0x00,
748       0x01,                    // TYPE is A.
749       0x00, 0x01,              // CLASS is IN.
750       0x00, 0x00,              // TTL (4 bytes) is 53 seconds.
751       0x00, 0x35, 0x00, 0x04,  // RDLENGTH is 4 bytes.
752       0x4a, 0x7d,              // RDATA is the IP: 74.125.95.121
753       0x5f, 0x79,
754   };
755 
756   DnsResponse resp;
757   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
758 
759   EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
760 
761   // Check header access.
762   EXPECT_THAT(resp.id(), testing::Optional(0xcafe));
763   EXPECT_EQ(0x8180, resp.flags());
764   EXPECT_EQ(0x0, resp.rcode());
765   EXPECT_EQ(0u, resp.question_count());
766   EXPECT_EQ(0x1u, resp.answer_count());
767 
768   EXPECT_THAT(resp.dotted_qnames(), testing::IsEmpty());
769   EXPECT_THAT(resp.qtypes(), testing::IsEmpty());
770 
771   DnsResourceRecord record;
772   DnsRecordParser parser = resp.Parser();
773 
774   EXPECT_FALSE(parser.AtEnd());
775   EXPECT_TRUE(parser.ReadRecord(&record));
776   EXPECT_EQ("codereview.chromium.org", record.name);
777   EXPECT_EQ(0x00000035u, record.ttl);
778   EXPECT_EQ(dns_protocol::kTypeA, record.type);
779 
780   EXPECT_TRUE(parser.AtEnd());
781   EXPECT_FALSE(parser.ReadRecord(&record));
782 }
783 
TEST(DnsResponseTest,InitParseWithoutQueryInvalidFlags)784 TEST(DnsResponseTest, InitParseWithoutQueryInvalidFlags) {
785   const uint8_t response_data[] = {
786       // Header
787       0xca, 0xfe,  // ID
788       0x01, 0x80,  // RA, no error. Note the absence of the required QR bit.
789       0x00, 0x00,  // No question
790       0x00, 0x01,  // 2 RRs (answers)
791       0x00, 0x00,  // 0 authority RRs
792       0x00, 0x00,  // 0 additional RRs
793 
794       // Answer 1
795       0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', 0x08, 'c', 'h',
796       'r', 'o', 'm', 'i', 'u', 'm', 0x03, 'o', 'r', 'g', 0x00, 0x00,
797       0x01,                    // TYPE is A.
798       0x00, 0x01,              // CLASS is IN.
799       0x00, 0x00,              // TTL (4 bytes) is 53 seconds.
800       0x00, 0x35, 0x00, 0x04,  // RDLENGTH is 4 bytes.
801       0x4a, 0x7d,              // RDATA is the IP: 74.125.95.121
802       0x5f, 0x79,
803   };
804 
805   DnsResponse resp;
806   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
807 
808   EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(response_data)));
809   EXPECT_THAT(resp.id(), testing::Optional(0xcafe));
810 }
811 
TEST(DnsResponseTest,InitParseWithoutQueryTwoQuestions)812 TEST(DnsResponseTest, InitParseWithoutQueryTwoQuestions) {
813   const uint8_t response_data[] = {
814       // Header
815       0xca,
816       0xfe,  // ID
817       0x81,
818       0x80,  // Standard query response, RA, no error
819       0x00,
820       0x02,  // 2 questions
821       0x00,
822       0x01,  // 2 RRs (answers)
823       0x00,
824       0x00,  // 0 authority RRs
825       0x00,
826       0x00,  // 0 additional RRs
827 
828       // Question 1
829       0x0a,
830       'c',
831       'o',
832       'd',
833       'e',
834       'r',
835       'e',
836       'v',
837       'i',
838       'e',
839       'w',
840       0x08,
841       'c',
842       'h',
843       'r',
844       'o',
845       'm',
846       'i',
847       'u',
848       'm',
849       0x03,
850       'o',
851       'r',
852       'g',
853       0x00,
854       0x00,
855       0x01,  // TYPE is A.
856       0x00,
857       0x01,  // CLASS is IN.
858 
859       // Question 2
860       0x0b,
861       'c',
862       'o',
863       'd',
864       'e',
865       'r',
866       'e',
867       'v',
868       'i',
869       'e',
870       'w',
871       '2',
872       0xc0,
873       0x17,  // pointer to "chromium.org"
874       0x00,
875       0x01,  // TYPE is A.
876       0x00,
877       0x01,  // CLASS is IN.
878 
879       // Answer 1
880       0xc0,
881       0x0c,  // NAME is a pointer to name in Question section.
882       0x00,
883       0x01,  // TYPE is A.
884       0x00,
885       0x01,  // CLASS is IN.
886       0x00,
887       0x00,  // TTL (4 bytes) is 53 seconds.
888       0x00,
889       0x35,
890       0x00,
891       0x04,  // RDLENGTH is 4 bytes.
892       0x4a,
893       0x7d,  // RDATA is the IP: 74.125.95.121
894       0x5f,
895       0x79,
896   };
897 
898   DnsResponse resp;
899   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
900 
901   EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
902 
903   // Check header access.
904   EXPECT_EQ(0x8180, resp.flags());
905   EXPECT_EQ(0x0, resp.rcode());
906   EXPECT_EQ(2u, resp.question_count());
907   EXPECT_EQ(0x01u, resp.answer_count());
908 
909   EXPECT_THAT(resp.dotted_qnames(),
910               testing::ElementsAre("codereview.chromium.org",
911                                    "codereview2.chromium.org"));
912   EXPECT_THAT(resp.qtypes(),
913               testing::ElementsAre(dns_protocol::kTypeA, dns_protocol::kTypeA));
914 
915   DnsResourceRecord record;
916   DnsRecordParser parser = resp.Parser();
917 
918   EXPECT_FALSE(parser.AtEnd());
919   EXPECT_TRUE(parser.ReadRecord(&record));
920   EXPECT_EQ("codereview.chromium.org", record.name);
921   EXPECT_EQ(0x35u, record.ttl);
922   EXPECT_EQ(dns_protocol::kTypeA, record.type);
923 
924   EXPECT_TRUE(parser.AtEnd());
925   EXPECT_FALSE(parser.ReadRecord(&record));
926 }
927 
TEST(DnsResponseTest,InitParseWithoutQueryPacketTooShort)928 TEST(DnsResponseTest, InitParseWithoutQueryPacketTooShort) {
929   const uint8_t response_data[] = {
930       // Header
931       0xca, 0xfe,  // ID
932       0x81, 0x80,  // Standard query response, RA, no error
933       0x00, 0x00,  // No question
934   };
935 
936   DnsResponse resp;
937   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
938 
939   EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(response_data)));
940 }
941 
TEST(DnsResponseTest,InitParseAllowsQuestionWithLongName)942 TEST(DnsResponseTest, InitParseAllowsQuestionWithLongName) {
943   const char kResponseHeader[] =
944       "\x02\x45"   // ID=581
945       "\x81\x80"   // Standard query response, RA, no error
946       "\x00\x01"   // 1 question
947       "\x00\x00"   // 0 answers
948       "\x00\x00"   // 0 authority records
949       "\x00\x00";  // 0 additional records
950 
951   std::string dotted_name;
952   const std::vector<uint8_t> dns_name =
953       BuildRfc1034Name(dns_protocol::kMaxNameLength, &dotted_name);
954 
955   std::string response_data(kResponseHeader, sizeof(kResponseHeader) - 1);
956   response_data.append(reinterpret_cast<const char*>(dns_name.data()),
957                        dns_name.size());
958   response_data.append(
959       "\x00\x01"   // TYPE=A
960       "\x00\x01",  // CLASS=IN)
961       4);
962 
963   DnsResponse resp1;
964   memcpy(resp1.io_buffer()->data(), response_data.data(), response_data.size());
965 
966   EXPECT_TRUE(resp1.InitParseWithoutQuery(response_data.size()));
967 
968   DnsQuery query(581, dns_name, dns_protocol::kTypeA);
969 
970   DnsResponse resp2(resp1.io_buffer(), response_data.size());
971   EXPECT_TRUE(resp2.InitParse(response_data.size(), query));
972 }
973 
974 // Tests against incorrect name length validation, which is anti-pattern #3 from
975 // the "NAME:WRECK" report:
976 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsResponseTest,InitParseRejectsQuestionWithTooLongName)977 TEST(DnsResponseTest, InitParseRejectsQuestionWithTooLongName) {
978   const char kResponseHeader[] =
979       "\x02\x45"   // ID=581
980       "\x81\x80"   // Standard query response, RA, no error
981       "\x00\x01"   // 1 question
982       "\x00\x00"   // 0 answers
983       "\x00\x00"   // 0 authority records
984       "\x00\x00";  // 0 additional records
985 
986   std::string dotted_name;
987   const std::vector<uint8_t> dns_name =
988       BuildRfc1034Name(dns_protocol::kMaxNameLength + 1, &dotted_name);
989 
990   std::string response_data(kResponseHeader, sizeof(kResponseHeader) - 1);
991   response_data.append(reinterpret_cast<const char*>(dns_name.data()),
992                        dns_name.size());
993   response_data.append(
994       "\x00\x01"   // TYPE=A
995       "\x00\x01",  // CLASS=IN)
996       4);
997 
998   DnsResponse resp;
999   memcpy(resp.io_buffer()->data(), response_data.data(), response_data.size());
1000 
1001   EXPECT_FALSE(resp.InitParseWithoutQuery(response_data.size()));
1002 
1003   // Note that `DnsQuery` disallows construction without a valid name, so
1004   // `InitParse()` can never be tested with a `query` that matches against a
1005   // too-long name in the response. Test with an arbitrary valid query name to
1006   // ensure no issues if this code is exercised after receiving a response with
1007   // a too-long name.
1008   const char kQueryName[] = "\005query\004test";
1009   DnsQuery query(
1010       /*id=*/581, base::as_byte_span(kQueryName), dns_protocol::kTypeA);
1011   EXPECT_FALSE(resp.InitParse(response_data.size(), query));
1012 }
1013 
1014 // Test that `InitParse[...]()` rejects a response with a question name
1015 // extending past the end of the response.
1016 // Tests against incorrect name length validation, which is anti-pattern #3 from
1017 // the "NAME:WRECK" report:
1018 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsResponseTest,InitParseRejectsQuestionWithNonendedName)1019 TEST(DnsResponseTest, InitParseRejectsQuestionWithNonendedName) {
1020   const char kResponse[] =
1021       "\x02\x45"                    // ID
1022       "\x81\x80"                    // Standard query response, RA, no error
1023       "\x00\x01"                    // 1 question
1024       "\x00\x00"                    // 0 answers
1025       "\x00\x00"                    // 0 authority records
1026       "\x00\x00"                    // 0 additional records
1027       "\003www\006google\006test";  // Name extending past the end.
1028 
1029   DnsResponse resp;
1030   memcpy(resp.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1031 
1032   EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(kResponse) - 1));
1033 
1034   const char kQueryName[] = "\003www\006google\006testtt";
1035   DnsQuery query(
1036       /*id=*/581, base::as_byte_span(kQueryName), dns_protocol::kTypeA);
1037   EXPECT_FALSE(resp.InitParse(sizeof(kResponse) - 1, query));
1038 }
1039 
1040 // Test that `InitParse[...]()` rejects responses that do not contain at least
1041 // the claimed number of questions.
1042 // Tests against incorrect record count field validation, which is anti-pattern
1043 // #5 from the "NAME:WRECK" report:
1044 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsResponseTest,InitParseRejectsResponseWithMissingQuestions)1045 TEST(DnsResponseTest, InitParseRejectsResponseWithMissingQuestions) {
1046   const char kResponse[] =
1047       "\x02\x45"                       // ID
1048       "\x81\x80"                       // Standard query response, RA, no error
1049       "\x00\x03"                       // 3 questions
1050       "\x00\x00"                       // 0 answers
1051       "\x00\x00"                       // 0 authority records
1052       "\x00\x00"                       // 0 additional records
1053       "\003www\006google\004test\000"  // www.google.test
1054       "\x00\x01"                       // TYPE=A
1055       "\x00\x01"                       // CLASS=IN
1056       "\003www\010chromium\004test\000"  // www.chromium.test
1057       "\x00\x01"                         // TYPE=A
1058       "\x00\x01";                        // CLASS=IN
1059   // Missing third question.
1060 
1061   DnsResponse resp;
1062   memcpy(resp.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1063 
1064   EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(kResponse) - 1));
1065 
1066   const char kQueryName[] = "\003www\006google\004test";
1067   DnsQuery query(
1068       /*id=*/581, base::as_byte_span(kQueryName), dns_protocol::kTypeA);
1069   EXPECT_FALSE(resp.InitParse(sizeof(kResponse) - 1, query));
1070 }
1071 
1072 // Test that a parsed DnsResponse only allows parsing the number of records
1073 // claimed in the response header.
1074 // Tests against incorrect record count field validation, which is anti-pattern
1075 // #5 from the "NAME:WRECK" report:
1076 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsResponseTest,ParserLimitedToNumClaimedRecords)1077 TEST(DnsResponseTest, ParserLimitedToNumClaimedRecords) {
1078   const char kResponse[] =
1079       "\x02\x45"  // ID
1080       "\x81\x80"  // Standard query response, RA, no error
1081       "\x00\x01"  // 1 question
1082       "\x00\x01"  // 1 answers
1083       "\x00\x02"  // 2 authority records
1084       "\x00\x01"  // 1 additional records
1085       "\003www\006google\004test\000"
1086       "\x00\x01"  // TYPE=A
1087       "\x00\x01"  // CLASS=IN
1088       // 6 total records.
1089       "\003www\006google\004test\000"
1090       "\x00\x01"          // TYPE=A
1091       "\x00\x01"          // CLASS=IN
1092       "\x00\x01\x51\x80"  // TTL=1 day
1093       "\x00\x04"          // RDLENGTH=4 bytes
1094       "\xc0\xa8\x00\x01"  // 192.168.0.1
1095       "\003www\010chromium\004test\000"
1096       "\x00\x01"          // TYPE=A
1097       "\x00\x01"          // CLASS=IN
1098       "\x00\x01\x51\x80"  // TTL=1 day
1099       "\x00\x04"          // RDLENGTH=4 bytes
1100       "\xc0\xa8\x00\x02"  // 192.168.0.2
1101       "\003www\007google1\004test\000"
1102       "\x00\x01"          // TYPE=A
1103       "\x00\x01"          // CLASS=IN
1104       "\x00\x01\x51\x80"  // TTL=1 day
1105       "\x00\x04"          // RDLENGTH=4 bytes
1106       "\xc0\xa8\x00\x03"  // 192.168.0.3
1107       "\003www\011chromium1\004test\000"
1108       "\x00\x01"          // TYPE=A
1109       "\x00\x01"          // CLASS=IN
1110       "\x00\x01\x51\x80"  // TTL=1 day
1111       "\x00\x04"          // RDLENGTH=4 bytes
1112       "\xc0\xa8\x00\x04"  // 192.168.0.4
1113       "\003www\007google2\004test\000"
1114       "\x00\x01"          // TYPE=A
1115       "\x00\x01"          // CLASS=IN
1116       "\x00\x01\x51\x80"  // TTL=1 day
1117       "\x00\x04"          // RDLENGTH=4 bytes
1118       "\xc0\xa8\x00\x05"  // 192.168.0.5
1119       "\003www\011chromium2\004test\000"
1120       "\x00\x01"           // TYPE=A
1121       "\x00\x01"           // CLASS=IN
1122       "\x00\x01\x51\x80"   // TTL=1 day
1123       "\x00\x04"           // RDLENGTH=4 bytes
1124       "\xc0\xa8\x00\x06";  // 192.168.0.6
1125 
1126   DnsResponse resp1;
1127   memcpy(resp1.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1128 
1129   ASSERT_TRUE(resp1.InitParseWithoutQuery(sizeof(kResponse) - 1));
1130   DnsRecordParser parser1 = resp1.Parser();
1131   ASSERT_TRUE(parser1.IsValid());
1132 
1133   // Response header only claims 4 records, so expect parser to only allow
1134   // parsing that many, ignoring extra records in the data.
1135   DnsResourceRecord record;
1136   EXPECT_TRUE(parser1.ReadRecord(&record));
1137   EXPECT_TRUE(parser1.ReadRecord(&record));
1138   EXPECT_TRUE(parser1.ReadRecord(&record));
1139   EXPECT_TRUE(parser1.ReadRecord(&record));
1140   EXPECT_FALSE(parser1.ReadRecord(&record));
1141   EXPECT_FALSE(parser1.ReadRecord(&record));
1142 
1143   // Repeat using InitParse()
1144   DnsResponse resp2;
1145   memcpy(resp2.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1146 
1147   const char kQueryName[] = "\003www\006google\004test";
1148   DnsQuery query(
1149       /*id=*/581, base::as_byte_span(kQueryName), dns_protocol::kTypeA);
1150 
1151   ASSERT_TRUE(resp2.InitParse(sizeof(kResponse) - 1, query));
1152   DnsRecordParser parser2 = resp2.Parser();
1153   ASSERT_TRUE(parser2.IsValid());
1154 
1155   // Response header only claims 4 records, so expect parser to only allow
1156   // parsing that many, ignoring extra records in the data.
1157   EXPECT_TRUE(parser2.ReadRecord(&record));
1158   EXPECT_TRUE(parser2.ReadRecord(&record));
1159   EXPECT_TRUE(parser2.ReadRecord(&record));
1160   EXPECT_TRUE(parser2.ReadRecord(&record));
1161   EXPECT_FALSE(parser2.ReadRecord(&record));
1162   EXPECT_FALSE(parser2.ReadRecord(&record));
1163 }
1164 
1165 // Test that a parsed DnsResponse does not allow parsing past the end of the
1166 // input, even if more records are claimed in the response header.
1167 // Tests against incorrect record count field validation, which is anti-pattern
1168 // #5 from the "NAME:WRECK" report:
1169 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST(DnsResponseTest,ParserLimitedToBufferSize)1170 TEST(DnsResponseTest, ParserLimitedToBufferSize) {
1171   const char kResponse[] =
1172       "\x02\x45"  // ID
1173       "\x81\x80"  // Standard query response, RA, no error
1174       "\x00\x01"  // 1 question
1175       "\x00\x01"  // 1 answers
1176       "\x00\x02"  // 2 authority records
1177       "\x00\x01"  // 1 additional records
1178       "\003www\006google\004test\000"
1179       "\x00\x01"  // TYPE=A
1180       "\x00\x01"  // CLASS=IN
1181       // 2 total records.
1182       "\003www\006google\004test\000"
1183       "\x00\x01"          // TYPE=A
1184       "\x00\x01"          // CLASS=IN
1185       "\x00\x01\x51\x80"  // TTL=1 day
1186       "\x00\x04"          // RDLENGTH=4 bytes
1187       "\xc0\xa8\x00\x01"  // 192.168.0.1
1188       "\003www\010chromium\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\x02";  // 192.168.0.2
1194 
1195   DnsResponse resp1;
1196   memcpy(resp1.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1197 
1198   ASSERT_TRUE(resp1.InitParseWithoutQuery(sizeof(kResponse) - 1));
1199   DnsRecordParser parser1 = resp1.Parser();
1200   ASSERT_TRUE(parser1.IsValid());
1201 
1202   // Response header claims 4 records, but only 2 present in input.
1203   DnsResourceRecord record;
1204   EXPECT_TRUE(parser1.ReadRecord(&record));
1205   EXPECT_TRUE(parser1.ReadRecord(&record));
1206   EXPECT_FALSE(parser1.ReadRecord(&record));
1207   EXPECT_FALSE(parser1.ReadRecord(&record));
1208 
1209   // Repeat using InitParse()
1210   DnsResponse resp2;
1211   memcpy(resp2.io_buffer()->data(), kResponse, sizeof(kResponse) - 1);
1212 
1213   ASSERT_TRUE(resp2.InitParseWithoutQuery(sizeof(kResponse) - 1));
1214   DnsRecordParser parser2 = resp2.Parser();
1215   ASSERT_TRUE(parser2.IsValid());
1216 
1217   // Response header claims 4 records, but only 2 present in input.
1218   EXPECT_TRUE(parser2.ReadRecord(&record));
1219   EXPECT_TRUE(parser2.ReadRecord(&record));
1220   EXPECT_FALSE(parser2.ReadRecord(&record));
1221   EXPECT_FALSE(parser2.ReadRecord(&record));
1222 }
1223 
TEST(DnsResponseWriteTest,SingleARecordAnswer)1224 TEST(DnsResponseWriteTest, SingleARecordAnswer) {
1225   const uint8_t response_data[] = {
1226       0x12, 0x34,  // ID
1227       0x84, 0x00,  // flags, response with authoritative answer
1228       0x00, 0x00,  // number of questions
1229       0x00, 0x01,  // number of answer rr
1230       0x00, 0x00,  // number of name server rr
1231       0x00, 0x00,  // number of additional rr
1232       0x03, 'w',  'w',  'w',  0x07, 'e', 'x', 'a',
1233       'm',  'p',  'l',  'e',  0x03, 'c', 'o', 'm',
1234       0x00,                    // null label
1235       0x00, 0x01,              // type A Record
1236       0x00, 0x01,              // class IN
1237       0x00, 0x00, 0x00, 0x78,  // TTL, 120 seconds
1238       0x00, 0x04,              // rdlength, 32 bits
1239       0xc0, 0xa8, 0x00, 0x01,  // 192.168.0.1
1240   };
1241   net::DnsResourceRecord answer;
1242   answer.name = "www.example.com";
1243   answer.type = dns_protocol::kTypeA;
1244   answer.klass = dns_protocol::kClassIN;
1245   answer.ttl = 120;  // 120 seconds.
1246   answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1247   std::vector<DnsResourceRecord> answers(1, answer);
1248   DnsResponse response(0x1234 /* response_id */, true /* is_authoritative*/,
1249                        answers, {} /* authority_records */,
1250                        {} /* additional records */, std::nullopt);
1251   ASSERT_NE(nullptr, response.io_buffer());
1252   EXPECT_TRUE(response.IsValid());
1253   std::string expected_response(reinterpret_cast<const char*>(response_data),
1254                                 sizeof(response_data));
1255   std::string actual_response(response.io_buffer()->data(),
1256                               response.io_buffer_size());
1257   EXPECT_EQ(expected_response, actual_response);
1258 }
1259 
TEST(DnsResponseWriteTest,SingleARecordAnswerWithFinalDotInName)1260 TEST(DnsResponseWriteTest, SingleARecordAnswerWithFinalDotInName) {
1261   const uint8_t response_data[] = {
1262       0x12, 0x34,  // ID
1263       0x84, 0x00,  // flags, response with authoritative answer
1264       0x00, 0x00,  // number of questions
1265       0x00, 0x01,  // number of answer rr
1266       0x00, 0x00,  // number of name server rr
1267       0x00, 0x00,  // number of additional rr
1268       0x03, 'w',  'w',  'w',  0x07, 'e', 'x', 'a',
1269       'm',  'p',  'l',  'e',  0x03, 'c', 'o', 'm',
1270       0x00,                    // null label
1271       0x00, 0x01,              // type A Record
1272       0x00, 0x01,              // class IN
1273       0x00, 0x00, 0x00, 0x78,  // TTL, 120 seconds
1274       0x00, 0x04,              // rdlength, 32 bits
1275       0xc0, 0xa8, 0x00, 0x01,  // 192.168.0.1
1276   };
1277   net::DnsResourceRecord answer;
1278   answer.name = "www.example.com.";  // FQDN with the final dot.
1279   answer.type = dns_protocol::kTypeA;
1280   answer.klass = dns_protocol::kClassIN;
1281   answer.ttl = 120;  // 120 seconds.
1282   answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1283   std::vector<DnsResourceRecord> answers(1, answer);
1284   DnsResponse response(0x1234 /* response_id */, true /* is_authoritative*/,
1285                        answers, {} /* authority_records */,
1286                        {} /* additional records */, std::nullopt);
1287   ASSERT_NE(nullptr, response.io_buffer());
1288   EXPECT_TRUE(response.IsValid());
1289   std::string expected_response(reinterpret_cast<const char*>(response_data),
1290                                 sizeof(response_data));
1291   std::string actual_response(response.io_buffer()->data(),
1292                               response.io_buffer_size());
1293   EXPECT_EQ(expected_response, actual_response);
1294 }
1295 
TEST(DnsResponseWriteTest,SingleARecordAnswerWithQuestion)1296 TEST(DnsResponseWriteTest, SingleARecordAnswerWithQuestion) {
1297   const uint8_t response_data[] = {
1298       0x12, 0x34,  // ID
1299       0x84, 0x00,  // flags, response with authoritative answer
1300       0x00, 0x01,  // number of questions
1301       0x00, 0x01,  // number of answer rr
1302       0x00, 0x00,  // number of name server rr
1303       0x00, 0x00,  // number of additional rr
1304       0x03, 'w',  'w',  'w',  0x07, 'e', 'x', 'a',
1305       'm',  'p',  'l',  'e',  0x03, 'c', 'o', 'm',
1306       0x00,        // null label
1307       0x00, 0x01,  // type A Record
1308       0x00, 0x01,  // class IN
1309       0x03, 'w',  'w',  'w',  0x07, 'e', 'x', 'a',
1310       'm',  'p',  'l',  'e',  0x03, 'c', 'o', 'm',
1311       0x00,                    // null label
1312       0x00, 0x01,              // type A Record
1313       0x00, 0x01,              // class IN
1314       0x00, 0x00, 0x00, 0x78,  // TTL, 120 seconds
1315       0x00, 0x04,              // rdlength, 32 bits
1316       0xc0, 0xa8, 0x00, 0x01,  // 192.168.0.1
1317   };
1318   std::string dotted_name("www.example.com");
1319   std::optional<std::vector<uint8_t>> dns_name =
1320       dns_names_util::DottedNameToNetwork(dotted_name);
1321   ASSERT_TRUE(dns_name.has_value());
1322 
1323   OptRecordRdata opt_rdata;
1324   opt_rdata.AddOpt(
1325       OptRecordRdata::UnknownOpt::CreateForTesting(255, "\xde\xad\xbe\xef"));
1326 
1327   std::optional<DnsQuery> query;
1328   query.emplace(0x1234 /* id */, dns_name.value(), dns_protocol::kTypeA,
1329                 &opt_rdata);
1330   net::DnsResourceRecord answer;
1331   answer.name = dotted_name;
1332   answer.type = dns_protocol::kTypeA;
1333   answer.klass = dns_protocol::kClassIN;
1334   answer.ttl = 120;  // 120 seconds.
1335   answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1336   std::vector<DnsResourceRecord> answers(1, answer);
1337   DnsResponse response(0x1234 /* id */, true /* is_authoritative*/, answers,
1338                        {} /* authority_records */, {} /* additional records */,
1339                        query);
1340   ASSERT_NE(nullptr, response.io_buffer());
1341   EXPECT_TRUE(response.IsValid());
1342   std::string expected_response(reinterpret_cast<const char*>(response_data),
1343                                 sizeof(response_data));
1344   std::string actual_response(response.io_buffer()->data(),
1345                               response.io_buffer_size());
1346   EXPECT_EQ(expected_response, actual_response);
1347 }
1348 
TEST(DnsResponseWriteTest,SingleAnswerWithQuestionConstructedFromSizeInflatedQuery)1349 TEST(DnsResponseWriteTest,
1350      SingleAnswerWithQuestionConstructedFromSizeInflatedQuery) {
1351   const uint8_t response_data[] = {
1352       0x12, 0x34,  // ID
1353       0x84, 0x00,  // flags, response with authoritative answer
1354       0x00, 0x01,  // number of questions
1355       0x00, 0x01,  // number of answer rr
1356       0x00, 0x00,  // number of name server rr
1357       0x00, 0x00,  // number of additional rr
1358       0x03, 'w',  'w',  'w',  0x07, 'e', 'x', 'a',
1359       'm',  'p',  'l',  'e',  0x03, 'c', 'o', 'm',
1360       0x00,        // null label
1361       0x00, 0x01,  // type A Record
1362       0x00, 0x01,  // class IN
1363       0x03, 'w',  'w',  'w',  0x07, 'e', 'x', 'a',
1364       'm',  'p',  'l',  'e',  0x03, 'c', 'o', 'm',
1365       0x00,                    // null label
1366       0x00, 0x01,              // type A Record
1367       0x00, 0x01,              // class IN
1368       0x00, 0x00, 0x00, 0x78,  // TTL, 120 seconds
1369       0x00, 0x04,              // rdlength, 32 bits
1370       0xc0, 0xa8, 0x00, 0x01,  // 192.168.0.1
1371   };
1372   std::string dotted_name("www.example.com");
1373   std::optional<std::vector<uint8_t>> dns_name =
1374       dns_names_util::DottedNameToNetwork(dotted_name);
1375   ASSERT_TRUE(dns_name.has_value());
1376   size_t buf_size =
1377       sizeof(dns_protocol::Header) + dns_name.value().size() + 2 /* qtype */ +
1378       2 /* qclass */ +
1379       10 /* extra bytes that inflate the internal buffer of a query */;
1380   auto buf = base::MakeRefCounted<IOBufferWithSize>(buf_size);
1381   std::ranges::fill(buf->span(), char{0});
1382   auto writer = base::SpanWriter(base::as_writable_bytes(buf->span()));
1383   writer.WriteU16BigEndian(0x1234);                  // id
1384   writer.WriteU16BigEndian(0);                       // flags, is query
1385   writer.WriteU16BigEndian(1);                       // qdcount
1386   writer.WriteU16BigEndian(0);                       // ancount
1387   writer.WriteU16BigEndian(0);                       // nscount
1388   writer.WriteU16BigEndian(0);                       // arcount
1389   writer.Write(dns_name.value());                    // qname
1390   writer.WriteU16BigEndian(dns_protocol::kTypeA);    // qtype
1391   writer.WriteU16BigEndian(dns_protocol::kClassIN);  // qclass
1392   // buf contains 10 extra zero bytes.
1393   std::optional<DnsQuery> query;
1394   query.emplace(buf);
1395   query->Parse(buf_size);
1396   net::DnsResourceRecord answer;
1397   answer.name = dotted_name;
1398   answer.type = dns_protocol::kTypeA;
1399   answer.klass = dns_protocol::kClassIN;
1400   answer.ttl = 120;  // 120 seconds.
1401   answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1402   std::vector<DnsResourceRecord> answers(1, answer);
1403   DnsResponse response(0x1234 /* id */, true /* is_authoritative*/, answers,
1404                        {} /* authority_records */, {} /* additional records */,
1405                        query);
1406   ASSERT_NE(nullptr, response.io_buffer());
1407   EXPECT_TRUE(response.IsValid());
1408   std::string expected_response(reinterpret_cast<const char*>(response_data),
1409                                 sizeof(response_data));
1410   std::string actual_response(response.io_buffer()->data(),
1411                               response.io_buffer_size());
1412   EXPECT_EQ(expected_response, actual_response);
1413 }
1414 
TEST(DnsResponseWriteTest,SingleQuadARecordAnswer)1415 TEST(DnsResponseWriteTest, SingleQuadARecordAnswer) {
1416   const uint8_t response_data[] = {
1417       0x12, 0x34,  // ID
1418       0x84, 0x00,  // flags, response with authoritative answer
1419       0x00, 0x00,  // number of questions
1420       0x00, 0x01,  // number of answer rr
1421       0x00, 0x00,  // number of name server rr
1422       0x00, 0x00,  // number of additional rr
1423       0x03, 'w',  'w',  'w',  0x07, 'e',  'x',  'a',
1424       'm',  'p',  'l',  'e',  0x03, 'c',  'o',  'm',
1425       0x00,                                            // null label
1426       0x00, 0x1c,                                      // type AAAA Record
1427       0x00, 0x01,                                      // class IN
1428       0x00, 0x00, 0x00, 0x78,                          // TTL, 120 seconds
1429       0x00, 0x10,                                      // rdlength, 128 bits
1430       0xfd, 0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0x01,  // fd12:3456:789a:1::1
1431       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1432   };
1433   net::DnsResourceRecord answer;
1434   answer.name = "www.example.com";
1435   answer.type = dns_protocol::kTypeAAAA;
1436   answer.klass = dns_protocol::kClassIN;
1437   answer.ttl = 120;  // 120 seconds.
1438   answer.SetOwnedRdata(std::string(
1439       "\xfd\x12\x34\x56\x78\x9a\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01", 16));
1440   std::vector<DnsResourceRecord> answers(1, answer);
1441   DnsResponse response(0x1234 /* id */, true /* is_authoritative*/, answers,
1442                        {} /* authority_records */, {} /* additional records */,
1443                        std::nullopt);
1444   ASSERT_NE(nullptr, response.io_buffer());
1445   EXPECT_TRUE(response.IsValid());
1446   std::string expected_response(reinterpret_cast<const char*>(response_data),
1447                                 sizeof(response_data));
1448   std::string actual_response(response.io_buffer()->data(),
1449                               response.io_buffer_size());
1450   EXPECT_EQ(expected_response, actual_response);
1451 }
1452 
TEST(DnsResponseWriteTest,SingleARecordAnswerWithQuestionAndNsecAdditionalRecord)1453 TEST(DnsResponseWriteTest,
1454      SingleARecordAnswerWithQuestionAndNsecAdditionalRecord) {
1455   const uint8_t response_data[] = {
1456       0x12, 0x34,  // ID
1457       0x84, 0x00,  // flags, response with authoritative answer
1458       0x00, 0x01,  // number of questions
1459       0x00, 0x01,  // number of answer rr
1460       0x00, 0x00,  // number of name server rr
1461       0x00, 0x01,  // number of additional rr
1462       0x03, 'w',  'w',  'w',  0x07, 'e', 'x', 'a',
1463       'm',  'p',  'l',  'e',  0x03, 'c', 'o', 'm',
1464       0x00,        // null label
1465       0x00, 0x01,  // type A Record
1466       0x00, 0x01,  // class IN
1467       0x03, 'w',  'w',  'w',  0x07, 'e', 'x', 'a',
1468       'm',  'p',  'l',  'e',  0x03, 'c', 'o', 'm',
1469       0x00,                    // null label
1470       0x00, 0x01,              // type A Record
1471       0x00, 0x01,              // class IN
1472       0x00, 0x00, 0x00, 0x78,  // TTL, 120 seconds
1473       0x00, 0x04,              // rdlength, 32 bits
1474       0xc0, 0xa8, 0x00, 0x01,  // 192.168.0.1
1475       0x03, 'w',  'w',  'w',  0x07, 'e', 'x', 'a',
1476       'm',  'p',  'l',  'e',  0x03, 'c', 'o', 'm',
1477       0x00,                    // null label
1478       0x00, 0x2f,              // type NSEC Record
1479       0x00, 0x01,              // class IN
1480       0x00, 0x00, 0x00, 0x78,  // TTL, 120 seconds
1481       0x00, 0x05,              // rdlength, 5 bytes
1482       0xc0, 0x0c,              // pointer to the previous "www.example.com"
1483       0x00, 0x01, 0x40,        // type bit map of type A: window block 0, bitmap
1484                                // length 1, bitmap with bit 1 set
1485   };
1486   std::string dotted_name("www.example.com");
1487   std::optional<std::vector<uint8_t>> dns_name =
1488       dns_names_util::DottedNameToNetwork(dotted_name);
1489   ASSERT_TRUE(dns_name.has_value());
1490   std::optional<DnsQuery> query;
1491   query.emplace(0x1234 /* id */, dns_name.value(), dns_protocol::kTypeA);
1492   net::DnsResourceRecord answer;
1493   answer.name = dotted_name;
1494   answer.type = dns_protocol::kTypeA;
1495   answer.klass = dns_protocol::kClassIN;
1496   answer.ttl = 120;  // 120 seconds.
1497   answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1498   std::vector<DnsResourceRecord> answers(1, answer);
1499   net::DnsResourceRecord additional_record;
1500   additional_record.name = dotted_name;
1501   additional_record.type = dns_protocol::kTypeNSEC;
1502   additional_record.klass = dns_protocol::kClassIN;
1503   additional_record.ttl = 120;  // 120 seconds.
1504   // Bitmap for "www.example.com" with type A set.
1505   additional_record.SetOwnedRdata(std::string("\xc0\x0c\x00\x01\x40", 5));
1506   std::vector<DnsResourceRecord> additional_records(1, additional_record);
1507   DnsResponse response(0x1234 /* id */, true /* is_authoritative*/, answers,
1508                        {} /* authority_records */, additional_records, query);
1509   ASSERT_NE(nullptr, response.io_buffer());
1510   EXPECT_TRUE(response.IsValid());
1511   std::string expected_response(reinterpret_cast<const char*>(response_data),
1512                                 sizeof(response_data));
1513   std::string actual_response(response.io_buffer()->data(),
1514                               response.io_buffer_size());
1515   EXPECT_EQ(expected_response, actual_response);
1516 }
1517 
TEST(DnsResponseWriteTest,TwoAnswersWithAAndQuadARecords)1518 TEST(DnsResponseWriteTest, TwoAnswersWithAAndQuadARecords) {
1519   const uint8_t response_data[] = {
1520       0x12, 0x34,  // ID
1521       0x84, 0x00,  // flags, response with authoritative answer
1522       0x00, 0x00,  // number of questions
1523       0x00, 0x02,  // number of answer rr
1524       0x00, 0x00,  // number of name server rr
1525       0x00, 0x00,  // number of additional rr
1526       0x03, 'w',  'w',  'w',  0x07, 'e',  'x',  'a',  'm',  'p', 'l', 'e',
1527       0x03, 'c',  'o',  'm',
1528       0x00,                    // null label
1529       0x00, 0x01,              // type A Record
1530       0x00, 0x01,              // class IN
1531       0x00, 0x00, 0x00, 0x78,  // TTL, 120 seconds
1532       0x00, 0x04,              // rdlength, 32 bits
1533       0xc0, 0xa8, 0x00, 0x01,  // 192.168.0.1
1534       0x07, 'e',  'x',  'a',  'm',  'p',  'l',  'e',  0x03, 'o', 'r', 'g',
1535       0x00,                                            // null label
1536       0x00, 0x1c,                                      // type AAAA Record
1537       0x00, 0x01,                                      // class IN
1538       0x00, 0x00, 0x00, 0x3c,                          // TTL, 60 seconds
1539       0x00, 0x10,                                      // rdlength, 128 bits
1540       0xfd, 0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0x01,  // fd12:3456:789a:1::1
1541       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1542   };
1543   net::DnsResourceRecord answer1;
1544   answer1.name = "www.example.com";
1545   answer1.type = dns_protocol::kTypeA;
1546   answer1.klass = dns_protocol::kClassIN;
1547   answer1.ttl = 120;  // 120 seconds.
1548   answer1.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1549   net::DnsResourceRecord answer2;
1550   answer2.name = "example.org";
1551   answer2.type = dns_protocol::kTypeAAAA;
1552   answer2.klass = dns_protocol::kClassIN;
1553   answer2.ttl = 60;
1554   answer2.SetOwnedRdata(std::string(
1555       "\xfd\x12\x34\x56\x78\x9a\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01", 16));
1556   std::vector<DnsResourceRecord> answers(2);
1557   answers[0] = answer1;
1558   answers[1] = answer2;
1559   DnsResponse response(0x1234 /* id */, true /* is_authoritative*/, answers,
1560                        {} /* authority_records */, {} /* additional records */,
1561                        std::nullopt);
1562   ASSERT_NE(nullptr, response.io_buffer());
1563   EXPECT_TRUE(response.IsValid());
1564   std::string expected_response(reinterpret_cast<const char*>(response_data),
1565                                 sizeof(response_data));
1566   std::string actual_response(response.io_buffer()->data(),
1567                               response.io_buffer_size());
1568   EXPECT_EQ(expected_response, actual_response);
1569 }
1570 
TEST(DnsResponseWriteTest,AnswerWithAuthorityRecord)1571 TEST(DnsResponseWriteTest, AnswerWithAuthorityRecord) {
1572   const uint8_t response_data[] = {
1573       0x12, 0x35,  // ID
1574       0x84, 0x00,  // flags, response with authoritative answer
1575       0x00, 0x00,  // number of questions
1576       0x00, 0x00,  // number of answer rr
1577       0x00, 0x01,  // number of name server rr
1578       0x00, 0x00,  // number of additional rr
1579       0x03, 'w',  'w',  'w',  0x07, 'e', 'x', 'a',
1580       'm',  'p',  'l',  'e',  0x03, 'c', 'o', 'm',
1581       0x00,                    // null label
1582       0x00, 0x01,              // type A Record
1583       0x00, 0x01,              // class IN
1584       0x00, 0x00, 0x00, 0x78,  // TTL, 120 seconds
1585       0x00, 0x04,              // rdlength, 32 bits
1586       0xc0, 0xa8, 0x00, 0x01,  // 192.168.0.1
1587   };
1588   DnsResourceRecord record;
1589   record.name = "www.example.com";
1590   record.type = dns_protocol::kTypeA;
1591   record.klass = dns_protocol::kClassIN;
1592   record.ttl = 120;  // 120 seconds.
1593   record.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1594   std::vector<DnsResourceRecord> authority_records(1, record);
1595   DnsResponse response(0x1235 /* response_id */, true /* is_authoritative*/,
1596                        {} /* answers */, authority_records,
1597                        {} /* additional records */, std::nullopt);
1598   ASSERT_NE(nullptr, response.io_buffer());
1599   EXPECT_TRUE(response.IsValid());
1600   std::string expected_response(reinterpret_cast<const char*>(response_data),
1601                                 sizeof(response_data));
1602   std::string actual_response(response.io_buffer()->data(),
1603                               response.io_buffer_size());
1604   EXPECT_EQ(expected_response, actual_response);
1605 }
1606 
TEST(DnsResponseWriteTest,AnswerWithRcode)1607 TEST(DnsResponseWriteTest, AnswerWithRcode) {
1608   const uint8_t response_data[] = {
1609       0x12, 0x12,  // ID
1610       0x80, 0x03,  // flags (response with non-existent domain)
1611       0x00, 0x00,  // number of questions
1612       0x00, 0x00,  // number of answer rr
1613       0x00, 0x00,  // number of name server rr
1614       0x00, 0x00,  // number of additional rr
1615   };
1616   DnsResponse response(0x1212 /* response_id */, false /* is_authoritative*/,
1617                        {} /* answers */, {} /* authority_records */,
1618                        {} /* additional records */, std::nullopt,
1619                        dns_protocol::kRcodeNXDOMAIN);
1620   ASSERT_NE(nullptr, response.io_buffer());
1621   EXPECT_TRUE(response.IsValid());
1622   std::string expected_response(reinterpret_cast<const char*>(response_data),
1623                                 sizeof(response_data));
1624   std::string actual_response(response.io_buffer()->data(),
1625                               response.io_buffer_size());
1626   EXPECT_EQ(expected_response, actual_response);
1627   EXPECT_EQ(dns_protocol::kRcodeNXDOMAIN, response.rcode());
1628 }
1629 
1630 // CNAME answers are always allowed for any question.
TEST(DnsResponseWriteTest,AAAAQuestionAndCnameAnswer)1631 TEST(DnsResponseWriteTest, AAAAQuestionAndCnameAnswer) {
1632   const std::string kName = "www.example.com";
1633   std::optional<std::vector<uint8_t>> dns_name =
1634       dns_names_util::DottedNameToNetwork(kName);
1635   ASSERT_TRUE(dns_name.has_value());
1636 
1637   DnsResourceRecord answer;
1638   answer.name = kName;
1639   answer.type = dns_protocol::kTypeCNAME;
1640   answer.klass = dns_protocol::kClassIN;
1641   answer.ttl = 120;  // 120 seconds.
1642   answer.SetOwnedRdata(
1643       std::string(reinterpret_cast<char*>(dns_name.value().data()),
1644                   dns_name.value().size()));
1645   std::vector<DnsResourceRecord> answers(1, answer);
1646 
1647   std::optional<DnsQuery> query(std::in_place, 114 /* id */, dns_name.value(),
1648                                 dns_protocol::kTypeAAAA);
1649 
1650   DnsResponse response(114 /* response_id */, true /* is_authoritative*/,
1651                        answers, {} /* authority_records */,
1652                        {} /* additional records */, query);
1653 
1654   EXPECT_TRUE(response.IsValid());
1655 }
1656 
TEST(DnsResponseWriteTest,WrittenResponseCanBeParsed)1657 TEST(DnsResponseWriteTest, WrittenResponseCanBeParsed) {
1658   std::string dotted_name("www.example.com");
1659   net::DnsResourceRecord answer;
1660   answer.name = dotted_name;
1661   answer.type = dns_protocol::kTypeA;
1662   answer.klass = dns_protocol::kClassIN;
1663   answer.ttl = 120;  // 120 seconds.
1664   answer.SetOwnedRdata(std::string("\xc0\xa8\x00\x01", 4));
1665   std::vector<DnsResourceRecord> answers(1, answer);
1666   net::DnsResourceRecord additional_record;
1667   additional_record.name = dotted_name;
1668   additional_record.type = dns_protocol::kTypeNSEC;
1669   additional_record.klass = dns_protocol::kClassIN;
1670   additional_record.ttl = 120;  // 120 seconds.
1671   additional_record.SetOwnedRdata(std::string("\xc0\x0c\x00\x01\x04", 5));
1672   std::vector<DnsResourceRecord> additional_records(1, additional_record);
1673   DnsResponse response(0x1234 /* response_id */, true /* is_authoritative*/,
1674                        answers, {} /* authority_records */, additional_records,
1675                        std::nullopt);
1676   ASSERT_NE(nullptr, response.io_buffer());
1677   EXPECT_TRUE(response.IsValid());
1678   EXPECT_THAT(response.id(), testing::Optional(0x1234));
1679   EXPECT_EQ(1u, response.answer_count());
1680   EXPECT_EQ(1u, response.additional_answer_count());
1681   auto parser = response.Parser();
1682   net::DnsResourceRecord parsed_record;
1683   EXPECT_TRUE(parser.ReadRecord(&parsed_record));
1684   // Answer with an A record.
1685   EXPECT_EQ(answer.name, parsed_record.name);
1686   EXPECT_EQ(answer.type, parsed_record.type);
1687   EXPECT_EQ(answer.klass, parsed_record.klass);
1688   EXPECT_EQ(answer.ttl, parsed_record.ttl);
1689   EXPECT_EQ(answer.owned_rdata, parsed_record.rdata);
1690   // Additional NSEC record.
1691   EXPECT_TRUE(parser.ReadRecord(&parsed_record));
1692   EXPECT_EQ(additional_record.name, parsed_record.name);
1693   EXPECT_EQ(additional_record.type, parsed_record.type);
1694   EXPECT_EQ(additional_record.klass, parsed_record.klass);
1695   EXPECT_EQ(additional_record.ttl, parsed_record.ttl);
1696   EXPECT_EQ(additional_record.owned_rdata, parsed_record.rdata);
1697 }
1698 
TEST(DnsResponseWriteTest,CreateEmptyNoDataResponse)1699 TEST(DnsResponseWriteTest, CreateEmptyNoDataResponse) {
1700   DnsResponse response = DnsResponse::CreateEmptyNoDataResponse(
1701       /*id=*/4,
1702       /*is_authoritative=*/true, base::as_byte_span("\x04name\x04test\x00"),
1703       dns_protocol::kTypeA);
1704 
1705   EXPECT_TRUE(response.IsValid());
1706   EXPECT_THAT(response.id(), testing::Optional(4));
1707   EXPECT_TRUE(response.flags() & dns_protocol::kFlagAA);
1708   EXPECT_EQ(response.question_count(), 1u);
1709   EXPECT_EQ(response.answer_count(), 0u);
1710   EXPECT_EQ(response.authority_count(), 0u);
1711   EXPECT_EQ(response.additional_answer_count(), 0u);
1712 
1713   EXPECT_THAT(response.qtypes(), testing::ElementsAre(dns_protocol::kTypeA));
1714   EXPECT_THAT(response.dotted_qnames(), testing::ElementsAre("name.test"));
1715 }
1716 
1717 }  // namespace
1718 
1719 }  // namespace net
1720