Coverage Report

Created: 2024-09-19 09:45

/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