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 QuartcSession::QuartcSession(std::unique_ptr<QuicConnection> connection, |
| 107 const QuicConfig& config, |
| 108 const std::string& unique_remote_server_id, |
| 109 Perspective perspective, |
| 110 QuicConnectionHelperInterface* helper) |
| 111 : QuicSession(connection.get(), nullptr /*visitor*/, config), |
| 112 unique_remote_server_id_(unique_remote_server_id), |
| 113 perspective_(perspective), |
| 114 connection_(std::move(connection)), |
| 115 helper_(helper) { |
| 116 // Initialization with default crypto configuration. |
| 117 if (perspective_ == Perspective::IS_CLIENT) { |
| 118 std::unique_ptr<ProofVerifier> proof_verifier(new InsecureProofVerifier); |
| 119 quic_crypto_client_config_.reset( |
| 120 new QuicCryptoClientConfig(std::move(proof_verifier))); |
| 121 } else { |
| 122 std::unique_ptr<ProofSource> proof_source(new DummyProofSource); |
| 123 std::string source_address_token_secret = |
| 124 base::RandBytesAsString(kInputKeyingMaterialLength); |
| 125 quic_crypto_server_config_.reset(new QuicCryptoServerConfig( |
| 126 source_address_token_secret, helper_->GetRandomGenerator(), |
| 127 std::move(proof_source))); |
| 128 // Provide server with serialized config string to prove ownership. |
| 129 QuicCryptoServerConfig::ConfigOptions options; |
| 130 // The |message| is used to handle the return value of AddDefaultConfig |
| 131 // which is raw pointer of the CryptoHandshakeMessage. |
| 132 std::unique_ptr<CryptoHandshakeMessage> message( |
| 133 quic_crypto_server_config_->AddDefaultConfig( |
| 134 helper_->GetRandomGenerator(), helper_->GetClock(), options)); |
| 135 } |
| 136 } |
| 137 |
| 138 QuartcSession::~QuartcSession() {} |
| 139 |
| 140 QuicCryptoStream* QuartcSession::GetCryptoStream() { |
| 141 return crypto_stream_.get(); |
| 142 } |
| 143 |
| 144 QuartcStream* QuartcSession::CreateOutgoingDynamicStream( |
| 145 SpdyPriority priority) { |
| 146 return CreateDataStream(GetNextOutgoingStreamId(), priority); |
| 147 } |
| 148 |
| 149 void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { |
| 150 QuicSession::OnCryptoHandshakeEvent(event); |
| 151 if (event == HANDSHAKE_CONFIRMED) { |
| 152 DCHECK(IsEncryptionEstablished()); |
| 153 DCHECK(IsCryptoHandshakeConfirmed()); |
| 154 |
| 155 DCHECK(session_delegate_); |
| 156 session_delegate_->OnCryptoHandshakeComplete(); |
| 157 } |
| 158 } |
| 159 |
| 160 void QuartcSession::CloseStream(QuicStreamId stream_id) { |
| 161 if (IsClosedStream(stream_id)) { |
| 162 // When CloseStream has been called recursively (via |
| 163 // ReliableQuicStream::OnClose), the stream is already closed so return. |
| 164 return; |
| 165 } |
| 166 write_blocked_streams()->UnregisterStream(stream_id); |
| 167 QuicSession::CloseStream(stream_id); |
| 168 } |
| 169 |
| 170 void QuartcSession::OnConnectionClosed(QuicErrorCode error, |
| 171 const std::string& error_details, |
| 172 ConnectionCloseSource source) { |
| 173 QuicSession::OnConnectionClosed(error, error_details, source); |
| 174 DCHECK(session_delegate_); |
| 175 session_delegate_->OnConnectionClosed( |
| 176 error, source == ConnectionCloseSource::FROM_PEER); |
| 177 } |
| 178 |
| 179 void QuartcSession::StartCryptoHandshake() { |
| 180 if (perspective_ == Perspective::IS_CLIENT) { |
| 181 QuicServerId server_id(unique_remote_server_id_, kQuicServerPort); |
| 182 QuicCryptoClientStream* crypto_stream = |
| 183 new QuicCryptoClientStream(server_id, this, new ProofVerifyContext(), |
| 184 quic_crypto_client_config_.get(), this); |
| 185 crypto_stream_.reset(crypto_stream); |
| 186 QuicSession::Initialize(); |
| 187 crypto_stream->CryptoConnect(); |
| 188 } else { |
| 189 quic_compressed_certs_cache_.reset(new QuicCompressedCertsCache( |
| 190 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize)); |
| 191 bool use_stateless_rejects_if_peer_supported = false; |
| 192 QuicCryptoServerStream* crypto_stream = new QuicCryptoServerStream( |
| 193 quic_crypto_server_config_.get(), quic_compressed_certs_cache_.get(), |
| 194 use_stateless_rejects_if_peer_supported, this, &stream_helper_); |
| 195 crypto_stream_.reset(crypto_stream); |
| 196 QuicSession::Initialize(); |
| 197 } |
| 198 } |
| 199 |
| 200 bool QuartcSession::ExportKeyingMaterial(const std::string& label, |
| 201 const uint8_t* context, |
| 202 size_t context_len, |
| 203 bool used_context, |
| 204 uint8_t* result, |
| 205 size_t result_len) { |
| 206 std::string quic_context(reinterpret_cast<const char*>(context), context_len); |
| 207 std::string quic_result; |
| 208 bool success = crypto_stream_->ExportKeyingMaterial(label, quic_context, |
| 209 result_len, &quic_result); |
| 210 quic_result.copy(reinterpret_cast<char*>(result), result_len); |
| 211 DCHECK(quic_result.length() == result_len); |
| 212 return success; |
| 213 } |
| 214 |
| 215 QuartcStreamInterface* QuartcSession::CreateOutgoingStream( |
| 216 const OutgoingStreamParameters& param) { |
| 217 // The |param| is for forward-compatibility. Not used for now. |
| 218 return CreateOutgoingDynamicStream(kDefaultPriority); |
| 219 } |
| 220 |
| 221 void QuartcSession::SetDelegate( |
| 222 QuartcSessionInterface::Delegate* session_delegate) { |
| 223 if (session_delegate_) { |
| 224 LOG(WARNING) << "The delegate for the session has already been set."; |
| 225 } |
| 226 session_delegate_ = session_delegate; |
| 227 DCHECK(session_delegate_); |
| 228 } |
| 229 |
| 230 void QuartcSession::OnTransportCanWrite() { |
| 231 if (HasDataToWrite()) { |
| 232 connection()->OnCanWrite(); |
| 233 } |
| 234 } |
| 235 |
| 236 bool QuartcSession::OnTransportReceived(const char* data, size_t data_len) { |
| 237 QuicReceivedPacket packet(data, data_len, clock_.Now()); |
| 238 ProcessUdpPacket(connection()->self_address(), connection()->peer_address(), |
| 239 packet); |
| 240 return true; |
| 241 } |
| 242 |
| 243 void QuartcSession::OnProofValid( |
| 244 const QuicCryptoClientConfig::CachedState& cached) { |
| 245 // TODO(zhihuang): Handle the proof verification. |
| 246 } |
| 247 |
| 248 void QuartcSession::OnProofVerifyDetailsAvailable( |
| 249 const ProofVerifyDetails& verify_details) { |
| 250 // TODO(zhihuang): Handle the proof verification. |
| 251 } |
| 252 |
| 253 void QuartcSession::SetClientCryptoConfig( |
| 254 QuicCryptoClientConfig* client_config) { |
| 255 quic_crypto_client_config_.reset(client_config); |
| 256 } |
| 257 |
| 258 void QuartcSession::SetServerCryptoConfig( |
| 259 QuicCryptoServerConfig* server_config) { |
| 260 quic_crypto_server_config_.reset(server_config); |
| 261 } |
| 262 |
| 263 ReliableQuicStream* QuartcSession::CreateIncomingDynamicStream( |
| 264 QuicStreamId id) { |
| 265 QuartcStream* stream = CreateDataStream(id, kDefaultPriority); |
| 266 if (stream) { |
| 267 DCHECK(session_delegate_); |
| 268 session_delegate_->OnIncomingStream(stream); |
| 269 } |
| 270 return stream; |
| 271 } |
| 272 |
| 273 QuartcStream* QuartcSession::CreateDataStream(QuicStreamId id, |
| 274 SpdyPriority priority) { |
| 275 if (crypto_stream_ == nullptr || !crypto_stream_->encryption_established()) { |
| 276 // Encryption not active so no stream created |
| 277 return nullptr; |
| 278 } |
| 279 QuartcStream* stream = new QuartcStream(id, this); |
| 280 if (stream) { |
| 281 // Make QuicSession take ownership of the stream. |
| 282 ActivateStream(std::unique_ptr<ReliableQuicStream>(stream)); |
| 283 // Register the stream to the QuicWriteBlockedList. |priority| is clamped |
| 284 // between 0 and 7, with 0 being the highest priority and 7 the lowest |
| 285 // priority. |
| 286 write_blocked_streams()->RegisterStream(stream->id(), priority); |
| 287 } |
| 288 return stream; |
| 289 } |
| 290 |
| 291 } // namespace net |
OLD | NEW |