Do not assume OSCertHandle is OpenSSL's X509 structure.

Instead create a X509Certificate instance from the OpenSSL 
chain via PeerCertificateChain, and compare with the existing
X509Certificate.

BUG=none

Review URL: https://codereview.chromium.org/203323004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258337 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index d04670f..f97c4697c 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -332,16 +332,17 @@
 // 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 @@
     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 @@
 #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 @@
   }
 }
 #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 @@
 }
 
 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 @@
     return 1;
   }
 
-  if (X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(),
-                                    sk_X509_value(store_ctx->untrusted, 0))) {
-    return 1;
-  }
+  CHECK(server_cert_.get());
 
-  LOG(ERROR) << "Server certificate changed between handshakes";
+  PeerCertificateChain chain(store_ctx->chain);
+  if (chain.IsValid() && server_cert_->Equals(chain.AsOSChain()))
+    return 1;
+
+  if (!chain.IsValid())
+    LOG(ERROR) << "Received invalid certificate chain between handshakes";
+  else
+    LOG(ERROR) << "Server certificate changed between handshakes";
   return 0;
 }