• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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