LCOV - code coverage report
Current view: top level - source/extensions/transport_sockets/tls - context_impl.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 0 5 0.0 %
Date: 2024-01-05 06:35:25 Functions: 0 3 0.0 %

          Line data    Source code
       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/extensions/transport_sockets/tls/cert_validator/cert_validator.h"
      23             : #include "source/extensions/transport_sockets/tls/context_manager_impl.h"
      24             : #include "source/extensions/transport_sockets/tls/ocsp/ocsp.h"
      25             : #include "source/extensions/transport_sockets/tls/stats.h"
      26             : 
      27             : #include "absl/synchronization/mutex.h"
      28             : #include "openssl/ssl.h"
      29             : #include "openssl/x509v3.h"
      30             : 
      31             : namespace Envoy {
      32             : #ifndef OPENSSL_IS_BORINGSSL
      33             : #error Envoy requires BoringSSL
      34             : #endif
      35             : 
      36             : namespace Extensions {
      37             : namespace TransportSockets {
      38             : namespace Tls {
      39             : 
      40             : struct TlsContext {
      41             :   // Each certificate specified for the context has its own SSL_CTX. `SSL_CTXs`
      42             :   // are identical with the exception of certificate material, and can be
      43             :   // safely substituted via SSL_set_SSL_CTX() during the
      44             :   // SSL_CTX_set_select_certificate_cb() callback following ClientHello.
      45             :   bssl::UniquePtr<SSL_CTX> ssl_ctx_;
      46             :   bssl::UniquePtr<X509> cert_chain_;
      47             :   std::string cert_chain_file_path_;
      48             :   Ocsp::OcspResponseWrapperPtr ocsp_response_;
      49             :   bool is_ecdsa_{};
      50             :   bool is_must_staple_{};
      51             :   Ssl::PrivateKeyMethodProviderSharedPtr private_key_method_provider_{};
      52             : 
      53           0 :   std::string getCertChainFileName() const { return cert_chain_file_path_; };
      54             :   bool isCipherEnabled(uint16_t cipher_id, uint16_t client_version);
      55           0 :   Envoy::Ssl::PrivateKeyMethodProviderSharedPtr getPrivateKeyMethodProvider() {
      56           0 :     return private_key_method_provider_;
      57           0 :   }
      58             :   void loadCertificateChain(const std::string& data, const std::string& data_path);
      59             :   void loadPrivateKey(const std::string& data, const std::string& data_path,
      60             :                       const std::string& password);
      61             :   void loadPkcs12(const std::string& data, const std::string& data_path,
      62             :                   const std::string& password);
      63             :   void checkPrivateKey(const bssl::UniquePtr<EVP_PKEY>& pkey, const std::string& key_path);
      64             : };
      65             : 
      66             : class ContextImpl : public virtual Envoy::Ssl::Context,
      67             :                     protected Logger::Loggable<Logger::Id::config> {
      68             : public:
      69             :   virtual bssl::UniquePtr<SSL> newSsl(const Network::TransportSocketOptionsConstSharedPtr& options);
      70             : 
      71             :   /**
      72             :    * Logs successful TLS handshake and updates stats.
      73             :    * @param ssl the connection to log
      74             :    */
      75             :   void logHandshake(SSL* ssl) const;
      76             : 
      77           0 :   SslStats& stats() { return stats_; }
      78             : 
      79             :   /**
      80             :    * The global SSL-library index used for storing a pointer to the SslExtendedSocketInfo
      81             :    * class in the SSL instance, for retrieval in callbacks.
      82             :    */
      83             :   static int sslExtendedSocketInfoIndex();
      84             : 
      85             :   static int sslSocketIndex();
      86             :   // Ssl::Context
      87             :   absl::optional<uint32_t> daysUntilFirstCertExpires() const override;
      88             :   Envoy::Ssl::CertificateDetailsPtr getCaCertInformation() const override;
      89             :   std::vector<Envoy::Ssl::CertificateDetailsPtr> getCertChainInformation() const override;
      90             :   absl::optional<uint64_t> secondsUntilFirstOcspResponseExpires() const override;
      91             : 
      92             :   std::vector<Ssl::PrivateKeyMethodProviderSharedPtr> getPrivateKeyMethodProviders();
      93             : 
      94             :   // Validate cert asynchronously for a QUIC connection.
      95             :   ValidationResults customVerifyCertChainForQuic(
      96             :       STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, bool is_server,
      97             :       const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options,
      98             :       const CertValidator::ExtraValidationContext& validation_context,
      99             :       const std::string& host_name);
     100             : 
     101             :   static void keylogCallback(const SSL* ssl, const char* line);
     102             : 
     103             : protected:
     104             :   friend class ContextImplPeer;
     105             : 
     106             :   ContextImpl(Stats::Scope& scope, const Envoy::Ssl::ContextConfig& config,
     107             :               TimeSource& time_source);
     108             : 
     109             :   /**
     110             :    * The global SSL-library index used for storing a pointer to the context
     111             :    * in the SSL instance, for retrieval in callbacks.
     112             :    */
     113             :   static int sslContextIndex();
     114             : 
     115             :   // A SSL_CTX_set_custom_verify callback for asynchronous cert validation.
     116             :   static enum ssl_verify_result_t customVerifyCallback(SSL* ssl, uint8_t* out_alert);
     117             : 
     118             :   bool parseAndSetAlpn(const std::vector<std::string>& alpn, SSL& ssl);
     119             :   std::vector<uint8_t> parseAlpnProtocols(const std::string& alpn_protocols);
     120             : 
     121             :   void incCounter(const Stats::StatName name, absl::string_view value,
     122             :                   const Stats::StatName fallback) const;
     123             : 
     124             :   // Helper function to validate cert for TCP connections asynchronously.
     125             :   ValidationResults customVerifyCertChain(
     126             :       Envoy::Ssl::SslExtendedSocketInfo* extended_socket_info,
     127             :       const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, SSL* ssl);
     128             : 
     129             :   void populateServerNamesMap(TlsContext& ctx, const int pkey_id);
     130             : 
     131             :   // This is always non-empty, with the first context used for all new SSL
     132             :   // objects. For server contexts, once we have ClientHello, we
     133             :   // potentially switch to a different CertificateContext based on certificate
     134             :   // selection.
     135             :   std::vector<TlsContext> tls_contexts_;
     136             :   CertValidatorPtr cert_validator_;
     137             :   Stats::Scope& scope_;
     138             :   SslStats stats_;
     139             :   std::vector<uint8_t> parsed_alpn_protocols_;
     140             :   bssl::UniquePtr<X509> cert_chain_;
     141             :   std::string cert_chain_file_path_;
     142             :   TimeSource& time_source_;
     143             :   const unsigned tls_max_version_;
     144             :   mutable Stats::StatNameSetPtr stat_name_set_;
     145             :   const Stats::StatName unknown_ssl_cipher_;
     146             :   const Stats::StatName unknown_ssl_curve_;
     147             :   const Stats::StatName unknown_ssl_algorithm_;
     148             :   const Stats::StatName unknown_ssl_version_;
     149             :   const Stats::StatName ssl_ciphers_;
     150             :   const Stats::StatName ssl_versions_;
     151             :   const Stats::StatName ssl_curves_;
     152             :   const Stats::StatName ssl_sigalgs_;
     153             :   const Ssl::HandshakerCapabilities capabilities_;
     154             :   const Network::Address::IpList tls_keylog_local_;
     155             :   const Network::Address::IpList tls_keylog_remote_;
     156             :   AccessLog::AccessLogFileSharedPtr tls_keylog_file_;
     157             : };
     158             : 
     159             : using ContextImplSharedPtr = std::shared_ptr<ContextImpl>;
     160             : 
     161             : class ClientContextImpl : public ContextImpl, public Envoy::Ssl::ClientContext {
     162             : public:
     163             :   ClientContextImpl(Stats::Scope& scope, const Envoy::Ssl::ClientContextConfig& config,
     164             :                     TimeSource& time_source);
     165             : 
     166             :   bssl::UniquePtr<SSL>
     167             :   newSsl(const Network::TransportSocketOptionsConstSharedPtr& options) override;
     168             : 
     169             : private:
     170             :   int newSessionKey(SSL_SESSION* session);
     171             : 
     172             :   const std::string server_name_indication_;
     173             :   const bool allow_renegotiation_;
     174             :   const bool enforce_rsa_key_usage_;
     175             :   const size_t max_session_keys_;
     176             :   absl::Mutex session_keys_mu_;
     177             :   std::deque<bssl::UniquePtr<SSL_SESSION>> session_keys_ ABSL_GUARDED_BY(session_keys_mu_);
     178             :   bool session_keys_single_use_{false};
     179             : };
     180             : 
     181             : enum class OcspStapleAction { Staple, NoStaple, Fail, ClientNotCapable };
     182             : 
     183             : class ServerContextImpl : public ContextImpl, public Envoy::Ssl::ServerContext {
     184             : public:
     185             :   ServerContextImpl(Stats::Scope& scope, const Envoy::Ssl::ServerContextConfig& config,
     186             :                     const std::vector<std::string>& server_names, TimeSource& time_source);
     187             : 
     188             :   // Select the TLS certificate context in SSL_CTX_set_select_certificate_cb() callback with
     189             :   // ClientHello details. This is made public for use by custom TLS extensions who want to
     190             :   // manually create and use this as a client hello callback.
     191             :   enum ssl_select_cert_result_t selectTlsContext(const SSL_CLIENT_HELLO* ssl_client_hello);
     192             : 
     193             : private:
     194             :   // Currently, at most one certificate of a given key type may be specified for each exact
     195             :   // server name or wildcard domain name.
     196             :   using PkeyTypesMap = absl::flat_hash_map<int, std::reference_wrapper<TlsContext>>;
     197             :   // Both exact server names and wildcard domains are part of the same map, in which wildcard
     198             :   // domains are prefixed with "." (i.e. ".example.com" for "*.example.com") to differentiate
     199             :   // between exact and wildcard entries.
     200             :   using ServerNamesMap = absl::flat_hash_map<std::string, PkeyTypesMap>;
     201             : 
     202             :   void populateServerNamesMap(TlsContext& ctx, const int pkey_id);
     203             : 
     204             :   using SessionContextID = std::array<uint8_t, SSL_MAX_SSL_SESSION_ID_LENGTH>;
     205             : 
     206             :   int alpnSelectCallback(const unsigned char** out, unsigned char* outlen, const unsigned char* in,
     207             :                          unsigned int inlen);
     208             :   int sessionTicketProcess(SSL* ssl, uint8_t* key_name, uint8_t* iv, EVP_CIPHER_CTX* ctx,
     209             :                            HMAC_CTX* hmac_ctx, int encrypt);
     210             :   bool isClientEcdsaCapable(const SSL_CLIENT_HELLO* ssl_client_hello);
     211             :   bool isClientOcspCapable(const SSL_CLIENT_HELLO* ssl_client_hello);
     212             :   OcspStapleAction ocspStapleAction(const TlsContext& ctx, bool client_ocsp_capable);
     213             : 
     214             :   SessionContextID generateHashForSessionContextId(const std::vector<std::string>& server_names);
     215             : 
     216             :   const std::vector<Envoy::Ssl::ServerContextConfig::SessionTicketKey> session_ticket_keys_;
     217             :   const Ssl::ServerContextConfig::OcspStaplePolicy ocsp_staple_policy_;
     218             :   ServerNamesMap server_names_map_;
     219             :   bool has_rsa_{false};
     220             :   bool full_scan_certs_on_sni_mismatch_;
     221             : };
     222             : 
     223             : } // namespace Tls
     224             : } // namespace TransportSockets
     225             : } // namespace Extensions
     226             : } // namespace Envoy

Generated by: LCOV version 1.15