| Index: net/socket/ssl_client_socket_nss.cc
|
| ===================================================================
|
| --- net/socket/ssl_client_socket_nss.cc (revision 89911)
|
| +++ net/socket/ssl_client_socket_nss.cc (working copy)
|
| @@ -585,7 +585,11 @@
|
| }
|
| }
|
|
|
| - GotoState(STATE_HANDSHAKE);
|
| + if (ssl_config_.cached_info_enabled && ssl_host_info_.get()) {
|
| + GotoState(STATE_LOAD_SSL_HOST_INFO);
|
| + } else {
|
| + GotoState(STATE_HANDSHAKE);
|
| + }
|
|
|
| rv = DoHandshakeLoop(OK);
|
| if (rv == ERR_IO_PENDING) {
|
| @@ -916,11 +920,20 @@
|
| #ifdef SSL_ENABLE_OCSP_STAPLING
|
| if (IsOCSPStaplingSupported()) {
|
| rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
|
| - if (rv != SECSuccess)
|
| - LogFailedNSSFunction(net_log_, "SSL_OptionSet (OCSP stapling)", "");
|
| + if (rv != SECSuccess) {
|
| + LogFailedNSSFunction(net_log_, "SSL_OptionSet",
|
| + "SSL_ENABLE_OCSP_STAPLING");
|
| + }
|
| }
|
| #endif
|
|
|
| +#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");
|
| @@ -1202,6 +1215,9 @@
|
| case STATE_NONE:
|
| // we're just pumping data between the buffer and the network
|
| break;
|
| + case STATE_LOAD_SSL_HOST_INFO:
|
| + rv = DoLoadSSLHostInfo();
|
| + break;
|
| case STATE_HANDSHAKE:
|
| rv = DoHandshake();
|
| break;
|
| @@ -1283,6 +1299,57 @@
|
| return rv;
|
| }
|
|
|
| +bool SSLClientSocketNSS::LoadSSLHostInfo() {
|
| + const SSLHostInfo::State& state(ssl_host_info_->state());
|
| +
|
| + if (state.certs.empty())
|
| + return false;
|
| +
|
| + SECStatus rv;
|
| + const std::vector<std::string>& certs_in = state.certs;
|
| + scoped_array<CERTCertificate*> certs(new CERTCertificate*[certs_in.size()]);
|
| +
|
| + for (size_t i = 0; i < certs_in.size(); i++) {
|
| + SECItem derCert;
|
| + derCert.data =
|
| + const_cast<uint8*>(reinterpret_cast<const uint8*>(certs_in[i].data()));
|
| + derCert.len = certs_in[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 false;
|
| + }
|
| + }
|
| +
|
| + rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), certs_in.size());
|
| + DestroyCertificates(&certs[0], certs_in.size());
|
| + DCHECK_EQ(SECSuccess, rv);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +int SSLClientSocketNSS::DoLoadSSLHostInfo() {
|
| + int rv;
|
| +
|
| + EnterFunction("");
|
| + rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_);
|
| + GotoState(STATE_HANDSHAKE);
|
| +
|
| + if (rv == OK) {
|
| + if (!LoadSSLHostInfo())
|
| + LOG(WARNING) << "LoadSSLHostInfo failed: " << host_and_port_.ToString();
|
| + } else {
|
| + DCHECK_EQ(ERR_IO_PENDING, rv);
|
| + GotoState(STATE_LOAD_SSL_HOST_INFO);
|
| + }
|
| +
|
| + LeaveFunction("");
|
| + return rv;
|
| +}
|
| +
|
| int SSLClientSocketNSS::DoHandshake() {
|
| EnterFunction("");
|
| int net_error = net::OK;
|
| @@ -1307,7 +1374,8 @@
|
| } else {
|
| // We need to see if the predicted certificate chain (in
|
| // |ssl_host_info_->state().certs) matches the actual certificate chain
|
| - // before we try to save it before we update |ssl_host_info_|.
|
| + // before we call SaveSSLHostInfo, as that will update
|
| + // |ssl_host_info_|.
|
| if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) {
|
| PeerCertificateChain certs(nss_fd_);
|
| const SSLHostInfo::State& state = ssl_host_info_->state();
|
|
|