From f3dcbd8d5e8481bb061575f9a7783eb8f89a0675 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Fri, 5 Mar 2021 09:34:09 +0900 Subject: [PATCH] Introduce TLSBasicSupport interface (#7556) * Introduce TLSBasicSupport interface This introduces an abstract interface to support QUICNetVC where we currently only supports SSLNetVC. * Run clang-format --- iocore/net/Makefile.am | 1 + iocore/net/P_SSLNetVConnection.h | 63 +++++---------- iocore/net/SSLNetVConnection.cc | 34 +++++--- iocore/net/SSLUtils.cc | 1 + iocore/net/TLSBasicSupport.cc | 134 +++++++++++++++++++++++++++++++ iocore/net/TLSBasicSupport.h | 62 ++++++++++++++ proxy/http/HttpSM.cc | 10 +-- src/traffic_server/InkAPI.cc | 19 ++--- 8 files changed, 252 insertions(+), 72 deletions(-) create mode 100644 iocore/net/TLSBasicSupport.cc create mode 100644 iocore/net/TLSBasicSupport.h diff --git a/iocore/net/Makefile.am b/iocore/net/Makefile.am index a07c6114bdd..85305f0dfb9 100644 --- a/iocore/net/Makefile.am +++ b/iocore/net/Makefile.am @@ -184,6 +184,7 @@ libinknet_a_SOURCES = \ SSLSessionTicket.cc \ SSLUtils.cc \ OCSPStapling.cc \ + TLSBasicSupport.cc \ TLSSessionResumptionSupport.cc \ TLSSNISupport.cc \ UDPIOEvent.cc \ diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h index 419e092f447..bc95bcf35d5 100644 --- a/iocore/net/P_SSLNetVConnection.h +++ b/iocore/net/P_SSLNetVConnection.h @@ -49,6 +49,7 @@ #include "P_ALPNSupport.h" #include "TLSSessionResumptionSupport.h" #include "TLSSNISupport.h" +#include "TLSBasicSupport.h" #include "P_SSLUtils.h" #include "P_SSLConfig.h" @@ -94,7 +95,11 @@ enum SSLHandshakeStatus { SSL_HANDSHAKE_ONGOING, SSL_HANDSHAKE_DONE, SSL_HANDSHA // A VConnection for a network socket. // ////////////////////////////////////////////////////////////////// -class SSLNetVConnection : public UnixNetVConnection, public ALPNSupport, public TLSSessionResumptionSupport, public TLSSNISupport +class SSLNetVConnection : public UnixNetVConnection, + public ALPNSupport, + public TLSSessionResumptionSupport, + public TLSSNISupport, + public TLSBasicSupport { typedef UnixNetVConnection super; ///< Parent type. @@ -106,9 +111,9 @@ class SSLNetVConnection : public UnixNetVConnection, public ALPNSupport, public bool trackFirstHandshake() override { - bool retval = sslHandshakeBeginTime == 0; + bool retval = this->get_tls_handshake_begin_time() == 0; if (retval) { - sslHandshakeBeginTime = Thread::get_hrtime(); + this->_record_tls_handshake_begin_time(); } return retval; } @@ -275,43 +280,6 @@ class SSLNetVConnection : public UnixNetVConnection, public ALPNSupport, public return retval; } - const char * - getSSLProtocol() const - { - return ssl ? SSL_get_version(ssl) : nullptr; - } - - const char * - getSSLCipherSuite() const - { - return ssl ? SSL_get_cipher_name(ssl) : nullptr; - } - - const char * - getSSLCurve() const - { - if (!ssl) { - return nullptr; - } - ssl_curve_id curve; - if (getSSLSessionCacheHit()) { - curve = getSSLCurveNID(); - } else { - curve = SSLGetCurveNID(ssl); - } -#ifndef OPENSSL_IS_BORINGSSL - if (curve == NID_undef) { - return nullptr; - } - return OBJ_nid2sn(curve); -#else - if (curve == 0) { - return nullptr; - } - return SSL_get_curve_name(curve); -#endif - } - bool has_tunnel_destination() const { @@ -362,11 +330,9 @@ class SSLNetVConnection : public UnixNetVConnection, public ALPNSupport, public */ int populate(Connection &con, Continuation *c, void *arg) override; - SSL *ssl = nullptr; - ink_hrtime sslHandshakeBeginTime = 0; - ink_hrtime sslHandshakeEndTime = 0; - ink_hrtime sslLastWriteTime = 0; - int64_t sslTotalBytesSent = 0; + SSL *ssl = nullptr; + ink_hrtime sslLastWriteTime = 0; + int64_t sslTotalBytesSent = 0; // The serverName is either a pointer to the (null-terminated) name fetched from the // SSL object or the empty string. @@ -468,6 +434,13 @@ class SSLNetVConnection : public UnixNetVConnection, public ALPNSupport, public } protected: + SSL * + _get_ssl_object() const override + { + return this->ssl; + } + ssl_curve_id _get_tls_curve() const override; + const IpEndpoint & _getLocalEndpoint() override { diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index 20a4a7e3b4c..b512e53461f 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -214,6 +214,7 @@ void SSLNetVConnection::_bindSSLObject() { SSLNetVCAttach(this->ssl, this); + TLSBasicSupport::bind(this->ssl, this); TLSSessionResumptionSupport::bind(this->ssl, this); TLSSNISupport::bind(this->ssl, this); } @@ -222,6 +223,7 @@ void SSLNetVConnection::_unbindSSLObject() { SSLNetVCDetach(this->ssl); + TLSBasicSupport::unbind(this->ssl); TLSSessionResumptionSupport::unbind(this->ssl); TLSSNISupport::unbind(this->ssl); } @@ -610,7 +612,7 @@ SSLNetVConnection::net_read_io(NetHandler *nh, EThread *lthread) readSignalError(nh, err); } else if (ret == SSL_HANDSHAKE_WANT_READ || ret == SSL_HANDSHAKE_WANT_ACCEPT) { if (SSLConfigParams::ssl_handshake_timeout_in > 0) { - double handshake_time = (static_cast(Thread::get_hrtime() - sslHandshakeBeginTime) / 1000000000); + double handshake_time = (static_cast(Thread::get_hrtime() - this->get_tls_handshake_begin_time()) / 1000000000); Debug("ssl", "ssl handshake for vc %p, took %.3f seconds, configured handshake_timer: %d", this, handshake_time, SSLConfigParams::ssl_handshake_timeout_in); if (handshake_time > SSLConfigParams::ssl_handshake_timeout_in) { @@ -938,11 +940,11 @@ SSLNetVConnection::clear() ssl = nullptr; } ALPNSupport::clear(); + TLSBasicSupport::clear(); TLSSessionResumptionSupport::clear(); TLSSNISupport::_clear(); sslHandshakeStatus = SSL_HANDSHAKE_ONGOING; - sslHandshakeBeginTime = 0; sslLastWriteTime = 0; sslTotalBytesSent = 0; sslClientRenegotiationAbort = false; @@ -999,8 +1001,8 @@ SSLNetVConnection::sslStartHandShake(int event, int &err) Debug("ssl", "Stopping handshake due to server shutting down."); return EVENT_ERROR; } - if (sslHandshakeBeginTime == 0) { - sslHandshakeBeginTime = Thread::get_hrtime(); + if (this->get_tls_handshake_begin_time() == 0) { + this->_record_tls_handshake_begin_time(); // net_activity will not be triggered until after the handshake set_inactivity_timeout(HRTIME_SECONDS(SSLConfigParams::ssl_handshake_timeout_in)); } @@ -1309,12 +1311,8 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err) sslHandshakeStatus = SSL_HANDSHAKE_DONE; - if (sslHandshakeBeginTime) { - sslHandshakeEndTime = Thread::get_hrtime(); - const ink_hrtime ssl_handshake_time = sslHandshakeEndTime - sslHandshakeBeginTime; - - Debug("ssl", "ssl handshake time:%" PRId64, ssl_handshake_time); - SSL_INCREMENT_DYN_STAT_EX(ssl_total_handshake_time_stat, ssl_handshake_time); + if (this->get_tls_handshake_begin_time()) { + this->_record_tls_handshake_end_time(); SSL_INCREMENT_DYN_STAT(ssl_total_success_handshake_count_in_stat); } @@ -1423,7 +1421,7 @@ SSLNetVConnection::sslClientHandShakeEvent(int &err) { ssl_error_t ssl_error; - ink_assert(SSLNetVCAccess(ssl) == this); + ink_assert(TLSBasicSupport::getInstance(ssl) == this); // Initialize properly for a client connection if (sslHandshakeHookState == HANDSHAKE_HOOKS_PRE) { @@ -1947,7 +1945,7 @@ SSLNetVConnection::populate_protocol(std::string_view *results, int n) const { int retval = 0; if (n > retval) { - results[retval] = map_tls_protocol_to_tag(getSSLProtocol()); + results[retval] = map_tls_protocol_to_tag(this->get_tls_protocol_name()); if (!results[retval].empty()) { ++retval; } @@ -1962,7 +1960,7 @@ const char * SSLNetVConnection::protocol_contains(std::string_view prefix) const { const char *retval = nullptr; - std::string_view tag = map_tls_protocol_to_tag(getSSLProtocol()); + std::string_view tag = map_tls_protocol_to_tag(this->get_tls_protocol_name()); if (prefix.size() <= tag.size() && strncmp(tag.data(), prefix.data(), prefix.size()) == 0) { retval = tag.data(); } else { @@ -2010,3 +2008,13 @@ SSLNetVConnection::_getNetProcessor() { return &sslNetProcessor; } + +ssl_curve_id +SSLNetVConnection::_get_tls_curve() const +{ + if (getSSLSessionCacheHit()) { + return getSSLCurveNID(); + } else { + return SSLGetCurveNID(ssl); + } +} diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc index c01cd387526..1239c690ea1 100644 --- a/iocore/net/SSLUtils.cc +++ b/iocore/net/SSLUtils.cc @@ -872,6 +872,7 @@ SSLInitializeLibrary() // the SSLNetVConnection to the SSL session. ssl_vc_index = SSL_get_ex_new_index(0, (void *)"NetVC index", nullptr, nullptr, nullptr); + TLSBasicSupport::initialize(); TLSSessionResumptionSupport::initialize(); TLSSNISupport::initialize(); diff --git a/iocore/net/TLSBasicSupport.cc b/iocore/net/TLSBasicSupport.cc new file mode 100644 index 00000000000..cd69eb62fc6 --- /dev/null +++ b/iocore/net/TLSBasicSupport.cc @@ -0,0 +1,134 @@ +/** @file + + TLSSBasicSupport.cc provides implmentations for + TLSBasicSupport 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 "TLSBasicSupport.h" +#include "SSLStats.h" + +int TLSBasicSupport::_ex_data_index = -1; + +void +TLSBasicSupport::initialize() +{ + ink_assert(_ex_data_index == -1); + if (_ex_data_index == -1) { + _ex_data_index = SSL_get_ex_new_index(0, (void *)"TLSBasicSupport index", nullptr, nullptr, nullptr); + } +} + +TLSBasicSupport * +TLSBasicSupport::getInstance(SSL *ssl) +{ + return static_cast(SSL_get_ex_data(ssl, _ex_data_index)); +} + +void +TLSBasicSupport::bind(SSL *ssl, TLSBasicSupport *srs) +{ + SSL_set_ex_data(ssl, _ex_data_index, srs); +} + +void +TLSBasicSupport::unbind(SSL *ssl) +{ + SSL_set_ex_data(ssl, _ex_data_index, nullptr); +} + +void +TLSBasicSupport::clear() +{ + this->_tls_handshake_begin_time = 0; + this->_tls_handshake_end_time = 0; +} + +const char * +TLSBasicSupport::get_tls_protocol_name() const +{ + auto ssl = this->_get_ssl_object(); + if (ssl) { + return SSL_get_version(ssl); + } else { + return nullptr; + } +} + +const char * +TLSBasicSupport::get_tls_cipher_suite() const +{ + auto ssl = this->_get_ssl_object(); + if (ssl) { + return SSL_get_cipher_name(ssl); + } else { + return nullptr; + } +} + +const char * +TLSBasicSupport::get_tls_curve() const +{ + auto ssl = this->_get_ssl_object(); + + if (!ssl) { + return nullptr; + } + ssl_curve_id curve = this->_get_tls_curve(); +#ifndef OPENSSL_IS_BORINGSSL + if (curve == NID_undef) { + return nullptr; + } + return OBJ_nid2sn(curve); +#else + if (curve == 0) { + return nullptr; + } + return SSL_get_curve_name(curve); +#endif +} + +ink_hrtime +TLSBasicSupport::get_tls_handshake_begin_time() const +{ + return this->_tls_handshake_begin_time; +} + +ink_hrtime +TLSBasicSupport::get_tls_handshake_end_time() const +{ + return this->_tls_handshake_end_time; +} + +void +TLSBasicSupport::_record_tls_handshake_begin_time() +{ + this->_tls_handshake_begin_time = Thread::get_hrtime(); +} + +void +TLSBasicSupport::_record_tls_handshake_end_time() +{ + this->_tls_handshake_end_time = Thread::get_hrtime(); + const ink_hrtime ssl_handshake_time = this->_tls_handshake_end_time - this->_tls_handshake_begin_time; + + Debug("ssl", "ssl handshake time:%" PRId64, ssl_handshake_time); + SSL_INCREMENT_DYN_STAT_EX(ssl_total_handshake_time_stat, ssl_handshake_time); +} diff --git a/iocore/net/TLSBasicSupport.h b/iocore/net/TLSBasicSupport.h new file mode 100644 index 00000000000..539eb1f26c6 --- /dev/null +++ b/iocore/net/TLSBasicSupport.h @@ -0,0 +1,62 @@ +/** @file + + TLSBasicSupport implements common methods and members to + support basic features on TLS connections + + @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 + +#include "tscore/ink_hrtime.h" +#include "P_SSLUtils.h" + +class TLSBasicSupport +{ +public: + virtual ~TLSBasicSupport() = default; + + static void initialize(); + static TLSBasicSupport *getInstance(SSL *ssl); + static void bind(SSL *ssl, TLSBasicSupport *srs); + static void unbind(SSL *ssl); + + const char *get_tls_protocol_name() const; + const char *get_tls_cipher_suite() const; + const char *get_tls_curve() const; + ink_hrtime get_tls_handshake_begin_time() const; + ink_hrtime get_tls_handshake_end_time() const; + +protected: + void clear(); + + virtual SSL *_get_ssl_object() const = 0; + virtual ssl_curve_id _get_tls_curve() const = 0; + + void _record_tls_handshake_begin_time(); + void _record_tls_handshake_end_time(); + +private: + static int _ex_data_index; + + ink_hrtime _tls_handshake_begin_time = 0; + ink_hrtime _tls_handshake_end_time = 0; +}; diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index e0e666c55fb..711cb7ecd27 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -552,18 +552,18 @@ HttpSM::attach_client_session(ProxyTransaction *client_vc, IOBufferReader *buffe if (ssl_vc != nullptr) { client_connection_is_ssl = true; client_ssl_reused = ssl_vc->getSSLSessionCacheHit(); - const char *protocol = ssl_vc->getSSLProtocol(); + const char *protocol = ssl_vc->get_tls_protocol_name(); client_sec_protocol = protocol ? protocol : "-"; - const char *cipher = ssl_vc->getSSLCipherSuite(); + const char *cipher = ssl_vc->get_tls_cipher_suite(); client_cipher_suite = cipher ? cipher : "-"; - const char *curve = ssl_vc->getSSLCurve(); + const char *curve = ssl_vc->get_tls_curve(); client_curve = curve ? curve : "-"; client_alpn_id = ssl_vc->get_negotiated_protocol_id(); if (!client_tcp_reused) { // Copy along the TLS handshake timings - milestones[TS_MILESTONE_TLS_HANDSHAKE_START] = ssl_vc->sslHandshakeBeginTime; - milestones[TS_MILESTONE_TLS_HANDSHAKE_END] = ssl_vc->sslHandshakeEndTime; + milestones[TS_MILESTONE_TLS_HANDSHAKE_START] = ssl_vc->get_tls_handshake_begin_time(); + milestones[TS_MILESTONE_TLS_HANDSHAKE_END] = ssl_vc->get_tls_handshake_end_time(); } } diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index e4b444c3e01..2cba9fabdfa 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -54,6 +54,7 @@ #include "P_SSLClientUtils.h" #include "SSLDiags.h" #include "SSLInternal.h" +#include "TLSBasicSupport.h" #include "ProxyConfig.h" #include "Plugin.h" #include "LogObject.h" @@ -6650,28 +6651,28 @@ TSVConnIsSslReused(TSVConn sslp) const char * TSVConnSslCipherGet(TSVConn sslp) { - NetVConnection *vc = reinterpret_cast(sslp); - SSLNetVConnection *ssl_vc = dynamic_cast(vc); + NetVConnection *vc = reinterpret_cast(sslp); + TLSBasicSupport *tlsbs = dynamic_cast(vc); - return ssl_vc ? ssl_vc->getSSLCipherSuite() : nullptr; + return tlsbs ? tlsbs->get_tls_cipher_suite() : nullptr; } const char * TSVConnSslProtocolGet(TSVConn sslp) { - NetVConnection *vc = reinterpret_cast(sslp); - SSLNetVConnection *ssl_vc = dynamic_cast(vc); + NetVConnection *vc = reinterpret_cast(sslp); + TLSBasicSupport *tlsbs = dynamic_cast(vc); - return ssl_vc ? ssl_vc->getSSLProtocol() : nullptr; + return tlsbs ? tlsbs->get_tls_protocol_name() : nullptr; } const char * TSVConnSslCurveGet(TSVConn sslp) { - NetVConnection *vc = reinterpret_cast(sslp); - SSLNetVConnection *ssl_vc = dynamic_cast(vc); + NetVConnection *vc = reinterpret_cast(sslp); + TLSBasicSupport *tlsbs = dynamic_cast(vc); - return ssl_vc ? ssl_vc->getSSLCurve() : nullptr; + return tlsbs ? tlsbs->get_tls_curve() : nullptr; } int