diff options
author | rtenneti <rtenneti@chromium.org> | 2014-09-18 15:18:35 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-18 22:19:39 +0000 |
commit | c584fb92ddd78cb2c2a36b90f0d7be30227d3cff (patch) | |
tree | d9591bc420358946011d093460e02c6a61a423ed /net | |
parent | f4cc5195cd3708c709dfe06f037010d82548f9d1 (diff) | |
download | chromium_src-c584fb92ddd78cb2c2a36b90f0d7be30227d3cff.zip chromium_src-c584fb92ddd78cb2c2a36b90f0d7be30227d3cff.tar.gz chromium_src-c584fb92ddd78cb2c2a36b90f0d7be30227d3cff.tar.bz2 |
Persist the server config that is received via kSCUP.
R=rjshade@chromium.org, rch@chromium.org, asvitkine@chromium.org, rvargas@chromium.org
Review URL: https://codereview.chromium.org/427313002
Cr-Commit-Position: refs/heads/master@{#295582}
Diffstat (limited to 'net')
-rw-r--r-- | net/http/disk_cache_based_quic_server_info.cc | 11 | ||||
-rw-r--r-- | net/quic/quic_crypto_client_stream.cc | 141 | ||||
-rw-r--r-- | net/quic/quic_crypto_client_stream.h | 17 |
3 files changed, 121 insertions, 48 deletions
diff --git a/net/http/disk_cache_based_quic_server_info.cc b/net/http/disk_cache_based_quic_server_info.cc index 51fba21..13c53b7 100644 --- a/net/http/disk_cache_based_quic_server_info.cc +++ b/net/http/disk_cache_based_quic_server_info.cc @@ -213,7 +213,9 @@ int DiskCacheBasedQuicServerInfo::DoReadComplete(int rv) { } int DiskCacheBasedQuicServerInfo::DoWriteComplete(int rv) { - state_ = SET_DONE; + // Keep the entry open for future writes. + new_data_.clear(); + state_ = NONE; return OK; } @@ -221,7 +223,8 @@ int DiskCacheBasedQuicServerInfo::DoCreateOrOpenComplete(int rv) { if (rv != OK) { state_ = SET_DONE; } else { - entry_ = data_shim_->entry; + if (!entry_) + entry_ = data_shim_->entry; state_ = WRITE; } return OK; @@ -264,8 +267,10 @@ int DiskCacheBasedQuicServerInfo::DoWrite() { } int DiskCacheBasedQuicServerInfo::DoCreateOrOpen() { - DCHECK(entry_ == NULL); state_ = CREATE_OR_OPEN_COMPLETE; + if (entry_) + return OK; + if (found_entry_) { return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_); } diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc index 40e4d45..4d9d032 100644 --- a/net/quic/quic_crypto_client_stream.cc +++ b/net/quic/quic_crypto_client_stream.cc @@ -4,6 +4,7 @@ #include "net/quic/quic_crypto_client_stream.h" +#include "base/metrics/histogram.h" #include "net/quic/crypto/crypto_protocol.h" #include "net/quic/crypto/crypto_utils.h" #include "net/quic/crypto/null_encrypter.h" @@ -156,6 +157,13 @@ void QuicCryptoClientStream::HandleServerConfigUpdateMessage( error, "Server config update invalid: " + error_details); return; } + + DCHECK(handshake_confirmed()); + if (proof_verify_callback_) { + proof_verify_callback_->Cancel(); + } + next_state_ = STATE_INITIALIZE_SCUP; + DoHandshakeLoop(NULL); } // kMaxClientHellos is the maximum number of times that we'll send a client @@ -308,57 +316,15 @@ void QuicCryptoClientStream::DoHandshakeLoop( next_state_ = STATE_GET_CHANNEL_ID; break; case STATE_VERIFY_PROOF: { - ProofVerifier* verifier = crypto_config_->proof_verifier(); - DCHECK(verifier); - next_state_ = STATE_VERIFY_PROOF_COMPLETE; - generation_counter_ = cached->generation_counter(); - - ProofVerifierCallbackImpl* proof_verify_callback = - new ProofVerifierCallbackImpl(this); - - verify_ok_ = false; - - QuicAsyncStatus status = verifier->VerifyProof( - server_id_.host(), - cached->server_config(), - cached->certs(), - cached->signature(), - verify_context_.get(), - &verify_error_details_, - &verify_details_, - proof_verify_callback); - - switch (status) { - case QUIC_PENDING: - proof_verify_callback_ = proof_verify_callback; - DVLOG(1) << "Doing VerifyProof"; - return; - case QUIC_FAILURE: - delete proof_verify_callback; - break; - case QUIC_SUCCESS: - delete proof_verify_callback; - verify_ok_ = true; - break; + if (QUIC_PENDING == DoVerifyProof(cached)) { + return; } break; } case STATE_VERIFY_PROOF_COMPLETE: - if (!verify_ok_) { - client_session()->OnProofVerifyDetailsAvailable(*verify_details_); - CloseConnectionWithDetails( - QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); + if (QUIC_PROOF_INVALID == DoVerifyProofComplete(cached)) { return; } - // Check if generation_counter has changed between STATE_VERIFY_PROOF - // and STATE_VERIFY_PROOF_COMPLETE state changes. - if (generation_counter_ != cached->generation_counter()) { - next_state_ = STATE_VERIFY_PROOF; - } else { - SetCachedProofValid(cached); - cached->SetProofVerifyDetails(verify_details_.release()); - next_state_ = STATE_GET_CHANNEL_ID; - } break; case STATE_GET_CHANNEL_ID: { next_state_ = STATE_GET_CHANNEL_ID_COMPLETE; @@ -471,8 +437,93 @@ void QuicCryptoClientStream::DoHandshakeLoop( // This means that the peer sent us a message that we weren't expecting. CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); return; + case STATE_INITIALIZE_SCUP: + DoInitializeServerConfigUpdate(cached); + break; + case STATE_VERIFY_PROOF_DONE: + return; // We are done. + } + } +} + +void QuicCryptoClientStream::DoInitializeServerConfigUpdate( + QuicCryptoClientConfig::CachedState* cached) { + if (!server_id_.is_https()) { + // We don't check the certificates for insecure QUIC connections. + SetCachedProofValid(cached); + next_state_ = STATE_VERIFY_PROOF_DONE; + return; + } + if (!cached->IsEmpty() && !cached->signature().empty()) { + // Note that we verify the proof even if the cached proof is valid. + DCHECK(crypto_config_->proof_verifier()); + next_state_ = STATE_VERIFY_PROOF; + } +} + +QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof( + QuicCryptoClientConfig::CachedState* cached) { + ProofVerifier* verifier = crypto_config_->proof_verifier(); + DCHECK(verifier); + next_state_ = STATE_VERIFY_PROOF_COMPLETE; + generation_counter_ = cached->generation_counter(); + + ProofVerifierCallbackImpl* proof_verify_callback = + new ProofVerifierCallbackImpl(this); + + verify_ok_ = false; + + QuicAsyncStatus status = verifier->VerifyProof( + server_id_.host(), + cached->server_config(), + cached->certs(), + cached->signature(), + verify_context_.get(), + &verify_error_details_, + &verify_details_, + proof_verify_callback); + + switch (status) { + case QUIC_PENDING: + proof_verify_callback_ = proof_verify_callback; + DVLOG(1) << "Doing VerifyProof"; + break; + case QUIC_FAILURE: + delete proof_verify_callback; + break; + case QUIC_SUCCESS: + delete proof_verify_callback; + verify_ok_ = true; + break; + } + return status; +} + +QuicErrorCode QuicCryptoClientStream::DoVerifyProofComplete( + QuicCryptoClientConfig::CachedState* cached) { + if (!verify_ok_) { + client_session()->OnProofVerifyDetailsAvailable(*verify_details_); + UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed", + handshake_confirmed()); + CloseConnectionWithDetails( + QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); + return QUIC_PROOF_INVALID; + } + + // Check if generation_counter has changed between STATE_VERIFY_PROOF and + // STATE_VERIFY_PROOF_COMPLETE state changes. + if (generation_counter_ != cached->generation_counter()) { + next_state_ = STATE_VERIFY_PROOF; + } else { + SetCachedProofValid(cached); + cached->SetProofVerifyDetails(verify_details_.release()); + if (!handshake_confirmed()) { + next_state_ = STATE_GET_CHANNEL_ID; + } else { + next_state_ = STATE_VERIFY_PROOF_DONE; } } + return QUIC_NO_ERROR; } void QuicCryptoClientStream::SetCachedProofValid( diff --git a/net/quic/quic_crypto_client_stream.h b/net/quic/quic_crypto_client_stream.h index 3be89ab..768e38a 100644 --- a/net/quic/quic_crypto_client_stream.h +++ b/net/quic/quic_crypto_client_stream.h @@ -106,6 +106,8 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream { STATE_GET_CHANNEL_ID, STATE_GET_CHANNEL_ID_COMPLETE, STATE_RECV_SHLO, + STATE_INITIALIZE_SCUP, + STATE_VERIFY_PROOF_DONE, }; // Handles new server config and optional source-address token provided by the @@ -117,6 +119,21 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream { // |in| may be NULL if the call did not result from a received message. void DoHandshakeLoop(const CryptoHandshakeMessage* in); + // Start the proof verification if |server_id_| is https and |cached| has + // signature. + void DoInitializeServerConfigUpdate( + QuicCryptoClientConfig::CachedState* cached); + + // Starts the proof verification. Returns the QuicAsyncStatus returned by the + // ProofVerifier's VerifyProof. + QuicAsyncStatus DoVerifyProof(QuicCryptoClientConfig::CachedState* cached); + + // If proof is valid then it sets the proof as valid (which persists the + // server config) and returns QUIC_NO_ERROR. If not, it closes the connection + // and returns QUIC_PROOF_INVALID. + QuicErrorCode DoVerifyProofComplete( + QuicCryptoClientConfig::CachedState* cached); + // Called to set the proof of |cached| valid. Also invokes the session's // OnProofValid() method. void SetCachedProofValid(QuicCryptoClientConfig::CachedState* cached); |