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

#include "base/base64.h"
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "net/base/parse_number.h"
#include "net/http/http_security_headers.h"
#include "net/http/http_util.h"
#include "starboard/memory.h"
#include "url/gurl.h"

namespace net {

namespace {

enum MaxAgeParsing { REQUIRE_MAX_AGE, DO_NOT_REQUIRE_MAX_AGE };

// MaxAgeToLimitedInt converts a string representation of a "whole number" of
// seconds into a uint32_t. The string may contain an arbitrarily large number,
// which will be clipped to a supplied limit and which is guaranteed to fit
// within a 32-bit unsigned integer. False is returned on any parse error.
bool MaxAgeToLimitedInt(std::string::const_iterator begin,
                        std::string::const_iterator end,
                        uint32_t limit,
                        uint32_t* result) {
  const base::StringPiece s(begin, end);

  ParseIntError error;
  if (!ParseUint32(s, result, &error)) {
    if (error == ParseIntError::FAILED_OVERFLOW) {
      *result = limit;
    } else {
      return false;
    }
  }

  if (*result > limit)
    *result = limit;

  return true;
}

// Returns true iff there is an item in |pins| which is not present in
// |from_cert_chain|. Such an SPKI hash is called a "backup pin".
bool IsBackupPinPresent(const HashValueVector& pins,
                        const HashValueVector& from_cert_chain) {
  for (const auto& pin : pins) {
    if (!base::ContainsValue(from_cert_chain, pin))
      return true;
  }
  return false;
}

// Returns true if the intersection of |a| and |b| is not empty. If either
// |a| or |b| is empty, returns false.
bool HashesIntersect(const HashValueVector& a,
                     const HashValueVector& b) {
  for (const auto& pin : a) {
    if (base::ContainsValue(b, pin))
      return true;
  }
  return false;
}

// Returns true iff |pins| contains both a live and a backup pin. A live pin
// is a pin whose SPKI is present in the certificate chain in |ssl_info|. A
// backup pin is a pin intended for disaster recovery, not day-to-day use, and
// thus must be absent from the certificate chain. The Public-Key-Pins header
// specification requires both.
bool IsPinListValid(const HashValueVector& pins,
                    const HashValueVector& from_cert_chain) {
  // Fast fail: 1 live + 1 backup = at least 2 pins. (Check for actual
  // liveness and backupness below.)
  if (pins.size() < 2)
    return false;

  if (from_cert_chain.empty())
    return false;

  return IsBackupPinPresent(pins, from_cert_chain) &&
         HashesIntersect(pins, from_cert_chain);
}

bool ParseAndAppendPin(std::string::const_iterator begin,
                       std::string::const_iterator end,
                       HashValueTag tag,
                       HashValueVector* hashes) {
  const base::StringPiece value(begin, end);
  if (value.empty())
    return false;

  std::string decoded;
  if (!base::Base64Decode(value, &decoded))
    return false;

  HashValue hash(tag);
  if (decoded.size() != hash.size())
    return false;

  memcpy(hash.data(), decoded.data(), hash.size());
  hashes->push_back(hash);
  return true;
}

bool ParseHPKPHeaderImpl(const std::string& value,
                         MaxAgeParsing max_age_status,
                         base::TimeDelta* max_age,
                         bool* include_subdomains,
                         HashValueVector* hashes,
                         GURL* report_uri) {
  bool parsed_max_age = false;
  bool include_subdomains_candidate = false;
  uint32_t max_age_candidate = 0;
  GURL parsed_report_uri;
  HashValueVector pins;
  bool require_max_age = max_age_status == REQUIRE_MAX_AGE;

  HttpUtil::NameValuePairsIterator name_value_pairs(
      value.begin(), value.end(), ';',
      HttpUtil::NameValuePairsIterator::Values::NOT_REQUIRED,
      HttpUtil::NameValuePairsIterator::Quotes::NOT_STRICT);

  while (name_value_pairs.GetNext()) {
    if (base::LowerCaseEqualsASCII(
            base::StringPiece(name_value_pairs.name_begin(),
                              name_value_pairs.name_end()),
            "max-age")) {
      if (!MaxAgeToLimitedInt(name_value_pairs.value_begin(),
                              name_value_pairs.value_end(), kMaxHPKPAgeSecs,
                              &max_age_candidate)) {
        return false;
      }
      parsed_max_age = true;
    } else if (base::LowerCaseEqualsASCII(
                   base::StringPiece(name_value_pairs.name_begin(),
                                     name_value_pairs.name_end()),
                   "pin-sha256")) {
      // Pins are always quoted.
      if (!name_value_pairs.value_is_quoted() ||
          !ParseAndAppendPin(name_value_pairs.value_begin(),
                             name_value_pairs.value_end(), HASH_VALUE_SHA256,
                             &pins)) {
        return false;
      }
    } else if (base::LowerCaseEqualsASCII(
                   base::StringPiece(name_value_pairs.name_begin(),
                                     name_value_pairs.name_end()),
                   "includesubdomains")) {
      include_subdomains_candidate = true;
    } else if (base::LowerCaseEqualsASCII(
                   base::StringPiece(name_value_pairs.name_begin(),
                                     name_value_pairs.name_end()),
                   "report-uri")) {
      // report-uris are always quoted.
      if (!name_value_pairs.value_is_quoted())
        return false;

      parsed_report_uri = GURL(name_value_pairs.value());
      if (parsed_report_uri.is_empty() || !parsed_report_uri.is_valid())
        return false;
    } else {
      // Silently ignore unknown directives for forward compatibility.
    }
  }

  if (!name_value_pairs.valid())
    return false;

  if (!parsed_max_age && require_max_age)
    return false;

  *max_age = base::TimeDelta::FromSeconds(max_age_candidate);
  *include_subdomains = include_subdomains_candidate;
  hashes->swap(pins);
  *report_uri = parsed_report_uri;

  return true;
}

}  // namespace

// Parse the Strict-Transport-Security header, as currently defined in
// http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec-14:
//
// Strict-Transport-Security = "Strict-Transport-Security" ":"
//                             [ directive ]  *( ";" [ directive ] )
//
// directive                 = directive-name [ "=" directive-value ]
// directive-name            = token
// directive-value           = token | quoted-string
//
// 1.  The order of appearance of directives is not significant.
//
// 2.  All directives MUST appear only once in an STS header field.
//     Directives are either optional or required, as stipulated in
//     their definitions.
//
// 3.  Directive names are case-insensitive.
//
// 4.  UAs MUST ignore any STS header fields containing directives, or
//     other header field value data, that does not conform to the
//     syntax defined in this specification.
//
// 5.  If an STS header field contains directive(s) not recognized by
//     the UA, the UA MUST ignore the unrecognized directives and if the
//     STS header field otherwise satisfies the above requirements (1
//     through 4), the UA MUST process the recognized directives.
bool ParseHSTSHeader(const std::string& value,
                     base::TimeDelta* max_age,
                     bool* include_subdomains) {
  uint32_t max_age_candidate = 0;
  bool include_subdomains_candidate = false;

  // We must see max-age exactly once.
  int max_age_observed = 0;
  // We must see includeSubdomains exactly 0 or 1 times.
  int include_subdomains_observed = 0;

  enum ParserState {
    START,
    AFTER_MAX_AGE_LABEL,
    AFTER_MAX_AGE_EQUALS,
    AFTER_MAX_AGE,
    AFTER_INCLUDE_SUBDOMAINS,
    AFTER_UNKNOWN_LABEL,
    DIRECTIVE_END
  } state = START;

  base::StringTokenizer tokenizer(value, " \t=;");
  tokenizer.set_options(base::StringTokenizer::RETURN_DELIMS);
  tokenizer.set_quote_chars("\"");
  std::string unquoted;
  while (tokenizer.GetNext()) {
    DCHECK(!tokenizer.token_is_delim() || tokenizer.token().length() == 1);
    switch (state) {
      case START:
      case DIRECTIVE_END:
        if (base::IsAsciiWhitespace(*tokenizer.token_begin()))
          continue;
        if (base::LowerCaseEqualsASCII(tokenizer.token(), "max-age")) {
          state = AFTER_MAX_AGE_LABEL;
          max_age_observed++;
        } else if (base::LowerCaseEqualsASCII(tokenizer.token(),
                                              "includesubdomains")) {
          state = AFTER_INCLUDE_SUBDOMAINS;
          include_subdomains_observed++;
          include_subdomains_candidate = true;
        } else {
          state = AFTER_UNKNOWN_LABEL;
        }
        break;

      case AFTER_MAX_AGE_LABEL:
        if (base::IsAsciiWhitespace(*tokenizer.token_begin()))
          continue;
        if (*tokenizer.token_begin() != '=')
          return false;
        DCHECK_EQ(tokenizer.token().length(), 1U);
        state = AFTER_MAX_AGE_EQUALS;
        break;

      case AFTER_MAX_AGE_EQUALS:
        if (base::IsAsciiWhitespace(*tokenizer.token_begin()))
          continue;
        unquoted = HttpUtil::Unquote(tokenizer.token());
        if (!MaxAgeToLimitedInt(unquoted.begin(), unquoted.end(),
                                kMaxHSTSAgeSecs, &max_age_candidate))
          return false;
        state = AFTER_MAX_AGE;
        break;

      case AFTER_MAX_AGE:
      case AFTER_INCLUDE_SUBDOMAINS:
        if (base::IsAsciiWhitespace(*tokenizer.token_begin()))
          continue;
        else if (*tokenizer.token_begin() == ';')
          state = DIRECTIVE_END;
        else
          return false;
        break;

      case AFTER_UNKNOWN_LABEL:
        // Consume and ignore the post-label contents (if any).
        if (*tokenizer.token_begin() != ';')
          continue;
        state = DIRECTIVE_END;
        break;
    }
  }

  // We've consumed all the input. Let's see what state we ended up in.
  if (max_age_observed != 1 ||
      (include_subdomains_observed != 0 && include_subdomains_observed != 1)) {
    return false;
  }

  switch (state) {
    case DIRECTIVE_END:
    case AFTER_MAX_AGE:
    case AFTER_INCLUDE_SUBDOMAINS:
    case AFTER_UNKNOWN_LABEL:
      *max_age = base::TimeDelta::FromSeconds(max_age_candidate);
      *include_subdomains = include_subdomains_candidate;
      return true;
    case START:
    case AFTER_MAX_AGE_LABEL:
    case AFTER_MAX_AGE_EQUALS:
      return false;
    default:
      NOTREACHED();
      return false;
  }
}

// "Public-Key-Pins" ":"
//     "max-age" "=" delta-seconds ";"
//     "pin-" algo "=" base64 [ ";" ... ]
//     [ ";" "includeSubdomains" ]
//     [ ";" "report-uri" "=" uri-reference ]
bool ParseHPKPHeader(const std::string& value,
                     const HashValueVector& chain_hashes,
                     base::TimeDelta* max_age,
                     bool* include_subdomains,
                     HashValueVector* hashes,
                     GURL* report_uri) {
  base::TimeDelta candidate_max_age;
  bool candidate_include_subdomains;
  HashValueVector candidate_hashes;
  GURL candidate_report_uri;

  if (!ParseHPKPHeaderImpl(value, REQUIRE_MAX_AGE, &candidate_max_age,
                           &candidate_include_subdomains, &candidate_hashes,
                           &candidate_report_uri)) {
    return false;
  }

  if (!IsPinListValid(candidate_hashes, chain_hashes))
    return false;

  *max_age = candidate_max_age;
  *include_subdomains = candidate_include_subdomains;
  hashes->swap(candidate_hashes);
  *report_uri = candidate_report_uri;
  return true;
}

// "Public-Key-Pins-Report-Only" ":"
//     [ "max-age" "=" delta-seconds ";" ]
//     "pin-" algo "=" base64 [ ";" ... ]
//     [ ";" "includeSubdomains" ]
//     [ ";" "report-uri" "=" uri-reference ]
bool ParseHPKPReportOnlyHeader(const std::string& value,
                               bool* include_subdomains,
                               HashValueVector* hashes,
                               GURL* report_uri) {
  // max-age is irrelevant for Report-Only headers.
  base::TimeDelta unused_max_age;
  return ParseHPKPHeaderImpl(value, DO_NOT_REQUIRE_MAX_AGE, &unused_max_age,
                             include_subdomains, hashes, report_uri);
}

// "Expect-CT" ":"
//     "max-age" "=" delta-seconds
//     [ "," "enforce" ]
//     [ "," "report-uri" "=" absolute-URI ]
bool ParseExpectCTHeader(const std::string& value,
                         base::TimeDelta* max_age,
                         bool* enforce,
                         GURL* report_uri) {
  bool parsed_max_age = false;
  bool enforce_candidate = false;
  bool has_report_uri = false;
  uint32_t max_age_candidate = 0;
  GURL parsed_report_uri;

  HttpUtil::NameValuePairsIterator name_value_pairs(
      value.begin(), value.end(), ',',
      HttpUtil::NameValuePairsIterator::Values::NOT_REQUIRED,
      // Use STRICT_QUOTES because "UAs must not attempt to fix malformed header
      // fields."
      HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);

  while (name_value_pairs.GetNext()) {
    base::StringPiece name(name_value_pairs.name_begin(),
                           name_value_pairs.name_end());
    if (base::LowerCaseEqualsASCII(name, "max-age")) {
      // "A given directive MUST NOT appear more than once in a given header
      // field."
      if (parsed_max_age)
        return false;
      if (!MaxAgeToLimitedInt(name_value_pairs.value_begin(),
                              name_value_pairs.value_end(), kMaxExpectCTAgeSecs,
                              &max_age_candidate)) {
        return false;
      }
      parsed_max_age = true;
    } else if (base::LowerCaseEqualsASCII(name, "enforce")) {
      // "A given directive MUST NOT appear more than once in a given header
      // field."
      if (enforce_candidate)
        return false;
      if (!name_value_pairs.value().empty())
        return false;
      enforce_candidate = true;
    } else if (base::LowerCaseEqualsASCII(name, "report-uri")) {
      // "A given directive MUST NOT appear more than once in a given header
      // field."
      if (has_report_uri)
        return false;

      has_report_uri = true;
      parsed_report_uri = GURL(base::StringPiece(name_value_pairs.value_begin(),
                                                 name_value_pairs.value_end()));
      if (parsed_report_uri.is_empty() || !parsed_report_uri.is_valid())
        return false;
    } else {
      // Silently ignore unknown directives for forward compatibility.
    }
  }

  if (!name_value_pairs.valid())
    return false;

  if (!parsed_max_age)
    return false;

  *max_age = base::TimeDelta::FromSeconds(max_age_candidate);
  *enforce = enforce_candidate;
  *report_uri = parsed_report_uri;
  return true;
}

}  // namespace net
