Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(345)

Side by Side Diff: tools/origin_trials/validate_subdomain_origin/validate_subdomain_origin.cc

Issue 2456053004: Validate origins when generating subdomain tokens (Closed)
Patch Set: Address comments Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
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 <stddef.h>
6 #include <stdint.h>
7
8 #include <iostream>
9 #include <string>
10
11 #include "base/command_line.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/strings/string_piece.h"
14 #include "base/strings/string_util.h"
15 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
16 #include "net/base/url_util.h"
17 #include "url/gurl.h"
18
19 using net::registry_controlled_domains::GetCanonicalHostRegistryLength;
20 using net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES;
21 using net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES;
22 using net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES;
23
24 // Return codes used by this utility.
25 static const int kStatusValid = 0;
26 static const int kStatusInvalidOrigin = 1;
27 static const int kStatusInPublicSuffixList = 2;
28 static const int kStatusError = 3;
29
30 // Causes the app to suppress logging/verbose output
31 static const char kOptionQuiet[] = "quiet";
32
33 void PrintHelp() {
34 std::cerr
35 << "Usage:\n"
36 " validate_subdomain_origin [--quiet] <origin>\n"
37 " Checks that the origin can be used in a token that matches\n"
38 " subdomains, returning 0 when the origin is valid for such use.\n"
39 " The origin may be specified as an url (e.g. "
40 "'https://example.com'),\n"
41 " or as bare hostname (e.g. 'example.com').\n"
42 " Pass \"--quiet\" to suppress any output.\n";
43 }
44
45 void PrintValidHost(const base::CommandLine::StringType origin) {
46 std::cerr << "validate_subdomain_origin: Valid origin - " << origin
47 << std::endl;
48 }
49
50 void PrintValidIPAddress(const base::CommandLine::StringType origin) {
51 std::cerr << "validate_subdomain_origin: Valid origin (IP address) - "
52 << origin << std::endl;
53 }
54
55 void PrintInvalidUrl(const base::CommandLine::StringType origin) {
56 std::cerr << "validate_subdomain_origin: Invalid url format for origin - "
57 << origin << std::endl;
58 }
59
60 void PrintInvalidOrigin(const base::CommandLine::StringType origin) {
61 std::cerr << "validate_subdomain_origin: Invalid origin - " << origin
62 << std::endl;
63 }
64
65 void PrintInPublicSuffixList(const base::CommandLine::StringType origin) {
66 std::cerr << "validate_subdomain_origin: Origin in Public Suffix List - "
67 << origin << std::endl;
68 }
69
70 int CheckOrigin(const base::CommandLine::StringType origin, bool log_enabled) {
71 base::StringPiece host;
72 std::unique_ptr<std::string> canon_host = nullptr;
73
74 // Validate the origin, which may be provided as an url (with scheme prefix),
75 // or just as a hostname. Regardless of format, if the origin is identified
76 // as an IP address, that is valid for subdomain tokens.
77 GURL gurl(origin);
78 if (gurl.is_valid()) {
79 if (gurl.HostIsIPAddress()) {
80 if (log_enabled) {
81 PrintValidIPAddress(origin);
82 }
83 return kStatusValid;
84 }
85 host = gurl.host_piece();
86 } else {
87 // Check if it looks like an url that is not valid
88 if (base::StartsWith(origin, "http",
89 base::CompareCase::INSENSITIVE_ASCII)) {
90 if (log_enabled) {
91 PrintInvalidUrl(origin);
92 }
93 return kStatusInvalidOrigin;
94 }
95 // Doesn't look like an url, try the origin as a hostname
96 url::CanonHostInfo host_info;
97 canon_host = base::MakeUnique<std::string>(
98 net::CanonicalizeHost(origin, &host_info));
99 if (canon_host->empty()) {
100 if (log_enabled) {
101 PrintInvalidOrigin(origin);
102 }
103 return kStatusInvalidOrigin;
104 }
105 if (host_info.IsIPAddress()) {
106 if (log_enabled) {
107 PrintValidIPAddress(origin);
108 }
109 return kStatusValid;
110 }
111 host.set(canon_host->c_str());
112 }
113
114 size_t registry_length = GetCanonicalHostRegistryLength(
115 host, INCLUDE_UNKNOWN_REGISTRIES, INCLUDE_PRIVATE_REGISTRIES);
116
117 if (registry_length > 0) {
118 // Host has at least one subcomponent (e.g. a.b), and the host is not just
119 // a registry (e.g. co.uk).
120 if (log_enabled) {
121 PrintValidHost(origin);
122 }
123 return kStatusValid;
124 }
125
126 // If registry length is 0, then the host may be a registry, or it has no
127 // subcomponents. If there are subcomponents, the host must be a registry,
128 // which makes it invalid.
129 if (host.find('.') != std::string::npos) {
130 if (log_enabled) {
131 PrintInPublicSuffixList(origin);
132 }
133 return kStatusInPublicSuffixList;
134 }
135
136 // There are no subcomponents, but still don't know if this a registry
137 // (e.g. host = "com"), or a private/internal address (e.g. host = "bar").
138 // Test by adding a subcomponent, and re-checking the registry. In this case,
139 // exclude unknown registries. That means that "prefix.com" will match the
140 // "com" registry, and return a non-zero length. Conversely, "prefix.bar" will
141 // not match any known registry, and return a zero length.
142 std::string test_host("prefix.");
143 test_host.append(host.as_string());
144
145 size_t test_registry_length = GetCanonicalHostRegistryLength(
146 test_host, EXCLUDE_UNKNOWN_REGISTRIES, INCLUDE_PRIVATE_REGISTRIES);
147 if (test_registry_length > 0) {
148 if (log_enabled) {
149 PrintInPublicSuffixList(origin);
150 }
151 return kStatusInPublicSuffixList;
152 }
153
154 if (log_enabled) {
155 PrintValidHost(origin);
156 }
157 return kStatusValid;
158 }
159
160 int main(int argc, const char* argv[]) {
161 base::CommandLine::Init(argc, argv);
162 const base::CommandLine& parsed_command_line =
163 *base::CommandLine::ForCurrentProcess();
164 const base::CommandLine::StringVector& args = parsed_command_line.GetArgs();
165 bool quiet = parsed_command_line.HasSwitch(kOptionQuiet);
166 if (args.size() == 1) {
167 return CheckOrigin(args[0], !quiet);
168 }
169
170 PrintHelp();
171 return kStatusError;
172 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698