Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/quic_crypto_client_stream.h" | 5 #include "net/quic/quic_crypto_client_stream.h" |
| 6 | 6 |
| 7 #include "net/base/completion_callback.h" | 7 #include "net/base/completion_callback.h" |
| 8 #include "net/base/net_errors.h" | 8 #include "net/base/net_errors.h" |
| 9 #include "net/quic/crypto/crypto_protocol.h" | 9 #include "net/quic/crypto/crypto_protocol.h" |
| 10 #include "net/quic/crypto/crypto_utils.h" | 10 #include "net/quic/crypto/crypto_utils.h" |
| 11 #include "net/quic/crypto/null_encrypter.h" | 11 #include "net/quic/crypto/null_encrypter.h" |
| 12 #include "net/quic/crypto/proof_verifier.h" | 12 #include "net/quic/crypto/proof_verifier.h" |
| 13 #include "net/quic/crypto/proof_verifier_chromium.h" | 13 #include "net/quic/crypto/proof_verifier_chromium.h" |
| 14 #include "net/quic/crypto/quic_server_info.h" | |
| 14 #include "net/quic/quic_protocol.h" | 15 #include "net/quic/quic_protocol.h" |
| 15 #include "net/quic/quic_session.h" | 16 #include "net/quic/quic_session.h" |
| 16 #include "net/ssl/ssl_connection_status_flags.h" | 17 #include "net/ssl/ssl_connection_status_flags.h" |
| 17 #include "net/ssl/ssl_info.h" | 18 #include "net/ssl/ssl_info.h" |
| 18 | 19 |
| 19 namespace net { | 20 namespace net { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 // Copies CertVerifyResult from |verify_details| to |cert_verify_result|. | 24 // Copies CertVerifyResult from |verify_details| to |cert_verify_result|. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 67 QuicCryptoClientStream::QuicCryptoClientStream( | 68 QuicCryptoClientStream::QuicCryptoClientStream( |
| 68 const string& server_hostname, | 69 const string& server_hostname, |
| 69 QuicSession* session, | 70 QuicSession* session, |
| 70 QuicCryptoClientConfig* crypto_config) | 71 QuicCryptoClientConfig* crypto_config) |
| 71 : QuicCryptoStream(session), | 72 : QuicCryptoStream(session), |
| 72 next_state_(STATE_IDLE), | 73 next_state_(STATE_IDLE), |
| 73 num_client_hellos_(0), | 74 num_client_hellos_(0), |
| 74 crypto_config_(crypto_config), | 75 crypto_config_(crypto_config), |
| 75 server_hostname_(server_hostname), | 76 server_hostname_(server_hostname), |
| 76 generation_counter_(0), | 77 generation_counter_(0), |
| 77 proof_verify_callback_(NULL) { | 78 proof_verify_callback_(NULL), |
| 79 disk_cache_load_result_(ERR_UNEXPECTED) { | |
| 78 } | 80 } |
| 79 | 81 |
| 80 QuicCryptoClientStream::~QuicCryptoClientStream() { | 82 QuicCryptoClientStream::~QuicCryptoClientStream() { |
| 81 if (proof_verify_callback_) { | 83 if (proof_verify_callback_) { |
| 82 proof_verify_callback_->Cancel(); | 84 proof_verify_callback_->Cancel(); |
| 83 } | 85 } |
| 84 } | 86 } |
| 85 | 87 |
| 86 void QuicCryptoClientStream::OnHandshakeMessage( | 88 void QuicCryptoClientStream::OnHandshakeMessage( |
| 87 const CryptoHandshakeMessage& message) { | 89 const CryptoHandshakeMessage& message) { |
| 88 QuicCryptoStream::OnHandshakeMessage(message); | 90 QuicCryptoStream::OnHandshakeMessage(message); |
| 89 | 91 |
| 90 DoHandshakeLoop(&message); | 92 DoHandshakeLoop(&message); |
| 91 } | 93 } |
| 92 | 94 |
| 93 bool QuicCryptoClientStream::CryptoConnect() { | 95 bool QuicCryptoClientStream::CryptoConnect() { |
| 94 next_state_ = STATE_SEND_CHLO; | 96 next_state_ = STATE_LOAD_QUIC_SERVER_INFO; |
| 95 DoHandshakeLoop(NULL); | 97 DoHandshakeLoop(NULL); |
| 96 return true; | 98 return true; |
| 97 } | 99 } |
| 98 | 100 |
| 99 int QuicCryptoClientStream::num_sent_client_hellos() const { | 101 int QuicCryptoClientStream::num_sent_client_hellos() const { |
| 100 return num_client_hellos_; | 102 return num_client_hellos_; |
| 101 } | 103 } |
| 102 | 104 |
| 103 // TODO(rtenneti): Add unittests for GetSSLInfo which exercise the various ways | 105 // TODO(rtenneti): Add unittests for GetSSLInfo which exercise the various ways |
| 104 // we learn about SSL info (sync vs async vs cached). | 106 // we learn about SSL info (sync vs async vs cached). |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 152 crypto_config_->LookupOrCreate(server_hostname_); | 154 crypto_config_->LookupOrCreate(server_hostname_); |
| 153 | 155 |
| 154 if (in != NULL) { | 156 if (in != NULL) { |
| 155 DVLOG(1) << "Client: Received " << in->DebugString(); | 157 DVLOG(1) << "Client: Received " << in->DebugString(); |
| 156 } | 158 } |
| 157 | 159 |
| 158 for (;;) { | 160 for (;;) { |
| 159 const State state = next_state_; | 161 const State state = next_state_; |
| 160 next_state_ = STATE_IDLE; | 162 next_state_ = STATE_IDLE; |
| 161 switch (state) { | 163 switch (state) { |
| 164 case STATE_LOAD_QUIC_SERVER_INFO: { | |
| 165 if (DoLoadQuicServerInfo(cached) == ERR_IO_PENDING) { | |
| 166 return; | |
| 167 } | |
| 168 break; | |
| 169 } | |
| 170 case STATE_LOAD_QUIC_SERVER_INFO_COMPLETE: { | |
| 171 DoLoadQuicServerInfoComplete(cached); | |
| 172 break; | |
| 173 } | |
| 162 case STATE_SEND_CHLO: { | 174 case STATE_SEND_CHLO: { |
| 163 // Send the client hello in plaintext. | 175 // Send the client hello in plaintext. |
| 164 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); | 176 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); |
| 165 if (num_client_hellos_ > kMaxClientHellos) { | 177 if (num_client_hellos_ > kMaxClientHellos) { |
| 166 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); | 178 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); |
| 167 return; | 179 return; |
| 168 } | 180 } |
| 169 num_client_hellos_++; | 181 num_client_hellos_++; |
| 170 | 182 |
| 171 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { | 183 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 return; | 399 return; |
| 388 } | 400 } |
| 389 case STATE_IDLE: | 401 case STATE_IDLE: |
| 390 // This means that the peer sent us a message that we weren't expecting. | 402 // This means that the peer sent us a message that we weren't expecting. |
| 391 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); | 403 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); |
| 392 return; | 404 return; |
| 393 } | 405 } |
| 394 } | 406 } |
| 395 } | 407 } |
| 396 | 408 |
| 409 void QuicCryptoClientStream::OnIOComplete(int result) { | |
| 410 DCHECK_EQ(STATE_LOAD_QUIC_SERVER_INFO_COMPLETE, next_state_); | |
| 411 DCHECK_NE(ERR_IO_PENDING, result); | |
| 412 disk_cache_load_result_ = result; | |
| 413 DoHandshakeLoop(NULL); | |
| 414 } | |
| 415 | |
| 416 int QuicCryptoClientStream::DoLoadQuicServerInfo( | |
| 417 QuicCryptoClientConfig::CachedState* cached) { | |
| 418 next_state_ = STATE_SEND_CHLO; | |
| 419 QuicServerInfo* quic_server_info = cached->quic_server_info(); | |
| 420 if (!quic_server_info) { | |
| 421 return OK; | |
| 422 } | |
| 423 | |
| 424 generation_counter_ = cached->generation_counter(); | |
| 425 next_state_ = STATE_LOAD_QUIC_SERVER_INFO_COMPLETE; | |
| 426 | |
| 427 // TODO(rtenneti): If multiple tabs load the same URL, all requests except for | |
| 428 // the first request send InchoateClientHello. Fix the code to handle multiple | |
| 429 // requests. A possible solution is to wait for the first request to finish | |
| 430 // and use the data from the disk cache for all requests. | |
| 431 // quic_server_info->Persist requires quic_server_info to be ready. We might | |
|
wtc
2014/02/20 20:06:16
Thanks for updating the comment. The new comment i
ramant (doing other things)
2014/02/20 23:44:08
Many many thanks for the new comments (they read l
| |
| 432 // have already initialized |cached| config from a the cached state for a | |
| 433 // canonical hostname. | |
| 434 int rv = quic_server_info->WaitForDataReady( | |
| 435 base::Bind(&QuicCryptoClientStream::OnIOComplete, | |
| 436 base::Unretained(this))); | |
| 437 | |
| 438 if (rv != ERR_IO_PENDING) { | |
| 439 disk_cache_load_result_ = rv; | |
| 440 } | |
| 441 return rv; | |
| 442 } | |
| 443 | |
| 444 void QuicCryptoClientStream::DoLoadQuicServerInfoComplete( | |
| 445 QuicCryptoClientConfig::CachedState* cached) { | |
| 446 next_state_ = STATE_SEND_CHLO; | |
| 447 | |
| 448 // If someone else already saved a server config, we don't want to overwrite | |
| 449 // it. Also, if someone else saved a server config and then cleared it (so | |
| 450 // cached->IsEmpty() is true, but the generation counter changed), we still | |
|
wtc
2014/02/20 20:06:16
We should delete ", but the generation counter cha
ramant (doing other things)
2014/02/20 23:44:08
Done in CL https://codereview.chromium.org/174533
| |
| 451 // want to load from QuicServerInfo. | |
| 452 if (!cached->IsEmpty()) { | |
| 453 // Someone else has already saved a server config received from the network | |
| 454 // or the canonical server config. | |
|
wtc
2014/02/20 20:06:16
We only need one of these comments, but not both.
ramant (doing other things)
2014/02/20 23:44:08
Done in CL https://codereview.chromium.org/174533
| |
| 455 return; | |
| 456 } | |
| 457 | |
| 458 if (disk_cache_load_result_ != OK || !cached->LoadQuicServerInfo( | |
| 459 session()->connection()->clock()->WallNow())) { | |
| 460 // It is ok to proceed to STATE_SEND_CHLO when we cannot load QuicServerInfo | |
| 461 // from the disk cache. | |
| 462 DCHECK(cached->IsEmpty()); | |
| 463 DVLOG(1) << "Empty server_config"; | |
| 464 return; | |
| 465 } | |
| 466 | |
| 467 ProofVerifier* verifier = crypto_config_->proof_verifier(); | |
| 468 if (!verifier) { | |
| 469 // If no verifier is set then we don't check the certificates. | |
| 470 cached->SetProofValid(); | |
| 471 } else if (!cached->signature().empty()) { | |
| 472 next_state_ = STATE_VERIFY_PROOF; | |
| 473 } | |
| 474 } | |
| 475 | |
| 397 } // namespace net | 476 } // namespace net |
| OLD | NEW |