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 cb247c6 Generalize ALPN logic (#7555)
cb247c6 is described below
commit cb247c6af699cb08286f04bd2ef481031b5babc7
Author: Masakazu Kitajo <[email protected]>
AuthorDate: Tue Mar 9 17:31:10 2021 +0900
Generalize ALPN logic (#7555)
---
iocore/net/ALPNSupport.cc | 59 +++++++++++++++++++++++++++++++++
iocore/net/P_ALPNSupport.h | 13 ++++++++
iocore/net/P_QUICNetVConnection.h | 3 --
iocore/net/P_SSLNetVConnection.h | 3 --
iocore/net/QUICMultiCertConfigLoader.cc | 12 -------
iocore/net/QUICMultiCertConfigLoader.h | 2 --
iocore/net/QUICNetVConnection.cc | 22 ------------
iocore/net/SSLNetVConnection.cc | 44 ++----------------------
iocore/net/SSLUtils.cc | 35 +++++++++++++++++--
iocore/net/quic/QUICConnection.h | 2 --
10 files changed, 107 insertions(+), 88 deletions(-)
diff --git a/iocore/net/ALPNSupport.cc b/iocore/net/ALPNSupport.cc
index bf6874c..d643ab4 100644
--- a/iocore/net/ALPNSupport.cc
+++ b/iocore/net/ALPNSupport.cc
@@ -25,6 +25,35 @@
#include "P_SSLNextProtocolSet.h"
#include "records/I_RecHttp.h"
+int ALPNSupport::_ex_data_index = -1;
+
+void
+ALPNSupport::initialize()
+{
+ ink_assert(_ex_data_index == -1);
+ if (_ex_data_index == -1) {
+ _ex_data_index = SSL_get_ex_new_index(0, (void *)"ALPNSupport index",
nullptr, nullptr, nullptr);
+ }
+}
+
+ALPNSupport *
+ALPNSupport::getInstance(SSL *ssl)
+{
+ return static_cast<ALPNSupport *>(SSL_get_ex_data(ssl, _ex_data_index));
+}
+
+void
+ALPNSupport::bind(SSL *ssl, ALPNSupport *alpns)
+{
+ SSL_set_ex_data(ssl, _ex_data_index, alpns);
+}
+
+void
+ALPNSupport::unbind(SSL *ssl)
+{
+ SSL_set_ex_data(ssl, _ex_data_index, nullptr);
+}
+
void
ALPNSupport::clear()
{
@@ -53,6 +82,36 @@ ALPNSupport::setSelectedProtocol(const unsigned char *proto,
unsigned int len)
return true;
}
+int
+ALPNSupport::advertise_next_protocol(SSL *ssl, const unsigned char **out,
unsigned *outlen)
+{
+ if (this->getNPN(out, outlen)) {
+ // Successful return tells OpenSSL to advertise.
+ return SSL_TLSEXT_ERR_OK;
+ }
+ return SSL_TLSEXT_ERR_NOACK;
+}
+
+int
+ALPNSupport::select_next_protocol(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
+ unsigned inlen)
+{
+ const unsigned char *npnptr = nullptr;
+ unsigned int npnsize = 0;
+ if (this->getNPN(&npnptr, &npnsize)) {
+ // SSL_select_next_proto chooses the first server-offered protocol that
appears in the clients protocol set, ie. the
+ // server selects the protocol. This is a n^2 search, so it's preferable
to keep the protocol set short.
+ if (SSL_select_next_proto(const_cast<unsigned char **>(out), outlen,
npnptr, npnsize, in, inlen) == OPENSSL_NPN_NEGOTIATED) {
+ Debug("ssl", "selected ALPN protocol %.*s", (int)(*outlen), *out);
+ return SSL_TLSEXT_ERR_OK;
+ }
+ }
+
+ *out = nullptr;
+ *outlen = 0;
+ return SSL_TLSEXT_ERR_NOACK;
+}
+
void
ALPNSupport::disableProtocol(int idx)
{
diff --git a/iocore/net/P_ALPNSupport.h b/iocore/net/P_ALPNSupport.h
index e403122..fe39800 100644
--- a/iocore/net/P_ALPNSupport.h
+++ b/iocore/net/P_ALPNSupport.h
@@ -24,6 +24,7 @@
#pragma once
#include "records/I_RecHttp.h"
+#include <openssl/ssl.h>
class SSLNextProtocolSet;
class SSLNextProtocolAccept;
@@ -32,12 +33,22 @@ class Continuation;
class ALPNSupport
{
public:
+ virtual ~ALPNSupport() = default;
+
+ static void initialize();
+ static ALPNSupport *getInstance(SSL *ssl);
+ static void bind(SSL *ssl, ALPNSupport *alpns);
+ static void unbind(SSL *ssl);
+
void registerNextProtocolSet(SSLNextProtocolSet *, const SessionProtocolSet
&protos);
void disableProtocol(int idx);
void enableProtocol(int idx);
void clear();
bool setSelectedProtocol(const unsigned char *proto, unsigned int len);
+ int advertise_next_protocol(SSL *ssl, const unsigned char **out, unsigned
*outlen);
+ int select_next_protocol(SSL *ssl, const unsigned char **out, unsigned char
*outlen, const unsigned char *in, unsigned inlen);
+
Continuation *
endpoint() const
{
@@ -65,6 +76,8 @@ public:
int get_negotiated_protocol_id() const;
private:
+ static int _ex_data_index;
+
const SSLNextProtocolSet *npnSet = nullptr;
SessionProtocolSet protoenabled;
// Local copies of the npn strings
diff --git a/iocore/net/P_QUICNetVConnection.h
b/iocore/net/P_QUICNetVConnection.h
index f04f32d..bcc23b1 100644
--- a/iocore/net/P_QUICNetVConnection.h
+++ b/iocore/net/P_QUICNetVConnection.h
@@ -186,9 +186,6 @@ public:
int populate_protocol(std::string_view *results, int n) const override;
const char *protocol_contains(std::string_view tag) const override;
- int select_next_protocol(SSL *ssl, const unsigned char **out, unsigned char
*outlen, const unsigned char *in,
- unsigned inlen) const override;
-
// QUICConnection
QUICStreamManager *stream_manager() override;
void close_quic_connection(QUICConnectionErrorUPtr error) override;
diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h
index bc95bcf..b3b9544 100644
--- a/iocore/net/P_SSLNetVConnection.h
+++ b/iocore/net/P_SSLNetVConnection.h
@@ -143,9 +143,6 @@ public:
////////////////////////////////////////////////////////////
SSLNetVConnection();
~SSLNetVConnection() override {}
- static int advertise_next_protocol(SSL *ssl, const unsigned char **out,
unsigned *outlen, void *);
- static int select_next_protocol(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
- unsigned inlen, void *);
bool
getSSLClientRenegotiationAbort() const
diff --git a/iocore/net/QUICMultiCertConfigLoader.cc
b/iocore/net/QUICMultiCertConfigLoader.cc
index 521a020..17a80ca 100644
--- a/iocore/net/QUICMultiCertConfigLoader.cc
+++ b/iocore/net/QUICMultiCertConfigLoader.cc
@@ -120,18 +120,6 @@
QUICMultiCertConfigLoader::_set_handshake_callbacks(SSL_CTX *ssl_ctx)
}
int
-QUICMultiCertConfigLoader::ssl_select_next_protocol(SSL *ssl, const unsigned
char **out, unsigned char *outlen,
- const unsigned char *in,
unsigned inlen, void *)
-{
- QUICConnection *qc = static_cast<QUICConnection *>(SSL_get_ex_data(ssl,
QUIC::ssl_quic_qc_index));
-
- if (qc) {
- return qc->select_next_protocol(ssl, out, outlen, in, inlen);
- }
- return SSL_TLSEXT_ERR_NOACK;
-}
-
-int
QUICMultiCertConfigLoader::ssl_sni_cb(SSL *ssl, int * /*ad*/, void * /*arg*/)
{
// XXX: add SNIConfig support ?
diff --git a/iocore/net/QUICMultiCertConfigLoader.h
b/iocore/net/QUICMultiCertConfigLoader.h
index 17a15d2..1f97ee3 100644
--- a/iocore/net/QUICMultiCertConfigLoader.h
+++ b/iocore/net/QUICMultiCertConfigLoader.h
@@ -55,8 +55,6 @@ private:
virtual bool _set_info_callback(SSL_CTX *ctx) override;
virtual bool _set_npn_callback(SSL_CTX *ctx) override;
- static int ssl_select_next_protocol(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
- unsigned inlen, void *);
static int ssl_cert_cb(SSL *ssl, void *arg);
static int ssl_sni_cb(SSL *ssl, int *ad, void *arg);
};
diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc
index fbba684..140bfb7 100644
--- a/iocore/net/QUICNetVConnection.cc
+++ b/iocore/net/QUICNetVConnection.cc
@@ -1079,28 +1079,6 @@ QUICNetVConnection::protocol_contains(std::string_view
prefix) const
return retval;
}
-// ALPN TLS extension callback. Given the client's set of offered
-// protocols, we have to select a protocol to use for this session.
-int
-QUICNetVConnection::select_next_protocol(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
- unsigned inlen) const
-{
- const unsigned char *npnptr = nullptr;
- unsigned int npnsize = 0;
- if (this->getNPN(&npnptr, &npnsize)) {
- // SSL_select_next_proto chooses the first server-offered protocol that
appears in the clients protocol set, ie. the
- // server selects the protocol. This is a n^2 search, so it's preferable
to keep the protocol set short.
- if (SSL_select_next_proto(const_cast<unsigned char **>(out), outlen,
npnptr, npnsize, in, inlen) == OPENSSL_NPN_NEGOTIATED) {
- Debug("ssl", "selected ALPN protocol %.*s", (int)(*outlen), *out);
- return SSL_TLSEXT_ERR_OK;
- }
- }
-
- *out = nullptr;
- *outlen = 0;
- return SSL_TLSEXT_ERR_NOACK;
-}
-
bool
QUICNetVConnection::is_closed() const
{
diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
index b512e53..4de9cc1 100644
--- a/iocore/net/SSLNetVConnection.cc
+++ b/iocore/net/SSLNetVConnection.cc
@@ -215,6 +215,7 @@ SSLNetVConnection::_bindSSLObject()
{
SSLNetVCAttach(this->ssl, this);
TLSBasicSupport::bind(this->ssl, this);
+ ALPNSupport::bind(this->ssl, this);
TLSSessionResumptionSupport::bind(this->ssl, this);
TLSSNISupport::bind(this->ssl, this);
}
@@ -224,6 +225,7 @@ SSLNetVConnection::_unbindSSLObject()
{
SSLNetVCDetach(this->ssl);
TLSBasicSupport::unbind(this->ssl);
+ ALPNSupport::unbind(this->ssl);
TLSSessionResumptionSupport::unbind(this->ssl);
TLSSNISupport::unbind(this->ssl);
}
@@ -1562,48 +1564,6 @@ SSLNetVConnection::sslClientHandShakeEvent(int &err)
return EVENT_CONT;
}
-// NextProtocolNegotiation TLS extension callback. The NPN extension
-// allows the client to select a preferred protocol, so all we have
-// to do here is tell them what out protocol set is.
-int
-SSLNetVConnection::advertise_next_protocol(SSL *ssl, const unsigned char
**out, unsigned int *outlen, void * /*arg ATS_UNUSED */)
-{
- SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
-
- ink_release_assert(netvc && netvc->ssl == ssl);
-
- if (netvc->getNPN(out, outlen)) {
- // Successful return tells OpenSSL to advertise.
- return SSL_TLSEXT_ERR_OK;
- }
- return SSL_TLSEXT_ERR_NOACK;
-}
-
-// ALPN TLS extension callback. Given the client's set of offered
-// protocols, we have to select a protocol to use for this session.
-int
-SSLNetVConnection::select_next_protocol(SSL *ssl, const unsigned char **out,
unsigned char *outlen,
- const unsigned char *in ATS_UNUSED,
unsigned inlen ATS_UNUSED, void *)
-{
- SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
-
- ink_release_assert(netvc && netvc->ssl == ssl);
- const unsigned char *npnptr = nullptr;
- unsigned int npnsize = 0;
- if (netvc->getNPN(&npnptr, &npnsize)) {
- // SSL_select_next_proto chooses the first server-offered protocol that
appears in the clients protocol set, ie. the
- // server selects the protocol. This is a n^2 search, so it's preferable
to keep the protocol set short.
- if (SSL_select_next_proto(const_cast<unsigned char **>(out), outlen,
npnptr, npnsize, in, inlen) == OPENSSL_NPN_NEGOTIATED) {
- Debug("ssl", "selected ALPN protocol %.*s", (int)(*outlen), *out);
- return SSL_TLSEXT_ERR_OK;
- }
- }
-
- *out = nullptr;
- *outlen = 0;
- return SSL_TLSEXT_ERR_NOACK;
-}
-
void
SSLNetVConnection::reenable(NetHandler *nh, int event)
{
diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc
index 1239c69..1d57f0b 100644
--- a/iocore/net/SSLUtils.cc
+++ b/iocore/net/SSLUtils.cc
@@ -463,6 +463,36 @@ ssl_servername_callback(SSL *ssl, int *al, void *arg)
return SSL_TLSEXT_ERR_OK;
}
+// NextProtocolNegotiation TLS extension callback. The NPN extension
+// allows the client to select a preferred protocol, so all we have
+// to do here is tell them what out protocol set is.
+int
+ssl_next_protos_advertised_callback(SSL *ssl, const unsigned char **out,
unsigned *outlen, void *)
+{
+ ALPNSupport *alpns = ALPNSupport::getInstance(ssl);
+
+ ink_assert(alpns);
+ if (alpns) {
+ return alpns->advertise_next_protocol(ssl, out, outlen);
+ }
+
+ return SSL_TLSEXT_ERR_NOACK;
+}
+
+int
+ssl_alpn_select_callback(SSL *ssl, const unsigned char **out, unsigned char
*outlen, const unsigned char *in, unsigned inlen,
+ void *)
+{
+ ALPNSupport *alpns = ALPNSupport::getInstance(ssl);
+
+ ink_assert(alpns);
+ if (alpns) {
+ return alpns->select_next_protocol(ssl, out, outlen, in, inlen);
+ }
+
+ return SSL_TLSEXT_ERR_NOACK;
+}
+
#if TS_USE_GET_DH_2048_256 == 0
/* Build 2048-bit MODP Group with 256-bit Prime Order Subgroup from RFC 5114 */
static DH *
@@ -873,6 +903,7 @@ SSLInitializeLibrary()
ssl_vc_index = SSL_get_ex_new_index(0, (void *)"NetVC index", nullptr,
nullptr, nullptr);
TLSBasicSupport::initialize();
+ ALPNSupport::initialize();
TLSSessionResumptionSupport::initialize();
TLSSNISupport::initialize();
@@ -1434,14 +1465,14 @@ SSLMultiCertConfigLoader::_set_info_callback(SSL_CTX
*ctx)
bool
SSLMultiCertConfigLoader::_set_npn_callback(SSL_CTX *ctx)
{
- SSL_CTX_set_next_protos_advertised_cb(ctx,
SSLNetVConnection::advertise_next_protocol, nullptr);
+ SSL_CTX_set_next_protos_advertised_cb(ctx,
ssl_next_protos_advertised_callback, nullptr);
return true;
}
bool
SSLMultiCertConfigLoader::_set_alpn_callback(SSL_CTX *ctx)
{
- SSL_CTX_set_alpn_select_cb(ctx, SSLNetVConnection::select_next_protocol,
nullptr);
+ SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_callback, nullptr);
return true;
}
diff --git a/iocore/net/quic/QUICConnection.h b/iocore/net/quic/QUICConnection.h
index 02cbbb0..660e75e 100644
--- a/iocore/net/quic/QUICConnection.h
+++ b/iocore/net/quic/QUICConnection.h
@@ -55,8 +55,6 @@ public:
virtual uint32_t pmtu() const = 0;
virtual NetVConnectionContext_t direction() const = 0;
- virtual int select_next_protocol(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
- unsigned inlen) const = 0;
virtual bool is_closed() const = 0;
virtual bool is_at_anti_amplification_limit() const = 0;
virtual bool is_address_validation_completed() const = 0;