1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "net/dns/record_rdata.h"
11
12 #include <algorithm>
13 #include <memory>
14 #include <optional>
15 #include <string_view>
16 #include <utility>
17
18 #include "base/big_endian.h"
19 #include "net/dns/dns_response.h"
20 #include "net/dns/dns_test_util.h"
21 #include "net/test/gtest_util.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 namespace net {
26 namespace {
27
28 using ::testing::ElementsAreArray;
29 using ::testing::IsNull;
30 using ::testing::NotNull;
31 using ::testing::SizeIs;
32
MakeStringPiece(const uint8_t * data,unsigned size)33 std::string_view MakeStringPiece(const uint8_t* data, unsigned size) {
34 const char* data_cc = reinterpret_cast<const char*>(data);
35 return std::string_view(data_cc, size);
36 }
37
TEST(RecordRdataTest,ParseSrvRecord)38 TEST(RecordRdataTest, ParseSrvRecord) {
39 // These are just the rdata portions of the DNS records, rather than complete
40 // records, but it works well enough for this test.
41
42 const uint8_t
43 record[] =
44 {
45 0x00, 0x01, 0x00, 0x02, 0x00, 0x50, 0x03, 'w', 'w',
46 'w', 0x06, 'g', 'o', 'o', 'g', 'l', 'e', 0x03,
47 'c', 'o', 'm', 0x00, 0x01, 0x01, 0x01, 0x02, 0x01,
48 0x03, 0x04, 'w', 'w', 'w', '2', 0xc0, 0x0a, // Pointer to
49 // "google.com"
50 };
51
52 DnsRecordParser parser(record, 0, /*num_records=*/0);
53 const unsigned first_record_len = 22;
54 std::string_view record1_strpiece = MakeStringPiece(record, first_record_len);
55 std::string_view record2_strpiece = MakeStringPiece(
56 record + first_record_len, sizeof(record) - first_record_len);
57
58 std::unique_ptr<SrvRecordRdata> record1_obj =
59 SrvRecordRdata::Create(record1_strpiece, parser);
60 ASSERT_TRUE(record1_obj != nullptr);
61 ASSERT_EQ(1, record1_obj->priority());
62 ASSERT_EQ(2, record1_obj->weight());
63 ASSERT_EQ(80, record1_obj->port());
64
65 ASSERT_EQ("www.google.com", record1_obj->target());
66
67 std::unique_ptr<SrvRecordRdata> record2_obj =
68 SrvRecordRdata::Create(record2_strpiece, parser);
69 ASSERT_TRUE(record2_obj != nullptr);
70 ASSERT_EQ(257, record2_obj->priority());
71 ASSERT_EQ(258, record2_obj->weight());
72 ASSERT_EQ(259, record2_obj->port());
73
74 ASSERT_EQ("www2.google.com", record2_obj->target());
75
76 ASSERT_TRUE(record1_obj->IsEqual(record1_obj.get()));
77 ASSERT_FALSE(record1_obj->IsEqual(record2_obj.get()));
78 }
79
TEST(RecordRdataTest,ParseARecord)80 TEST(RecordRdataTest, ParseARecord) {
81 // These are just the rdata portions of the DNS records, rather than complete
82 // records, but it works well enough for this test.
83
84 const uint8_t record[] = {
85 0x7F, 0x00, 0x00, 0x01 // 127.0.0.1
86 };
87
88 DnsRecordParser parser(record, 0, /*num_records=*/0);
89 std::string_view record_strpiece = MakeStringPiece(record, sizeof(record));
90
91 std::unique_ptr<ARecordRdata> record_obj =
92 ARecordRdata::Create(record_strpiece, parser);
93 ASSERT_TRUE(record_obj != nullptr);
94
95 ASSERT_EQ("127.0.0.1", record_obj->address().ToString());
96
97 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
98 }
99
TEST(RecordRdataTest,ParseAAAARecord)100 TEST(RecordRdataTest, ParseAAAARecord) {
101 // These are just the rdata portions of the DNS records, rather than complete
102 // records, but it works well enough for this test.
103
104 const uint8_t record[] = {
105 0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 // 1234:5678::9A
107 };
108
109 DnsRecordParser parser(record, 0, /*num_records=*/0);
110 std::string_view record_strpiece = MakeStringPiece(record, sizeof(record));
111
112 std::unique_ptr<AAAARecordRdata> record_obj =
113 AAAARecordRdata::Create(record_strpiece, parser);
114 ASSERT_TRUE(record_obj != nullptr);
115
116 ASSERT_EQ("1234:5678::9", record_obj->address().ToString());
117
118 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
119 }
120
TEST(RecordRdataTest,ParseCnameRecord)121 TEST(RecordRdataTest, ParseCnameRecord) {
122 // These are just the rdata portions of the DNS records, rather than complete
123 // records, but it works well enough for this test.
124
125 const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o',
126 'g', 'l', 'e', 0x03, 'c', 'o', 'm', 0x00};
127
128 DnsRecordParser parser(record, 0, /*num_records=*/0);
129 std::string_view record_strpiece = MakeStringPiece(record, sizeof(record));
130
131 std::unique_ptr<CnameRecordRdata> record_obj =
132 CnameRecordRdata::Create(record_strpiece, parser);
133 ASSERT_TRUE(record_obj != nullptr);
134
135 ASSERT_EQ("www.google.com", record_obj->cname());
136
137 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
138 }
139
TEST(RecordRdataTest,ParsePtrRecord)140 TEST(RecordRdataTest, ParsePtrRecord) {
141 // These are just the rdata portions of the DNS records, rather than complete
142 // records, but it works well enough for this test.
143
144 const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o',
145 'g', 'l', 'e', 0x03, 'c', 'o', 'm', 0x00};
146
147 DnsRecordParser parser(record, 0, /*num_records=*/0);
148 std::string_view record_strpiece = MakeStringPiece(record, sizeof(record));
149
150 std::unique_ptr<PtrRecordRdata> record_obj =
151 PtrRecordRdata::Create(record_strpiece, parser);
152 ASSERT_TRUE(record_obj != nullptr);
153
154 ASSERT_EQ("www.google.com", record_obj->ptrdomain());
155
156 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
157 }
158
TEST(RecordRdataTest,ParseTxtRecord)159 TEST(RecordRdataTest, ParseTxtRecord) {
160 // These are just the rdata portions of the DNS records, rather than complete
161 // records, but it works well enough for this test.
162
163 const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o',
164 'g', 'l', 'e', 0x03, 'c', 'o', 'm'};
165
166 DnsRecordParser parser(record, 0, /*num_records=*/0);
167 std::string_view record_strpiece = MakeStringPiece(record, sizeof(record));
168
169 std::unique_ptr<TxtRecordRdata> record_obj =
170 TxtRecordRdata::Create(record_strpiece, parser);
171 ASSERT_TRUE(record_obj != nullptr);
172
173 std::vector<std::string> expected;
174 expected.push_back("www");
175 expected.push_back("google");
176 expected.push_back("com");
177
178 ASSERT_EQ(expected, record_obj->texts());
179
180 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
181 }
182
TEST(RecordRdataTest,ParseNsecRecord)183 TEST(RecordRdataTest, ParseNsecRecord) {
184 // These are just the rdata portions of the DNS records, rather than complete
185 // records, but it works well enough for this test.
186
187 const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o',
188 'o', 'g', 'l', 'e', 0x03, 'c', 'o',
189 'm', 0x00, 0x00, 0x02, 0x40, 0x01};
190
191 DnsRecordParser parser(record, 0, /*num_records=*/0);
192 std::string_view record_strpiece = MakeStringPiece(record, sizeof(record));
193
194 std::unique_ptr<NsecRecordRdata> record_obj =
195 NsecRecordRdata::Create(record_strpiece, parser);
196 ASSERT_TRUE(record_obj != nullptr);
197
198 ASSERT_EQ(16u, record_obj->bitmap_length());
199
200 EXPECT_FALSE(record_obj->GetBit(0));
201 EXPECT_TRUE(record_obj->GetBit(1));
202 for (int i = 2; i < 15; i++) {
203 EXPECT_FALSE(record_obj->GetBit(i));
204 }
205 EXPECT_TRUE(record_obj->GetBit(15));
206
207 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
208 }
209
TEST(RecordRdataTest,CreateNsecRecordWithEmptyBitmapReturnsNull)210 TEST(RecordRdataTest, CreateNsecRecordWithEmptyBitmapReturnsNull) {
211 // These are just the rdata portions of the DNS records, rather than complete
212 // records, but it works well enough for this test.
213 // This record has a bitmap that is 0 bytes long.
214 const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o', 'g',
215 'l', 'e', 0x03, 'c', 'o', 'm', 0x00, 0x00, 0x00};
216
217 DnsRecordParser parser(record, 0, /*num_records=*/0);
218 std::string_view record_strpiece = MakeStringPiece(record, sizeof(record));
219
220 std::unique_ptr<NsecRecordRdata> record_obj =
221 NsecRecordRdata::Create(record_strpiece, parser);
222 ASSERT_FALSE(record_obj);
223 }
224
TEST(RecordRdataTest,CreateNsecRecordWithOversizedBitmapReturnsNull)225 TEST(RecordRdataTest, CreateNsecRecordWithOversizedBitmapReturnsNull) {
226 // These are just the rdata portions of the DNS records, rather than complete
227 // records, but it works well enough for this test.
228 // This record has a bitmap that is 33 bytes long. The maximum size allowed by
229 // RFC 3845, Section 2.1.2, is 32 bytes.
230 const uint8_t record[] = {
231 0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o', 'g', 'l', 'e',
232 0x03, 'c', 'o', 'm', 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
236
237 DnsRecordParser parser(record, 0, /*num_records=*/0);
238 std::string_view record_strpiece = MakeStringPiece(record, sizeof(record));
239
240 std::unique_ptr<NsecRecordRdata> record_obj =
241 NsecRecordRdata::Create(record_strpiece, parser);
242 ASSERT_FALSE(record_obj);
243 }
244
245 } // namespace
246 } // namespace net
247