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

Unified Diff: net/socket/ssl_client_socket_openssl.cc

Issue 576233002: Only use the platform cert in verification in SSLClientSocketOpenSSL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: don't export two versions Created 6 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2e011d97997d551dc780eded34b235bd7440278f..1a9d4b735fb40f2c5b6f205d4e16cd3807081af3 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -27,6 +27,7 @@
#include "net/cert/ct_verifier.h"
#include "net/cert/single_request_cert_verifier.h"
#include "net/cert/x509_certificate_net_log_param.h"
+#include "net/cert/x509_util_openssl.h"
#include "net/http/transport_security_state.h"
#include "net/socket/ssl_session_cache_openssl.h"
#include "net/ssl/openssl_ssl_util.h"
@@ -251,7 +252,7 @@ class SSLClientSocketOpenSSL::PeerCertificateChain {
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_; }
+ scoped_refptr<X509Certificate> AsOSChain() const;
size_t size() const {
if (!openssl_chain_.get())
@@ -259,17 +260,17 @@ class SSLClientSocketOpenSSL::PeerCertificateChain {
return sk_X509_num(openssl_chain_.get());
}
- X509* operator[](size_t index) const {
+ bool empty() const {
+ return size() == 0;
+ }
+
+ X509* Get(size_t index) const {
DCHECK_LT(index, size());
return sk_X509_value(openssl_chain_.get(), index);
}
- bool IsValid() { return os_chain_.get() && openssl_chain_.get(); }
-
private:
ScopedX509Stack openssl_chain_;
-
- scoped_refptr<X509Certificate> os_chain_;
};
SSLClientSocketOpenSSL::PeerCertificateChain&
@@ -278,69 +279,41 @@ SSLClientSocketOpenSSL::PeerCertificateChain::operator=(
if (this == &other)
return *this;
- // os_chain_ is reference counted by scoped_refptr;
- os_chain_ = other.os_chain_;
-
openssl_chain_.reset(X509_chain_up_ref(other.openssl_chain_.get()));
-
return *this;
}
-#if defined(USE_OPENSSL_CERTS)
-// 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(
STACK_OF(X509)* chain) {
- openssl_chain_.reset(NULL);
- os_chain_ = NULL;
-
- if (!chain)
- return;
-
- X509Certificate::OSCertHandles intermediates;
- for (size_t i = 1; i < sk_X509_num(chain); ++i)
- intermediates.push_back(sk_X509_value(chain, i));
-
- os_chain_ =
- X509Certificate::CreateFromHandle(sk_X509_value(chain, 0), intermediates);
-
- openssl_chain_.reset(X509_chain_up_ref(chain));
+ openssl_chain_.reset(chain ? X509_chain_up_ref(chain) : NULL);
}
-#else // !defined(USE_OPENSSL_CERTS)
-void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(
- STACK_OF(X509)* chain) {
- openssl_chain_.reset(NULL);
- os_chain_ = NULL;
-
- if (!chain)
- return;
- openssl_chain_.reset(X509_chain_up_ref(chain));
+scoped_refptr<X509Certificate>
+SSLClientSocketOpenSSL::PeerCertificateChain::AsOSChain() const {
+#if defined(USE_OPENSSL_CERTS)
+ // When OSCertHandle is typedef'ed to X509, this implementation does a short
+ // cut to avoid converting back and forth between DER and the X509 struct.
+ X509Certificate::OSCertHandles intermediates;
+ for (size_t i = 1; i < sk_X509_num(openssl_chain_.get()); ++i) {
+ intermediates.push_back(sk_X509_value(openssl_chain_.get(), i));
+ }
+ return make_scoped_refptr(X509Certificate::CreateFromHandle(
+ sk_X509_value(openssl_chain_.get(), 0), intermediates));
+#else
+ // DER-encode the chain and convert to a platform certificate handle.
std::vector<base::StringPiece> der_chain;
for (size_t i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) {
X509* x = sk_X509_value(openssl_chain_.get(), i);
-
- unsigned char* cert_data = NULL;
- int cert_data_length = i2d_X509(x, &cert_data);
- if (cert_data_length && cert_data)
- der_chain.push_back(base::StringPiece(reinterpret_cast<char*>(cert_data),
- cert_data_length));
- }
-
- os_chain_ = X509Certificate::CreateFromDERCertChain(der_chain);
-
- for (size_t i = 0; i < der_chain.size(); ++i) {
- OPENSSL_free(const_cast<char*>(der_chain[i].data()));
+ base::StringPiece der;
+ if (!x509_util::GetDER(x, &der))
+ return NULL;
+ der_chain.push_back(der);
}
- if (der_chain.size() !=
- static_cast<size_t>(sk_X509_num(openssl_chain_.get()))) {
- openssl_chain_.reset(NULL);
- os_chain_ = NULL;
- }
+ return make_scoped_refptr(X509Certificate::CreateFromDERCertChain(der_chain));
+#endif
}
-#endif // defined(USE_OPENSSL_CERTS)
// static
SSLSessionCacheOpenSSL::Config
@@ -613,7 +586,7 @@ bool SSLClientSocketOpenSSL::UsingTCPFastOpen() const {
bool SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->Reset();
- if (!server_cert_.get())
+ if (server_cert_chain_->empty())
return false;
ssl_info->cert = server_cert_verify_result_.verified_cert;
@@ -961,12 +934,7 @@ int SSLClientSocketOpenSSL::DoHandshake() {
set_signed_cert_timestamps_received(sct_list_len != 0);
// Verify the certificate.
- const bool got_cert = !!UpdateServerCert();
- DCHECK(got_cert);
- net_log_.AddEvent(
- NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
- base::Bind(&NetLogX509CertificateCallback,
- base::Unretained(server_cert_.get())));
+ UpdateServerCert();
GotoState(STATE_VERIFY_CERT);
} else {
int ssl_error = SSL_get_error(ssl_, rv);
@@ -1049,12 +1017,20 @@ int SSLClientSocketOpenSSL::DoChannelIDLookupComplete(int result) {
}
int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
- DCHECK(server_cert_.get());
+ DCHECK(!server_cert_chain_->empty());
DCHECK(start_cert_verification_time_.is_null());
+
GotoState(STATE_VERIFY_CERT_COMPLETE);
+ // If the certificate is bad and has been previously accepted, use
+ // the previous status and bypass the error.
+ base::StringPiece der_cert;
+ if (!x509_util::GetDER(server_cert_chain_->Get(0), &der_cert)) {
+ NOTREACHED();
+ return ERR_CERT_INVALID;
+ }
CertStatus cert_status;
- if (ssl_config_.IsAllowedBadCert(server_cert_.get(), &cert_status)) {
+ if (ssl_config_.IsAllowedBadCert(der_cert, &cert_status)) {
VLOG(1) << "Received an expected bad cert with status: " << cert_status;
server_cert_verify_result_.Reset();
server_cert_verify_result_.cert_status = cert_status;
@@ -1062,6 +1038,15 @@ int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
return OK;
}
+ // When running in a sandbox, it may not be possible to create an
+ // X509Certificate*, as that may depend on OS functionality blocked
+ // in the sandbox.
+ if (!server_cert_.get()) {
+ server_cert_verify_result_.Reset();
+ server_cert_verify_result_.cert_status = CERT_STATUS_INVALID;
+ return ERR_CERT_INVALID;
+ }
+
start_cert_verification_time_ = base::TimeTicks::Now();
int flags = 0;
@@ -1147,14 +1132,16 @@ void SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
}
}
-X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() {
+void SSLClientSocketOpenSSL::UpdateServerCert() {
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();
+ if (server_cert_.get()) {
+ net_log_.AddEvent(
+ NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
+ base::Bind(&NetLogX509CertificateCallback,
+ base::Unretained(server_cert_.get())));
+ }
}
void SSLClientSocketOpenSSL::VerifyCT() {
@@ -1619,17 +1606,24 @@ int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) {
return 1;
}
- CHECK(server_cert_.get());
-
- PeerCertificateChain chain(store_ctx->untrusted);
- if (chain.IsValid() && server_cert_->Equals(chain.AsOSChain().get()))
- return 1;
-
- if (!chain.IsValid())
+ // Disallow the server certificate to change in a renegotiation.
+ if (server_cert_chain_->empty()) {
LOG(ERROR) << "Received invalid certificate chain between handshakes";
- else
+ return 0;
+ }
+ base::StringPiece old_der, new_der;
+ if (store_ctx->cert == NULL ||
+ !x509_util::GetDER(server_cert_chain_->Get(0), &old_der) ||
+ !x509_util::GetDER(store_ctx->cert, &new_der)) {
+ LOG(ERROR) << "Failed to encode certificates";
+ return 0;
+ }
+ if (old_der != new_der) {
LOG(ERROR) << "Server certificate changed between handshakes";
- return 0;
+ return 0;
+ }
+
+ return 1;
}
// SelectNextProtoCallback is called by OpenSSL during the handshake. If the
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698