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