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