gnutls: set priority via --ciphers

No longer ignore the `--ciphers` argument in gnutls curl builds, but use
it to set the gnutls priority string.

When the set ciphers start with '+', '-' or '!', it is *appended* to the
curl generated priority string. Otherwise it replaces the curl one
completely.

Add test_17_18 to check various combinations.

Closes #16557
This commit is contained in:
Stefan Eissing 2025-03-04 15:50:12 +01:00 committed by Daniel Stenberg
parent e6c78e18da
commit 9bfa64f850
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
5 changed files with 225 additions and 44 deletions

View file

@ -63,12 +63,6 @@
/* The last #include file should be: */
#include "memdebug.h"
#define QUIC_PRIORITY \
"NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
"+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
"+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
"%DISABLE_TLS13_COMPAT_MODE"
/* Enable GnuTLS debugging by defining GTLSDEBUG */
/*#define GTLSDEBUG */
@ -319,12 +313,18 @@ static gnutls_x509_crt_fmt_t gnutls_do_file_type(const char *type)
*/
#define GNUTLS_SRP "+SRP"
#define QUIC_PRIORITY \
"NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
"+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
"+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
"%DISABLE_TLS13_COMPAT_MODE"
static CURLcode
gnutls_set_ssl_version_min_max(struct Curl_easy *data,
struct ssl_peer *peer,
struct ssl_primary_config *conn_config,
const char **prioritylist,
const char *tls13support)
bool tls13support)
{
long ssl_version = conn_config->version;
long ssl_version_max = conn_config->version_max;
@ -780,6 +780,63 @@ static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
return 0;
}
static CURLcode gtls_set_priority(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct gtls_ctx *gtls,
const char *priority)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct dynbuf buf;
const char *err = NULL;
CURLcode result = CURLE_OK;
int rc;
Curl_dyn_init(&buf, 4096);
#ifdef USE_GNUTLS_SRP
if(conn_config->username) {
/* Only add SRP to the cipher list if SRP is requested. Otherwise
* GnuTLS will disable TLS 1.3 support. */
result = Curl_dyn_add(&buf, priority);
if(!result)
result = Curl_dyn_add(&buf, ":" GNUTLS_SRP);
if(result)
goto out;
priority = Curl_dyn_ptr(&buf);
}
#endif
if(conn_config->cipher_list) {
if((conn_config->cipher_list[0] == '+') ||
(conn_config->cipher_list[0] == '-') ||
(conn_config->cipher_list[0] == '!')) {
/* add it to out own */
if(!Curl_dyn_len(&buf)) { /* not added yet */
result = Curl_dyn_add(&buf, priority);
if(result)
goto out;
}
result = Curl_dyn_addf(&buf, ":%s", conn_config->cipher_list);
if(result)
goto out;
priority = Curl_dyn_ptr(&buf);
}
else /* replace our own completely */
priority = conn_config->cipher_list;
}
infof(data, "GnuTLS priority: %s", priority);
rc = gnutls_priority_set_direct(gtls->session, priority, &err);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "Error %d setting GnuTLS priority: %s", rc, err);
result = CURLE_SSL_CONNECT_ERROR;
}
out:
Curl_dyn_free(&buf);
return result;
}
static CURLcode gtls_client_init(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
@ -792,8 +849,7 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
int rc;
bool sni = TRUE; /* default is SNI enabled */
const char *prioritylist;
const char *err = NULL;
const char *tls13support;
bool tls13support;
CURLcode result;
if(!gtls_inited)
@ -888,7 +944,7 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR;
/* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
tls13support = gnutls_check_version("3.6.5");
tls13support = !!gnutls_check_version("3.6.5");
/* Ensure +SRP comes at the *end* of all relevant strings so that it can be
* removed if a runtime error indicates that SRP is not supported by this
@ -913,33 +969,9 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
if(result)
return result;
#ifdef USE_GNUTLS_SRP
/* Only add SRP to the cipher list if SRP is requested. Otherwise
* GnuTLS will disable TLS 1.3 support. */
if(config->username) {
char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
if(!prioritysrp)
return CURLE_OUT_OF_MEMORY;
rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
free(prioritysrp);
if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
infof(data, "This GnuTLS does not support SRP");
}
}
else {
#endif
infof(data, "GnuTLS ciphers: %s", prioritylist);
rc = gnutls_priority_set_direct(gtls->session, prioritylist, &err);
#ifdef USE_GNUTLS_SRP
}
#endif
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "Error %d setting GnuTLS cipher list starting with %s",
rc, err);
return CURLE_SSL_CONNECT_ERROR;
}
result = gtls_set_priority(cf, data, gtls, prioritylist);
if(result)
return result;
if(config->clientcert) {
if(!gtls->shared_creds->trust_setup) {
@ -2155,6 +2187,7 @@ const struct Curl_ssl Curl_ssl_gnutls = {
SSLSUPP_CERTINFO |
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_HTTPS_PROXY |
SSLSUPP_CIPHER_LIST |
SSLSUPP_CA_CACHE,
sizeof(struct gtls_ssl_backend_data),