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

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

Issue 2456053004: Validate origins when generating subdomain tokens (Closed)
Patch Set: Rebase 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 void PrintHelp() {
31 std::cerr
32 << "Usage:\n"
33 " validate_subdomain_origin <origin>\n"
34 " Checks that the origin can be used in a token that matches\n"
35 " subdomains, returning 0 when the origin is valid for such use.\n"
36 " The origin may be specified as an url (e.g. "
37 "'https://example.com'),\n"
38 " or as bare hostname (e.g. 'example.com').\n";
39 }
40
41 int CheckOrigin(const base::CommandLine::StringType origin) {
42 base::StringPiece host;
43 std::unique_ptr<std::string> canon_host = nullptr;
44
45 // Validate the origin, which may be provided as an url (with scheme prefix),
46 // or just as a hostname. Regardless of format, if the origin is identified
47 // as an IP address, that is valid for subdomain tokens.
48 GURL gurl(origin);
49 if (gurl.is_valid()) {
50 if (gurl.HostIsIPAddress()) {
51 return kStatusValid;
52 }
53 host = gurl.host_piece();
54 } else {
55 // Check if it looks like an url, that is not valid
iclelland 2016/11/02 15:25:47 nit: drop the comma
chasej 2016/11/03 19:23:40 Done.
56 if (base::StartsWith(origin, "http",
iclelland 2016/11/02 15:25:47 Less of a nit: Why does this utility care whether
iclelland 2016/11/02 15:28:55 Actually, I misunderstood -- I tried to get this t
chasej 2016/11/03 19:23:40 I was trying to address the scenario where GURL.is
iclelland 2016/11/03 19:47:55 I agree that if we can drop this check, then we sh
57 base::CompareCase::INSENSITIVE_ASCII)) {
58 std::cerr << "validate_subdomain_origin: Invalid url - " << origin
59 << std::endl;
60 return kStatusInvalidOrigin;
61 }
62 // Doesn't look like an url, try the origin as a hostname
63 url::CanonHostInfo host_info;
64 canon_host = base::MakeUnique<std::string>(
65 net::CanonicalizeHost(origin, &host_info));
66 if (canon_host->empty()) {
67 std::cerr << "validate_subdomain_origin: Invalid origin - " << origin
68 << std::endl;
69 return kStatusInvalidOrigin;
70 }
71 if (host_info.IsIPAddress()) {
72 return kStatusValid;
73 }
74 host.set(canon_host->c_str());
iclelland 2016/11/02 15:25:47 What happens to this string after this block ends?
chasej 2016/11/03 19:23:40 canon_host not is declared in this block - it's sc
iclelland 2016/11/03 19:47:55 Ahh, you're right; that makes sense. Thanks.
75 }
76
77 size_t registry_length = GetCanonicalHostRegistryLength(
78 host, INCLUDE_UNKNOWN_REGISTRIES, INCLUDE_PRIVATE_REGISTRIES);
79
80 if (registry_length > 0) {
81 // Host has at least one subcomponent (e.g. a.b), and the host is not just
82 // a registry (e.g. co.uk).
83 return kStatusValid;
84 }
85
86 // If registry length is 0, then the host may be a registry, or it has no
87 // subcomponents. If there are subcomponents, the host must be a registry,
88 // which makes it invalid.
89 if (host.find('.') != std::string::npos) {
90 std::cerr << "validate_subdomain_origin: Origin in Public Suffix List - "
91 << host << std::endl;
92 return kStatusInPublicSuffixList;
93 }
94
95 // There are no subcomponents, but still don't know if this a registry
96 // (e.g. host = "com"), or a private/internal address (e.g. host = "bar").
97 // Test by adding a subcomponent, and re-checking the registry. In this case,
98 // exclude unknown registries. That means that "prefix.com" will match the
99 // "com" registry, and return a non-zero length. Conversely, "prefix.bar" will
100 // not match any known registry, and return a zero length.
101 std::string test_host("prefix.");
102 test_host.append(host.as_string());
103
104 size_t test_registry_length = GetCanonicalHostRegistryLength(
105 test_host, EXCLUDE_UNKNOWN_REGISTRIES, INCLUDE_PRIVATE_REGISTRIES);
106 if (test_registry_length > 0) {
107 std::cerr << "validate_subdomain_origin: Origin in Public Suffix List - "
iclelland 2016/11/02 15:25:47 Nit -- I'd prefer a '-v' or '-q' option to control
chasej 2016/11/03 19:23:40 Done. You can have a pony, but just this one time
108 << host << std::endl;
109 return kStatusInPublicSuffixList;
110 }
111
112 return kStatusValid;
113 }
114
115 int main(int argc, const char* argv[]) {
116 base::CommandLine::Init(argc, argv);
117 const base::CommandLine& parsed_command_line =
118 *base::CommandLine::ForCurrentProcess();
119
120 const base::CommandLine::StringVector& args = parsed_command_line.GetArgs();
121 if (args.size() == 1) {
122 return CheckOrigin(args[0]);
123 }
124
125 PrintHelp();
126 return kStatusError;
127 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698