PR #24586 opened by tosiek URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24586 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24586.patch
### Description In GnuTLS versions prior to 3.8.13, GnuTLS's client certificate selection heuristics can fail to automatically send the client certificate during a TLS handshake, even when the user explicitly provides both `cert_file` and `key_file` via FFmpeg options. This change explicitly forces sending the configured client certificate during handshakes under GnuTLS < 3.8.13 when `cert_file` and `key_file` are set, bypassing the flawed client certificate lookup heuristics. Fixes #22707 ### Changes Made - Updated `libavformat/tls_gnutls.c` to check for provided client certificate files. - Enforced client certificate sending for GnuTLS versions prior to 3.8.13. ### Testing - Tested against server setups requiring mTLS using GnuTLS builds (< 3.8.13). - Verified client certificate is reliably transmitted during TLS handshakes. >From 237b5a76af690632ccdf779d97c1aaef435fe5ad Mon Sep 17 00:00:00 2001 From: Your Name <[email protected]> Date: Sun, 20 Sep 2026 16:33:28 +0200 Subject: [PATCH 1/3] avformat/tls_gnutls: force sending client cert if one is provided In GnuTLS versions prior to 3.8.13, client certificate selection heuristics can fail to send the client certificate even when the user explicitly supplied cert_file and key_file. Force sending the client certificate when one is provided. Fixes #22707 Signed-off-by: Your Name <[email protected]> --- libavformat/tls_gnutls.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c index df251ad79c..0e8fc4df94 100644 --- a/libavformat/tls_gnutls.c +++ b/libavformat/tls_gnutls.c @@ -151,6 +151,7 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op { TLSContext *p = h->priv_data; TLSShared *c = &p->tls_shared; + uint16_t gnutls_flags = 0; int ret; ff_gnutls_init(); @@ -158,9 +159,6 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0) goto fail; - gnutls_init(&p->session, c->listen ? GNUTLS_SERVER : GNUTLS_CLIENT); - if (!c->listen && !c->numerichost) - gnutls_server_name_set(p->session, GNUTLS_NAME_DNS, c->host, strlen(c->host)); gnutls_certificate_allocate_credentials(&p->cred); if (c->ca_file) { ret = gnutls_certificate_set_x509_trust_file(p->cred, c->ca_file, GNUTLS_X509_FMT_PEM); @@ -186,6 +184,20 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op } } else if (c->cert_file || c->key_file) av_log(h, AV_LOG_ERROR, "cert and key required\n"); + + if (c->listen) + gnutls_flags |= GNUTLS_SERVER; + else { + gnutls_flags |= GNUTLS_CLIENT; +#if defined(GNUTLS_VERSION_NUMBER) && defined(GNUTLS_FORCE_CLIENT_CERT) && GNUTLS_VERSION_NUMBER >= 0x030500 && GNUTLS_VERSION_NUMBER < 0x03080d + if (c->cert_file && c->key_file) + gnutls_flags |= GNUTLS_FORCE_CLIENT_CERT; +#endif + } + + gnutls_init(&p->session, gnutls_flags); + if (!c->listen && !c->numerichost) + gnutls_server_name_set(p->session, GNUTLS_NAME_DNS, c->host, strlen(c->host)); gnutls_credentials_set(p->session, GNUTLS_CRD_CERTIFICATE, p->cred); gnutls_transport_set_pull_function(p->session, gnutls_url_pull); gnutls_transport_set_push_function(p->session, gnutls_url_push); -- 2.52.0 >From f59d34252b2c2edc987268095ade6a882b23a295 Mon Sep 17 00:00:00 2001 From: Your Name <[email protected]> Date: Sun, 20 Sep 2026 16:40:01 +0200 Subject: [PATCH 2/3] avformat/tls_gnutls: force sending client cert if one is provided In GnuTLS versions prior to 3.8.13, client certificate selection heuristics can fail to send the client certificate even when the user explicitly supplied cert_file and key_file. Force sending the client certificate when one is provided under GnuTLS < 3.8.13. Fixes #22707 Signed-off-by: Your Name <[email protected]> --- libavformat/tls_gnutls.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c index 0e8fc4df94..609b31a0b4 100644 --- a/libavformat/tls_gnutls.c +++ b/libavformat/tls_gnutls.c @@ -190,8 +190,11 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op else { gnutls_flags |= GNUTLS_CLIENT; #if defined(GNUTLS_VERSION_NUMBER) && defined(GNUTLS_FORCE_CLIENT_CERT) && GNUTLS_VERSION_NUMBER >= 0x030500 && GNUTLS_VERSION_NUMBER < 0x03080d - if (c->cert_file && c->key_file) + if (c->cert_file && c->key_file) { + av_log(h, AV_LOG_WARNING, + "Forcing client certificate transmission due to GnuTLS < 3.8.13\n"); gnutls_flags |= GNUTLS_FORCE_CLIENT_CERT; + } #endif } -- 2.52.0 >From 247d106f50c3df4eb7988ae7e12508f24cd0aa16 Mon Sep 17 00:00:00 2001 From: Your Name <[email protected]> Date: Sun, 20 Sep 2026 17:05:11 +0200 Subject: [PATCH 3/3] avformat/tls_gnutls: force sending client cert if one is provided In GnuTLS versions prior to 3.8.13, client certificate selection heuristics can fail to send the client certificate even when the user explicitly supplied cert_file and key_file. Force sending the client certificate when one is provided under GnuTLS < 3.8.13. Fixes #22707 Signed-off-by: Your Name <[email protected]> --- libavformat/tls_gnutls.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c index 609b31a0b4..1631b261a2 100644 --- a/libavformat/tls_gnutls.c +++ b/libavformat/tls_gnutls.c @@ -189,8 +189,12 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op gnutls_flags |= GNUTLS_SERVER; else { gnutls_flags |= GNUTLS_CLIENT; -#if defined(GNUTLS_VERSION_NUMBER) && defined(GNUTLS_FORCE_CLIENT_CERT) && GNUTLS_VERSION_NUMBER >= 0x030500 && GNUTLS_VERSION_NUMBER < 0x03080d - if (c->cert_file && c->key_file) { +#if defined(GNUTLS_VERSION_NUMBER) && defined(GNUTLS_FORCE_CLIENT_CERT) && GNUTLS_VERSION_NUMBER >= 0x030500 + /* GnuTLS < 3.8.13 has a bug where the client certificate is silently + * suppressed if the server's CertificateRequest CA list or signature + * algorithm list doesn't match, even when the user explicitly provided + * cert_file and key_file. Force sending it when the library is affected. */ + if (c->cert_file && c->key_file && !gnutls_check_version("3.8.13")) { av_log(h, AV_LOG_WARNING, "Forcing client certificate transmission due to GnuTLS < 3.8.13\n"); gnutls_flags |= GNUTLS_FORCE_CLIENT_CERT; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
