diff options
Diffstat (limited to 'chromium/net/third_party/quiche/src/quic/core/stateless_rejector.cc')
-rw-r--r-- | chromium/net/third_party/quiche/src/quic/core/stateless_rejector.cc | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/chromium/net/third_party/quiche/src/quic/core/stateless_rejector.cc b/chromium/net/third_party/quiche/src/quic/core/stateless_rejector.cc new file mode 100644 index 00000000000..e2ef51cb845 --- /dev/null +++ b/chromium/net/third_party/quiche/src/quic/core/stateless_rejector.cc @@ -0,0 +1,162 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/third_party/quiche/src/quic/core/stateless_rejector.h" + +#include <string> + +#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" + +namespace quic { + +class StatelessRejector::ValidateCallback + : public ValidateClientHelloResultCallback { + public: + explicit ValidateCallback( + std::unique_ptr<StatelessRejector> rejector, + std::unique_ptr<StatelessRejector::ProcessDoneCallback> cb) + : rejector_(std::move(rejector)), cb_(std::move(cb)) {} + + ~ValidateCallback() override = default; + + void Run(QuicReferenceCountedPointer<Result> result, + std::unique_ptr<ProofSource::Details> /* proof_source_details */) + override { + StatelessRejector* rejector_ptr = rejector_.get(); + rejector_ptr->ProcessClientHello(std::move(result), std::move(rejector_), + std::move(cb_)); + } + + private: + std::unique_ptr<StatelessRejector> rejector_; + std::unique_ptr<StatelessRejector::ProcessDoneCallback> cb_; +}; + +StatelessRejector::StatelessRejector( + ParsedQuicVersion version, + const ParsedQuicVersionVector& versions, + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache, + const QuicClock* clock, + QuicRandom* random, + QuicByteCount chlo_packet_size, + const QuicSocketAddress& client_address, + const QuicSocketAddress& server_address) + : state_(UNKNOWN), + error_(QUIC_INTERNAL_ERROR), + version_(version), + versions_(versions), + connection_id_(EmptyQuicConnectionId()), + chlo_packet_size_(chlo_packet_size), + client_address_(client_address), + server_address_(server_address), + clock_(clock), + random_(random), + crypto_config_(crypto_config), + compressed_certs_cache_(compressed_certs_cache), + signed_config_(new QuicSignedServerConfig), + params_(new QuicCryptoNegotiatedParameters) {} + +StatelessRejector::~StatelessRejector() = default; + +void StatelessRejector::OnChlo(QuicTransportVersion version, + QuicConnectionId connection_id, + QuicConnectionId server_designated_connection_id, + const CryptoHandshakeMessage& message) { + DCHECK_EQ(kCHLO, message.tag()); + DCHECK_NE(connection_id, server_designated_connection_id); + DCHECK_EQ(state_, UNKNOWN); + + if (!GetQuicReloadableFlag(enable_quic_stateless_reject_support) || + !GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) || + !QuicCryptoServerStream::DoesPeerSupportStatelessRejects(message)) { + state_ = UNSUPPORTED; + return; + } + + connection_id_ = connection_id; + server_designated_connection_id_ = server_designated_connection_id; + chlo_ = message; // Note: copies the message +} + +void StatelessRejector::Process(std::unique_ptr<StatelessRejector> rejector, + std::unique_ptr<ProcessDoneCallback> done_cb) { + QUIC_BUG_IF(rejector->state() != UNKNOWN) << "StatelessRejector::Process " + "called for a rejector which " + "has already made a decision"; + StatelessRejector* rejector_ptr = rejector.get(); + rejector_ptr->crypto_config_->ValidateClientHello( + rejector_ptr->chlo_, rejector_ptr->client_address_.host(), + rejector_ptr->server_address_, rejector_ptr->version_.transport_version, + rejector_ptr->clock_, rejector_ptr->signed_config_, + std::unique_ptr<ValidateCallback>( + new ValidateCallback(std::move(rejector), std::move(done_cb)))); +} + +class StatelessRejector::ProcessClientHelloCallback + : public ProcessClientHelloResultCallback { + public: + ProcessClientHelloCallback( + std::unique_ptr<StatelessRejector> rejector, + std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb) + : rejector_(std::move(rejector)), done_cb_(std::move(done_cb)) {} + + void Run(QuicErrorCode error, + const std::string& error_details, + std::unique_ptr<CryptoHandshakeMessage> message, + std::unique_ptr<DiversificationNonce> diversification_nonce, + std::unique_ptr<ProofSource::Details> /* proof_source_details */) + override { + StatelessRejector* rejector_ptr = rejector_.get(); + rejector_ptr->ProcessClientHelloDone( + error, error_details, std::move(message), std::move(rejector_), + std::move(done_cb_)); + } + + private: + std::unique_ptr<StatelessRejector> rejector_; + std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb_; +}; + +void StatelessRejector::ProcessClientHello( + QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> + result, + std::unique_ptr<StatelessRejector> rejector, + std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb) { + std::unique_ptr<ProcessClientHelloCallback> cb( + new ProcessClientHelloCallback(std::move(rejector), std::move(done_cb))); + crypto_config_->ProcessClientHello( + result, + /*reject_only=*/true, connection_id_, server_address_, client_address_, + version_, versions_, + /*use_stateless_rejects=*/true, server_designated_connection_id_, clock_, + random_, compressed_certs_cache_, params_, signed_config_, + QuicCryptoStream::CryptoMessageFramingOverhead(version_.transport_version, + connection_id_), + chlo_packet_size_, std::move(cb)); +} + +void StatelessRejector::ProcessClientHelloDone( + QuicErrorCode error, + const std::string& error_details, + std::unique_ptr<CryptoHandshakeMessage> message, + std::unique_ptr<StatelessRejector> rejector, + std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb) { + reply_ = std::move(message); + + if (error != QUIC_NO_ERROR) { + error_ = error; + error_details_ = error_details; + state_ = FAILED; + } else if (reply_->tag() == kSREJ) { + state_ = REJECTED; + } else { + state_ = ACCEPTED; + } + done_cb->Run(std::move(rejector)); +} + +} // namespace quic |