summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/base/ssl_config_service.cc10
-rw-r--r--net/base/ssl_config_service.h8
-rw-r--r--net/base/x509_certificate.cc18
-rw-r--r--net/http/http_stream_factory_impl_job.cc8
-rw-r--r--net/socket/ssl_client_socket_nss.cc32
-rw-r--r--net/socket/ssl_client_socket_nss.h2
-rw-r--r--net/socket/ssl_server_socket_unittest.cc2
-rw-r--r--net/socket_stream/socket_stream.cc8
-rw-r--r--remoting/protocol/jingle_stream_connector.cc5
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.