1
#include "source/common/quic/quic_client_transport_socket_factory.h"
2

            
3
#include <memory>
4

            
5
#include "envoy/extensions/transport_sockets/quic/v3/quic_transport.pb.validate.h"
6

            
7
#include "source/common/quic/envoy_quic_proof_verifier.h"
8
#include "source/common/quic/envoy_quic_utils.h"
9
#include "source/common/tls/context_config_impl.h"
10

            
11
#include "quiche/quic/core/crypto/quic_client_session_cache.h"
12

            
13
namespace Envoy {
14
namespace Quic {
15

            
16
absl::StatusOr<std::unique_ptr<QuicClientTransportSocketFactory>>
17
QuicClientTransportSocketFactory::create(
18
    Ssl::ClientContextConfigPtr config,
19
2213
    Server::Configuration::TransportSocketFactoryContext& context) {
20
2213
  if (config->tlsCertificateSelectorFactory()) {
21
1
    return absl::UnimplementedError("Client certificate selector not supported on QUIC");
22
1
  }
23
2212
  absl::Status creation_status = absl::OkStatus();
24
2212
  auto factory = std::unique_ptr<QuicClientTransportSocketFactory>(
25
2212
      new QuicClientTransportSocketFactory(std::move(config), context, creation_status));
26
2212
  RETURN_IF_NOT_OK(creation_status);
27
2212
  factory->initialize();
28
2212
  return factory;
29
2212
}
30

            
31
absl::StatusOr<Network::UpstreamTransportSocketFactoryPtr>
32
QuicClientTransportSocketConfigFactory::createTransportSocketFactory(
33
    const Protobuf::Message& config,
34
2191
    Server::Configuration::TransportSocketFactoryContext& context) {
35
2191
  auto quic_transport = MessageUtil::downcastAndValidate<
36
2191
      const envoy::extensions::transport_sockets::quic::v3::QuicUpstreamTransport&>(
37
2191
      config, context.messageValidationVisitor());
38
2191
  absl::StatusOr<std::unique_ptr<Extensions::TransportSockets::Tls::ClientContextConfigImpl>>
39
2191
      client_config_or_error = Extensions::TransportSockets::Tls::ClientContextConfigImpl::create(
40
2191
          quic_transport.upstream_tls_context(), context);
41
2191
  RETURN_IF_NOT_OK(client_config_or_error.status());
42
2191
  return QuicClientTransportSocketFactory::create(std::move(*client_config_or_error), context);
43
2191
}
44

            
45
QuicClientTransportSocketFactory::QuicClientTransportSocketFactory(
46
    Ssl::ClientContextConfigPtr config,
47
    Server::Configuration::TransportSocketFactoryContext& factory_context,
48
    absl::Status& creation_status)
49
2214
    : QuicTransportSocketFactoryBase(factory_context.statsScope(), "client"),
50
2214
      tls_slot_(factory_context.serverFactoryContext().threadLocal()) {
51
2214
  auto factory_or_error = Extensions::TransportSockets::Tls::ClientSslSocketFactory::create(
52
2214
      std::move(config), factory_context.serverFactoryContext().sslContextManager(),
53
2214
      factory_context.statsScope());
54
2214
  SET_AND_RETURN_IF_NOT_OK(factory_or_error.status(), creation_status);
55
2214
  fallback_factory_ = std::move(*factory_or_error);
56
3267
  tls_slot_.set([](Event::Dispatcher&) { return std::make_shared<ThreadLocalQuicConfig>(); });
57
2214
}
58

            
59
2225
void QuicClientTransportSocketFactory::initialize() {
60
2225
  if (!fallback_factory_->clientContextConfig()->alpnProtocols().empty()) {
61
1064
    supported_alpns_ =
62
1064
        absl::StrSplit(fallback_factory_->clientContextConfig()->alpnProtocols(), ',');
63
1064
  }
64
2225
}
65

            
66
1595
ProtobufTypes::MessagePtr QuicClientTransportSocketConfigFactory::createEmptyConfigProto() {
67
1595
  return std::make_unique<envoy::extensions::transport_sockets::quic::v3::QuicUpstreamTransport>();
68
1595
}
69

            
70
2954
std::shared_ptr<quic::QuicCryptoClientConfig> QuicClientTransportSocketFactory::getCryptoConfig() {
71
2954
  Envoy::Ssl::ClientContextSharedPtr context = sslCtx();
72
  // If the secrets haven't been loaded, there is no crypto config.
73
2954
  if (context == nullptr) {
74
2
    ENVOY_LOG(warn, "SDS hasn't finished updating Ssl context config yet.");
75
2
    stats_.upstream_context_secrets_not_ready_.inc();
76
2
    return nullptr;
77
2
  }
78

            
79
2952
  ASSERT(tls_slot_.currentThreadRegistered());
80
2952
  ThreadLocalQuicConfig& tls_config = *tls_slot_;
81

            
82
2952
  if (tls_config.client_context_ != context) {
83
1769
    bool accept_untrusted =
84
1769
        clientContextConfig() && clientContextConfig()->certificateValidationContext() &&
85
1769
        clientContextConfig()->certificateValidationContext()->trustChainVerification() ==
86
1747
            envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext::
87
1747
                ACCEPT_UNTRUSTED;
88
    // If the context has been updated, update the crypto config.
89
1769
    tls_config.client_context_ = context;
90
1769
    tls_config.crypto_config_ = std::make_shared<quic::QuicCryptoClientConfig>(
91
1769
        std::make_unique<Quic::EnvoyQuicProofVerifier>(std::move(context), accept_untrusted),
92
1769
        std::make_unique<quic::QuicClientSessionCache>());
93

            
94
1769
    registerCertCompression(tls_config.crypto_config_->ssl_ctx());
95
1769
  }
96
  // Return the latest crypto config.
97
2952
  return tls_config.crypto_config_;
98
2954
}
99

            
100
REGISTER_FACTORY(QuicClientTransportSocketConfigFactory,
101
                 Server::Configuration::UpstreamTransportSocketConfigFactory);
102

            
103
} // namespace Quic
104
} // namespace Envoy