| Index: net/http/http_security_headers.cc
|
| diff --git a/net/http/http_security_headers.cc b/net/http/http_security_headers.cc
|
| index 8225385ee8a5772c472ae617822d6143fa246dec..9df02cfb9a5ebbe7f5523fc853b6909438542085 100644
|
| --- a/net/http/http_security_headers.cc
|
| +++ b/net/http/http_security_headers.cc
|
| @@ -365,4 +365,78 @@ bool ParseHPKPReportOnlyHeader(const std::string& value,
|
| include_subdomains, hashes, report_uri);
|
| }
|
|
|
| +// "Expect-CT" ":"
|
| +// "max-age" "=" delta-seconds
|
| +// [ "," "enforce" ]
|
| +// [ "," "report-uri" "=" uri-reference ]
|
| +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;
|
| + // report-uris are always quoted.
|
| + if (!name_value_pairs.value_is_quoted())
|
| + 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
|
|
|