Index: net/socket/ssl_client_socket_nss.cc |
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc |
index 0ac5a83a0fa3440830e5840fc900d69138263238..b0c392bb97cfe6a44c6f7a7cbd039e0c582dd760 100644 |
--- a/net/socket/ssl_client_socket_nss.cc |
+++ b/net/socket/ssl_client_socket_nss.cc |
@@ -3432,15 +3432,26 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) { |
// 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 |
+ // 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. |
+ // Perform pin validation if, and only if, all these conditions obtain: |
+ // |
+ // * a TransportSecurityState object is available; |
+ // * the server's certificate chain is valid (or suffers from only a minor |
+ // error); |
+ // * the server's certificate chain chains up to a known root (i.e. not a |
+ // user-installed trust anchor); and |
+ // * the build is recent (very old builds should fail open so that users |
+ // have some chance to recover). |
+ // |
const CertStatus cert_status = server_cert_verify_result_.cert_status; |
- if ((result == OK || (IsCertificateError(result) && |
- IsCertStatusMinorError(cert_status))) && |
+ if (transport_security_state_ && |
+ (result == OK || |
+ (IsCertificateError(result) && IsCertStatusMinorError(cert_status))) && |
server_cert_verify_result_.is_issued_by_known_root && |
- transport_security_state_) { |
+ TransportSecurityState::IsBuildTimely()) { |
bool sni_available = |
ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1 || |
ssl_config_.version_fallback; |
@@ -3451,13 +3462,10 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) { |
&domain_state) && |
domain_state.HasPublicKeyPins()) { |
if (!domain_state.CheckPublicKeyPins( |
- server_cert_verify_result_.public_key_hashes)) { |
- // Pins are not enforced if the build is too old. |
- if (TransportSecurityState::IsBuildTimely()) { |
- result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN; |
- UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", false); |
- TransportSecurityState::ReportUMAOnPinFailure(host); |
- } |
+ server_cert_verify_result_.public_key_hashes)) { |
+ 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); |
} |