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 "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "net/base/completion_callback.h" | 8 #include "net/base/completion_callback.h" |
| 9 #include "net/base/net_errors.h" | 9 #include "net/base/net_errors.h" |
| 10 #include "net/quic/crypto/crypto_protocol.h" | 10 #include "net/quic/crypto/crypto_protocol.h" |
| 11 #include "net/quic/crypto/crypto_utils.h" | 11 #include "net/quic/crypto/crypto_utils.h" |
| 12 #include "net/quic/crypto/null_encrypter.h" | 12 #include "net/quic/crypto/null_encrypter.h" |
| 13 #include "net/quic/crypto/proof_verifier.h" | 13 #include "net/quic/crypto/proof_verifier.h" |
| 14 #include "net/quic/crypto/proof_verifier_chromium.h" | 14 #include "net/quic/crypto/proof_verifier_chromium.h" |
| 15 #include "net/quic/crypto/quic_server_info.h" | 15 #include "net/quic/crypto/quic_server_info.h" |
| 16 #include "net/quic/crypto/quic_server_info.h" | |
|
ramant (doing other things)
2014/03/12 00:50:56
nit: line 16 could be deleted.
Ryan Hamilton
2014/03/12 04:00:45
Done.
| |
| 16 #include "net/quic/quic_protocol.h" | 17 #include "net/quic/quic_protocol.h" |
| 17 #include "net/quic/quic_session.h" | 18 #include "net/quic/quic_session.h" |
| 18 #include "net/ssl/ssl_connection_status_flags.h" | 19 #include "net/ssl/ssl_connection_status_flags.h" |
| 19 #include "net/ssl/ssl_info.h" | 20 #include "net/ssl/ssl_info.h" |
| 20 | 21 |
| 21 namespace net { | 22 namespace net { |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 25 // Copies CertVerifyResult from |verify_details| to |cert_verify_result|. | 26 // Copies CertVerifyResult from |verify_details| to |cert_verify_result|. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 58 stream_->DoHandshakeLoop(NULL); | 59 stream_->DoHandshakeLoop(NULL); |
| 59 | 60 |
| 60 // The ProofVerifier owns this object and will delete it when this method | 61 // The ProofVerifier owns this object and will delete it when this method |
| 61 // returns. | 62 // returns. |
| 62 } | 63 } |
| 63 | 64 |
| 64 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { | 65 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { |
| 65 stream_ = NULL; | 66 stream_ = NULL; |
| 66 } | 67 } |
| 67 | 68 |
| 68 | |
| 69 QuicCryptoClientStream::QuicCryptoClientStream( | 69 QuicCryptoClientStream::QuicCryptoClientStream( |
| 70 const string& server_hostname, | 70 const string& server_hostname, |
| 71 QuicSession* session, | 71 QuicSession* session, |
| 72 QuicCryptoClientConfig* crypto_config) | 72 QuicCryptoClientConfig* crypto_config) |
| 73 : QuicCryptoStream(session), | 73 : QuicCryptoStream(session), |
| 74 next_state_(STATE_IDLE), | 74 next_state_(STATE_IDLE), |
| 75 num_client_hellos_(0), | 75 num_client_hellos_(0), |
| 76 crypto_config_(crypto_config), | 76 crypto_config_(crypto_config), |
| 77 server_hostname_(server_hostname), | 77 server_hostname_(server_hostname), |
| 78 generation_counter_(0), | 78 generation_counter_(0), |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 270 *in, session()->connection()->clock()->WallNow(), cached, | 270 *in, session()->connection()->clock()->WallNow(), cached, |
| 271 &crypto_negotiated_params_, &error_details); | 271 &crypto_negotiated_params_, &error_details); |
| 272 if (error != QUIC_NO_ERROR) { | 272 if (error != QUIC_NO_ERROR) { |
| 273 CloseConnectionWithDetails(error, error_details); | 273 CloseConnectionWithDetails(error, error_details); |
| 274 return; | 274 return; |
| 275 } | 275 } |
| 276 if (!cached->proof_valid()) { | 276 if (!cached->proof_valid()) { |
| 277 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 277 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
| 278 if (!verifier) { | 278 if (!verifier) { |
| 279 // If no verifier is set then we don't check the certificates. | 279 // If no verifier is set then we don't check the certificates. |
| 280 cached->SetProofValid(); | 280 cached->SetProofValid(); |
|
ramant (doing other things)
2014/03/12 00:50:56
nit: consider calling SaveQuicServerInfo from here
Ryan Hamilton
2014/03/12 04:00:45
Done, and in the other places. We should probably
| |
| 281 } else if (!cached->signature().empty()) { | 281 } else if (!cached->signature().empty()) { |
| 282 next_state_ = STATE_VERIFY_PROOF; | 282 next_state_ = STATE_VERIFY_PROOF; |
| 283 break; | 283 break; |
| 284 } | 284 } |
| 285 } | 285 } |
| 286 next_state_ = STATE_SEND_CHLO; | 286 next_state_ = STATE_SEND_CHLO; |
| 287 break; | 287 break; |
| 288 case STATE_VERIFY_PROOF: { | 288 case STATE_VERIFY_PROOF: { |
| 289 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 289 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
| 290 DCHECK(verifier); | 290 DCHECK(verifier); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 408 } | 408 } |
| 409 } | 409 } |
| 410 | 410 |
| 411 void QuicCryptoClientStream::OnIOComplete(int result) { | 411 void QuicCryptoClientStream::OnIOComplete(int result) { |
| 412 DCHECK_EQ(STATE_LOAD_QUIC_SERVER_INFO_COMPLETE, next_state_); | 412 DCHECK_EQ(STATE_LOAD_QUIC_SERVER_INFO_COMPLETE, next_state_); |
| 413 DCHECK_NE(ERR_IO_PENDING, result); | 413 DCHECK_NE(ERR_IO_PENDING, result); |
| 414 disk_cache_load_result_ = result; | 414 disk_cache_load_result_ = result; |
| 415 DoHandshakeLoop(NULL); | 415 DoHandshakeLoop(NULL); |
| 416 } | 416 } |
| 417 | 417 |
| 418 void QuicCryptoClientStream::SetQuicServerInfo( | |
| 419 scoped_ptr<QuicServerInfo> server_info) { | |
| 420 quic_server_info_.reset(server_info.release()); | |
| 421 } | |
| 422 | |
| 418 int QuicCryptoClientStream::DoLoadQuicServerInfo( | 423 int QuicCryptoClientStream::DoLoadQuicServerInfo( |
| 419 QuicCryptoClientConfig::CachedState* cached) { | 424 QuicCryptoClientConfig::CachedState* cached) { |
| 420 next_state_ = STATE_SEND_CHLO; | 425 next_state_ = STATE_SEND_CHLO; |
| 421 QuicServerInfo* quic_server_info = cached->quic_server_info(); | 426 if (!quic_server_info_) { |
| 422 if (!quic_server_info) { | |
| 423 return OK; | 427 return OK; |
| 424 } | 428 } |
| 425 | 429 |
| 426 read_start_time_ = base::TimeTicks::Now(); | 430 read_start_time_ = base::TimeTicks::Now(); |
| 427 generation_counter_ = cached->generation_counter(); | 431 generation_counter_ = cached->generation_counter(); |
| 428 next_state_ = STATE_LOAD_QUIC_SERVER_INFO_COMPLETE; | 432 next_state_ = STATE_LOAD_QUIC_SERVER_INFO_COMPLETE; |
| 429 | 433 |
| 430 // TODO(rtenneti): Use host:port to access QUIC server information from disk | 434 // TODO(rtenneti): Use host:port to access QUIC server information from disk |
| 431 // cache. If multiple tabs load URLs with same hostname but different | 435 // cache. If multiple tabs load URLs with same hostname but different |
| 432 // ports, all requests except for the first request send InchoateClientHello. | 436 // ports, all requests except for the first request send InchoateClientHello. |
| 433 // Fix the code to handle multiple requests. A possible solution is to wait | 437 // Fix the code to handle multiple requests. A possible solution is to wait |
| 434 // for the first request to finish and use the data from the disk cache for | 438 // for the first request to finish and use the data from the disk cache for |
| 435 // all requests. | 439 // all requests. |
| 436 // We may need to call quic_server_info->Persist later. | 440 // We may need to call quic_server_info->Persist later. |
| 437 // quic_server_info->Persist requires quic_server_info to be ready, so we | 441 // quic_server_info->Persist requires quic_server_info to be ready, so we |
| 438 // always call WaitForDataReady, even though we might have initialized | 442 // always call WaitForDataReady, even though we might have initialized |
| 439 // |cached| config from the cached state for a canonical hostname. | 443 // |cached| config from the cached state for a canonical hostname. |
| 440 int rv = quic_server_info->WaitForDataReady( | 444 int rv = quic_server_info_->WaitForDataReady( |
| 441 base::Bind(&QuicCryptoClientStream::OnIOComplete, | 445 base::Bind(&QuicCryptoClientStream::OnIOComplete, |
| 442 weak_factory_.GetWeakPtr())); | 446 weak_factory_.GetWeakPtr())); |
| 443 | 447 |
| 444 if (rv != ERR_IO_PENDING) { | 448 if (rv != ERR_IO_PENDING) { |
| 445 disk_cache_load_result_ = rv; | 449 disk_cache_load_result_ = rv; |
| 446 } | 450 } |
| 447 return rv; | 451 return rv; |
| 448 } | 452 } |
| 449 | 453 |
| 450 void QuicCryptoClientStream::DoLoadQuicServerInfoComplete( | 454 void QuicCryptoClientStream::DoLoadQuicServerInfoComplete( |
| 451 QuicCryptoClientConfig::CachedState* cached) { | 455 QuicCryptoClientConfig::CachedState* cached) { |
| 452 LoadQuicServerInfo(cached); | 456 LoadQuicServerInfo(cached); |
| 453 QuicServerInfo::State* state = cached->quic_server_info()->mutable_state(); | 457 QuicServerInfo::State* state = quic_server_info_->mutable_state(); |
| 454 state->Clear(); | 458 state->Clear(); |
| 455 } | 459 } |
| 456 | 460 |
| 457 void QuicCryptoClientStream::LoadQuicServerInfo( | 461 void QuicCryptoClientStream::LoadQuicServerInfo( |
| 458 QuicCryptoClientConfig::CachedState* cached) { | 462 QuicCryptoClientConfig::CachedState* cached) { |
| 459 next_state_ = STATE_SEND_CHLO; | 463 next_state_ = STATE_SEND_CHLO; |
| 460 | 464 |
| 461 // If someone else already saved a server config, we don't want to overwrite | 465 // If someone else already saved a server config, we don't want to overwrite |
| 462 // it. Also, if someone else saved a server config and then cleared it (so | 466 // it. Also, if someone else saved a server config and then cleared it (so |
| 463 // cached->IsEmpty() is true), we still want to load from QuicServerInfo. | 467 // cached->IsEmpty() is true), we still want to load from QuicServerInfo. |
| 464 if (!cached->IsEmpty()) { | 468 if (!cached->IsEmpty()) { |
| 465 return; | 469 return; |
| 466 } | 470 } |
| 467 | 471 |
| 468 UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheReadTime", | 472 UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheReadTime", |
| 469 base::TimeTicks::Now() - read_start_time_); | 473 base::TimeTicks::Now() - read_start_time_); |
| 470 | 474 |
| 471 if (disk_cache_load_result_ != OK || !cached->LoadQuicServerInfo( | 475 if (disk_cache_load_result_ != OK || |
| 472 session()->connection()->clock()->WallNow())) { | 476 !cached->Initialize(quic_server_info_->state().server_config, |
| 477 quic_server_info_->state().server_config_sig, | |
| 478 quic_server_info_->state().source_address_token, | |
| 479 quic_server_info_->state().certs, | |
| 480 session()->connection()->clock()->WallNow())) { | |
| 473 // It is ok to proceed to STATE_SEND_CHLO when we cannot load QuicServerInfo | 481 // It is ok to proceed to STATE_SEND_CHLO when we cannot load QuicServerInfo |
| 474 // from the disk cache. | 482 // from the disk cache. |
| 475 DCHECK(cached->IsEmpty()); | 483 DCHECK(cached->IsEmpty()); |
| 476 DVLOG(1) << "Empty server_config"; | 484 DVLOG(1) << "Empty server_config"; |
| 477 return; | 485 return; |
| 478 } | 486 } |
| 479 | 487 |
| 480 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 488 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
| 481 if (!verifier) { | 489 if (!verifier) { |
| 482 // If no verifier is set then we don't check the certificates. | 490 // If no verifier is set then we don't check the certificates. |
| 483 cached->SetProofValid(); | 491 cached->SetProofValid(); |
| 484 } else if (!cached->signature().empty()) { | 492 } else if (!cached->signature().empty()) { |
| 485 next_state_ = STATE_VERIFY_PROOF; | 493 next_state_ = STATE_VERIFY_PROOF; |
| 486 } | 494 } |
| 487 } | 495 } |
| 488 | 496 |
| 497 void QuicCryptoClientStream::SaveQuicServerInfo( | |
| 498 QuicCryptoClientConfig::CachedState* cached) { | |
| 499 DCHECK(cached->proof_valid()); | |
| 500 | |
| 501 // If the QuicServerInfo hasn't managed to load from disk yet then we can't | |
| 502 // save anything. TODO(rtenneti): we should fix this. | |
| 503 if (!quic_server_info_->IsDataReady()) { | |
| 504 return; | |
| 505 } | |
| 506 | |
| 507 QuicServerInfo::State* state = quic_server_info_->mutable_state(); | |
| 508 | |
| 509 state->server_config = cached->server_config(); | |
| 510 state->source_address_token = cached->source_address_token(); | |
| 511 state->server_config_sig = cached->signature(); | |
| 512 state->certs = cached->certs(); | |
| 513 | |
| 514 quic_server_info_->Persist(); | |
| 515 } | |
| 516 | |
| 489 } // namespace net | 517 } // namespace net |
| OLD | NEW |