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;

Reply via email to