Skip to content

THRIFT-6174: Fix TSSLSocket build with OpenSSL 4.0 - #3752

Open
jaipaulcheernam wants to merge 1 commit into
apache:masterfrom
jaipaulcheernam:fix-openssl4
Open

THRIFT-6174: Fix TSSLSocket build with OpenSSL 4.0#3752
jaipaulcheernam wants to merge 1 commit into
apache:masterfrom
jaipaulcheernam:fix-openssl4

Conversation

@jaipaulcheernam

@jaipaulcheernam jaipaulcheernam commented Aug 27, 2026

Copy link
Copy Markdown

OpenSSL 4.0 removes SSLv3_method() and per-version TLS method functions (TLSv1_method, TLSv1_1_method, TLSv1_2_method), the deprecated ASN1_STRING_data() function, and returns const pointers from X509_get_subject_name(), X509_NAME_get_entry(), and X509_NAME_ENTRY_get_data().

  • Guard SSLv3_method and TLS version methods with version check
  • Replace ASN1_STRING_data with ASN1_STRING_get0_data
  • Add const qualifiers for X509_NAME, X509_NAME_ENTRY, ASN1_STRING

This is backward-compatible with OpenSSL >= 1.1.0 since all replacement APIs exist since that version.

  • Did you create an Apache Jira ticket? (Request account here, not required for trivial changes)
  • If a ticket exists: Does your pull request title follow the pattern "THRIFT-NNNN: describe my issue"?
  • Did you squash your changes to a single commit? (not required, but preferred)
  • Did you do your best to avoid breaking changes? If one was needed, did you label the Jira ticket with "Breaking-Change"?
  • If your change does not involve any code, include [skip ci] anywhere in the commit message to free up build resources.

@mergeable mergeable Bot added the c++ Pull requests that update C++ code label Aug 27, 2026
@mergeable mergeable Bot added the c_glib label Aug 27, 2026
@Jens-G

Jens-G commented Aug 27, 2026

Copy link
Copy Markdown
Member

This branch has conflicts that must be resolved

@Jens-G Jens-G added the rebase needed rebase needed label Aug 27, 2026
@loqs

loqs commented Aug 27, 2026

Copy link
Copy Markdown

Is it expected that SecurityTest and SecurityFromBufferTest both hang/timeout with OpenSSL 4.0.2 and the test expectations will be changed in a future pull request?

OPENSSL_NO_SSL3 is not defined for OpenSSSL 4 so #ifdef OPENSSL_NO_SSL3 passes and the tests try to use SSL3 and timeout. TLSv1.0/1.1 require SSL_CTX_set_min_proto_version when using TLS_method instead of the per version method. Without it being set the TLSv1.0 and TLSv1.1 tests timeout like the SSL 3 tests.

kraj pushed a commit to YoeDistro/meta-openembedded that referenced this pull request Aug 28, 2026
OpenSSL 4.0 removes SSLv3_method(), per-version TLS method functions,
ERR_remove_state(), ASN1_STRING_data(), and returns const pointers
from X509 accessor functions. Fix both C++ and C GLib bindings.

Upstream-Status: Submitted [apache/thrift#3752]
Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
@jaipaulcheernam

Copy link
Copy Markdown
Author

This branch has conflicts that must be resolved

Done. rebased and please check

@jaipaulcheernam

Copy link
Copy Markdown
Author

Is it expected that SecurityTest and SecurityFromBufferTest both hang/timeout with OpenSSL 4.0.2 and the test expectations will be changed in a future pull request?

OPENSSL_NO_SSL3 is not defined for OpenSSSL 4 so #ifdef OPENSSL_NO_SSL3 passes and the tests try to use SSL3 and timeout. TLSv1.0/1.1 require SSL_CTX_set_min_proto_version when using TLS_method instead of the per version method. Without it being set the TLSv1.0 and TLSv1.1 tests timeout like the SSL 3 tests.

Thanks for the feedback! Updated the PR:

  • Rebased onto latest master (conflicts resolved)
  • TLSv1.0/1.1/1.2 now use TLS_method() + SSL_CTX_set_min_proto_version() / SSL_CTX_set_max_proto_version() on OpenSSL 4.0, so tests should no longer hang
  • SSLv3 is guarded out on OpenSSL 4.0 (returns error since the protocol is truly removed)
  • ERR_remove_state() calls removed (no-op since OpenSSL 1.1)

I haven't been able to run the SecurityTest/SecurityFromBufferTest locally — if there are still test timeouts, happy to iterate.

@loqs

loqs commented Aug 28, 2026

Copy link
Copy Markdown

Thank you for working on this. There are still timeouts which I was able to fix with:

--- a/lib/cpp/test/SecurityFromBufferTest.cpp
+++ b/lib/cpp/test/SecurityFromBufferTest.cpp
@@ -229,7 +229,7 @@ BOOST_AUTO_TEST_CASE(ssl_security_matrix) {
           continue;
         }
 
-#ifdef OPENSSL_NO_SSL3
+#if defined(OPENSSL_NO_SSL3) || OPENSSL_VERSION_NUMBER >= 0x40000000L
         if (si == 2 || ci == 2) {
           // Skip all SSLv3 cases - protocol not supported
           continue;
diff --git a/lib/cpp/test/SecurityTest.cpp b/lib/cpp/test/SecurityTest.cpp
index 86640bd68..b133ef0f8 100644
--- a/lib/cpp/test/SecurityTest.cpp
+++ b/lib/cpp/test/SecurityTest.cpp
@@ -357,7 +357,7 @@ BOOST_AUTO_TEST_CASE(ssl_security_matrix)
                     continue;
                 }
 
-#ifdef OPENSSL_NO_SSL3
+#if defined(OPENSSL_NO_SSL3) || OPENSSL_VERSION_NUMBER >= 0x40000000L
                 if (si == 2 || ci == 2)
                 {
                     // Skip all SSLv3 cases - protocol not supported

All tests then pass for C and C++ however I believe that is due to lack of coverage in testtransportsslsocket.c compared to SecurityTest.cpp for SSLv3/TLSv1_0/TLSv1_1. I think the C code needs SSL_CTX_set_min_proto_version() / SSL_CTX_set_max_proto_version() to match the C++ code.

@Jens-G Jens-G removed the rebase needed rebase needed label Aug 30, 2026
@Jens-G Jens-G self-assigned this Aug 31, 2026
@Jens-G

Jens-G commented Sep 1, 2026

Copy link
Copy Markdown
Member

Where on earth have you found that ticket number? AI hallucinated?

image

:

@Jens-G Jens-G changed the title THRIFT-6170: Fix TSSLSocket build with OpenSSL 4.0 THRIFT-6174: Fix TSSLSocket build with OpenSSL 4.0 Sep 1, 2026
@jaipaulcheernam

Copy link
Copy Markdown
Author

Where on earth have you found that ticket number? AI hallucinated?
image

:

Thanks for fixing the title

OpenSSL 4.0 removes SSLv3_method(), per-version TLS method functions,
ERR_remove_state(), ASN1_STRING_data(), and returns const pointers
from X509 accessor functions.

C++ (TSSLSocket.cpp):
- Remove ERR_remove_state() calls (no-op since OpenSSL 1.1)
- Guard SSLv3_method with version check
- Use TLS_method() + SSL_CTX_set_min/max_proto_version() for
  TLSv1.0/1.1/1.2 on OpenSSL 4.0 (per-version methods removed)
- Replace ASN1_STRING_data with ASN1_STRING_get0_data
- Add const qualifiers for X509_NAME, X509_NAME_ENTRY, ASN1_STRING

C (thrift_ssl_socket.c):
- Remove ERR_remove_state() calls
- Guard SSLv3 and TLS version methods with version check

Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
@loqs

loqs commented Sep 7, 2026

Copy link
Copy Markdown

This additional patch adds SSL_CTX_set_min_proto_version and SSL_CTX_set_max_proto_version use to the C bindings matching the C++ bindings and adds unit tests for the C bings for SSL3, TLSv1, TLSv1.1, TLSv1.2 it does not check the result of SSL_CTX_set_min_proto_version or SSL_CTX_set_max_proto_version as @FinnRG's patch does to match the current PR.

diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c
index b734ec914..4987018b2 100644
--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c
@@ -833,12 +833,25 @@ thrift_ssl_socket_context_initialize(ThriftSSLSocketProtocol ssl_protocol, GErro
     case SSLTLS:
       context = SSL_CTX_new(SSLv23_method());
       break;
-#if OPENSSL_VERSION_NUMBER < 0x40000000L
-#ifndef OPENSSL_NO_SSL3
+#if !defined(OPENSSL_NO_SSL3) && OPENSSL_VERSION_NUMBER < 0x40000000L
     case SSLv3:
       context = SSL_CTX_new(SSLv3_method());
       break;
 #endif
+#if OPENSSL_VERSION_NUMBER >= 0x40000000L
+    case TLSv1_0:
+    case TLSv1_1:
+    case TLSv1_2:
+      context = SSL_CTX_new(TLS_method());
+      if (context != NULL) {
+        int ver = (ssl_protocol == TLSv1_0) ? TLS1_VERSION
+                : (ssl_protocol == TLSv1_1) ? TLS1_1_VERSION
+                : TLS1_2_VERSION;
+        SSL_CTX_set_min_proto_version(context, ver);
+        SSL_CTX_set_max_proto_version(context, ver);
+      }
+      break;
+#else
     case TLSv1_0:
       context = SSL_CTX_new(TLSv1_method());
       break;
@@ -848,7 +861,7 @@ thrift_ssl_socket_context_initialize(ThriftSSLSocketProtocol ssl_protocol, GErro
     case TLSv1_2:
       context = SSL_CTX_new(TLSv1_2_method());
       break;
-#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
+#endif
     default:
       g_set_error (error, THRIFT_TRANSPORT_ERROR,
 		   THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE,
diff --git a/lib/c_glib/test/CMakeLists.txt b/lib/c_glib/test/CMakeLists.txt
index 4f60473b2..205390389 100644
--- a/lib/c_glib/test/CMakeLists.txt
+++ b/lib/c_glib/test/CMakeLists.txt
@@ -68,6 +68,12 @@ add_executable(testtransportsocket testtransportsocket.c)
 target_link_libraries(testtransportsocket thrift_c_glib)
 add_test(NAME testtransportsocket COMMAND testtransportsocket)
 
+if(OPENSSL_FOUND AND WITH_OPENSSL)
+  add_executable(testtransportsslsocket testtransportsslsocket.c)
+  target_link_libraries(testtransportsslsocket thrift_c_glib)
+  add_test(NAME testtransportsslsocket COMMAND testtransportsslsocket)
+endif()
+
 add_executable(testbinaryprotocol testbinaryprotocol.c)
 target_link_libraries(testbinaryprotocol thrift_c_glib)
 add_test(NAME testbinaryprotocol COMMAND testbinaryprotocol)
diff --git a/lib/c_glib/test/testtransportsslsocket.c b/lib/c_glib/test/testtransportsslsocket.c
index ba9ffdcae..ec0b86e2a 100644
--- a/lib/c_glib/test/testtransportsslsocket.c
+++ b/lib/c_glib/test/testtransportsslsocket.c
@@ -514,6 +514,65 @@ thrift_socket_server (const int port)
   g_object_unref (client);
 }
 
+static void
+test_ssl_context_for_ssl_tls(void)
+{
+  GError *error = NULL;
+  SSL_CTX *ctx = thrift_ssl_socket_context_initialize(SSLTLS, &error);
+  g_assert (ctx != NULL);
+  g_assert_no_error (error);
+  SSL_CTX_free(ctx);
+}
+
+static void
+test_ssl_context_for_sslv3(void)
+{
+  GError *error = NULL;
+  SSL_CTX *ctx = thrift_ssl_socket_context_initialize(SSLv3, &error);
+#if defined(OPENSSL_NO_SSL3) || OPENSSL_VERSION_NUMBER >= 0x40000000L
+  if (ctx == NULL) {
+    g_assert (error != NULL);
+    g_clear_error (&error);
+  } else {
+    SSL_CTX_free(ctx);
+  }
+#else
+  g_assert (ctx != NULL);
+  g_assert_no_error (error);
+  SSL_CTX_free(ctx);
+#endif
+}
+
+static void
+test_ssl_context_for_tlsv1_0(void)
+{
+  GError *error = NULL;
+  SSL_CTX *ctx = thrift_ssl_socket_context_initialize(TLSv1_0, &error);
+  g_assert (ctx != NULL);
+  g_assert_no_error (error);
+  SSL_CTX_free(ctx);
+}
+
+static void
+test_ssl_context_for_tlsv1_1(void)
+{
+  GError *error = NULL;
+  SSL_CTX *ctx = thrift_ssl_socket_context_initialize(TLSv1_1, &error);
+  g_assert (ctx != NULL);
+  g_assert_no_error (error);
+  SSL_CTX_free(ctx);
+}
+
+static void
+test_ssl_context_for_tlsv1_2(void)
+{
+  GError *error = NULL;
+  SSL_CTX *ctx = thrift_ssl_socket_context_initialize(TLSv1_2, &error);
+  g_assert (ctx != NULL);
+  g_assert_no_error (error);
+  SSL_CTX_free(ctx);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -530,6 +591,11 @@ main(int argc, char *argv[])
   g_test_add_func ("/testtransportsslsocket/CreateAndSetProperties", test_ssl_create_and_set_properties);
   g_test_add_func ("/testtransportsslsocket/OpenAndCloseNonSSLServer", test_ssl_open_and_close_non_ssl_server);
   g_test_add_func ("/testtransportsslsocket/OpenAndWriteInvalidSocket", test_ssl_write_invalid_socket);
+  g_test_add_func ("/testtransportsslsocket/ContextForSSLTLS", test_ssl_context_for_ssl_tls);
+  g_test_add_func ("/testtransportsslsocket/ContextForSSLv3", test_ssl_context_for_sslv3);
+  g_test_add_func ("/testtransportsslsocket/ContextForTLSv1_0", test_ssl_context_for_tlsv1_0);
+  g_test_add_func ("/testtransportsslsocket/ContextForTLSv1_1", test_ssl_context_for_tlsv1_1);
+  g_test_add_func ("/testtransportsslsocket/ContextForTLSv1_2", test_ssl_context_for_tlsv1_2);
 
 
 
diff --git a/lib/cpp/test/SecurityFromBufferTest.cpp b/lib/cpp/test/SecurityFromBufferTest.cpp
index 08f76b3f2..3df15106e 100644
--- a/lib/cpp/test/SecurityFromBufferTest.cpp
+++ b/lib/cpp/test/SecurityFromBufferTest.cpp
@@ -229,7 +229,7 @@ BOOST_AUTO_TEST_CASE(ssl_security_matrix) {
           continue;
         }
 
-#ifdef OPENSSL_NO_SSL3
+#if defined(OPENSSL_NO_SSL3) || OPENSSL_VERSION_NUMBER >= 0x40000000L
         if (si == 2 || ci == 2) {
           // Skip all SSLv3 cases - protocol not supported
           continue;
diff --git a/lib/cpp/test/SecurityTest.cpp b/lib/cpp/test/SecurityTest.cpp
index 86640bd68..b133ef0f8 100644
--- a/lib/cpp/test/SecurityTest.cpp
+++ b/lib/cpp/test/SecurityTest.cpp
@@ -357,7 +357,7 @@ BOOST_AUTO_TEST_CASE(ssl_security_matrix)
                     continue;
                 }
 
-#ifdef OPENSSL_NO_SSL3
+#if defined(OPENSSL_NO_SSL3) || OPENSSL_VERSION_NUMBER >= 0x40000000L
                 if (si == 2 || ci == 2)
                 {
                     // Skip all SSLv3 cases - protocol not supported

if (ctx_) {
int ver = (protocol == TLSv1_0) ? TLS1_VERSION : (protocol == TLSv1_1) ? TLS1_1_VERSION : TLS1_2_VERSION;
SSL_CTX_set_min_proto_version(ctx_, ver);
SSL_CTX_set_max_proto_version(ctx_, ver);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result is not checked. On failure the context should be released and ctx_ set to null then either a new error thrown or it could then be managed by the existing check for ctx_ being a nullptr.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c_glib c++ Pull requests that update C++ code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants