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 "absl/container/inlined_vector.h"
13
#include "openssl/ssl.h"
14

            
15
namespace Envoy {
16

            
17
namespace Server {
18
namespace Configuration {
19
class GenericFactoryContext;
20
} // namespace Configuration
21
} // namespace Server
22

            
23
namespace Ssl {
24

            
25
// Opaque type defined and used by the low-level TLS certificate context.
26
struct TlsContext;
27

            
28
class ServerContextConfig;
29

            
30
using CurveNID = int;
31
// Currently this type only ever holds 3 values: P-256, P-384, and P-521, so optimize by using
32
// `InlinedVector`.
33
using CurveNIDVector = absl::InlinedVector<int, 3>;
34

            
35
class HandshakeCallbacks {
36
public:
37
2561
  virtual ~HandshakeCallbacks() = default;
38

            
39
  /**
40
   * @return the connection.
41
   */
42
  virtual Network::Connection& connection() const PURE;
43

            
44
  /**
45
   * A callback which will be executed at most once upon successful completion
46
   * of a handshake.
47
   */
48
  virtual void onSuccess(SSL* ssl) PURE;
49

            
50
  /**
51
   * A callback which will be executed at most once upon handshake failure.
52
   */
53
  virtual void onFailure() PURE;
54

            
55
  /**
56
   * Returns a pointer to the transportSocketCallbacks struct, or nullptr if
57
   * unset.
58
   */
59
  virtual Network::TransportSocketCallbacks* transportSocketCallbacks() PURE;
60

            
61
  /**
62
   * A callback to be called upon certificate validation completion if the validation is
63
   * asynchronous.
64
   */
65
  virtual void onAsynchronousCertValidationComplete() PURE;
66

            
67
  /**
68
   * A callback to be called upon certificate selection completion if the selection is
69
   * asynchronous.
70
   */
71
  virtual void onAsynchronousCertificateSelectionComplete() PURE;
72
};
73

            
74
/**
75
 * Base interface for performing TLS handshakes.
76
 */
77
class Handshaker {
78
public:
79
2560
  virtual ~Handshaker() = default;
80

            
81
  /**
82
   * Performs a TLS handshake and returns an action indicating
83
   * whether the callsite should close the connection or keep it open.
84
   */
85
  virtual Network::PostIoAction doHandshake() PURE;
86
};
87

            
88
using HandshakerSharedPtr = std::shared_ptr<Handshaker>;
89
using HandshakerFactoryCb =
90
    std::function<HandshakerSharedPtr(bssl::UniquePtr<SSL>, int, HandshakeCallbacks*)>;
91

            
92
// Callback for modifying an SSL_CTX.
93
using SslCtxCb = std::function<void(SSL_CTX*)>;
94

            
95
class HandshakerFactoryContext {
96
public:
97
7054
  virtual ~HandshakerFactoryContext() = default;
98

            
99
  /**
100
   * Returns the singleton manager.
101
   */
102
  virtual Singleton::Manager& singletonManager() PURE;
103

            
104
  /**
105
   * @return reference to the server options
106
   */
107
  virtual const Server::Options& options() const PURE;
108

            
109
  /**
110
   * @return reference to the Api object
111
   */
112
  virtual Api::Api& api() PURE;
113

            
114
  /**
115
   * The list of supported protocols exposed via ALPN, from ContextConfig.
116
   */
117
  virtual absl::string_view alpnProtocols() const PURE;
118

            
119
  /**
120
   * @return reference to the server lifecycle notifier
121
   */
122
  virtual Server::ServerLifecycleNotifier& lifecycleNotifier() PURE;
123
};
124

            
125
struct HandshakerCapabilities {
126
  // Whether or not a handshaker implementation provides certificates itself.
127
  bool provides_certificates = false;
128

            
129
  // Whether or not a handshaker implementation verifies certificates itself.
130
  bool verifies_peer_certificates = false;
131

            
132
  // Whether or not a handshaker implementation handles session resumption
133
  // itself.
134
  bool handles_session_resumption = false;
135

            
136
  // Whether or not a handshaker implementation provides its own list of ciphers
137
  // and curves.
138
  bool provides_ciphers_and_curves = false;
139

            
140
  // Whether or not a handshaker implementation handles ALPN selection.
141
  bool handles_alpn_selection = false;
142

            
143
  // Should return true if this handshaker is FIPS-compliant.
144
  // Envoy will fail to compile if this returns true and `--define=boringssl=fips`.
145
  bool is_fips_compliant = true;
146

            
147
  // Whether or not a handshaker implementation provides its own list of
148
  // supported signature algorithms.
149
  bool provides_sigalgs = false;
150
};
151

            
152
class HandshakerFactory : public Config::TypedFactory {
153
public:
154
  /**
155
   * @returns a callback to create a Handshaker. Accepts the |config| and
156
   * |validation_visitor| for early validation. This virtual base doesn't
157
   * perform MessageUtil::downcastAndValidate, but an implementation should.
158
   */
159
  virtual HandshakerFactoryCb
160
  createHandshakerCb(const Protobuf::Message& message,
161
                     HandshakerFactoryContext& handshaker_factory_context,
162
                     ProtobufMessage::ValidationVisitor& validation_visitor) PURE;
163

            
164
4
  std::string category() const override { return "envoy.tls_handshakers"; }
165

            
166
  /**
167
   * Implementations should return a struct with their capabilities. See
168
   * HandshakerCapabilities above. For any capability a Handshaker
169
   * implementation explicitly declares, Envoy will not also configure that SSL
170
   * capability.
171
   */
172
  virtual HandshakerCapabilities capabilities() const PURE;
173

            
174
  /**
175
   * Implementations should return a callback for configuring an SSL_CTX context
176
   * before it is used to create any SSL objects. Providing
177
   * |handshaker_factory_context| as an argument allows callsites to access the
178
   * API and other factory context methods.
179
   */
180
  virtual SslCtxCb sslctxCb(HandshakerFactoryContext& handshaker_factory_context) const PURE;
181
};
182

            
183
// A handle tracking the certificate selection request. This can be used to supply additonal data
184
// to attach to the TLS sockets, and to detect when a request is cancelled.
185
class SelectionHandle {
186
public:
187
35
  virtual ~SelectionHandle() = default;
188
};
189

            
190
using SelectionHandleConstSharedPtr = std::shared_ptr<const SelectionHandle>;
191

            
192
struct SelectionResult {
193
  enum class SelectionStatus {
194
    // A certificate was successfully selected.
195
    Success,
196
    // Certificate selection will complete asynchronously later.
197
    Pending,
198
    // Certificate selection failed.
199
    Failed,
200
  };
201

            
202
  // Status of the certificate selection.
203
  SelectionStatus status;
204
  // Selected TLS context: it must be non-null when status is Success.
205
  const Ssl::TlsContext* selected_ctx{nullptr};
206
  // True if OCSP stapling should be enabled.
207
  bool staple{false};
208
  // Optional handle to attach to the individual TLS socket connection.
209
  SelectionHandleConstSharedPtr handle{nullptr};
210
};
211

            
212
/**
213
 * Used to return the result from an asynchronous cert selection.
214
 */
215
class CertificateSelectionCallback {
216
public:
217
1281
  virtual ~CertificateSelectionCallback() = default;
218

            
219
  virtual Event::Dispatcher& dispatcher() PURE;
220

            
221
  /**
222
   * Called when the asynchronous cert selection completes.
223
   * @param selected_ctx selected Ssl::TlsContext, it's empty when selection failed.
224
   * @param staple true when need to set OCSP response.
225
   */
226
  virtual void onCertificateSelectionResult(OptRef<const Ssl::TlsContext> selected_ctx,
227
                                            bool staple) PURE;
228
};
229

            
230
using CertificateSelectionCallbackPtr = std::unique_ptr<CertificateSelectionCallback>;
231

            
232
enum class OcspStapleAction { Staple, NoStaple, Fail, ClientNotCapable };
233

            
234
class TlsCertificateSelector {
235
public:
236
3472
  virtual ~TlsCertificateSelector() = default;
237

            
238
  /**
239
   * @return true if the selector provides its own SSL contexts.
240
   */
241
1
  virtual bool providesCertificates() const { return false; }
242

            
243
  /**
244
   * Select TLS context based on the client hello in non-QUIC TLS handshake.
245
   *
246
   * @return selected_ctx should only not be null when status is SelectionStatus::Success, and it
247
   * will have the same lifetime as ``ServerContextImpl``.
248
   *
249
   * @param ssl_client_hello low-level SSL object, only valid during the callback.
250
   */
251
  virtual SelectionResult selectTlsContext(const SSL_CLIENT_HELLO& ssl_client_hello,
252
                                           CertificateSelectionCallbackPtr cb) PURE;
253

            
254
  /**
255
   * Finds the best matching context in QUIC TLS handshake, which doesn't support async mode yet.
256
   *
257
   * @return context will have the same lifetime as ``ServerContextImpl``.
258
   */
259
  virtual std::pair<const Ssl::TlsContext&, OcspStapleAction>
260
  findTlsContext(absl::string_view sni, const CurveNIDVector& client_ecdsa_capabilities,
261
                 bool client_ocsp_capable, bool* cert_matched_sni) PURE;
262
};
263

            
264
using TlsCertificateSelectorPtr = std::unique_ptr<TlsCertificateSelector>;
265

            
266
class TlsCertificateSelectorContext {
267
public:
268
7016
  virtual ~TlsCertificateSelectorContext() = default;
269

            
270
  /**
271
   * @return reference to the available TLS contexts.
272
   */
273
  virtual const std::vector<TlsContext>& getTlsContexts() const PURE;
274
};
275

            
276
class TlsCertificateSelectorFactory {
277
public:
278
3508
  virtual ~TlsCertificateSelectorFactory() = default;
279

            
280
  /** Creates a per-context certificate selector.*/
281
  virtual TlsCertificateSelectorPtr create(TlsCertificateSelectorContext&) PURE;
282

            
283
  /** Notify about changes in the TLS context config, e.g. an SDS update to the certificates or the
284
   * validation context. */
285
  virtual absl::Status onConfigUpdate() PURE;
286
};
287

            
288
using TlsCertificateSelectorFactoryPtr = std::unique_ptr<TlsCertificateSelectorFactory>;
289

            
290
class TlsCertificateSelectorConfigFactory : public Config::TypedFactory {
291
public:
292
  /**
293
   * Create a certificate selector for a TLS context.
294
   * @param config proto configuration.
295
   * @param factory_context generic factory context.
296
   * @param tls_context is the parent TLS context which is guaranteed to outlive the selector.
297
   * @param for_quic true when in quic context, which does not support selecting certificate
298
   * asynchronously.
299
   * @returns a factory to create a TlsCertificateSelector. Accepts the |config| and
300
   * |validation_visitor| for early validation. This virtual base doesn't
301
   * perform MessageUtil::downcastAndValidate, but an implementation should.
302
   */
303
  virtual absl::StatusOr<TlsCertificateSelectorFactoryPtr>
304
  createTlsCertificateSelectorFactory(const Protobuf::Message& config,
305
                                      Server::Configuration::GenericFactoryContext& factory_context,
306
                                      const ServerContextConfig& tls_context, bool for_quic) PURE;
307

            
308
19
  std::string category() const override { return "envoy.tls.certificate_selectors"; }
309
};
310

            
311
class UpstreamTlsCertificateSelector {
312
public:
313
17
  virtual ~UpstreamTlsCertificateSelector() = default;
314

            
315
  /**
316
   * Select TLS context using a server hello and transport socket options.
317
   * Please see BoringSSL documentation on the accessors to the SSL object.
318
   */
319
  virtual SelectionResult
320
  selectTlsContext(const SSL& ssl, const Network::TransportSocketOptionsConstSharedPtr& options,
321
                   CertificateSelectionCallbackPtr cb) PURE;
322
};
323

            
324
using UpstreamTlsCertificateSelectorPtr = std::unique_ptr<UpstreamTlsCertificateSelector>;
325

            
326
class UpstreamTlsCertificateSelectorFactory {
327
public:
328
16
  virtual ~UpstreamTlsCertificateSelectorFactory() = default;
329

            
330
  /** Creates a per-context certificate selector.*/
331
  virtual UpstreamTlsCertificateSelectorPtr
332
  createUpstreamTlsCertificateSelector(TlsCertificateSelectorContext&) PURE;
333

            
334
  /** Notify about changes in the TLS context config, e.g. an SDS update to the certificates or the
335
   * validation context. */
336
  virtual absl::Status onConfigUpdate() PURE;
337
};
338
using UpstreamTlsCertificateSelectorFactoryPtr =
339
    std::unique_ptr<UpstreamTlsCertificateSelectorFactory>;
340

            
341
class UpstreamTlsCertificateSelectorConfigFactory : public Config::TypedFactory {
342
public:
343
  /**
344
   * Creates a factory for the upstream TLS certificate selectors. The factory
345
   * is bound to the client context config.
346
   */
347
  virtual absl::StatusOr<UpstreamTlsCertificateSelectorFactoryPtr>
348
  createUpstreamTlsCertificateSelectorFactory(
349
      const Protobuf::Message& proto_config,
350
      Server::Configuration::GenericFactoryContext& factory_context,
351
      const ClientContextConfig& tls_config) PURE;
352

            
353
16
  std::string category() const override { return "envoy.tls.upstream_certificate_selectors"; }
354
};
355

            
356
class TlsCertificateMapper {
357
public:
358
27
  virtual ~TlsCertificateMapper() = default;
359
  virtual std::string deriveFromClientHello(const SSL_CLIENT_HELLO&) PURE;
360
};
361

            
362
class UpstreamTlsCertificateMapper {
363
public:
364
28
  virtual ~UpstreamTlsCertificateMapper() = default;
365
  virtual std::string
366
  deriveFromServerHello(const SSL&, const Network::TransportSocketOptionsConstSharedPtr&) PURE;
367
};
368

            
369
using TlsCertificateMapperPtr = std::unique_ptr<TlsCertificateMapper>;
370
using TlsCertificateMapperFactory = std::function<TlsCertificateMapperPtr()>;
371
using UpstreamTlsCertificateMapperPtr = std::unique_ptr<UpstreamTlsCertificateMapper>;
372
using UpstreamTlsCertificateMapperFactory = std::function<UpstreamTlsCertificateMapperPtr()>;
373

            
374
class TlsCertificateMapperConfigFactory : public Config::TypedFactory {
375
public:
376
  /**
377
   * Create a certificate selector secret name mapper.
378
   * @param config proto configuration.
379
   * @param factory_context generic factory context.
380
   */
381
  virtual absl::StatusOr<TlsCertificateMapperFactory> createTlsCertificateMapperFactory(
382
      const Protobuf::Message& config,
383
      Server::Configuration::GenericFactoryContext& factory_context) PURE;
384

            
385
15
  std::string category() const override { return "envoy.tls.certificate_mappers"; }
386
};
387

            
388
class UpstreamTlsCertificateMapperConfigFactory : public Config::TypedFactory {
389
public:
390
  /**
391
   * Create an upstream certificate selector secret name mapper.
392
   * @param config proto configuration.
393
   * @param factory_context generic factory context.
394
   */
395
  virtual absl::StatusOr<UpstreamTlsCertificateMapperFactory> createTlsCertificateMapperFactory(
396
      const Protobuf::Message& config,
397
      Server::Configuration::GenericFactoryContext& factory_context) PURE;
398

            
399
15
  std::string category() const override { return "envoy.tls.upstream_certificate_mappers"; }
400
};
401

            
402
} // namespace Ssl
403
} // namespace Envoy