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 c9d557bda9 Add TLSEventSupport (#11744)
c9d557bda9 is described below
commit c9d557bda9444f89a1bd1d9f850e99f496a92efc
Author: Masakazu Kitajo <[email protected]>
AuthorDate: Fri Sep 20 10:19:26 2024 -0600
Add TLSEventSupport (#11744)
* Add TLSEventSupport
* Remove _fire_ssl_servername_event
* Refactoring for Clang-Analyzer
* const
---
include/iocore/net/NetVConnection.h | 15 +
include/iocore/net/TLSEventSupport.h | 89 ++++++
include/iocore/net/TLSSNISupport.h | 2 -
src/api/InkAPI.cc | 24 +-
src/iocore/net/CMakeLists.txt | 1 +
src/iocore/net/P_QUICNetVConnection.h | 23 +-
src/iocore/net/P_SSLNetVConnection.h | 123 ++------
src/iocore/net/QUICNetVConnection.cc | 35 ++-
src/iocore/net/SSLClientUtils.cc | 5 +-
src/iocore/net/SSLNetVConnection.cc | 420 +++-----------------------
src/iocore/net/SSLUtils.cc | 64 ++--
src/iocore/net/TLSEventSupport.cc | 553 ++++++++++++++++++++++++++++++++++
src/iocore/net/TLSSNISupport.cc | 2 -
13 files changed, 820 insertions(+), 536 deletions(-)
diff --git a/include/iocore/net/NetVConnection.h
b/include/iocore/net/NetVConnection.h
index a7d8bd8886..7a89a11625 100644
--- a/include/iocore/net/NetVConnection.h
+++ b/include/iocore/net/NetVConnection.h
@@ -501,6 +501,7 @@ protected:
TLS_ALPN,
TLS_Basic,
TLS_CertSwitch,
+ TLS_Event,
TLS_EarlyData,
TLS_SNI,
TLS_SessionResumption,
@@ -594,6 +595,20 @@ NetVConnection::_set_service(TLSBasicSupport *instance)
this->_set_service(NetVConnection::Service::TLS_Basic, instance);
}
+class TLSEventSupport;
+template <>
+inline TLSEventSupport *
+NetVConnection::get_service() const
+{
+ return static_cast<TLSEventSupport
*>(this->_get_service(NetVConnection::Service::TLS_Event));
+}
+template <>
+inline void
+NetVConnection::_set_service(TLSEventSupport *instance)
+{
+ this->_set_service(NetVConnection::Service::TLS_Event, instance);
+}
+
class TLSEarlyDataSupport;
template <>
inline TLSEarlyDataSupport *
diff --git a/include/iocore/net/TLSEventSupport.h
b/include/iocore/net/TLSEventSupport.h
new file mode 100644
index 0000000000..2e71b9c015
--- /dev/null
+++ b/include/iocore/net/TLSEventSupport.h
@@ -0,0 +1,89 @@
+/** @file
+
+ TLSEventSupport implements common methods and members to
+ support TLS related events
+
+ @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 "iocore/eventsystem/Lock.h"
+
+class Continuation;
+
+class TLSEventSupport
+{
+public:
+ enum class SSLHandshakeHookState {
+ HANDSHAKE_HOOKS_PRE,
+ HANDSHAKE_HOOKS_PRE_INVOKE,
+ HANDSHAKE_HOOKS_CLIENT_HELLO,
+ HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE,
+ HANDSHAKE_HOOKS_SNI,
+ HANDSHAKE_HOOKS_CERT,
+ HANDSHAKE_HOOKS_CERT_INVOKE,
+ HANDSHAKE_HOOKS_CLIENT_CERT,
+ HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE,
+ HANDSHAKE_HOOKS_OUTBOUND_PRE,
+ HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE,
+ HANDSHAKE_HOOKS_VERIFY_SERVER,
+ HANDSHAKE_HOOKS_DONE
+ };
+
+ static char const *get_ssl_handshake_hook_state_name(SSLHandshakeHookState
state);
+
+ virtual ~TLSEventSupport() = default;
+
+ static void initialize();
+ static TLSEventSupport *getInstance(SSL *ssl);
+ static void bind(SSL *ssl, TLSEventSupport *es);
+ static void unbind(SSL *ssl);
+
+ bool callHooks(TSEvent eventId);
+ bool calledHooks(TSEvent eventId) const;
+ virtual Continuation *getContinuationForTLSEvents() = 0;
+ virtual EThread *getThreadForTLSEvents() = 0;
+ virtual Ptr<ProxyMutex> getMutexForTLSEvents() = 0;
+ virtual void reenable(int event) = 0;
+
+protected:
+ void clear();
+
+ SSLHandshakeHookState get_handshake_hook_state();
+ void set_handshake_hook_state(SSLHandshakeHookState state);
+ bool is_invoked_state() const;
+ int invoke_tls_event();
+ void resume_tls_event();
+
+ virtual bool _is_tunneling_requested() const = 0;
+ virtual void _switch_to_tunneling_mode() = 0;
+
+private:
+ static int _ex_data_index;
+ SSL *_ssl;
+
+ bool _first_handshake_hooks_pre = true;
+ bool _first_handshake_hooks_outbound_pre = true;
+
+ /// The current hook.
+ /// @note For @C SSL_HOOKS_INVOKE, this is the hook to invoke.
+ class APIHook *curHook = nullptr;
+ SSLHandshakeHookState sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE;
+};
diff --git a/include/iocore/net/TLSSNISupport.h
b/include/iocore/net/TLSSNISupport.h
index 1b35a683cf..fbba3810d5 100644
--- a/include/iocore/net/TLSSNISupport.h
+++ b/include/iocore/net/TLSSNISupport.h
@@ -82,8 +82,6 @@ public:
} hints_from_sni;
protected:
- virtual void _fire_ssl_servername_event() = 0;
-
virtual in_port_t _get_local_port() = 0;
void _clear();
diff --git a/src/api/InkAPI.cc b/src/api/InkAPI.cc
index 83aba64917..cf957ac97f 100644
--- a/src/api/InkAPI.cc
+++ b/src/api/InkAPI.cc
@@ -7870,25 +7870,25 @@ TSHttpEventNameLookup(TSEvent event)
return HttpDebugNames::get_event_name(static_cast<int>(event));
}
-/// Re-enable SSL VC.
+/// Re-enable NetVC that has TLSEventSupport.
class TSSslCallback : public Continuation
{
public:
- TSSslCallback(SSLNetVConnection *vc, TSEvent event) :
Continuation(vc->nh->mutex), m_vc(vc), m_event(event)
+ TSSslCallback(TLSEventSupport *tes, TSEvent event) :
Continuation(tes->getMutexForTLSEvents().get()), m_tes(tes), m_event(event)
{
SET_HANDLER(&TSSslCallback::event_handler);
}
int
event_handler(int /* event ATS_UNUSED */, void *)
{
- m_vc->reenable(m_vc->nh, m_event);
+ m_tes->reenable(m_event);
delete this;
return 0;
}
private:
- SSLNetVConnection *m_vc;
- TSEvent m_event;
+ TLSEventSupport *m_tes;
+ TSEvent m_event;
};
/// SSL Hooks
@@ -8372,19 +8372,19 @@ TSVConnReenable(TSVConn vconn)
void
TSVConnReenableEx(TSVConn vconn, TSEvent event)
{
- NetVConnection *vc = reinterpret_cast<NetVConnection *>(vconn);
- SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
- // We really only deal with a SSLNetVConnection at the moment
- if (ssl_vc != nullptr) {
+ NetVConnection *vc = reinterpret_cast<NetVConnection *>(vconn);
+
+ if (auto tes = vc->get_service<TLSEventSupport>(); tes) {
EThread *eth = this_ethread();
// We use the mutex of VC's NetHandler so we can put the VC into
ready_list by reenable()
- MUTEX_TRY_LOCK(trylock, ssl_vc->nh->mutex, eth);
+ Ptr<ProxyMutex> m = tes->getMutexForTLSEvents();
+ MUTEX_TRY_LOCK(trylock, m, eth);
if (trylock.is_locked()) {
- ssl_vc->reenable(ssl_vc->nh, event);
+ tes->reenable(event);
} else {
// We schedule the reenable to the home thread of ssl_vc.
- ssl_vc->thread->schedule_imm(new TSSslCallback(ssl_vc, event));
+ tes->getThreadForTLSEvents()->schedule_imm(new TSSslCallback(tes,
event));
}
}
}
diff --git a/src/iocore/net/CMakeLists.txt b/src/iocore/net/CMakeLists.txt
index 7d925af515..45371e3c8d 100644
--- a/src/iocore/net/CMakeLists.txt
+++ b/src/iocore/net/CMakeLists.txt
@@ -55,6 +55,7 @@ add_library(
SSLUtils.cc
OCSPStapling.cc
TLSBasicSupport.cc
+ TLSEventSupport.cc
TLSCertSwitchSupport.cc
TLSEarlyDataSupport.cc
TLSKeyLogger.cc
diff --git a/src/iocore/net/P_QUICNetVConnection.h
b/src/iocore/net/P_QUICNetVConnection.h
index fd1ae29938..019f870eaa 100644
--- a/src/iocore/net/P_QUICNetVConnection.h
+++ b/src/iocore/net/P_QUICNetVConnection.h
@@ -43,6 +43,7 @@
#include "P_UDPNet.h"
#include "iocore/net/TLSALPNSupport.h"
#include "iocore/net/TLSBasicSupport.h"
+#include "iocore/net/TLSEventSupport.h"
#include "iocore/net/TLSSessionResumptionSupport.h"
#include "iocore/net/TLSSNISupport.h"
#include "iocore/net/TLSCertSwitchSupport.h"
@@ -59,6 +60,7 @@
#include <netinet/in.h>
#include <quiche.h>
+class EThread;
class QUICPacketHandler;
class QUICResetTokenTable;
class QUICConnectionTable;
@@ -70,6 +72,7 @@ class QUICNetVConnection : public UnixNetVConnection,
public TLSSNISupport,
public TLSSessionResumptionSupport,
public TLSCertSwitchSupport,
+ public TLSEventSupport,
public TLSBasicSupport,
public QUICSupport
{
@@ -142,6 +145,12 @@ public:
// QUICNetVConnection
int in_closed_queue = 0;
+ // TLSEventSupport
+ void reenable(int event) override;
+ Continuation *getContinuationForTLSEvents() override;
+ EThread *getThreadForTLSEvents() override;
+ Ptr<ProxyMutex> getMutexForTLSEvents() override;
+
bool shouldDestroy();
void destroy(EThread *t);
void remove_connection_ids();
@@ -158,7 +167,6 @@ protected:
ssl_curve_id _get_tls_curve() const override;
// TLSSNISupport
- void _fire_ssl_servername_event() override;
in_port_t _get_local_port() override;
// TLSSessionResumptionSupport
@@ -169,6 +177,19 @@ protected:
shared_SSL_CTX _lookupContextByName(const std::string &servername,
SSLCertContextType ctxType) override;
shared_SSL_CTX _lookupContextByIP() override;
+ // TLSEventSupport
+ bool
+ _is_tunneling_requested() const override
+ {
+ // FIXME Not Supported
+ return false;
+ }
+ void
+ _switch_to_tunneling_mode() override
+ {
+ // FIXME Not supported
+ }
+
private:
SSL *_ssl;
QUICConfig::scoped_config _quic_config;
diff --git a/src/iocore/net/P_SSLNetVConnection.h
b/src/iocore/net/P_SSLNetVConnection.h
index 0f54f75fa0..edce1e1206 100644
--- a/src/iocore/net/P_SSLNetVConnection.h
+++ b/src/iocore/net/P_SSLNetVConnection.h
@@ -43,6 +43,7 @@
#include "iocore/net/TLSEarlyDataSupport.h"
#include "iocore/net/TLSTunnelSupport.h"
#include "iocore/net/TLSBasicSupport.h"
+#include "iocore/net/TLSEventSupport.h"
#include "iocore/net/TLSCertSwitchSupport.h"
#include "P_SSLUtils.h"
#include "P_SSLConfig.h"
@@ -105,6 +106,7 @@ class SSLNetVConnection : public UnixNetVConnection,
public TLSEarlyDataSupport,
public TLSTunnelSupport,
public TLSCertSwitchSupport,
+ public TLSEventSupport,
public TLSBasicSupport
{
typedef UnixNetVConnection super; ///< Parent type.
@@ -195,9 +197,6 @@ public:
// Copy up here so we overload but don't override
using super::reenable;
- /// Reenable the VC after a pre-accept or SNI hook is called.
- virtual void reenable(NetHandler *nh, int event = TS_EVENT_CONTINUE);
-
int64_t read_raw_data();
void
@@ -227,80 +226,6 @@ public:
this->handShakeBioStored = 0;
}
- // Returns true if all the hooks reenabled
- bool callHooks(TSEvent eventId);
-
- // Returns true if we have already called at
- // least some of the hooks
- bool
- calledHooks(TSEvent eventId) const
- {
- bool retval = false;
- switch (this->sslHandshakeHookState) {
- case HANDSHAKE_HOOKS_PRE:
- case HANDSHAKE_HOOKS_PRE_INVOKE:
- if (eventId == TS_EVENT_VCONN_START) {
- if (curHook) {
- retval = true;
- }
- }
- break;
- case HANDSHAKE_HOOKS_CLIENT_HELLO:
- case HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
- if (eventId == TS_EVENT_VCONN_START) {
- retval = true;
- } else if (eventId == TS_EVENT_SSL_CLIENT_HELLO) {
- if (curHook) {
- retval = true;
- }
- }
- break;
- case HANDSHAKE_HOOKS_SNI:
- if (eventId == TS_EVENT_VCONN_START || eventId ==
TS_EVENT_SSL_CLIENT_HELLO) {
- retval = true;
- } else if (eventId == TS_EVENT_SSL_SERVERNAME) {
- if (curHook) {
- retval = true;
- }
- }
- break;
- case HANDSHAKE_HOOKS_CERT:
- case HANDSHAKE_HOOKS_CERT_INVOKE:
- if (eventId == TS_EVENT_VCONN_START || eventId ==
TS_EVENT_SSL_CLIENT_HELLO || eventId == TS_EVENT_SSL_SERVERNAME) {
- retval = true;
- } else if (eventId == TS_EVENT_SSL_CERT) {
- if (curHook) {
- retval = true;
- }
- }
- break;
- case HANDSHAKE_HOOKS_CLIENT_CERT:
- case HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE:
- if (eventId == TS_EVENT_SSL_VERIFY_CLIENT || eventId ==
TS_EVENT_VCONN_START) {
- retval = true;
- }
- break;
-
- case HANDSHAKE_HOOKS_OUTBOUND_PRE:
- case HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE:
- if (eventId == TS_EVENT_VCONN_OUTBOUND_START) {
- if (curHook) {
- retval = true;
- }
- }
- break;
-
- case HANDSHAKE_HOOKS_VERIFY_SERVER:
- retval = (eventId == TS_EVENT_SSL_VERIFY_SERVER);
- break;
-
- case HANDSHAKE_HOOKS_DONE:
- retval = true;
- break;
- }
- return retval;
- }
-
int populate_protocol(std::string_view *results, int n) const
override;
const char *protocol_contains(std::string_view tag) const override;
@@ -387,7 +312,15 @@ public:
return _ca_cert_dir.get();
}
+ // TLSEventSupport
+ /// Reenable the VC after a pre-accept or SNI hook is called.
+ void reenable(int event = TS_EVENT_CONTINUE) override;
+ Continuation *getContinuationForTLSEvents() override;
+ EThread *getThreadForTLSEvents() override;
+ Ptr<ProxyMutex> getMutexForTLSEvents() override;
+
protected:
+ // TLSBasicSupport
SSL *
_get_ssl_object() const override
{
@@ -395,6 +328,7 @@ protected:
}
ssl_curve_id _get_tls_curve() const override;
+ // TLSSessionResumptionSupport
const IpEndpoint &
_getLocalEndpoint() override
{
@@ -402,13 +336,24 @@ protected:
}
// TLSSNISupport
- void _fire_ssl_servername_event() override;
in_port_t _get_local_port() override;
bool _isTryingRenegotiation() const override;
shared_SSL_CTX _lookupContextByName(const std::string &servername,
SSLCertContextType ctxType) override;
shared_SSL_CTX _lookupContextByIP() override;
+ // TLSEventSupport
+ bool
+ _is_tunneling_requested() const override
+ {
+ return SSL_HOOK_OP_TUNNEL == hookOpRequested;
+ }
+ void
+ _switch_to_tunneling_mode() override
+ {
+ this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
+ }
+
private:
std::string_view map_tls_protocol_to_tag(const char *proto_string) const;
bool update_rbio(bool move_to_socket);
@@ -429,28 +374,6 @@ private:
int sent_cert = 0;
- /// The current hook.
- /// @note For @C SSL_HOOKS_INVOKE, this is the hook to invoke.
- class APIHook *curHook = nullptr;
-
- enum SSLHandshakeHookState {
- HANDSHAKE_HOOKS_PRE,
- HANDSHAKE_HOOKS_PRE_INVOKE,
- HANDSHAKE_HOOKS_CLIENT_HELLO,
- HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE,
- HANDSHAKE_HOOKS_SNI,
- HANDSHAKE_HOOKS_CERT,
- HANDSHAKE_HOOKS_CERT_INVOKE,
- HANDSHAKE_HOOKS_CLIENT_CERT,
- HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE,
- HANDSHAKE_HOOKS_OUTBOUND_PRE,
- HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE,
- HANDSHAKE_HOOKS_VERIFY_SERVER,
- HANDSHAKE_HOOKS_DONE
- } sslHandshakeHookState = HANDSHAKE_HOOKS_PRE;
-
- static char const *get_ssl_handshake_hook_state_name(SSLHandshakeHookState
state);
-
int64_t redoWriteSize = 0;
X509_STORE_CTX *verify_cert = nullptr;
diff --git a/src/iocore/net/QUICNetVConnection.cc
b/src/iocore/net/QUICNetVConnection.cc
index d20330360e..d6c002221c 100644
--- a/src/iocore/net/QUICNetVConnection.cc
+++ b/src/iocore/net/QUICNetVConnection.cc
@@ -24,9 +24,12 @@
#include "P_SSLUtils.h"
#include "P_QUICNetVConnection.h"
#include "P_QUICPacketHandler.h"
+#include "api/APIHook.h"
+#include "iocore/eventsystem/EThread.h"
#include "iocore/net/QUICMultiCertConfigLoader.h"
#include "iocore/net/quic/QUICStream.h"
#include "iocore/net/quic/QUICGlobals.h"
+#include "iocore/net/SSLAPIHooks.h"
#include <netinet/in.h>
#include <quiche.h>
@@ -49,6 +52,7 @@ QUICNetVConnection::QUICNetVConnection()
{
this->_set_service(static_cast<ALPNSupport *>(this));
this->_set_service(static_cast<TLSBasicSupport *>(this));
+ this->_set_service(static_cast<TLSEventSupport *>(this));
this->_set_service(static_cast<TLSCertSwitchSupport *>(this));
this->_set_service(static_cast<TLSSNISupport *>(this));
this->_set_service(static_cast<TLSSessionResumptionSupport *>(this));
@@ -142,6 +146,7 @@ QUICNetVConnection::free_thread(EThread * /* t ATS_UNUSED
*/)
super::clear();
ALPNSupport::clear();
TLSBasicSupport::clear();
+ TLSEventSupport::clear();
TLSCertSwitchSupport::_clear();
this->_packet_handler->close_connection(this);
@@ -540,6 +545,7 @@ void
QUICNetVConnection::_bindSSLObject()
{
TLSBasicSupport::bind(this->_ssl, this);
+ TLSEventSupport::bind(this->_ssl, this);
ALPNSupport::bind(this->_ssl, this);
TLSSessionResumptionSupport::bind(this->_ssl, this);
TLSSNISupport::bind(this->_ssl, this);
@@ -551,6 +557,7 @@ void
QUICNetVConnection::_unbindSSLObject()
{
TLSBasicSupport::unbind(this->_ssl);
+ TLSEventSupport::unbind(this->_ssl);
ALPNSupport::unbind(this->_ssl);
TLSSessionResumptionSupport::unbind(this->_ssl);
TLSSNISupport::unbind(this->_ssl);
@@ -761,6 +768,29 @@ QUICNetVConnection::get_quic_connection()
return static_cast<QUICConnection *>(this);
}
+void
+QUICNetVConnection::reenable(int /* event ATS_UNUSED */)
+{
+}
+
+Continuation *
+QUICNetVConnection::getContinuationForTLSEvents()
+{
+ return this;
+}
+
+EThread *
+QUICNetVConnection::getThreadForTLSEvents()
+{
+ return this->thread;
+}
+
+Ptr<ProxyMutex>
+QUICNetVConnection::getMutexForTLSEvents()
+{
+ return this->nh->mutex;
+}
+
SSL *
QUICNetVConnection::_get_ssl_object() const
{
@@ -777,11 +807,6 @@ QUICNetVConnection::_get_tls_curve() const
}
}
-void
-QUICNetVConnection::_fire_ssl_servername_event()
-{
-}
-
in_port_t
QUICNetVConnection::_get_local_port()
{
diff --git a/src/iocore/net/SSLClientUtils.cc b/src/iocore/net/SSLClientUtils.cc
index 51b6d4a897..aef0ecf9f3 100644
--- a/src/iocore/net/SSLClientUtils.cc
+++ b/src/iocore/net/SSLClientUtils.cc
@@ -132,7 +132,10 @@ verify_callback(int signature_ok, X509_STORE_CTX *ctx)
}
// If the previous configured checks passed, give the hook a try
netvc->set_verify_cert(ctx);
- netvc->callHooks(TS_EVENT_SSL_VERIFY_SERVER);
+ TLSEventSupport *es = TLSEventSupport::getInstance(ssl);
+ if (es) {
+ es->callHooks(TS_EVENT_SSL_VERIFY_SERVER);
+ }
netvc->set_verify_cert(nullptr);
if (netvc->getSSLHandshakeStatus() ==
SSLHandshakeStatus::SSL_HANDSHAKE_ERROR) {
diff --git a/src/iocore/net/SSLNetVConnection.cc
b/src/iocore/net/SSLNetVConnection.cc
index dcf222aea7..0ca851ebc8 100644
--- a/src/iocore/net/SSLNetVConnection.cc
+++ b/src/iocore/net/SSLNetVConnection.cc
@@ -39,7 +39,6 @@
#include "P_SSLClientUtils.h"
#include "P_SSLNetVConnection.h"
#include "BIO_fastopen.h"
-#include "iocore/net/SSLAPIHooks.h"
#include "SSLStats.h"
#include "iocore/net/TLSALPNSupport.h"
@@ -92,117 +91,12 @@ DbgCtl dbg_ctl_ssl_alpn{"ssl_alpn"};
DbgCtl dbg_ctl_ssl_origin_session_cache{"ssl.origin_session_cache"};
DbgCtl dbg_ctl_proxyprotocol{"proxyprotocol"};
-/// Callback to get two locks.
-/// The lock for this continuation, and for the target continuation.
-class ContWrapper : public Continuation
-{
-public:
- /** Constructor.
- This takes the secondary @a mutex and the @a target continuation
- to invoke, along with the arguments for that invocation.
- */
- ContWrapper(ProxyMutex *mutex, ///< Mutex for this
continuation (primary lock).
- Continuation *target, ///< "Real"
continuation we want to call.
- int eventId = EVENT_IMMEDIATE, ///< Event ID for
invocation of @a target.
- void *edata = nullptr ///< Data for
invocation of @a target.
- )
- : Continuation(mutex), _target(target), _eventId(eventId), _edata(edata)
- {
- SET_HANDLER(&ContWrapper::event_handler);
- }
-
- /// Required event handler method.
- int
- event_handler(int, void *)
- {
- EThread *eth = this_ethread();
-
- MUTEX_TRY_LOCK(lock, _target->mutex, eth);
- if (lock.is_locked()) { // got the target lock, we can proceed.
- _target->handleEvent(_eventId, _edata);
- delete this;
- } else { // can't get both locks, try again.
- eventProcessor.schedule_imm(this, ET_NET);
- }
- return 0;
- }
-
- /** Convenience static method.
-
- This lets a client make one call and not have to (accurately)
- copy the invocation logic embedded here. We duplicate it near
- by textually so it is easier to keep in sync.
-
- This takes the same arguments as the constructor but, if the
- lock can be obtained immediately, does not construct an
- instance but simply calls the @a target.
- */
- static void
- wrap(ProxyMutex *mutex, ///< Mutex for this
continuation (primary lock).
- Continuation *target, ///< "Real" continuation we
want to call.
- int eventId = EVENT_IMMEDIATE, ///< Event ID for invocation
of @a target.
- void *edata = nullptr ///< Data for invocation of @a
target.
- )
- {
- EThread *eth = this_ethread();
- if (!target->mutex) {
- // If there's no mutex, plugin doesn't care about locking so why should
we?
- target->handleEvent(eventId, edata);
- } else {
- MUTEX_TRY_LOCK(lock, target->mutex, eth);
- if (lock.is_locked()) {
- target->handleEvent(eventId, edata);
- } else {
- eventProcessor.schedule_imm(new ContWrapper(mutex, target, eventId,
edata), ET_NET);
- }
- }
- }
-
-private:
- Continuation *_target; ///< Continuation to invoke.
- int _eventId; ///< with this event
- void *_edata; ///< and this data
-};
} // namespace
//
// Private
//
-char const *
-SSLNetVConnection::get_ssl_handshake_hook_state_name(SSLHandshakeHookState
state)
-{
- switch (state) {
- case HANDSHAKE_HOOKS_PRE:
- return "TS_SSL_HOOK_PRE_ACCEPT";
- case HANDSHAKE_HOOKS_PRE_INVOKE:
- return "TS_SSL_HOOK_PRE_ACCEPT_INVOKE";
- case HANDSHAKE_HOOKS_CLIENT_HELLO:
- return "TS_SSL_HOOK_CLIENT_HELLO";
- case HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
- return "TS_SSL_HOOK_CLIENT_HELLO_INVOKE";
- case HANDSHAKE_HOOKS_SNI:
- return "TS_SSL_HOOK_SERVERNAME";
- case HANDSHAKE_HOOKS_CERT:
- return "TS_SSL_HOOK_CERT";
- case HANDSHAKE_HOOKS_CERT_INVOKE:
- return "TS_SSL_HOOK_CERT_INVOKE";
- case HANDSHAKE_HOOKS_CLIENT_CERT:
- return "TS_SSL_HOOK_CLIENT_CERT";
- case HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE:
- return "TS_SSL_HOOK_CLIENT_CERT_INVOKE";
- case HANDSHAKE_HOOKS_OUTBOUND_PRE:
- return "TS_SSL_HOOK_PRE_CONNECT";
- case HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE:
- return "TS_SSL_HOOK_PRE_CONNECT_INVOKE";
- case HANDSHAKE_HOOKS_VERIFY_SERVER:
- return "TS_SSL_HOOK_VERIFY_SERVER";
- case HANDSHAKE_HOOKS_DONE:
- return "TS_SSL_HOOKS_DONE";
- }
- return "unknown handshake hook name";
-}
-
void
SSLNetVConnection::_make_ssl_connection(SSL_CTX *ctx)
{
@@ -236,6 +130,7 @@ SSLNetVConnection::_bindSSLObject()
{
SSLNetVCAttach(this->ssl, this);
TLSBasicSupport::bind(this->ssl, this);
+ TLSEventSupport::bind(this->ssl, this);
ALPNSupport::bind(this->ssl, this);
TLSSessionResumptionSupport::bind(this->ssl, this);
TLSSNISupport::bind(this->ssl, this);
@@ -249,6 +144,7 @@ SSLNetVConnection::_unbindSSLObject()
{
SSLNetVCDetach(this->ssl);
TLSBasicSupport::unbind(this->ssl);
+ TLSEventSupport::unbind(this->ssl);
ALPNSupport::unbind(this->ssl);
TLSSessionResumptionSupport::unbind(this->ssl);
TLSSNISupport::unbind(this->ssl);
@@ -929,6 +825,7 @@ SSLNetVConnection::SSLNetVConnection()
{
this->_set_service(static_cast<ALPNSupport *>(this));
this->_set_service(static_cast<TLSBasicSupport *>(this));
+ this->_set_service(static_cast<TLSEventSupport *>(this));
this->_set_service(static_cast<TLSCertSwitchSupport *>(this));
this->_set_service(static_cast<TLSEarlyDataSupport *>(this));
this->_set_service(static_cast<TLSSNISupport *>(this));
@@ -1010,6 +907,7 @@ SSLNetVConnection::clear()
ALPNSupport::clear();
TLSBasicSupport::clear();
+ TLSEventSupport::clear();
TLSSessionResumptionSupport::clear();
TLSSNISupport::_clear();
TLSTunnelSupport::_clear();
@@ -1020,7 +918,6 @@ SSLNetVConnection::clear()
sslTotalBytesSent = 0;
sslClientRenegotiationAbort = false;
- curHook = nullptr;
hookOpRequested = SSL_HOOK_OP_DEFAULT;
free_handshake_buffers();
@@ -1281,27 +1178,13 @@ int
SSLNetVConnection::sslServerHandShakeEvent(int &err)
{
// Continue on if we are in the invoked state. The hook has not yet
reenabled
- if (sslHandshakeHookState == HANDSHAKE_HOOKS_CERT_INVOKE ||
sslHandshakeHookState == HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE ||
- sslHandshakeHookState == HANDSHAKE_HOOKS_PRE_INVOKE ||
sslHandshakeHookState == HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE) {
+ if (this->is_invoked_state()) {
return SSL_WAIT_FOR_HOOK;
}
// Go do the preaccept hooks
- if (sslHandshakeHookState == HANDSHAKE_HOOKS_PRE) {
- Metrics::Counter::increment(ssl_rsb.total_attempts_handshake_count_in);
- if (!curHook) {
- Dbg(dbg_ctl_ssl, "Initialize preaccept curHook from NULL");
- curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_VCONN_START_HOOK));
- } else {
- curHook = curHook->next();
- }
- // If no more hooks, move onto CLIENT HELLO
-
- if (nullptr == curHook) {
- sslHandshakeHookState = HANDSHAKE_HOOKS_CLIENT_HELLO;
- } else {
- sslHandshakeHookState = HANDSHAKE_HOOKS_PRE_INVOKE;
- ContWrapper::wrap(nh->mutex.get(), curHook->m_cont,
TS_EVENT_VCONN_START, this);
+ if (this->get_handshake_hook_state() ==
TLSEventSupport::SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE) {
+ if (this->invoke_tls_event() == 1) {
return SSL_WAIT_FOR_HOOK;
}
}
@@ -1325,7 +1208,8 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err)
return EVENT_DONE;
}
- Dbg(dbg_ctl_ssl, "Go on with the handshake state=%s",
get_ssl_handshake_hook_state_name(sslHandshakeHookState));
+ Dbg(dbg_ctl_ssl, "Go on with the handshake state=%s",
+
TLSEventSupport::get_ssl_handshake_hook_state_name(this->get_handshake_hook_state()));
// All the pre-accept hooks have completed, proceed with the actual accept.
if (this->handShakeReader) {
@@ -1552,7 +1436,7 @@ SSLNetVConnection::sslClientHandShakeEvent(int &err)
ink_assert(TLSBasicSupport::getInstance(ssl) == this);
// Initialize properly for a client connection
- if (sslHandshakeHookState == HANDSHAKE_HOOKS_PRE) {
+ if (this->get_handshake_hook_state() ==
TLSEventSupport::SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE) {
if (this->pp_info.version != ProxyProtocolVersion::UNDEFINED) {
// Outbound PROXY Protocol
VIO &vio = this->write.vio;
@@ -1582,28 +1466,18 @@ SSLNetVConnection::sslClientHandShakeEvent(int &err)
}
}
- sslHandshakeHookState = HANDSHAKE_HOOKS_OUTBOUND_PRE;
+
this->set_handshake_hook_state(TLSEventSupport::SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE);
}
// Do outbound hook processing here
// Continue on if we are in the invoked state. The hook has not yet
reenabled
- if (sslHandshakeHookState == HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE) {
+ if (this->is_invoked_state()) {
return SSL_WAIT_FOR_HOOK;
}
// Go do the preaccept hooks
- if (sslHandshakeHookState == HANDSHAKE_HOOKS_OUTBOUND_PRE) {
- Metrics::Counter::increment(ssl_rsb.total_attempts_handshake_count_out);
- if (!curHook) {
- Dbg(dbg_ctl_ssl, "Initialize outbound connect curHook from NULL");
- curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_VCONN_OUTBOUND_START_HOOK));
- } else {
- curHook = curHook->next();
- }
- // If no more hooks, carry on
- if (nullptr != curHook) {
- sslHandshakeHookState = HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE;
- ContWrapper::wrap(nh->mutex.get(), curHook->m_cont,
TS_EVENT_VCONN_OUTBOUND_START, this);
+ if (this->get_handshake_hook_state() ==
TLSEventSupport::SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE) {
+ if (this->invoke_tls_event() == 1) {
return SSL_WAIT_FOR_HOOK;
}
}
@@ -1707,34 +1581,17 @@ SSLNetVConnection::sslClientHandShakeEvent(int &err)
}
void
-SSLNetVConnection::reenable(NetHandler *nh, int event)
+SSLNetVConnection::reenable(int event)
{
- Dbg(dbg_ctl_ssl, "Handshake reenable from state=%s",
get_ssl_handshake_hook_state_name(sslHandshakeHookState));
+ Dbg(dbg_ctl_ssl, "Handshake reenable from state=%s",
+
TLSEventSupport::get_ssl_handshake_hook_state_name(this->get_handshake_hook_state()));
// Mark as error to stop the Handshake
if (event == TS_EVENT_ERROR) {
sslHandshakeStatus = SSLHandshakeStatus::SSL_HANDSHAKE_ERROR;
}
- switch (sslHandshakeHookState) {
- case HANDSHAKE_HOOKS_PRE_INVOKE:
- sslHandshakeHookState = HANDSHAKE_HOOKS_PRE;
- break;
- case HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE:
- sslHandshakeHookState = HANDSHAKE_HOOKS_OUTBOUND_PRE;
- break;
- case HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
- sslHandshakeHookState = HANDSHAKE_HOOKS_CLIENT_HELLO;
- break;
- case HANDSHAKE_HOOKS_CERT_INVOKE:
- sslHandshakeHookState = HANDSHAKE_HOOKS_CERT;
- break;
- case HANDSHAKE_HOOKS_VERIFY_SERVER:
- case HANDSHAKE_HOOKS_CLIENT_CERT:
- break;
- default:
- break;
- }
+ this->resume_tls_event();
// Reenabling from the handshake callback
//
@@ -1743,232 +1600,31 @@ SSLNetVConnection::reenable(NetHandler *nh, int event)
// can be replaced by the plugin, it didn't seem reasonable to assume that
the
// callback would be executed again. So we walk through the rest of the
hooks
// here in the reenable.
- if (curHook != nullptr) {
- curHook = curHook->next();
- Dbg(dbg_ctl_ssl, "iterate from reenable curHook=%p", curHook);
- }
- if (curHook != nullptr) {
- // Invoke the hook and return, wait for next reenable
- if (sslHandshakeHookState == HANDSHAKE_HOOKS_CLIENT_HELLO) {
- sslHandshakeHookState = HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE;
- curHook->invoke(TS_EVENT_SSL_CLIENT_HELLO, this);
- } else if (sslHandshakeHookState == HANDSHAKE_HOOKS_CLIENT_CERT) {
- sslHandshakeHookState = HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE;
- curHook->invoke(TS_EVENT_SSL_VERIFY_CLIENT, this);
- } else if (sslHandshakeHookState == HANDSHAKE_HOOKS_CERT) {
- sslHandshakeHookState = HANDSHAKE_HOOKS_CERT_INVOKE;
- curHook->invoke(TS_EVENT_SSL_CERT, this);
- } else if (sslHandshakeHookState == HANDSHAKE_HOOKS_SNI) {
- curHook->invoke(TS_EVENT_SSL_SERVERNAME, this);
- } else if (sslHandshakeHookState == HANDSHAKE_HOOKS_PRE) {
- Dbg(dbg_ctl_ssl, "Reenable preaccept");
- sslHandshakeHookState = HANDSHAKE_HOOKS_PRE_INVOKE;
- ContWrapper::wrap(nh->mutex.get(), curHook->m_cont,
TS_EVENT_VCONN_START, this);
- } else if (sslHandshakeHookState == HANDSHAKE_HOOKS_OUTBOUND_PRE) {
- Dbg(dbg_ctl_ssl, "Reenable outbound connect");
- sslHandshakeHookState = HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE;
- ContWrapper::wrap(nh->mutex.get(), curHook->m_cont,
TS_EVENT_VCONN_OUTBOUND_START, this);
- } else if (sslHandshakeHookState == HANDSHAKE_HOOKS_DONE) {
- if (this->get_context() == NET_VCONNECTION_OUT) {
- ContWrapper::wrap(nh->mutex.get(), curHook->m_cont,
TS_EVENT_VCONN_OUTBOUND_CLOSE, this);
- } else {
- ContWrapper::wrap(nh->mutex.get(), curHook->m_cont,
TS_EVENT_VCONN_CLOSE, this);
- }
- } else if (sslHandshakeHookState == HANDSHAKE_HOOKS_VERIFY_SERVER) {
- Dbg(dbg_ctl_ssl, "ServerVerify");
- ContWrapper::wrap(nh->mutex.get(), curHook->m_cont,
TS_EVENT_SSL_VERIFY_SERVER, this);
- }
- return;
- } else {
- // Move onto the "next" state
- switch (this->sslHandshakeHookState) {
- case HANDSHAKE_HOOKS_PRE:
- case HANDSHAKE_HOOKS_PRE_INVOKE:
- sslHandshakeHookState = HANDSHAKE_HOOKS_CLIENT_HELLO;
- break;
- case HANDSHAKE_HOOKS_CLIENT_HELLO:
- case HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
- sslHandshakeHookState = HANDSHAKE_HOOKS_SNI;
- break;
- case HANDSHAKE_HOOKS_SNI:
- sslHandshakeHookState = HANDSHAKE_HOOKS_CERT;
- break;
- case HANDSHAKE_HOOKS_CERT:
- case HANDSHAKE_HOOKS_CERT_INVOKE:
- sslHandshakeHookState = HANDSHAKE_HOOKS_CLIENT_CERT;
- break;
- case HANDSHAKE_HOOKS_OUTBOUND_PRE:
- case HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE:
- this->write.triggered = true;
- this->write.enabled = true;
- this->writeReschedule(nh);
- sslHandshakeHookState = HANDSHAKE_HOOKS_DONE;
- break;
- case HANDSHAKE_HOOKS_CLIENT_CERT:
- case HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE:
- sslHandshakeHookState = HANDSHAKE_HOOKS_DONE;
- break;
- case HANDSHAKE_HOOKS_VERIFY_SERVER:
- sslHandshakeHookState = HANDSHAKE_HOOKS_DONE;
- break;
- default:
- break;
- }
- Dbg(dbg_ctl_ssl, "iterate from reenable curHook=%p %s", curHook,
get_ssl_handshake_hook_state_name(sslHandshakeHookState));
+ if (this->invoke_tls_event() == 2) {
+ this->write.triggered = true;
+ this->write.enabled = true;
+ this->writeReschedule(nh);
}
this->readReschedule(nh);
}
-bool
-SSLNetVConnection::callHooks(TSEvent eventId)
+Continuation *
+SSLNetVConnection::getContinuationForTLSEvents()
{
- // Only dealing with the SNI/CERT hook so far.
- ink_assert(eventId == TS_EVENT_SSL_CLIENT_HELLO || eventId ==
TS_EVENT_SSL_CERT || eventId == TS_EVENT_SSL_SERVERNAME ||
- eventId == TS_EVENT_SSL_VERIFY_SERVER || eventId ==
TS_EVENT_SSL_VERIFY_CLIENT || eventId == TS_EVENT_VCONN_CLOSE ||
- eventId == TS_EVENT_VCONN_OUTBOUND_CLOSE);
- Dbg(dbg_ctl_ssl, "sslHandshakeHookState=%s eventID=%d",
get_ssl_handshake_hook_state_name(this->sslHandshakeHookState), eventId);
-
- // Move state if it is appropriate
- if (eventId == TS_EVENT_VCONN_CLOSE) {
- // Regardless of state, if the connection is closing, then transition to
- // the DONE state. This will trigger us to call the appropriate cleanup
- // routines.
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_DONE;
- } else {
- switch (this->sslHandshakeHookState) {
- case HANDSHAKE_HOOKS_PRE:
- case HANDSHAKE_HOOKS_OUTBOUND_PRE:
- if (eventId == TS_EVENT_SSL_CLIENT_HELLO) {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_CLIENT_HELLO;
- } else if (eventId == TS_EVENT_SSL_SERVERNAME) {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_SNI;
- } else if (eventId == TS_EVENT_SSL_VERIFY_SERVER) {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_VERIFY_SERVER;
- } else if (eventId == TS_EVENT_SSL_CERT) {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_CERT;
- }
- break;
- case HANDSHAKE_HOOKS_CLIENT_HELLO:
- if (eventId == TS_EVENT_SSL_SERVERNAME) {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_SNI;
- } else if (eventId == TS_EVENT_SSL_CERT) {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_CERT;
- }
- break;
- case HANDSHAKE_HOOKS_SNI:
- if (eventId == TS_EVENT_SSL_CERT) {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_CERT;
- }
- break;
- default:
- break;
- }
- }
-
- // Look for hooks associated with the event
- switch (this->sslHandshakeHookState) {
- case HANDSHAKE_HOOKS_CLIENT_HELLO:
- case HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
- if (!curHook) {
- curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_SSL_CLIENT_HELLO_HOOK));
- } else {
- curHook = curHook->next();
- }
- if (curHook == nullptr) {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_SNI;
- } else {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE;
- }
- break;
- case HANDSHAKE_HOOKS_VERIFY_SERVER:
- // The server verify event addresses ATS to origin handshake
- // All the other events are for client to ATS
- if (!curHook) {
- curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_SSL_VERIFY_SERVER_HOOK));
- } else {
- curHook = curHook->next();
- }
- break;
- case HANDSHAKE_HOOKS_SNI:
- if (!curHook) {
- curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_SSL_SERVERNAME_HOOK));
- } else {
- curHook = curHook->next();
- }
- if (!curHook) {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_CERT;
- }
- break;
- case HANDSHAKE_HOOKS_CERT:
- case HANDSHAKE_HOOKS_CERT_INVOKE:
- if (!curHook) {
- curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_SSL_CERT_HOOK));
- } else {
- curHook = curHook->next();
- }
- if (curHook == nullptr) {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_CLIENT_CERT;
- } else {
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_CERT_INVOKE;
- }
- break;
- case HANDSHAKE_HOOKS_CLIENT_CERT:
- case HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE:
- if (!curHook) {
- curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_SSL_VERIFY_CLIENT_HOOK));
- } else {
- curHook = curHook->next();
- }
- // fallthrough
- case HANDSHAKE_HOOKS_DONE:
- case HANDSHAKE_HOOKS_OUTBOUND_PRE:
- if (eventId == TS_EVENT_VCONN_CLOSE) {
- sslHandshakeHookState = HANDSHAKE_HOOKS_DONE;
- if (curHook == nullptr) {
- curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_VCONN_CLOSE_HOOK));
- } else {
- curHook = curHook->next();
- }
- } else if (eventId == TS_EVENT_VCONN_OUTBOUND_CLOSE) {
- sslHandshakeHookState = HANDSHAKE_HOOKS_DONE;
- if (curHook == nullptr) {
- curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_VCONN_OUTBOUND_CLOSE_HOOK));
- } else {
- curHook = curHook->next();
- }
- }
- break;
- default:
- curHook = nullptr;
- this->sslHandshakeHookState = HANDSHAKE_HOOKS_DONE;
- return true;
- }
-
- Dbg(dbg_ctl_ssl, "iterated to curHook=%p", curHook);
-
- bool reenabled = true;
-
- if (SSL_HOOK_OP_TUNNEL == hookOpRequested) {
- this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
- // Don't mark the handshake as complete yet,
- // Will be checking for that flag not being set after
- // we get out of this callback, and then will shuffle
- // over the buffered handshake packets to the O.S.
- // sslHandShakeComplete = 1;
- return reenabled;
- }
+ return this;
+}
- if (curHook != nullptr) {
- WEAK_SCOPED_MUTEX_LOCK(lock, curHook->m_cont->mutex, this_ethread());
- curHook->invoke(eventId, this);
- reenabled =
- (this->sslHandshakeHookState != HANDSHAKE_HOOKS_CERT_INVOKE &&
this->sslHandshakeHookState != HANDSHAKE_HOOKS_PRE_INVOKE &&
- this->sslHandshakeHookState != HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE);
- Dbg(dbg_ctl_ssl, "Called hook on state=%s reenabled=%d",
get_ssl_handshake_hook_state_name(sslHandshakeHookState), reenabled);
- }
+EThread *
+SSLNetVConnection::getThreadForTLSEvents()
+{
+ return this->thread;
+}
- return reenabled;
+Ptr<ProxyMutex>
+SSLNetVConnection::getMutexForTLSEvents()
+{
+ return this->nh->mutex;
}
int
@@ -2116,12 +1772,6 @@ SSLNetVConnection::protocol_contains(std::string_view
prefix) const
return retval;
}
-void
-SSLNetVConnection::_fire_ssl_servername_event()
-{
- this->callHooks(TS_EVENT_SSL_SERVERNAME);
-}
-
in_port_t
SSLNetVConnection::_get_local_port()
{
diff --git a/src/iocore/net/SSLUtils.cc b/src/iocore/net/SSLUtils.cc
index 639cbfa4ad..95680bccb3 100644
--- a/src/iocore/net/SSLUtils.cc
+++ b/src/iocore/net/SSLUtils.cc
@@ -290,7 +290,10 @@ ssl_verify_client_callback(int preverify_ok,
X509_STORE_CTX *ctx)
}
netvc->set_verify_cert(ctx);
- netvc->callHooks(TS_EVENT_SSL_VERIFY_CLIENT);
+ TLSEventSupport *es = TLSEventSupport::getInstance(ssl);
+ if (es) {
+ es->callHooks(TS_EVENT_SSL_VERIFY_CLIENT);
+ }
netvc->set_verify_cert(nullptr);
if (netvc->getSSLHandShakeComplete()) { // hook moved the handshake state to
terminal
@@ -330,17 +333,15 @@ ssl_client_hello_callback(const SSL_CLIENT_HELLO
*client_hello)
return CLIENT_HELLO_ERROR;
}
- SSLNetVConnection *netvc = dynamic_cast<SSLNetVConnection *>(snis);
- if (netvc) {
- if (netvc->ssl != s) {
- Dbg(dbg_ctl_ssl_error, "ssl_client_hello_callback call back on stale
netvc");
- return CLIENT_HELLO_ERROR;
- }
-
- bool reenabled = netvc->callHooks(TS_EVENT_SSL_CLIENT_HELLO);
+ TLSEventSupport *es = TLSEventSupport::getInstance(s);
+ if (es) {
+ bool reenabled = es->callHooks(TS_EVENT_SSL_CLIENT_HELLO);
if (!reenabled) {
return CLIENT_HELLO_RETRY;
}
+ } else {
+ Dbg(dbg_ctl_ssl_error, "ssl_client_hello_callback call back on stale
netvc");
+ return CLIENT_HELLO_ERROR;
}
return CLIENT_HELLO_SUCCESS;
@@ -354,6 +355,7 @@ static int
ssl_cert_callback(SSL *ssl, [[maybe_unused]] void *arg)
{
TLSCertSwitchSupport *tcss = TLSCertSwitchSupport::getInstance(ssl);
+ TLSEventSupport *tes = TLSEventSupport::getInstance(ssl);
SSLNetVConnection *sslnetvc = dynamic_cast<SSLNetVConnection *>(tcss);
bool reenabled;
int retval = 1;
@@ -379,28 +381,30 @@ ssl_cert_callback(SSL *ssl, [[maybe_unused]] void *arg)
}
#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;
+ if (tcss) {
+ if (tes) {
+ // Do the common certificate lookup only once. If we pause
+ // and restart processing, do not execute the common logic again
+ if (!tes->calledHooks(TS_EVENT_SSL_CERT)) {
+ retval = tcss->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 && tcss->selectCertificate(ssl, ctxType) == 1) {
- retval = 1;
+ // Call the plugin cert code
+ reenabled = tes->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 {
- retval = 0;
+ if (tcss->selectCertificate(ssl, ctxType) == 1) {
+ retval = 1;
+ } else {
+ retval = 0;
+ }
}
}
@@ -433,6 +437,9 @@ ssl_servername_callback(SSL *ssl, int *al, void *arg)
{
TLSSNISupport *snis = TLSSNISupport::getInstance(ssl);
if (snis) {
+ if (TLSEventSupport *es = TLSEventSupport::getInstance(ssl); es) {
+ es->callHooks(TS_EVENT_SSL_SERVERNAME);
+ }
snis->on_servername(ssl, al, arg);
#if !TS_USE_HELLO_CB
// Only call the SNI actions here if not already performed in the HELLO_CB
@@ -900,6 +907,7 @@ SSLInitializeLibrary()
ssl_vc_index = SSL_get_ex_new_index(0, (void *)"NetVC index", nullptr,
nullptr, nullptr);
TLSBasicSupport::initialize();
+ TLSEventSupport::initialize();
ALPNSupport::initialize();
TLSSessionResumptionSupport::initialize();
TLSSNISupport::initialize();
diff --git a/src/iocore/net/TLSEventSupport.cc
b/src/iocore/net/TLSEventSupport.cc
new file mode 100644
index 0000000000..718332b9a1
--- /dev/null
+++ b/src/iocore/net/TLSEventSupport.cc
@@ -0,0 +1,553 @@
+/** @file
+
+ TLSSEventSupport.cc provides implementations for
+ TLSEventSupport methods
+
+ @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 <openssl/ssl.h>
+#include "iocore/net/TLSEventSupport.h"
+#include "iocore/net/SSLAPIHooks.h"
+#include "tscore/Diags.h"
+#include "SSLStats.h"
+
+int TLSEventSupport::_ex_data_index = -1;
+
+namespace
+{
+DbgCtl dbg_ctl_ssl{"ssl"};
+
+/// Callback to get two locks.
+/// The lock for this continuation, and for the target continuation.
+class ContWrapper : public Continuation
+{
+public:
+ /** Constructor.
+ This takes the secondary @a mutex and the @a target continuation
+ to invoke, along with the arguments for that invocation.
+ */
+ ContWrapper(ProxyMutex *mutex, ///< Mutex for this
continuation (primary lock).
+ Continuation *target, ///< "Real"
continuation we want to call.
+ int eventId = EVENT_IMMEDIATE, ///< Event ID for
invocation of @a target.
+ void *edata = nullptr ///< Data for
invocation of @a target.
+ )
+ : Continuation(mutex), _target(target), _eventId(eventId), _edata(edata)
+ {
+ SET_HANDLER(&ContWrapper::event_handler);
+ }
+
+ /// Required event handler method.
+ int
+ event_handler(int, void *)
+ {
+ EThread *eth = this_ethread();
+
+ MUTEX_TRY_LOCK(lock, _target->mutex, eth);
+ if (lock.is_locked()) { // got the target lock, we can proceed.
+ _target->handleEvent(_eventId, _edata);
+ delete this;
+ } else { // can't get both locks, try again.
+ eventProcessor.schedule_imm(this, ET_NET);
+ }
+ return 0;
+ }
+
+ /** Convenience static method.
+
+ This lets a client make one call and not have to (accurately)
+ copy the invocation logic embedded here. We duplicate it near
+ by textually so it is easier to keep in sync.
+
+ This takes the same arguments as the constructor but, if the
+ lock can be obtained immediately, does not construct an
+ instance but simply calls the @a target.
+ */
+ static void
+ wrap(ProxyMutex *mutex, ///< Mutex for this
continuation (primary lock).
+ Continuation *target, ///< "Real" continuation we
want to call.
+ int eventId = EVENT_IMMEDIATE, ///< Event ID for invocation
of @a target.
+ void *edata = nullptr ///< Data for invocation of @a
target.
+ )
+ {
+ EThread *eth = this_ethread();
+ if (!target->mutex) {
+ // If there's no mutex, plugin doesn't care about locking so why should
we?
+ target->handleEvent(eventId, edata);
+ } else {
+ MUTEX_TRY_LOCK(lock, target->mutex, eth);
+ if (lock.is_locked()) {
+ target->handleEvent(eventId, edata);
+ } else {
+ eventProcessor.schedule_imm(new ContWrapper(mutex, target, eventId,
edata), ET_NET);
+ }
+ }
+ }
+
+private:
+ Continuation *_target; ///< Continuation to invoke.
+ int _eventId; ///< with this event
+ void *_edata; ///< and this data
+};
+
+} // end anonymous namespace
+
+void
+TLSEventSupport::initialize()
+{
+ ink_assert(_ex_data_index == -1);
+ if (_ex_data_index == -1) {
+ _ex_data_index = SSL_get_ex_new_index(0, (void *)"TLSEventSupport index",
nullptr, nullptr, nullptr);
+ }
+}
+
+TLSEventSupport *
+TLSEventSupport::getInstance(SSL *ssl)
+{
+ return static_cast<TLSEventSupport *>(SSL_get_ex_data(ssl, _ex_data_index));
+}
+
+void
+TLSEventSupport::bind(SSL *ssl, TLSEventSupport *es)
+{
+ SSL_set_ex_data(ssl, _ex_data_index, es);
+ es->_ssl = ssl;
+}
+
+void
+TLSEventSupport::unbind(SSL *ssl)
+{
+ SSL_set_ex_data(ssl, _ex_data_index, nullptr);
+}
+
+void
+TLSEventSupport::clear()
+{
+ curHook = nullptr;
+}
+
+bool
+TLSEventSupport::callHooks(TSEvent eventId)
+{
+ // Only dealing with the SNI/CERT hook so far.
+ ink_assert(eventId == TS_EVENT_SSL_CLIENT_HELLO || eventId ==
TS_EVENT_SSL_CERT || eventId == TS_EVENT_SSL_SERVERNAME ||
+ eventId == TS_EVENT_SSL_VERIFY_SERVER || eventId ==
TS_EVENT_SSL_VERIFY_CLIENT || eventId == TS_EVENT_VCONN_CLOSE ||
+ eventId == TS_EVENT_VCONN_OUTBOUND_CLOSE);
+ Dbg(dbg_ctl_ssl, "sslHandshakeHookState=%s eventID=%d",
get_ssl_handshake_hook_state_name(this->sslHandshakeHookState), eventId);
+
+ // Move state if it is appropriate
+ if (eventId == TS_EVENT_VCONN_CLOSE) {
+ // Regardless of state, if the connection is closing, then transition to
+ // the DONE state. This will trigger us to call the appropriate cleanup
+ // routines.
+ this->sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_DONE;
+ } else {
+ switch (this->sslHandshakeHookState) {
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE:
+ if (eventId == TS_EVENT_SSL_CLIENT_HELLO) {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO;
+ } else if (eventId == TS_EVENT_SSL_SERVERNAME) {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_SNI;
+ } else if (eventId == TS_EVENT_SSL_VERIFY_SERVER) {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_VERIFY_SERVER;
+ } else if (eventId == TS_EVENT_SSL_CERT) {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT;
+ }
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO:
+ if (eventId == TS_EVENT_SSL_SERVERNAME) {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_SNI;
+ } else if (eventId == TS_EVENT_SSL_CERT) {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT;
+ }
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_SNI:
+ if (eventId == TS_EVENT_SSL_CERT) {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Look for hooks associated with the event
+ switch (this->sslHandshakeHookState) {
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
+ if (!curHook) {
+ curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_SSL_CLIENT_HELLO_HOOK));
+ } else {
+ curHook = curHook->next();
+ }
+ if (curHook == nullptr) {
+ this->sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_SNI;
+ } else {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE;
+ }
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_VERIFY_SERVER:
+ // The server verify event addresses ATS to origin handshake
+ // All the other events are for client to ATS
+ if (!curHook) {
+ curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_SSL_VERIFY_SERVER_HOOK));
+ } else {
+ curHook = curHook->next();
+ }
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_SNI:
+ if (!curHook) {
+ curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_SSL_SERVERNAME_HOOK));
+ } else {
+ curHook = curHook->next();
+ }
+ if (!curHook) {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT;
+ }
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT_INVOKE:
+ if (!curHook) {
+ curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_SSL_CERT_HOOK));
+ } else {
+ curHook = curHook->next();
+ }
+ if (curHook == nullptr) {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT;
+ } else {
+ this->sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT_INVOKE;
+ }
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE:
+ if (!curHook) {
+ curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_SSL_VERIFY_CLIENT_HOOK));
+ } else {
+ curHook = curHook->next();
+ }
+ [[fallthrough]];
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_DONE:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE:
+ if (eventId == TS_EVENT_VCONN_CLOSE) {
+ sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_DONE;
+ if (curHook == nullptr) {
+ curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_VCONN_CLOSE_HOOK));
+ } else {
+ curHook = curHook->next();
+ }
+ } else if (eventId == TS_EVENT_VCONN_OUTBOUND_CLOSE) {
+ sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_DONE;
+ if (curHook == nullptr) {
+ curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_VCONN_OUTBOUND_CLOSE_HOOK));
+ } else {
+ curHook = curHook->next();
+ }
+ }
+ break;
+ default:
+ curHook = nullptr;
+ this->sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_DONE;
+ return true;
+ }
+
+ Dbg(dbg_ctl_ssl, "iterated to curHook=%p", curHook);
+
+ bool reenabled = true;
+
+ if (this->_is_tunneling_requested()) {
+ this->_switch_to_tunneling_mode();
+ // Don't mark the handshake as complete yet,
+ // Will be checking for that flag not being set after
+ // we get out of this callback, and then will shuffle
+ // over the buffered handshake packets to the O.S.
+ // sslHandShakeComplete = 1;
+ return reenabled;
+ }
+
+ if (curHook != nullptr) {
+ WEAK_SCOPED_MUTEX_LOCK(lock, curHook->m_cont->mutex, this_ethread());
+ curHook->invoke(eventId, this->getContinuationForTLSEvents());
+ reenabled = (this->sslHandshakeHookState !=
SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT_INVOKE &&
+ this->sslHandshakeHookState !=
SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE_INVOKE &&
+ this->sslHandshakeHookState !=
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE);
+ Dbg(dbg_ctl_ssl, "Called hook on state=%s reenabled=%d",
get_ssl_handshake_hook_state_name(sslHandshakeHookState), reenabled);
+ }
+
+ return reenabled;
+}
+
+// Returns true if we have already called at
+// least some of the hooks
+bool
+TLSEventSupport::calledHooks(TSEvent eventId) const
+{
+ bool retval = false;
+ switch (this->sslHandshakeHookState) {
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE_INVOKE:
+ if (eventId == TS_EVENT_VCONN_START) {
+ if (curHook) {
+ retval = true;
+ }
+ }
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
+ if (eventId == TS_EVENT_VCONN_START) {
+ retval = true;
+ } else if (eventId == TS_EVENT_SSL_CLIENT_HELLO) {
+ if (curHook) {
+ retval = true;
+ }
+ }
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_SNI:
+ if (eventId == TS_EVENT_VCONN_START || eventId ==
TS_EVENT_SSL_CLIENT_HELLO) {
+ retval = true;
+ } else if (eventId == TS_EVENT_SSL_SERVERNAME) {
+ if (curHook) {
+ retval = true;
+ }
+ }
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT_INVOKE:
+ if (eventId == TS_EVENT_VCONN_START || eventId ==
TS_EVENT_SSL_CLIENT_HELLO || eventId == TS_EVENT_SSL_SERVERNAME) {
+ retval = true;
+ } else if (eventId == TS_EVENT_SSL_CERT) {
+ if (curHook) {
+ retval = true;
+ }
+ }
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE:
+ if (eventId == TS_EVENT_SSL_VERIFY_CLIENT || eventId ==
TS_EVENT_VCONN_START) {
+ retval = true;
+ }
+ break;
+
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE:
+ if (eventId == TS_EVENT_VCONN_OUTBOUND_START) {
+ if (curHook) {
+ retval = true;
+ }
+ }
+ break;
+
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_VERIFY_SERVER:
+ retval = (eventId == TS_EVENT_SSL_VERIFY_SERVER);
+ break;
+
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_DONE:
+ retval = true;
+ break;
+ }
+ return retval;
+}
+
+char const *
+TLSEventSupport::get_ssl_handshake_hook_state_name(SSLHandshakeHookState state)
+{
+ switch (state) {
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE:
+ return "TS_SSL_HOOK_PRE_ACCEPT";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE_INVOKE:
+ return "TS_SSL_HOOK_PRE_ACCEPT_INVOKE";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO:
+ return "TS_SSL_HOOK_CLIENT_HELLO";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
+ return "TS_SSL_HOOK_CLIENT_HELLO_INVOKE";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_SNI:
+ return "TS_SSL_HOOK_SERVERNAME";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT:
+ return "TS_SSL_HOOK_CERT";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT_INVOKE:
+ return "TS_SSL_HOOK_CERT_INVOKE";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT:
+ return "TS_SSL_HOOK_CLIENT_CERT";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE:
+ return "TS_SSL_HOOK_CLIENT_CERT_INVOKE";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE:
+ return "TS_SSL_HOOK_PRE_CONNECT";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE:
+ return "TS_SSL_HOOK_PRE_CONNECT_INVOKE";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_VERIFY_SERVER:
+ return "TS_SSL_HOOK_VERIFY_SERVER";
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_DONE:
+ return "TS_SSL_HOOKS_DONE";
+ }
+ return "unknown handshake hook name";
+}
+
+TLSEventSupport::SSLHandshakeHookState
+TLSEventSupport::get_handshake_hook_state()
+{
+ return this->sslHandshakeHookState;
+}
+
+void
+TLSEventSupport::set_handshake_hook_state(TLSEventSupport::SSLHandshakeHookState
state)
+{
+ this->sslHandshakeHookState = state;
+}
+
+bool
+TLSEventSupport::is_invoked_state() const
+{
+ return sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT_INVOKE ||
+ sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE ||
+ sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE_INVOKE ||
+ sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE ||
+ sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE;
+}
+
+int
+TLSEventSupport::invoke_tls_event()
+{
+ if (curHook != nullptr) {
+ curHook = curHook->next();
+ Dbg(dbg_ctl_ssl, "iterate from reenable curHook=%p", curHook);
+ }
+ if (curHook != nullptr) {
+ // Invoke the hook and return, wait for next reenable
+ if (sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO) {
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE;
+ curHook->invoke(TS_EVENT_SSL_CLIENT_HELLO,
this->getContinuationForTLSEvents());
+ } else if (sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT) {
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE;
+ curHook->invoke(TS_EVENT_SSL_VERIFY_CLIENT,
this->getContinuationForTLSEvents());
+ } else if (sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT) {
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT_INVOKE;
+ curHook->invoke(TS_EVENT_SSL_CERT, this->getContinuationForTLSEvents());
+ } else if (sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_SNI) {
+ curHook->invoke(TS_EVENT_SSL_SERVERNAME,
this->getContinuationForTLSEvents());
+ } else if (sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE) {
+ Dbg(dbg_ctl_ssl, "Reenable preaccept");
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE_INVOKE;
+ ContWrapper::wrap(this->getMutexForTLSEvents().get(), curHook->m_cont,
TS_EVENT_VCONN_START,
+ this->getContinuationForTLSEvents());
+ } else if (sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE) {
+ Dbg(dbg_ctl_ssl, "Reenable outbound connect");
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE;
+ ContWrapper::wrap(this->getMutexForTLSEvents().get(), curHook->m_cont,
TS_EVENT_VCONN_OUTBOUND_START,
+ this->getContinuationForTLSEvents());
+ } else if (sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_DONE) {
+ if (SSL_is_server(this->_ssl)) {
+ ContWrapper::wrap(this->getMutexForTLSEvents().get(), curHook->m_cont,
TS_EVENT_VCONN_CLOSE,
+ this->getContinuationForTLSEvents());
+ } else {
+ ContWrapper::wrap(this->getMutexForTLSEvents().get(), curHook->m_cont,
TS_EVENT_VCONN_OUTBOUND_CLOSE,
+ this->getContinuationForTLSEvents());
+ }
+ } else if (sslHandshakeHookState ==
SSLHandshakeHookState::HANDSHAKE_HOOKS_VERIFY_SERVER) {
+ Dbg(dbg_ctl_ssl, "ServerVerify");
+ ContWrapper::wrap(this->getMutexForTLSEvents().get(), curHook->m_cont,
TS_EVENT_SSL_VERIFY_SERVER,
+ this->getContinuationForTLSEvents());
+ }
+ return 1;
+ } else {
+ // Move onto the "next" state
+ switch (this->sslHandshakeHookState) {
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE:
+ if (this->_first_handshake_hooks_pre) {
+ this->_first_handshake_hooks_pre = false;
+ Metrics::Counter::increment(ssl_rsb.total_attempts_handshake_count_in);
+ Dbg(dbg_ctl_ssl, "Initialize preaccept curHook from NULL");
+ curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_VCONN_START_HOOK));
+ if (curHook) {
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE_INVOKE;
+ ContWrapper::wrap(this->getMutexForTLSEvents().get(),
curHook->m_cont, TS_EVENT_VCONN_START,
+ this->getContinuationForTLSEvents());
+ return 1;
+ }
+ }
+ [[fallthrough]];
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE_INVOKE:
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO;
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
+ sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_SNI;
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_SNI:
+ sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT;
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT_INVOKE:
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT;
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE:
+ if (this->_first_handshake_hooks_outbound_pre) {
+ this->_first_handshake_hooks_outbound_pre = false;
+
Metrics::Counter::increment(ssl_rsb.total_attempts_handshake_count_out);
+ Dbg(dbg_ctl_ssl, "Initialize outbound connect curHook from NULL");
+ curHook =
SSLAPIHooks::instance()->get(TSSslHookInternalID(TS_VCONN_OUTBOUND_START_HOOK));
+ if (curHook) {
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE;
+ ContWrapper::wrap(this->getMutexForTLSEvents().get(),
curHook->m_cont, TS_EVENT_VCONN_OUTBOUND_START,
+ this->getContinuationForTLSEvents());
+ return 1;
+ }
+ }
+ [[fallthrough]];
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE:
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE;
+ return 2;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE:
+ sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_DONE;
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_VERIFY_SERVER:
+ sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_DONE;
+ break;
+ default:
+ break;
+ }
+ Dbg(dbg_ctl_ssl, "iterate from reenable curHook=%p %s", curHook,
+
TLSEventSupport::get_ssl_handshake_hook_state_name(sslHandshakeHookState));
+ }
+ return 0;
+}
+
+void
+TLSEventSupport::resume_tls_event()
+{
+ switch (this->sslHandshakeHookState) {
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE_INVOKE:
+ sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_PRE;
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE:
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_OUTBOUND_PRE;
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
+ sslHandshakeHookState =
SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_HELLO;
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT_INVOKE:
+ sslHandshakeHookState = SSLHandshakeHookState::HANDSHAKE_HOOKS_CERT;
+ break;
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_VERIFY_SERVER:
+ case SSLHandshakeHookState::HANDSHAKE_HOOKS_CLIENT_CERT:
+ break;
+ default:
+ break;
+ }
+}
diff --git a/src/iocore/net/TLSSNISupport.cc b/src/iocore/net/TLSSNISupport.cc
index 090ad9d00d..4de80326d6 100644
--- a/src/iocore/net/TLSSNISupport.cc
+++ b/src/iocore/net/TLSSNISupport.cc
@@ -127,8 +127,6 @@ TLSSNISupport::on_client_hello(ClientHello &client_hello)
void
TLSSNISupport::on_servername(SSL *ssl, int * /* al ATS_UNUSED */, void * /*
arg ATS_UNUSED */)
{
- this->_fire_ssl_servername_event();
-
const char *name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
if (name) {
this->_set_sni_server_name(name);