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 |