summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quiche/common/platform/api/quiche_hostname_utils.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/third_party/quiche/src/quiche/common/platform/api/quiche_hostname_utils.cc')
-rw-r--r--chromium/net/third_party/quiche/src/quiche/common/platform/api/quiche_hostname_utils.cc109
1 files changed, 109 insertions, 0 deletions
diff --git a/chromium/net/third_party/quiche/src/quiche/common/platform/api/quiche_hostname_utils.cc b/chromium/net/third_party/quiche/src/quiche/common/platform/api/quiche_hostname_utils.cc
new file mode 100644
index 00000000000..19ac83e61cc
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quiche/common/platform/api/quiche_hostname_utils.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "quiche/common/platform/api/quiche_hostname_utils.h"
+
+#include <string>
+
+#include "absl/strings/string_view.h"
+#include "url/url_canon.h"
+#include "url/url_canon_stdstring.h"
+#include "quiche/common/platform/api/quiche_logging.h"
+
+namespace quiche {
+
+// TODO(vasilvv): the functions below are forked from Chromium's
+// net/base/url_util.h; those should be moved to googleurl.
+namespace {
+
+std::string CanonicalizeHost(absl::string_view host,
+ url::CanonHostInfo* host_info) {
+ // Try to canonicalize the host.
+ const url::Component raw_host_component(0, static_cast<int>(host.length()));
+ std::string canon_host;
+ url::StdStringCanonOutput canon_host_output(&canon_host);
+ url::CanonicalizeHostVerbose(host.data(), raw_host_component,
+ &canon_host_output, host_info);
+
+ if (host_info->out_host.is_nonempty() &&
+ host_info->family != url::CanonHostInfo::BROKEN) {
+ // Success! Assert that there's no extra garbage.
+ canon_host_output.Complete();
+ QUICHE_DCHECK_EQ(host_info->out_host.len,
+ static_cast<int>(canon_host.length()));
+ } else {
+ // Empty host, or canonicalization failed. We'll return empty.
+ canon_host.clear();
+ }
+
+ return canon_host;
+}
+
+bool IsHostCharAlphanumeric(char c) {
+ // We can just check lowercase because uppercase characters have already been
+ // normalized.
+ return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'));
+}
+
+bool IsCanonicalizedHostCompliant(const std::string& host) {
+ if (host.empty()) {
+ return false;
+ }
+
+ bool in_component = false;
+ bool most_recent_component_started_alphanumeric = false;
+
+ for (char c : host) {
+ if (!in_component) {
+ most_recent_component_started_alphanumeric = IsHostCharAlphanumeric(c);
+ if (!most_recent_component_started_alphanumeric && (c != '-') &&
+ (c != '_')) {
+ return false;
+ }
+ in_component = true;
+ } else if (c == '.') {
+ in_component = false;
+ } else if (!IsHostCharAlphanumeric(c) && (c != '-') && (c != '_')) {
+ return false;
+ }
+ }
+
+ return most_recent_component_started_alphanumeric;
+}
+
+} // namespace
+
+// static
+bool QuicheHostnameUtils::IsValidSNI(absl::string_view sni) {
+ // TODO(rtenneti): Support RFC2396 hostname.
+ // NOTE: Microsoft does NOT enforce this spec, so if we throw away hostnames
+ // based on the above spec, we may be losing some hostnames that windows
+ // would consider valid. By far the most common hostname character NOT
+ // accepted by the above spec is '_'.
+ url::CanonHostInfo host_info;
+ std::string canonicalized_host = CanonicalizeHost(sni, &host_info);
+ return !host_info.IsIPAddress() &&
+ IsCanonicalizedHostCompliant(canonicalized_host);
+}
+
+// static
+std::string QuicheHostnameUtils::NormalizeHostname(absl::string_view hostname) {
+ url::CanonHostInfo host_info;
+ std::string host = CanonicalizeHost(hostname, &host_info);
+
+ // Walk backwards over the string, stopping at the first trailing dot.
+ size_t host_end = host.length();
+ while (host_end != 0 && host[host_end - 1] == '.') {
+ host_end--;
+ }
+
+ // Erase the trailing dots.
+ if (host_end != host.length()) {
+ host.erase(host_end, host.length() - host_end);
+ }
+
+ return host;
+}
+
+} // namespace quiche