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

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

Issue 1212613004: Build and send HPKP violation reports (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove unnecessary net::'s Created 5 years, 4 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 unified diff | Download patch
« no previous file with comments | « net/http/transport_security_state.h ('k') | net/http/transport_security_state_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/http/transport_security_state.h" 5 #include "net/http/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 <nspr.h> 14 #include <nspr.h>
15 #include <pk11pub.h> 15 #include <pk11pub.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/build_time.h" 21 #include "base/build_time.h"
22 #include "base/json/json_writer.h"
22 #include "base/logging.h" 23 #include "base/logging.h"
23 #include "base/memory/scoped_ptr.h" 24 #include "base/memory/scoped_ptr.h"
24 #include "base/metrics/histogram_macros.h" 25 #include "base/metrics/histogram_macros.h"
25 #include "base/metrics/sparse_histogram.h" 26 #include "base/metrics/sparse_histogram.h"
26 #include "base/sha1.h" 27 #include "base/sha1.h"
27 #include "base/strings/string_number_conversions.h" 28 #include "base/strings/string_number_conversions.h"
28 #include "base/strings/string_util.h" 29 #include "base/strings/string_util.h"
30 #include "base/strings/stringprintf.h"
29 #include "base/strings/utf_string_conversions.h" 31 #include "base/strings/utf_string_conversions.h"
30 #include "base/time/time.h" 32 #include "base/time/time.h"
31 #include "base/values.h" 33 #include "base/values.h"
32 #include "crypto/sha2.h" 34 #include "crypto/sha2.h"
33 #include "net/base/dns_util.h" 35 #include "net/base/dns_util.h"
36 #include "net/base/host_port_pair.h"
34 #include "net/cert/x509_cert_types.h" 37 #include "net/cert/x509_cert_types.h"
35 #include "net/cert/x509_certificate.h" 38 #include "net/cert/x509_certificate.h"
36 #include "net/http/http_security_headers.h" 39 #include "net/http/http_security_headers.h"
37 #include "net/ssl/ssl_info.h" 40 #include "net/ssl/ssl_info.h"
38 #include "url/gurl.h" 41 #include "url/gurl.h"
39 42
40 #if defined(USE_OPENSSL) 43 #if defined(USE_OPENSSL)
41 #include "crypto/openssl_util.h" 44 #include "crypto/openssl_util.h"
42 #endif 45 #endif
43 46
44 namespace net { 47 namespace net {
45 48
46 namespace { 49 namespace {
47 50
48 #include "net/http/transport_security_state_static.h" 51 #include "net/http/transport_security_state_static.h"
49 52
53 std::string TimeToISO8601(const base::Time& t) {
54 base::Time::Exploded exploded;
55 t.UTCExplode(&exploded);
56 return base::StringPrintf(
57 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month,
58 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
59 exploded.millisecond);
60 }
61
62 scoped_ptr<base::ListValue> GetPEMEncodedChainAsList(
63 const net::X509Certificate* cert_chain) {
64 if (!cert_chain)
65 return make_scoped_ptr(new base::ListValue());
66
67 scoped_ptr<base::ListValue> result(new base::ListValue());
68 std::vector<std::string> pem_encoded_chain;
69 cert_chain->GetPEMEncodedChain(&pem_encoded_chain);
70 for (const std::string& cert : pem_encoded_chain)
71 result->Append(make_scoped_ptr(new base::StringValue(cert)));
72
73 return result.Pass();
74 }
75
76 bool GetHPKPReport(const HostPortPair& host_port_pair,
77 const TransportSecurityState::PKPState& pkp_state,
78 const X509Certificate* served_certificate_chain,
79 const X509Certificate* validated_certificate_chain,
80 std::string* serialized_report) {
81 // TODO(estark): keep track of reports already sent and rate-limit,
82 // break loops
83 if (pkp_state.report_uri.is_empty())
84 return false;
85
86 base::DictionaryValue report;
87 base::Time now = base::Time::Now();
88 report.SetString("date-time", TimeToISO8601(now));
89 report.SetString("hostname", host_port_pair.host());
90 report.SetInteger("port", host_port_pair.port());
91 report.SetString("effective-expiration-date",
92 TimeToISO8601(pkp_state.expiry));
93 report.SetBoolean("include-subdomains", pkp_state.include_subdomains);
94 report.SetString("noted-hostname", pkp_state.domain);
95
96 scoped_ptr<base::ListValue> served_certificate_chain_list =
97 GetPEMEncodedChainAsList(served_certificate_chain);
98 scoped_ptr<base::ListValue> validated_certificate_chain_list =
99 GetPEMEncodedChainAsList(validated_certificate_chain);
100 report.Set("served-certificate-chain", served_certificate_chain_list.Pass());
101 report.Set("validated-certificate-chain",
102 validated_certificate_chain_list.Pass());
103
104 scoped_ptr<base::ListValue> known_pin_list(new base::ListValue());
105 for (const auto& hash_value : pkp_state.spki_hashes) {
106 std::string known_pin;
107
108 switch (hash_value.tag) {
109 case HASH_VALUE_SHA1:
110 known_pin += "pin-sha1=";
111 break;
112 case HASH_VALUE_SHA256:
113 known_pin += "pin-sha256=";
114 break;
115 }
116
117 std::string base64_value;
118 base::Base64Encode(
119 base::StringPiece(reinterpret_cast<const char*>(hash_value.data()),
120 hash_value.size()),
121 &base64_value);
122 known_pin += "\"" + base64_value + "\"";
123
124 known_pin_list->Append(
125 scoped_ptr<base::Value>(new base::StringValue(known_pin)));
126 }
127
128 report.Set("known-pins", known_pin_list.Pass());
129
130 if (!base::JSONWriter::Write(report, serialized_report)) {
131 LOG(ERROR) << "Failed to serialize HPKP violation report.";
132 return false;
133 }
134
135 return true;
136 }
137
50 std::string HashesToBase64String(const HashValueVector& hashes) { 138 std::string HashesToBase64String(const HashValueVector& hashes) {
51 std::string str; 139 std::string str;
52 for (size_t i = 0; i != hashes.size(); ++i) { 140 for (size_t i = 0; i != hashes.size(); ++i) {
53 if (i != 0) 141 if (i != 0)
54 str += ","; 142 str += ",";
55 str += hashes[i].ToString(); 143 str += hashes[i].ToString();
56 } 144 }
57 return str; 145 return str;
58 } 146 }
59 147
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 << hostname; 554 << hostname;
467 return false; 555 return false;
468 } 556 }
469 557
470 return found; 558 return found;
471 } 559 }
472 560
473 } // namespace 561 } // namespace
474 562
475 TransportSecurityState::TransportSecurityState() 563 TransportSecurityState::TransportSecurityState()
476 : delegate_(NULL), enable_static_pins_(true) { 564 : delegate_(NULL), enable_static_pins_(true) {
Lei Zhang 2015/07/28 20:27:26 I think DrMemory's complaint is not initializing |
477 // Static pinning is only enabled for official builds to make sure that 565 // Static pinning is only enabled for official builds to make sure that
478 // others don't end up with pins that cannot be easily updated. 566 // others don't end up with pins that cannot be easily updated.
479 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS) 567 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS)
480 enable_static_pins_ = false; 568 enable_static_pins_ = false;
481 #endif 569 #endif
482 DCHECK(CalledOnValidThread()); 570 DCHECK(CalledOnValidThread());
483 } 571 }
484 572
485 // Both HSTS and HPKP cause fatal SSL errors, so return true if a 573 // Both HSTS and HPKP cause fatal SSL errors, so return true if a
486 // host has either. 574 // host has either.
(...skipping 16 matching lines...) Expand all
503 PKPState unused; 591 PKPState unused;
504 if (GetStaticDomainState(host, &static_sts_state, &unused) && 592 if (GetStaticDomainState(host, &static_sts_state, &unused) &&
505 static_sts_state.ShouldUpgradeToSSL()) { 593 static_sts_state.ShouldUpgradeToSSL()) {
506 return true; 594 return true;
507 } 595 }
508 596
509 return false; 597 return false;
510 } 598 }
511 599
512 bool TransportSecurityState::CheckPublicKeyPins( 600 bool TransportSecurityState::CheckPublicKeyPins(
513 const std::string& host, 601 const HostPortPair& host_port_pair,
514 bool is_issued_by_known_root, 602 bool is_issued_by_known_root,
515 const HashValueVector& public_key_hashes, 603 const HashValueVector& public_key_hashes,
604 const X509Certificate* served_certificate_chain,
605 const X509Certificate* validated_certificate_chain,
606 const PublicKeyPinReportStatus report_status,
516 std::string* pinning_failure_log) { 607 std::string* pinning_failure_log) {
517 // Perform pin validation if, and only if, all these conditions obtain: 608 // Perform pin validation if, and only if, all these conditions obtain:
518 // 609 //
519 // * the server's certificate chain chains up to a known root (i.e. not a 610 // * the server's certificate chain chains up to a known root (i.e. not a
520 // user-installed trust anchor); and 611 // user-installed trust anchor); and
521 // * the server actually has public key pins. 612 // * the server actually has public key pins.
522 if (!is_issued_by_known_root || !HasPublicKeyPins(host)) { 613 if (!is_issued_by_known_root || !HasPublicKeyPins(host_port_pair.host())) {
523 return true; 614 return true;
524 } 615 }
525 616
526 bool pins_are_valid = 617 bool pins_are_valid = CheckPublicKeyPinsImpl(
527 CheckPublicKeyPinsImpl(host, public_key_hashes, pinning_failure_log); 618 host_port_pair, public_key_hashes, served_certificate_chain,
619 validated_certificate_chain, report_status, pinning_failure_log);
528 if (!pins_are_valid) { 620 if (!pins_are_valid) {
529 LOG(ERROR) << *pinning_failure_log; 621 LOG(ERROR) << *pinning_failure_log;
530 ReportUMAOnPinFailure(host); 622 ReportUMAOnPinFailure(host_port_pair.host());
531 } 623 }
532 624
533 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); 625 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid);
534 return pins_are_valid; 626 return pins_are_valid;
535 } 627 }
536 628
537 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { 629 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) {
538 PKPState dynamic_state; 630 PKPState dynamic_state;
539 if (GetDynamicPKPState(host, &dynamic_state)) 631 if (GetDynamicPKPState(host, &dynamic_state))
540 return dynamic_state.HasPublicKeyPins(); 632 return dynamic_state.HasPublicKeyPins();
541 633
542 STSState unused; 634 STSState unused;
543 PKPState static_pkp_state; 635 PKPState static_pkp_state;
544 if (GetStaticDomainState(host, &unused, &static_pkp_state)) { 636 if (GetStaticDomainState(host, &unused, &static_pkp_state)) {
545 if (static_pkp_state.HasPublicKeyPins()) 637 if (static_pkp_state.HasPublicKeyPins())
546 return true; 638 return true;
547 } 639 }
548 640
549 return false; 641 return false;
550 } 642 }
551 643
552 void TransportSecurityState::SetDelegate( 644 void TransportSecurityState::SetDelegate(
553 TransportSecurityState::Delegate* delegate) { 645 TransportSecurityState::Delegate* delegate) {
554 DCHECK(CalledOnValidThread()); 646 DCHECK(CalledOnValidThread());
555 delegate_ = delegate; 647 delegate_ = delegate;
556 } 648 }
557 649
650 void TransportSecurityState::SetReportSender(
651 TransportSecurityState::ReportSender* report_sender) {
652 DCHECK(CalledOnValidThread());
653 report_sender_ = report_sender;
654 }
655
558 void TransportSecurityState::AddHSTSInternal( 656 void TransportSecurityState::AddHSTSInternal(
559 const std::string& host, 657 const std::string& host,
560 TransportSecurityState::STSState::UpgradeMode upgrade_mode, 658 TransportSecurityState::STSState::UpgradeMode upgrade_mode,
561 const base::Time& expiry, 659 const base::Time& expiry,
562 bool include_subdomains) { 660 bool include_subdomains) {
563 DCHECK(CalledOnValidThread()); 661 DCHECK(CalledOnValidThread());
564 662
565 STSState sts_state; 663 STSState sts_state;
566 sts_state.last_observed = base::Time::Now(); 664 sts_state.last_observed = base::Time::Now();
567 sts_state.include_subdomains = include_subdomains; 665 sts_state.include_subdomains = include_subdomains;
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 #if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD) 904 #if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
807 return true; 905 return true;
808 #else 906 #else
809 const base::Time build_time = base::GetBuildTime(); 907 const base::Time build_time = base::GetBuildTime();
810 // We consider built-in information to be timely for 10 weeks. 908 // We consider built-in information to be timely for 10 weeks.
811 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; 909 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
812 #endif 910 #endif
813 } 911 }
814 912
815 bool TransportSecurityState::CheckPublicKeyPinsImpl( 913 bool TransportSecurityState::CheckPublicKeyPinsImpl(
816 const std::string& host, 914 const HostPortPair& host_port_pair,
817 const HashValueVector& hashes, 915 const HashValueVector& hashes,
916 const X509Certificate* served_certificate_chain,
917 const X509Certificate* validated_certificate_chain,
918 const PublicKeyPinReportStatus report_status,
818 std::string* failure_log) { 919 std::string* failure_log) {
819 PKPState dynamic_state; 920 PKPState pkp_state;
820 if (GetDynamicPKPState(host, &dynamic_state)) 921 STSState unused;
821 return dynamic_state.CheckPublicKeyPins(hashes, failure_log);
822 922
823 PKPState static_pkp_state; 923 if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) &&
824 STSState unused; 924 !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) {
825 if (GetStaticDomainState(host, &unused, &static_pkp_state)) 925 // HasPublicKeyPins should have returned true in order for this method
826 return static_pkp_state.CheckPublicKeyPins(hashes, failure_log); 926 // to have been called, so if we fall through to here, it's an error.
927 return false;
928 }
827 929
828 // HasPublicKeyPins should have returned true in order for this method 930 if (pkp_state.CheckPublicKeyPins(hashes, failure_log))
829 // to have been called, so if we fall through to here, it's an error. 931 return true;
932
933 if (!report_sender_ || report_status != ENABLE_PIN_REPORTS ||
934 pkp_state.report_uri.is_empty()) {
935 return false;
936 }
937
938 DCHECK(pkp_state.report_uri.is_valid());
939
940 std::string serialized_report;
941
942 if (!GetHPKPReport(host_port_pair, pkp_state, served_certificate_chain,
943 validated_certificate_chain, &serialized_report)) {
944 return false;
945 }
946
947 report_sender_->Send(pkp_state.report_uri, serialized_report);
948
830 return false; 949 return false;
831 } 950 }
832 951
833 bool TransportSecurityState::GetStaticDomainState(const std::string& host, 952 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
834 STSState* sts_state, 953 STSState* sts_state,
835 PKPState* pkp_state) const { 954 PKPState* pkp_state) const {
836 DCHECK(CalledOnValidThread()); 955 DCHECK(CalledOnValidThread());
837 956
838 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS; 957 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS;
839 sts_state->include_subdomains = false; 958 sts_state->include_subdomains = false;
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 TransportSecurityState::PKPStateIterator::PKPStateIterator( 1175 TransportSecurityState::PKPStateIterator::PKPStateIterator(
1057 const TransportSecurityState& state) 1176 const TransportSecurityState& state)
1058 : iterator_(state.enabled_pkp_hosts_.begin()), 1177 : iterator_(state.enabled_pkp_hosts_.begin()),
1059 end_(state.enabled_pkp_hosts_.end()) { 1178 end_(state.enabled_pkp_hosts_.end()) {
1060 } 1179 }
1061 1180
1062 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { 1181 TransportSecurityState::PKPStateIterator::~PKPStateIterator() {
1063 } 1182 }
1064 1183
1065 } // namespace 1184 } // namespace
OLDNEW
« no previous file with comments | « net/http/transport_security_state.h ('k') | net/http/transport_security_state_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698