summaryrefslogtreecommitdiffstats
path: root/chromium/net/socket/ssl_client_socket_nss.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/socket/ssl_client_socket_nss.cc')
-rw-r--r--chromium/net/socket/ssl_client_socket_nss.cc177
1 files changed, 72 insertions, 105 deletions
diff --git a/chromium/net/socket/ssl_client_socket_nss.cc b/chromium/net/socket/ssl_client_socket_nss.cc
index 0c73ec6c582..9f40a78371e 100644
--- a/chromium/net/socket/ssl_client_socket_nss.cc
+++ b/chromium/net/socket/ssl_client_socket_nss.cc
@@ -271,11 +271,6 @@ BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
#endif
-void DestroyCertificates(CERTCertificate** certs, size_t len) {
- for (size_t i = 0; i < len; i++)
- CERT_DestroyCertificate(certs[i]);
-}
-
// Helper functions to make it possible to log events from within the
// SSLClientSocketNSS::Core.
void AddLogEvent(const base::WeakPtr<BoundNetLog>& net_log,
@@ -335,7 +330,6 @@ class PeerCertificateChain {
std::vector<base::StringPiece> AsStringPieceVector() const;
bool empty() const { return certs_.empty(); }
- size_t size() const { return certs_.size(); }
CERTCertificate* operator[](size_t index) const {
DCHECK_LT(index, certs_.size());
@@ -615,13 +609,6 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
bool Init(PRFileDesc* socket, memio_Private* buffers);
// Called on the network task runner.
- // Sets the predicted certificate chain that the peer will send, for use
- // with the TLS CachedInfo extension. If called, it must not be called
- // before Init() or after Connect().
- void SetPredictedCertificates(
- const std::vector<std::string>& predicted_certificates);
-
- // Called on the network task runner.
//
// Attempts to perform an SSL handshake. If the handshake cannot be
// completed synchronously, returns ERR_IO_PENDING, invoking |callback| on
@@ -648,9 +635,10 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
// Called on the network task runner.
- bool IsConnected();
- bool HasPendingAsyncOperation();
- bool HasUnhandledReceivedData();
+ bool IsConnected() const;
+ bool HasPendingAsyncOperation() const;
+ bool HasUnhandledReceivedData() const;
+ bool WasEverUsed() const;
// Called on the network task runner.
// Causes the associated SSL/TLS session ID to be added to NSS's session
@@ -853,6 +841,10 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
bool nss_waiting_write_;
bool nss_is_closed_;
+ // Set when Read() or Write() successfully reads or writes data to or from the
+ // network.
+ bool was_ever_used_;
+
////////////////////////////////////////////////////////////////////////////
// Members that are ONLY accessed on the NSS task runner:
////////////////////////////////////////////////////////////////////////////
@@ -948,6 +940,7 @@ SSLClientSocketNSS::Core::Core(
nss_waiting_read_(false),
nss_waiting_write_(false),
nss_is_closed_(false),
+ was_ever_used_(false),
host_and_port_(host_and_port),
ssl_config_(ssl_config),
nss_fd_(NULL),
@@ -1015,7 +1008,13 @@ bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket,
DCHECK_EQ(dst, wire_protos.get() + wire_length);
rv = SSL_SetNextProtoNego(nss_fd_, wire_protos.get(), wire_length);
if (rv != SECSuccess)
- LogFailedNSSFunction(*weak_net_log_, "SSL_SetNextProtoCallback", "");
+ LogFailedNSSFunction(*weak_net_log_, "SSL_SetNextProtoNego", "");
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_ALPN, PR_TRUE);
+ if (rv != SECSuccess)
+ LogFailedNSSFunction(*weak_net_log_, "SSL_OptionSet", "SSL_ENABLE_ALPN");
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_NPN, PR_TRUE);
+ if (rv != SECSuccess)
+ LogFailedNSSFunction(*weak_net_log_, "SSL_OptionSet", "SSL_ENABLE_NPN");
}
rv = SSL_AuthCertificateHook(
@@ -1064,57 +1063,6 @@ bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket,
return true;
}
-void SSLClientSocketNSS::Core::SetPredictedCertificates(
- const std::vector<std::string>& predicted_certs) {
- if (predicted_certs.empty())
- return;
-
- if (!OnNSSTaskRunner()) {
- DCHECK(!detached_);
- nss_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&Core::SetPredictedCertificates, this, predicted_certs));
- return;
- }
-
- DCHECK(nss_fd_);
-
- predicted_certs_ = predicted_certs;
-
- scoped_ptr<CERTCertificate*[]> certs(
- new CERTCertificate*[predicted_certs.size()]);
-
- for (size_t i = 0; i < predicted_certs.size(); i++) {
- SECItem derCert;
- derCert.data = const_cast<uint8*>(reinterpret_cast<const uint8*>(
- predicted_certs[i].data()));
- derCert.len = predicted_certs[i].size();
- certs[i] = CERT_NewTempCertificate(
- CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */,
- PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */);
- if (!certs[i]) {
- DestroyCertificates(&certs[0], i);
- NOTREACHED();
- return;
- }
- }
-
- SECStatus rv;
-#ifdef SSL_ENABLE_CACHED_INFO
- rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(),
- predicted_certs.size());
- DCHECK_EQ(SECSuccess, rv);
-#else
- rv = SECFailure; // Not implemented.
-#endif
- DestroyCertificates(&certs[0], predicted_certs.size());
-
- if (rv != SECSuccess) {
- LOG(WARNING) << "SetPredictedCertificates failed: "
- << host_and_port_.ToString();
- }
-}
-
int SSLClientSocketNSS::Core::Connect(const CompletionCallback& callback) {
if (!OnNSSTaskRunner()) {
DCHECK(!detached_);
@@ -1205,8 +1153,11 @@ int SSLClientSocketNSS::Core::Read(IOBuffer* buf, int buf_len,
return ERR_IO_PENDING;
} else {
DCHECK(!nss_waiting_read_);
- if (rv <= 0)
+ if (rv <= 0) {
nss_is_closed_ = true;
+ } else {
+ was_ever_used_ = true;
+ }
}
}
@@ -1259,29 +1210,37 @@ int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
return ERR_IO_PENDING;
} else {
DCHECK(!nss_waiting_write_);
- if (rv < 0)
+ if (rv < 0) {
nss_is_closed_ = true;
+ } else if (rv > 0) {
+ was_ever_used_ = true;
+ }
}
}
return rv;
}
-bool SSLClientSocketNSS::Core::IsConnected() {
+bool SSLClientSocketNSS::Core::IsConnected() const {
DCHECK(OnNetworkTaskRunner());
return !nss_is_closed_;
}
-bool SSLClientSocketNSS::Core::HasPendingAsyncOperation() {
+bool SSLClientSocketNSS::Core::HasPendingAsyncOperation() const {
DCHECK(OnNetworkTaskRunner());
return nss_waiting_read_ || nss_waiting_write_;
}
-bool SSLClientSocketNSS::Core::HasUnhandledReceivedData() {
+bool SSLClientSocketNSS::Core::HasUnhandledReceivedData() const {
DCHECK(OnNetworkTaskRunner());
return unhandled_buffer_size_ != 0;
}
+bool SSLClientSocketNSS::Core::WasEverUsed() const {
+ DCHECK(OnNetworkTaskRunner());
+ return was_ever_used_;
+}
+
void SSLClientSocketNSS::Core::CacheSessionIfNecessary() {
// TODO(rsleevi): This should occur on the NSS task runner, due to the use of
// nss_fd_. However, it happens on the network task runner in order to match
@@ -2184,7 +2143,12 @@ int SSLClientSocketNSS::Core::BufferSend() {
const char* buf1;
const char* buf2;
unsigned int len1, len2;
- memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
+ if (memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2)) {
+ // It is important this return synchronously to prevent spinning infinitely
+ // in the off-thread NSS case. The error code itself is ignored, so just
+ // return ERR_ABORTED. See https://crbug.com/381160.
+ return ERR_ABORTED;
+ }
const unsigned int len = len1 + len2;
int rv = 0;
@@ -2450,9 +2414,14 @@ void SSLClientSocketNSS::Core::UpdateSignedCertTimestamps() {
}
void SSLClientSocketNSS::Core::UpdateStapledOCSPResponse() {
+ PRBool ocsp_requested = PR_FALSE;
+ SSL_OptionGet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, &ocsp_requested);
const SECItemArray* ocsp_responses =
SSL_PeerStapledOCSPResponses(nss_fd_);
- if (!ocsp_responses || !ocsp_responses->len)
+ bool ocsp_responses_present = ocsp_responses && ocsp_responses->len;
+ if (ocsp_requested)
+ UMA_HISTOGRAM_BOOLEAN("Net.OCSPResponseStapled", ocsp_responses_present);
+ if (!ocsp_responses_present)
return;
nss_handshake_state_.stapled_ocsp_response = std::string(
@@ -2708,16 +2677,22 @@ void SSLClientSocketNSS::Core::DidNSSRead(int result) {
DCHECK(OnNetworkTaskRunner());
DCHECK(nss_waiting_read_);
nss_waiting_read_ = false;
- if (result <= 0)
+ if (result <= 0) {
nss_is_closed_ = true;
+ } else {
+ was_ever_used_ = true;
+ }
}
void SSLClientSocketNSS::Core::DidNSSWrite(int result) {
DCHECK(OnNetworkTaskRunner());
DCHECK(nss_waiting_write_);
nss_waiting_write_ = false;
- if (result < 0)
+ if (result < 0) {
nss_is_closed_ = true;
+ } else if (result > 0) {
+ was_ever_used_ = true;
+ }
}
void SSLClientSocketNSS::Core::BufferSendComplete(int result) {
@@ -2884,15 +2859,12 @@ bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->connection_status =
core_->state().ssl_connection_status;
ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes;
- for (HashValueVector::const_iterator i = side_pinned_public_keys_.begin();
- i != side_pinned_public_keys_.end(); ++i) {
- ssl_info->public_key_hashes.push_back(*i);
- }
ssl_info->is_issued_by_known_root =
server_cert_verify_result_.is_issued_by_known_root;
ssl_info->client_cert_sent =
ssl_config_.send_client_cert && ssl_config_.client_cert.get();
ssl_info->channel_id_sent = WasChannelIDSent();
+ ssl_info->pinning_failure_log = pinning_failure_log_;
PRUint16 cipher_suite = SSLConnectionStatusToCipherSuite(
core_->state().ssl_connection_status);
@@ -2917,8 +2889,7 @@ bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
void SSLClientSocketNSS::GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) {
EnterFunction("");
- // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair
- cert_request_info->host_and_port = host_and_port_.ToString();
+ cert_request_info->host_and_port = host_and_port_;
cert_request_info->cert_authorities = core_->state().cert_authorities;
LeaveFunction("");
}
@@ -3082,11 +3053,9 @@ void SSLClientSocketNSS::SetOmniboxSpeculation() {
}
bool SSLClientSocketNSS::WasEverUsed() const {
- if (transport_.get() && transport_->socket()) {
- return transport_->socket()->WasEverUsed();
- }
- NOTREACHED();
- return false;
+ DCHECK(core_.get());
+
+ return core_->WasEverUsed();
}
bool SSLClientSocketNSS::UsingTCPFastOpen() const {
@@ -3121,11 +3090,11 @@ int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len,
return rv;
}
-bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) {
+int SSLClientSocketNSS::SetReceiveBufferSize(int32 size) {
return transport_->socket()->SetReceiveBufferSize(size);
}
-bool SSLClientSocketNSS::SetSendBufferSize(int32 size) {
+int SSLClientSocketNSS::SetSendBufferSize(int32 size) {
return transport_->socket()->SetSendBufferSize(size);
}
@@ -3273,14 +3242,6 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
"SSL_ENABLE_SIGNED_CERT_TIMESTAMPS");
}
-// Chromium patch to libssl
-#ifdef SSL_ENABLE_CACHED_INFO
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_CACHED_INFO,
- ssl_config_.cached_info_enabled);
- if (rv != SECSuccess)
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_CACHED_INFO");
-#endif
-
rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
if (rv != SECSuccess) {
LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
@@ -3308,7 +3269,7 @@ int SSLClientSocketNSS::InitializeSSLPeerName() {
SockaddrStorage storage;
if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len))
- return ERR_UNEXPECTED;
+ return ERR_ADDRESS_INVALID;
PRNetAddr peername;
memset(&peername, 0, sizeof(peername));
@@ -3541,12 +3502,13 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
ssl_config_.version_fallback;
const std::string& host = host_and_port_.host();
- TransportSecurityState::DomainState domain_state;
- if (transport_security_state_->GetDomainState(host, sni_available,
- &domain_state) &&
- domain_state.HasPublicKeyPins()) {
- if (!domain_state.CheckPublicKeyPins(
- server_cert_verify_result_.public_key_hashes)) {
+ if (transport_security_state_->HasPublicKeyPins(host, sni_available)) {
+ if (!transport_security_state_->CheckPublicKeyPins(
+ host,
+ sni_available,
+ server_cert_verify_result_.public_key_hashes,
+ &pinning_failure_log_)) {
+ LOG(ERROR) << pinning_failure_log_;
result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", false);
TransportSecurityState::ReportUMAOnPinFailure(host);
@@ -3654,6 +3616,11 @@ void SSLClientSocketNSS::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const {
}
}
+scoped_refptr<X509Certificate>
+SSLClientSocketNSS::GetUnverifiedServerCertificateChain() const {
+ return core_->state().server_cert.get();
+}
+
ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const {
return server_bound_cert_service_;
}