Index: net/socket/ssl_client_socket_openssl.cc |
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc |
index d04670fc14fcab9b1e7465a3525886b6b798b03a..f97c4697cfe6fb30e8801a9193afc51d5e6fca30 100644 |
--- a/net/socket/ssl_client_socket_openssl.cc |
+++ b/net/socket/ssl_client_socket_openssl.cc |
@@ -332,16 +332,17 @@ class SSLClientSocketOpenSSL::SSLContext { |
// and the other elements are in the order given by the server. |
class SSLClientSocketOpenSSL::PeerCertificateChain { |
public: |
- explicit PeerCertificateChain(SSL* ssl) { Reset(ssl); } |
+ explicit PeerCertificateChain(STACK_OF(X509)* chain) { Reset(chain); } |
PeerCertificateChain(const PeerCertificateChain& other) { *this = other; } |
~PeerCertificateChain() {} |
PeerCertificateChain& operator=(const PeerCertificateChain& other); |
- // Resets the PeerCertificateChain to the set of certificates supplied by the |
- // peer of |ssl|, which may be NULL, indicating to empty the store |
- // certificates. Note: If an error occurs, such as being unable to parse the |
- // certificates, this will behave as if Reset(NULL) was called. |
- void Reset(SSL* ssl); |
+ // Resets the PeerCertificateChain to the set of certificates in|chain|, |
+ // which may be NULL, indicating to empty the store certificates. |
+ // Note: If an error occurs, such as being unable to parse the certificates, |
+ // this will behave as if Reset(NULL) was called. |
+ void Reset(STACK_OF(X509)* chain); |
+ |
// Note that when USE_OPENSSL is defined, OSCertHandle is X509* |
const scoped_refptr<X509Certificate>& AsOSChain() const { return os_chain_; } |
@@ -356,6 +357,8 @@ class SSLClientSocketOpenSSL::PeerCertificateChain { |
return sk_X509_value(openssl_chain_.get(), index); |
} |
+ bool IsValid() { return os_chain_.get() && openssl_chain_.get(); } |
+ |
private: |
static void FreeX509Stack(STACK_OF(X509)* cert_chain) { |
sk_X509_pop_free(cert_chain, X509_free); |
@@ -389,14 +392,11 @@ SSLClientSocketOpenSSL::PeerCertificateChain::operator=( |
#if defined(USE_OPENSSL) |
// When OSCertHandle is typedef'ed to X509, this implementation does a short cut |
// to avoid converting back and forth between der and X509 struct. |
-void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(SSL* ssl) { |
+void SSLClientSocketOpenSSL::PeerCertificateChain::Reset( |
+ STACK_OF(X509)* chain) { |
openssl_chain_.reset(NULL); |
os_chain_ = NULL; |
- if (ssl == NULL) |
- return; |
- |
- STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); |
if (!chain) |
return; |
@@ -418,14 +418,11 @@ void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(SSL* ssl) { |
} |
} |
#else // !defined(USE_OPENSSL) |
-void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(SSL* ssl) { |
+void SSLClientSocketOpenSSL::PeerCertificateChain::Reset( |
+ STACK_OF(X509)* chain) { |
openssl_chain_.reset(NULL); |
os_chain_ = NULL; |
- if (ssl == NULL) |
- return; |
- |
- STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); |
if (!chain) |
return; |
@@ -1058,8 +1055,12 @@ void SSLClientSocketOpenSSL::DoConnectCallback(int rv) { |
} |
X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { |
- server_cert_chain_->Reset(ssl_); |
+ server_cert_chain_->Reset(SSL_get_peer_cert_chain(ssl_)); |
server_cert_ = server_cert_chain_->AsOSChain(); |
+ |
+ if (!server_cert_chain_->IsValid()) |
+ DVLOG(1) << "UpdateServerCert received invalid certificate chain from peer"; |
+ |
return server_cert_.get(); |
} |
@@ -1502,12 +1503,16 @@ int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) { |
return 1; |
} |
- if (X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(), |
- sk_X509_value(store_ctx->untrusted, 0))) { |
+ CHECK(server_cert_.get()); |
+ |
+ PeerCertificateChain chain(store_ctx->chain); |
+ if (chain.IsValid() && server_cert_->Equals(chain.AsOSChain())) |
return 1; |
- } |
- LOG(ERROR) << "Server certificate changed between handshakes"; |
+ if (!chain.IsValid()) |
+ LOG(ERROR) << "Received invalid certificate chain between handshakes"; |
+ else |
+ LOG(ERROR) << "Server certificate changed between handshakes"; |
return 0; |
} |