| 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 "extensions/common/csp_validator.h" | 5 #include "extensions/common/csp_validator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <initializer_list> | 9 #include <initializer_list> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/callback.h" | 13 #include "base/callback.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/strings/string_piece.h" |
| 15 #include "base/strings/string_split.h" | 16 #include "base/strings/string_split.h" |
| 16 #include "base/strings/string_tokenizer.h" | 17 #include "base/strings/string_tokenizer.h" |
| 17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 18 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 19 #include "content/public/common/url_constants.h" | 20 #include "content/public/common/url_constants.h" |
| 20 #include "extensions/common/constants.h" | 21 #include "extensions/common/constants.h" |
| 21 #include "extensions/common/error_utils.h" | 22 #include "extensions/common/error_utils.h" |
| 22 #include "extensions/common/install_warning.h" | 23 #include "extensions/common/install_warning.h" |
| 23 #include "extensions/common/manifest_constants.h" | 24 #include "extensions/common/manifest_constants.h" |
| 24 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 25 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 | 191 |
| 191 InstallWarning CSPInstallWarning(const std::string& csp_warning) { | 192 InstallWarning CSPInstallWarning(const std::string& csp_warning) { |
| 192 return InstallWarning(csp_warning, manifest_keys::kContentSecurityPolicy); | 193 return InstallWarning(csp_warning, manifest_keys::kContentSecurityPolicy); |
| 193 } | 194 } |
| 194 | 195 |
| 195 std::string GetSecureDirectiveValues( | 196 std::string GetSecureDirectiveValues( |
| 196 int options, | 197 int options, |
| 197 const std::string& directive_name, | 198 const std::string& directive_name, |
| 198 const std::vector<base::StringPiece>& directive_values, | 199 const std::vector<base::StringPiece>& directive_values, |
| 199 std::vector<InstallWarning>* warnings) { | 200 std::vector<InstallWarning>* warnings) { |
| 200 std::vector<std::string> sane_csp_parts(1, directive_name); | 201 std::vector<base::StringPiece> sane_csp_parts{directive_name}; |
| 201 for (base::StringPiece source_literal : directive_values) { | 202 for (base::StringPiece source_literal : directive_values) { |
| 202 std::string source_lower = base::ToLowerASCII(source_literal); | 203 std::string source_lower = base::ToLowerASCII(source_literal); |
| 203 bool is_secure_csp_token = false; | 204 bool is_secure_csp_token = false; |
| 204 | 205 |
| 205 // We might need to relax this whitelist over time. | 206 // We might need to relax this whitelist over time. |
| 206 if (source_lower == "'self'" || source_lower == "'none'" || | 207 if (source_lower == "'self'" || source_lower == "'none'" || |
| 207 source_lower == "http://127.0.0.1" || source_lower == "blob:" || | 208 source_lower == "http://127.0.0.1" || source_lower == "blob:" || |
| 208 source_lower == "filesystem:" || source_lower == "http://localhost" || | 209 source_lower == "filesystem:" || source_lower == "http://localhost" || |
| 209 base::StartsWith(source_lower, "http://127.0.0.1:", | 210 base::StartsWith(source_lower, "http://127.0.0.1:", |
| 210 base::CompareCase::SENSITIVE) || | 211 base::CompareCase::SENSITIVE) || |
| (...skipping 13 matching lines...) Expand all Loading... |
| 224 } else if (base::StartsWith(source_lower, "chrome-extension-resource:", | 225 } else if (base::StartsWith(source_lower, "chrome-extension-resource:", |
| 225 base::CompareCase::SENSITIVE)) { | 226 base::CompareCase::SENSITIVE)) { |
| 226 // The "chrome-extension-resource" scheme has been removed from the | 227 // The "chrome-extension-resource" scheme has been removed from the |
| 227 // codebase, but it may still appear in existing CSPs. We continue to | 228 // codebase, but it may still appear in existing CSPs. We continue to |
| 228 // allow it here for compatibility. Requests on this scheme will not | 229 // allow it here for compatibility. Requests on this scheme will not |
| 229 // return any kind of network response. | 230 // return any kind of network response. |
| 230 is_secure_csp_token = true; | 231 is_secure_csp_token = true; |
| 231 } | 232 } |
| 232 | 233 |
| 233 if (is_secure_csp_token) { | 234 if (is_secure_csp_token) { |
| 234 sane_csp_parts.push_back(source_literal.as_string()); | 235 sane_csp_parts.push_back(source_literal); |
| 235 } else if (warnings) { | 236 } else if (warnings) { |
| 236 warnings->push_back(CSPInstallWarning(ErrorUtils::FormatErrorMessage( | 237 warnings->push_back(CSPInstallWarning(ErrorUtils::FormatErrorMessage( |
| 237 manifest_errors::kInvalidCSPInsecureValue, source_literal.as_string(), | 238 manifest_errors::kInvalidCSPInsecureValue, source_literal.as_string(), |
| 238 directive_name))); | 239 directive_name))); |
| 239 } | 240 } |
| 240 } | 241 } |
| 241 // End of CSP directive that was started at the beginning of this method. If | 242 // End of CSP directive that was started at the beginning of this method. If |
| 242 // none of the values are secure, the policy will be empty and default to | 243 // none of the values are secure, the policy will be empty and default to |
| 243 // 'none', which is secure. | 244 // 'none', which is secure. |
| 244 sane_csp_parts.back().push_back(kDirectiveSeparator); | 245 std::string last_part = sane_csp_parts.back().as_string(); |
| 246 last_part.push_back(kDirectiveSeparator); |
| 247 sane_csp_parts.back() = last_part; |
| 245 return base::JoinString(sane_csp_parts, " "); | 248 return base::JoinString(sane_csp_parts, " "); |
| 246 } | 249 } |
| 247 | 250 |
| 248 // Given a CSP directive-token for app sandbox, returns a secure value of that | 251 // Given a CSP directive-token for app sandbox, returns a secure value of that |
| 249 // directive. | 252 // directive. |
| 250 // The directive-token's name is |directive_name| and its values are splitted | 253 // The directive-token's name is |directive_name| and its values are splitted |
| 251 // into |directive_values|. | 254 // into |directive_values|. |
| 252 std::string GetAppSandboxSecureDirectiveValues( | 255 std::string GetAppSandboxSecureDirectiveValues( |
| 253 const std::string& directive_name, | 256 const std::string& directive_name, |
| 254 const std::vector<base::StringPiece>& directive_values, | 257 const std::vector<base::StringPiece>& directive_values, |
| 255 std::vector<InstallWarning>* warnings) { | 258 std::vector<InstallWarning>* warnings) { |
| 256 std::vector<std::string> sane_csp_parts(1, directive_name); | 259 std::vector<std::string> sane_csp_parts{directive_name}; |
| 257 bool seen_self_or_none = false; | 260 bool seen_self_or_none = false; |
| 258 for (base::StringPiece source_literal : directive_values) { | 261 for (base::StringPiece source_literal : directive_values) { |
| 259 std::string source_lower = base::ToLowerASCII(source_literal); | 262 std::string source_lower = base::ToLowerASCII(source_literal); |
| 260 | 263 |
| 261 // Keyword directive sources are surrounded with quotes, e.g. 'self', | 264 // Keyword directive sources are surrounded with quotes, e.g. 'self', |
| 262 // 'sha256-...', 'unsafe-eval', 'nonce-...'. These do not specify a remote | 265 // 'sha256-...', 'unsafe-eval', 'nonce-...'. These do not specify a remote |
| 263 // host or '*', so keep them and restrict the rest. | 266 // host or '*', so keep them and restrict the rest. |
| 264 if (source_lower.size() > 1u && source_lower[0] == '\'' && | 267 if (source_lower.size() > 1u && source_lower[0] == '\'' && |
| 265 source_lower.back() == '\'') { | 268 source_lower.back() == '\'') { |
| 266 seen_self_or_none |= source_lower == "'none'" || source_lower == "'self'"; | 269 seen_self_or_none |= source_lower == "'none'" || source_lower == "'self'"; |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 } | 589 } |
| 587 } | 590 } |
| 588 } | 591 } |
| 589 | 592 |
| 590 return seen_sandbox; | 593 return seen_sandbox; |
| 591 } | 594 } |
| 592 | 595 |
| 593 } // namespace csp_validator | 596 } // namespace csp_validator |
| 594 | 597 |
| 595 } // namespace extensions | 598 } // namespace extensions |
| OLD | NEW |