1 // Copyright 2022 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_names_util.h"
6
7 #include <climits>
8 #include <cstdint>
9 #include <cstring>
10 #include <string>
11 #include <vector>
12
13 #include "base/big_endian.h"
14 #include "base/numerics/safe_conversions.h"
15 #include "net/dns/dns_util.h"
16 #include "net/dns/public/dns_protocol.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/abseil-cpp/absl/types/optional.h"
20
21 namespace net::dns_names_util {
22 namespace {
23
24 using ::testing::Eq;
25 using ::testing::Optional;
26
27 // ToBytes converts a char* to a std::vector<uint8_t> and includes the
28 // terminating NUL in the result.
ToBytes(const char * in)29 std::vector<uint8_t> ToBytes(const char* in) {
30 size_t size = strlen(in) + 1;
31 std::vector<uint8_t> out(size, 0);
32 memcpy(out.data(), in, size);
33 return out;
34 }
35
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidation)36 TEST(DnsNamesUtilTest, DottedNameToNetworkWithValidation) {
37 EXPECT_THAT(
38 DottedNameToNetwork("com", /*require_valid_internet_hostname=*/true),
39 Optional(ToBytes("\003com")));
40 EXPECT_THAT(DottedNameToNetwork("google.com",
41 /*require_valid_internet_hostname=*/true),
42 Optional(ToBytes("\x006google\003com")));
43 EXPECT_THAT(DottedNameToNetwork("www.google.com",
44 /*require_valid_internet_hostname=*/true),
45 Optional(ToBytes("\003www\006google\003com")));
46 }
47
TEST(DnsNamesUtilTest,DottedNameToNetwork)48 TEST(DnsNamesUtilTest, DottedNameToNetwork) {
49 EXPECT_THAT(
50 DottedNameToNetwork("com", /*require_valid_internet_hostname=*/false),
51 Optional(ToBytes("\003com")));
52 EXPECT_THAT(DottedNameToNetwork("google.com",
53 /*require_valid_internet_hostname=*/false),
54 Optional(ToBytes("\x006google\003com")));
55 EXPECT_THAT(DottedNameToNetwork("www.google.com",
56 /*require_valid_internet_hostname=*/false),
57 Optional(ToBytes("\003www\006google\003com")));
58 }
59
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidationRejectsEmptyLabels)60 TEST(DnsNamesUtilTest, DottedNameToNetworkWithValidationRejectsEmptyLabels) {
61 EXPECT_FALSE(DottedNameToNetwork("", /*require_valid_internet_hostname=*/true)
62 .has_value());
63 EXPECT_FALSE(
64 DottedNameToNetwork(".", /*require_valid_internet_hostname=*/true)
65 .has_value());
66 EXPECT_FALSE(
67 DottedNameToNetwork("..", /*require_valid_internet_hostname=*/true)
68 .has_value());
69 EXPECT_FALSE(DottedNameToNetwork(".google.com",
70 /*require_valid_internet_hostname=*/true)
71 .has_value());
72 EXPECT_FALSE(DottedNameToNetwork("www..google.com",
73 /*require_valid_internet_hostname=*/true)
74 .has_value());
75 }
76
TEST(DnsNamesUtilTest,DottedNameToNetworkRejectsEmptyLabels)77 TEST(DnsNamesUtilTest, DottedNameToNetworkRejectsEmptyLabels) {
78 EXPECT_FALSE(
79 DottedNameToNetwork("", /*require_valid_internet_hostname=*/false)
80 .has_value());
81 EXPECT_FALSE(
82 DottedNameToNetwork(".", /*require_valid_internet_hostname=*/false)
83 .has_value());
84 EXPECT_FALSE(
85 DottedNameToNetwork("..", /*require_valid_internet_hostname=*/false)
86 .has_value());
87 EXPECT_FALSE(DottedNameToNetwork(".google.com",
88 /*require_valid_internet_hostname=*/false)
89 .has_value());
90 EXPECT_FALSE(DottedNameToNetwork("www..google.com",
91 /*require_valid_internet_hostname=*/false)
92 .has_value());
93 }
94
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidationAcceptsEmptyLabelAtEnd)95 TEST(DnsNamesUtilTest,
96 DottedNameToNetworkWithValidationAcceptsEmptyLabelAtEnd) {
97 EXPECT_THAT(DottedNameToNetwork("www.google.com.",
98 /*require_valid_internet_hostname=*/true),
99 Optional(ToBytes("\003www\006google\003com")));
100 }
101
TEST(DnsNamesUtilTest,DottedNameToNetworkAcceptsEmptyLabelAtEnd)102 TEST(DnsNamesUtilTest, DottedNameToNetworkAcceptsEmptyLabelAtEnd) {
103 EXPECT_THAT(DottedNameToNetwork("www.google.com.",
104 /*require_valid_internet_hostname=*/false),
105 Optional(ToBytes("\003www\006google\003com")));
106 }
107
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidationAllowsLongNames)108 TEST(DnsNamesUtilTest, DottedNameToNetworkWithValidationAllowsLongNames) {
109 // Label is 63 chars: still valid
110 EXPECT_THAT(
111 DottedNameToNetwork(
112 "z23456789a123456789a123456789a123456789a123456789a123456789a123",
113 /*require_valid_internet_hostname=*/true),
114 Optional(ToBytes("\077z23456789a123456789a123456789a123456789a123456"
115 "789a123456789a123")));
116 EXPECT_THAT(
117 DottedNameToNetwork(
118 "z23456789a123456789a123456789a123456789a123456789a123456789a123.",
119 /*require_valid_internet_hostname=*/true),
120 Optional(ToBytes("\077z23456789a123456789a123456789a123456789a123456"
121 "789a123456789a123")));
122
123 // 253 characters in the name: still valid
124 EXPECT_THAT(
125 DottedNameToNetwork(
126 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
127 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
128 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
129 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
130 "abcdefghi.abc",
131 /*require_valid_internet_hostname=*/true),
132 Optional(ToBytes("\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
133 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
134 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
135 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
136 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
137 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
138 "\011abcdefghi\003abc")));
139
140 // 253 characters in the name plus final dot: still valid
141 EXPECT_THAT(
142 DottedNameToNetwork(
143 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
144 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
145 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
146 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
147 "abcdefghi.abc.",
148 /*require_valid_internet_hostname=*/true),
149 Optional(ToBytes("\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
150 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
151 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
152 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
153 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
154 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
155 "\011abcdefghi\003abc")));
156 }
157
TEST(DnsNamesUtilTest,DottedNameToNetworkAllowsLongNames)158 TEST(DnsNamesUtilTest, DottedNameToNetworkAllowsLongNames) {
159 // Label is 63 chars: still valid
160 EXPECT_THAT(
161 DottedNameToNetwork(
162 "z23456789a123456789a123456789a123456789a123456789a123456789a123",
163 /*require_valid_internet_hostname=*/false),
164 Optional(ToBytes("\077z23456789a123456789a123456789a123456789a123456"
165 "789a123456789a123")));
166 // Label is 63 chars: still valid
167 EXPECT_THAT(
168 DottedNameToNetwork(
169 "z23456789a123456789a123456789a123456789a123456789a123456789a123.",
170 /*require_valid_internet_hostname=*/false),
171 Optional(ToBytes("\077z23456789a123456789a123456789a123456789a123456"
172 "789a123456789a123")));
173
174 // 253 characters in the name: still valid
175 EXPECT_THAT(
176 DottedNameToNetwork(
177 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
178 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
179 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
180 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
181 "abcdefghi.abc",
182 /*require_valid_internet_hostname=*/false),
183 Optional(ToBytes("\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
184 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
185 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
186 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
187 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
188 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
189 "\011abcdefghi\003abc")));
190
191 // 253 characters in the name plus final dot: still valid
192 EXPECT_THAT(
193 DottedNameToNetwork(
194 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
195 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
196 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
197 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
198 "abcdefghi.abc.",
199 /*require_valid_internet_hostname=*/false),
200 Optional(ToBytes("\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
201 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
202 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
203 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
204 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
205 "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
206 "\011abcdefghi\003abc")));
207 }
208
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidationRejectsTooLongNames)209 TEST(DnsNamesUtilTest, DottedNameToNetworkWithValidationRejectsTooLongNames) {
210 // Label is too long: invalid
211 EXPECT_FALSE(
212 DottedNameToNetwork(
213 "123456789a123456789a123456789a123456789a123456789a123456789a1234",
214 /*require_valid_internet_hostname=*/true)
215 .has_value());
216 EXPECT_FALSE(
217 DottedNameToNetwork(
218 "123456789a123456789a123456789a123456789a123456789a123456789a1234.",
219 /*require_valid_internet_hostname=*/true)
220 .has_value());
221
222 // 254 characters in the name: invalid
223 EXPECT_FALSE(
224 DottedNameToNetwork(
225 "123456789.123456789.123456789.123456789.123456789.123456789."
226 "123456789.123456789.123456789.123456789.123456789.123456789."
227 "123456789.123456789.123456789.123456789.123456789.123456789."
228 "123456789.123456789.123456789.123456789.123456789.123456789."
229 "123456789.1234",
230 /*require_valid_internet_hostname=*/true)
231 .has_value());
232 EXPECT_FALSE(
233 DottedNameToNetwork(
234 "123456789.123456789.123456789.123456789.123456789.123456789."
235 "123456789.123456789.123456789.123456789.123456789.123456789."
236 "123456789.123456789.123456789.123456789.123456789.123456789."
237 "123456789.123456789.123456789.123456789.123456789.123456789."
238 "123456789.1234.",
239 /*require_valid_internet_hostname=*/true)
240 .has_value());
241
242 // 255 characters in the name: invalid before even trying to add a final
243 // zero-length termination
244 EXPECT_FALSE(
245 DottedNameToNetwork(
246 "123456789.123456789.123456789.123456789.123456789.123456789."
247 "123456789.123456789.123456789.123456789.123456789.123456789."
248 "123456789.123456789.123456789.123456789.123456789.123456789."
249 "123456789.123456789.123456789.123456789.123456789.123456789."
250 "123456789.12345",
251 /*require_valid_internet_hostname=*/true)
252 .has_value());
253 EXPECT_FALSE(
254 DottedNameToNetwork(
255 "123456789.123456789.123456789.123456789.123456789.123456789."
256 "123456789.123456789.123456789.123456789.123456789.123456789."
257 "123456789.123456789.123456789.123456789.123456789.123456789."
258 "123456789.123456789.123456789.123456789.123456789.123456789."
259 "123456789.12345.",
260 /*require_valid_internet_hostname=*/true)
261 .has_value());
262 }
263
TEST(DnsNamesUtilTest,DottedNameToNetworkRejectsTooLongNames)264 TEST(DnsNamesUtilTest, DottedNameToNetworkRejectsTooLongNames) {
265 // Label is too long: invalid
266 EXPECT_FALSE(
267 DottedNameToNetwork(
268 "123456789a123456789a123456789a123456789a123456789a123456789a1234",
269 /*require_valid_internet_hostname=*/false)
270 .has_value());
271 EXPECT_FALSE(
272 DottedNameToNetwork(
273 "123456789a123456789a123456789a123456789a123456789a123456789a1234.",
274 /*require_valid_internet_hostname=*/false)
275 .has_value());
276
277 // 254 characters in the name: invalid
278 EXPECT_FALSE(
279 DottedNameToNetwork(
280 "123456789.123456789.123456789.123456789.123456789.123456789."
281 "123456789.123456789.123456789.123456789.123456789.123456789."
282 "123456789.123456789.123456789.123456789.123456789.123456789."
283 "123456789.123456789.123456789.123456789.123456789.123456789."
284 "123456789.1234",
285 /*require_valid_internet_hostname=*/false)
286 .has_value());
287 EXPECT_FALSE(
288 DottedNameToNetwork(
289 "123456789.123456789.123456789.123456789.123456789.123456789."
290 "123456789.123456789.123456789.123456789.123456789.123456789."
291 "123456789.123456789.123456789.123456789.123456789.123456789."
292 "123456789.123456789.123456789.123456789.123456789.123456789."
293 "123456789.1234.",
294 /*require_valid_internet_hostname=*/false)
295 .has_value());
296
297 // 255 characters in the name: invalid before even trying to add a final
298 // zero-length termination
299 EXPECT_FALSE(
300 DottedNameToNetwork(
301 "123456789.123456789.123456789.123456789.123456789.123456789."
302 "123456789.123456789.123456789.123456789.123456789.123456789."
303 "123456789.123456789.123456789.123456789.123456789.123456789."
304 "123456789.123456789.123456789.123456789.123456789.123456789."
305 "123456789.12345",
306 /*require_valid_internet_hostname=*/false)
307 .has_value());
308 EXPECT_FALSE(
309 DottedNameToNetwork(
310 "123456789.123456789.123456789.123456789.123456789.123456789."
311 "123456789.123456789.123456789.123456789.123456789.123456789."
312 "123456789.123456789.123456789.123456789.123456789.123456789."
313 "123456789.123456789.123456789.123456789.123456789.123456789."
314 "123456789.12345.",
315 /*require_valid_internet_hostname=*/false)
316 .has_value());
317 }
318
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidationRejectsRestrictedCharacters)319 TEST(DnsNamesUtilTest,
320 DottedNameToNetworkWithValidationRejectsRestrictedCharacters) {
321 EXPECT_FALSE(DottedNameToNetwork("foo,bar.com",
322 /*require_valid_internet_hostname=*/true)
323 .has_value());
324 EXPECT_FALSE(DottedNameToNetwork("_ipp._tcp.local.foo printer (bar)",
325 /*require_valid_internet_hostname=*/true)
326 .has_value());
327 }
328
TEST(DnsNamesUtilTest,DottedNameToNetworkAcceptsRestrictedCharacters)329 TEST(DnsNamesUtilTest, DottedNameToNetworkAcceptsRestrictedCharacters) {
330 EXPECT_THAT(DottedNameToNetwork("foo,bar.com",
331 /*require_valid_internet_hostname=*/false),
332 Optional(ToBytes("\007foo,bar\003com")));
333
334 EXPECT_THAT(
335 DottedNameToNetwork("_ipp._tcp.local.foo printer (bar)",
336 /*require_valid_internet_hostname=*/false),
337 Optional(ToBytes("\004_ipp\004_tcp\005local\021foo printer (bar)")));
338 }
339
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleSimpleNames)340 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleSimpleNames) {
341 std::string dns_name = "\003foo";
342 EXPECT_THAT(NetworkToDottedName(dns_name), Optional(Eq("foo")));
343 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
344 EXPECT_THAT(NetworkToDottedName(reader), Optional(Eq("foo")));
345
346 dns_name += "\003bar";
347 EXPECT_THAT(NetworkToDottedName(dns_name), Optional(Eq("foo.bar")));
348 auto reader1 = base::BigEndianReader::FromStringPiece(dns_name);
349 EXPECT_THAT(NetworkToDottedName(reader1), Optional(Eq("foo.bar")));
350
351 dns_name += "\002uk";
352 EXPECT_THAT(NetworkToDottedName(dns_name), Optional(Eq("foo.bar.uk")));
353 auto reader2 = base::BigEndianReader::FromStringPiece(dns_name);
354 EXPECT_THAT(NetworkToDottedName(reader2), Optional(Eq("foo.bar.uk")));
355
356 dns_name += '\0';
357 EXPECT_THAT(NetworkToDottedName(dns_name), Optional(Eq("foo.bar.uk")));
358 auto reader3 = base::BigEndianReader::FromStringPiece(dns_name);
359 EXPECT_THAT(NetworkToDottedName(reader3), Optional(Eq("foo.bar.uk")));
360 }
361
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleEmpty)362 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleEmpty) {
363 std::string dns_name;
364
365 EXPECT_THAT(NetworkToDottedName(dns_name), Optional(Eq("")));
366 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
367 EXPECT_THAT(NetworkToDottedName(reader), Optional(Eq("")));
368
369 dns_name += '\0';
370
371 EXPECT_THAT(NetworkToDottedName(dns_name), Optional(Eq("")));
372 auto reader1 = base::BigEndianReader::FromStringPiece(dns_name);
373 EXPECT_THAT(NetworkToDottedName(reader1), Optional(Eq("")));
374 }
375
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectEmptyIncomplete)376 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectEmptyIncomplete) {
377 std::string dns_name;
378
379 EXPECT_THAT(NetworkToDottedName(dns_name, false /* require_complete */),
380 Optional(Eq("")));
381 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
382 EXPECT_THAT(NetworkToDottedName(reader, false /* require_complete */),
383 Optional(Eq("")));
384
385 EXPECT_EQ(NetworkToDottedName(dns_name, true /* require_complete */),
386 absl::nullopt);
387 auto reader1 = base::BigEndianReader::FromStringPiece(dns_name);
388 EXPECT_EQ(NetworkToDottedName(reader1, true /* require_complete */),
389 absl::nullopt);
390 }
391
392 // Test `require_complete` functionality given an input with terminating zero-
393 // length label.
TEST(DnsNamesUtilTest,NetworkToDottedNameComplete)394 TEST(DnsNamesUtilTest, NetworkToDottedNameComplete) {
395 std::string dns_name("\003foo\004test");
396 dns_name += '\0';
397
398 EXPECT_THAT(NetworkToDottedName(dns_name, false /* require_complete */),
399 Optional(Eq("foo.test")));
400 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
401 EXPECT_THAT(NetworkToDottedName(reader, false /* require_complete */),
402 Optional(Eq("foo.test")));
403
404 EXPECT_THAT(NetworkToDottedName(dns_name, true /* require_complete */),
405 Optional(Eq("foo.test")));
406 auto reader1 = base::BigEndianReader::FromStringPiece(dns_name);
407 EXPECT_THAT(NetworkToDottedName(reader1, true /* require_complete */),
408 Optional(Eq("foo.test")));
409 }
410
411 // Test `require_complete` functionality given an input without terminating
412 // zero-length label.
TEST(DnsNamesUtilTest,NetworkToDottedNameNotComplete)413 TEST(DnsNamesUtilTest, NetworkToDottedNameNotComplete) {
414 std::string dns_name("\003boo\004test");
415
416 EXPECT_THAT(NetworkToDottedName(dns_name, false /* require_complete */),
417 Optional(Eq("boo.test")));
418 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
419 EXPECT_THAT(NetworkToDottedName(reader, false /* require_complete */),
420 Optional(Eq("boo.test")));
421
422 EXPECT_EQ(NetworkToDottedName(dns_name, true /* require_complete */),
423 absl::nullopt);
424 auto reader2 = base::BigEndianReader::FromStringPiece(dns_name);
425 EXPECT_EQ(NetworkToDottedName(reader2, true /* require_complete */),
426 absl::nullopt);
427 }
428
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectEmptyWhenRequiringComplete)429 TEST(DnsNamesUtilTest,
430 NetworkToDottedNameShouldRejectEmptyWhenRequiringComplete) {
431 std::string dns_name;
432
433 EXPECT_THAT(NetworkToDottedName(dns_name, false /* require_complete */),
434 Optional(Eq("")));
435 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
436 EXPECT_THAT(NetworkToDottedName(reader, false /* require_complete */),
437 Optional(Eq("")));
438
439 EXPECT_EQ(NetworkToDottedName(dns_name, true /* require_complete */),
440 absl::nullopt);
441 auto reader1 = base::BigEndianReader::FromStringPiece(dns_name);
442 EXPECT_EQ(NetworkToDottedName(reader1, true /* require_complete */),
443 absl::nullopt);
444
445 dns_name += '\0';
446
447 EXPECT_THAT(NetworkToDottedName(dns_name, true /* require_complete */),
448 Optional(Eq("")));
449 auto reader2 = base::BigEndianReader::FromStringPiece(dns_name);
450 EXPECT_THAT(NetworkToDottedName(reader2, true /* require_complete */),
451 Optional(Eq("")));
452 }
453
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectCompression)454 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectCompression) {
455 std::string dns_name = CreateNamePointer(152);
456
457 EXPECT_EQ(NetworkToDottedName(dns_name), absl::nullopt);
458 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
459 EXPECT_EQ(NetworkToDottedName(reader), absl::nullopt);
460
461 dns_name = "\005hello";
462 dns_name += CreateNamePointer(152);
463
464 EXPECT_EQ(NetworkToDottedName(dns_name), absl::nullopt);
465 auto reader1 = base::BigEndianReader::FromStringPiece(dns_name);
466 EXPECT_EQ(NetworkToDottedName(reader1), absl::nullopt);
467 }
468
469 // Test that extra input past the terminating zero-length label are ignored.
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleExcessInput)470 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleExcessInput) {
471 std::string dns_name("\004cool\004name\004test");
472 dns_name += '\0';
473 dns_name += "blargh!";
474
475 EXPECT_THAT(NetworkToDottedName(dns_name), Optional(Eq("cool.name.test")));
476 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
477 EXPECT_THAT(NetworkToDottedName(reader), Optional(Eq("cool.name.test")));
478
479 dns_name = "\002hi";
480 dns_name += '\0';
481 dns_name += "goodbye";
482
483 EXPECT_THAT(NetworkToDottedName(dns_name), Optional(Eq("hi")));
484 auto reader1 = base::BigEndianReader::FromStringPiece(dns_name);
485 EXPECT_THAT(NetworkToDottedName(reader1), Optional(Eq("hi")));
486 }
487
488 // Test that input is malformed if it ends mid label.
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectTruncatedNames)489 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectTruncatedNames) {
490 std::string dns_name = "\07cheese";
491
492 EXPECT_EQ(NetworkToDottedName(dns_name), absl::nullopt);
493 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
494 EXPECT_EQ(NetworkToDottedName(reader), absl::nullopt);
495
496 dns_name = "\006cheesy\05test";
497
498 EXPECT_EQ(NetworkToDottedName(dns_name), absl::nullopt);
499 auto reader1 = base::BigEndianReader::FromStringPiece(dns_name);
500 EXPECT_EQ(NetworkToDottedName(reader1), absl::nullopt);
501 }
502
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleLongSingleLabel)503 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleLongSingleLabel) {
504 std::string dns_name(1, static_cast<char>(dns_protocol::kMaxLabelLength));
505 for (int i = 0; i < dns_protocol::kMaxLabelLength; ++i) {
506 dns_name += 'a';
507 }
508
509 EXPECT_NE(NetworkToDottedName(dns_name), absl::nullopt);
510 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
511 EXPECT_NE(NetworkToDottedName(reader), absl::nullopt);
512 }
513
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleLongSecondLabel)514 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleLongSecondLabel) {
515 std::string dns_name("\003foo");
516 dns_name += static_cast<char>(dns_protocol::kMaxLabelLength);
517 for (int i = 0; i < dns_protocol::kMaxLabelLength; ++i) {
518 dns_name += 'a';
519 }
520
521 EXPECT_NE(NetworkToDottedName(dns_name), absl::nullopt);
522 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
523 EXPECT_NE(NetworkToDottedName(reader), absl::nullopt);
524 }
525
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectTooLongSingleLabel)526 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectTooLongSingleLabel) {
527 std::string dns_name(1, static_cast<char>(dns_protocol::kMaxLabelLength));
528 for (int i = 0; i < dns_protocol::kMaxLabelLength + 1; ++i) {
529 dns_name += 'a';
530 }
531
532 EXPECT_EQ(NetworkToDottedName(dns_name), absl::nullopt);
533 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
534 EXPECT_EQ(NetworkToDottedName(reader), absl::nullopt);
535 }
536
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectTooLongSecondLabel)537 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectTooLongSecondLabel) {
538 std::string dns_name("\003foo");
539 dns_name += static_cast<char>(dns_protocol::kMaxLabelLength);
540 for (int i = 0; i < dns_protocol::kMaxLabelLength + 1; ++i) {
541 dns_name += 'a';
542 }
543
544 EXPECT_EQ(NetworkToDottedName(dns_name), absl::nullopt);
545 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
546 EXPECT_EQ(NetworkToDottedName(reader), absl::nullopt);
547 }
548
549 #if CHAR_MIN < 0
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectCharMinLabels)550 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectCharMinLabels) {
551 ASSERT_GT(static_cast<uint8_t>(CHAR_MIN), dns_protocol::kMaxLabelLength);
552
553 std::string dns_name;
554 dns_name += base::checked_cast<char>(CHAR_MIN);
555
556 // Wherever possible, make the name otherwise valid.
557 if (static_cast<uint8_t>(CHAR_MIN) < UINT8_MAX) {
558 for (uint8_t i = 0; i < static_cast<uint8_t>(CHAR_MIN); ++i) {
559 dns_name += 'a';
560 }
561 }
562
563 EXPECT_EQ(NetworkToDottedName(dns_name), absl::nullopt);
564 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
565 EXPECT_EQ(NetworkToDottedName(reader), absl::nullopt);
566 }
567 #endif // if CHAR_MIN < 0
568
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleLongName)569 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleLongName) {
570 std::string dns_name;
571 for (int i = 0; i < dns_protocol::kMaxNameLength;
572 i += (dns_protocol::kMaxLabelLength + 1)) {
573 int label_size = std::min(dns_protocol::kMaxNameLength - 1 - i,
574 dns_protocol::kMaxLabelLength);
575 dns_name += static_cast<char>(label_size);
576 for (int j = 0; j < label_size; ++j) {
577 dns_name += 'a';
578 }
579 }
580 ASSERT_EQ(dns_name.size(), static_cast<size_t>(dns_protocol::kMaxNameLength));
581
582 EXPECT_NE(NetworkToDottedName(dns_name), absl::nullopt);
583 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
584 EXPECT_NE(NetworkToDottedName(reader), absl::nullopt);
585 }
586
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectTooLongName)587 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectTooLongName) {
588 std::string dns_name;
589 for (int i = 0; i < dns_protocol::kMaxNameLength + 1;
590 i += (dns_protocol::kMaxLabelLength + 1)) {
591 int label_size = std::min(dns_protocol::kMaxNameLength - i,
592 dns_protocol::kMaxLabelLength);
593 dns_name += static_cast<char>(label_size);
594 for (int j = 0; j < label_size; ++j) {
595 dns_name += 'a';
596 }
597 }
598 ASSERT_EQ(dns_name.size(),
599 static_cast<size_t>(dns_protocol::kMaxNameLength + 1));
600
601 EXPECT_EQ(NetworkToDottedName(dns_name), absl::nullopt);
602 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
603 EXPECT_EQ(NetworkToDottedName(reader), absl::nullopt);
604 }
605
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleLongCompleteName)606 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleLongCompleteName) {
607 std::string dns_name;
608 for (int i = 0; i < dns_protocol::kMaxNameLength;
609 i += (dns_protocol::kMaxLabelLength + 1)) {
610 int label_size = std::min(dns_protocol::kMaxNameLength - 1 - i,
611 dns_protocol::kMaxLabelLength);
612 dns_name += static_cast<char>(label_size);
613 for (int j = 0; j < label_size; ++j) {
614 dns_name += 'a';
615 }
616 }
617 dns_name += '\0';
618 ASSERT_EQ(dns_name.size(),
619 static_cast<size_t>(dns_protocol::kMaxNameLength + 1));
620
621 EXPECT_NE(NetworkToDottedName(dns_name), absl::nullopt);
622 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
623 EXPECT_NE(NetworkToDottedName(reader), absl::nullopt);
624 }
625
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectTooLongCompleteName)626 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectTooLongCompleteName) {
627 std::string dns_name;
628 for (int i = 0; i < dns_protocol::kMaxNameLength + 1;
629 i += (dns_protocol::kMaxLabelLength + 1)) {
630 int label_size = std::min(dns_protocol::kMaxNameLength - i,
631 dns_protocol::kMaxLabelLength);
632 dns_name += static_cast<char>(label_size);
633 for (int j = 0; j < label_size; ++j) {
634 dns_name += 'a';
635 }
636 }
637 dns_name += '\0';
638 ASSERT_EQ(dns_name.size(),
639 static_cast<size_t>(dns_protocol::kMaxNameLength + 2));
640
641 EXPECT_EQ(NetworkToDottedName(dns_name), absl::nullopt);
642 auto reader = base::BigEndianReader::FromStringPiece(dns_name);
643 EXPECT_EQ(NetworkToDottedName(reader), absl::nullopt);
644 }
645
TEST(DnsNamesUtilTest,ValidDnsNames)646 TEST(DnsNamesUtilTest, ValidDnsNames) {
647 constexpr base::StringPiece kGoodHostnames[] = {
648 "www.noodles.blorg", "1www.noodles.blorg", "www.2noodles.blorg",
649 "www.n--oodles.blorg", "www.noodl_es.blorg", "www.no-_odles.blorg",
650 "www_.noodles.blorg", "www.noodles.blorg.", "_privet._tcp.local",
651 "%20%20noodles.blorg", "noo dles.blorg ", "noo dles_ipp._tcp.local",
652 "www.nood(les).blorg", "noo dl(es)._tcp.local",
653 };
654
655 for (base::StringPiece good_hostname : kGoodHostnames) {
656 EXPECT_TRUE(IsValidDnsName(good_hostname));
657 EXPECT_TRUE(IsValidDnsRecordName(good_hostname));
658 }
659 }
660
TEST(DnsNamesUtilTest,EmptyNotValidDnsName)661 TEST(DnsNamesUtilTest, EmptyNotValidDnsName) {
662 EXPECT_FALSE(IsValidDnsName(""));
663 EXPECT_FALSE(IsValidDnsRecordName(""));
664 }
665
TEST(DnsNamesUtilTest,EmptyLabelNotValidDnsName)666 TEST(DnsNamesUtilTest, EmptyLabelNotValidDnsName) {
667 EXPECT_FALSE(IsValidDnsName("www..test"));
668 EXPECT_FALSE(IsValidDnsName(".foo.test"));
669
670 EXPECT_FALSE(IsValidDnsRecordName("www..test"));
671 EXPECT_FALSE(IsValidDnsRecordName(".foo.test"));
672 }
673
TEST(DnsNameUtilTest,LongLabelsInValidDnsNames)674 TEST(DnsNameUtilTest, LongLabelsInValidDnsNames) {
675 EXPECT_TRUE(IsValidDnsName(
676 "z23456789a123456789a123456789a123456789a123456789a123456789a123"));
677 EXPECT_TRUE(IsValidDnsName(
678 "z23456789a123456789a123456789a123456789a123456789a123456789a123."));
679
680 EXPECT_TRUE(IsValidDnsRecordName(
681 "z23456789a123456789a123456789a123456789a123456789a123456789a123"));
682 EXPECT_TRUE(IsValidDnsRecordName(
683 "z23456789a123456789a123456789a123456789a123456789a123456789a123."));
684 }
685
TEST(DnsNameUtilTest,TooLongLabelsInInvalidDnsNames)686 TEST(DnsNameUtilTest, TooLongLabelsInInvalidDnsNames) {
687 EXPECT_FALSE(IsValidDnsName(
688 "123456789a123456789a123456789a123456789a123456789a123456789a1234"));
689 EXPECT_FALSE(IsValidDnsName(
690 "z23456789a123456789a123456789a123456789a123456789a123456789a1234."));
691
692 EXPECT_FALSE(IsValidDnsRecordName(
693 "z23456789a123456789a123456789a123456789a123456789a123456789a1234"));
694 EXPECT_FALSE(IsValidDnsRecordName(
695 "z23456789a123456789a123456789a123456789a123456789a123456789a1234."));
696 }
697
TEST(DnsNameUtilTest,LongValidDnsNames)698 TEST(DnsNameUtilTest, LongValidDnsNames) {
699 EXPECT_TRUE(IsValidDnsName(
700 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
701 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
702 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
703 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
704 "abcdefghi.abc"));
705 EXPECT_TRUE(IsValidDnsName(
706 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
707 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
708 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
709 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
710 "abcdefghi.abc."));
711
712 EXPECT_TRUE(IsValidDnsRecordName(
713 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
714 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
715 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
716 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
717 "abcdefghi.abc"));
718 EXPECT_TRUE(IsValidDnsRecordName(
719 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
720 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
721 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
722 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
723 "abcdefghi.abc."));
724 }
725
TEST(DnsNameUtilTest,TooLongInalidDnsNames)726 TEST(DnsNameUtilTest, TooLongInalidDnsNames) {
727 EXPECT_FALSE(IsValidDnsName(
728 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
729 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
730 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
731 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
732 "abcdefghi.abcd"));
733 EXPECT_FALSE(IsValidDnsName(
734 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
735 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
736 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
737 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
738 "abcdefghi.abcd."));
739
740 EXPECT_FALSE(IsValidDnsRecordName(
741 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
742 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
743 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
744 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
745 "abcdefghi.abcd"));
746 EXPECT_FALSE(IsValidDnsRecordName(
747 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
748 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
749 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
750 "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
751 "abcdefghi.abcd."));
752 }
753
TEST(DnsNameUtilTest,LocalhostNotValidDnsRecordName)754 TEST(DnsNameUtilTest, LocalhostNotValidDnsRecordName) {
755 EXPECT_TRUE(IsValidDnsName("localhost"));
756 EXPECT_FALSE(IsValidDnsRecordName("localhost"));
757 }
758
TEST(DnsNameUtilTest,IpAddressNotValidDnsRecordName)759 TEST(DnsNameUtilTest, IpAddressNotValidDnsRecordName) {
760 EXPECT_TRUE(IsValidDnsName("1.2.3.4"));
761 EXPECT_FALSE(IsValidDnsRecordName("1.2.3.4"));
762
763 EXPECT_TRUE(IsValidDnsName("[2001:4860:4860::8888]"));
764 EXPECT_FALSE(IsValidDnsRecordName("[2001:4860:4860::8888]"));
765
766 EXPECT_TRUE(IsValidDnsName("2001:4860:4860::8888"));
767 EXPECT_FALSE(IsValidDnsRecordName("2001:4860:4860::8888"));
768 }
769
TEST(DnsUtilTest,CanonicalizeNames)770 TEST(DnsUtilTest, CanonicalizeNames) {
771 EXPECT_EQ(UrlCanonicalizeNameIfAble("GOOGLE.test"), "google.test");
772
773 EXPECT_EQ(UrlCanonicalizeNameIfAble("g{oo}gle.test"), "g{oo}gle.test");
774 EXPECT_EQ(UrlCanonicalizeNameIfAble("G{OO}GLE.test"), "g{oo}gle.test");
775
776 // g�gle.test
777 EXPECT_EQ(UrlCanonicalizeNameIfAble("g\u00FCgle.test"), "xn--ggle-0ra.test");
778 EXPECT_EQ(UrlCanonicalizeNameIfAble("G\u00fcGLE.test"), "xn--ggle-0ra.test");
779 }
780
TEST(DnsUtilTest,IgnoreUncanonicalizeableNames)781 TEST(DnsUtilTest, IgnoreUncanonicalizeableNames) {
782 EXPECT_EQ(UrlCanonicalizeNameIfAble(""), "");
783
784 // Forbidden domain code point.
785 // https://url.spec.whatwg.org/#forbidden-domain-code-point
786 EXPECT_EQ(UrlCanonicalizeNameIfAble("g<oo>gle.test"), "g<oo>gle.test");
787 EXPECT_EQ(UrlCanonicalizeNameIfAble("G<OO>GLE.test"), "G<OO>GLE.test");
788
789 // Invalid UTF8 character.
790 EXPECT_EQ(UrlCanonicalizeNameIfAble("g\x00FCgle.test"), "g\x00fcgle.test");
791 EXPECT_EQ(UrlCanonicalizeNameIfAble("G\x00fcGLE.test"), "G\x00fcGLE.test");
792
793 // Disallowed ASCII character.
794 EXPECT_EQ(UrlCanonicalizeNameIfAble("google\n.test"), "google\n.test");
795 EXPECT_EQ(UrlCanonicalizeNameIfAble("GOOGLE\n.test"), "GOOGLE\n.test");
796 }
797
798 } // namespace
799 } // namespace net::dns_names_util
800