Commit f3572592 authored by agl@chromium.org's avatar agl@chromium.org

Reland: net: move pinning checks into the SSL socket.

This is a reland of r113823, hopefully without breaking the Pepper tests.

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114081 0039d316-1c4b-4281-b951-d872f2087c98
parent f9b85d83
...@@ -31,6 +31,7 @@ struct SSLClientSocketContext { ...@@ -31,6 +31,7 @@ struct SSLClientSocketContext {
SSLClientSocketContext() SSLClientSocketContext()
: cert_verifier(NULL), : cert_verifier(NULL),
origin_bound_cert_service(NULL), origin_bound_cert_service(NULL),
transport_security_state(NULL),
dns_cert_checker(NULL), dns_cert_checker(NULL),
ssl_host_info_factory(NULL) {} ssl_host_info_factory(NULL) {}
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/build_time.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
...@@ -96,7 +97,6 @@ ...@@ -96,7 +97,6 @@
#include "net/base/x509_certificate_net_log_param.h" #include "net/base/x509_certificate_net_log_param.h"
#include "net/ocsp/nss_ocsp.h" #include "net/ocsp/nss_ocsp.h"
#include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_handle.h"
#include "net/socket/dns_cert_provenance_checker.h"
#include "net/socket/nss_ssl_util.h" #include "net/socket/nss_ssl_util.h"
#include "net/socket/ssl_error_params.h" #include "net/socket/ssl_error_params.h"
#include "net/socket/ssl_host_info.h" #include "net/socket/ssl_host_info.h"
...@@ -458,7 +458,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket, ...@@ -458,7 +458,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
nss_bufs_(NULL), nss_bufs_(NULL),
net_log_(transport_socket->socket()->NetLog()), net_log_(transport_socket->socket()->NetLog()),
ssl_host_info_(ssl_host_info), ssl_host_info_(ssl_host_info),
dns_cert_checker_(context.dns_cert_checker), transport_security_state_(context.transport_security_state),
next_proto_status_(kNextProtoUnsupported), next_proto_status_(kNextProtoUnsupported),
valid_thread_id_(base::kInvalidThreadId) { valid_thread_id_(base::kInvalidThreadId) {
EnterFunction(""); EnterFunction("");
...@@ -1624,13 +1624,6 @@ int SSLClientSocketNSS::DoGetOBCertComplete(int result) { ...@@ -1624,13 +1624,6 @@ int SSLClientSocketNSS::DoGetOBCertComplete(int result) {
} }
int SSLClientSocketNSS::DoVerifyDNSSEC(int result) { int SSLClientSocketNSS::DoVerifyDNSSEC(int result) {
if (ssl_config_.dns_cert_provenance_checking_enabled &&
dns_cert_checker_) {
PeerCertificateChain certs(nss_fd_);
dns_cert_checker_->DoAsyncVerification(
host_and_port_.host(), certs.AsStringPieceVector());
}
DNSValidationResult r = CheckDNSSECChain(host_and_port_.host(), DNSValidationResult r = CheckDNSSECChain(host_and_port_.host(),
server_cert_nss_, server_cert_nss_,
host_and_port_.port()); host_and_port_.port());
...@@ -1794,7 +1787,7 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) { ...@@ -1794,7 +1787,7 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
// http://crbug.com/15630 for more info. // http://crbug.com/15630 for more info.
// TODO(hclam): Skip logging if server cert was expected to be bad because // TODO(hclam): Skip logging if server cert was expected to be bad because
// |server_cert_verify_results_| doesn't contain all the information about // |server_cert_verify_result_| doesn't contain all the information about
// the cert. // the cert.
if (result == OK) if (result == OK)
LogConnectionTypeMetrics(); LogConnectionTypeMetrics();
...@@ -1807,6 +1800,47 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) { ...@@ -1807,6 +1800,47 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
DoReadCallback(rv); DoReadCallback(rv);
} }
//#if defined(OFFICIAL_BUILD) && !defined(OS_ANDROID)
// Take care of any mandates for public key pinning.
//
// Pinning is only enabled for official builds to make sure that others don't
// end up with pins that cannot be easily updated.
//
// TODO(agl): we might have an issue here where a request for foo.example.com
// merges into a SPDY connection to www.example.com, and gets a different
// certificate.
const CertStatus cert_status = server_cert_verify_result_->cert_status;
if ((result == OK || (IsCertificateError(result) &&
IsCertStatusMinorError(cert_status))) &&
server_cert_verify_result_->is_issued_by_known_root &&
transport_security_state_) {
bool sni_available = ssl_config_.tls1_enabled || ssl_config_.ssl3_fallback;
const std::string& host = host_and_port_.host();
TransportSecurityState::DomainState domain_state;
if (transport_security_state_->HasPinsForHost(
&domain_state, host, sni_available)) {
if (!domain_state.IsChainOfPublicKeysPermitted(
server_cert_verify_result_->public_key_hashes)) {
const base::Time build_time = base::GetBuildTime();
// Pins are not enforced if the build is sufficiently old. Chrome
// users should get updates every six weeks or so, but it's possible
// that some users will stop getting updates for some reason. We
// don't want those users building up as a pool of people with bad
// pins.
if ((base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */) {
result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", false);
TransportSecurityState::ReportUMAOnPinFailure(host);
}
} else {
UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", true);
}
}
}
//#endif
// Exit DoHandshakeLoop and return the result to the caller to Connect. // Exit DoHandshakeLoop and return the result to the caller to Connect.
DCHECK(next_handshake_state_ == STATE_NONE); DCHECK(next_handshake_state_ == STATE_NONE);
return result; return result;
......
...@@ -35,10 +35,10 @@ namespace net { ...@@ -35,10 +35,10 @@ namespace net {
class BoundNetLog; class BoundNetLog;
class CertVerifier; class CertVerifier;
class ClientSocketHandle; class ClientSocketHandle;
class DnsCertProvenanceChecker;
class OriginBoundCertService; class OriginBoundCertService;
class SingleRequestCertVerifier; class SingleRequestCertVerifier;
class SSLHostInfo; class SSLHostInfo;
class TransportSecurityState;
class X509Certificate; class X509Certificate;
// An SSL client socket implemented with Mozilla NSS. // An SSL client socket implemented with Mozilla NSS.
...@@ -296,7 +296,8 @@ class SSLClientSocketNSS : public SSLClientSocket { ...@@ -296,7 +296,8 @@ class SSLClientSocketNSS : public SSLClientSocket {
base::TimeTicks start_cert_verification_time_; base::TimeTicks start_cert_verification_time_;
scoped_ptr<SSLHostInfo> ssl_host_info_; scoped_ptr<SSLHostInfo> ssl_host_info_;
DnsCertProvenanceChecker* const dns_cert_checker_;
TransportSecurityState* transport_security_state_;
// next_proto_ is the protocol that we selected by NPN. // next_proto_ is the protocol that we selected by NPN.
std::string next_proto_; std::string next_proto_;
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include "base/base_switches.h" #include "base/base_switches.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/build_time.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/file_util.h" #include "base/file_util.h"
...@@ -30,7 +29,6 @@ ...@@ -30,7 +29,6 @@
#include "net/base/sdch_manager.h" #include "net/base/sdch_manager.h"
#include "net/base/ssl_cert_request_info.h" #include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_config_service.h" #include "net/base/ssl_config_service.h"
#include "net/base/transport_security_state.h"
#include "net/http/http_mac_signature.h" #include "net/http/http_mac_signature.h"
#include "net/http/http_request_headers.h" #include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
...@@ -661,53 +659,19 @@ void URLRequestHttpJob::OnStartCompleted(int result) { ...@@ -661,53 +659,19 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
// Clear the IO_PENDING status // Clear the IO_PENDING status
SetStatus(URLRequestStatus()); SetStatus(URLRequestStatus());
#if defined(OFFICIAL_BUILD) && !defined(OS_ANDROID) if (result == ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN &&
// Take care of any mandates for public key pinning. transaction_->GetResponseInfo() != NULL) {
// FraudulentCertificateReporter* reporter =
// Pinning is only enabled for official builds to make sure that others don't context_->fraudulent_certificate_reporter();
// end up with pins that cannot be easily updated. if (reporter != NULL) {
// const SSLInfo& ssl_info = transaction_->GetResponseInfo()->ssl_info;
// TODO(agl): we might have an issue here where a request for foo.example.com
// merges into a SPDY connection to www.example.com, and gets a different
// certificate.
if (transaction_->GetResponseInfo() != NULL) {
const SSLInfo& ssl_info = transaction_->GetResponseInfo()->ssl_info;
if (ssl_info.is_valid() &&
(result == OK || (IsCertificateError(result) &&
IsCertStatusMinorError(ssl_info.cert_status))) &&
ssl_info.is_issued_by_known_root &&
context_->transport_security_state()) {
TransportSecurityState::DomainState domain_state;
bool sni_available = SSLConfigService::IsSNIAvailable( bool sni_available = SSLConfigService::IsSNIAvailable(
context_->ssl_config_service()); context_->ssl_config_service());
std::string host = request_->url().host(); const std::string& host = request_->url().host();
if (context_->transport_security_state()->HasPinsForHost( reporter->SendReport(host, ssl_info, sni_available);
&domain_state, host, sni_available)) {
if (!domain_state.IsChainOfPublicKeysPermitted(
ssl_info.public_key_hashes)) {
const base::Time build_time = base::GetBuildTime();
// Pins are not enforced if the build is sufficiently old. Chrome
// users should get updates every six weeks or so, but it's possible
// that some users will stop getting updates for some reason. We
// don't want those users building up as a pool of people with bad
// pins.
if ((base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */) {
result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", false);
TransportSecurityState::ReportUMAOnPinFailure(host);
FraudulentCertificateReporter* reporter =
context_->fraudulent_certificate_reporter();
if (reporter != NULL)
reporter->SendReport(host, ssl_info, sni_available);
}
} else {
UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", true);
}
}
} }
} }
#endif
if (result == OK) { if (result == OK) {
scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders(); scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment