/proc/self/cwd/source/common/tls/context_impl.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <openssl/safestack.h> |
4 | | |
5 | | #include <array> |
6 | | #include <deque> |
7 | | #include <functional> |
8 | | #include <memory> |
9 | | #include <string> |
10 | | #include <vector> |
11 | | |
12 | | #include "envoy/network/transport_socket.h" |
13 | | #include "envoy/ssl/context.h" |
14 | | #include "envoy/ssl/context_config.h" |
15 | | #include "envoy/ssl/private_key/private_key.h" |
16 | | #include "envoy/ssl/ssl_socket_extended_info.h" |
17 | | #include "envoy/stats/scope.h" |
18 | | #include "envoy/stats/stats_macros.h" |
19 | | |
20 | | #include "source/common/common/matchers.h" |
21 | | #include "source/common/stats/symbol_table.h" |
22 | | #include "source/common/tls/cert_validator/cert_validator.h" |
23 | | #include "source/common/tls/context_manager_impl.h" |
24 | | #include "source/common/tls/stats.h" |
25 | | |
26 | | #include "absl/synchronization/mutex.h" |
27 | | #include "openssl/ssl.h" |
28 | | #include "openssl/x509v3.h" |
29 | | |
30 | | #ifdef ENVOY_ENABLE_QUIC |
31 | | #include "quiche/quic/core/crypto/proof_source.h" |
32 | | #endif |
33 | | |
34 | | namespace Envoy { |
35 | | #ifndef OPENSSL_IS_BORINGSSL |
36 | | #error Envoy requires BoringSSL |
37 | | #endif |
38 | | |
39 | | namespace Ssl { |
40 | | |
41 | | struct TlsContext { |
42 | | // Each certificate specified for the context has its own SSL_CTX. `SSL_CTXs` |
43 | | // are identical with the exception of certificate material, and can be |
44 | | // safely substituted via SSL_set_SSL_CTX() during the |
45 | | // SSL_CTX_set_select_certificate_cb() callback following ClientHello. |
46 | | bssl::UniquePtr<SSL_CTX> ssl_ctx_; |
47 | | bssl::UniquePtr<X509> cert_chain_; |
48 | | std::string cert_chain_file_path_; |
49 | | std::unique_ptr<OcspResponseWrapper> ocsp_response_; |
50 | | bool is_ecdsa_{}; |
51 | | bool is_must_staple_{}; |
52 | | Ssl::PrivateKeyMethodProviderSharedPtr private_key_method_provider_{}; |
53 | | |
54 | | #ifdef ENVOY_ENABLE_QUIC |
55 | | quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain> quic_cert_; |
56 | | std::shared_ptr<quic::CertificatePrivateKey> quic_private_key_; |
57 | | #endif |
58 | | |
59 | 0 | std::string getCertChainFileName() const { return cert_chain_file_path_; }; |
60 | | bool isCipherEnabled(uint16_t cipher_id, uint16_t client_version) const; |
61 | 0 | Envoy::Ssl::PrivateKeyMethodProviderSharedPtr getPrivateKeyMethodProvider() { |
62 | 0 | return private_key_method_provider_; |
63 | 0 | } |
64 | | absl::Status loadCertificateChain(const std::string& data, const std::string& data_path); |
65 | | absl::Status loadPrivateKey(const std::string& data, const std::string& data_path, |
66 | | const std::string& password); |
67 | | absl::Status loadPkcs12(const std::string& data, const std::string& data_path, |
68 | | const std::string& password); |
69 | | absl::Status checkPrivateKey(const bssl::UniquePtr<EVP_PKEY>& pkey, const std::string& key_path); |
70 | | }; |
71 | | } // namespace Ssl |
72 | | |
73 | | namespace Extensions { |
74 | | namespace TransportSockets { |
75 | | namespace Tls { |
76 | | |
77 | | class ContextImpl : public virtual Envoy::Ssl::Context, |
78 | | protected Logger::Loggable<Logger::Id::config> { |
79 | | public: |
80 | | virtual absl::StatusOr<bssl::UniquePtr<SSL>> |
81 | | newSsl(const Network::TransportSocketOptionsConstSharedPtr& options); |
82 | | |
83 | | /** |
84 | | * Logs successful TLS handshake and updates stats. |
85 | | * @param ssl the connection to log |
86 | | */ |
87 | | void logHandshake(SSL* ssl) const; |
88 | | |
89 | 0 | SslStats& stats() { return stats_; } |
90 | | |
91 | | /** |
92 | | * The global SSL-library index used for storing a pointer to the SslExtendedSocketInfo |
93 | | * class in the SSL instance, for retrieval in callbacks. |
94 | | */ |
95 | | static int sslExtendedSocketInfoIndex(); |
96 | | |
97 | | static int sslSocketIndex(); |
98 | | // Ssl::Context |
99 | | absl::optional<uint32_t> daysUntilFirstCertExpires() const override; |
100 | | Envoy::Ssl::CertificateDetailsPtr getCaCertInformation() const override; |
101 | | std::vector<Envoy::Ssl::CertificateDetailsPtr> getCertChainInformation() const override; |
102 | | absl::optional<uint64_t> secondsUntilFirstOcspResponseExpires() const override; |
103 | | |
104 | | std::vector<Ssl::PrivateKeyMethodProviderSharedPtr> getPrivateKeyMethodProviders(); |
105 | | |
106 | | // Validate cert asynchronously for a QUIC connection. |
107 | | ValidationResults customVerifyCertChainForQuic( |
108 | | STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, bool is_server, |
109 | | const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, |
110 | | const CertValidator::ExtraValidationContext& validation_context, |
111 | | const std::string& host_name); |
112 | | |
113 | | static void keylogCallback(const SSL* ssl, const char* line); |
114 | | |
115 | | protected: |
116 | | friend class ContextImplPeer; |
117 | | |
118 | | ContextImpl(Stats::Scope& scope, const Envoy::Ssl::ContextConfig& config, |
119 | | Server::Configuration::CommonFactoryContext& factory_context, |
120 | | Ssl::ContextAdditionalInitFunc additional_init, absl::Status& creation_status); |
121 | | |
122 | | /** |
123 | | * The global SSL-library index used for storing a pointer to the context |
124 | | * in the SSL instance, for retrieval in callbacks. |
125 | | */ |
126 | | static int sslContextIndex(); |
127 | | |
128 | | // A SSL_CTX_set_custom_verify callback for asynchronous cert validation. |
129 | | static enum ssl_verify_result_t customVerifyCallback(SSL* ssl, uint8_t* out_alert); |
130 | | |
131 | | bool parseAndSetAlpn(const std::vector<std::string>& alpn, SSL& ssl, absl::Status& parse_status); |
132 | | std::vector<uint8_t> parseAlpnProtocols(const std::string& alpn_protocols, |
133 | | absl::Status& parse_status); |
134 | | |
135 | | void incCounter(const Stats::StatName name, absl::string_view value, |
136 | | const Stats::StatName fallback) const; |
137 | | |
138 | | // Helper function to validate cert for TCP connections asynchronously. |
139 | | ValidationResults customVerifyCertChain( |
140 | | Envoy::Ssl::SslExtendedSocketInfo* extended_socket_info, |
141 | | const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, SSL* ssl); |
142 | | |
143 | | void populateServerNamesMap(Ssl::TlsContext& ctx, const int pkey_id); |
144 | | |
145 | | // This is always non-empty, with the first context used for all new SSL |
146 | | // objects. For server contexts, once we have ClientHello, we |
147 | | // potentially switch to a different CertificateContext based on certificate |
148 | | // selection. |
149 | | std::vector<Ssl::TlsContext> tls_contexts_; |
150 | | CertValidatorPtr cert_validator_; |
151 | | Stats::Scope& scope_; |
152 | | SslStats stats_; |
153 | | std::vector<uint8_t> parsed_alpn_protocols_; |
154 | | bssl::UniquePtr<X509> cert_chain_; |
155 | | std::string cert_chain_file_path_; |
156 | | Server::Configuration::CommonFactoryContext& factory_context_; |
157 | | const unsigned tls_max_version_; |
158 | | mutable Stats::StatNameSetPtr stat_name_set_; |
159 | | const Stats::StatName unknown_ssl_cipher_; |
160 | | const Stats::StatName unknown_ssl_curve_; |
161 | | const Stats::StatName unknown_ssl_algorithm_; |
162 | | const Stats::StatName unknown_ssl_version_; |
163 | | const Stats::StatName ssl_ciphers_; |
164 | | const Stats::StatName ssl_versions_; |
165 | | const Stats::StatName ssl_curves_; |
166 | | const Stats::StatName ssl_sigalgs_; |
167 | | const Ssl::HandshakerCapabilities capabilities_; |
168 | | const Network::Address::IpList tls_keylog_local_; |
169 | | const Network::Address::IpList tls_keylog_remote_; |
170 | | AccessLog::AccessLogFileSharedPtr tls_keylog_file_; |
171 | | }; |
172 | | |
173 | | using ContextImplSharedPtr = std::shared_ptr<ContextImpl>; |
174 | | |
175 | | class ServerContextFactory : public Envoy::Config::UntypedFactory { |
176 | | public: |
177 | 56 | std::string category() const override { return "envoy.ssl.server_context_factory"; } |
178 | | virtual absl::StatusOr<Ssl::ServerContextSharedPtr> |
179 | | createServerContext(Stats::Scope& scope, const Envoy::Ssl::ServerContextConfig& config, |
180 | | const std::vector<std::string>& server_names, |
181 | | Server::Configuration::CommonFactoryContext& factory_context, |
182 | | Ssl::ContextAdditionalInitFunc additional_init) PURE; |
183 | | }; |
184 | | |
185 | | } // namespace Tls |
186 | | } // namespace TransportSockets |
187 | | } // namespace Extensions |
188 | | } // namespace Envoy |