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