1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/dns/record_rdata.h"
6 
7 #include <algorithm>
8 #include <memory>
9 
10 #include "base/big_endian.h"
11 #include "net/dns/dns_response.h"
12 #include "net/dns/dns_test_util.h"
13 #include "net/test/gtest_util.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace net {
18 namespace {
19 
20 using ::testing::ElementsAreArray;
21 using ::testing::IsNull;
22 using ::testing::NotNull;
23 using ::testing::SizeIs;
24 
MakeStringPiece(const uint8_t * data,unsigned size)25 base::StringPiece MakeStringPiece(const uint8_t* data, unsigned size) {
26   const char* data_cc = reinterpret_cast<const char*>(data);
27   return base::StringPiece(data_cc, size);
28 }
29 
TEST(RecordRdataTest,ParseSrvRecord)30 TEST(RecordRdataTest, ParseSrvRecord) {
31   // These are just the rdata portions of the DNS records, rather than complete
32   // records, but it works well enough for this test.
33 
34   const uint8_t
35       record[] =
36           {
37               0x00, 0x01, 0x00, 0x02, 0x00, 0x50, 0x03, 'w',  'w',
38               'w',  0x06, 'g',  'o',  'o',  'g',  'l',  'e',  0x03,
39               'c',  'o',  'm',  0x00, 0x01, 0x01, 0x01, 0x02, 0x01,
40               0x03, 0x04, 'w',  'w',  'w',  '2',  0xc0, 0x0a,  // Pointer to
41                                                                // "google.com"
42           };
43 
44   DnsRecordParser parser(record, sizeof(record), 0);
45   const unsigned first_record_len = 22;
46   base::StringPiece record1_strpiece = MakeStringPiece(
47       record, first_record_len);
48   base::StringPiece record2_strpiece = MakeStringPiece(
49       record + first_record_len, sizeof(record) - first_record_len);
50 
51   std::unique_ptr<SrvRecordRdata> record1_obj =
52       SrvRecordRdata::Create(record1_strpiece, parser);
53   ASSERT_TRUE(record1_obj != nullptr);
54   ASSERT_EQ(1, record1_obj->priority());
55   ASSERT_EQ(2, record1_obj->weight());
56   ASSERT_EQ(80, record1_obj->port());
57 
58   ASSERT_EQ("www.google.com", record1_obj->target());
59 
60   std::unique_ptr<SrvRecordRdata> record2_obj =
61       SrvRecordRdata::Create(record2_strpiece, parser);
62   ASSERT_TRUE(record2_obj != nullptr);
63   ASSERT_EQ(257, record2_obj->priority());
64   ASSERT_EQ(258, record2_obj->weight());
65   ASSERT_EQ(259, record2_obj->port());
66 
67   ASSERT_EQ("www2.google.com", record2_obj->target());
68 
69   ASSERT_TRUE(record1_obj->IsEqual(record1_obj.get()));
70   ASSERT_FALSE(record1_obj->IsEqual(record2_obj.get()));
71 }
72 
TEST(RecordRdataTest,ParseARecord)73 TEST(RecordRdataTest, ParseARecord) {
74   // These are just the rdata portions of the DNS records, rather than complete
75   // records, but it works well enough for this test.
76 
77   const uint8_t record[] = {
78       0x7F, 0x00, 0x00, 0x01  // 127.0.0.1
79   };
80 
81   DnsRecordParser parser(record, sizeof(record), 0);
82   base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
83 
84   std::unique_ptr<ARecordRdata> record_obj =
85       ARecordRdata::Create(record_strpiece, parser);
86   ASSERT_TRUE(record_obj != nullptr);
87 
88   ASSERT_EQ("127.0.0.1", record_obj->address().ToString());
89 
90   ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
91 }
92 
TEST(RecordRdataTest,ParseAAAARecord)93 TEST(RecordRdataTest, ParseAAAARecord) {
94   // These are just the rdata portions of the DNS records, rather than complete
95   // records, but it works well enough for this test.
96 
97   const uint8_t record[] = {
98       0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
99       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09  // 1234:5678::9A
100   };
101 
102   DnsRecordParser parser(record, sizeof(record), 0);
103   base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
104 
105   std::unique_ptr<AAAARecordRdata> record_obj =
106       AAAARecordRdata::Create(record_strpiece, parser);
107   ASSERT_TRUE(record_obj != nullptr);
108 
109   ASSERT_EQ("1234:5678::9", record_obj->address().ToString());
110 
111   ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
112 }
113 
TEST(RecordRdataTest,ParseCnameRecord)114 TEST(RecordRdataTest, ParseCnameRecord) {
115   // These are just the rdata portions of the DNS records, rather than complete
116   // records, but it works well enough for this test.
117 
118   const uint8_t record[] = {0x03, 'w', 'w', 'w',  0x06, 'g', 'o', 'o',
119                             'g',  'l', 'e', 0x03, 'c',  'o', 'm', 0x00};
120 
121   DnsRecordParser parser(record, sizeof(record), 0);
122   base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
123 
124   std::unique_ptr<CnameRecordRdata> record_obj =
125       CnameRecordRdata::Create(record_strpiece, parser);
126   ASSERT_TRUE(record_obj != nullptr);
127 
128   ASSERT_EQ("www.google.com", record_obj->cname());
129 
130   ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
131 }
132 
133 // Appends a well-formed ESNIKeys struct to the stream owned by "writer".
134 // Returns the length, in bytes, of this struct, or 0 on error.
135 //
136 // (There is no ambiguity in the return value because a well-formed
137 // ESNIKeys struct has positive length.)
AppendWellFormedEsniKeys(base::BigEndianWriter * writer)138 void AppendWellFormedEsniKeys(base::BigEndianWriter* writer) {
139   CHECK(writer);
140   writer->WriteBytes(kWellFormedEsniKeys, kWellFormedEsniKeysSize);
141 }
142 
143 // This helper checks |keys| against the well-formed sample ESNIKeys
144 // struct; it's necessary because we can't implicitly convert
145 // kWellFormedEsniKeys to a StringPiece (it's a byte array, not a
146 // null-terminated string).
ExpectMatchesSampleKeys(base::StringPiece keys)147 void ExpectMatchesSampleKeys(base::StringPiece keys) {
148   EXPECT_EQ(keys,
149             base::StringPiece(kWellFormedEsniKeys, kWellFormedEsniKeysSize));
150 }
151 
152 // Appends an IP address in network byte order, prepended by one byte
153 // containing its version number, to |*serialized_addresses|. Appends
154 // the corresponding IPAddress object to |*address_objects|.
AppendAnotherIPAddress(std::vector<uint8_t> * serialized_addresses,std::vector<IPAddress> * address_objects,int ip_version)155 void AppendAnotherIPAddress(std::vector<uint8_t>* serialized_addresses,
156                             std::vector<IPAddress>* address_objects,
157                             int ip_version) {
158   CHECK(serialized_addresses);
159   CHECK(address_objects);
160 
161   // To make the addresses vary, but in a deterministic manner, assign octets
162   // in increasing order as they're requested, potentially eventually wrapping
163   // to 0.
164   static uint8_t next_octet;
165 
166   CHECK(ip_version == 4 || ip_version == 6);
167   const int address_num_bytes = ip_version == 4 ? 4 : 16;
168 
169   std::vector<uint8_t> address_bytes;
170   for (int i = 0; i < address_num_bytes; ++i)
171     address_bytes.push_back(next_octet++);
172   IPAddress address(address_bytes.data(), address_num_bytes);
173 
174   serialized_addresses->push_back(ip_version);
175   serialized_addresses->insert(serialized_addresses->end(),
176                                address_bytes.begin(), address_bytes.end());
177   address_objects->push_back(address);
178 }
179 
180 // Writes a dns_extensions ESNIRecord block containing given the address
181 // set to |writer|. This involves:
182 // - writing the 16-bit length prefix for the dns_extensions block
183 // - writing the 16-bit extension type (0x1001 "address_set")
184 // - writing the 16-bit length prefix for the address set extension
185 // - writing the extension itself
AppendDnsExtensionsBlock(base::BigEndianWriter * writer,const std::vector<uint8_t> & address_list)186 void AppendDnsExtensionsBlock(base::BigEndianWriter* writer,
187                               const std::vector<uint8_t>& address_list) {
188   CHECK(writer);
189   // 2 bytes for the DNS extension type
190   writer->WriteU16(4 +
191                    address_list.size());  // length of the dns_extensions field
192   writer->WriteU16(EsniRecordRdata::kAddressSetExtensionType);
193   writer->WriteU16(address_list.size());  // length of the address set
194   writer->WriteBytes(address_list.data(), address_list.size());
195 }
196 
197 // Test parsing a well-formed ESNI record with no DNS extensions.
TEST(RecordRdataTest,ParseEsniRecordNoExtensions)198 TEST(RecordRdataTest, ParseEsniRecordNoExtensions) {
199   char record[10000] = {};
200   base::BigEndianWriter writer(record, sizeof(record));
201   AppendWellFormedEsniKeys(&writer);
202 
203   writer.WriteU16(0);  // dns_extensions length
204 
205   auto record_size = writer.ptr() - record;
206   DnsRecordParser parser(record, record_size, 0 /* offset */);
207 
208   std::unique_ptr<EsniRecordRdata> record_obj =
209       EsniRecordRdata::Create(std::string(record, record_size), parser);
210   ASSERT_THAT(record_obj, NotNull());
211   EXPECT_TRUE(record_obj->IsEqual(record_obj.get()));
212   EXPECT_EQ(record_obj->esni_keys(),
213             std::string(kWellFormedEsniKeys, kWellFormedEsniKeysSize));
214   EXPECT_EQ(record_obj->Type(), dns_protocol::kExperimentalTypeEsniDraft4);
215 }
216 
217 // Test parsing a well-formed ESNI record bearing an address_set extension
218 // containing a single IPv4 address.
TEST(RecordRdataTest,ParseEsniRecordOneIPv4Address)219 TEST(RecordRdataTest, ParseEsniRecordOneIPv4Address) {
220   // ESNI record:
221   // well-formed ESNI keys
222   // extensions length
223   // extension
224   char record[10000] = {};
225   base::BigEndianWriter writer(record, sizeof(record));
226   AppendWellFormedEsniKeys(&writer);
227 
228   std::vector<uint8_t> address_list;
229   std::vector<IPAddress> addresses_for_validation;
230 
231   AppendAnotherIPAddress(&address_list, &addresses_for_validation,
232                          4 /* ip_version */);
233 
234   AppendDnsExtensionsBlock(&writer, address_list);
235 
236   auto record_size = writer.ptr() - record;
237   DnsRecordParser parser(record, record_size, 0 /* offset */);
238 
239   std::unique_ptr<EsniRecordRdata> record_obj =
240       EsniRecordRdata::Create(std::string(record, record_size), parser);
241   ASSERT_THAT(record_obj, NotNull());
242 
243   const auto& addresses = record_obj->addresses();
244 
245   EXPECT_EQ(addresses, addresses_for_validation);
246 
247   EXPECT_TRUE(record_obj->IsEqual(record_obj.get()));
248   ExpectMatchesSampleKeys(record_obj->esni_keys());
249 }
250 
251 // Test parsing a well-formed ESNI record bearing an address_set extension
252 // containing a single IPv6 address.
TEST(RecordRdataTest,ParseEsniRecordOneIPv6Address)253 TEST(RecordRdataTest, ParseEsniRecordOneIPv6Address) {
254   // ESNI record:
255   // well-formed ESNI keys
256   // extensions length
257   // extension
258   char record[10000] = {};
259   base::BigEndianWriter writer(record, sizeof(record));
260   AppendWellFormedEsniKeys(&writer);
261 
262   std::vector<uint8_t> address_list;
263   std::vector<IPAddress> addresses_for_validation;
264 
265   AppendAnotherIPAddress(&address_list, &addresses_for_validation,
266                          6 /* ip_version */);
267 
268   AppendDnsExtensionsBlock(&writer, address_list);
269 
270   auto record_size = writer.ptr() - record;
271   DnsRecordParser parser(record, record_size, 0 /* offset */);
272 
273   std::unique_ptr<EsniRecordRdata> record_obj =
274       EsniRecordRdata::Create(std::string(record, record_size), parser);
275   ASSERT_THAT(record_obj, NotNull());
276 
277   const auto& addresses = record_obj->addresses();
278 
279   EXPECT_EQ(addresses, addresses_for_validation);
280 
281   EXPECT_TRUE(record_obj->IsEqual(record_obj.get()));
282   ExpectMatchesSampleKeys(record_obj->esni_keys());
283 }
284 
285 // Test parsing a well-formed ESNI record bearing an address_set extension
286 // containing several IPv4 and IPv6 addresses.
TEST(RecordRdataTest,ParseEsniRecordManyAddresses)287 TEST(RecordRdataTest, ParseEsniRecordManyAddresses) {
288   // ESNI record:
289   // well-formed ESNI keys
290   // extensions length
291   // extension
292   char record[10000] = {};
293   base::BigEndianWriter writer(record, sizeof(record));
294   AppendWellFormedEsniKeys(&writer);
295 
296   std::vector<uint8_t> address_list;
297   std::vector<IPAddress> addresses_for_validation;
298 
299   for (int i = 0; i < 100; ++i)
300     AppendAnotherIPAddress(&address_list, &addresses_for_validation,
301                            (i % 3) ? 4 : 6 /* ip_version */);
302 
303   AppendDnsExtensionsBlock(&writer, address_list);
304 
305   auto record_size = writer.ptr() - record;
306   DnsRecordParser parser(record, record_size, 0 /* offset */);
307 
308   std::unique_ptr<EsniRecordRdata> record_obj =
309       EsniRecordRdata::Create(std::string(record, record_size), parser);
310   ASSERT_THAT(record_obj, NotNull());
311 
312   const auto& addresses = record_obj->addresses();
313 
314   EXPECT_EQ(addresses, addresses_for_validation);
315 
316   EXPECT_TRUE(record_obj->IsEqual(record_obj.get()));
317   ExpectMatchesSampleKeys(record_obj->esni_keys());
318 }
319 
320 // Test that we correctly reject a record with an ill-formed ESNI keys field.
321 //
322 // This test makes sure that the //net-side record parser is able
323 // correctly to handle the case where an external ESNI keys validation
324 // subroutine reports that the keys are ill-formed; because this validation
325 // will eventually be performed by BoringSSL once the corresponding
326 // BSSL code lands, it's out of scope here to exercise the
327 // validation logic itself.
TEST(RecordRdataTest,EsniMalformedRecord_InvalidEsniKeys)328 TEST(RecordRdataTest, EsniMalformedRecord_InvalidEsniKeys) {
329   char record[10000] = {};
330   base::BigEndianWriter writer(record, sizeof(record));
331 
332   // Oops! This otherwise well-formed ESNIKeys struct is missing its
333   // final byte, and the reader contains no content after this incomplete
334   // struct.
335   const char ill_formed_esni_keys[] = {
336       0xff, 0x3,  0x0,  0x0,  0x0,  0x24, 0x0,  0x1d, 0x0,  0x20,
337       0xed, 0xed, 0xc8, 0x68, 0xc1, 0x71, 0xd6, 0x9e, 0xa9, 0xf0,
338       0xa2, 0xc9, 0xf5, 0xa9, 0xdc, 0xcf, 0xf9, 0xb8, 0xed, 0x15,
339       0x5c, 0xc4, 0x5a, 0xec, 0x6f, 0xb2, 0x86, 0x14, 0xb7, 0x71,
340       0x1b, 0x7c, 0x0,  0x2,  0x13, 0x1,  0x1,  0x4,  0x0};
341   writer.WriteBytes(ill_formed_esni_keys, sizeof(ill_formed_esni_keys));
342 
343   auto record_size = writer.ptr() - record;
344   DnsRecordParser parser(record, record_size, 0 /* offset */);
345   std::unique_ptr<EsniRecordRdata> record_obj =
346       EsniRecordRdata::Create(std::string(record, record_size), parser);
347 
348   ASSERT_THAT(record_obj, IsNull());
349 }
350 
351 // Test that an empty address_set extension is correctly accepted.
TEST(RecordRdataTest,ParseEsniRecord_EmptyAddressSet)352 TEST(RecordRdataTest, ParseEsniRecord_EmptyAddressSet) {
353   char record[10000] = {};
354   base::BigEndianWriter writer(record, sizeof(record));
355   AppendWellFormedEsniKeys(&writer);
356 
357   writer.WriteU16(4);  // length of the dns_extensions field
358   writer.WriteU16(EsniRecordRdata::kAddressSetExtensionType);
359   writer.WriteU16(0);  // length of the (empty) address_set extension
360 
361   auto record_size = writer.ptr() - record;
362   DnsRecordParser parser(record, record_size, 0 /* offset */);
363   std::unique_ptr<EsniRecordRdata> record_obj =
364       EsniRecordRdata::Create(std::string(record, record_size), parser);
365 
366   ASSERT_THAT(record_obj, NotNull());
367 }
368 
369 // Test that we correctly reject a record invalid due to having extra
370 // data within its dns_extensions block but after its last extension.
TEST(RecordRdataTest,EsniMalformedRecord_TrailingDataWithinDnsExtensions)371 TEST(RecordRdataTest, EsniMalformedRecord_TrailingDataWithinDnsExtensions) {
372   char record[10000] = {};
373   base::BigEndianWriter writer(record, sizeof(record));
374   AppendWellFormedEsniKeys(&writer);
375 
376   writer.WriteU16(5);  // length of the dns_extensions field
377   writer.WriteU16(EsniRecordRdata::kAddressSetExtensionType);
378   writer.WriteU16(0);  // length of the (empty) address_set extension
379 
380   // Pad the otherwise-valid extensions block with one byte of garbage.
381   writer.WriteBytes(&"a", 1);
382 
383   auto record_size = writer.ptr() - record;
384   DnsRecordParser parser(record, record_size, 0 /* offset */);
385   std::unique_ptr<EsniRecordRdata> record_obj =
386       EsniRecordRdata::Create(std::string(record, record_size), parser);
387 
388   ASSERT_THAT(record_obj, IsNull());
389 }
390 
391 // Test that we correctly reject a record with two well-formed
392 // DNS extensions (only one extension of each type is permitted).
TEST(RecordRdataTest,EsniMalformedRecord_TooManyExtensions)393 TEST(RecordRdataTest, EsniMalformedRecord_TooManyExtensions) {
394   char record[10000] = {};
395   base::BigEndianWriter writer(record, sizeof(record));
396   AppendWellFormedEsniKeys(&writer);
397 
398   writer.WriteU16(8);  // length of the dns_extensions field
399   writer.WriteU16(EsniRecordRdata::kAddressSetExtensionType);
400   writer.WriteU16(0);  // length of the (empty) address_set extension
401   // Write another (empty, but completely valid on its own) extension,
402   // rendering the record invalid.
403   writer.WriteU16(EsniRecordRdata::kAddressSetExtensionType);
404   writer.WriteU16(0);
405 
406   auto record_size = writer.ptr() - record;
407   DnsRecordParser parser(record, record_size, 0 /* offset */);
408   std::unique_ptr<EsniRecordRdata> record_obj =
409       EsniRecordRdata::Create(std::string(record, record_size), parser);
410 
411   ASSERT_THAT(record_obj, IsNull());
412 }
413 
414 // Test that an ESNIRecord with an extension of invalid type
415 // is correctly rejected.
TEST(RecordRdataTest,EsniMalformedRecord_InvalidExtensionType)416 TEST(RecordRdataTest, EsniMalformedRecord_InvalidExtensionType) {
417   char record[10000] = {};
418   base::BigEndianWriter writer(record, sizeof(record));
419   AppendWellFormedEsniKeys(&writer);
420 
421   // 2 bytes for the DNS extension type
422   writer.WriteU16(2);       // length of the dns_extensions field
423   writer.WriteU16(0xdead);  // invalid address type
424 
425   auto record_size = writer.ptr() - record;
426   DnsRecordParser parser(record, record_size, 0 /* offset */);
427   std::unique_ptr<EsniRecordRdata> record_obj =
428       EsniRecordRdata::Create(std::string(record, record_size), parser);
429 
430   ASSERT_THAT(record_obj, IsNull());
431 }
432 
433 // Test that an address_set extension missing a length field
434 // is correctly rejected.
TEST(RecordRdataTest,EsniMalformedRecord_MalformedAddressSetLength)435 TEST(RecordRdataTest, EsniMalformedRecord_MalformedAddressSetLength) {
436   char record[10000] = {};
437   base::BigEndianWriter writer(record, sizeof(record));
438   AppendWellFormedEsniKeys(&writer);
439 
440   // 3 bytes: 2 for the DNS extension type, and one for our
441   // too-short address_set length
442   writer.WriteU16(3);  // length of the dns_extensions field
443   writer.WriteU16(EsniRecordRdata::kAddressSetExtensionType);
444   // oops! need two bytes for the address length
445   writer.WriteU8(57);
446 
447   auto record_size = writer.ptr() - record;
448   DnsRecordParser parser(record, record_size, 0 /* offset */);
449   std::unique_ptr<EsniRecordRdata> record_obj =
450       EsniRecordRdata::Create(std::string(record, record_size), parser);
451 
452   ASSERT_THAT(record_obj, IsNull());
453 }
454 
455 // Test that an ESNI record with malformed dns_extensions length is
456 // correctly rejected.
TEST(RecordRdataTest,EsniMalformedRecord_MalformedDnsExtensionsLength)457 TEST(RecordRdataTest, EsniMalformedRecord_MalformedDnsExtensionsLength) {
458   char record[10000] = {};
459   base::BigEndianWriter writer(record, sizeof(record));
460   AppendWellFormedEsniKeys(&writer);
461 
462   // Oops! Length field of dns_extensions should be 2 bytes.
463   writer.WriteU8(57);
464 
465   auto record_size = writer.ptr() - record;
466   DnsRecordParser parser(record, record_size, 0 /* offset */);
467   std::unique_ptr<EsniRecordRdata> record_obj =
468       EsniRecordRdata::Create(std::string(record, record_size), parser);
469 
470   ASSERT_THAT(record_obj, IsNull());
471 }
472 
473 // Test that an ESNI record with invalid dns_extensions length is
474 // correctly rejected.
TEST(RecordRdataTest,EsniMalformedRecord_BadDnsExtensionsLength)475 TEST(RecordRdataTest, EsniMalformedRecord_BadDnsExtensionsLength) {
476   char record[10000] = {};
477   base::BigEndianWriter writer(record, sizeof(record));
478   AppendWellFormedEsniKeys(&writer);
479 
480   // Length-prepend the dns_extensions field with value 5, even though
481   // the extensions object will have length 4 (two U16's): this should
482   // make the record be rejected as malformed.
483   writer.WriteU16(5);
484   writer.WriteU16(EsniRecordRdata::kAddressSetExtensionType);
485   writer.WriteU16(0);  // length of the address_set extension
486 
487   auto record_size = writer.ptr() - record;
488   DnsRecordParser parser(record, record_size, 0 /* offset */);
489   std::unique_ptr<EsniRecordRdata> record_obj =
490       EsniRecordRdata::Create(std::string(record, record_size), parser);
491 
492   ASSERT_THAT(record_obj, IsNull());
493 }
494 
495 // Test that an ESNI record with invalid address_set extension length is
496 // correctly rejected.
TEST(RecordRdataTest,EsniMalformedRecord_BadAddressSetLength)497 TEST(RecordRdataTest, EsniMalformedRecord_BadAddressSetLength) {
498   char record[10000] = {};
499   base::BigEndianWriter writer(record, sizeof(record));
500   AppendWellFormedEsniKeys(&writer);
501 
502   writer.WriteU16(4);  // 2 bytes for each of the U16s to be written
503   writer.WriteU16(EsniRecordRdata::kAddressSetExtensionType);
504   // Oops! Length-prepending the empty address_set field with the value 1.
505   writer.WriteU16(1);
506 
507   auto record_size = writer.ptr() - record;
508   DnsRecordParser parser(record, record_size, 0 /* offset */);
509   std::unique_ptr<EsniRecordRdata> record_obj =
510       EsniRecordRdata::Create(std::string(record, record_size), parser);
511 
512   ASSERT_THAT(record_obj, IsNull());
513 }
514 
515 // Test that an ESNI record with an address_set entry of bad address
516 // type is correctly rejected.
TEST(RecordRdataTest,EsniMalformedRecord_InvalidAddressType)517 TEST(RecordRdataTest, EsniMalformedRecord_InvalidAddressType) {
518   char record[10000] = {};
519   base::BigEndianWriter writer(record, sizeof(record));
520   AppendWellFormedEsniKeys(&writer);
521 
522   writer.WriteU16(9);  // dns_extensions length: two U16's and a 5-byte address
523   writer.WriteU16(EsniRecordRdata::kAddressSetExtensionType);
524 
525   std::vector<uint8_t> address_list;
526   IPAddress ipv4;
527   ASSERT_TRUE(net::ParseURLHostnameToAddress("192.168.1.1", &ipv4));
528   address_list.push_back(5);  // Oops! "5" isn't a valid AddressType.
529   std::copy(ipv4.bytes().begin(), ipv4.bytes().end(),
530             std::back_inserter(address_list));
531 
532   writer.WriteU16(address_list.size());
533   writer.WriteBytes(address_list.data(), address_list.size());
534 
535   auto record_size = writer.ptr() - record;
536   DnsRecordParser parser(record, record_size, 0 /* offset */);
537   std::unique_ptr<EsniRecordRdata> record_obj =
538       EsniRecordRdata::Create(std::string(record, record_size), parser);
539 
540   ASSERT_THAT(record_obj, IsNull());
541 }
542 
543 // Test that an ESNI record with an address_set entry of bad address
544 // type is correctly rejected.
TEST(RecordRdataTest,EsniMalformedRecord_NotEnoughAddressData_IPv4)545 TEST(RecordRdataTest, EsniMalformedRecord_NotEnoughAddressData_IPv4) {
546   char record[10000] = {};
547   base::BigEndianWriter writer(record, sizeof(record));
548   AppendWellFormedEsniKeys(&writer);
549 
550   std::vector<uint8_t> address_list;
551   std::vector<IPAddress> addresses_for_validation_unused;
552   AppendAnotherIPAddress(&address_list, &addresses_for_validation_unused, 4);
553 
554   // dns_extensions length: 2 bytes for address type, 2 for address_set length
555   // Subtract 1 because we're deliberately writing one byte too few for the
556   // purposes of this test.
557   writer.WriteU16(address_list.size() - 1 + 4);
558   writer.WriteU16(EsniRecordRdata::kAddressSetExtensionType);
559   writer.WriteU16(address_list.size() - 1);
560   // oops! missing the last byte of our IPv4 address
561   writer.WriteBytes(address_list.data(), address_list.size() - 1);
562 
563   auto record_size = writer.ptr() - record;
564   DnsRecordParser parser(record, record_size, 0 /* offset */);
565   std::unique_ptr<EsniRecordRdata> record_obj =
566       EsniRecordRdata::Create(std::string(record, record_size), parser);
567 
568   ASSERT_THAT(record_obj, IsNull());
569 }
570 
571 // Test that an ESNI record with an address_set entry of bad address
572 // type is correctly rejected.
TEST(RecordRdataTest,EsniMalformedRecord_NotEnoughAddressData_IPv6)573 TEST(RecordRdataTest, EsniMalformedRecord_NotEnoughAddressData_IPv6) {
574   char record[10000] = {};
575   base::BigEndianWriter writer(record, sizeof(record));
576   AppendWellFormedEsniKeys(&writer);
577 
578   std::vector<uint8_t> address_list;
579   std::vector<IPAddress> addresses_for_validation_unused;
580   AppendAnotherIPAddress(&address_list, &addresses_for_validation_unused, 6);
581 
582   // dns_extensions length: 2 bytes for address type, 2 for address_set length
583   // Subtract 1 because we're deliberately writing one byte too few for the
584   // purposes of this test.
585   writer.WriteU16(address_list.size() - 1 + 4);
586   writer.WriteU16(EsniRecordRdata::kAddressSetExtensionType);
587   writer.WriteU16(address_list.size() - 1);
588   // oops! missing the last byte of our IPv6 address
589   writer.WriteBytes(address_list.data(), address_list.size() - 1);
590 
591   auto record_size = writer.ptr() - record;
592   DnsRecordParser parser(record, record_size, 0 /* offset */);
593   std::unique_ptr<EsniRecordRdata> record_obj =
594       EsniRecordRdata::Create(std::string(record, record_size), parser);
595 
596   ASSERT_THAT(record_obj, IsNull());
597 }
598 
TEST(RecordRdataTest,ParsePtrRecord)599 TEST(RecordRdataTest, ParsePtrRecord) {
600   // These are just the rdata portions of the DNS records, rather than complete
601   // records, but it works well enough for this test.
602 
603   const uint8_t record[] = {0x03, 'w', 'w', 'w',  0x06, 'g', 'o', 'o',
604                             'g',  'l', 'e', 0x03, 'c',  'o', 'm', 0x00};
605 
606   DnsRecordParser parser(record, sizeof(record), 0);
607   base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
608 
609   std::unique_ptr<PtrRecordRdata> record_obj =
610       PtrRecordRdata::Create(record_strpiece, parser);
611   ASSERT_TRUE(record_obj != nullptr);
612 
613   ASSERT_EQ("www.google.com", record_obj->ptrdomain());
614 
615   ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
616 }
617 
TEST(RecordRdataTest,ParseTxtRecord)618 TEST(RecordRdataTest, ParseTxtRecord) {
619   // These are just the rdata portions of the DNS records, rather than complete
620   // records, but it works well enough for this test.
621 
622   const uint8_t record[] = {0x03, 'w', 'w', 'w',  0x06, 'g', 'o', 'o',
623                             'g',  'l', 'e', 0x03, 'c',  'o', 'm'};
624 
625   DnsRecordParser parser(record, sizeof(record), 0);
626   base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
627 
628   std::unique_ptr<TxtRecordRdata> record_obj =
629       TxtRecordRdata::Create(record_strpiece, parser);
630   ASSERT_TRUE(record_obj != nullptr);
631 
632   std::vector<std::string> expected;
633   expected.push_back("www");
634   expected.push_back("google");
635   expected.push_back("com");
636 
637   ASSERT_EQ(expected, record_obj->texts());
638 
639   ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
640 }
641 
TEST(RecordRdataTest,ParseNsecRecord)642 TEST(RecordRdataTest, ParseNsecRecord) {
643   // These are just the rdata portions of the DNS records, rather than complete
644   // records, but it works well enough for this test.
645 
646   const uint8_t record[] = {0x03, 'w',  'w',  'w',  0x06, 'g', 'o',
647                             'o',  'g',  'l',  'e',  0x03, 'c', 'o',
648                             'm',  0x00, 0x00, 0x02, 0x40, 0x01};
649 
650   DnsRecordParser parser(record, sizeof(record), 0);
651   base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
652 
653   std::unique_ptr<NsecRecordRdata> record_obj =
654       NsecRecordRdata::Create(record_strpiece, parser);
655   ASSERT_TRUE(record_obj != nullptr);
656 
657   ASSERT_EQ(16u, record_obj->bitmap_length());
658 
659   EXPECT_FALSE(record_obj->GetBit(0));
660   EXPECT_TRUE(record_obj->GetBit(1));
661   for (int i = 2; i < 15; i++) {
662     EXPECT_FALSE(record_obj->GetBit(i));
663   }
664   EXPECT_TRUE(record_obj->GetBit(15));
665 
666   ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
667 }
668 
TEST(RecordRdataTest,CreateNsecRecordWithEmptyBitmapReturnsNull)669 TEST(RecordRdataTest, CreateNsecRecordWithEmptyBitmapReturnsNull) {
670   // These are just the rdata portions of the DNS records, rather than complete
671   // records, but it works well enough for this test.
672   // This record has a bitmap that is 0 bytes long.
673   const uint8_t record[] = {0x03, 'w', 'w',  'w', 0x06, 'g', 'o',  'o',  'g',
674                             'l',  'e', 0x03, 'c', 'o',  'm', 0x00, 0x00, 0x00};
675 
676   DnsRecordParser parser(record, sizeof(record), 0);
677   base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
678 
679   std::unique_ptr<NsecRecordRdata> record_obj =
680       NsecRecordRdata::Create(record_strpiece, parser);
681   ASSERT_FALSE(record_obj);
682 }
683 
TEST(RecordRdataTest,CreateNsecRecordWithOversizedBitmapReturnsNull)684 TEST(RecordRdataTest, CreateNsecRecordWithOversizedBitmapReturnsNull) {
685   // These are just the rdata portions of the DNS records, rather than complete
686   // records, but it works well enough for this test.
687   // This record has a bitmap that is 33 bytes long. The maximum size allowed by
688   // RFC 3845, Section 2.1.2, is 32 bytes.
689   const uint8_t record[] = {
690       0x03, 'w',  'w',  'w',  0x06, 'g',  'o',  'o',  'g',  'l',  'e',
691       0x03, 'c',  'o',  'm',  0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
692       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
695 
696   DnsRecordParser parser(record, sizeof(record), 0);
697   base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
698 
699   std::unique_ptr<NsecRecordRdata> record_obj =
700       NsecRecordRdata::Create(record_strpiece, parser);
701   ASSERT_FALSE(record_obj);
702 }
703 
TEST(RecordRdataTest,ParseOptRecord)704 TEST(RecordRdataTest, ParseOptRecord) {
705   // This is just the rdata portion of an OPT record, rather than a complete
706   // record.
707   const uint8_t rdata[] = {
708       // First OPT
709       0x00, 0x01,  // OPT code
710       0x00, 0x02,  // OPT data size
711       0xDE, 0xAD,  // OPT data
712       // Second OPT
713       0x00, 0xFF,             // OPT code
714       0x00, 0x04,             // OPT data size
715       0xDE, 0xAD, 0xBE, 0xEF  // OPT data
716   };
717 
718   DnsRecordParser parser(rdata, sizeof(rdata), 0);
719   base::StringPiece rdata_strpiece = MakeStringPiece(rdata, sizeof(rdata));
720 
721   std::unique_ptr<OptRecordRdata> rdata_obj =
722       OptRecordRdata::Create(rdata_strpiece, parser);
723   ASSERT_THAT(rdata_obj, NotNull());
724   ASSERT_THAT(rdata_obj->opts(), SizeIs(2));
725   ASSERT_EQ(1, rdata_obj->opts()[0].code());
726   ASSERT_EQ("\xde\xad", rdata_obj->opts()[0].data());
727   ASSERT_EQ(255, rdata_obj->opts()[1].code());
728   ASSERT_EQ("\xde\xad\xbe\xef", rdata_obj->opts()[1].data());
729   ASSERT_TRUE(rdata_obj->IsEqual(rdata_obj.get()));
730 }
731 
TEST(RecordRdataTest,ParseOptRecordWithShorterSizeThanData)732 TEST(RecordRdataTest, ParseOptRecordWithShorterSizeThanData) {
733   // This is just the rdata portion of an OPT record, rather than a complete
734   // record.
735   const uint8_t rdata[] = {
736       0x00, 0xFF,             // OPT code
737       0x00, 0x02,             // OPT data size (incorrect, should be 4)
738       0xDE, 0xAD, 0xBE, 0xEF  // OPT data
739   };
740 
741   DnsRecordParser parser(rdata, sizeof(rdata), 0);
742   base::StringPiece rdata_strpiece = MakeStringPiece(rdata, sizeof(rdata));
743 
744   std::unique_ptr<OptRecordRdata> rdata_obj =
745       OptRecordRdata::Create(rdata_strpiece, parser);
746   ASSERT_THAT(rdata_obj, IsNull());
747 }
748 
TEST(RecordRdataTest,ParseOptRecordWithLongerSizeThanData)749 TEST(RecordRdataTest, ParseOptRecordWithLongerSizeThanData) {
750   // This is just the rdata portion of an OPT record, rather than a complete
751   // record.
752   const uint8_t rdata[] = {
753       0x00, 0xFF,  // OPT code
754       0x00, 0x04,  // OPT data size (incorrect, should be 4)
755       0xDE, 0xAD   // OPT data
756   };
757 
758   DnsRecordParser parser(rdata, sizeof(rdata), 0);
759   base::StringPiece rdata_strpiece = MakeStringPiece(rdata, sizeof(rdata));
760 
761   std::unique_ptr<OptRecordRdata> rdata_obj =
762       OptRecordRdata::Create(rdata_strpiece, parser);
763   ASSERT_THAT(rdata_obj, IsNull());
764 }
765 
TEST(RecordRdataTest,AddOptToOptRecord)766 TEST(RecordRdataTest, AddOptToOptRecord) {
767   // This is just the rdata portion of an OPT record, rather than a complete
768   // record.
769   const uint8_t expected_rdata[] = {
770       0x00, 0xFF,             // OPT code
771       0x00, 0x04,             // OPT data size
772       0xDE, 0xAD, 0xBE, 0xEF  // OPT data
773   };
774 
775   OptRecordRdata rdata;
776   rdata.AddOpt(OptRecordRdata::Opt(255, "\xde\xad\xbe\xef"));
777   EXPECT_THAT(rdata.buf(), ElementsAreArray(expected_rdata));
778 }
779 
780 }  // namespace
781 }  // namespace net
782