OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/common/extensions/permissions/socket_permission_entry.h" | 5 #include "extensions/common/permissions/socket_permission_entry.h" |
6 | 6 |
7 #include <cstdlib> | 7 #include <cstdlib> |
8 #include <sstream> | 8 #include <sstream> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
14 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
16 #include "chrome/common/extensions/permissions/socket_permission.h" | |
17 #include "extensions/common/permissions/api_permission.h" | 16 #include "extensions/common/permissions/api_permission.h" |
| 17 #include "extensions/common/permissions/socket_permission.h" |
18 #include "url/url_canon.h" | 18 #include "url/url_canon.h" |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 using content::SocketPermissionRequest; | 22 using content::SocketPermissionRequest; |
23 | 23 |
24 const char kColon = ':'; | 24 const char kColon = ':'; |
25 const char kDot = '.'; | 25 const char kDot = '.'; |
26 const char kWildcard[] = "*"; | 26 const char kWildcard[] = "*"; |
27 const int kWildcardPortNumber = 0; | 27 const int kWildcardPortNumber = 0; |
28 const int kInvalidPort = -1; | 28 const int kInvalidPort = -1; |
29 | 29 |
30 bool StartsOrEndsWithWhitespace(const std::string& str) { | 30 bool StartsOrEndsWithWhitespace(const std::string& str) { |
31 if (str.find_first_not_of(base::kWhitespaceASCII) != 0) | 31 if (str.find_first_not_of(base::kWhitespaceASCII) != 0) |
32 return true; | 32 return true; |
33 if (str.find_last_not_of(base::kWhitespaceASCII) != str.length() - 1) | 33 if (str.find_last_not_of(base::kWhitespaceASCII) != str.length() - 1) |
34 return true; | 34 return true; |
35 return false; | 35 return false; |
36 } | 36 } |
37 | 37 |
38 } // namespace | 38 } // namespace |
39 | 39 |
40 namespace extensions { | 40 namespace extensions { |
41 | 41 |
42 SocketPermissionEntry::SocketPermissionEntry() | 42 SocketPermissionEntry::SocketPermissionEntry() |
43 : pattern_(SocketPermissionRequest::NONE, std::string(), kInvalidPort), | 43 : pattern_(SocketPermissionRequest::NONE, std::string(), kInvalidPort), |
44 match_subdomains_(false) { | 44 match_subdomains_(false) {} |
45 } | |
46 | 45 |
47 SocketPermissionEntry::~SocketPermissionEntry() {} | 46 SocketPermissionEntry::~SocketPermissionEntry() {} |
48 | 47 |
49 bool SocketPermissionEntry::operator<(const SocketPermissionEntry& rhs) const { | 48 bool SocketPermissionEntry::operator<(const SocketPermissionEntry& rhs) const { |
50 if (pattern_.type < rhs.pattern_.type) | 49 if (pattern_.type < rhs.pattern_.type) |
51 return true; | 50 return true; |
52 if (pattern_.type > rhs.pattern_.type) | 51 if (pattern_.type > rhs.pattern_.type) |
53 return false; | 52 return false; |
54 | 53 |
55 if (pattern_.host < rhs.pattern_.host) | 54 if (pattern_.host < rhs.pattern_.host) |
(...skipping 26 matching lines...) Expand all Loading... |
82 std::string lhost = StringToLowerASCII(request.host); | 81 std::string lhost = StringToLowerASCII(request.host); |
83 if (pattern_.host != lhost) { | 82 if (pattern_.host != lhost) { |
84 if (!match_subdomains_) | 83 if (!match_subdomains_) |
85 return false; | 84 return false; |
86 | 85 |
87 if (!pattern_.host.empty()) { | 86 if (!pattern_.host.empty()) { |
88 // Do not wildcard part of IP address. | 87 // Do not wildcard part of IP address. |
89 url_parse::Component component(0, lhost.length()); | 88 url_parse::Component component(0, lhost.length()); |
90 url_canon::RawCanonOutputT<char, 128> ignored_output; | 89 url_canon::RawCanonOutputT<char, 128> ignored_output; |
91 url_canon::CanonHostInfo host_info; | 90 url_canon::CanonHostInfo host_info; |
92 url_canon::CanonicalizeIPAddress(lhost.c_str(), component, | 91 url_canon::CanonicalizeIPAddress( |
93 &ignored_output, &host_info); | 92 lhost.c_str(), component, &ignored_output, &host_info); |
94 if (host_info.IsIPAddress()) | 93 if (host_info.IsIPAddress()) |
95 return false; | 94 return false; |
96 | 95 |
97 // host should equal one or more chars + "." + host_. | 96 // host should equal one or more chars + "." + host_. |
98 int i = lhost.length() - pattern_.host.length(); | 97 int i = lhost.length() - pattern_.host.length(); |
99 if (i < 2) | 98 if (i < 2) |
100 return false; | 99 return false; |
101 | 100 |
102 if (lhost.compare(i, pattern_.host.length(), pattern_.host) != 0) | 101 if (lhost.compare(i, pattern_.host.length(), pattern_.host) != 0) |
103 return false; | 102 return false; |
104 | 103 |
105 if (lhost[i - 1] != kDot) | 104 if (lhost[i - 1] != kDot) |
106 return false; | 105 return false; |
107 } | 106 } |
108 } | 107 } |
109 | 108 |
110 if (pattern_.port != request.port && pattern_.port != kWildcardPortNumber) | 109 if (pattern_.port != request.port && pattern_.port != kWildcardPortNumber) |
111 return false; | 110 return false; |
112 | 111 |
113 return true; | 112 return true; |
114 } | 113 } |
115 | 114 |
116 SocketPermissionEntry::HostType SocketPermissionEntry::GetHostType() const { | 115 SocketPermissionEntry::HostType SocketPermissionEntry::GetHostType() const { |
117 return pattern_.host.empty() ? SocketPermissionEntry::ANY_HOST : | 116 return pattern_.host.empty() |
118 match_subdomains_ ? SocketPermissionEntry::HOSTS_IN_DOMAINS : | 117 ? SocketPermissionEntry::ANY_HOST |
119 SocketPermissionEntry::SPECIFIC_HOSTS; | 118 : match_subdomains_ ? SocketPermissionEntry::HOSTS_IN_DOMAINS |
| 119 : SocketPermissionEntry::SPECIFIC_HOSTS; |
120 } | 120 } |
121 | 121 |
122 bool SocketPermissionEntry::IsAddressBoundType() const { | 122 bool SocketPermissionEntry::IsAddressBoundType() const { |
123 return pattern_.type == SocketPermissionRequest::TCP_CONNECT || | 123 return pattern_.type == SocketPermissionRequest::TCP_CONNECT || |
124 pattern_.type == SocketPermissionRequest::TCP_LISTEN || | 124 pattern_.type == SocketPermissionRequest::TCP_LISTEN || |
125 pattern_.type == SocketPermissionRequest::UDP_BIND || | 125 pattern_.type == SocketPermissionRequest::UDP_BIND || |
126 pattern_.type == SocketPermissionRequest::UDP_SEND_TO; | 126 pattern_.type == SocketPermissionRequest::UDP_SEND_TO; |
127 } | 127 } |
128 | 128 |
129 // static | 129 // static |
130 bool SocketPermissionEntry::ParseHostPattern( | 130 bool SocketPermissionEntry::ParseHostPattern( |
131 SocketPermissionRequest::OperationType type, | 131 SocketPermissionRequest::OperationType type, |
132 const std::string& pattern, | 132 const std::string& pattern, |
133 SocketPermissionEntry* entry) { | 133 SocketPermissionEntry* entry) { |
134 std::vector<std::string> tokens; | 134 std::vector<std::string> tokens; |
135 base::SplitStringDontTrim(pattern, kColon, &tokens); | 135 base::SplitStringDontTrim(pattern, kColon, &tokens); |
136 return ParseHostPattern(type, tokens, entry); | 136 return ParseHostPattern(type, tokens, entry); |
(...skipping 15 matching lines...) Expand all Loading... |
152 | 152 |
153 result.pattern_.type = type; | 153 result.pattern_.type = type; |
154 result.pattern_.port = kWildcardPortNumber; | 154 result.pattern_.port = kWildcardPortNumber; |
155 result.match_subdomains_ = true; | 155 result.match_subdomains_ = true; |
156 | 156 |
157 if (pattern_tokens.size() == 0) { | 157 if (pattern_tokens.size() == 0) { |
158 *entry = result; | 158 *entry = result; |
159 return true; | 159 return true; |
160 } | 160 } |
161 | 161 |
162 // Return an error if address is specified for permissions that don't | 162 // Return an error if address is specified for permissions that don't |
163 // need it (such as 'resolve-host'). | 163 // need it (such as 'resolve-host'). |
164 if (!result.IsAddressBoundType()) | 164 if (!result.IsAddressBoundType()) |
165 return false; | 165 return false; |
166 | 166 |
167 result.pattern_.host = pattern_tokens[0]; | 167 result.pattern_.host = pattern_tokens[0]; |
168 if (!result.pattern_.host.empty()) { | 168 if (!result.pattern_.host.empty()) { |
169 if (StartsOrEndsWithWhitespace(result.pattern_.host)) | 169 if (StartsOrEndsWithWhitespace(result.pattern_.host)) |
170 return false; | 170 return false; |
171 result.pattern_.host = StringToLowerASCII(result.pattern_.host); | 171 result.pattern_.host = StringToLowerASCII(result.pattern_.host); |
172 | 172 |
173 // The first component can optionally be '*' to match all subdomains. | 173 // The first component can optionally be '*' to match all subdomains. |
174 std::vector<std::string> host_components; | 174 std::vector<std::string> host_components; |
175 base::SplitString(result.pattern_.host, kDot, &host_components); | 175 base::SplitString(result.pattern_.host, kDot, &host_components); |
176 DCHECK(!host_components.empty()); | 176 DCHECK(!host_components.empty()); |
177 | 177 |
178 if (host_components[0] == kWildcard || host_components[0].empty()) { | 178 if (host_components[0] == kWildcard || host_components[0].empty()) { |
179 host_components.erase(host_components.begin(), | 179 host_components.erase(host_components.begin(), |
180 host_components.begin() + 1); | 180 host_components.begin() + 1); |
181 } else { | 181 } else { |
182 result.match_subdomains_ = false; | 182 result.match_subdomains_ = false; |
183 } | 183 } |
184 result.pattern_.host = JoinString(host_components, kDot); | 184 result.pattern_.host = JoinString(host_components, kDot); |
185 } | 185 } |
186 | 186 |
187 if (pattern_tokens.size() == 1 || | 187 if (pattern_tokens.size() == 1 || pattern_tokens[1].empty() || |
188 pattern_tokens[1].empty() || | |
189 pattern_tokens[1] == kWildcard) { | 188 pattern_tokens[1] == kWildcard) { |
190 *entry = result; | 189 *entry = result; |
191 return true; | 190 return true; |
192 } | 191 } |
193 | 192 |
194 if (StartsOrEndsWithWhitespace(pattern_tokens[1])) | 193 if (StartsOrEndsWithWhitespace(pattern_tokens[1])) |
195 return false; | 194 return false; |
196 | 195 |
197 if (!base::StringToInt(pattern_tokens[1], &result.pattern_.port) || | 196 if (!base::StringToInt(pattern_tokens[1], &result.pattern_.port) || |
198 result.pattern_.port < 1 || result.pattern_.port > 65535) | 197 result.pattern_.port < 1 || result.pattern_.port > 65535) |
199 return false; | 198 return false; |
200 | 199 |
201 *entry = result; | 200 *entry = result; |
202 return true; | 201 return true; |
203 } | 202 } |
204 | 203 |
205 std::string SocketPermissionEntry::GetHostPatternAsString() const { | 204 std::string SocketPermissionEntry::GetHostPatternAsString() const { |
206 std::string result; | 205 std::string result; |
207 | 206 |
208 if (!IsAddressBoundType()) | 207 if (!IsAddressBoundType()) |
209 return result; | 208 return result; |
210 | 209 |
211 if (match_subdomains()) { | 210 if (match_subdomains()) { |
212 result.append(kWildcard); | 211 result.append(kWildcard); |
213 if (!pattern_.host.empty()) | 212 if (!pattern_.host.empty()) |
214 result.append(1, kDot).append(pattern_.host); | 213 result.append(1, kDot).append(pattern_.host); |
215 } else { | 214 } else { |
216 result.append(pattern_.host); | 215 result.append(pattern_.host); |
217 } | 216 } |
218 | 217 |
219 if (pattern_.port == kWildcardPortNumber) | 218 if (pattern_.port == kWildcardPortNumber) |
220 result.append(1, kColon).append(kWildcard); | 219 result.append(1, kColon).append(kWildcard); |
221 else | 220 else |
222 result.append(1, kColon).append(base::IntToString(pattern_.port)); | 221 result.append(1, kColon).append(base::IntToString(pattern_.port)); |
223 | 222 |
224 return result; | 223 return result; |
225 } | 224 } |
226 | 225 |
227 } // namespace extensions | 226 } // namespace extensions |
OLD | NEW |