| Index: extensions/common/csp_validator.cc
|
| diff --git a/extensions/common/csp_validator.cc b/extensions/common/csp_validator.cc
|
| index 3224ad6e1324d3348bb6d30be6372e2d982aa8a9..6895b31fdb0e7b8f8cd219f8709db6f2dd4b2a7e 100644
|
| --- a/extensions/common/csp_validator.cc
|
| +++ b/extensions/common/csp_validator.cc
|
| @@ -22,11 +22,20 @@ namespace {
|
| const char kDefaultSrc[] = "default-src";
|
| const char kScriptSrc[] = "script-src";
|
| const char kObjectSrc[] = "object-src";
|
| +const char kPluginTypes[] = "plugin-types";
|
|
|
| const char kSandboxDirectiveName[] = "sandbox";
|
| const char kAllowSameOriginToken[] = "allow-same-origin";
|
| const char kAllowTopNavigation[] = "allow-top-navigation";
|
|
|
| +// This is the list of plugin types which are fully sandboxed and are safe to
|
| +// load up in an extension, regardless of the URL they are navigated to.
|
| +const char* const kSandboxedPluginTypes[] = {
|
| + "application/pdf",
|
| + "application/x-google-chrome-pdf",
|
| + "application/x-pnacl"
|
| +};
|
| +
|
| struct DirectiveStatus {
|
| explicit DirectiveStatus(const char* name)
|
| : directive_name(name)
|
| @@ -156,6 +165,58 @@ bool UpdateStatus(const std::string& directive_name,
|
| return true;
|
| }
|
|
|
| +// Parses the plugin-types directive and returns the list of mime types
|
| +// specified in |plugin_types|.
|
| +bool ParsePluginTypes(const std::string& directive_name,
|
| + base::StringTokenizer& tokenizer,
|
| + std::vector<std::string>* plugin_types) {
|
| + DCHECK(plugin_types);
|
| +
|
| + if (directive_name != kPluginTypes || !plugin_types->empty())
|
| + return false;
|
| +
|
| + while (tokenizer.GetNext()) {
|
| + std::string mime_type = tokenizer.token();
|
| + base::StringToLowerASCII(&mime_type);
|
| + // Since we're comparing the mime types to a whitelist, we don't check them
|
| + // for strict validity right now.
|
| + plugin_types->push_back(mime_type);
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// Returns true if the |plugin_type| is one of the fully sandboxed plugin types.
|
| +bool PluginTypeAllowed(const std::string& plugin_type) {
|
| + for (size_t i = 0; i < arraysize(kSandboxedPluginTypes); ++i) {
|
| + if (plugin_type == kSandboxedPluginTypes[i])
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +// Returns true if the policy is allowed to contain an insecure object-src
|
| +// directive. This requires OPTIONS_ALLOW_INSECURE_OBJECT_SRC to be specified
|
| +// as an option and the plugin-types that can be loaded must be restricted to
|
| +// the set specified in kSandboxedPluginTypes.
|
| +bool AllowedToHaveInsecureObjectSrc(
|
| + int options,
|
| + const std::vector<std::string>& plugin_types) {
|
| + if (!(options & OPTIONS_ALLOW_INSECURE_OBJECT_SRC))
|
| + return false;
|
| +
|
| + // plugin-types must be specified.
|
| + if (plugin_types.empty())
|
| + return false;
|
| +
|
| + for (const auto& plugin_type : plugin_types) {
|
| + if (!PluginTypeAllowed(plugin_type))
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| } // namespace
|
|
|
| bool ContentSecurityPolicyIsLegal(const std::string& policy) {
|
| @@ -177,6 +238,8 @@ bool ContentSecurityPolicyIsSecure(const std::string& policy,
|
| DirectiveStatus script_src_status(kScriptSrc);
|
| DirectiveStatus object_src_status(kObjectSrc);
|
|
|
| + std::vector<std::string> plugin_types;
|
| +
|
| for (size_t i = 0; i < directives.size(); ++i) {
|
| std::string& input = directives[i];
|
| base::StringTokenizer tokenizer(input, " \t\r\n");
|
| @@ -192,6 +255,8 @@ bool ContentSecurityPolicyIsSecure(const std::string& policy,
|
| continue;
|
| if (UpdateStatus(directive_name, tokenizer, &object_src_status, options))
|
| continue;
|
| + if (ParsePluginTypes(directive_name, tokenizer, &plugin_types))
|
| + continue;
|
| }
|
|
|
| if (script_src_status.seen_in_policy && !script_src_status.is_secure)
|
| @@ -200,7 +265,7 @@ bool ContentSecurityPolicyIsSecure(const std::string& policy,
|
| if (object_src_status.seen_in_policy && !object_src_status.is_secure) {
|
| // Note that this does not fully check the object-src source list for
|
| // validity but Blink will do this anyway.
|
| - if (!(options & OPTIONS_ALLOW_INSECURE_OBJECT_SRC))
|
| + if (!AllowedToHaveInsecureObjectSrc(options, plugin_types))
|
| return false;
|
| }
|
|
|
|
|