OLD | NEW |
---|---|
(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 } | |
OLD | NEW |