| 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 "base/base64.h" | 5 #include "base/base64.h" |
| 6 #include "base/basictypes.h" | 6 #include "base/basictypes.h" |
| 7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
| 8 #include "base/strings/string_tokenizer.h" | 8 #include "base/strings/string_tokenizer.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "net/http/http_security_headers.h" | 10 #include "net/http/http_security_headers.h" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 if (i > kMaxHSTSAgeSecs) | 41 if (i > kMaxHSTSAgeSecs) |
| 42 i = kMaxHSTSAgeSecs; | 42 i = kMaxHSTSAgeSecs; |
| 43 *result = (uint32)i; | 43 *result = (uint32)i; |
| 44 return true; | 44 return true; |
| 45 } | 45 } |
| 46 | 46 |
| 47 // Returns true iff there is an item in |pins| which is not present in | 47 // Returns true iff there is an item in |pins| which is not present in |
| 48 // |from_cert_chain|. Such an SPKI hash is called a "backup pin". | 48 // |from_cert_chain|. Such an SPKI hash is called a "backup pin". |
| 49 bool IsBackupPinPresent(const HashValueVector& pins, | 49 bool IsBackupPinPresent(const HashValueVector& pins, |
| 50 const HashValueVector& from_cert_chain) { | 50 const HashValueVector& from_cert_chain) { |
| 51 for (HashValueVector::const_iterator i = pins.begin(); i != pins.end(); | 51 for (HashValueVector::const_iterator i = pins.begin(); i != pins.end(); ++i) { |
| 52 ++i) { | 52 HashValueVector::const_iterator j = std::find_if( |
| 53 HashValueVector::const_iterator j = | 53 from_cert_chain.begin(), from_cert_chain.end(), HashValuesEqual(*i)); |
| 54 std::find_if(from_cert_chain.begin(), from_cert_chain.end(), | |
| 55 HashValuesEqual(*i)); | |
| 56 if (j == from_cert_chain.end()) | 54 if (j == from_cert_chain.end()) |
| 57 return true; | 55 return true; |
| 58 } | 56 } |
| 59 | 57 |
| 60 return false; | 58 return false; |
| 61 } | 59 } |
| 62 | 60 |
| 63 // Returns true if the intersection of |a| and |b| is not empty. If either | 61 // Returns true if the intersection of |a| and |b| is not empty. If either |
| 64 // |a| or |b| is empty, returns false. | 62 // |a| or |b| is empty, returns false. |
| 65 bool HashesIntersect(const HashValueVector& a, | 63 bool HashesIntersect(const HashValueVector& a, const HashValueVector& b) { |
| 66 const HashValueVector& b) { | |
| 67 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) { | 64 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) { |
| 68 HashValueVector::const_iterator j = | 65 HashValueVector::const_iterator j = |
| 69 std::find_if(b.begin(), b.end(), HashValuesEqual(*i)); | 66 std::find_if(b.begin(), b.end(), HashValuesEqual(*i)); |
| 70 if (j != b.end()) | 67 if (j != b.end()) |
| 71 return true; | 68 return true; |
| 72 } | 69 } |
| 73 return false; | 70 return false; |
| 74 } | 71 } |
| 75 | 72 |
| 76 // Returns true iff |pins| contains both a live and a backup pin. A live pin | 73 // Returns true iff |pins| contains both a live and a backup pin. A live pin |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 return pair; | 112 return pair; |
| 116 } | 113 } |
| 117 | 114 |
| 118 bool ParseAndAppendPin(const std::string& value, | 115 bool ParseAndAppendPin(const std::string& value, |
| 119 HashValueTag tag, | 116 HashValueTag tag, |
| 120 HashValueVector* hashes) { | 117 HashValueVector* hashes) { |
| 121 std::string unquoted = HttpUtil::Unquote(value); | 118 std::string unquoted = HttpUtil::Unquote(value); |
| 122 std::string decoded; | 119 std::string decoded; |
| 123 | 120 |
| 124 if (unquoted.empty()) | 121 if (unquoted.empty()) |
| 125 return false; | 122 return false; |
| 126 | 123 |
| 127 if (!base::Base64Decode(unquoted, &decoded)) | 124 if (!base::Base64Decode(unquoted, &decoded)) |
| 128 return false; | 125 return false; |
| 129 | 126 |
| 130 HashValue hash(tag); | 127 HashValue hash(tag); |
| 131 if (decoded.size() != hash.size()) | 128 if (decoded.size() != hash.size()) |
| 132 return false; | 129 return false; |
| 133 | 130 |
| 134 memcpy(hash.data(), decoded.data(), hash.size()); | 131 memcpy(hash.data(), decoded.data(), hash.size()); |
| 135 hashes->push_back(hash); | 132 hashes->push_back(hash); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 while (!source.empty()) { | 285 while (!source.empty()) { |
| 289 StringPair semicolon = Split(source, ';'); | 286 StringPair semicolon = Split(source, ';'); |
| 290 semicolon.first = Strip(semicolon.first); | 287 semicolon.first = Strip(semicolon.first); |
| 291 semicolon.second = Strip(semicolon.second); | 288 semicolon.second = Strip(semicolon.second); |
| 292 StringPair equals = Split(semicolon.first, '='); | 289 StringPair equals = Split(semicolon.first, '='); |
| 293 equals.first = Strip(equals.first); | 290 equals.first = Strip(equals.first); |
| 294 equals.second = Strip(equals.second); | 291 equals.second = Strip(equals.second); |
| 295 | 292 |
| 296 if (LowerCaseEqualsASCII(equals.first, "max-age")) { | 293 if (LowerCaseEqualsASCII(equals.first, "max-age")) { |
| 297 if (equals.second.empty() || | 294 if (equals.second.empty() || |
| 298 !MaxAgeToInt(equals.second.begin(), equals.second.end(), | 295 !MaxAgeToInt( |
| 299 &max_age_candidate)) { | 296 equals.second.begin(), equals.second.end(), &max_age_candidate)) { |
| 300 return false; | 297 return false; |
| 301 } | 298 } |
| 302 parsed_max_age = true; | 299 parsed_max_age = true; |
| 303 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha1")) { | 300 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha1")) { |
| 304 if (!ParseAndAppendPin(equals.second, HASH_VALUE_SHA1, &pins)) | 301 if (!ParseAndAppendPin(equals.second, HASH_VALUE_SHA1, &pins)) |
| 305 return false; | 302 return false; |
| 306 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha256")) { | 303 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha256")) { |
| 307 if (!ParseAndAppendPin(equals.second, HASH_VALUE_SHA256, &pins)) | 304 if (!ParseAndAppendPin(equals.second, HASH_VALUE_SHA256, &pins)) |
| 308 return false; | 305 return false; |
| 309 } else if (LowerCaseEqualsASCII(equals.first, "includesubdomains")) { | 306 } else if (LowerCaseEqualsASCII(equals.first, "includesubdomains")) { |
| 310 include_subdomains_candidate = true; | 307 include_subdomains_candidate = true; |
| 311 } else { | 308 } else { |
| 312 // Silently ignore unknown directives for forward compatibility. | 309 // Silently ignore unknown directives for forward compatibility. |
| 313 } | 310 } |
| 314 | 311 |
| 315 source = semicolon.second; | 312 source = semicolon.second; |
| 316 } | 313 } |
| 317 | 314 |
| 318 if (!parsed_max_age) | 315 if (!parsed_max_age) |
| 319 return false; | 316 return false; |
| 320 | 317 |
| 321 if (!IsPinListValid(pins, chain_hashes)) | 318 if (!IsPinListValid(pins, chain_hashes)) |
| 322 return false; | 319 return false; |
| 323 | 320 |
| 324 *max_age = base::TimeDelta::FromSeconds(max_age_candidate); | 321 *max_age = base::TimeDelta::FromSeconds(max_age_candidate); |
| 325 *include_subdomains = include_subdomains_candidate; | 322 *include_subdomains = include_subdomains_candidate; |
| 326 for (HashValueVector::const_iterator i = pins.begin(); | 323 for (HashValueVector::const_iterator i = pins.begin(); i != pins.end(); ++i) { |
| 327 i != pins.end(); ++i) { | |
| 328 bool found = false; | 324 bool found = false; |
| 329 | 325 |
| 330 for (HashValueVector::const_iterator j = hashes->begin(); | 326 for (HashValueVector::const_iterator j = hashes->begin(); |
| 331 j != hashes->end(); ++j) { | 327 j != hashes->end(); |
| 328 ++j) { |
| 332 if (j->Equals(*i)) { | 329 if (j->Equals(*i)) { |
| 333 found = true; | 330 found = true; |
| 334 break; | 331 break; |
| 335 } | 332 } |
| 336 } | 333 } |
| 337 | 334 |
| 338 if (!found) | 335 if (!found) |
| 339 hashes->push_back(*i); | 336 hashes->push_back(*i); |
| 340 } | 337 } |
| 341 | 338 |
| 342 return true; | 339 return true; |
| 343 } | 340 } |
| 344 | 341 |
| 345 } // namespace net | 342 } // namespace net |
| OLD | NEW |