Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/envoy/ssl/handshaker.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include "envoy/api/api.h"
4
#include "envoy/config/typed_config.h"
5
#include "envoy/network/connection.h"
6
#include "envoy/network/post_io_action.h"
7
#include "envoy/protobuf/message_validator.h"
8
#include "envoy/server/lifecycle_notifier.h"
9
#include "envoy/server/options.h"
10
#include "envoy/singleton/manager.h"
11
12
#include "openssl/ssl.h"
13
14
namespace Envoy {
15
16
namespace Server {
17
namespace Configuration {
18
class CommonFactoryContext;
19
} // namespace Configuration
20
} // namespace Server
21
22
namespace Ssl {
23
24
// Opaque type defined and used by the ``ServerContext``.
25
struct TlsContext;
26
27
class ServerContextConfig;
28
29
class HandshakeCallbacks {
30
public:
31
0
  virtual ~HandshakeCallbacks() = default;
32
33
  /**
34
   * @return the connection.
35
   */
36
  virtual Network::Connection& connection() const PURE;
37
38
  /**
39
   * A callback which will be executed at most once upon successful completion
40
   * of a handshake.
41
   */
42
  virtual void onSuccess(SSL* ssl) PURE;
43
44
  /**
45
   * A callback which will be executed at most once upon handshake failure.
46
   */
47
  virtual void onFailure() PURE;
48
49
  /**
50
   * Returns a pointer to the transportSocketCallbacks struct, or nullptr if
51
   * unset.
52
   */
53
  virtual Network::TransportSocketCallbacks* transportSocketCallbacks() PURE;
54
55
  /**
56
   * A callback to be called upon certificate validation completion if the validation is
57
   * asynchronous.
58
   */
59
  virtual void onAsynchronousCertValidationComplete() PURE;
60
61
  /**
62
   * A callback to be called upon certificate selection completion if the selection is
63
   * asynchronous.
64
   */
65
  virtual void onAsynchronousCertificateSelectionComplete() PURE;
66
};
67
68
/**
69
 * Base interface for performing TLS handshakes.
70
 */
71
class Handshaker {
72
public:
73
0
  virtual ~Handshaker() = default;
74
75
  /**
76
   * Performs a TLS handshake and returns an action indicating
77
   * whether the callsite should close the connection or keep it open.
78
   */
79
  virtual Network::PostIoAction doHandshake() PURE;
80
};
81
82
using HandshakerSharedPtr = std::shared_ptr<Handshaker>;
83
using HandshakerFactoryCb =
84
    std::function<HandshakerSharedPtr(bssl::UniquePtr<SSL>, int, HandshakeCallbacks*)>;
85
86
// Callback for modifying an SSL_CTX.
87
using SslCtxCb = std::function<void(SSL_CTX*)>;
88
89
class HandshakerFactoryContext {
90
public:
91
0
  virtual ~HandshakerFactoryContext() = default;
92
93
  /**
94
   * Returns the singleton manager.
95
   */
96
  virtual Singleton::Manager& singletonManager() PURE;
97
98
  /**
99
   * @return reference to the server options
100
   */
101
  virtual const Server::Options& options() const PURE;
102
103
  /**
104
   * @return reference to the Api object
105
   */
106
  virtual Api::Api& api() PURE;
107
108
  /**
109
   * The list of supported protocols exposed via ALPN, from ContextConfig.
110
   */
111
  virtual absl::string_view alpnProtocols() const PURE;
112
113
  /**
114
   * @return reference to the server lifecycle notifier
115
   */
116
  virtual Server::ServerLifecycleNotifier& lifecycleNotifier() PURE;
117
};
118
119
struct HandshakerCapabilities {
120
  // Whether or not a handshaker implementation provides certificates itself.
121
  bool provides_certificates = false;
122
123
  // Whether or not a handshaker implementation verifies certificates itself.
124
  bool verifies_peer_certificates = false;
125
126
  // Whether or not a handshaker implementation handles session resumption
127
  // itself.
128
  bool handles_session_resumption = false;
129
130
  // Whether or not a handshaker implementation provides its own list of ciphers
131
  // and curves.
132
  bool provides_ciphers_and_curves = false;
133
134
  // Whether or not a handshaker implementation handles ALPN selection.
135
  bool handles_alpn_selection = false;
136
137
  // Should return true if this handshaker is FIPS-compliant.
138
  // Envoy will fail to compile if this returns true and `--define=boringssl=fips`.
139
  bool is_fips_compliant = true;
140
141
  // Whether or not a handshaker implementation provides its own list of
142
  // supported signature algorithms.
143
  bool provides_sigalgs = false;
144
};
145
146
class HandshakerFactory : public Config::TypedFactory {
147
public:
148
  /**
149
   * @returns a callback to create a Handshaker. Accepts the |config| and
150
   * |validation_visitor| for early validation. This virtual base doesn't
151
   * perform MessageUtil::downcastAndValidate, but an implementation should.
152
   */
153
  virtual HandshakerFactoryCb
154
  createHandshakerCb(const Protobuf::Message& message,
155
                     HandshakerFactoryContext& handshaker_factory_context,
156
                     ProtobufMessage::ValidationVisitor& validation_visitor) PURE;
157
158
0
  std::string category() const override { return "envoy.tls_handshakers"; }
159
160
  /**
161
   * Implementations should return a struct with their capabilities. See
162
   * HandshakerCapabilities above. For any capability a Handshaker
163
   * implementation explicitly declares, Envoy will not also configure that SSL
164
   * capability.
165
   */
166
  virtual HandshakerCapabilities capabilities() const PURE;
167
168
  /**
169
   * Implementations should return a callback for configuring an SSL_CTX context
170
   * before it is used to create any SSL objects. Providing
171
   * |handshaker_factory_context| as an argument allows callsites to access the
172
   * API and other factory context methods.
173
   */
174
  virtual SslCtxCb sslctxCb(HandshakerFactoryContext& handshaker_factory_context) const PURE;
175
};
176
177
struct SelectionResult {
178
  enum class SelectionStatus {
179
    // A certificate was successfully selected.
180
    Success,
181
    // Certificate selection will complete asynchronously later.
182
    Pending,
183
    // Certificate selection failed.
184
    Failed,
185
  };
186
  SelectionStatus status; // Status of the certificate selection.
187
  // Selected TLS context which it only be non-null when status is Success.
188
  const Ssl::TlsContext* selected_ctx;
189
  // True if OCSP stapling should be enabled.
190
  bool staple;
191
};
192
193
/**
194
 * Used to return the result from an asynchronous cert selection.
195
 */
196
class CertificateSelectionCallback {
197
public:
198
0
  virtual ~CertificateSelectionCallback() = default;
199
200
  virtual Event::Dispatcher& dispatcher() PURE;
201
202
  /**
203
   * Called when the asynchronous cert selection completes.
204
   * @param selected_ctx selected Ssl::TlsContext, it's empty when selection failed.
205
   * @param staple true when need to set OCSP response.
206
   */
207
  virtual void onCertificateSelectionResult(OptRef<const Ssl::TlsContext> selected_ctx,
208
                                            bool staple) PURE;
209
};
210
211
using CertificateSelectionCallbackPtr = std::unique_ptr<CertificateSelectionCallback>;
212
213
enum class OcspStapleAction { Staple, NoStaple, Fail, ClientNotCapable };
214
215
class TlsCertificateSelector {
216
public:
217
0
  virtual ~TlsCertificateSelector() = default;
218
219
  /**
220
   * Select TLS context based on the client hello in non-QUIC TLS handshake.
221
   *
222
   * @return selected_ctx should only not be null when status is SelectionStatus::Success, and it
223
   * will have the same lifetime as ``ServerContextImpl``.
224
   */
225
  virtual SelectionResult selectTlsContext(const SSL_CLIENT_HELLO& ssl_client_hello,
226
                                           CertificateSelectionCallbackPtr cb) PURE;
227
228
  /**
229
   * Finds the best matching context in QUIC TLS handshake, which doesn't support async mode yet.
230
   *
231
   * @return context will have the same lifetime as ``ServerContextImpl``.
232
   */
233
  virtual std::pair<const Ssl::TlsContext&, OcspStapleAction>
234
  findTlsContext(absl::string_view sni, bool client_ecdsa_capable, bool client_ocsp_capable,
235
                 bool* cert_matched_sni) PURE;
236
};
237
238
using TlsCertificateSelectorPtr = std::unique_ptr<TlsCertificateSelector>;
239
240
class TlsCertificateSelectorContext {
241
public:
242
0
  virtual ~TlsCertificateSelectorContext() = default;
243
244
  /**
245
   * @return reference to the initialized Tls Contexts.
246
   */
247
  virtual const std::vector<TlsContext>& getTlsContexts() const PURE;
248
};
249
250
using TlsCertificateSelectorFactory = std::function<TlsCertificateSelectorPtr(
251
    const ServerContextConfig&, TlsCertificateSelectorContext&)>;
252
253
class TlsCertificateSelectorConfigFactory : public Config::TypedFactory {
254
public:
255
  /**
256
   * @param for_quic true when in quic context, which does not support selecting certificate
257
   * asynchronously.
258
   * @returns a factory to create a TlsCertificateSelector. Accepts the |config| and
259
   * |validation_visitor| for early validation. This virtual base doesn't
260
   * perform MessageUtil::downcastAndValidate, but an implementation should.
261
   */
262
  virtual TlsCertificateSelectorFactory
263
  createTlsCertificateSelectorFactory(const Protobuf::Message& config,
264
                                      Server::Configuration::CommonFactoryContext& factory_context,
265
                                      ProtobufMessage::ValidationVisitor& validation_visitor,
266
                                      absl::Status& creation_status, bool for_quic) PURE;
267
268
0
  std::string category() const override { return "envoy.tls.certificate_selectors"; }
269
};
270
271
} // namespace Ssl
272
} // namespace Envoy