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_server_stream.h" | 5 #include "net/quic/quic_crypto_server_stream.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "crypto/secure_hash.h" | 8 #include "crypto/secure_hash.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/quic_crypto_server_config.h" | 11 #include "net/quic/crypto/quic_crypto_server_config.h" |
| 12 #include "net/quic/crypto/quic_random.h" |
12 #include "net/quic/proto/cached_network_parameters.pb.h" | 13 #include "net/quic/proto/cached_network_parameters.pb.h" |
13 #include "net/quic/quic_config.h" | 14 #include "net/quic/quic_config.h" |
| 15 #include "net/quic/quic_flags.h" |
14 #include "net/quic/quic_protocol.h" | 16 #include "net/quic/quic_protocol.h" |
15 #include "net/quic/quic_session.h" | 17 #include "net/quic/quic_session.h" |
16 | 18 |
17 using std::string; | 19 using std::string; |
18 | 20 |
19 namespace net { | 21 namespace net { |
20 | 22 |
21 void ServerHelloNotifier::OnAckNotification( | 23 void ServerHelloNotifier::OnAckNotification( |
22 int num_retransmitted_packets, | 24 int num_retransmitted_packets, |
23 int num_retransmitted_bytes, | 25 int num_retransmitted_bytes, |
24 QuicTime::Delta delta_largest_observed) { | 26 QuicTime::Delta delta_largest_observed) { |
25 server_stream_->OnServerHelloAcked(); | 27 server_stream_->OnServerHelloAcked(); |
26 } | 28 } |
27 | 29 |
28 QuicCryptoServerStream::QuicCryptoServerStream( | 30 QuicCryptoServerStream::QuicCryptoServerStream( |
29 const QuicCryptoServerConfig* crypto_config, | 31 const QuicCryptoServerConfig* crypto_config, |
30 QuicSession* session) | 32 QuicSession* session) |
31 : QuicCryptoStream(session), | 33 : QuicCryptoStream(session), |
32 crypto_config_(crypto_config), | 34 crypto_config_(crypto_config), |
33 validate_client_hello_cb_(nullptr), | 35 validate_client_hello_cb_(nullptr), |
34 num_handshake_messages_(0), | 36 num_handshake_messages_(0), |
35 num_server_config_update_messages_sent_(0) { | 37 num_server_config_update_messages_sent_(0), |
| 38 use_stateless_rejects_if_peer_supported_(false), |
| 39 peer_supports_stateless_rejects_(false) { |
36 DCHECK_EQ(Perspective::IS_SERVER, session->connection()->perspective()); | 40 DCHECK_EQ(Perspective::IS_SERVER, session->connection()->perspective()); |
37 } | 41 } |
38 | 42 |
39 QuicCryptoServerStream::~QuicCryptoServerStream() { | 43 QuicCryptoServerStream::~QuicCryptoServerStream() { |
40 CancelOutstandingCallbacks(); | 44 CancelOutstandingCallbacks(); |
41 } | 45 } |
42 | 46 |
43 void QuicCryptoServerStream::CancelOutstandingCallbacks() { | 47 void QuicCryptoServerStream::CancelOutstandingCallbacks() { |
44 // Detach from the validation callback. Calling this multiple times is safe. | 48 // Detach from the validation callback. Calling this multiple times is safe. |
45 if (validate_client_hello_cb_ != nullptr) { | 49 if (validate_client_hello_cb_ != nullptr) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 session()->connection()->clock(), validate_client_hello_cb_); | 81 session()->connection()->clock(), validate_client_hello_cb_); |
78 } | 82 } |
79 | 83 |
80 void QuicCryptoServerStream::FinishProcessingHandshakeMessage( | 84 void QuicCryptoServerStream::FinishProcessingHandshakeMessage( |
81 const CryptoHandshakeMessage& message, | 85 const CryptoHandshakeMessage& message, |
82 const ValidateClientHelloResultCallback::Result& result) { | 86 const ValidateClientHelloResultCallback::Result& result) { |
83 // Clear the callback that got us here. | 87 // Clear the callback that got us here. |
84 DCHECK(validate_client_hello_cb_ != nullptr); | 88 DCHECK(validate_client_hello_cb_ != nullptr); |
85 validate_client_hello_cb_ = nullptr; | 89 validate_client_hello_cb_ = nullptr; |
86 | 90 |
| 91 if (FLAGS_enable_quic_stateless_reject_support) { |
| 92 peer_supports_stateless_rejects_ = DoesPeerSupportStatelessRejects(message); |
| 93 } |
| 94 |
| 95 CryptoHandshakeMessage reply; |
87 string error_details; | 96 string error_details; |
88 CryptoHandshakeMessage reply; | 97 QuicErrorCode error = |
89 QuicErrorCode error = ProcessClientHello( | 98 ProcessClientHello(message, result, &reply, &error_details); |
90 message, result, &reply, &error_details); | |
91 | 99 |
92 if (error != QUIC_NO_ERROR) { | 100 if (error != QUIC_NO_ERROR) { |
93 CloseConnectionWithDetails(error, error_details); | 101 CloseConnectionWithDetails(error, error_details); |
94 return; | 102 return; |
95 } | 103 } |
96 | 104 |
97 if (reply.tag() != kSHLO) { | 105 if (reply.tag() != kSHLO) { |
98 SendHandshakeMessage(reply); | 106 SendHandshakeMessage(reply); |
99 return; | 107 return; |
100 } | 108 } |
101 | 109 |
102 // If we are returning a SHLO then we accepted the handshake. | 110 // If we are returning a SHLO then we accepted the handshake. Now |
| 111 // process the negotiated configuration options as part of the |
| 112 // session config. |
103 QuicConfig* config = session()->config(); | 113 QuicConfig* config = session()->config(); |
104 OverrideQuicConfigDefaults(config); | 114 OverrideQuicConfigDefaults(config); |
105 error = config->ProcessPeerHello(message, CLIENT, &error_details); | 115 error = config->ProcessPeerHello(message, CLIENT, &error_details); |
106 if (error != QUIC_NO_ERROR) { | 116 if (error != QUIC_NO_ERROR) { |
107 CloseConnectionWithDetails(error, error_details); | 117 CloseConnectionWithDetails(error, error_details); |
108 return; | 118 return; |
109 } | 119 } |
| 120 |
110 session()->OnConfigNegotiated(); | 121 session()->OnConfigNegotiated(); |
111 | 122 |
112 config->ToHandshakeMessage(&reply); | 123 config->ToHandshakeMessage(&reply); |
113 | 124 |
114 // Receiving a full CHLO implies the client is prepared to decrypt with | 125 // Receiving a full CHLO implies the client is prepared to decrypt with |
115 // the new server write key. We can start to encrypt with the new server | 126 // the new server write key. We can start to encrypt with the new server |
116 // write key. | 127 // write key. |
117 // | 128 // |
118 // NOTE: the SHLO will be encrypted with the new server write key. | 129 // NOTE: the SHLO will be encrypted with the new server write key. |
119 session()->connection()->SetEncrypter( | 130 session()->connection()->SetEncrypter( |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 const ValidateClientHelloResultCallback::Result& result, | 227 const ValidateClientHelloResultCallback::Result& result, |
217 CryptoHandshakeMessage* reply, | 228 CryptoHandshakeMessage* reply, |
218 string* error_details) { | 229 string* error_details) { |
219 // Store the bandwidth estimate from the client. | 230 // Store the bandwidth estimate from the client. |
220 if (result.cached_network_params.bandwidth_estimate_bytes_per_second() > 0) { | 231 if (result.cached_network_params.bandwidth_estimate_bytes_per_second() > 0) { |
221 previous_cached_network_params_.reset( | 232 previous_cached_network_params_.reset( |
222 new CachedNetworkParameters(result.cached_network_params)); | 233 new CachedNetworkParameters(result.cached_network_params)); |
223 } | 234 } |
224 previous_source_address_tokens_ = result.info.source_address_tokens; | 235 previous_source_address_tokens_ = result.info.source_address_tokens; |
225 | 236 |
| 237 const bool use_stateless_rejects_in_crypto_config = |
| 238 FLAGS_enable_quic_stateless_reject_support && |
| 239 use_stateless_rejects_if_peer_supported_ && |
| 240 peer_supports_stateless_rejects_; |
226 QuicConnection* connection = session()->connection(); | 241 QuicConnection* connection = session()->connection(); |
| 242 const QuicConnectionId server_designated_connection_id = |
| 243 use_stateless_rejects_in_crypto_config |
| 244 ? GenerateConnectionIdForReject(connection->connection_id()) |
| 245 : 0; |
227 return crypto_config_->ProcessClientHello( | 246 return crypto_config_->ProcessClientHello( |
228 result, connection->connection_id(), connection->self_address().address(), | 247 result, connection->connection_id(), connection->self_address().address(), |
229 connection->peer_address(), version(), connection->supported_versions(), | 248 connection->peer_address(), version(), connection->supported_versions(), |
230 /* use_stateless_rejects= */ false, | 249 use_stateless_rejects_in_crypto_config, server_designated_connection_id, |
231 /* server_designated_connection_id= */ 0, connection->clock(), | 250 connection->clock(), connection->random_generator(), |
232 connection->random_generator(), &crypto_negotiated_params_, reply, | 251 &crypto_negotiated_params_, reply, error_details); |
233 error_details); | |
234 } | 252 } |
235 | 253 |
236 void QuicCryptoServerStream::OverrideQuicConfigDefaults(QuicConfig* config) { | 254 void QuicCryptoServerStream::OverrideQuicConfigDefaults(QuicConfig* config) { |
237 } | 255 } |
238 | 256 |
239 const CachedNetworkParameters* | 257 const CachedNetworkParameters* |
240 QuicCryptoServerStream::previous_cached_network_params() const { | 258 QuicCryptoServerStream::previous_cached_network_params() const { |
241 return previous_cached_network_params_.get(); | 259 return previous_cached_network_params_.get(); |
242 } | 260 } |
243 | 261 |
244 QuicCryptoServerStream::ValidateCallback::ValidateCallback( | 262 QuicCryptoServerStream::ValidateCallback::ValidateCallback( |
245 QuicCryptoServerStream* parent) : parent_(parent) { | 263 QuicCryptoServerStream* parent) : parent_(parent) { |
246 } | 264 } |
247 | 265 |
248 void QuicCryptoServerStream::ValidateCallback::Cancel() { parent_ = nullptr; } | 266 void QuicCryptoServerStream::ValidateCallback::Cancel() { parent_ = nullptr; } |
249 | 267 |
250 void QuicCryptoServerStream::ValidateCallback::RunImpl( | 268 void QuicCryptoServerStream::ValidateCallback::RunImpl( |
251 const CryptoHandshakeMessage& client_hello, | 269 const CryptoHandshakeMessage& client_hello, |
252 const Result& result) { | 270 const Result& result) { |
253 if (parent_ != nullptr) { | 271 if (parent_ != nullptr) { |
254 parent_->FinishProcessingHandshakeMessage(client_hello, result); | 272 parent_->FinishProcessingHandshakeMessage(client_hello, result); |
255 } | 273 } |
256 } | 274 } |
257 | 275 |
| 276 QuicConnectionId QuicCryptoServerStream::GenerateConnectionIdForReject( |
| 277 QuicConnectionId connection_id) { |
| 278 return session()->connection()->random_generator()->RandUint64(); |
| 279 } |
| 280 |
| 281 // TODO(jokulik): Once stateless rejects support is inherent in the version |
| 282 // number, this function will likely go away entirely. |
| 283 // static |
| 284 bool QuicCryptoServerStream::DoesPeerSupportStatelessRejects( |
| 285 const CryptoHandshakeMessage& message) { |
| 286 const QuicTag* received_tags; |
| 287 size_t received_tags_length; |
| 288 QuicErrorCode error = |
| 289 message.GetTaglist(kCOPT, &received_tags, &received_tags_length); |
| 290 if (error != QUIC_NO_ERROR) { |
| 291 return false; |
| 292 } |
| 293 for (size_t i = 0; i < received_tags_length; ++i) { |
| 294 if (received_tags[i] == kSREJ) { |
| 295 return true; |
| 296 } |
| 297 } |
| 298 return false; |
| 299 } |
| 300 |
258 } // namespace net | 301 } // namespace net |
OLD | NEW |