Skip to content

Commit

Permalink
92x #11501 patch (#11882)
Browse files Browse the repository at this point in the history
* Fix for OpenSSL 3.2+. (#11501)

It seems BIO user data is no longer set to nullptr.

(cherry picked from commit 6bf342b)

----- Still needs configure modifications for non-Cmake build

* Fix socket def

* Chris' make fixes

---------

Co-authored-by: Walt Karas <[email protected]>
  • Loading branch information
ezelkow1 and ywkaras authored Nov 21, 2024
1 parent a0d49dd commit c683ee4
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 23 deletions.
29 changes: 29 additions & 0 deletions build/crypto.m4
Original file line number Diff line number Diff line change
Expand Up @@ -450,3 +450,32 @@ AC_DEFUN([TS_CHECK_VERIFY_CERT_STORE], [
AC_SUBST(has_verify_cert_store)
])

AC_DEFUN([TS_CHECK_BIO_GET_EX_NEW_INDEX], [
_saved_LIBS=$LIBS
TS_ADDTO(LIBS, [$OPENSSL_LIBS])
bio_get_ex_new_index_check=no
has_verify_cert_store=0
AC_MSG_CHECKING([for BIO_get_ex_new_index macro])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <openssl/ssl.h>]],
[[
#ifndef BIO_get_ex_new_index
#error
#endif
]])
],
[
bio_get_ex_new_index_check=yes
have_bio_get_ex_new_index=1
],
[]
)
AC_MSG_RESULT([$bio_get_ex_new_index_check])
LIBS=$_saved_LIBS
AC_SUBST(have_bio_get_ex_new_index)
])
4 changes: 4 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1354,8 +1354,12 @@ AC_CHECK_FUNCS([ \
SHA256_Init \
MD5_Init \
SSL_SESSION_dup \
BIO_get_ex_data \
BIO_set_ex_data \
])

TS_CHECK_BIO_GET_EX_NEW_INDEX

AC_CHECK_FUNC([ASN1_STRING_get0_data], [],
[AC_DEFINE([ASN1_STRING_get0_data], [ASN1_STRING_data], [Added in OpenSSL 1.1])])

Expand Down
2 changes: 2 additions & 0 deletions include/tscore/ink_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@
#define TS_HAS_TLS_EARLY_DATA @has_tls_early_data@
#define TS_HAS_TLS_SESSION_TICKET @has_tls_session_ticket@
#define TS_HAS_VERIFY_CERT_STORE @has_verify_cert_store@
#define TS_HAS_VERIFY_CERT_STORE @has_verify_cert_store@
#define HAVE_BIO_GET_EX_NEW_INDEX @have_bio_get_ex_new_index@

#define TS_USE_HRW_GEOIP @use_hrw_geoip@
#define TS_USE_HRW_MAXMINDDB @use_hrw_maxminddb@
Expand Down
133 changes: 118 additions & 15 deletions iocore/net/BIO_fastopen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,115 @@
* limitations under the License.
*/

#include <openssl/opensslv.h>

#include "P_Net.h"
#include "I_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
Expand Down Expand Up @@ -113,13 +216,14 @@ 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));
ProxyMutex *mutex = this_ethread()->mutex.get();
ProxyMutex *mutex = this_ethread()->mutex.get();

NET_INCREMENT_DYN_STAT(net_fastopen_attempts_stat);

Expand All @@ -128,7 +232,7 @@ fastopen_bwrite(BIO *bio, const char *in, int insz)
NET_INCREMENT_DYN_STAT(net_fastopen_successes_stat);
}

BIO_set_data(bio, nullptr);
set_dest_addr_for_bio(bio, nullptr);
} else {
err = socketManager.write(fd, (void *)in, insz);
}
Expand Down Expand Up @@ -166,21 +270,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,
.name = "fastopen",
Expand All @@ -193,12 +290,12 @@ static const BIO_METHOD fastopen_methods[] = {{
.destroy = fastopen_destroy,
.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;
Expand All @@ -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));
}
7 changes: 2 additions & 5 deletions iocore/net/BIO_fastopen.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,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);
5 changes: 2 additions & 3 deletions iocore/net/SSLNetVConnection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,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 {
Expand Down

0 comments on commit c683ee4

Please sign in to comment.