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/quic/crypto/crypto_protocol.h" | 7 #include "net/quic/crypto/crypto_protocol.h" |
8 #include "net/quic/crypto/crypto_utils.h" | 8 #include "net/quic/crypto/crypto_utils.h" |
| 9 #include "net/quic/crypto/proof_verifier.h" |
9 #include "net/quic/quic_protocol.h" | 10 #include "net/quic/quic_protocol.h" |
10 #include "net/quic/quic_session.h" | 11 #include "net/quic/quic_session.h" |
11 | 12 |
12 namespace net { | 13 namespace net { |
13 | 14 |
14 QuicCryptoClientStream::QuicCryptoClientStream( | 15 QuicCryptoClientStream::QuicCryptoClientStream( |
15 const string& server_hostname, | 16 const string& server_hostname, |
16 const QuicConfig& config, | 17 const QuicConfig& config, |
17 QuicSession* session, | 18 QuicSession* session, |
18 QuicCryptoClientConfig* crypto_config) | 19 QuicCryptoClientConfig* crypto_config) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 // * One failure due to an incorrect or missing source-address token. | 59 // * One failure due to an incorrect or missing source-address token. |
59 // * One failure due the server's certificate chain being unavailible and the | 60 // * One failure due the server's certificate chain being unavailible and the |
60 // server being unwilling to send it without a valid source-address token. | 61 // server being unwilling to send it without a valid source-address token. |
61 static const int kMaxClientHellos = 3; | 62 static const int kMaxClientHellos = 3; |
62 | 63 |
63 void QuicCryptoClientStream::DoHandshakeLoop( | 64 void QuicCryptoClientStream::DoHandshakeLoop( |
64 const CryptoHandshakeMessage* in) { | 65 const CryptoHandshakeMessage* in) { |
65 CryptoHandshakeMessage out; | 66 CryptoHandshakeMessage out; |
66 QuicErrorCode error; | 67 QuicErrorCode error; |
67 string error_details; | 68 string error_details; |
| 69 QuicCryptoClientConfig::CachedState* cached = |
| 70 crypto_config_->LookupOrCreate(server_hostname_); |
68 | 71 |
69 if (in != NULL) { | 72 if (in != NULL) { |
70 DLOG(INFO) << "Client received: " << in->DebugString(); | 73 DLOG(INFO) << "Client received: " << in->DebugString(); |
71 } | 74 } |
72 | 75 |
73 for (;;) { | 76 for (;;) { |
74 const State state = next_state_; | 77 const State state = next_state_; |
75 next_state_ = STATE_IDLE; | 78 next_state_ = STATE_IDLE; |
76 switch (state) { | 79 switch (state) { |
77 case STATE_SEND_CHLO: { | 80 case STATE_SEND_CHLO: { |
78 if (num_client_hellos_ > kMaxClientHellos) { | 81 if (num_client_hellos_ > kMaxClientHellos) { |
79 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); | 82 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); |
80 return; | 83 return; |
81 } | 84 } |
82 num_client_hellos_++; | 85 num_client_hellos_++; |
83 | 86 |
84 const QuicCryptoClientConfig::CachedState* cached = | 87 if (!cached->is_complete()) { |
85 crypto_config_->Lookup(server_hostname_); | |
86 if (!cached || !cached->is_complete()) { | |
87 crypto_config_->FillInchoateClientHello(server_hostname_, cached, | 88 crypto_config_->FillInchoateClientHello(server_hostname_, cached, |
88 &out); | 89 &out); |
89 next_state_ = STATE_RECV_REJ; | 90 next_state_ = STATE_RECV_REJ; |
90 DLOG(INFO) << "Client Sending: " << out.DebugString(); | 91 DLOG(INFO) << "Client Sending: " << out.DebugString(); |
91 SendHandshakeMessage(out); | 92 SendHandshakeMessage(out); |
92 return; | 93 return; |
93 } | 94 } |
94 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); | 95 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); |
95 config_.ToHandshakeMessage(&out); | 96 config_.ToHandshakeMessage(&out); |
96 error = crypto_config_->FillClientHello( | 97 error = crypto_config_->FillClientHello( |
(...skipping 24 matching lines...) Expand all Loading... |
121 crypto_negotiated_params_.decrypter.release()); | 122 crypto_negotiated_params_.decrypter.release()); |
122 decrypter_pushed_ = true; | 123 decrypter_pushed_ = true; |
123 return; | 124 return; |
124 } | 125 } |
125 case STATE_RECV_REJ: | 126 case STATE_RECV_REJ: |
126 // We sent a dummy CHLO because we didn't have enough information to | 127 // We sent a dummy CHLO because we didn't have enough information to |
127 // perform a handshake, or we sent a full hello that the server | 128 // perform a handshake, or we sent a full hello that the server |
128 // rejected. Here we hope to have a REJ that contains the information | 129 // rejected. Here we hope to have a REJ that contains the information |
129 // that we need. | 130 // that we need. |
130 if (in->tag() != kREJ) { | 131 if (in->tag() != kREJ) { |
131 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, | 132 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, |
132 "Expected REJ"); | 133 "Expected REJ"); |
133 return; | 134 return; |
134 } | 135 } |
135 error = crypto_config_->ProcessRejection(server_hostname_, *in, | 136 error = crypto_config_->ProcessRejection(cached, *in, |
136 &crypto_negotiated_params_, | 137 &crypto_negotiated_params_, |
137 &error_details); | 138 &error_details); |
138 if (error != QUIC_NO_ERROR) { | 139 if (error != QUIC_NO_ERROR) { |
139 CloseConnectionWithDetails(error, error_details); | 140 CloseConnectionWithDetails(error, error_details); |
140 return; | 141 return; |
| 142 } |
| 143 if (!cached->proof_valid()) { |
| 144 const ProofVerifier* verifier = crypto_config_->proof_verifier(); |
| 145 if (!verifier) { |
| 146 // If no verifier is set then we don't check the certificates. |
| 147 cached->SetProofValid(); |
| 148 } else if (!cached->signature().empty()) { |
| 149 // TODO(rtenneti): In Chromium, we will need to make VerifyProof() |
| 150 // asynchronous. |
| 151 if (!verifier->VerifyProof(server_hostname_, |
| 152 cached->server_config(), |
| 153 cached->certs(), |
| 154 cached->signature(), |
| 155 &error_details)) { |
| 156 CloseConnectionWithDetails(QUIC_PROOF_INVALID, |
| 157 "Proof invalid: " + error_details); |
| 158 return; |
| 159 } |
| 160 cached->SetProofValid(); |
| 161 } |
141 } | 162 } |
142 // Clear any new server write key that we may have set before. | 163 // Clear any new server write key that we may have set before. |
143 if (decrypter_pushed_) { | 164 if (decrypter_pushed_) { |
144 session()->connection()->PopDecrypter(); | 165 session()->connection()->PopDecrypter(); |
145 decrypter_pushed_ = false; | 166 decrypter_pushed_ = false; |
146 } | 167 } |
147 next_state_ = STATE_SEND_CHLO; | 168 next_state_ = STATE_SEND_CHLO; |
148 break; | 169 break; |
149 case STATE_RECV_SHLO: | 170 case STATE_RECV_SHLO: |
150 // We sent a CHLO that we expected to be accepted and now we're hoping | 171 // We sent a CHLO that we expected to be accepted and now we're hoping |
(...skipping 19 matching lines...) Expand all Loading... |
170 return; | 191 return; |
171 case STATE_IDLE: | 192 case STATE_IDLE: |
172 // This means that the peer sent us a message that we weren't expecting. | 193 // This means that the peer sent us a message that we weren't expecting. |
173 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); | 194 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); |
174 return; | 195 return; |
175 } | 196 } |
176 } | 197 } |
177 } | 198 } |
178 | 199 |
179 } // namespace net | 200 } // namespace net |
OLD | NEW |