// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/socket/ssl_client_socket.h" #include #include "base/logging.h" #include "net/socket/ssl_client_socket_impl.h" #include "net/socket/stream_socket.h" #include "net/ssl/ssl_client_session_cache.h" #include "net/ssl/ssl_key_logger.h" namespace net { SSLClientSocket::SSLClientSocket() : signed_cert_timestamps_received_(false), stapled_ocsp_response_received_(false) {} // static void SSLClientSocket::SetSSLKeyLogger(std::unique_ptr logger) { SSLClientSocketImpl::SetSSLKeyLogger(std::move(logger)); } // static std::vector SSLClientSocket::SerializeNextProtos( const NextProtoVector& next_protos) { std::vector wire_protos; for (const NextProto next_proto : next_protos) { const std::string proto = NextProtoToString(next_proto); if (proto.size() > 255) { LOG(WARNING) << "Ignoring overlong ALPN protocol: " << proto; continue; } if (proto.size() == 0) { LOG(WARNING) << "Ignoring empty ALPN protocol"; continue; } wire_protos.push_back(proto.size()); for (const char ch : proto) { wire_protos.push_back(static_cast(ch)); } } return wire_protos; } SSLClientContext::SSLClientContext( SSLConfigService* ssl_config_service, CertVerifier* cert_verifier, TransportSecurityState* transport_security_state, CTVerifier* cert_transparency_verifier, CTPolicyEnforcer* ct_policy_enforcer, SSLClientSessionCache* ssl_client_session_cache) : ssl_config_service_(ssl_config_service), cert_verifier_(cert_verifier), transport_security_state_(transport_security_state), cert_transparency_verifier_(cert_transparency_verifier), ct_policy_enforcer_(ct_policy_enforcer), ssl_client_session_cache_(ssl_client_session_cache) { CHECK(cert_verifier_); CHECK(transport_security_state_); CHECK(cert_transparency_verifier_); CHECK(ct_policy_enforcer_); if (ssl_config_service_) { config_ = ssl_config_service_->GetSSLContextConfig(); ssl_config_service_->AddObserver(this); } CertDatabase::GetInstance()->AddObserver(this); } SSLClientContext::~SSLClientContext() { if (ssl_config_service_) { ssl_config_service_->RemoveObserver(this); } CertDatabase::GetInstance()->RemoveObserver(this); } std::unique_ptr SSLClientContext::CreateSSLClientSocket( std::unique_ptr stream_socket, const HostPortPair& host_and_port, const SSLConfig& ssl_config) { return std::make_unique(this, std::move(stream_socket), host_and_port, ssl_config); } bool SSLClientContext::GetClientCertificate( const HostPortPair& server, scoped_refptr* client_cert, scoped_refptr* private_key) { return ssl_client_auth_cache_.Lookup(server, client_cert, private_key); } void SSLClientContext::SetClientCertificate( const HostPortPair& server, scoped_refptr client_cert, scoped_refptr private_key) { ssl_client_auth_cache_.Add(server, std::move(client_cert), std::move(private_key)); if (ssl_client_session_cache_) { // Session resumption bypasses client certificate negotiation, so flush all // associated sessions when preferences change. ssl_client_session_cache_->FlushForServer(server); } NotifySSLConfigForServerChanged(server); } bool SSLClientContext::ClearClientCertificate(const HostPortPair& server) { if (!ssl_client_auth_cache_.Remove(server)) { return false; } if (ssl_client_session_cache_) { // Session resumption bypasses client certificate negotiation, so flush all // associated sessions when preferences change. ssl_client_session_cache_->FlushForServer(server); } NotifySSLConfigForServerChanged(server); return true; } void SSLClientContext::AddObserver(Observer* observer) { observers_.AddObserver(observer); } void SSLClientContext::RemoveObserver(Observer* observer) { observers_.RemoveObserver(observer); } void SSLClientContext::OnSSLContextConfigChanged() { // TODO(davidben): Should we flush |ssl_client_session_cache_| here? We flush // the socket pools, but not the session cache. While BoringSSL-based servers // never change version or cipher negotiation based on client-offered // sessions, other servers do. config_ = ssl_config_service_->GetSSLContextConfig(); NotifySSLConfigChanged(false /* not a cert database change */); } void SSLClientContext::OnCertDBChanged() { // Both the trust store and client certificate store may have changed. ssl_client_auth_cache_.Clear(); if (ssl_client_session_cache_) { ssl_client_session_cache_->Flush(); } NotifySSLConfigChanged(true /* cert database change */); } void SSLClientContext::NotifySSLConfigChanged(bool is_cert_database_change) { for (Observer& observer : observers_) { observer.OnSSLConfigChanged(is_cert_database_change); } } void SSLClientContext::NotifySSLConfigForServerChanged( const HostPortPair& server) { for (Observer& observer : observers_) { observer.OnSSLConfigForServerChanged(server); } } } // namespace net