Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Unified Diff: net/http/http_security_headers.cc

Issue 1211363005: Parse HPKP report-uri and persist in TransportSecurityPersister (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: GetNext() fix Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/http/http_security_headers.h ('k') | net/http/http_security_headers_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_security_headers.cc
diff --git a/net/http/http_security_headers.cc b/net/http/http_security_headers.cc
index d95e5878d7c4ce10e2e393d875fb254257d5b6de..ed7ceccbb73080a7e5dfa1627083a728c3a044fe 100644
--- a/net/http/http_security_headers.cc
+++ b/net/http/http_security_headers.cc
@@ -5,10 +5,12 @@
#include "base/base64.h"
#include "base/basictypes.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "net/http/http_security_headers.h"
#include "net/http/http_util.h"
+#include "url/gurl.h"
namespace net {
@@ -23,7 +25,10 @@ static_assert(kMaxHSTSAgeSecs <= kuint32max, "kMaxHSTSAgeSecs too large");
bool MaxAgeToInt(std::string::const_iterator begin,
std::string::const_iterator end,
uint32* result) {
- const std::string s(begin, end);
+ const base::StringPiece s(begin, end);
+ if (s.empty())
+ return false;
+
int64 i = 0;
// Return false on any StringToInt64 parse errors *except* for
@@ -92,42 +97,16 @@ bool IsPinListValid(const HashValueVector& pins,
HashesIntersect(pins, from_cert_chain);
}
-std::string Strip(const std::string& source) {
- if (source.empty())
- return source;
-
- std::string::const_iterator start = source.begin();
- std::string::const_iterator end = source.end();
- HttpUtil::TrimLWS(&start, &end);
- return std::string(start, end);
-}
-
-typedef std::pair<std::string, std::string> StringPair;
-
-StringPair Split(const std::string& source, char delimiter) {
- StringPair pair;
- size_t point = source.find(delimiter);
-
- pair.first = source.substr(0, point);
- if (std::string::npos != point)
- pair.second = source.substr(point + 1);
-
- return pair;
-}
-
-bool ParseAndAppendPin(const std::string& value,
+bool ParseAndAppendPin(std::string::const_iterator begin,
+ std::string::const_iterator end,
HashValueTag tag,
HashValueVector* hashes) {
- // Pins are always quoted.
- if (value.empty() || !HttpUtil::IsQuote(value[0]))
+ const base::StringPiece value(begin, end);
+ if (value.empty())
return false;
- std::string unquoted = HttpUtil::Unquote(value);
- if (unquoted.empty())
- return false;
-
std::string decoded;
- if (!base::Base64Decode(unquoted, &decoded))
+ if (!base::Base64Decode(value, &decoded))
return false;
HashValue hash(tag);
@@ -273,51 +252,83 @@ bool ParseHSTSHeader(const std::string& value,
}
}
-// "Public-Key-Pins" ":"
+// "Public-Key-Pins[-Report-Only]" ":"
// "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) {
+ HashValueVector* hashes,
+ GURL* report_uri) {
bool parsed_max_age = false;
bool include_subdomains_candidate = false;
uint32 max_age_candidate = 0;
+ GURL parsed_report_uri;
HashValueVector pins;
- std::string source = value;
-
- while (!source.empty()) {
- StringPair semicolon = Split(source, ';');
- semicolon.first = Strip(semicolon.first);
- semicolon.second = Strip(semicolon.second);
- StringPair equals = Split(semicolon.first, '=');
- equals.first = Strip(equals.first);
- equals.second = Strip(equals.second);
-
- if (base::LowerCaseEqualsASCII(equals.first, "max-age")) {
- if (equals.second.empty() ||
- !MaxAgeToInt(equals.second.begin(), equals.second.end(),
- &max_age_candidate)) {
+ HttpUtil::NameValuePairsIterator name_value_pairs(
+ value.begin(), value.end(), ';',
+ HttpUtil::NameValuePairsIterator::VALUES_OPTIONAL);
+
+ while (name_value_pairs.GetNext()) {
+ if (base::LowerCaseEqualsASCII(
+ base::StringPiece(name_value_pairs.name_begin(),
+ name_value_pairs.name_end()),
+ "max-age")) {
+ if (!MaxAgeToInt(name_value_pairs.value_begin(),
+ name_value_pairs.value_end(), &max_age_candidate)) {
return false;
}
parsed_max_age = true;
- } else if (base::LowerCaseEqualsASCII(equals.first, "pin-sha1")) {
- if (!ParseAndAppendPin(equals.second, HASH_VALUE_SHA1, &pins))
+ } else if (base::LowerCaseEqualsASCII(
+ base::StringPiece(name_value_pairs.name_begin(),
+ name_value_pairs.name_end()),
+ "pin-sha1")) {
+ // Pins are always quoted.
+ if (!name_value_pairs.value_is_quoted() ||
+ !ParseAndAppendPin(name_value_pairs.value_begin(),
+ name_value_pairs.value_end(), HASH_VALUE_SHA1,
+ &pins)) {
return false;
- } else if (base::LowerCaseEqualsASCII(equals.first, "pin-sha256")) {
- if (!ParseAndAppendPin(equals.second, HASH_VALUE_SHA256, &pins))
+ }
+ } 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(equals.first, "includesubdomains")) {
+ }
+ } 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.
}
-
- source = semicolon.second;
}
+ if (!name_value_pairs.valid())
+ return false;
+
if (!parsed_max_age)
return false;
@@ -327,6 +338,7 @@ bool ParseHPKPHeader(const std::string& value,
*max_age = base::TimeDelta::FromSeconds(max_age_candidate);
*include_subdomains = include_subdomains_candidate;
hashes->swap(pins);
+ *report_uri = parsed_report_uri;
return true;
}
« no previous file with comments | « net/http/http_security_headers.h ('k') | net/http/http_security_headers_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698