1*6777b538SAndroid Build Coastguard Worker // Copyright 2022 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef NET_DNS_DNS_NAMES_UTIL_H_ 6*6777b538SAndroid Build Coastguard Worker #define NET_DNS_DNS_NAMES_UTIL_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <cstdint> 9*6777b538SAndroid Build Coastguard Worker #include <optional> 10*6777b538SAndroid Build Coastguard Worker #include <string> 11*6777b538SAndroid Build Coastguard Worker #include <string_view> 12*6777b538SAndroid Build Coastguard Worker #include <vector> 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/containers/span_reader.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h" 17*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h" 18*6777b538SAndroid Build Coastguard Worker 19*6777b538SAndroid Build Coastguard Worker // Various utilities for converting, validating, and comparing DNS names. 20*6777b538SAndroid Build Coastguard Worker namespace net::dns_names_util { 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Worker // Returns true iff `dotted` is acceptable to be encoded as a DNS name. That is 23*6777b538SAndroid Build Coastguard Worker // that it is non-empty and fits size limitations. Also must match the expected 24*6777b538SAndroid Build Coastguard Worker // structure of dot-separated labels, each non-empty and fitting within 25*6777b538SAndroid Build Coastguard Worker // additional size limitations, and an optional dot at the end. See RFCs 1035 26*6777b538SAndroid Build Coastguard Worker // and 2181. 27*6777b538SAndroid Build Coastguard Worker // 28*6777b538SAndroid Build Coastguard Worker // No validation is performed for correctness of characters within a label. 29*6777b538SAndroid Build Coastguard Worker // As explained by RFC 2181, commonly cited rules for such characters are not 30*6777b538SAndroid Build Coastguard Worker // DNS restrictions, but actually restrictions for Internet hostnames. For such 31*6777b538SAndroid Build Coastguard Worker // validation, see IsCanonicalizedHostCompliant(). 32*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE bool IsValidDnsName(std::string_view dotted_form_name); 33*6777b538SAndroid Build Coastguard Worker 34*6777b538SAndroid Build Coastguard Worker // Like IsValidDnsName() but further validates `dotted_form_name` is not an IP 35*6777b538SAndroid Build Coastguard Worker // address (with or without surrounding []) or localhost, as such names would 36*6777b538SAndroid Build Coastguard Worker // not be suitable for DNS queries or for use as DNS record names or alias 37*6777b538SAndroid Build Coastguard Worker // target names. 38*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE bool IsValidDnsRecordName(std::string_view dotted_form_name); 39*6777b538SAndroid Build Coastguard Worker 40*6777b538SAndroid Build Coastguard Worker // Convert a dotted-form DNS name to network wire format. Returns nullopt if 41*6777b538SAndroid Build Coastguard Worker // input is not valid for conversion (equivalent validity can be checked using 42*6777b538SAndroid Build Coastguard Worker // IsValidDnsName()). If `require_valid_internet_hostname` is true, also returns 43*6777b538SAndroid Build Coastguard Worker // nullopt if input is not a valid internet hostname (equivalent validity can be 44*6777b538SAndroid Build Coastguard Worker // checked using net::IsCanonicalizedHostCompliant()). 45*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE std::optional<std::vector<uint8_t>> DottedNameToNetwork( 46*6777b538SAndroid Build Coastguard Worker std::string_view dotted_form_name, 47*6777b538SAndroid Build Coastguard Worker bool require_valid_internet_hostname = false); 48*6777b538SAndroid Build Coastguard Worker 49*6777b538SAndroid Build Coastguard Worker // Converts a domain in DNS format to a dotted string. Excludes the dot at the 50*6777b538SAndroid Build Coastguard Worker // end. Returns nullopt on malformed input. 51*6777b538SAndroid Build Coastguard Worker // 52*6777b538SAndroid Build Coastguard Worker // If `require_complete` is true, input will be considered malformed if it does 53*6777b538SAndroid Build Coastguard Worker // not contain a terminating zero-length label. If false, assumes the standard 54*6777b538SAndroid Build Coastguard Worker // terminating zero-length label at the end if not included in the input. 55*6777b538SAndroid Build Coastguard Worker // 56*6777b538SAndroid Build Coastguard Worker // DNS name compression (see RFC 1035, section 4.1.4) is disallowed and 57*6777b538SAndroid Build Coastguard Worker // considered malformed. To handle a potentially compressed name, in a 58*6777b538SAndroid Build Coastguard Worker // DnsResponse object, use DnsRecordParser::ReadName(). 59*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE std::optional<std::string> NetworkToDottedName( 60*6777b538SAndroid Build Coastguard Worker base::SpanReader<const uint8_t>& reader, 61*6777b538SAndroid Build Coastguard Worker bool require_complete = false); 62*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE std::optional<std::string> NetworkToDottedName( 63*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> span, 64*6777b538SAndroid Build Coastguard Worker bool require_complete = false); 65*6777b538SAndroid Build Coastguard Worker 66*6777b538SAndroid Build Coastguard Worker // Reads a length-prefixed region: 67*6777b538SAndroid Build Coastguard Worker // 1. reads a big-endian length L from the buffer of a size determined by the 68*6777b538SAndroid Build Coastguard Worker // function (e.g. ReadU8 reads an 8-bit length); 69*6777b538SAndroid Build Coastguard Worker // 2. sets `*out` to a span over the next L many bytes of the buffer (beyond 70*6777b538SAndroid Build Coastguard Worker // the end of the bytes encoding the length); and 71*6777b538SAndroid Build Coastguard Worker // 3. skips the main reader past this L-byte substring. 72*6777b538SAndroid Build Coastguard Worker // 73*6777b538SAndroid Build Coastguard Worker // Fails if reading the length L fails, or if the parsed length is greater 74*6777b538SAndroid Build Coastguard Worker // than the number of bytes remaining in the input span. 75*6777b538SAndroid Build Coastguard Worker // 76*6777b538SAndroid Build Coastguard Worker // On failure, leaves the stream at the same position 77*6777b538SAndroid Build Coastguard Worker // as before the call. 78*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE bool ReadU8LengthPrefixed( 79*6777b538SAndroid Build Coastguard Worker base::SpanReader<const uint8_t>& reader, 80*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t>* out); 81*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE bool ReadU16LengthPrefixed( 82*6777b538SAndroid Build Coastguard Worker base::SpanReader<const uint8_t>& reader, 83*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t>* out); 84*6777b538SAndroid Build Coastguard Worker 85*6777b538SAndroid Build Coastguard Worker // Canonicalize `name` as a URL hostname if able. If unable (typically if a name 86*6777b538SAndroid Build Coastguard Worker // is not a valid URL hostname), returns `name` without change because such a 87*6777b538SAndroid Build Coastguard Worker // name could still be a valid DNS name. 88*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE std::string UrlCanonicalizeNameIfAble(std::string_view name); 89*6777b538SAndroid Build Coastguard Worker 90*6777b538SAndroid Build Coastguard Worker // std::map-compliant Compare for two domain names. Works for any valid 91*6777b538SAndroid Build Coastguard Worker // dotted-format or network-wire-format names. Returns true iff `lhs` is before 92*6777b538SAndroid Build Coastguard Worker // `rhs` in strict weak ordering. 93*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE DomainNameComparator { 94*6777b538SAndroid Build Coastguard Worker public: operator()95*6777b538SAndroid Build Coastguard Worker bool operator()(std::string_view lhs, std::string_view rhs) const { 96*6777b538SAndroid Build Coastguard Worker // This works for dotted format or network-wire format as long as the names 97*6777b538SAndroid Build Coastguard Worker // are valid because valid network-wire names have labels of max 63 bytes 98*6777b538SAndroid Build Coastguard Worker // and thus will never have label length prefixes high enough to be 99*6777b538SAndroid Build Coastguard Worker // misinterpreted as capital letters ('A' is 65). 100*6777b538SAndroid Build Coastguard Worker return base::CompareCaseInsensitiveASCII(lhs, rhs) < 0; 101*6777b538SAndroid Build Coastguard Worker } 102*6777b538SAndroid Build Coastguard Worker }; 103*6777b538SAndroid Build Coastguard Worker 104*6777b538SAndroid Build Coastguard Worker } // namespace net::dns_names_util 105*6777b538SAndroid Build Coastguard Worker 106*6777b538SAndroid Build Coastguard Worker #endif // NET_DNS_DNS_NAMES_UTIL_H_ 107