commit 5eb9e43bb063caa873ade4a0a8f767d4107fd5b3
parent 9f36568776f6592206a99b6d4790e218b0ad0922
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 11 Aug 2026 23:28:24 +0200
propagate enforcment of HTTP/1.1 also to auditor lib if set for exchange
Diffstat:
1 file changed, 120 insertions(+), 0 deletions(-)
diff --git a/src/lib/exchange_api_curl_defaults.c b/src/lib/exchange_api_curl_defaults.c
@@ -21,6 +21,7 @@
*/
#include "taler/taler_curl_lib.h"
#include "exchange_api_curl_defaults.h"
+#include "taler/taler_auditor_service.h"
#include "taler/exchange/common.h"
@@ -34,6 +35,104 @@ void
TALER_EXCHANGE_setup (enum TALER_EXCHANGE_GlobalOptions go)
{
eglobal_options = go;
+ if (TALER_EXCHANGE_GO_FORCE_HTTP1_1)
+ {
+ /* libtalerexchange also makes connections via libtalerauditor
+ to the auditor, so do enforce HTTP/1.1 there as well. */
+ TALER_AUDITOR_setup (TALER_AUDITOR_GO_FORCE_HTTP1_1);
+ }
+}
+
+
+#include <curl/curl.h>
+#include <stdbool.h>
+#include <string.h>
+
+
+/**
+ * Check if feature @a name is in the @a vi
+ *
+ * @param vi version data to test
+ * @param name feature to test for
+ * @true if feature is supported by curl
+ */
+static bool
+has_feature (const curl_version_info_data *vi,
+ const char *name)
+{
+ if (! vi->feature_names)
+ return false;
+
+ for (const char * const *p = vi->feature_names; *p; ++p)
+ if (0 ==
+ strcmp (*p,
+ name))
+ return true;
+ return false;
+}
+
+
+/**
+ * Check if @a s is non-NULL and starts with @a prefix
+ */
+static bool
+starts_with (const char *s,
+ const char *prefix)
+{
+ return ( (NULL != s) &&
+ (0 == strncmp (s,
+ prefix,
+ strlen (prefix)) ) );
+}
+
+
+/**
+ * Check if using HTTP3 is likely OK with our version of libcurl.
+ *
+ * @return true if HTTP3 should be well-supported
+ */
+static bool
+curl_http3_is_conservative_ok (void)
+{
+ const curl_version_info_data *vi =
+ curl_version_info (CURLVERSION_NOW);
+
+ if (! has_feature (vi,
+ "HTTP3"))
+ return false;
+
+ /*
+ * Require a QUIC backend we regard as production-ready.
+ *
+ * curl currently considers ngtcp2 non-experimental.
+ * quiche is still experimental.
+ */
+ if (! starts_with (vi->quic_version,
+ "ngtcp2/"))
+ return false;
+
+ /*
+ * Conservative policy: don't use HTTP/3 with GnuTLS.
+ * (too many bugs in recent releases still)
+ */
+ if (starts_with (vi->ssl_version,
+ "GnuTLS/"))
+ return false;
+
+ /*
+ * At this point the remaining ngtcp2 TLS configurations
+ * are the OpenSSL family and wolfSSL.
+ *
+ * We deliberately whitelist them rather than assuming
+ * every possible future TLS backend is safe.
+ */
+ if (starts_with (vi->ssl_version,
+ "OpenSSL/"))
+ return true;
+ if (starts_with (vi->ssl_version,
+ "wolfSSL/"))
+ return true;
+ return false;
}
@@ -65,9 +164,30 @@ TALER_EXCHANGE_curl_easy_get_ (const char *url)
CURLOPT_TCP_FASTOPEN,
1L));
if (TALER_EXCHANGE_GO_FORCE_HTTP1_1 & eglobal_options)
+ {
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_HTTP_VERSION,
CURL_HTTP_VERSION_1_1));
+ }
+ else
+ {
+ static enum GNUNET_GenericReturnValue http3 = GNUNET_SYSERR;
+
+ if (GNUNET_SYSERR == http3)
+ http3 = curl_http3_is_conservative_ok () ? GNUNET_YES : GNUNET_NO;
+ if (GNUNET_YES == http3)
+ {
+ /* HTTP/3 support with GnuTLS remains spotty, prefer HTTP/2 */
+ curl_easy_setopt (eh,
+ CURLOPT_HTTP_VERSION,
+ CURL_HTTP_VERSION_2TLS);
+ }
+ else
+ {
+ curl_easy_setopt (eh, CURLOPT_HTTP_VERSION,
+ CURL_HTTP_VERSION_3);
+ }
+ }
return eh;
}