/proc/self/cwd/source/common/tls/ssl_handshaker.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <sys/types.h> |
4 | | |
5 | | #include <cstdint> |
6 | | |
7 | | #include "envoy/network/connection.h" |
8 | | #include "envoy/network/transport_socket.h" |
9 | | #include "envoy/secret/secret_callbacks.h" |
10 | | #include "envoy/server/options.h" |
11 | | #include "envoy/ssl/handshaker.h" |
12 | | #include "envoy/ssl/private_key/private_key_callbacks.h" |
13 | | #include "envoy/ssl/ssl_socket_extended_info.h" |
14 | | #include "envoy/ssl/ssl_socket_state.h" |
15 | | #include "envoy/stats/scope.h" |
16 | | #include "envoy/stats/stats_macros.h" |
17 | | |
18 | | #include "source/common/common/logger.h" |
19 | | #include "source/common/tls/connection_info_impl_base.h" |
20 | | #include "source/common/tls/utility.h" |
21 | | |
22 | | #include "absl/container/node_hash_map.h" |
23 | | #include "absl/synchronization/mutex.h" |
24 | | #include "absl/types/optional.h" |
25 | | #include "openssl/ssl.h" |
26 | | |
27 | | namespace Envoy { |
28 | | namespace Extensions { |
29 | | namespace TransportSockets { |
30 | | namespace Tls { |
31 | | |
32 | | class SslHandshakerImpl; |
33 | | class SslExtendedSocketInfoImpl; |
34 | | |
35 | | class ValidateResultCallbackImpl : public Ssl::ValidateResultCallback { |
36 | | public: |
37 | | ValidateResultCallbackImpl(Event::Dispatcher& dispatcher, |
38 | | SslExtendedSocketInfoImpl& extended_socket_info) |
39 | 0 | : dispatcher_(dispatcher), extended_socket_info_(extended_socket_info) {} |
40 | | |
41 | 0 | Event::Dispatcher& dispatcher() override { return dispatcher_; } |
42 | | |
43 | | void onCertValidationResult(bool succeeded, Ssl::ClientValidationStatus detailed_status, |
44 | | const std::string& error_details, uint8_t tls_alert) override; |
45 | | |
46 | | void onSslHandshakeCancelled(); |
47 | | |
48 | | private: |
49 | | Event::Dispatcher& dispatcher_; |
50 | | OptRef<SslExtendedSocketInfoImpl> extended_socket_info_; |
51 | | }; |
52 | | |
53 | | class CertificateSelectionCallbackImpl : public Ssl::CertificateSelectionCallback, |
54 | | protected Logger::Loggable<Logger::Id::connection> { |
55 | | public: |
56 | | CertificateSelectionCallbackImpl(Event::Dispatcher& dispatcher, |
57 | | SslExtendedSocketInfoImpl& extended_socket_info) |
58 | 0 | : dispatcher_(dispatcher), extended_socket_info_(extended_socket_info) {} |
59 | | |
60 | 0 | Event::Dispatcher& dispatcher() override { return dispatcher_; } |
61 | | |
62 | | void onCertificateSelectionResult(OptRef<const Ssl::TlsContext> selected_ctx, |
63 | | bool staple) override; |
64 | | |
65 | | void onSslHandshakeCancelled(); |
66 | | |
67 | | private: |
68 | | Event::Dispatcher& dispatcher_; |
69 | | OptRef<SslExtendedSocketInfoImpl> extended_socket_info_; |
70 | | }; |
71 | | |
72 | | class SslExtendedSocketInfoImpl : public Envoy::Ssl::SslExtendedSocketInfo { |
73 | | public: |
74 | 0 | explicit SslExtendedSocketInfoImpl(SslHandshakerImpl& handshaker) : ssl_handshaker_(handshaker) {} |
75 | | // Overridden to notify cert_validate_result_callback_ that the handshake has been cancelled. |
76 | | ~SslExtendedSocketInfoImpl() override; |
77 | | |
78 | | void setCertificateValidationStatus(Envoy::Ssl::ClientValidationStatus validated) override; |
79 | | Envoy::Ssl::ClientValidationStatus certificateValidationStatus() const override; |
80 | | Ssl::ValidateResultCallbackPtr createValidateResultCallback() override; |
81 | | void onCertificateValidationCompleted(bool succeeded, bool async) override; |
82 | 0 | Ssl::ValidateStatus certificateValidationResult() const override { |
83 | 0 | return cert_validation_result_; |
84 | 0 | } |
85 | 0 | uint8_t certificateValidationAlert() const override { return cert_validation_alert_; } |
86 | | |
87 | 0 | void setCertificateValidationAlert(uint8_t alert) { cert_validation_alert_ = alert; } |
88 | | |
89 | | Ssl::CertificateSelectionCallbackPtr createCertificateSelectionCallback() override; |
90 | | void onCertificateSelectionCompleted(OptRef<const Ssl::TlsContext> selected_ctx, bool staple, |
91 | | bool async) override; |
92 | 0 | Ssl::CertificateSelectionStatus certificateSelectionResult() const override { |
93 | 0 | return cert_selection_result_; |
94 | 0 | } |
95 | | |
96 | | private: |
97 | | Envoy::Ssl::ClientValidationStatus certificate_validation_status_{ |
98 | | Envoy::Ssl::ClientValidationStatus::NotValidated}; |
99 | | SslHandshakerImpl& ssl_handshaker_; |
100 | | // Latch the in-flight async cert validation callback. |
101 | | // nullopt if there is none. |
102 | | OptRef<ValidateResultCallbackImpl> cert_validate_result_callback_; |
103 | | // Stores the TLS alert. |
104 | | uint8_t cert_validation_alert_{SSL_AD_CERTIFICATE_UNKNOWN}; |
105 | | // Stores the validation result if there is any. |
106 | | // nullopt if no validation has ever been kicked off. |
107 | | Ssl::ValidateStatus cert_validation_result_{Ssl::ValidateStatus::NotStarted}; |
108 | | // Latch the in-flight cert selection callback. |
109 | | // nullopt if there is none. |
110 | | OptRef<CertificateSelectionCallbackImpl> cert_selection_callback_{absl::nullopt}; |
111 | | // Stores the cert selection result if there is any. |
112 | | // NotStarted if no cert selection has ever been kicked off. |
113 | | Ssl::CertificateSelectionStatus cert_selection_result_{ |
114 | | Ssl::CertificateSelectionStatus::NotStarted}; |
115 | | }; |
116 | | |
117 | | class SslHandshakerImpl : public ConnectionInfoImplBase, |
118 | | public Ssl::Handshaker, |
119 | | protected Logger::Loggable<Logger::Id::connection> { |
120 | | public: |
121 | | SslHandshakerImpl(bssl::UniquePtr<SSL> ssl, int ssl_extended_socket_info_index, |
122 | | Ssl::HandshakeCallbacks* handshake_callbacks); |
123 | | |
124 | | // Ssl::ConnectionInfo |
125 | | bool peerCertificateValidated() const override; |
126 | | |
127 | | // ConnectionInfoImplBase |
128 | 0 | SSL* ssl() const override { return ssl_.get(); } |
129 | | |
130 | | // Ssl::Handshaker |
131 | | Network::PostIoAction doHandshake() override; |
132 | | |
133 | 0 | Ssl::SocketState state() const { return state_; } |
134 | 0 | void setState(Ssl::SocketState state) { state_ = state; } |
135 | 0 | Ssl::HandshakeCallbacks* handshakeCallbacks() { return handshake_callbacks_; } |
136 | | |
137 | | bssl::UniquePtr<SSL> ssl_; |
138 | | |
139 | | private: |
140 | | Ssl::HandshakeCallbacks* handshake_callbacks_; |
141 | | |
142 | | Ssl::SocketState state_{Ssl::SocketState::PreHandshake}; |
143 | | mutable SslExtendedSocketInfoImpl extended_socket_info_; |
144 | | }; |
145 | | |
146 | | using SslHandshakerImplSharedPtr = std::shared_ptr<SslHandshakerImpl>; |
147 | | |
148 | | class HandshakerFactoryContextImpl : public Ssl::HandshakerFactoryContext { |
149 | | public: |
150 | | HandshakerFactoryContextImpl(Api::Api& api, const Server::Options& options, |
151 | | absl::string_view alpn_protocols, |
152 | | Singleton::Manager& singleton_manager, |
153 | | Server::ServerLifecycleNotifier& lifecycle_notifier) |
154 | | : api_(api), options_(options), alpn_protocols_(alpn_protocols), |
155 | 0 | singleton_manager_(singleton_manager), lifecycle_notifier_(lifecycle_notifier) {} |
156 | | |
157 | | // HandshakerFactoryContext |
158 | 0 | Api::Api& api() override { return api_; } |
159 | 0 | const Server::Options& options() const override { return options_; } |
160 | 0 | absl::string_view alpnProtocols() const override { return alpn_protocols_; } |
161 | 0 | Singleton::Manager& singletonManager() override { return singleton_manager_; } |
162 | 0 | Server::ServerLifecycleNotifier& lifecycleNotifier() override { return lifecycle_notifier_; } |
163 | | |
164 | | private: |
165 | | Api::Api& api_; |
166 | | const Server::Options& options_; |
167 | | const std::string alpn_protocols_; |
168 | | Singleton::Manager& singleton_manager_; |
169 | | Server::ServerLifecycleNotifier& lifecycle_notifier_; |
170 | | }; |
171 | | |
172 | | class HandshakerFactoryImpl : public Ssl::HandshakerFactory { |
173 | | public: |
174 | 0 | std::string name() const override { return "envoy.default_tls_handshaker"; } |
175 | | |
176 | 0 | ProtobufTypes::MessagePtr createEmptyConfigProto() override { |
177 | 0 | return ProtobufTypes::MessagePtr{new Envoy::ProtobufWkt::Struct()}; |
178 | 0 | } |
179 | | |
180 | | Ssl::HandshakerFactoryCb createHandshakerCb(const Protobuf::Message&, |
181 | | Ssl::HandshakerFactoryContext&, |
182 | 0 | ProtobufMessage::ValidationVisitor&) override { |
183 | | // The default HandshakerImpl doesn't take a config or use the HandshakerFactoryContext. |
184 | 0 | return [](bssl::UniquePtr<SSL> ssl, int ssl_extended_socket_info_index, |
185 | 0 | Ssl::HandshakeCallbacks* handshake_callbacks) { |
186 | 0 | return std::make_shared<SslHandshakerImpl>(std::move(ssl), ssl_extended_socket_info_index, |
187 | 0 | handshake_callbacks); |
188 | 0 | }; |
189 | 0 | } |
190 | | |
191 | 0 | Ssl::HandshakerCapabilities capabilities() const override { |
192 | | // The default handshaker impl requires Envoy to handle all enumerated behaviors. |
193 | 0 | return Ssl::HandshakerCapabilities{}; |
194 | 0 | } |
195 | | |
196 | 0 | Ssl::SslCtxCb sslctxCb(Ssl::HandshakerFactoryContext&) const override { |
197 | | // The default handshaker impl doesn't additionally modify SSL_CTX. |
198 | 0 | return nullptr; |
199 | 0 | } |
200 | | |
201 | 0 | static HandshakerFactory* getDefaultHandshakerFactory() { |
202 | 0 | static HandshakerFactoryImpl default_handshaker_factory; |
203 | 0 | return &default_handshaker_factory; |
204 | 0 | } |
205 | | }; |
206 | | |
207 | | } // namespace Tls |
208 | | } // namespace TransportSockets |
209 | | } // namespace Extensions |
210 | | } // namespace Envoy |