// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/extensions/csp_validator.h"

#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"

namespace extensions {

namespace csp_validator {

namespace {

const char kDefaultSrc[] = "default-src";
const char kScriptSrc[] = "script-src";
const char kObjectSrc[] = "object-src";

const char kSandboxDirectiveName[] = "sandbox";
const char kAllowSameOriginToken[] = "allow-same-origin";
const char kAllowTopNavigation[] = "allow-top-navigation";
const char kAllowPopups[] = "allow-popups";

struct DirectiveStatus {
  explicit DirectiveStatus(const char* name)
    : directive_name(name)
    , seen_in_policy(false)
    , is_secure(false) {
  }

  const char* directive_name;
  bool seen_in_policy;
  bool is_secure;
};

bool HasOnlySecureTokens(base::StringTokenizer& tokenizer,
                         Manifest::Type type) {
  while (tokenizer.GetNext()) {
    std::string source = tokenizer.token();
    StringToLowerASCII(&source);

    // Don't alow whitelisting of all hosts. This boils down to:
    //   1. Maximum of 2 '*' characters.
    //   2. Each '*' is either followed by a '.' or preceded by a ':'
    int wildcards = 0;
    size_t length = source.length();
    for (size_t i = 0; i < length; ++i) {
      if (source[i] == L'*') {
        wildcards++;
        if (wildcards > 2)
          return false;

        bool isWildcardPort = i > 0 && source[i - 1] == L':';
        bool isWildcardSubdomain = i + 1 < length && source[i + 1] == L'.';
        if (!isWildcardPort && !isWildcardSubdomain)
          return false;
      }
    }

    // We might need to relax this whitelist over time.
    if (source == "'self'" ||
        source == "'none'" ||
        source == "http://127.0.0.1" ||
        LowerCaseEqualsASCII(source, "blob:") ||
        LowerCaseEqualsASCII(source, "filesystem:") ||
        LowerCaseEqualsASCII(source, "http://localhost") ||
        StartsWithASCII(source, "http://127.0.0.1:", false) ||
        StartsWithASCII(source, "http://localhost:", false) ||
        StartsWithASCII(source, "https://", true) ||
        StartsWithASCII(source, "chrome://", true) ||
        StartsWithASCII(source, "chrome-extension://", true) ||
        StartsWithASCII(source, "chrome-extension-resource:", true)) {
      continue;
    }

    // crbug.com/146487
    if (type == Manifest::TYPE_EXTENSION ||
        type == Manifest::TYPE_LEGACY_PACKAGED_APP) {
      if (source == "'unsafe-eval'")
        continue;
    }

    return false;
  }

  return true;  // Empty values default to 'none', which is secure.
}

// Returns true if |directive_name| matches |status.directive_name|.
bool UpdateStatus(const std::string& directive_name,
                  base::StringTokenizer& tokenizer,
                  DirectiveStatus* status,
                  Manifest::Type type) {
  if (status->seen_in_policy)
    return false;
  if (directive_name != status->directive_name)
    return false;
  status->seen_in_policy = true;
  status->is_secure = HasOnlySecureTokens(tokenizer, type);
  return true;
}

}  //  namespace

bool ContentSecurityPolicyIsLegal(const std::string& policy) {
  // We block these characters to prevent HTTP header injection when
  // representing the content security policy as an HTTP header.
  const char kBadChars[] = {',', '\r', '\n', '\0'};

  return policy.find_first_of(kBadChars, 0, arraysize(kBadChars)) ==
      std::string::npos;
}

bool ContentSecurityPolicyIsSecure(const std::string& policy,
                                   Manifest::Type type) {
  // See http://www.w3.org/TR/CSP/#parse-a-csp-policy for parsing algorithm.
  std::vector<std::string> directives;
  base::SplitString(policy, ';', &directives);

  DirectiveStatus default_src_status(kDefaultSrc);
  DirectiveStatus script_src_status(kScriptSrc);
  DirectiveStatus object_src_status(kObjectSrc);

  for (size_t i = 0; i < directives.size(); ++i) {
    std::string& input = directives[i];
    base::StringTokenizer tokenizer(input, " \t\r\n");
    if (!tokenizer.GetNext())
      continue;

    std::string directive_name = tokenizer.token();
    StringToLowerASCII(&directive_name);

    if (UpdateStatus(directive_name, tokenizer, &default_src_status, type))
      continue;
    if (UpdateStatus(directive_name, tokenizer, &script_src_status, type))
      continue;
    if (UpdateStatus(directive_name, tokenizer, &object_src_status, type))
      continue;
  }

  if (script_src_status.seen_in_policy && !script_src_status.is_secure)
    return false;

  if (object_src_status.seen_in_policy && !object_src_status.is_secure)
    return false;

  if (default_src_status.seen_in_policy && !default_src_status.is_secure) {
    return script_src_status.seen_in_policy &&
           object_src_status.seen_in_policy;
  }

  return default_src_status.seen_in_policy ||
      (script_src_status.seen_in_policy && object_src_status.seen_in_policy);
}

bool ContentSecurityPolicyIsSandboxed(
    const std::string& policy, Manifest::Type type) {
  // See http://www.w3.org/TR/CSP/#parse-a-csp-policy for parsing algorithm.
  std::vector<std::string> directives;
  base::SplitString(policy, ';', &directives);

  bool seen_sandbox = false;

  for (size_t i = 0; i < directives.size(); ++i) {
    std::string& input = directives[i];
    base::StringTokenizer tokenizer(input, " \t\r\n");
    if (!tokenizer.GetNext())
      continue;

    std::string directive_name = tokenizer.token();
    StringToLowerASCII(&directive_name);

    if (directive_name != kSandboxDirectiveName)
      continue;

    seen_sandbox = true;

    while (tokenizer.GetNext()) {
      std::string token = tokenizer.token();
      StringToLowerASCII(&token);

      // The same origin token negates the sandboxing.
      if (token == kAllowSameOriginToken)
        return false;

      // Platform apps don't allow navigation.
      if (type == Manifest::TYPE_PLATFORM_APP) {
        if (token == kAllowTopNavigation)
          return false;
      }
    }
  }

  return seen_sandbox;
}

}  // csp_validator

}  // extensions
