This is an automated email from the ASF dual-hosted git repository.

maskit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 5bb84630f Add TLSCertSwitchSupport (#9322)
5bb84630f is described below

commit 5bb84630f103c0f75c3ff936db9ed5e798856633
Author: Masakazu Kitajo <[email protected]>
AuthorDate: Tue Mar 14 11:11:01 2023 -0600

    Add TLSCertSwitchSupport (#9322)
    
    * Add TLSCertSwitchSupport
    
    This is a preparation for enabling cert switching on QUIC connections.
    
    * Fix an invalid cast
---
 iocore/net/Makefile.am             |   1 +
 iocore/net/P_SSLNetVConnection.h   |   6 +
 iocore/net/SSLNetVConnection.cc    |  74 +++++++++++++
 iocore/net/SSLUtils.cc             | 220 ++++++++++++-------------------------
 iocore/net/TLSCertSwitchSupport.cc | 103 +++++++++++++++++
 iocore/net/TLSCertSwitchSupport.h  |  51 +++++++++
 6 files changed, 307 insertions(+), 148 deletions(-)

diff --git a/iocore/net/Makefile.am b/iocore/net/Makefile.am
index fac842765..fd5026e87 100644
--- a/iocore/net/Makefile.am
+++ b/iocore/net/Makefile.am
@@ -200,6 +200,7 @@ libinknet_a_SOURCES = \
        TLSSessionResumptionSupport.cc \
        TLSSNISupport.cc \
        TLSTunnelSupport.cc \
+       TLSCertSwitchSupport.cc \
        UDPIOEvent.cc \
        UnixConnection.cc \
        UnixNet.cc \
diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h
index ca6f8b17a..6fcacdf72 100644
--- a/iocore/net/P_SSLNetVConnection.h
+++ b/iocore/net/P_SSLNetVConnection.h
@@ -52,6 +52,7 @@
 #include "TLSEarlyDataSupport.h"
 #include "TLSTunnelSupport.h"
 #include "TLSBasicSupport.h"
+#include "TLSCertSwitchSupport.h"
 #include "P_SSLUtils.h"
 #include "P_SSLConfig.h"
 
@@ -103,6 +104,7 @@ class SSLNetVConnection : public UnixNetVConnection,
                           public TLSSNISupport,
                           public TLSEarlyDataSupport,
                           public TLSTunnelSupport,
+                          public TLSCertSwitchSupport,
                           public TLSBasicSupport
 {
   typedef UnixNetVConnection super; ///< Parent type.
@@ -410,6 +412,10 @@ protected:
 
   void _fire_ssl_servername_event() override;
 
+  bool _isTryingRenegotiation() const override;
+  shared_SSL_CTX _lookupContextByName(const std::string &servername, 
SSLCertContextType ctxType) override;
+  shared_SSL_CTX _lookupContextByIP() override;
+
 private:
   std::string_view map_tls_protocol_to_tag(const char *proto_string) const;
   bool update_rbio(bool move_to_socket);
diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
index f7fb137aa..48546217c 100644
--- a/iocore/net/SSLNetVConnection.cc
+++ b/iocore/net/SSLNetVConnection.cc
@@ -225,6 +225,7 @@ SSLNetVConnection::_bindSSLObject()
   TLSSNISupport::bind(this->ssl, this);
   TLSEarlyDataSupport::bind(this->ssl, this);
   TLSTunnelSupport::bind(this->ssl, this);
+  TLSCertSwitchSupport::bind(this->ssl, this);
 }
 
 void
@@ -237,6 +238,7 @@ SSLNetVConnection::_unbindSSLObject()
   TLSSNISupport::unbind(this->ssl);
   TLSEarlyDataSupport::unbind(this->ssl);
   TLSTunnelSupport::unbind(this->ssl);
+  TLSCertSwitchSupport::unbind(this->ssl);
 }
 
 static void
@@ -971,6 +973,7 @@ SSLNetVConnection::clear()
   TLSSessionResumptionSupport::clear();
   TLSSNISupport::_clear();
   TLSTunnelSupport::_clear();
+  TLSCertSwitchSupport::_clear();
 
   sslHandshakeStatus          = SSL_HANDSHAKE_ONGOING;
   sslLastWriteTime            = 0;
@@ -1999,6 +2002,77 @@ SSLNetVConnection::_fire_ssl_servername_event()
   this->callHooks(TS_EVENT_SSL_SERVERNAME);
 }
 
+bool
+SSLNetVConnection::_isTryingRenegotiation() const
+{
+  if (SSLConfigParams::ssl_allow_client_renegotiation == false && 
this->getSSLHandShakeComplete()) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+shared_SSL_CTX
+SSLNetVConnection::_lookupContextByName(const std::string &servername, 
SSLCertContextType ctxType)
+{
+  shared_SSL_CTX ctx = nullptr;
+  SSLCertificateConfig::scoped_config lookup;
+  SSLCertContext *cc = lookup->find(servername, ctxType);
+
+  if (cc) {
+    ctx = cc->getCtx();
+  }
+
+  if (cc && ctx && SSLCertContextOption::OPT_TUNNEL == cc->opt && 
this->get_is_transparent()) {
+    this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
+    this->setSSLHandShakeComplete(SSL_HANDSHAKE_DONE);
+    return nullptr;
+  } else {
+    return ctx;
+  }
+}
+
+shared_SSL_CTX
+SSLNetVConnection::_lookupContextByIP()
+{
+  shared_SSL_CTX ctx = nullptr;
+  SSLCertificateConfig::scoped_config lookup;
+  IpEndpoint ip;
+  int namelen = sizeof(ip);
+
+  // Return null if this vc is already configured as a tunnel
+  if (this->attributes == HttpProxyPort::TRANSPORT_BLIND_TUNNEL) {
+    return nullptr;
+  }
+
+  SSLCertContext *cc = nullptr;
+  if (this->get_is_proxy_protocol() && this->get_proxy_protocol_version() != 
ProxyProtocolVersion::UNDEFINED) {
+    ip.sa = *(this->get_proxy_protocol_dst_addr());
+    ip_port_text_buffer ipb1;
+    ats_ip_nptop(&ip, ipb1, sizeof(ipb1));
+    cc = lookup->find(ip);
+    if (is_debug_tag_set("proxyprotocol")) {
+      IpEndpoint src;
+      ip_port_text_buffer ipb2;
+      int ip_len = sizeof(src);
+
+      if (0 != safe_getpeername(this->get_socket(), &src.sa, &ip_len)) {
+        Debug("proxyprotocol", "Failed to get src ip, errno = [%d]", errno);
+        return nullptr;
+      }
+      ats_ip_nptop(&src, ipb2, sizeof(ipb2));
+      Debug("proxyprotocol", "IP context is %p for [%s] -> [%s], default 
context %p", cc, ipb2, ipb1, lookup->defaultContext());
+    }
+  } else if (0 == safe_getsockname(this->get_socket(), &ip.sa, &namelen)) {
+    cc = lookup->find(ip);
+  }
+  if (cc) {
+    ctx = cc->getCtx();
+  }
+
+  return ctx;
+}
+
 void
 SSLNetVConnection::set_ca_cert_file(std::string_view file, std::string_view 
dir)
 {
diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc
index 11a2d2d0a..8920e17ca 100644
--- a/iocore/net/SSLUtils.cc
+++ b/iocore/net/SSLUtils.cc
@@ -261,118 +261,6 @@ ssl_rm_cached_session(SSL_CTX *ctx, SSL_SESSION *sess)
   session_cache->removeSession(sid);
 }
 
-static int
-set_context_cert(SSL *ssl, void *arg)
-{
-  shared_SSL_CTX ctx  = nullptr;
-  SSL_CTX *verify_ctx = nullptr;
-  SSLCertContext *cc  = nullptr;
-  SSLCertificateConfig::scoped_config lookup;
-
-  const char *servername     = SSL_get_servername(ssl, 
TLSEXT_NAMETYPE_host_name);
-  SSLNetVConnection *netvc   = SSLNetVCAccess(ssl);
-  bool found                 = true;
-  int retval                 = 1;
-  SSLCertContextType ctxType = SSLCertContextType::GENERIC;
-
-  if (!netvc || netvc->ssl != ssl) {
-    Debug("ssl.error", "set_context_cert call back on stale netvc");
-    retval = 0; // Error
-    goto done;
-  }
-
-  Debug("ssl_load", "set_context_cert ssl=%p server=%s handshake_complete=%d", 
ssl, servername, netvc->getSSLHandShakeComplete());
-
-  // catch the client renegotiation early on
-  if (SSLConfigParams::ssl_allow_client_renegotiation == false && 
netvc->getSSLHandShakeComplete()) {
-    Debug("ssl_load", "set_context_cert trying to renegotiate from the 
client");
-    retval = 0; // Error
-    goto done;
-  }
-
-#ifdef OPENSSL_IS_BORINGSSL
-  if (arg != nullptr) {
-    const SSL_CLIENT_HELLO *client_hello = (const SSL_CLIENT_HELLO *)arg;
-    const bool client_ecdsa_capable      = 
BoringSSLUtils::isClientEcdsaCapable(client_hello);
-    ctxType                              = client_ecdsa_capable ? 
SSLCertContextType::EC : SSLCertContextType::RSA;
-  }
-#endif
-
-  // The incoming SSL_CTX is either the one mapped from the inbound IP address 
or the default one. If we
-  // don't find a name-based match at this point, we *do not* want to mess 
with the context because we've
-  // already made a best effort to find the best match.
-  if (likely(servername)) {
-    cc = lookup->find(servername, ctxType);
-    if (cc) {
-      ctx = cc->getCtx();
-    }
-    if (cc && ctx && SSLCertContextOption::OPT_TUNNEL == cc->opt && 
netvc->get_is_transparent()) {
-      netvc->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
-      netvc->setSSLHandShakeComplete(SSL_HANDSHAKE_DONE);
-      retval = -1;
-      goto done;
-    }
-  }
-
-  // If there's no match on the server name, try to match on the peer address.
-  if (ctx == nullptr) {
-    IpEndpoint ip;
-    int namelen = sizeof(ip);
-
-    if (netvc->get_is_proxy_protocol() && netvc->get_proxy_protocol_version() 
!= ProxyProtocolVersion::UNDEFINED) {
-      ip.sa = *(netvc->get_proxy_protocol_dst_addr());
-      ip_port_text_buffer ipb1;
-      ats_ip_nptop(&ip, ipb1, sizeof(ipb1));
-      cc = lookup->find(ip);
-      if (is_debug_tag_set("proxyprotocol")) {
-        IpEndpoint src;
-        ip_port_text_buffer ipb2;
-        int ip_len = sizeof(src);
-
-        if (0 != safe_getpeername(netvc->get_socket(), &src.sa, &ip_len)) {
-          Debug("proxyprotocol", "Failed to get src ip, errno = [%d]", errno);
-          return EVENT_ERROR;
-        }
-        ats_ip_nptop(&src, ipb2, sizeof(ipb2));
-        Debug("proxyprotocol", "IP context is %p for [%s] -> [%s], default 
context %p", cc, ipb2, ipb1, lookup->defaultContext());
-      }
-    } else if (0 == safe_getsockname(netvc->get_socket(), &ip.sa, &namelen)) {
-      cc = lookup->find(ip);
-    }
-    if (cc) {
-      ctx = cc->getCtx();
-    }
-  }
-
-  if (ctx != nullptr) {
-    SSL_set_SSL_CTX(ssl, ctx.get());
-#if TS_HAS_TLS_SESSION_TICKET
-    // Reset the ticket callback if needed
-#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
-    SSL_CTX_set_tlsext_ticket_key_evp_cb(ctx.get(), 
ssl_callback_session_ticket);
-#else
-    SSL_CTX_set_tlsext_ticket_key_cb(ctx.get(), ssl_callback_session_ticket);
-#endif
-#endif
-    // After replacing the SSL_CTX, make sure the overridden ca_cert_file is 
still set
-    setClientCertCACerts(ssl, netvc->get_ca_cert_file(), 
netvc->get_ca_cert_dir());
-  } else {
-    found = false;
-  }
-
-  verify_ctx = SSL_get_SSL_CTX(ssl);
-  // set_context_cert found SSL context for ...
-  Debug("ssl_load", "ssl_cert_callback %s SSL context %p for requested name 
'%s'", found ? "found" : "using", verify_ctx,
-        servername);
-
-  if (verify_ctx == nullptr) {
-    retval = 0;
-    goto done;
-  }
-done:
-  return retval;
-}
-
 // Callback function for verifying client certificate
 static int
 ssl_verify_client_callback(int preverify_ok, X509_STORE_CTX *ctx)
@@ -418,17 +306,19 @@ ssl_client_hello_callback(SSL *s, int *al, void *arg)
     return SSL_CLIENT_HELLO_ERROR;
   }
 
-  SSLNetVConnection *netvc = SSLNetVCAccess(s);
-  if (!netvc || netvc->ssl != s) {
-    Debug("ssl.error", "ssl_client_hello_callback call back on stale netvc");
-    return SSL_CLIENT_HELLO_ERROR;
-  }
-
-  bool reenabled = netvc->callHooks(TS_EVENT_SSL_CLIENT_HELLO);
+  SSLNetVConnection *netvc = dynamic_cast<SSLNetVConnection *>(snis);
+  if (netvc) {
+    if (netvc->ssl != s) {
+      Debug("ssl.error", "ssl_client_hello_callback call back on stale netvc");
+      return SSL_CLIENT_HELLO_ERROR;
+    }
 
-  if (!reenabled) {
-    return SSL_CLIENT_HELLO_RETRY;
+    bool reenabled = netvc->callHooks(TS_EVENT_SSL_CLIENT_HELLO);
+    if (!reenabled) {
+      return SSL_CLIENT_HELLO_RETRY;
+    }
   }
+
   return SSL_CLIENT_HELLO_SUCCESS;
 }
 #elif defined(OPENSSL_IS_BORINGSSL)
@@ -452,17 +342,19 @@ ssl_client_hello_callback(const SSL_CLIENT_HELLO 
*client_hello)
     return ssl_select_cert_error;
   }
 
-  SSLNetVConnection *netvc = SSLNetVCAccess(s);
-  if (!netvc || netvc->ssl != s) {
-    Debug("ssl.error", "ssl_client_hello_callback call back on stale netvc");
-    return ssl_select_cert_error;
-  }
-
-  bool reenabled = netvc->callHooks(TS_EVENT_SSL_CLIENT_HELLO);
+  SSLNetVConnection *netvc = dynamic_cast<SSLNetVConnection *>(snis);
+  if (netvc) {
+    if (netvc->ssl != s) {
+      Debug("ssl.error", "ssl_client_hello_callback call back on stale netvc");
+      return ssl_select_cert_error;
+    }
 
-  if (!reenabled) {
-    return ssl_select_cert_retry;
+    bool reenabled = netvc->callHooks(TS_EVENT_SSL_CLIENT_HELLO);
+    if (!reenabled) {
+      return ssl_select_cert_retry;
+    }
   }
+
   return ssl_select_cert_success;
 }
 #endif
@@ -474,16 +366,13 @@ ssl_client_hello_callback(const SSL_CLIENT_HELLO 
*client_hello)
 static int
 ssl_cert_callback(SSL *ssl, void *arg)
 {
-  SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
+  TLSCertSwitchSupport *tcss  = TLSCertSwitchSupport::getInstance(ssl);
+  SSLNetVConnection *sslnetvc = dynamic_cast<SSLNetVConnection *>(tcss);
   bool reenabled;
   int retval = 1;
 
-  if (!netvc || netvc->ssl != ssl) {
-    Debug("ssl.error", "ssl_cert_callback call back on stale netvc");
-    return 0;
-  }
-
   // If we are in tunnel mode, don't select a cert.  Pause!
+  NetVConnection *netvc = reinterpret_cast<NetVConnection *>(sslnetvc);
   if (HttpProxyPort::TRANSPORT_BLIND_TUNNEL == netvc->attributes) {
 #ifdef OPENSSL_IS_BORINGSSL
     return -2; // Retry
@@ -492,22 +381,56 @@ ssl_cert_callback(SSL *ssl, void *arg)
 #endif
   }
 
-  // Do the common certificate lookup only once.  If we pause
-  // and restart processing, do not execute the common logic again
-  if (!netvc->calledHooks(TS_EVENT_SSL_CERT)) {
-    retval = set_context_cert(ssl, arg);
-    if (retval != 1) {
-      return retval;
+  SSLCertContextType ctxType = SSLCertContextType::GENERIC;
+#ifdef OPENSSL_IS_BORINGSSL
+  if (arg != nullptr) {
+    const SSL_CLIENT_HELLO *client_hello = (const SSL_CLIENT_HELLO *)arg;
+    const bool client_ecdsa_capable      = 
BoringSSLUtils::isClientEcdsaCapable(client_hello);
+    ctxType                              = client_ecdsa_capable ? 
SSLCertContextType::EC : SSLCertContextType::RSA;
+  }
+#endif
+
+  if (sslnetvc) {
+    // Do the common certificate lookup only once.  If we pause
+    // and restart processing, do not execute the common logic again
+    if (!sslnetvc->calledHooks(TS_EVENT_SSL_CERT)) {
+      retval = sslnetvc->selectCertificate(ssl, ctxType);
+      if (retval != 1) {
+        return retval;
+      }
+    }
+
+    // Call the plugin cert code
+    reenabled = sslnetvc->callHooks(TS_EVENT_SSL_CERT);
+    // If it did not re-enable, return the code to
+    // stop the accept processing
+    if (!reenabled) {
+      retval = -1; // Pause
+    }
+  } else {
+    if (tcss->selectCertificate(ssl, ctxType) == 1) {
+      retval = 1;
+    } else {
+      retval = 0;
     }
   }
 
-  // Call the plugin cert code
-  reenabled = netvc->callHooks(TS_EVENT_SSL_CERT);
-  // If it did not re-enable, return the code to
-  // stop the accept processing
-  if (!reenabled) {
-    retval = -1; // Pause
+#if TS_HAS_TLS_SESSION_TICKET
+  if (retval == 1) {
+    // After replacing the SSL_CTX, make sure the overridden ca_cert_file is 
still set
+    if (sslnetvc) {
+      setClientCertCACerts(ssl, sslnetvc->get_ca_cert_file(), 
sslnetvc->get_ca_cert_dir());
+    }
+
+    // Reset the ticket callback if needed
+    SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
+#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+    SSL_CTX_set_tlsext_ticket_key_evp_cb(ctx, ssl_callback_session_ticket);
+#else
+    SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_callback_session_ticket);
+#endif
   }
+#endif
 
   // Return 1 for success, 0 for error, or -1 to pause
   return retval;
@@ -1020,6 +943,7 @@ SSLInitializeLibrary()
   TLSSNISupport::initialize();
   TLSEarlyDataSupport::initialize();
   TLSTunnelSupport::initialize();
+  TLSCertSwitchSupport::initialize();
 
   open_ssl_initialized = true;
 }
diff --git a/iocore/net/TLSCertSwitchSupport.cc 
b/iocore/net/TLSCertSwitchSupport.cc
new file mode 100644
index 000000000..4ee68605d
--- /dev/null
+++ b/iocore/net/TLSCertSwitchSupport.cc
@@ -0,0 +1,103 @@
+/** @file
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#include "TLSCertSwitchSupport.h"
+#include "P_SSLCertLookup.h"
+
+int TLSCertSwitchSupport::_ex_data_index = -1;
+
+void
+TLSCertSwitchSupport::initialize()
+{
+  ink_assert(_ex_data_index == -1);
+  if (_ex_data_index == -1) {
+    _ex_data_index = SSL_get_ex_new_index(0, (void *)"TLSEarlyDataSupport 
index", nullptr, nullptr, nullptr);
+  }
+}
+
+TLSCertSwitchSupport *
+TLSCertSwitchSupport::getInstance(SSL *ssl)
+{
+  return static_cast<TLSCertSwitchSupport *>(SSL_get_ex_data(ssl, 
_ex_data_index));
+}
+
+void
+TLSCertSwitchSupport::bind(SSL *ssl, TLSCertSwitchSupport *tcss)
+{
+  SSL_set_ex_data(ssl, _ex_data_index, tcss);
+}
+
+void
+TLSCertSwitchSupport::unbind(SSL *ssl)
+{
+  SSL_set_ex_data(ssl, _ex_data_index, nullptr);
+}
+
+void
+TLSCertSwitchSupport::_clear()
+{
+}
+
+int
+TLSCertSwitchSupport::selectCertificate(SSL *ssl, SSLCertContextType ctxType)
+{
+  shared_SSL_CTX ctx = nullptr;
+
+  const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+  bool found             = true;
+
+  Debug("ssl", "set_context_cert ssl=%p server=%s", ssl, servername);
+
+  // catch the client renegotiation early on
+  if (this->_isTryingRenegotiation()) {
+    Debug("ssl_load", "set_context_cert trying to renegotiate from the 
client");
+    return 0;
+  }
+
+  // The incoming SSL_CTX is either the one mapped from the inbound IP address 
or the default one. If we
+  // don't find a name-based match at this point, we *do not* want to mess 
with the context because we've
+  // already made a best effort to find the best match.
+  if (likely(servername)) {
+    ctx = this->_lookupContextByName(servername, ctxType);
+  }
+
+  // If there's no match on the server name, try to match on the peer address.
+  if (ctx == nullptr) {
+    ctx = this->_lookupContextByIP();
+  }
+
+  if (ctx != nullptr) {
+    SSL_set_SSL_CTX(ssl, ctx.get());
+  } else {
+    found = false;
+  }
+
+  SSL_CTX *verify_ctx = SSL_get_SSL_CTX(ssl);
+  // set_context_cert found SSL context for ...
+  Debug("ssl_load", "ssl_cert_callback %s SSL context %p for requested name 
'%s'", found ? "found" : "using", verify_ctx,
+        servername);
+
+  if (verify_ctx == nullptr) {
+    return 0;
+  }
+
+  return 1;
+}
diff --git a/iocore/net/TLSCertSwitchSupport.h 
b/iocore/net/TLSCertSwitchSupport.h
new file mode 100644
index 000000000..451933f5f
--- /dev/null
+++ b/iocore/net/TLSCertSwitchSupport.h
@@ -0,0 +1,51 @@
+/** @file
+
+  TLSCertSwitchSupport implements common methods and members to
+  support switching certificate
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#pragma once
+
+#include <openssl/ssl.h>
+#include "P_SSLCertLookup.h"
+
+class TLSCertSwitchSupport
+{
+public:
+  virtual ~TLSCertSwitchSupport() = default;
+
+  static void initialize();
+  static TLSCertSwitchSupport *getInstance(SSL *ssl);
+  static void bind(SSL *ssl, TLSCertSwitchSupport *tcss);
+  static void unbind(SSL *ssl);
+
+  int selectCertificate(SSL *ssl, SSLCertContextType ctxType);
+
+protected:
+  void _clear();
+
+  virtual bool _isTryingRenegotiation() const                                  
                          = 0;
+  virtual shared_SSL_CTX _lookupContextByName(const std::string &servername, 
SSLCertContextType ctxType) = 0;
+  virtual shared_SSL_CTX _lookupContextByIP()                                  
                          = 0;
+
+private:
+  static int _ex_data_index;
+};

Reply via email to