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

cmcfarlen pushed a commit to branch 10.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit 0e540a7b73886c9d527fa77b0a81f9b60925bea6
Author: Walt Karas <[email protected]>
AuthorDate: Tue Jul 16 14:32:37 2024 -0400

    Fix for OpenSSL 3.2+. (#11501)
    
    It seems BIO user data is no longer set to nullptr.
    
    (cherry picked from commit 6bf342ba362a42786b9efcb0d4d554f725643a8d)
---
 CMakeLists.txt                       |   3 +
 include/tscore/ink_config.h.cmake.in |   3 +
 src/iocore/net/BIO_fastopen.cc       | 133 +++++++++++++++++++++++++++++++----
 src/iocore/net/BIO_fastopen.h        |   7 +-
 src/iocore/net/SSLNetVConnection.cc  |   5 +-
 5 files changed, 128 insertions(+), 23 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5b0a9ba594..0069e1b68f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -450,6 +450,9 @@ check_symbol_exists(BIO_meth_new "openssl/bio.h" 
HAVE_BIO_METH_NEW)
 check_symbol_exists(BIO_set_data "openssl/bio.h" HAVE_BIO_SET_DATA)
 check_symbol_exists(BIO_get_data "openssl/bio.h" HAVE_BIO_GET_DATA)
 check_symbol_exists(BIO_get_shutdown "openssl/bio.h" HAVE_BIO_GET_SHUTDOWN)
+check_symbol_exists(BIO_get_ex_new_index "openssl/bio.h" 
HAVE_BIO_GET_EX_NEW_INDEX)
+check_symbol_exists(BIO_get_ex_data "openssl/bio.h" HAVE_BIO_GET_EX_DATA)
+check_symbol_exists(BIO_set_ex_data "openssl/bio.h" HAVE_BIO_SET_EX_DATA)
 check_symbol_exists(BIO_meth_get_ctrl "openssl/bio.h" HAVE_BIO_METH_GET_CTRL)
 check_symbol_exists(BIO_meth_get_create "openssl/bio.h" 
HAVE_BIO_METH_GET_CREATE)
 check_symbol_exists(BIO_meth_get_destroy "openssl/bio.h" 
HAVE_BIO_METH_GET_DESTROY)
diff --git a/include/tscore/ink_config.h.cmake.in 
b/include/tscore/ink_config.h.cmake.in
index b8f036457f..50e14e4019 100644
--- a/include/tscore/ink_config.h.cmake.in
+++ b/include/tscore/ink_config.h.cmake.in
@@ -80,6 +80,9 @@
 #cmakedefine HAVE_BIO_SET_DATA 1
 #cmakedefine HAVE_BIO_GET_DATA 1
 #cmakedefine HAVE_BIO_GET_SHUTDOWN 1
+#cmakedefine HAVE_BIO_GET_EX_NEW_INDEX 1
+#cmakedefine HAVE_BIO_GET_EX_DATA 1
+#cmakedefine HAVE_BIO_SET_EX_DATA 1
 #cmakedefine HAVE_BIO_METH_GET_CTRL 1
 #cmakedefine HAVE_BIO_METH_GET_CREATE 1
 #cmakedefine HAVE_BIO_METH_GET_DESTROY 1
diff --git a/src/iocore/net/BIO_fastopen.cc b/src/iocore/net/BIO_fastopen.cc
index ac2a9e38b7..fd9ea9dd9c 100644
--- a/src/iocore/net/BIO_fastopen.cc
+++ b/src/iocore/net/BIO_fastopen.cc
@@ -21,12 +21,116 @@
  *  limitations under the License.
  */
 
+#include <openssl/opensslv.h>
+
 #include "P_Net.h"
 #include "iocore/eventsystem/SocketManager.h"
 #include "tscore/ink_assert.h"
+#include "tscore/ink_config.h"
 
 #include "BIO_fastopen.h"
 
+#if defined(BORINGLIKE)
+#error
+#elif defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+#define BORINGLIKE 1
+#else
+#define BORINGLIKE 0
+#endif
+
+namespace
+{
+
+#if defined(HAVE_BIO_GET_EX_NEW_INDEX) && defined(HAVE_BIO_GET_EX_DATA) && 
defined(HAVE_BIO_SET_EX_DATA)
+
+class ExData
+{
+public:
+  // Pseudo-namespace
+  ExData() = delete;
+
+  static int
+  idx()
+  {
+    static int idx_ = []() -> int {
+      int i = BIO_get_ex_new_index(0, nullptr, _new, _dup, _free);
+      ink_release_assert(i >= 0);
+      return i;
+    }();
+    return idx_;
+  }
+
+private:
+#if BORINGLIKE
+  static constexpr CRYPTO_EX_unused *_new{nullptr};
+#else
+  static void
+  _new(void * /* parent */, void * /* ptr */, CRYPTO_EX_DATA *ad, int idx_, 
long /* argl */, void * /* argp */)
+  {
+    ink_release_assert(CRYPTO_set_ex_data(ad, idx_, nullptr) == 1);
+  }
+#endif
+
+#if BORINGLIKE
+  static void
+  _free(void * /* parent */, void * /* ptr */, CRYPTO_EX_DATA * /* ad */, int 
/* idx_ */, long /* argl */, void * /* argp */)
+  {
+  }
+#else
+  static void
+  _free(void * /* parent */, void * /* ptr */, CRYPTO_EX_DATA *ad, int idx_, 
long /* argl */, void * /* argp */)
+  {
+    ink_release_assert(CRYPTO_set_ex_data(ad, idx_, nullptr) == 1);
+  }
+#endif
+
+#if BORINGLIKE || (OPENSSL_VERSION_MAJOR >= 3)
+  using _Type_from_d = void **;
+#else
+  using _Type_from_d = void *;
+#endif
+
+  static int
+  _dup(CRYPTO_EX_DATA * /* to */, const CRYPTO_EX_DATA * /* from */, 
_Type_from_d /* from_d */, int /* idx */, long /* argl */,
+       void * /* argp */)
+  {
+    ink_assert(false);
+    return 0;
+  }
+};
+
+inline void
+set_dest_addr_for_bio(BIO *b, void *dest_addr)
+{
+  ink_assert(BIO_set_ex_data(b, ExData::idx(), dest_addr) == 1);
+}
+
+inline void *
+get_dest_addr_for_bio(BIO *b)
+{
+  return BIO_get_ex_data(b, ExData::idx());
+}
+
+#else // no BIO ex data in SSL library
+
+// Fall back on the krufty way this was done using older SSL libraries.
+
+inline void
+set_dest_addr_for_bio(BIO *b, void *dest_addr)
+{
+  BIO_set_data(b, dest_addr);
+}
+
+inline void *
+get_dest_addr_for_bio(BIO *b)
+{
+  return BIO_get_data(b);
+}
+
+#endif
+
+} // end anonymous namespace
+
 // For BoringSSL, which for some reason doesn't have this function.
 // (In BoringSSL, sock_read() and sock_write() use the internal
 // bio_fd_non_fatal_error() instead.) #1437
@@ -113,20 +217,20 @@ fastopen_bwrite(BIO *bio, const char *in, int insz)
   int fd = BIO_get_fd(bio, nullptr);
   ink_assert(fd != NO_FD);
 
-  if (BIO_get_data(bio)) {
+  void *dst_void = get_dest_addr_for_bio(bio);
+  if (dst_void) {
+    auto dst = static_cast<sockaddr *>(dst_void);
     // On the first write only, make a TFO request if TFO is enabled.
     // The best documentation on the behavior of the Linux API is in
     // RFC 7413. If we get EINPROGRESS it means that the SYN has been
     // sent without data and we should retry.
-    const sockaddr *dst = reinterpret_cast<const sockaddr 
*>(BIO_get_data(bio));
-
     Metrics::Counter::increment(net_rsb.fastopen_attempts);
     err = SocketManager::sendto(fd, (void *)in, insz, MSG_FASTOPEN, dst, 
ats_ip_size(dst));
     if (err >= 0) {
       Metrics::Counter::increment(net_rsb.fastopen_successes);
     }
 
-    BIO_set_data(bio, nullptr);
+    set_dest_addr_for_bio(bio, nullptr);
   } else {
     err = SocketManager::write(fd, (void *)in, insz);
   }
@@ -164,21 +268,14 @@ fastopen_bread(BIO *bio, char *out, int outsz)
   return err < 0 ? -1 : err;
 }
 
+#ifndef HAVE_BIO_METH_NEW
+
 static long
 fastopen_ctrl(BIO *bio, int cmd, long larg, void *ptr)
 {
-  switch (cmd) {
-  case BIO_C_SET_CONNECT:
-    // We only support BIO_set_conn_address(), which sets a sockaddr.
-    ink_assert(larg == 2);
-    BIO_set_data(bio, ptr);
-    return 0;
-  }
-
   return BIO_meth_get_ctrl(const_cast<BIO_METHOD *>(BIO_s_socket()))(bio, cmd, 
larg, ptr);
 }
 
-#ifndef HAVE_BIO_METH_NEW
 static const BIO_METHOD fastopen_methods[] = {
   {
    .type          = BIO_TYPE_SOCKET,
@@ -193,12 +290,12 @@ static const BIO_METHOD fastopen_methods[] = {
    .callback_ctrl = nullptr,
    }
 };
-#else
+#else // defined(HAVE_BIO_METH_NEW)
 static const BIO_METHOD *fastopen_methods = [] {
   BIO_METHOD *methods = BIO_meth_new(BIO_TYPE_SOCKET, "fastopen");
   BIO_meth_set_write(methods, fastopen_bwrite);
   BIO_meth_set_read(methods, fastopen_bread);
-  BIO_meth_set_ctrl(methods, fastopen_ctrl);
+  BIO_meth_set_ctrl(methods, BIO_meth_get_ctrl(const_cast<BIO_METHOD 
*>(BIO_s_socket())));
   BIO_meth_set_create(methods, fastopen_create);
   BIO_meth_set_destroy(methods, fastopen_destroy);
   return methods;
@@ -210,3 +307,9 @@ BIO_s_fastopen()
 {
   return fastopen_methods;
 }
+
+void
+BIO_fastopen_set_dest_addr(BIO *bio, const sockaddr *dest_addr)
+{
+  set_dest_addr_for_bio(bio, const_cast<sockaddr *>(dest_addr));
+}
diff --git a/src/iocore/net/BIO_fastopen.h b/src/iocore/net/BIO_fastopen.h
index ce42e3be42..b949953daa 100644
--- a/src/iocore/net/BIO_fastopen.h
+++ b/src/iocore/net/BIO_fastopen.h
@@ -29,8 +29,5 @@
 // Return a BIO_METHOD for a socket BIO that implements TCP Fast Open.
 const BIO_METHOD *BIO_s_fastopen();
 
-// OpenSSL 1.0.2h has BIO_set_conn_ip(), but master has 
BIO_set_conn_address(). Use
-// the API from master since it makes more sense.
-#if !defined(BIO_set_conn_address)
-#define BIO_set_conn_address(b, addr) BIO_ctrl(b, BIO_C_SET_CONNECT, 2, (char 
*)addr)
-#endif
+// Set destination address for a BIO for a fastopen TCP socket where the local 
host is the client.
+void BIO_fastopen_set_dest_addr(BIO *bio, const sockaddr *dest_addr);
diff --git a/src/iocore/net/SSLNetVConnection.cc 
b/src/iocore/net/SSLNetVConnection.cc
index ca89894be0..5ebb705f0e 100644
--- a/src/iocore/net/SSLNetVConnection.cc
+++ b/src/iocore/net/SSLNetVConnection.cc
@@ -212,9 +212,8 @@ SSLNetVConnection::_make_ssl_connection(SSL_CTX *ctx)
       BIO *bio = BIO_new(const_cast<BIO_METHOD *>(BIO_s_fastopen()));
       BIO_set_fd(bio, this->get_socket(), BIO_NOCLOSE);
 
-      if (this->options.f_tcp_fastopen) {
-        BIO_set_conn_address(bio, this->get_remote_addr());
-      }
+      BIO_fastopen_set_dest_addr(bio,
+                                 this->options.f_tcp_fastopen ? 
this->get_remote_addr() : static_cast<const sockaddr *>(nullptr));
 
       SSL_set_bio(ssl, bio, bio);
     } else {

Reply via email to