Chromium Code Reviews| Index: net/socket/ssl_client_socket_nss.cc |
| =================================================================== |
| --- net/socket/ssl_client_socket_nss.cc (revision 222312) |
| +++ net/socket/ssl_client_socket_nss.cc (working copy) |
| @@ -711,9 +711,14 @@ |
| SECKEYPrivateKey** result_private_key); |
| #endif |
| - // Called by NSS once the handshake has completed. |
| + // Called once the handshake has completed. |
| + void HandshakeSucceeded(); |
| + |
| + // Called by NSS to determine if we can false start. |
|
agl
2013/09/13 15:03:29
In other comments, "false start" is written as "Fa
wtc
2013/09/18 22:57:23
Done.
|
| // |arg| contains a pointer to the current SSLClientSocketNSS::Core. |
| - static void HandshakeCallback(PRFileDesc* socket, void* arg); |
| + static SECStatus CanFalseStartCallback(PRFileDesc* socket, |
| + void* arg, |
| + PRBool* can_false_start); |
| // Handles an NSS error generated while handshaking or performing IO. |
| // Returns a network error code mapped from the original NSS error. |
| @@ -866,8 +871,6 @@ |
| bool channel_id_needed_; |
| // True if the handshake state machine was interrupted for client auth. |
| bool client_auth_cert_needed_; |
| - // True if NSS has called HandshakeCallback. |
| - bool handshake_callback_called_; |
| HandshakeState nss_handshake_state_; |
| @@ -934,7 +937,6 @@ |
| channel_id_xtn_negotiated_(false), |
| channel_id_needed_(false), |
| client_auth_cert_needed_(false), |
| - handshake_callback_called_(false), |
| transport_recv_busy_(false), |
| transport_recv_eof_(false), |
| transport_send_busy_(false), |
| @@ -1029,10 +1031,10 @@ |
| } |
| } |
| - rv = SSL_HandshakeCallback( |
| - nss_fd_, SSLClientSocketNSS::Core::HandshakeCallback, this); |
| + rv = SSL_SetCanFalseStartCallback( |
| + nss_fd_, SSLClientSocketNSS::Core::CanFalseStartCallback, this); |
| if (rv != SECSuccess) { |
| - LogFailedNSSFunction(*weak_net_log_, "SSL_HandshakeCallback", ""); |
| + LogFailedNSSFunction(*weak_net_log_, "SSL_SetCanFalseStartCallback", ""); |
| return false; |
| } |
| @@ -1155,7 +1157,6 @@ |
| } |
| DCHECK(OnNSSTaskRunner()); |
| - DCHECK(handshake_callback_called_); |
| DCHECK_EQ(STATE_NONE, next_handshake_state_); |
| DCHECK(user_read_callback_.is_null()); |
| DCHECK(user_connect_callback_.is_null()); |
| @@ -1209,7 +1210,6 @@ |
| } |
| DCHECK(OnNSSTaskRunner()); |
| - DCHECK(handshake_callback_called_); |
| DCHECK_EQ(STATE_NONE, next_handshake_state_); |
| DCHECK(user_write_callback_.is_null()); |
| DCHECK(user_connect_callback_.is_null()); |
| @@ -1271,28 +1271,6 @@ |
| PRFileDesc* socket, |
| PRBool checksig, |
| PRBool is_server) { |
| - Core* core = reinterpret_cast<Core*>(arg); |
| - if (!core->handshake_callback_called_) { |
| - // Only need to turn off False Start in the initial handshake. Also, it is |
| - // unsafe to call SSL_OptionSet in a renegotiation because the "first |
| - // handshake" lock isn't already held, which will result in an assertion |
| - // failure in the ssl_Get1stHandshakeLock call in SSL_OptionSet. |
| - PRBool negotiated_extension; |
| - SECStatus rv = SSL_HandshakeNegotiatedExtension(socket, |
| - ssl_app_layer_protocol_xtn, |
| - &negotiated_extension); |
| - if (rv != SECSuccess || !negotiated_extension) { |
| - rv = SSL_HandshakeNegotiatedExtension(socket, |
| - ssl_next_proto_nego_xtn, |
| - &negotiated_extension); |
| - } |
| - if (rv != SECSuccess || !negotiated_extension) { |
| - // If the server doesn't support NPN or ALPN, then we don't do False |
| - // Start with it. |
| - SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE); |
| - } |
| - } |
| - |
| // Tell NSS to not verify the certificate. |
| return SECSuccess; |
| } |
| @@ -1605,37 +1583,53 @@ |
| } |
| #endif // NSS_PLATFORM_CLIENT_AUTH |
| -// static |
| -void SSLClientSocketNSS::Core::HandshakeCallback( |
| - PRFileDesc* socket, |
| - void* arg) { |
| - Core* core = reinterpret_cast<Core*>(arg); |
| - DCHECK(core->OnNSSTaskRunner()); |
| +void SSLClientSocketNSS::Core::HandshakeSucceeded() { |
| + DCHECK(OnNSSTaskRunner()); |
| - core->handshake_callback_called_ = true; |
| - |
| - HandshakeState* nss_state = &core->nss_handshake_state_; |
| - |
| PRBool last_handshake_resumed; |
| - SECStatus rv = SSL_HandshakeResumedSession(socket, &last_handshake_resumed); |
| + SECStatus rv = SSL_HandshakeResumedSession(nss_fd_, &last_handshake_resumed); |
| if (rv == SECSuccess && last_handshake_resumed) { |
| - nss_state->resumed_handshake = true; |
| + nss_handshake_state_.resumed_handshake = true; |
| } else { |
| - nss_state->resumed_handshake = false; |
| + nss_handshake_state_.resumed_handshake = false; |
| } |
| - core->RecordChannelIDSupport(); |
| - core->UpdateServerCert(); |
| - core->UpdateConnectionStatus(); |
| - core->UpdateNextProto(); |
| + RecordChannelIDSupport(); |
| + UpdateServerCert(); |
| + UpdateConnectionStatus(); |
| + UpdateNextProto(); |
| // Update the network task runners view of the handshake state whenever |
| // a handshake has completed. |
| - core->PostOrRunCallback( |
| - FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core, |
| - *nss_state)); |
| + PostOrRunCallback( |
| + FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this, |
| + nss_handshake_state_)); |
| } |
| +// static |
| +SECStatus SSLClientSocketNSS::Core::CanFalseStartCallback( |
| + PRFileDesc* socket, |
| + void* arg, |
| + PRBool* can_false_start) { |
| + // If the server doesn't support NPN or ALPN, then we don't do False Start |
| + // with it. |
| + PRBool negotiated_extension; |
| + SECStatus rv = SSL_HandshakeNegotiatedExtension(socket, |
| + ssl_app_layer_protocol_xtn, |
| + &negotiated_extension); |
| + if (rv != SECSuccess || !negotiated_extension) { |
| + rv = SSL_HandshakeNegotiatedExtension(socket, |
| + ssl_next_proto_nego_xtn, |
| + &negotiated_extension); |
| + } |
| + if (rv != SECSuccess || !negotiated_extension) { |
| + *can_false_start = PR_FALSE; |
| + return SECSuccess; |
| + } |
| + |
| + return SSL_DefaultCanFalseStart(socket, can_false_start); |
| +} |
| + |
| int SSLClientSocketNSS::Core::HandleNSSError(PRErrorCode nss_error, |
| bool handshake_error) { |
| DCHECK(OnNSSTaskRunner()); |
| @@ -1708,7 +1702,6 @@ |
| int SSLClientSocketNSS::Core::DoReadLoop(int result) { |
| DCHECK(OnNSSTaskRunner()); |
| - DCHECK(handshake_callback_called_); |
| DCHECK_EQ(STATE_NONE, next_handshake_state_); |
| if (result < 0) |
| @@ -1737,7 +1730,6 @@ |
| int SSLClientSocketNSS::Core::DoWriteLoop(int result) { |
| DCHECK(OnNSSTaskRunner()); |
| - DCHECK(handshake_callback_called_); |
| DCHECK_EQ(STATE_NONE, next_handshake_state_); |
| if (result < 0) |
| @@ -1793,52 +1785,41 @@ |
| if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) |
| LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError(); |
| } else if (rv == SECSuccess) { |
| - if (!handshake_callback_called_) { |
| - // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=562434 - |
| - // SSL_ForceHandshake returned SECSuccess prematurely. |
| - rv = SECFailure; |
| - net_error = ERR_SSL_PROTOCOL_ERROR; |
| - PostOrRunCallback( |
| - FROM_HERE, |
| - base::Bind(&AddLogEventWithCallback, weak_net_log_, |
| - NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
| - CreateNetLogSSLErrorCallback(net_error, 0))); |
| - } else { |
| + HandshakeSucceeded(); |
| #if defined(SSL_ENABLE_OCSP_STAPLING) |
| - // TODO(agl): figure out how to plumb an OCSP response into the Mac |
| - // system library and update IsOCSPStaplingSupported for Mac. |
| - if (IsOCSPStaplingSupported()) { |
| - const SECItemArray* ocsp_responses = |
| - SSL_PeerStapledOCSPResponses(nss_fd_); |
| - if (ocsp_responses->len) { |
| + // TODO(agl): figure out how to plumb an OCSP response into the Mac |
| + // system library and update IsOCSPStaplingSupported for Mac. |
| + if (IsOCSPStaplingSupported()) { |
| + const SECItemArray* ocsp_responses = |
| + SSL_PeerStapledOCSPResponses(nss_fd_); |
| + if (ocsp_responses->len) { |
| #if defined(OS_WIN) |
| - if (nss_handshake_state_.server_cert) { |
| - CRYPT_DATA_BLOB ocsp_response_blob; |
| - ocsp_response_blob.cbData = ocsp_responses->items[0].len; |
| - ocsp_response_blob.pbData = ocsp_responses->items[0].data; |
| - BOOL ok = CertSetCertificateContextProperty( |
| - nss_handshake_state_.server_cert->os_cert_handle(), |
| - CERT_OCSP_RESPONSE_PROP_ID, |
| - CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, |
| - &ocsp_response_blob); |
| - if (!ok) { |
| - VLOG(1) << "Failed to set OCSP response property: " |
| - << GetLastError(); |
| - } |
| + if (nss_handshake_state_.server_cert) { |
| + CRYPT_DATA_BLOB ocsp_response_blob; |
| + ocsp_response_blob.cbData = ocsp_responses->items[0].len; |
| + ocsp_response_blob.pbData = ocsp_responses->items[0].data; |
| + BOOL ok = CertSetCertificateContextProperty( |
| + nss_handshake_state_.server_cert->os_cert_handle(), |
| + CERT_OCSP_RESPONSE_PROP_ID, |
| + CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, |
| + &ocsp_response_blob); |
| + if (!ok) { |
| + VLOG(1) << "Failed to set OCSP response property: " |
| + << GetLastError(); |
| } |
| + } |
| #elif defined(USE_NSS) |
| - CacheOCSPResponseFromSideChannelFunction cache_ocsp_response = |
| - GetCacheOCSPResponseFromSideChannelFunction(); |
| + CacheOCSPResponseFromSideChannelFunction cache_ocsp_response = |
| + GetCacheOCSPResponseFromSideChannelFunction(); |
| - cache_ocsp_response( |
| - CERT_GetDefaultCertDB(), |
| - nss_handshake_state_.server_cert_chain[0], PR_Now(), |
| - &ocsp_responses->items[0], NULL); |
| + cache_ocsp_response( |
| + CERT_GetDefaultCertDB(), |
| + nss_handshake_state_.server_cert_chain[0], PR_Now(), |
| + &ocsp_responses->items[0], NULL); |
| #endif |
| - } |
| } |
| - #endif |
| } |
| + #endif |
| // Done! |
| } else { |
| PRErrorCode prerr = PR_GetError(); |