| Index: net/quic/quic_crypto_client_stream.cc
|
| diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
|
| index 28a6db8569195660a55a34639065e3fa56d75bc8..f1f09092952b9e89163f6cf7ad980822ba277f5c 100644
|
| --- a/net/quic/quic_crypto_client_stream.cc
|
| +++ b/net/quic/quic_crypto_client_stream.cc
|
| @@ -87,7 +87,8 @@ QuicCryptoClientStream::QuicCryptoClientStream(
|
| channel_id_source_callback_run_(false),
|
| channel_id_source_callback_(nullptr),
|
| verify_context_(verify_context),
|
| - proof_verify_callback_(nullptr) {
|
| + proof_verify_callback_(nullptr),
|
| + stateless_reject_received_(false) {
|
| DCHECK_EQ(Perspective::IS_CLIENT, session->connection()->perspective());
|
| }
|
|
|
| @@ -246,6 +247,19 @@ void QuicCryptoClientStream::DoInitialize(
|
| void QuicCryptoClientStream::DoSendCHLO(
|
| const CryptoHandshakeMessage* in,
|
| QuicCryptoClientConfig::CachedState* cached) {
|
| + if (stateless_reject_received_) {
|
| + // If we've gotten to this point, we've sent at least one hello
|
| + // and received a stateless reject in response. We cannot
|
| + // continue to send hellos because the server has abandoned state
|
| + // for this connection. Abandon further handshakes.
|
| + next_state_ = STATE_NONE;
|
| + if (session()->connection()->connected()) {
|
| + session()->connection()->CloseConnection(
|
| + QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, false);
|
| + }
|
| + return;
|
| + }
|
| +
|
| // Send the client hello in plaintext.
|
| session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
|
| if (num_client_hellos_ > kMaxClientHellos) {
|
| @@ -255,6 +269,11 @@ void QuicCryptoClientStream::DoSendCHLO(
|
| num_client_hellos_++;
|
|
|
| CryptoHandshakeMessage out;
|
| + DCHECK(session() != nullptr);
|
| + DCHECK(session()->config() != nullptr);
|
| + // Send all the options, regardless of whether we're sending an
|
| + // inchoate or subsequent hello.
|
| + session()->config()->ToHandshakeMessage(&out);
|
| if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
|
| crypto_config_->FillInchoateClientHello(
|
| server_id_,
|
| @@ -282,7 +301,6 @@ void QuicCryptoClientStream::DoSendCHLO(
|
| return;
|
| }
|
|
|
| - session()->config()->ToHandshakeMessage(&out);
|
| string error_details;
|
| QuicErrorCode error = crypto_config_->FillClientHello(
|
| server_id_,
|
| @@ -344,16 +362,18 @@ void QuicCryptoClientStream::DoReceiveREJ(
|
| // perform a handshake, or we sent a full hello that the server
|
| // rejected. Here we hope to have a REJ that contains the information
|
| // that we need.
|
| - if (in->tag() != kREJ) {
|
| + if ((in->tag() != kREJ) && (in->tag() != kSREJ)) {
|
| next_state_ = STATE_NONE;
|
| CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
|
| "Expected REJ");
|
| return;
|
| }
|
| + stateless_reject_received_ = in->tag() == kSREJ;
|
| string error_details;
|
| QuicErrorCode error = crypto_config_->ProcessRejection(
|
| *in, session()->connection()->clock()->WallNow(), cached,
|
| server_id_.is_https(), &crypto_negotiated_params_, &error_details);
|
| +
|
| if (error != QUIC_NO_ERROR) {
|
| next_state_ = STATE_NONE;
|
| CloseConnectionWithDetails(error, error_details);
|
| @@ -491,9 +511,11 @@ void QuicCryptoClientStream::DoReceiveSHLO(
|
| const CryptoHandshakeMessage* in,
|
| QuicCryptoClientConfig::CachedState* cached) {
|
| next_state_ = STATE_NONE;
|
| - // We sent a CHLO that we expected to be accepted and now we're hoping
|
| - // for a SHLO from the server to confirm that.
|
| - if (in->tag() == kREJ) {
|
| + // We sent a CHLO that we expected to be accepted and now we're
|
| + // hoping for a SHLO from the server to confirm that. First check
|
| + // to see whether the response was a reject, and if so, move on to
|
| + // the reject-processing state.
|
| + if ((in->tag() == kREJ) || (in->tag() == kSREJ)) {
|
| // alternative_decrypter will be nullptr if the original alternative
|
| // decrypter latched and became the primary decrypter. That happens
|
| // if we received a message encrypted with the INITIAL key.
|
|
|