diff options
-rw-r--r-- | net/base/ssl_config_service.cc | 10 | ||||
-rw-r--r-- | net/base/ssl_config_service.h | 8 | ||||
-rw-r--r-- | net/base/x509_certificate.cc | 18 | ||||
-rw-r--r-- | net/http/http_stream_factory_impl_job.cc | 8 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 32 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.h | 2 | ||||
-rw-r--r-- | net/socket/ssl_server_socket_unittest.cc | 2 | ||||
-rw-r--r-- | net/socket_stream/socket_stream.cc | 8 | ||||
-rw-r--r-- | remoting/protocol/jingle_stream_connector.cc | 5 |
9 files changed, 69 insertions, 24 deletions
diff --git a/net/base/ssl_config_service.cc b/net/base/ssl_config_service.cc index 5fe01cf..f3a09f0 100644 --- a/net/base/ssl_config_service.cc +++ b/net/base/ssl_config_service.cc @@ -26,8 +26,16 @@ SSLConfig::~SSLConfig() { bool SSLConfig::IsAllowedBadCert(X509Certificate* cert, int* cert_status) const { + std::string der_cert; + if (!cert->GetDEREncoded(&der_cert)) + return false; + return IsAllowedBadCert(der_cert, cert_status); +} + +bool SSLConfig::IsAllowedBadCert(const base::StringPiece& der_cert, + int* cert_status) const { for (size_t i = 0; i < allowed_bad_certs.size(); ++i) { - if (cert->Equals(allowed_bad_certs[i].cert)) { + if (der_cert == allowed_bad_certs[i].der_cert) { if (cert_status) *cert_status = allowed_bad_certs[i].cert_status; return true; diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h index 2b2e28a..ab84aad 100644 --- a/net/base/ssl_config_service.h +++ b/net/base/ssl_config_service.h @@ -11,6 +11,7 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" +#include "base/string_piece.h" #include "net/base/net_api.h" #include "net/base/x509_certificate.h" @@ -28,6 +29,11 @@ struct NET_API SSLConfig { // be NULL if user doesn't care about the cert status. bool IsAllowedBadCert(X509Certificate* cert, int* cert_status) const; + // Same as above except works with DER encoded certificates instead + // of X509Certificate. + bool IsAllowedBadCert(const base::StringPiece& der_cert, + int* cert_status) const; + bool rev_checking_enabled; // True if server certificate revocation // checking is enabled. // SSL 2.0 is not supported. @@ -67,7 +73,7 @@ struct NET_API SSLConfig { CertAndStatus(); ~CertAndStatus(); - scoped_refptr<X509Certificate> cert; + std::string der_cert; int cert_status; }; diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc index 5ac75b3..9d36b50 100644 --- a/net/base/x509_certificate.cc +++ b/net/base/x509_certificate.cc @@ -262,14 +262,22 @@ X509Certificate* X509Certificate::CreateFromDERCertChain( X509Certificate::OSCertHandles intermediate_ca_certs; for (size_t i = 1; i < der_certs.size(); i++) { OSCertHandle handle = CreateOSCert(der_certs[i]); - DCHECK(handle); + if (!handle) + break; intermediate_ca_certs.push_back(handle); } - OSCertHandle handle = CreateOSCert(der_certs[0]); - DCHECK(handle); - X509Certificate* cert = CreateFromHandle(handle, intermediate_ca_certs); - FreeOSCertHandle(handle); + OSCertHandle handle = NULL; + // Return NULL if we failed to parse any of the certs. + if (der_certs.size() - 1 == intermediate_ca_certs.size()) + handle = CreateOSCert(der_certs[0]); + + X509Certificate* cert = NULL; + if (handle) { + cert = CreateFromHandle(handle, intermediate_ca_certs); + FreeOSCertHandle(handle); + } + for (size_t i = 0; i < intermediate_ca_certs.size(); i++) FreeOSCertHandle(intermediate_ca_certs[i]); diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index 417857b..dcbf114 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc @@ -1013,7 +1013,13 @@ int HttpStreamFactoryImpl::Job::HandleCertificateError(int error) { // RestartIgnoringLastError(). And the user will be asked interactively // before RestartIgnoringLastError() is ever called. SSLConfig::CertAndStatus bad_cert; - bad_cert.cert = ssl_info_.cert; + + // |ssl_info_.cert| may be NULL if we failed to create + // X509Certificate for whatever reason, but normally it shouldn't + // happen, unless this code is used inside sandbox. + if (ssl_info_.cert == NULL || + !ssl_info_.cert->GetDEREncoded(&bad_cert.der_cert)) + return error; bad_cert.cert_status = ssl_info_.cert_status; ssl_config_.allowed_bad_certs.push_back(bad_cert); diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index f0a4ee0..18fd378 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -478,11 +478,10 @@ void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { EnterFunction(""); ssl_info->Reset(); - if (!server_cert_) + if (!server_cert_nss_) return; ssl_info->cert_status = server_cert_verify_result_->cert_status; - DCHECK(server_cert_ != NULL); ssl_info->cert = server_cert_; ssl_info->connection_status = ssl_connection_status_; ssl_info->public_key_hashes = server_cert_verify_result_->public_key_hashes; @@ -1038,18 +1037,18 @@ int SSLClientSocketNSS::InitializeSSLPeerName() { // Sets server_cert_ and server_cert_nss_ if not yet set. -// Returns server_cert_. -X509Certificate *SSLClientSocketNSS::UpdateServerCert() { +void SSLClientSocketNSS::UpdateServerCert() { // We set the server_cert_ from HandshakeCallback(). if (server_cert_ == NULL) { server_cert_nss_ = SSL_PeerCertificate(nss_fd_); if (server_cert_nss_) { PeerCertificateChain certs(nss_fd_); + // This call may fail when SSL is used inside sandbox. In that + // case CreateFromDERCertChain() returns NULL. server_cert_ = X509Certificate::CreateFromDERCertChain( certs.AsStringPieceVector()); } } - return server_cert_; } // Sets ssl_connection_status_. @@ -1521,14 +1520,20 @@ int SSLClientSocketNSS::DoVerifyDNSSEC(int result) { } int SSLClientSocketNSS::DoVerifyCert(int result) { - DCHECK(server_cert_); + DCHECK(server_cert_nss_); GotoState(STATE_VERIFY_CERT_COMPLETE); - // If the certificate is expected to be bad we can use the expectation as the - // cert status. + // If the certificate is expected to be bad we can use the + // expectation as the cert status. Don't use |server_cert_| here + // because it can be set to NULL in case we failed to create + // X509Certificate in UpdateServerCert(). This may happen when this + // code is used inside sandbox. + base::StringPiece der_cert( + reinterpret_cast<char*>(server_cert_nss_->derCert.data), + server_cert_nss_->derCert.len); int cert_status; - if (ssl_config_.IsAllowedBadCert(server_cert_, &cert_status)) { + if (ssl_config_.IsAllowedBadCert(der_cert, &cert_status)) { DCHECK(start_cert_verification_time_.is_null()); VLOG(1) << "Received an expected bad cert with status: " << cert_status; server_cert_verify_result_ = &local_server_cert_verify_result_; @@ -1537,6 +1542,15 @@ int SSLClientSocketNSS::DoVerifyCert(int result) { return OK; } + // We may have failed to create X509Certificate object if we are + // running inside sandbox. + if (!server_cert_) { + server_cert_verify_result_ = &local_server_cert_verify_result_; + local_server_cert_verify_result_.Reset(); + local_server_cert_verify_result_.cert_status = CERT_STATUS_INVALID; + return ERR_CERT_INVALID; + } + start_cert_verification_time_ = base::TimeTicks::Now(); if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty() && diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h index 8573b48..8189949 100644 --- a/net/socket/ssl_client_socket_nss.h +++ b/net/socket/ssl_client_socket_nss.h @@ -102,7 +102,7 @@ class SSLClientSocketNSS : public SSLClientSocket { // Initializes the socket peer name in SSL. Returns a net error code. int InitializeSSLPeerName(); - X509Certificate* UpdateServerCert(); + void UpdateServerCert(); void UpdateConnectionStatus(); void DoReadCallback(int result); void DoWriteCallback(int result); diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc index de89c20..894bf98 100644 --- a/net/socket/ssl_server_socket_unittest.cc +++ b/net/socket/ssl_server_socket_unittest.cc @@ -262,7 +262,7 @@ class SSLServerSocketTest : public PlatformTest { // Certificate provided by the host doesn't need authority. net::SSLConfig::CertAndStatus cert_and_status; cert_and_status.cert_status = CERT_STATUS_AUTHORITY_INVALID; - cert_and_status.cert = cert; + cert_and_status.der_cert = cert_der; ssl_config.allowed_bad_certs.push_back(cert_and_status); net::HostPortPair host_and_pair("unittest", 0); diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc index d89c074..b8e9773 100644 --- a/net/socket_stream/socket_stream.cc +++ b/net/socket_stream/socket_stream.cc @@ -877,7 +877,8 @@ int SocketStream::DoSSLConnectComplete(int result) { reinterpret_cast<SSLClientSocket*>(socket_.get()); SSLInfo ssl_info; ssl_socket->GetSSLInfo(&ssl_info); - if (ssl_config_.IsAllowedBadCert(ssl_info.cert, NULL)) { + if (ssl_info.cert == NULL || + ssl_config_.IsAllowedBadCert(ssl_info.cert, NULL)) { // If we already have the certificate in the set of allowed bad // certificates, we did try it and failed again, so we should not // retry again: the connection should fail at last. @@ -887,7 +888,10 @@ int SocketStream::DoSSLConnectComplete(int result) { // Add the bad certificate to the set of allowed certificates in the // SSL config object. SSLConfig::CertAndStatus bad_cert; - bad_cert.cert = ssl_info.cert; + if (!ssl_info.cert->GetDEREncoded(&bad_cert.der_cert)) { + next_state_ = STATE_CLOSE; + return result; + } bad_cert.cert_status = ssl_info.cert_status; ssl_config_.allowed_bad_certs.push_back(bad_cert); // Restart connection ignoring the bad certificate. diff --git a/remoting/protocol/jingle_stream_connector.cc b/remoting/protocol/jingle_stream_connector.cc index 27fa331..59813ff 100644 --- a/remoting/protocol/jingle_stream_connector.cc +++ b/remoting/protocol/jingle_stream_connector.cc @@ -28,15 +28,14 @@ const int kTcpAckDelayMilliseconds = 10; // Helper method to create a SSL client socket. net::SSLClientSocket* CreateSSLClientSocket( - net::StreamSocket* socket, const std::string& cert_der, + net::StreamSocket* socket, const std::string& der_cert, net::CertVerifier* cert_verifier) { net::SSLConfig ssl_config; // Certificate provided by the host doesn't need authority. net::SSLConfig::CertAndStatus cert_and_status; cert_and_status.cert_status = net::CERT_STATUS_AUTHORITY_INVALID; - cert_and_status.cert = net::X509Certificate::CreateFromBytes( - cert_der.data(), cert_der.length()); + cert_and_status.der_cert = der_cert; ssl_config.allowed_bad_certs.push_back(cert_and_status); // SSLClientSocket takes ownership of the adapter. |