OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/quic/quartc/quartc_session.h" | |
6 | |
7 #include "base/rand_util.h" | |
8 | |
9 namespace { | |
10 | |
11 // Default priority for incoming QUIC streams. | |
12 // TODO(zhihuang): Determine if this value is correct. | |
13 static const net::SpdyPriority kDefaultPriority = 3; | |
14 | |
15 // Arbitrary server port number for net::QuicCryptoClientConfig. | |
16 const int kQuicServerPort = 0; | |
17 | |
18 // Length of HKDF input keying material, equal to its number of bytes. | |
19 // https://tools.ietf.org/html/rfc5869#section-2.2. | |
20 // TODO(zhihuang): Verify that input keying material length is correct. | |
21 const size_t kInputKeyingMaterialLength = 32; | |
22 | |
23 // Used by QuicCryptoServerConfig to provide dummy proof credentials. | |
24 // TODO(zhihuang): Remove when secure P2P QUIC handshake is possible. | |
25 class DummyProofSource : public net::ProofSource { | |
26 public: | |
27 DummyProofSource() {} | |
28 ~DummyProofSource() override {} | |
29 | |
30 // ProofSource override. | |
31 bool GetProof(const net::IPAddress& server_ip, | |
32 const std::string& hostname, | |
33 const std::string& server_config, | |
34 net::QuicVersion quic_version, | |
35 base::StringPiece chlo_hash, | |
36 scoped_refptr<net::ProofSource::Chain>* out_chain, | |
37 std::string* out_signature, | |
38 std::string* out_leaf_cert_sct) override { | |
39 std::vector<std::string> certs; | |
40 certs.push_back("Dummy cert"); | |
41 *out_chain = new ProofSource::Chain(certs); | |
42 *out_signature = "Dummy signature"; | |
43 *out_leaf_cert_sct = "Dummy timestamp"; | |
44 return true; | |
45 } | |
46 | |
47 void GetProof(const net::IPAddress& server_ip, | |
48 const std::string& hostname, | |
49 const std::string& server_config, | |
50 net::QuicVersion quic_version, | |
51 base::StringPiece chlo_hash, | |
52 std::unique_ptr<Callback> callback) override {} | |
53 }; | |
54 | |
55 // Used by QuicCryptoClientConfig to ignore the peer's credentials | |
56 // and establish an insecure QUIC connection. | |
57 // TODO(zhihuang): Remove when secure P2P QUIC handshake is possible. | |
58 class InsecureProofVerifier : public net::ProofVerifier { | |
59 public: | |
60 InsecureProofVerifier() {} | |
61 ~InsecureProofVerifier() override {} | |
62 | |
63 // ProofVerifier override. | |
64 net::QuicAsyncStatus VerifyProof( | |
65 const std::string& hostname, | |
66 const uint16_t port, | |
67 const std::string& server_config, | |
68 net::QuicVersion quic_version, | |
69 base::StringPiece chlo_hash, | |
70 const std::vector<std::string>& certs, | |
71 const std::string& cert_sct, | |
72 const std::string& signature, | |
73 const net::ProofVerifyContext* context, | |
74 std::string* error_details, | |
75 std::unique_ptr<net::ProofVerifyDetails>* verify_details, | |
76 std::unique_ptr<net::ProofVerifierCallback> callback) override { | |
77 return net::QUIC_SUCCESS; | |
78 } | |
79 | |
80 net::QuicAsyncStatus VerifyCertChain( | |
81 const std::string& hostname, | |
82 const std::vector<std::string>& certs, | |
83 const net::ProofVerifyContext* context, | |
84 std::string* error_details, | |
85 std::unique_ptr<net::ProofVerifyDetails>* details, | |
86 std::unique_ptr<net::ProofVerifierCallback> callback) override { | |
87 return net::QUIC_SUCCESS; | |
88 } | |
89 }; | |
90 } | |
91 | |
92 namespace net { | |
93 | |
94 QuicConnectionId QuartcCryptoServerStreamHelper::GenerateConnectionIdForReject( | |
95 QuicConnectionId connection_id) const { | |
96 return 0; | |
97 } | |
98 | |
99 bool QuartcCryptoServerStreamHelper::CanAcceptClientHello( | |
100 const CryptoHandshakeMessage& message, | |
101 const IPEndPoint& self_address, | |
102 std::string* error_details) const { | |
103 return true; | |
104 } | |
105 | |
106 void QuartcSessionTransportDelegate::OnCanWrite() { | |
107 OnQuartcCanWrite(); | |
108 } | |
109 | |
110 QuartcSession::QuartcSession( | |
111 std::unique_ptr<QuicConnection> connection, | |
112 const QuicConfig& config, | |
113 const std::string& remote_fingerprint_value, | |
114 Perspective perspective, | |
115 QuartcSessionInterface::Transport* session_transport) | |
116 : QuicSession(connection.get(), config), | |
117 remote_fingerprint_value_(remote_fingerprint_value), | |
118 perspective_(perspective), | |
119 connection_(std::move(connection)), | |
120 session_transport_(session_transport) { | |
121 // Initialization with default crypto configuration. | |
122 if (perspective_ == Perspective::IS_CLIENT) { | |
123 std::unique_ptr<ProofVerifier> proof_verifier(new InsecureProofVerifier); | |
124 quic_crypto_client_config_.reset( | |
125 new QuicCryptoClientConfig(std::move(proof_verifier))); | |
126 } else { | |
127 std::unique_ptr<ProofSource> proof_source(new DummyProofSource); | |
128 std::string source_address_token_secret = | |
129 base::RandBytesAsString(kInputKeyingMaterialLength); | |
130 quic_crypto_server_config_.reset(new QuicCryptoServerConfig( | |
131 source_address_token_secret, helper_.GetRandomGenerator(), | |
132 std::move(proof_source))); | |
133 // Provide server with serialized config string to prove ownership. | |
134 QuicCryptoServerConfig::ConfigOptions options; | |
135 quic_crypto_server_config_->AddDefaultConfig(helper_.GetRandomGenerator(), | |
136 helper_.GetClock(), options); | |
137 } | |
138 // Set the delegate for the |session_transport_|. | |
139 DCHECK(session_transport_); | |
140 session_transport_->SetDelegate(this); | |
141 } | |
142 | |
143 QuartcSession::~QuartcSession() {} | |
144 | |
145 QuicCryptoStream* QuartcSession::GetCryptoStream() { | |
146 return crypto_stream_.get(); | |
147 } | |
148 | |
149 QuartcStream* QuartcSession::CreateOutgoingDynamicStream( | |
150 SpdyPriority priority) { | |
151 return CreateDataStream(GetNextOutgoingStreamId(), priority); | |
152 } | |
153 | |
154 void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { | |
155 QuicSession::OnCryptoHandshakeEvent(event); | |
156 if (event == HANDSHAKE_CONFIRMED) { | |
157 DCHECK(IsEncryptionEstablished()); | |
158 DCHECK(IsCryptoHandshakeConfirmed()); | |
159 | |
160 DCHECK(session_delegate_); | |
161 session_delegate_->OnCryptoHandshakeComplete(); | |
162 } | |
163 } | |
164 | |
165 void QuartcSession::CloseStream(QuicStreamId stream_id) { | |
166 if (IsClosedStream(stream_id)) { | |
167 // When CloseStream has been called recursively (via | |
168 // ReliableQuicStream::OnClose), the stream is already closed so return. | |
169 return; | |
170 } | |
171 write_blocked_streams()->UnregisterStream(stream_id); | |
172 QuicSession::CloseStream(stream_id); | |
173 } | |
174 | |
175 void QuartcSession::OnConnectionClosed(QuicErrorCode error, | |
176 const std::string& error_details, | |
177 ConnectionCloseSource source) { | |
178 QuicSession::OnConnectionClosed(error, error_details, source); | |
179 DCHECK(session_delegate_); | |
180 session_delegate_->OnConnectionClosed( | |
181 error, source == ConnectionCloseSource::FROM_PEER); | |
182 } | |
183 | |
184 void QuartcSession::StartCryptoHandshake() { | |
185 if (perspective_ == Perspective::IS_CLIENT) { | |
186 QuicServerId server_id(remote_fingerprint_value_, kQuicServerPort); | |
187 QuicCryptoClientStream* crypto_stream = | |
188 new QuicCryptoClientStream(server_id, this, new ProofVerifyContext(), | |
189 quic_crypto_client_config_.get(), this); | |
190 crypto_stream_.reset(crypto_stream); | |
191 QuicSession::Initialize(); | |
192 crypto_stream->CryptoConnect(); | |
193 } else { | |
194 quic_compressed_certs_cache_.reset(new QuicCompressedCertsCache( | |
195 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize)); | |
196 bool use_stateless_rejects_if_peer_supported = false; | |
197 QuicCryptoServerStream* crypto_stream = new QuicCryptoServerStream( | |
198 quic_crypto_server_config_.get(), quic_compressed_certs_cache_.get(), | |
199 use_stateless_rejects_if_peer_supported, this, &stream_helper_); | |
200 crypto_stream_.reset(crypto_stream); | |
201 QuicSession::Initialize(); | |
202 } | |
203 } | |
204 | |
205 bool QuartcSession::ExportKeyingMaterial(const std::string& label, | |
206 const uint8_t* context, | |
207 size_t context_len, | |
208 bool used_context, | |
209 uint8_t* result, | |
210 size_t result_len) { | |
211 std::string quic_context(reinterpret_cast<const char*>(context), context_len); | |
212 std::string quic_result; | |
213 bool success = crypto_stream_->ExportKeyingMaterial(label, quic_context, | |
214 result_len, &quic_result); | |
215 quic_result.copy(reinterpret_cast<char*>(result), result_len); | |
216 DCHECK(quic_result.length() == result_len); | |
217 return success; | |
218 } | |
219 | |
220 QuartcStreamInterface* QuartcSession::CreateOutgoingStream( | |
221 const OutgoingStreamParameters& param) { | |
222 // The |param| is for forward-compatibility. Not used for now. | |
223 return CreateOutgoingDynamicStream(kDefaultPriority); | |
224 } | |
225 | |
226 void QuartcSession::OnQuartcCanWrite() { | |
227 connection()->OnCanWrite(); | |
228 } | |
229 | |
230 void QuartcSession::SetDelegate( | |
231 QuartcSessionInterface::Delegate* session_delegate) { | |
232 if (session_delegate_) { | |
233 DVLOG(1) << "The delegate for the session has already been set."; | |
234 return; | |
235 } | |
236 session_delegate_ = session_delegate; | |
237 DCHECK(session_delegate_); | |
238 } | |
239 | |
240 // Decrypts an incoming QUIC packet to a data stream. | |
pthatcher2
2016/10/05 22:12:06
I don't think this comment is needed.
zhihuang1
2016/10/13 06:22:40
Done.
| |
241 bool QuartcSession::OnReceived(const char* data, size_t data_len) { | |
242 QuicReceivedPacket packet(data, data_len, clock_.Now()); | |
243 ProcessUdpPacket(connection()->self_address(), connection()->peer_address(), | |
244 packet); | |
245 return true; | |
246 } | |
247 | |
248 void QuartcSession::OnProofValid( | |
249 const QuicCryptoClientConfig::CachedState& cached) { | |
250 // TODO(zhihuang): Handle the proof verification. | |
251 } | |
252 | |
253 void QuartcSession::OnProofVerifyDetailsAvailable( | |
254 const ProofVerifyDetails& verify_details) { | |
255 // TODO(zhihuang): Handle the proof verification. | |
256 } | |
257 | |
258 void QuartcSession::SetClientCryptoConfig( | |
259 QuicCryptoClientConfig* client_config) { | |
260 quic_crypto_client_config_.reset(client_config); | |
261 } | |
262 | |
263 void QuartcSession::SetServerCryptoConfig( | |
264 QuicCryptoServerConfig* server_config) { | |
265 quic_crypto_server_config_.reset(server_config); | |
266 } | |
267 | |
268 ReliableQuicStream* QuartcSession::CreateIncomingDynamicStream( | |
269 QuicStreamId id) { | |
270 QuartcStream* stream = CreateDataStream(id, kDefaultPriority); | |
271 if (stream) { | |
272 DCHECK(session_delegate_); | |
273 session_delegate_->OnIncomingStream(stream); | |
274 } | |
275 return stream; | |
276 } | |
277 | |
278 QuartcStream* QuartcSession::CreateDataStream(QuicStreamId id, | |
279 SpdyPriority priority) { | |
280 if (crypto_stream_ == nullptr || !crypto_stream_->encryption_established()) { | |
281 // Encryption not active so no stream created | |
282 return nullptr; | |
283 } | |
284 QuartcStream* stream = new QuartcStream(id, this); | |
285 if (stream) { | |
286 // Make QuicSession take ownership of the stream. | |
287 ActivateStream(stream); | |
288 // Register the stream to the QuicWriteBlockedList. |priority| is clamped | |
289 // between 0 and 7, with 0 being the highest priority and 7 the lowest | |
290 // priority. | |
291 write_blocked_streams()->RegisterStream(stream->id(), priority); | |
292 } | |
293 return stream; | |
294 } | |
295 | |
296 } // namespace net | |
OLD | NEW |