gnutls: fix building with older supported GnuTLS versions

Also:
- GHA/linux-old: switch jobs from OpenSSL 1.0.2 to GnuTLS 3.5.8.

Ref: https://gitlab.com/gnutls/gnutls/blob/master/NEWS
Follow-up to fa0ccd9f1f #15774
Follow-up to 68bd759c2b #15667
Cherry-picked from #18330
Closes #18335
This commit is contained in:
Viktor Szakats 2025-08-21 12:09:17 +02:00
parent 12a10ca77c
commit 7956a2a756
No known key found for this signature in database
GPG key ID: B5ABD165E2AEF201
3 changed files with 45 additions and 9 deletions

View file

@ -70,7 +70,7 @@ jobs:
dpkg -i freexian-archive-keyring_2022.06.08_all.deb
echo 'deb http://deb.freexian.com/extended-lts stretch-lts main contrib non-free' | tee /etc/apt/sources.list.d/extended-lts.list
apt-get -o Dpkg::Use-Pty=0 update
apt-get -o Dpkg::Use-Pty=0 install -y --no-install-suggests --no-install-recommends cmake make automake autoconf libtool gcc pkg-config libpsl-dev libzstd-dev zlib1g-dev libssl1.0-dev libssh-dev libssh2-1-dev libc-ares-dev heimdal-dev libldap2-dev librtmp-dev stunnel4 groff
apt-get -o Dpkg::Use-Pty=0 install -y --no-install-suggests --no-install-recommends cmake make automake autoconf libtool gcc pkg-config libpsl-dev libzstd-dev zlib1g-dev libgnutls28-dev libssh-dev libssh2-1-dev libc-ares-dev heimdal-dev libldap2-dev librtmp-dev stunnel4 groff
# GitHub's actions/checkout needs newer glibc and libstdc++. The latter also depends on
# gcc-8-base, but it doesn't actually seem used in our situation and isn't available in
# the main repo, so force the install.
@ -87,7 +87,7 @@ jobs:
mkdir bld-1
cd bld-1
cmake .. -DCMAKE_UNITY_BUILD=ON -DCURL_WERROR=ON -DBUILD_SHARED_LIBS=ON \
-DENABLE_ARES=OFF -DCURL_ZSTD=OFF -DCURL_USE_GSSAPI=OFF -DCURL_USE_LIBSSH2=ON -DCURL_USE_LIBSSH=OFF -DUSE_LIBRTMP=ON
-DCURL_USE_GNUTLS=ON -DENABLE_ARES=OFF -DCURL_ZSTD=OFF -DCURL_USE_GSSAPI=OFF -DCURL_USE_LIBSSH2=ON -DCURL_USE_LIBSSH=OFF -DUSE_LIBRTMP=ON
make install
src/curl --disable --version
@ -103,7 +103,7 @@ jobs:
mkdir bld-cares
cd bld-cares
cmake .. -DCMAKE_UNITY_BUILD=ON -DCURL_WERROR=ON -DBUILD_SHARED_LIBS=ON \
-DENABLE_ARES=ON -DCURL_USE_GSSAPI=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=OFF -DUSE_LIBRTMP=ON \
-DCURL_USE_GNUTLS=ON -DENABLE_ARES=ON -DCURL_USE_GSSAPI=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=OFF -DUSE_LIBRTMP=ON \
-DCURL_LIBCURL_VERSIONED_SYMBOLS=ON
- name: 'cmake curl_config.h'
@ -136,7 +136,7 @@ jobs:
mkdir bld-am
cd bld-am
../configure --disable-dependency-tracking --enable-unity --enable-warnings --enable-werror \
--with-openssl --enable-ares --with-libssh2 --with-zstd --with-gssapi --with-librtmp \
--with-gnutls --enable-ares --with-libssh2 --with-zstd --with-gssapi --with-librtmp \
--prefix="$PWD"/../curl-install-am
- name: 'autotools curl_config.h'

View file

@ -77,7 +77,12 @@ static bool gtls_inited = FALSE;
#error "too old GnuTLS version"
#endif
# include <gnutls/ocsp.h>
#undef CURL_GNUTLS_EARLY_DATA
#if GNUTLS_VERSION_NUMBER >= 0x03060d
#define CURL_GNUTLS_EARLY_DATA
#endif
#include <gnutls/ocsp.h>
struct gtls_ssl_backend_data {
struct gtls_ctx gtls;
@ -655,6 +660,7 @@ CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
return CURLE_OK;
}
#ifdef CURL_GNUTLS_EARLY_DATA
CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf,
struct Curl_easy *data,
const char *ssl_peer_key,
@ -715,6 +721,7 @@ CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf,
}
return result;
}
#endif
int Curl_glts_get_ietf_proto(gnutls_session_t session)
{
@ -727,13 +734,16 @@ int Curl_glts_get_ietf_proto(gnutls_session_t session)
return CURL_IETF_PROTO_TLS1_1;
case GNUTLS_TLS1_2:
return CURL_IETF_PROTO_TLS1_2;
#if GNUTLS_VERSION_NUMBER >= 0x030603
case GNUTLS_TLS1_3:
return CURL_IETF_PROTO_TLS1_3;
#endif
default:
return CURL_IETF_PROTO_UNKNOWN;
}
}
#ifdef CURL_GNUTLS_EARLY_DATA
static CURLcode cf_gtls_update_session_id(struct Curl_cfilter *cf,
struct Curl_easy *data,
gnutls_session_t session)
@ -769,6 +779,7 @@ static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
}
return 0;
}
#endif
static CURLcode gtls_set_priority(struct Curl_cfilter *cf,
struct Curl_easy *data,
@ -883,6 +894,7 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
/* Initialize TLS session as a client */
init_flags = GNUTLS_CLIENT;
#ifdef CURL_GNUTLS_EARLY_DATA
if(peer->transport == TRNSPRT_QUIC && earlydata_max > 0)
init_flags |= GNUTLS_ENABLE_EARLY_DATA | GNUTLS_NO_END_OF_EARLY_DATA;
else if(earlydata_max > 0 && earlydata_max != 0xFFFFFFFFUL)
@ -891,13 +903,14 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
* and one announcing 0xFFFFFFFFUL. On TCP+TLS, this is unlikely, but
* on QUIC this is common. */
init_flags |= GNUTLS_ENABLE_EARLY_DATA;
#endif
#ifdef GNUTLS_FORCE_CLIENT_CERT
init_flags |= GNUTLS_FORCE_CLIENT_CERT;
#endif
#ifdef GNUTLS_NO_TICKETS_TLS12
init_flags |= GNUTLS_NO_TICKETS_TLS12;
init_flags |= GNUTLS_NO_TICKETS_TLS12;
#endif
#ifdef GNUTLS_NO_STATUS_REQUEST
@ -1032,6 +1045,7 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
return CURLE_OK;
}
#ifdef CURL_GNUTLS_EARLY_DATA
static int keylog_callback(gnutls_session_t session, const char *label,
const gnutls_datum_t *secret)
{
@ -1080,6 +1094,7 @@ static CURLcode gtls_on_session_reuse(struct Curl_cfilter *cf,
}
return result;
}
#endif
CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
struct Curl_cfilter *cf,
@ -1158,11 +1173,13 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
goto out;
}
#ifdef CURL_GNUTLS_EARLY_DATA
/* Open the file if a TLS or QUIC backend has not done this before. */
Curl_tls_keylog_open();
if(Curl_tls_keylog_enabled()) {
gnutls_session_set_keylog_function(gctx->session, keylog_callback);
}
#endif
/* convert the ALPN string from our arguments to a list of strings that
* gnutls wants and will convert internally back to this string for sending
@ -1207,7 +1224,13 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
connssl->alpn, NULL, NULL, cf,
gtls_on_session_reuse);
#ifdef CURL_GNUTLS_EARLY_DATA
gtls_on_session_reuse
#else
NULL
#endif
);
if(result)
return result;
@ -1218,9 +1241,11 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
#ifdef CURL_GNUTLS_EARLY_DATA
gnutls_handshake_set_hook_function(backend->gtls.session,
GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST,
gtls_handshake_cb);
#endif
/* register callback functions and handle to send and receive data. */
gnutls_transport_set_ptr(backend->gtls.session, cf);
@ -1793,15 +1818,18 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
if(result)
goto out;
#ifdef CURL_GNUTLS_EARLY_DATA
/* Only on TLSv1.2 or lower do we have the session id now. For
* TLSv1.3 we get it via a SESSION_TICKET message that arrives later. */
if(gnutls_protocol_get_version(session) < GNUTLS_TLS1_3)
result = cf_gtls_update_session_id(cf, data, session);
#endif
out:
return result;
}
#ifdef CURL_GNUTLS_EARLY_DATA
static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
@ -1840,6 +1868,7 @@ static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf,
out:
return result;
}
#endif
/*
* This function is called after the TCP connect has completed. Setup the TLS
@ -1876,6 +1905,7 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
}
if(connssl->connecting_state == ssl_connect_2) {
#ifdef CURL_GNUTLS_EARLY_DATA
if(connssl->earlydata_state == ssl_earlydata_await) {
goto out;
}
@ -1887,7 +1917,7 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
}
DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) ||
(connssl->earlydata_state == ssl_earlydata_sent));
#endif
result = handshake(cf, data);
if(result)
goto out;
@ -1918,6 +1948,7 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
if(result)
goto out;
#ifdef CURL_GNUTLS_EARLY_DATA
if(connssl->earlydata_state > ssl_earlydata_none) {
/* We should be in this state by now */
DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sent);
@ -1926,6 +1957,7 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
GNUTLS_SFLAGS_EARLY_DATA) ?
ssl_earlydata_accepted : ssl_earlydata_rejected;
}
#endif
connssl->connecting_state = ssl_connect_done;
}
@ -1947,6 +1979,7 @@ static CURLcode gtls_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
{
#ifdef CURL_GNUTLS_EARLY_DATA
struct ssl_connect_data *connssl = cf->ctx;
if((connssl->state == ssl_connection_deferred) &&
(connssl->earlydata_state == ssl_earlydata_await)) {
@ -1954,6 +1987,7 @@ static CURLcode gtls_connect(struct Curl_cfilter *cf,
*done = TRUE;
return CURLE_OK;
}
#endif
return gtls_connect_common(cf, data, done);
}

View file

@ -464,7 +464,9 @@ class Env:
@staticmethod
def curl_can_early_data() -> bool:
return Env.curl_uses_any_libs(['gnutls', 'wolfssl', 'quictls', 'openssl'])
if Env.curl_uses_lib('gnutls'):
return Env.curl_lib_version_at_least('gnutls', '3.6.13')
return Env.curl_uses_any_libs(['wolfssl', 'quictls', 'openssl'])
@staticmethod
def curl_can_h3_early_data() -> bool: