| 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 |