csp_info.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/csp_info.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/csp_validator.h"
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/sandboxed_page_info.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace extensions {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace keys = manifest_keys;
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace errors = manifest_errors;
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using csp_validator::ContentSecurityPolicyIsLegal;
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using csp_validator::ContentSecurityPolicyIsSecure;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kDefaultContentSecurityPolicy[] =
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "script-src 'self' chrome-extension-resource:; object-src 'self'";
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define PLATFORM_APP_LOCAL_CSP_SOURCES \
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "'self' data: chrome-extension-resource:"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kDefaultPlatformAppContentSecurityPolicy[] =
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Platform apps can only use local resources by default.
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "default-src 'self' chrome-extension-resource:;"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // For remote resources, they can fetch them via XMLHttpRequest.
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "connect-src *;"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // And serve them via data: or same-origin (blob:, filesystem:) URLs
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "style-src " PLATFORM_APP_LOCAL_CSP_SOURCES " 'unsafe-inline';"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "img-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "frame-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "font-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Media can be loaded from remote resources since:
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // 1. <video> and <audio> have good fallback behavior when offline or under
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //    spotty connectivity.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // 2. Fetching via XHR and serving via blob: URLs currently does not allow
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //    streaming or partial buffering.
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "media-src *;";
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CSPInfo::CSPInfo(const std::string& security_policy)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : content_security_policy(security_policy) {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CSPInfo::~CSPInfo() {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::string& CSPInfo::GetContentSecurityPolicy(
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Extension* extension) {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CSPInfo* csp_info = static_cast<CSPInfo*>(
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          extension->GetManifestData(keys::kContentSecurityPolicy));
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return csp_info ? csp_info->content_security_policy : base::EmptyString();
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& CSPInfo::GetResourceContentSecurityPolicy(
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const Extension* extension,
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& relative_path) {
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SandboxedPageInfo::IsSandboxedPage(extension, relative_path) ?
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SandboxedPageInfo::GetContentSecurityPolicy(extension) :
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetContentSecurityPolicy(extension);
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CSPHandler::CSPHandler(bool is_platform_app)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : is_platform_app_(is_platform_app) {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CSPHandler::~CSPHandler() {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CSPHandler::Parse(Extension* extension, string16* error) {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string key = Keys()[0];
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!extension->manifest()->HasPath(key)) {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (extension->manifest_version() >= 2) {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // TODO(abarth): Should we continue to let extensions override the
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      //               default Content-Security-Policy?
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string content_security_policy = is_platform_app_ ?
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kDefaultPlatformAppContentSecurityPolicy :
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kDefaultContentSecurityPolicy;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK(ContentSecurityPolicyIsSecure(content_security_policy,
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          extension->GetType()));
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension->SetManifestData(keys::kContentSecurityPolicy,
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 new CSPInfo(content_security_policy));
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string content_security_policy;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!extension->manifest()->GetString(key, &content_security_policy)) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ContentSecurityPolicyIsLegal(content_security_policy)) {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (extension->manifest_version() >= 2 &&
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !ContentSecurityPolicyIsSecure(content_security_policy,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     extension->GetType())) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = ASCIIToUTF16(errors::kInsecureContentSecurityPolicy);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension->SetManifestData(keys::kContentSecurityPolicy,
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             new CSPInfo(content_security_policy));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CSPHandler::AlwaysParseForType(Manifest::Type type) const {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_platform_app_)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return type == Manifest::TYPE_PLATFORM_APP;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return type == Manifest::TYPE_EXTENSION ||
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        type == Manifest::TYPE_LEGACY_PACKAGED_APP;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<std::string> CSPHandler::Keys() const {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& key = is_platform_app_ ?
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      keys::kPlatformAppContentSecurityPolicy : keys::kContentSecurityPolicy;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return SingleKey(key);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
134