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 "net/base/transport_security_state.h" | 5 #include "net/base/transport_security_state.h" |
6 | 6 |
7 #if defined(USE_OPENSSL) | 7 #if defined(USE_OPENSSL) |
8 #include <openssl/ecdsa.h> | 8 #include <openssl/ecdsa.h> |
9 #include <openssl/ssl.h> | 9 #include <openssl/ssl.h> |
10 #else // !defined(USE_OPENSSL) | 10 #else // !defined(USE_OPENSSL) |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "base/string_number_conversions.h" | 26 #include "base/string_number_conversions.h" |
27 #include "base/string_tokenizer.h" | 27 #include "base/string_tokenizer.h" |
28 #include "base/string_util.h" | 28 #include "base/string_util.h" |
29 #include "base/time.h" | 29 #include "base/time.h" |
30 #include "base/utf_string_conversions.h" | 30 #include "base/utf_string_conversions.h" |
31 #include "base/values.h" | 31 #include "base/values.h" |
32 #include "crypto/sha2.h" | 32 #include "crypto/sha2.h" |
33 #include "googleurl/src/gurl.h" | 33 #include "googleurl/src/gurl.h" |
34 #include "net/base/dns_util.h" | 34 #include "net/base/dns_util.h" |
35 #include "net/base/ssl_info.h" | 35 #include "net/base/ssl_info.h" |
| 36 #include "net/base/x509_cert_types.h" |
36 #include "net/base/x509_certificate.h" | 37 #include "net/base/x509_certificate.h" |
37 #include "net/http/http_util.h" | 38 #include "net/http/http_util.h" |
38 | 39 |
39 #if defined(USE_OPENSSL) | 40 #if defined(USE_OPENSSL) |
40 #include "crypto/openssl_util.h" | 41 #include "crypto/openssl_util.h" |
41 #endif | 42 #endif |
42 | 43 |
43 namespace net { | 44 namespace net { |
44 | 45 |
45 const long int TransportSecurityState::kMaxHSTSAgeSecs = 86400 * 365; // 1 year | 46 const long int TransportSecurityState::kMaxHSTSAgeSecs = 86400 * 365; // 1 year |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 StringPair pair; | 212 StringPair pair; |
212 size_t point = source.find(delimiter); | 213 size_t point = source.find(delimiter); |
213 | 214 |
214 pair.first = source.substr(0, point); | 215 pair.first = source.substr(0, point); |
215 if (std::string::npos != point) | 216 if (std::string::npos != point) |
216 pair.second = source.substr(point + 1); | 217 pair.second = source.substr(point + 1); |
217 | 218 |
218 return pair; | 219 return pair; |
219 } | 220 } |
220 | 221 |
221 // TODO(palmer): Support both sha256 and sha1. This will require additional | |
222 // infrastructure code changes and can come in a later patch. | |
223 // | |
224 // static | 222 // static |
225 bool TransportSecurityState::ParsePin(const std::string& value, | 223 bool TransportSecurityState::ParsePin(const std::string& value, |
226 SHA1Fingerprint* out) { | 224 Fingerprint* out) { |
227 StringPair slash = Split(Strip(value), '/'); | 225 StringPair slash = Split(Strip(value), '/'); |
228 if (slash.first != "sha1") | 226 |
| 227 if (slash.first == "sha1") |
| 228 out->tag = FINGERPRINT_SHA1; |
| 229 else if (slash.first == "sha256") |
| 230 out->tag = FINGERPRINT_SHA256; |
| 231 else |
229 return false; | 232 return false; |
230 | 233 |
231 std::string decoded; | 234 std::string decoded; |
232 if (!base::Base64Decode(slash.second, &decoded) || | 235 if (!base::Base64Decode(slash.second, &decoded) || |
233 decoded.size() != arraysize(out->data)) { | 236 decoded.size() != out->size()) { |
234 return false; | 237 return false; |
235 } | 238 } |
236 | 239 |
237 memcpy(out->data, decoded.data(), arraysize(out->data)); | 240 memcpy(out->data(), decoded.data(), out->size()); |
238 return true; | 241 return true; |
239 } | 242 } |
240 | 243 |
241 static bool ParseAndAppendPin(const std::string& value, | 244 static bool ParseAndAppendPin(const std::string& value, |
242 FingerprintVector* fingerprints) { | 245 FingerprintVector* fingerprints) { |
243 // The base64'd fingerprint MUST be a quoted-string. 20 bytes base64'd is 28 | 246 // The base64'd fingerprint MUST be a quoted-string. 20 bytes base64'd is 28 |
244 // characters; 32 bytes base64'd is 44 characters. TODO(palmer): Support | 247 // characters; 32 bytes base64'd is 44 characters. |
245 // SHA256. | |
246 size_t size = value.size(); | 248 size_t size = value.size(); |
247 if (size != 30 || value[0] != '"' || value[size - 1] != '"') | 249 if (size != 30 || value[0] != '"' || value[size - 1] != '"') |
248 return false; | 250 return false; |
249 | 251 |
250 std::string unquoted = HttpUtil::Unquote(value); | 252 std::string unquoted = HttpUtil::Unquote(value); |
251 std::string decoded; | 253 std::string decoded; |
252 SHA1Fingerprint fp; | 254 Fingerprint fp; |
253 | 255 |
254 if (!base::Base64Decode(unquoted, &decoded) || | 256 // This code has to assume that 32 bytes is SHA-256 and 20 bytes is SHA-1. |
255 decoded.size() != arraysize(fp.data)) { | 257 // Currently, those are the only two possibilities, so the assumption is |
| 258 // valid. |
| 259 if (!base::Base64Decode(unquoted, &decoded)) |
256 return false; | 260 return false; |
257 } | |
258 | 261 |
259 memcpy(fp.data, decoded.data(), arraysize(fp.data)); | 262 if (decoded.size() == 20) |
| 263 fp.tag = FINGERPRINT_SHA1; |
| 264 else if (decoded.size() == 32) |
| 265 fp.tag = FINGERPRINT_SHA256; |
| 266 else |
| 267 return false; |
| 268 |
| 269 memcpy(fp.data(), decoded.data(), fp.size()); |
260 fingerprints->push_back(fp); | 270 fingerprints->push_back(fp); |
261 return true; | 271 return true; |
262 } | 272 } |
263 | 273 |
264 struct FingerprintsEqualPredicate { | 274 struct FingerprintsEqualPredicate { |
265 explicit FingerprintsEqualPredicate(const SHA1Fingerprint& fingerprint) : | 275 explicit FingerprintsEqualPredicate(const Fingerprint& fingerprint) : |
266 fingerprint_(fingerprint) {} | 276 fingerprint_(fingerprint) {} |
267 | 277 |
268 bool operator()(const SHA1Fingerprint& other) const { | 278 bool operator()(const Fingerprint& other) const { |
269 return fingerprint_.Equals(other); | 279 return fingerprint_.Equals(other); |
270 } | 280 } |
271 | 281 |
272 const SHA1Fingerprint& fingerprint_; | 282 const Fingerprint& fingerprint_; |
273 }; | 283 }; |
274 | 284 |
275 // Returns true iff there is an item in |pins| which is not present in | 285 // Returns true iff there is an item in |pins| which is not present in |
276 // |from_cert_chain|. Such an SPKI hash is called a "backup pin". | 286 // |from_cert_chain|. Such an SPKI hash is called a "backup pin". |
277 static bool IsBackupPinPresent(const FingerprintVector& pins, | 287 static bool IsBackupPinPresent(const FingerprintVector& pins, |
278 const FingerprintVector& from_cert_chain) { | 288 const FingerprintVector& from_cert_chain) { |
279 for (FingerprintVector::const_iterator | 289 for (FingerprintVector::const_iterator |
280 i = pins.begin(); i != pins.end(); ++i) { | 290 i = pins.begin(); i != pins.end(); ++i) { |
281 FingerprintVector::const_iterator j = | 291 FingerprintVector::const_iterator j = |
282 std::find_if(from_cert_chain.begin(), from_cert_chain.end(), | 292 std::find_if(from_cert_chain.begin(), from_cert_chain.end(), |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 | 352 |
343 if (LowerCaseEqualsASCII(equals.first, "max-age")) { | 353 if (LowerCaseEqualsASCII(equals.first, "max-age")) { |
344 if (equals.second.empty() || | 354 if (equals.second.empty() || |
345 !MaxAgeToInt(equals.second.begin(), equals.second.end(), | 355 !MaxAgeToInt(equals.second.begin(), equals.second.end(), |
346 &max_age_candidate)) { | 356 &max_age_candidate)) { |
347 return false; | 357 return false; |
348 } | 358 } |
349 if (max_age_candidate > kMaxHSTSAgeSecs) | 359 if (max_age_candidate > kMaxHSTSAgeSecs) |
350 max_age_candidate = kMaxHSTSAgeSecs; | 360 max_age_candidate = kMaxHSTSAgeSecs; |
351 parsed_max_age = true; | 361 parsed_max_age = true; |
352 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha1")) { | 362 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha1") || |
| 363 LowerCaseEqualsASCII(equals.first, "pin-sha256")) { |
353 if (!ParseAndAppendPin(equals.second, &pins)) | 364 if (!ParseAndAppendPin(equals.second, &pins)) |
354 return false; | 365 return false; |
355 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha256")) { | |
356 // TODO(palmer) | |
357 } else { | 366 } else { |
358 // Silently ignore unknown directives for forward compatibility. | 367 // Silently ignore unknown directives for forward compatibility. |
359 } | 368 } |
360 | 369 |
361 source = semicolon.second; | 370 source = semicolon.second; |
362 } | 371 } |
363 | 372 |
364 if (!parsed_max_age || !IsPinListValid(pins, ssl_info)) | 373 if (!parsed_max_age || !IsPinListValid(pins, ssl_info)) |
365 return false; | 374 return false; |
366 | 375 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 upgrade_mode = MODE_FORCE_HTTPS; | 479 upgrade_mode = MODE_FORCE_HTTPS; |
471 return true; | 480 return true; |
472 default: | 481 default: |
473 NOTREACHED(); | 482 NOTREACHED(); |
474 return false; | 483 return false; |
475 } | 484 } |
476 } | 485 } |
477 | 486 |
478 static bool AddHash(const std::string& type_and_base64, | 487 static bool AddHash(const std::string& type_and_base64, |
479 FingerprintVector* out) { | 488 FingerprintVector* out) { |
480 SHA1Fingerprint hash; | 489 Fingerprint hash; |
481 | 490 |
482 if (!TransportSecurityState::ParsePin(type_and_base64, &hash)) | 491 if (!TransportSecurityState::ParsePin(type_and_base64, &hash)) |
483 return false; | 492 return false; |
484 | 493 |
485 out->push_back(hash); | 494 out->push_back(hash); |
486 return true; | 495 return true; |
487 } | 496 } |
488 | 497 |
489 TransportSecurityState::~TransportSecurityState() {} | 498 TransportSecurityState::~TransportSecurityState() {} |
490 | 499 |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 const std::string& hashed_host, const DomainState& state) { | 745 const std::string& hashed_host, const DomainState& state) { |
737 forced_hosts_[hashed_host] = state; | 746 forced_hosts_[hashed_host] = state; |
738 } | 747 } |
739 | 748 |
740 static std::string HashesToBase64String( | 749 static std::string HashesToBase64String( |
741 const FingerprintVector& hashes) { | 750 const FingerprintVector& hashes) { |
742 std::vector<std::string> hashes_strs; | 751 std::vector<std::string> hashes_strs; |
743 for (FingerprintVector::const_iterator | 752 for (FingerprintVector::const_iterator |
744 i = hashes.begin(); i != hashes.end(); i++) { | 753 i = hashes.begin(); i != hashes.end(); i++) { |
745 std::string s; | 754 std::string s; |
746 const std::string hash_str(reinterpret_cast<const char*>(i->data), | 755 const std::string hash_str(reinterpret_cast<const char*>(i->data()), |
747 sizeof(i->data)); | 756 i->size()); |
748 base::Base64Encode(hash_str, &s); | 757 base::Base64Encode(hash_str, &s); |
749 hashes_strs.push_back(s); | 758 hashes_strs.push_back(s); |
750 } | 759 } |
751 | 760 |
752 return JoinString(hashes_strs, ','); | 761 return JoinString(hashes_strs, ','); |
753 } | 762 } |
754 | 763 |
755 TransportSecurityState::DomainState::DomainState() | 764 TransportSecurityState::DomainState::DomainState() |
756 : upgrade_mode(MODE_FORCE_HTTPS), | 765 : upgrade_mode(MODE_FORCE_HTTPS), |
757 created(base::Time::Now()), | 766 created(base::Time::Now()), |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 return true; | 805 return true; |
797 } | 806 } |
798 | 807 |
799 bool TransportSecurityState::DomainState::HasPins() const { | 808 bool TransportSecurityState::DomainState::HasPins() const { |
800 return static_spki_hashes.size() > 0 || | 809 return static_spki_hashes.size() > 0 || |
801 bad_static_spki_hashes.size() > 0 || | 810 bad_static_spki_hashes.size() > 0 || |
802 dynamic_spki_hashes.size() > 0; | 811 dynamic_spki_hashes.size() > 0; |
803 } | 812 } |
804 | 813 |
805 } // namespace | 814 } // namespace |
OLD | NEW |