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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
84 } | 85 } |
85 | 86 |
86 void QuicCryptoClientStream::OnHandshakeMessage( | 87 void QuicCryptoClientStream::OnHandshakeMessage( |
87 const CryptoHandshakeMessage& message) { | 88 const CryptoHandshakeMessage& message) { |
88 QuicCryptoStream::OnHandshakeMessage(message); | 89 QuicCryptoStream::OnHandshakeMessage(message); |
89 | 90 |
90 DoHandshakeLoop(&message); | 91 DoHandshakeLoop(&message); |
91 } | 92 } |
92 | 93 |
93 bool QuicCryptoClientStream::CryptoConnect() { | 94 bool QuicCryptoClientStream::CryptoConnect() { |
94 next_state_ = STATE_SEND_CHLO; | 95 next_state_ = STATE_LOAD_QUIC_SERVER_INFO; |
95 DoHandshakeLoop(NULL); | 96 DoHandshakeLoop(NULL); |
96 return true; | 97 return true; |
97 } | 98 } |
98 | 99 |
99 int QuicCryptoClientStream::num_sent_client_hellos() const { | 100 int QuicCryptoClientStream::num_sent_client_hellos() const { |
100 return num_client_hellos_; | 101 return num_client_hellos_; |
101 } | 102 } |
102 | 103 |
103 // TODO(rtenneti): Add unittests for GetSSLInfo which exercise the various ways | 104 // TODO(rtenneti): Add unittests for GetSSLInfo which exercise the various ways |
104 // we learn about SSL info (sync vs async vs cached). | 105 // 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_); | 153 crypto_config_->LookupOrCreate(server_hostname_); |
153 | 154 |
154 if (in != NULL) { | 155 if (in != NULL) { |
155 DVLOG(1) << "Client: Received " << in->DebugString(); | 156 DVLOG(1) << "Client: Received " << in->DebugString(); |
156 } | 157 } |
157 | 158 |
158 for (;;) { | 159 for (;;) { |
159 const State state = next_state_; | 160 const State state = next_state_; |
160 next_state_ = STATE_IDLE; | 161 next_state_ = STATE_IDLE; |
161 switch (state) { | 162 switch (state) { |
163 case STATE_LOAD_QUIC_SERVER_INFO: { | |
164 if (DoLoadQuicServerInfo(cached) == ERR_IO_PENDING) { | |
165 return; | |
166 } | |
167 break; | |
168 } | |
169 case STATE_LOAD_QUIC_SERVER_INFO_COMPLETE: { | |
170 DoLoadQuicServerInfoComplete(cached); | |
171 DCHECK_EQ(STATE_SEND_CHLO, next_state_); | |
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 } |
181 if (!cached->proof_valid()) { | |
182 ProofVerifier* verifier = crypto_config_->proof_verifier(); | |
183 if (!verifier) { | |
184 // If no verifier is set then we don't check the certificates. | |
185 cached->SetProofValid(); | |
186 } else if (!cached->signature().empty()) { | |
187 next_state_ = STATE_VERIFY_PROOF; | |
188 break; | |
189 } | |
190 } | |
wtc
2014/02/11 01:01:45
I think this (lines 181-190) should be moved to Do
ramant (doing other things)
2014/02/11 07:57:55
Done.
| |
169 num_client_hellos_++; | 191 num_client_hellos_++; |
170 | 192 |
171 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { | 193 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { |
172 crypto_config_->FillInchoateClientHello( | 194 crypto_config_->FillInchoateClientHello( |
173 server_hostname_, | 195 server_hostname_, |
174 session()->connection()->supported_versions().front(), | 196 session()->connection()->supported_versions().front(), |
175 cached, &crypto_negotiated_params_, &out); | 197 cached, &crypto_negotiated_params_, &out); |
176 // Pad the inchoate client hello to fill up a packet. | 198 // Pad the inchoate client hello to fill up a packet. |
177 const size_t kFramingOverhead = 50; // A rough estimate. | 199 const size_t kFramingOverhead = 50; // A rough estimate. |
178 const size_t max_packet_size = | 200 const size_t max_packet_size = |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
311 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); | 333 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); |
312 return; | 334 return; |
313 } | 335 } |
314 // Check if generation_counter has changed between STATE_VERIFY_PROOF | 336 // Check if generation_counter has changed between STATE_VERIFY_PROOF |
315 // and STATE_VERIFY_PROOF_COMPLETE state changes. | 337 // and STATE_VERIFY_PROOF_COMPLETE state changes. |
316 if (generation_counter_ != cached->generation_counter()) { | 338 if (generation_counter_ != cached->generation_counter()) { |
317 next_state_ = STATE_VERIFY_PROOF; | 339 next_state_ = STATE_VERIFY_PROOF; |
318 } else { | 340 } else { |
319 cached->SetProofValid(); | 341 cached->SetProofValid(); |
320 cached->SetProofVerifyDetails(verify_details_.release()); | 342 cached->SetProofVerifyDetails(verify_details_.release()); |
343 cached->SaveQuicServerInfo(); | |
wtc
2014/02/11 01:01:45
We should also call cached->SaveQuicServerInfo() w
ramant (doing other things)
2014/02/11 07:57:55
Done.
| |
321 next_state_ = STATE_SEND_CHLO; | 344 next_state_ = STATE_SEND_CHLO; |
322 } | 345 } |
323 break; | 346 break; |
324 case STATE_RECV_SHLO: { | 347 case STATE_RECV_SHLO: { |
325 // We sent a CHLO that we expected to be accepted and now we're hoping | 348 // We sent a CHLO that we expected to be accepted and now we're hoping |
326 // for a SHLO from the server to confirm that. | 349 // for a SHLO from the server to confirm that. |
327 if (in->tag() == kREJ) { | 350 if (in->tag() == kREJ) { |
328 // alternative_decrypter will be NULL if the original alternative | 351 // alternative_decrypter will be NULL if the original alternative |
329 // decrypter latched and became the primary decrypter. That happens | 352 // decrypter latched and became the primary decrypter. That happens |
330 // if we received a message encrypted with the INITIAL key. | 353 // if we received a message encrypted with the INITIAL key. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 return; | 410 return; |
388 } | 411 } |
389 case STATE_IDLE: | 412 case STATE_IDLE: |
390 // This means that the peer sent us a message that we weren't expecting. | 413 // This means that the peer sent us a message that we weren't expecting. |
391 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); | 414 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); |
392 return; | 415 return; |
393 } | 416 } |
394 } | 417 } |
395 } | 418 } |
396 | 419 |
420 void QuicCryptoClientStream::OnIOComplete(int result) { | |
421 DCHECK_EQ(STATE_LOAD_QUIC_SERVER_INFO, next_state_); | |
wtc
2014/02/11 01:01:45
next_state_ should be STATE_LOAD_QUIC_SERVER_INFO_
ramant (doing other things)
2014/02/11 07:57:55
Done.
| |
422 DCHECK_NE(ERR_IO_PENDING, result); | |
423 if (result != OK) { | |
424 next_state_ = STATE_SEND_CHLO; | |
425 } else { | |
426 next_state_ = STATE_LOAD_QUIC_SERVER_INFO_COMPLETE; | |
427 } | |
wtc
2014/02/11 01:01:45
Lines 423-427 should be deleted.
Since DoHandshak
ramant (doing other things)
2014/02/11 07:57:55
Done.
| |
428 DoHandshakeLoop(NULL); | |
429 } | |
430 | |
431 int QuicCryptoClientStream::DoLoadQuicServerInfo( | |
432 QuicCryptoClientConfig::CachedState* cached) { | |
433 next_state_ = STATE_SEND_CHLO; | |
434 QuicServerInfo* quic_server_info = cached->quic_server_info(); | |
435 if (!quic_server_info) { | |
436 return OK; | |
437 } | |
438 | |
439 // TODO(rtenneti): If multiple tabs load the same URL, all requests except for | |
440 // the first request send InchoateClientHello. Fix the code to handle multiple | |
441 // requests. A possible solution is to wait for the first request to finish | |
442 // and use the data from the disk cache for all requests. | |
443 int rv = quic_server_info->WaitForDataReady( | |
wtc
2014/02/11 01:01:45
We probably should save the generation count of |c
ramant (doing other things)
2014/02/11 07:57:55
Done.
| |
444 base::Bind(&QuicCryptoClientStream::OnIOComplete, | |
445 base::Unretained(this))); | |
446 | |
447 if (rv != OK) { | |
448 if (rv == ERR_IO_PENDING) { | |
449 next_state_ = STATE_LOAD_QUIC_SERVER_INFO; | |
wtc
2014/02/11 01:01:45
This should be STATE_LOAD_QUIC_SERVER_INFO_COMPLET
ramant (doing other things)
2014/02/11 07:57:55
Done.
| |
450 return rv; | |
451 } | |
452 // It is ok to proceed to STATE_SEND_CHLO when we cannot load QuicServerInfo | |
453 // from the disk cache. | |
454 DVLOG(1) << "QuicServerInfo's WaitForDataReady failed"; | |
455 } | |
456 return OK; | |
457 } | |
458 | |
459 void QuicCryptoClientStream::DoLoadQuicServerInfoComplete( | |
460 QuicCryptoClientConfig::CachedState* cached) { | |
461 next_state_ = STATE_SEND_CHLO; | |
462 | |
463 if (!cached->quic_server_info()->IsDataReady()) { | |
wtc
2014/02/11 01:01:45
We probably need to check the generation count her
ramant (doing other things)
2014/02/11 07:57:55
Done.
| |
464 // It is ok to proceed to STATE_SEND_CHLO when we cannot load QuicServerInfo | |
465 // from the disk cache. | |
466 DVLOG(1) << "Loading of QuicServerInfo failed"; | |
467 return; | |
468 } | |
469 | |
470 cached->LoadQuicServerInfo(); | |
471 | |
472 return; | |
473 } | |
474 | |
397 } // namespace net | 475 } // namespace net |
OLD | NEW |