| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <limits> |
| 6 |
| 5 #include "base/base64.h" | 7 #include "base/base64.h" |
| 6 #include "base/basictypes.h" | |
| 7 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 8 #include "base/strings/string_piece.h" | 9 #include "base/strings/string_piece.h" |
| 9 #include "base/strings/string_tokenizer.h" | 10 #include "base/strings/string_tokenizer.h" |
| 10 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 11 #include "net/http/http_security_headers.h" | 12 #include "net/http/http_security_headers.h" |
| 12 #include "net/http/http_util.h" | 13 #include "net/http/http_util.h" |
| 13 #include "url/gurl.h" | 14 #include "url/gurl.h" |
| 14 | 15 |
| 15 namespace net { | 16 namespace net { |
| 16 | 17 |
| 17 namespace { | 18 namespace { |
| 18 | 19 |
| 19 enum MaxAgeParsing { REQUIRE_MAX_AGE, DO_NOT_REQUIRE_MAX_AGE }; | 20 enum MaxAgeParsing { REQUIRE_MAX_AGE, DO_NOT_REQUIRE_MAX_AGE }; |
| 20 | 21 |
| 21 static_assert(kMaxHSTSAgeSecs <= kuint32max, "kMaxHSTSAgeSecs too large"); | 22 static_assert(kMaxHSTSAgeSecs <= UINT32_MAX, "kMaxHSTSAgeSecs too large"); |
| 22 | 23 |
| 23 // MaxAgeToInt converts a string representation of a "whole number" of | 24 // MaxAgeToInt converts a string representation of a "whole number" of |
| 24 // seconds into a uint32. The string may contain an arbitrarily large number, | 25 // seconds into a uint32_t. The string may contain an arbitrarily large number, |
| 25 // which will be clipped to kMaxHSTSAgeSecs and which is guaranteed to fit | 26 // which will be clipped to kMaxHSTSAgeSecs and which is guaranteed to fit |
| 26 // within a 32-bit unsigned integer. False is returned on any parse error. | 27 // within a 32-bit unsigned integer. False is returned on any parse error. |
| 27 bool MaxAgeToInt(std::string::const_iterator begin, | 28 bool MaxAgeToInt(std::string::const_iterator begin, |
| 28 std::string::const_iterator end, | 29 std::string::const_iterator end, |
| 29 uint32* result) { | 30 uint32_t* result) { |
| 30 const base::StringPiece s(begin, end); | 31 const base::StringPiece s(begin, end); |
| 31 if (s.empty()) | 32 if (s.empty()) |
| 32 return false; | 33 return false; |
| 33 | 34 |
| 34 int64 i = 0; | 35 int64_t i = 0; |
| 35 | 36 |
| 36 // Return false on any StringToInt64 parse errors *except* for | 37 // Return false on any StringToInt64 parse errors *except* for int64_t |
| 37 // int64 overflow. StringToInt64 is used, rather than StringToUint64, | 38 // overflow. StringToInt64 is used, rather than StringToUint64, in order to |
| 38 // in order to properly handle and reject negative numbers | 39 // properly handle and reject negative numbers (StringToUint64 does not return |
| 39 // (StringToUint64 does not return false on negative numbers). | 40 // false on negative numbers). For values too large to be stored in an |
| 40 // For values too large to be stored in an int64, StringToInt64 will | 41 // int64_t, StringToInt64 will return false with i set to |
| 41 // return false with i set to kint64max, so this case is detected | 42 // std::numeric_limits<int64_t>::max(), so this case is detected by the |
| 42 // by the immediately following if-statement and allowed to fall | 43 // immediately following if-statement and allowed to fall through so that i |
| 43 // through so that i gets clipped to kMaxHSTSAgeSecs. | 44 // gets clipped to kMaxHSTSAgeSecs. |
| 44 if (!base::StringToInt64(s, &i) && i != kint64max) | 45 if (!base::StringToInt64(s, &i) && i != std::numeric_limits<int64_t>::max()) |
| 45 return false; | 46 return false; |
| 46 if (i < 0) | 47 if (i < 0) |
| 47 return false; | 48 return false; |
| 48 if (i > kMaxHSTSAgeSecs) | 49 if (i > kMaxHSTSAgeSecs) |
| 49 i = kMaxHSTSAgeSecs; | 50 i = kMaxHSTSAgeSecs; |
| 50 *result = (uint32)i; | 51 *result = (uint32_t)i; |
| 51 return true; | 52 return true; |
| 52 } | 53 } |
| 53 | 54 |
| 54 // Returns true iff there is an item in |pins| which is not present in | 55 // Returns true iff there is an item in |pins| which is not present in |
| 55 // |from_cert_chain|. Such an SPKI hash is called a "backup pin". | 56 // |from_cert_chain|. Such an SPKI hash is called a "backup pin". |
| 56 bool IsBackupPinPresent(const HashValueVector& pins, | 57 bool IsBackupPinPresent(const HashValueVector& pins, |
| 57 const HashValueVector& from_cert_chain) { | 58 const HashValueVector& from_cert_chain) { |
| 58 for (HashValueVector::const_iterator i = pins.begin(); i != pins.end(); | 59 for (HashValueVector::const_iterator i = pins.begin(); i != pins.end(); |
| 59 ++i) { | 60 ++i) { |
| 60 HashValueVector::const_iterator j = | 61 HashValueVector::const_iterator j = |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 } | 122 } |
| 122 | 123 |
| 123 bool ParseHPKPHeaderImpl(const std::string& value, | 124 bool ParseHPKPHeaderImpl(const std::string& value, |
| 124 MaxAgeParsing max_age_status, | 125 MaxAgeParsing max_age_status, |
| 125 base::TimeDelta* max_age, | 126 base::TimeDelta* max_age, |
| 126 bool* include_subdomains, | 127 bool* include_subdomains, |
| 127 HashValueVector* hashes, | 128 HashValueVector* hashes, |
| 128 GURL* report_uri) { | 129 GURL* report_uri) { |
| 129 bool parsed_max_age = false; | 130 bool parsed_max_age = false; |
| 130 bool include_subdomains_candidate = false; | 131 bool include_subdomains_candidate = false; |
| 131 uint32 max_age_candidate = 0; | 132 uint32_t max_age_candidate = 0; |
| 132 GURL parsed_report_uri; | 133 GURL parsed_report_uri; |
| 133 HashValueVector pins; | 134 HashValueVector pins; |
| 134 bool require_max_age = max_age_status == REQUIRE_MAX_AGE; | 135 bool require_max_age = max_age_status == REQUIRE_MAX_AGE; |
| 135 | 136 |
| 136 HttpUtil::NameValuePairsIterator name_value_pairs( | 137 HttpUtil::NameValuePairsIterator name_value_pairs( |
| 137 value.begin(), value.end(), ';', | 138 value.begin(), value.end(), ';', |
| 138 HttpUtil::NameValuePairsIterator::VALUES_OPTIONAL); | 139 HttpUtil::NameValuePairsIterator::VALUES_OPTIONAL); |
| 139 | 140 |
| 140 while (name_value_pairs.GetNext()) { | 141 while (name_value_pairs.GetNext()) { |
| 141 if (base::LowerCaseEqualsASCII( | 142 if (base::LowerCaseEqualsASCII( |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 // other header field value data, that does not conform to the | 218 // other header field value data, that does not conform to the |
| 218 // syntax defined in this specification. | 219 // syntax defined in this specification. |
| 219 // | 220 // |
| 220 // 5. If an STS header field contains directive(s) not recognized by | 221 // 5. If an STS header field contains directive(s) not recognized by |
| 221 // the UA, the UA MUST ignore the unrecognized directives and if the | 222 // the UA, the UA MUST ignore the unrecognized directives and if the |
| 222 // STS header field otherwise satisfies the above requirements (1 | 223 // STS header field otherwise satisfies the above requirements (1 |
| 223 // through 4), the UA MUST process the recognized directives. | 224 // through 4), the UA MUST process the recognized directives. |
| 224 bool ParseHSTSHeader(const std::string& value, | 225 bool ParseHSTSHeader(const std::string& value, |
| 225 base::TimeDelta* max_age, | 226 base::TimeDelta* max_age, |
| 226 bool* include_subdomains) { | 227 bool* include_subdomains) { |
| 227 uint32 max_age_candidate = 0; | 228 uint32_t max_age_candidate = 0; |
| 228 bool include_subdomains_candidate = false; | 229 bool include_subdomains_candidate = false; |
| 229 | 230 |
| 230 // We must see max-age exactly once. | 231 // We must see max-age exactly once. |
| 231 int max_age_observed = 0; | 232 int max_age_observed = 0; |
| 232 // We must see includeSubdomains exactly 0 or 1 times. | 233 // We must see includeSubdomains exactly 0 or 1 times. |
| 233 int include_subdomains_observed = 0; | 234 int include_subdomains_observed = 0; |
| 234 | 235 |
| 235 enum ParserState { | 236 enum ParserState { |
| 236 START, | 237 START, |
| 237 AFTER_MAX_AGE_LABEL, | 238 AFTER_MAX_AGE_LABEL, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 bool* include_subdomains, | 369 bool* include_subdomains, |
| 369 HashValueVector* hashes, | 370 HashValueVector* hashes, |
| 370 GURL* report_uri) { | 371 GURL* report_uri) { |
| 371 // max-age is irrelevant for Report-Only headers. | 372 // max-age is irrelevant for Report-Only headers. |
| 372 base::TimeDelta unused_max_age; | 373 base::TimeDelta unused_max_age; |
| 373 return ParseHPKPHeaderImpl(value, DO_NOT_REQUIRE_MAX_AGE, &unused_max_age, | 374 return ParseHPKPHeaderImpl(value, DO_NOT_REQUIRE_MAX_AGE, &unused_max_age, |
| 374 include_subdomains, hashes, report_uri); | 375 include_subdomains, hashes, report_uri); |
| 375 } | 376 } |
| 376 | 377 |
| 377 } // namespace net | 378 } // namespace net |
| OLD | NEW |