| Index: net/socket/ssl_client_socket_nss.cc
|
| diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
|
| index 60f03240ab9e07f0496a1ffd71a6ec0c5cab599a..554d8d7119bfa733fde7d3031f66217d4359919c 100644
|
| --- a/net/socket/ssl_client_socket_nss.cc
|
| +++ b/net/socket/ssl_client_socket_nss.cc
|
| @@ -93,6 +93,7 @@
|
| #include "net/cert/asn1_util.h"
|
| #include "net/cert/cert_status_flags.h"
|
| #include "net/cert/cert_verifier.h"
|
| +#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.h"
|
| @@ -2751,6 +2752,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(
|
| nss_fd_(NULL),
|
| net_log_(transport_->socket()->NetLog()),
|
| transport_security_state_(context.transport_security_state),
|
| + cert_transparency_verifier_(context.cert_transparency_verifier),
|
| valid_thread_id_(base::kInvalidThreadId) {
|
| EnterFunction("");
|
| InitCore();
|
| @@ -3271,6 +3273,12 @@ int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
|
| case STATE_VERIFY_CERT_COMPLETE:
|
| rv = DoVerifyCertComplete(rv);
|
| break;
|
| + case STATE_VERIFY_CT:
|
| + rv = DoVerifyCT(rv);
|
| + break;
|
| + case STATE_VERIFY_CT_COMPLETE:
|
| + rv = DoVerifyCTComplete(rv);
|
| + break;
|
| case STATE_NONE:
|
| default:
|
| rv = ERR_UNEXPECTED;
|
| @@ -3307,7 +3315,6 @@ int SSLClientSocketNSS::DoHandshakeComplete(int result) {
|
| return result;
|
| }
|
|
|
| -
|
| int SSLClientSocketNSS::DoVerifyCert(int result) {
|
| DCHECK(!core_->state().server_cert_chain.empty());
|
| DCHECK(core_->state().server_cert_chain[0]);
|
| @@ -3391,8 +3398,6 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
|
| if (result == OK)
|
| LogConnectionTypeMetrics();
|
|
|
| - completed_handshake_ = true;
|
| -
|
| #if defined(OFFICIAL_BUILD) && !defined(OS_ANDROID) && !defined(OS_IOS)
|
| // Take care of any mandates for public key pinning.
|
| //
|
| @@ -3440,11 +3445,72 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
|
| }
|
| #endif
|
|
|
| + if (result == OK) {
|
| + // Only check Certificate Transparency if there were no other errors with
|
| + // the connection.
|
| + GotoState(STATE_VERIFY_CT);
|
| + return OK;
|
| + }
|
| +
|
| + completed_handshake_ = true;
|
| +
|
| // Exit DoHandshakeLoop and return the result to the caller to Connect.
|
| DCHECK_EQ(STATE_NONE, next_handshake_state_);
|
| return result;
|
| }
|
|
|
| +int SSLClientSocketNSS::DoVerifyCT(int result) {
|
| + GotoState(STATE_VERIFY_CT_COMPLETE);
|
| +
|
| + if (!cert_transparency_verifier_)
|
| + return OK;
|
| +
|
| + // XXX(rsleevi): Not actually async-safe (using base::Unretained and giving
|
| + // the raw pointer up). Need to use WeakPtr<> so that this can be cancelled,
|
| + // but without requiring the opaque request handles of CertVerifier.
|
| + return cert_transparency_verifier_->Verify(
|
| + core_->state().server_cert,
|
| + server_cert_verify_result_.verified_cert,
|
| + &ct_verify_result_,
|
| + base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
|
| + base::Unretained(this)),
|
| + net_log_);
|
| +}
|
| +
|
| +int SSLClientSocketNSS::DoVerifyCTComplete(int result) {
|
| + VLOG(1) << "CT Verification complete: result " << result <<
|
| + " Unverified scts: " << ct_verify_result_.unverified_scts.size() <<
|
| + " Verified scts: " << ct_verify_result_.verified_scts.size() <<
|
| + " scts from unknown logs: " <<
|
| + ct_verify_result_.unknown_logs_scts.size();
|
| + if (ct_verify_result_.unverified_scts.empty() &&
|
| + ct_verify_result_.unknown_logs_scts.empty() &&
|
| + ct_verify_result_.verified_scts.empty()) {
|
| + return OK;
|
| + }
|
| +
|
| + // XXX(eranm): Saving CT state in cert_status bits is a temporary solution,
|
| + // until the SCTs themselves are threaded into the SSLInfo (as well as into
|
| + // the HTTP cache). Using a status flag is a cheap way to persist the
|
| + // SCT status.
|
| + server_cert_verify_result_.cert_status |= CERT_STATUS_HAS_ANY_SCT;
|
| +
|
| + if (!ct_verify_result_.verified_scts.empty() && result == OK) {
|
| + // Found some valid SCTs - good
|
| + server_cert_verify_result_.cert_status |=
|
| + CERT_STATUS_HAS_VALID_SCT | CERT_STATUS_HAS_SCT_FROM_KNOWN_LOG;
|
| + } else if (!ct_verify_result_.unverified_scts.empty()) {
|
| + server_cert_verify_result_.cert_status |=
|
| + CERT_STATUS_HAS_SCT_FROM_KNOWN_LOG;
|
| + }
|
| +
|
| + completed_handshake_ = true;
|
| +
|
| + DCHECK_EQ(STATE_NONE, next_handshake_state_);
|
| +
|
| + return OK;
|
| +}
|
| +
|
| void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
|
| UpdateConnectionTypeHistograms(CONNECTION_SSL);
|
| int ssl_version = SSLConnectionStatusToVersion(
|
|
|