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

Side by Side Diff: net/base/transport_security_state.cc

Issue 11274032: Separate http_security_headers from transport_security_state (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years 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 unified diff | Download patch
OLDNEW
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)
11 #include <cryptohi.h> 11 #include <cryptohi.h>
12 #include <hasht.h> 12 #include <hasht.h>
13 #include <keyhi.h> 13 #include <keyhi.h>
14 #include <pk11pub.h> 14 #include <pk11pub.h>
15 #include <nspr.h> 15 #include <nspr.h>
16 #endif 16 #endif
17 17
18 #include <algorithm> 18 #include <algorithm>
19 19
20 #include "base/base64.h" 20 #include "base/base64.h"
21 #include "base/logging.h" 21 #include "base/logging.h"
22 #include "base/memory/scoped_ptr.h" 22 #include "base/memory/scoped_ptr.h"
23 #include "base/metrics/histogram.h" 23 #include "base/metrics/histogram.h"
24 #include "base/sha1.h" 24 #include "base/sha1.h"
25 #include "base/string_number_conversions.h" 25 #include "base/string_number_conversions.h"
26 #include "base/string_tokenizer.h"
27 #include "base/string_util.h" 26 #include "base/string_util.h"
28 #include "base/time.h" 27 #include "base/time.h"
29 #include "base/utf_string_conversions.h" 28 #include "base/utf_string_conversions.h"
30 #include "base/values.h" 29 #include "base/values.h"
31 #include "crypto/sha2.h" 30 #include "crypto/sha2.h"
32 #include "googleurl/src/gurl.h" 31 #include "googleurl/src/gurl.h"
33 #include "net/base/dns_util.h" 32 #include "net/base/dns_util.h"
34 #include "net/base/ssl_info.h" 33 #include "net/base/ssl_info.h"
35 #include "net/base/x509_cert_types.h" 34 #include "net/base/x509_cert_types.h"
36 #include "net/base/x509_certificate.h" 35 #include "net/base/x509_certificate.h"
37 #include "net/http/http_util.h" 36 #include "net/http/http_security_headers.h"
38 37
39 #if defined(USE_OPENSSL) 38 #if defined(USE_OPENSSL)
40 #include "crypto/openssl_util.h" 39 #include "crypto/openssl_util.h"
41 #endif 40 #endif
42 41
43 namespace net { 42 namespace net {
44 43
45 const long int TransportSecurityState::kMaxHSTSAgeSecs = 86400 * 365; // 1 year 44 namespace {
46 45
47 static std::string HashHost(const std::string& canonicalized_host) { 46 std::string HashesToBase64String(const HashValueVector& hashes) {
47 std::string str;
48 for (size_t i = 0; i != hashes.size(); ++i) {
49 if (i != 0)
50 str += ",";
51 str += hashes[i].ToString();
52 }
53 return str;
54 }
55
56 std::string HashHost(const std::string& canonicalized_host) {
48 char hashed[crypto::kSHA256Length]; 57 char hashed[crypto::kSHA256Length];
49 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed)); 58 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
50 return std::string(hashed, sizeof(hashed)); 59 return std::string(hashed, sizeof(hashed));
51 } 60 }
52 61
62 // Returns true if the intersection of |a| and |b| is not empty. If either
63 // |a| or |b| is empty, returns false.
64 bool HashesIntersect(const HashValueVector& a,
65 const HashValueVector& b) {
66 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
67 HashValueVector::const_iterator j =
68 std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
69 if (j != b.end())
70 return true;
71 }
72 return false;
73 }
74
75 bool AddHash(const char* sha1_hash,
76 HashValueVector* out) {
77 HashValue hash(HASH_VALUE_SHA1);
78 memcpy(hash.data(), sha1_hash, 20);
Ryan Sleevi 2012/12/07 23:37:21 nit: 20 -> hash.size()?
unsafe 2012/12/08 09:22:42 Done.
79 out->push_back(hash);
80 return true;
81 }
82
83 } // namespace
84
53 TransportSecurityState::TransportSecurityState() 85 TransportSecurityState::TransportSecurityState()
54 : delegate_(NULL) { 86 : delegate_(NULL) {
55 } 87 }
56 88
57 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) 89 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state)
58 : iterator_(state.enabled_hosts_.begin()), 90 : iterator_(state.enabled_hosts_.begin()),
59 end_(state.enabled_hosts_.end()) { 91 end_(state.enabled_hosts_.end()) {
60 } 92 }
61 93
62 TransportSecurityState::Iterator::~Iterator() {} 94 TransportSecurityState::Iterator::~Iterator() {}
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 enabled_hosts_.erase(i++); 207 enabled_hosts_.erase(i++);
176 } else { 208 } else {
177 i++; 209 i++;
178 } 210 }
179 } 211 }
180 212
181 if (dirtied) 213 if (dirtied)
182 DirtyNotify(); 214 DirtyNotify();
183 } 215 }
184 216
185 // MaxAgeToInt converts a string representation of a number of seconds into a
186 // int. We use strtol in order to handle overflow correctly. The string may
187 // contain an arbitary number which we should truncate correctly rather than
188 // throwing a parse failure.
189 static bool MaxAgeToInt(std::string::const_iterator begin,
190 std::string::const_iterator end,
191 int* result) {
192 const std::string s(begin, end);
193 char* endptr;
194 long int i = strtol(s.data(), &endptr, 10 /* base */);
195 if (*endptr || i < 0)
196 return false;
197 if (i > TransportSecurityState::kMaxHSTSAgeSecs)
198 i = TransportSecurityState::kMaxHSTSAgeSecs;
199 *result = i;
200 return true;
201 }
202
203 // Strip, Split, StringPair, and ParsePins are private implementation details
204 // of ParsePinsHeader(std::string&, DomainState&).
205 static std::string Strip(const std::string& source) {
206 if (source.empty())
207 return source;
208
209 std::string::const_iterator start = source.begin();
210 std::string::const_iterator end = source.end();
211 HttpUtil::TrimLWS(&start, &end);
212 return std::string(start, end);
213 }
214
215 typedef std::pair<std::string, std::string> StringPair;
216
217 static StringPair Split(const std::string& source, char delimiter) {
218 StringPair pair;
219 size_t point = source.find(delimiter);
220
221 pair.first = source.substr(0, point);
222 if (std::string::npos != point)
223 pair.second = source.substr(point + 1);
224
225 return pair;
226 }
227
228 // static
229 bool TransportSecurityState::ParsePin(const std::string& value,
230 HashValue* out) {
231 StringPair slash = Split(Strip(value), '/');
232
233 if (slash.first == "sha1")
234 out->tag = HASH_VALUE_SHA1;
235 else if (slash.first == "sha256")
236 out->tag = HASH_VALUE_SHA256;
237 else
238 return false;
239
240 std::string decoded;
241 if (!base::Base64Decode(slash.second, &decoded) ||
242 decoded.size() != out->size()) {
243 return false;
244 }
245
246 memcpy(out->data(), decoded.data(), out->size());
247 return true;
248 }
249
250 static bool ParseAndAppendPin(const std::string& value,
251 HashValueTag tag,
252 HashValueVector* hashes) {
253 std::string unquoted = HttpUtil::Unquote(value);
254 std::string decoded;
255
256 // This code has to assume that 32 bytes is SHA-256 and 20 bytes is SHA-1.
257 // Currently, those are the only two possibilities, so the assumption is
258 // valid.
259 if (!base::Base64Decode(unquoted, &decoded))
260 return false;
261
262 HashValue hash(tag);
263 if (decoded.size() != hash.size())
264 return false;
265
266 memcpy(hash.data(), decoded.data(), hash.size());
267 hashes->push_back(hash);
268 return true;
269 }
270
271 struct HashValuesEqualPredicate {
272 explicit HashValuesEqualPredicate(const HashValue& fingerprint) :
273 fingerprint_(fingerprint) {}
274
275 bool operator()(const HashValue& other) const {
276 return fingerprint_.Equals(other);
277 }
278
279 const HashValue& fingerprint_;
280 };
281
282 // Returns true iff there is an item in |pins| which is not present in
283 // |from_cert_chain|. Such an SPKI hash is called a "backup pin".
284 static bool IsBackupPinPresent(const HashValueVector& pins,
285 const HashValueVector& from_cert_chain) {
286 for (HashValueVector::const_iterator
287 i = pins.begin(); i != pins.end(); ++i) {
288 HashValueVector::const_iterator j =
289 std::find_if(from_cert_chain.begin(), from_cert_chain.end(),
290 HashValuesEqualPredicate(*i));
291 if (j == from_cert_chain.end())
292 return true;
293 }
294
295 return false;
296 }
297
298 // Returns true if the intersection of |a| and |b| is not empty. If either
299 // |a| or |b| is empty, returns false.
300 static bool HashesIntersect(const HashValueVector& a,
301 const HashValueVector& b) {
302 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
303 HashValueVector::const_iterator j =
304 std::find_if(b.begin(), b.end(), HashValuesEqualPredicate(*i));
305 if (j != b.end())
306 return true;
307 }
308
309 return false;
310 }
311
312 // Returns true iff |pins| contains both a live and a backup pin. A live pin
313 // is a pin whose SPKI is present in the certificate chain in |ssl_info|. A
314 // backup pin is a pin intended for disaster recovery, not day-to-day use, and
315 // thus must be absent from the certificate chain. The Public-Key-Pins header
316 // specification requires both.
317 static bool IsPinListValid(const HashValueVector& pins,
318 const SSLInfo& ssl_info) {
319 // Fast fail: 1 live + 1 backup = at least 2 pins. (Check for actual
320 // liveness and backupness below.)
321 if (pins.size() < 2)
322 return false;
323
324 const HashValueVector& from_cert_chain = ssl_info.public_key_hashes;
325 if (from_cert_chain.empty())
326 return false;
327
328 return IsBackupPinPresent(pins, from_cert_chain) &&
329 HashesIntersect(pins, from_cert_chain);
330 }
331
332 // "Public-Key-Pins" ":"
333 // "max-age" "=" delta-seconds ";"
334 // "pin-" algo "=" base64 [ ";" ... ]
335 bool TransportSecurityState::DomainState::ParsePinsHeader(
336 const base::Time& now,
337 const std::string& value,
338 const SSLInfo& ssl_info) {
339 bool parsed_max_age = false;
340 int max_age_candidate = 0;
341 HashValueVector pins;
342
343 std::string source = value;
344
345 while (!source.empty()) {
346 StringPair semicolon = Split(source, ';');
347 semicolon.first = Strip(semicolon.first);
348 semicolon.second = Strip(semicolon.second);
349 StringPair equals = Split(semicolon.first, '=');
350 equals.first = Strip(equals.first);
351 equals.second = Strip(equals.second);
352
353 if (LowerCaseEqualsASCII(equals.first, "max-age")) {
354 if (equals.second.empty() ||
355 !MaxAgeToInt(equals.second.begin(), equals.second.end(),
356 &max_age_candidate)) {
357 return false;
358 }
359 if (max_age_candidate > kMaxHSTSAgeSecs)
360 max_age_candidate = kMaxHSTSAgeSecs;
361 parsed_max_age = true;
362 } else if (StartsWithASCII(equals.first, "pin-", false)) {
363 HashValueTag tag;
364 if (LowerCaseEqualsASCII(equals.first, "pin-sha1")) {
365 tag = HASH_VALUE_SHA1;
366 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha256")) {
367 tag = HASH_VALUE_SHA256;
368 } else {
369 LOG(WARNING) << "Ignoring pin of unknown type: " << equals.first;
370 return false;
371 }
372 if (!ParseAndAppendPin(equals.second, tag, &pins))
373 return false;
374 } else {
375 // Silently ignore unknown directives for forward compatibility.
376 }
377
378 source = semicolon.second;
379 }
380
381 if (!parsed_max_age || !IsPinListValid(pins, ssl_info))
382 return false;
383
384 dynamic_spki_hashes_expiry =
385 now + base::TimeDelta::FromSeconds(max_age_candidate);
386
387 dynamic_spki_hashes.clear();
388 if (max_age_candidate > 0) {
389 for (HashValueVector::const_iterator i = pins.begin();
390 i != pins.end(); ++i) {
391 dynamic_spki_hashes.push_back(*i);
392 }
393 }
394
395 return true;
396 }
397
398 // Parse the Strict-Transport-Security header, as currently defined in
399 // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec-14:
400 //
401 // Strict-Transport-Security = "Strict-Transport-Security" ":"
402 // [ directive ] *( ";" [ directive ] )
403 //
404 // directive = directive-name [ "=" directive-value ]
405 // directive-name = token
406 // directive-value = token | quoted-string
407 //
408 // 1. The order of appearance of directives is not significant.
409 //
410 // 2. All directives MUST appear only once in an STS header field.
411 // Directives are either optional or required, as stipulated in
412 // their definitions.
413 //
414 // 3. Directive names are case-insensitive.
415 //
416 // 4. UAs MUST ignore any STS header fields containing directives, or
417 // other header field value data, that does not conform to the
418 // syntax defined in this specification.
419 //
420 // 5. If an STS header field contains directive(s) not recognized by
421 // the UA, the UA MUST ignore the unrecognized directives and if the
422 // STS header field otherwise satisfies the above requirements (1
423 // through 4), the UA MUST process the recognized directives.
424 bool TransportSecurityState::DomainState::ParseSTSHeader(
425 const base::Time& now,
426 const std::string& value) {
427 int max_age_candidate = 0;
428 bool include_subdomains_candidate = false;
429
430 // We must see max-age exactly once.
431 int max_age_observed = 0;
432 // We must see includeSubdomains exactly 0 or 1 times.
433 int include_subdomains_observed = 0;
434
435 enum ParserState {
436 START,
437 AFTER_MAX_AGE_LABEL,
438 AFTER_MAX_AGE_EQUALS,
439 AFTER_MAX_AGE,
440 AFTER_INCLUDE_SUBDOMAINS,
441 AFTER_UNKNOWN_LABEL,
442 DIRECTIVE_END
443 } state = START;
444
445 StringTokenizer tokenizer(value, " \t=;");
446 tokenizer.set_options(StringTokenizer::RETURN_DELIMS);
447 tokenizer.set_quote_chars("\"");
448 std::string unquoted;
449 while (tokenizer.GetNext()) {
450 DCHECK(!tokenizer.token_is_delim() || tokenizer.token().length() == 1);
451 switch (state) {
452 case START:
453 case DIRECTIVE_END:
454 if (IsAsciiWhitespace(*tokenizer.token_begin()))
455 continue;
456 if (LowerCaseEqualsASCII(tokenizer.token(), "max-age")) {
457 state = AFTER_MAX_AGE_LABEL;
458 max_age_observed++;
459 } else if (LowerCaseEqualsASCII(tokenizer.token(),
460 "includesubdomains")) {
461 state = AFTER_INCLUDE_SUBDOMAINS;
462 include_subdomains_observed++;
463 include_subdomains_candidate = true;
464 } else {
465 state = AFTER_UNKNOWN_LABEL;
466 }
467 break;
468
469 case AFTER_MAX_AGE_LABEL:
470 if (IsAsciiWhitespace(*tokenizer.token_begin()))
471 continue;
472 if (*tokenizer.token_begin() != '=')
473 return false;
474 DCHECK_EQ(tokenizer.token().length(), 1U);
475 state = AFTER_MAX_AGE_EQUALS;
476 break;
477
478 case AFTER_MAX_AGE_EQUALS:
479 if (IsAsciiWhitespace(*tokenizer.token_begin()))
480 continue;
481 unquoted = HttpUtil::Unquote(tokenizer.token());
482 if (!MaxAgeToInt(unquoted.begin(),
483 unquoted.end(),
484 &max_age_candidate))
485 return false;
486 state = AFTER_MAX_AGE;
487 break;
488
489 case AFTER_MAX_AGE:
490 case AFTER_INCLUDE_SUBDOMAINS:
491 if (IsAsciiWhitespace(*tokenizer.token_begin()))
492 continue;
493 else if (*tokenizer.token_begin() == ';')
494 state = DIRECTIVE_END;
495 else
496 return false;
497 break;
498
499 case AFTER_UNKNOWN_LABEL:
500 // Consume and ignore the post-label contents (if any).
501 if (*tokenizer.token_begin() != ';')
502 continue;
503 state = DIRECTIVE_END;
504 break;
505 }
506 }
507
508 // We've consumed all the input. Let's see what state we ended up in.
509 if (max_age_observed != 1 ||
510 (include_subdomains_observed != 0 && include_subdomains_observed != 1)) {
511 return false;
512 }
513
514 switch (state) {
515 case AFTER_MAX_AGE:
516 case AFTER_INCLUDE_SUBDOMAINS:
517 case AFTER_UNKNOWN_LABEL:
518 if (max_age_candidate > 0) {
519 upgrade_expiry = now + base::TimeDelta::FromSeconds(max_age_candidate);
520 upgrade_mode = MODE_FORCE_HTTPS;
521 } else {
522 upgrade_expiry = now;
523 upgrade_mode = MODE_DEFAULT;
524 }
525 include_subdomains = include_subdomains_candidate;
526 return true;
527 case START:
528 case DIRECTIVE_END:
529 case AFTER_MAX_AGE_LABEL:
530 case AFTER_MAX_AGE_EQUALS:
531 return false;
532 default:
533 NOTREACHED();
534 return false;
535 }
536 }
537
538 static bool AddHash(const std::string& type_and_base64,
539 HashValueVector* out) {
540 HashValue hash;
541
542 if (!TransportSecurityState::ParsePin(type_and_base64, &hash))
543 return false;
544
545 out->push_back(hash);
546 return true;
547 }
548
549 TransportSecurityState::~TransportSecurityState() {} 217 TransportSecurityState::~TransportSecurityState() {}
550 218
551 void TransportSecurityState::DirtyNotify() { 219 void TransportSecurityState::DirtyNotify() {
552 DCHECK(CalledOnValidThread()); 220 DCHECK(CalledOnValidThread());
553 221
554 if (delegate_) 222 if (delegate_)
555 delegate_->StateIsDirty(this); 223 delegate_->StateIsDirty(this);
556 } 224 }
557 225
558 // static 226 // static
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 memcmp(entries[j].dns_name, &canonicalized_host[i], 546 memcmp(entries[j].dns_name, &canonicalized_host[i],
879 entries[j].length) == 0) { 547 entries[j].length) == 0) {
880 if (!entries[j].include_subdomains && i != 0) { 548 if (!entries[j].include_subdomains && i != 0) {
881 *ret = false; 549 *ret = false;
882 } else { 550 } else {
883 out->include_subdomains = entries[j].include_subdomains; 551 out->include_subdomains = entries[j].include_subdomains;
884 *ret = true; 552 *ret = true;
885 if (!entries[j].https_required) 553 if (!entries[j].https_required)
886 out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT; 554 out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT;
887 if (entries[j].pins.required_hashes) { 555 if (entries[j].pins.required_hashes) {
888 const char* const* hash = entries[j].pins.required_hashes; 556 const char* const* sha1_hash = entries[j].pins.required_hashes;
889 while (*hash) { 557 while (*sha1_hash) {
890 bool ok = AddHash(*hash, &out->static_spki_hashes); 558 AddHash(*sha1_hash, &out->static_spki_hashes);
891 DCHECK(ok) << " failed to parse " << *hash; 559 sha1_hash++;
892 hash++;
893 } 560 }
894 } 561 }
895 if (entries[j].pins.excluded_hashes) { 562 if (entries[j].pins.excluded_hashes) {
896 const char* const* hash = entries[j].pins.excluded_hashes; 563 const char* const* sha1_hash = entries[j].pins.excluded_hashes;
897 while (*hash) { 564 while (*sha1_hash) {
898 bool ok = AddHash(*hash, &out->bad_static_spki_hashes); 565 AddHash(*sha1_hash, &out->bad_static_spki_hashes);
899 DCHECK(ok) << " failed to parse " << *hash; 566 sha1_hash++;
900 hash++;
901 } 567 }
902 } 568 }
903 } 569 }
904 return true; 570 return true;
905 } 571 }
906 } 572 }
907 return false; 573 return false;
908 } 574 }
909 575
910 #include "net/base/transport_security_state_static.h" 576 #include "net/base/transport_security_state_static.h"
(...skipping 18 matching lines...) Expand all
929 if (entry->length == canonicalized_host.size() - i && 595 if (entry->length == canonicalized_host.size() - i &&
930 memcmp(entry->dns_name, &canonicalized_host[i], entry->length) == 0) { 596 memcmp(entry->dns_name, &canonicalized_host[i], entry->length) == 0) {
931 return entry; 597 return entry;
932 } 598 }
933 } 599 }
934 } 600 }
935 601
936 return NULL; 602 return NULL;
937 } 603 }
938 604
605 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
606 const std::string& value) {
607 base::Time now = base::Time::Now();
608 TransportSecurityState::DomainState domain_state;
609 if (ParseHSTSHeader(now, value,
610 &domain_state.upgrade_expiry,
611 &domain_state.include_subdomains)) {
Ryan Sleevi 2012/12/07 23:37:21 The wrapping here is inconsistent. Can you fit thi
unsafe 2012/12/08 09:22:42 Done.
612 // Handle max-age == 0
613 if (now == domain_state.upgrade_expiry)
614 domain_state.upgrade_mode = DomainState::MODE_DEFAULT;
615 else
616 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
617 domain_state.created = now;
618 EnableHost(host, domain_state);
619 return true;
620 }
621 return false;
622 }
623
624 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
625 const std::string& value,
626 const SSLInfo& ssl_info) {
627 base::Time now = base::Time::Now();
628 TransportSecurityState::DomainState domain_state;
629 if (ParseHPKPHeader(now, value,
630 ssl_info.public_key_hashes,
631 &domain_state.dynamic_spki_hashes_expiry,
632 &domain_state.dynamic_spki_hashes)) {
633 domain_state.upgrade_mode = DomainState::MODE_DEFAULT;
634 domain_state.created = now;
635 EnableHost(host, domain_state);
636 return true;
637 }
638 return false;
639 }
640
939 // static 641 // static
940 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, 642 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host,
941 bool sni_enabled) { 643 bool sni_enabled) {
942 std::string canonicalized_host = CanonicalizeHost(host); 644 std::string canonicalized_host = CanonicalizeHost(host);
943 const struct HSTSPreload* entry = 645 const struct HSTSPreload* entry =
944 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); 646 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
945 647
946 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts) 648 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
947 return true; 649 return true;
948 650
(...skipping 25 matching lines...) Expand all
974 } 676 }
975 677
976 DCHECK(entry); 678 DCHECK(entry);
977 DCHECK(entry->pins.required_hashes); 679 DCHECK(entry->pins.required_hashes);
978 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED); 680 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED);
979 681
980 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain", 682 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain",
981 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); 683 entry->second_level_domain_name, DOMAIN_NUM_EVENTS);
982 } 684 }
983 685
984 // static
985 const char* TransportSecurityState::HashValueLabel(
986 const HashValue& hash_value) {
987 switch (hash_value.tag) {
988 case HASH_VALUE_SHA1:
989 return "sha1/";
990 case HASH_VALUE_SHA256:
991 return "sha256/";
992 default:
993 NOTREACHED();
994 LOG(WARNING) << "Invalid fingerprint of unknown type " << hash_value.tag;
995 return "unknown/";
996 }
997 }
998
999 bool TransportSecurityState::GetStaticDomainState( 686 bool TransportSecurityState::GetStaticDomainState(
1000 const std::string& canonicalized_host, 687 const std::string& canonicalized_host,
1001 bool sni_enabled, 688 bool sni_enabled,
1002 DomainState* out) { 689 DomainState* out) {
1003 DCHECK(CalledOnValidThread()); 690 DCHECK(CalledOnValidThread());
1004 691
1005 out->upgrade_mode = DomainState::MODE_FORCE_HTTPS; 692 out->upgrade_mode = DomainState::MODE_FORCE_HTTPS;
1006 out->include_subdomains = false; 693 out->include_subdomains = false;
1007 694
1008 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 695 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
(...skipping 24 matching lines...) Expand all
1033 void TransportSecurityState::AddOrUpdateEnabledHosts( 720 void TransportSecurityState::AddOrUpdateEnabledHosts(
1034 const std::string& hashed_host, const DomainState& state) { 721 const std::string& hashed_host, const DomainState& state) {
1035 enabled_hosts_[hashed_host] = state; 722 enabled_hosts_[hashed_host] = state;
1036 } 723 }
1037 724
1038 void TransportSecurityState::AddOrUpdateForcedHosts( 725 void TransportSecurityState::AddOrUpdateForcedHosts(
1039 const std::string& hashed_host, const DomainState& state) { 726 const std::string& hashed_host, const DomainState& state) {
1040 forced_hosts_[hashed_host] = state; 727 forced_hosts_[hashed_host] = state;
1041 } 728 }
1042 729
1043 static std::string HashesToBase64String(
1044 const HashValueVector& hashes) {
1045 std::vector<std::string> hashes_strs;
1046 for (HashValueVector::const_iterator
1047 i = hashes.begin(); i != hashes.end(); i++) {
1048 std::string s;
1049 const std::string hash_str(reinterpret_cast<const char*>(i->data()),
1050 i->size());
1051 base::Base64Encode(hash_str, &s);
1052 hashes_strs.push_back(s);
1053 }
1054
1055 return JoinString(hashes_strs, ',');
1056 }
1057
1058 TransportSecurityState::DomainState::DomainState() 730 TransportSecurityState::DomainState::DomainState()
1059 : upgrade_mode(MODE_FORCE_HTTPS), 731 : upgrade_mode(MODE_FORCE_HTTPS),
1060 created(base::Time::Now()), 732 created(base::Time::Now()),
1061 include_subdomains(false) { 733 include_subdomains(false) {
1062 } 734 }
1063 735
1064 TransportSecurityState::DomainState::~DomainState() { 736 TransportSecurityState::DomainState::~DomainState() {
1065 } 737 }
1066 738
1067 bool TransportSecurityState::DomainState::IsChainOfPublicKeysPermitted( 739 bool TransportSecurityState::DomainState::IsChainOfPublicKeysPermitted(
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 return true; 782 return true;
1111 } 783 }
1112 784
1113 bool TransportSecurityState::DomainState::HasPins() const { 785 bool TransportSecurityState::DomainState::HasPins() const {
1114 return static_spki_hashes.size() > 0 || 786 return static_spki_hashes.size() > 0 ||
1115 bad_static_spki_hashes.size() > 0 || 787 bad_static_spki_hashes.size() > 0 ||
1116 dynamic_spki_hashes.size() > 0; 788 dynamic_spki_hashes.size() > 0;
1117 } 789 }
1118 790
1119 } // namespace 791 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698