• 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 #ifndef NET_DNS_DNS_NAMES_UTIL_H_
6 #define NET_DNS_DNS_NAMES_UTIL_H_
7 
8 #include <cstdint>
9 #include <string>
10 #include <vector>
11 
12 #include "base/containers/span.h"
13 #include "base/strings/string_piece.h"
14 #include "base/strings/string_util.h"
15 #include "net/base/net_export.h"
16 #include "third_party/abseil-cpp/absl/types/optional.h"
17 
18 namespace base {
19 class BigEndianReader;
20 }  // namespace base
21 
22 // Various utilities for converting, validating, and comparing DNS names.
23 namespace net::dns_names_util {
24 
25 // Returns true iff `dotted` is acceptable to be encoded as a DNS name. That is
26 // that it is non-empty and fits size limitations. Also must match the expected
27 // structure of dot-separated labels, each non-empty and fitting within
28 // additional size limitations, and an optional dot at the end. See RFCs 1035
29 // and 2181.
30 //
31 // No validation is performed for correctness of characters within a label.
32 // As explained by RFC 2181, commonly cited rules for such characters are not
33 // DNS restrictions, but actually restrictions for Internet hostnames. For such
34 // validation, see IsCanonicalizedHostCompliant().
35 NET_EXPORT_PRIVATE bool IsValidDnsName(base::StringPiece dotted_form_name);
36 
37 // Like IsValidDnsName() but further validates `dotted_form_name` is not an IP
38 // address (with or without surrounding []) or localhost, as such names would
39 // not be suitable for DNS queries or for use as DNS record names or alias
40 // target names.
41 NET_EXPORT_PRIVATE bool IsValidDnsRecordName(
42     base::StringPiece dotted_form_name);
43 
44 // Convert a dotted-form DNS name to network wire format. Returns nullopt if
45 // input is not valid for conversion (equivalent validity can be checked using
46 // IsValidDnsName()). If `require_valid_internet_hostname` is true, also returns
47 // nullopt if input is not a valid internet hostname (equivalent validity can be
48 // checked using net::IsCanonicalizedHostCompliant()).
49 NET_EXPORT_PRIVATE absl::optional<std::vector<uint8_t>> DottedNameToNetwork(
50     base::StringPiece dotted_form_name,
51     bool require_valid_internet_hostname = false);
52 
53 // Converts a domain in DNS format to a dotted string. Excludes the dot at the
54 // end.  Returns nullopt on malformed input.
55 //
56 // If `require_complete` is true, input will be considered malformed if it does
57 // not contain a terminating zero-length label. If false, assumes the standard
58 // terminating zero-length label at the end if not included in the input.
59 //
60 // DNS name compression (see RFC 1035, section 4.1.4) is disallowed and
61 // considered malformed. To handle a potentially compressed name, in a
62 // DnsResponse object, use DnsRecordParser::ReadName().
63 NET_EXPORT_PRIVATE absl::optional<std::string> NetworkToDottedName(
64     base::span<const uint8_t> dns_network_wire_name,
65     bool require_complete = false);
66 NET_EXPORT_PRIVATE absl::optional<std::string> NetworkToDottedName(
67     base::StringPiece dns_network_wire_name,
68     bool require_complete = false);
69 NET_EXPORT_PRIVATE absl::optional<std::string> NetworkToDottedName(
70     base::BigEndianReader& reader,
71     bool require_complete = false);
72 
73 // Canonicalize `name` as a URL hostname if able. If unable (typically if a name
74 // is not a valid URL hostname), returns `name` without change because such a
75 // name could still be a valid DNS name.
76 NET_EXPORT_PRIVATE std::string UrlCanonicalizeNameIfAble(
77     base::StringPiece name);
78 
79 // std::map-compliant Compare for two domain names. Works for any valid
80 // dotted-format or network-wire-format names. Returns true iff `lhs` is before
81 // `rhs` in strict weak ordering.
82 class NET_EXPORT_PRIVATE DomainNameComparator {
83  public:
operator()84   bool operator()(base::StringPiece lhs, base::StringPiece rhs) const {
85     // This works for dotted format or network-wire format as long as the names
86     // are valid because valid network-wire names have labels of max 63 bytes
87     // and thus will never have label length prefixes high enough to be
88     // misinterpreted as capital letters ('A' is 65).
89     return base::CompareCaseInsensitiveASCII(lhs, rhs) < 0;
90   }
91 };
92 
93 }  // namespace net::dns_names_util
94 
95 #endif  // NET_DNS_DNS_NAMES_UTIL_H_
96