From 7417f14b93b2bcc4ed31696dee7e9404ab2897af Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Sep 2025 16:54:27 +0000 Subject: [PATCH 01/10] GHA: update rojopolis/spellcheck-github-actions digest to 739a1e3 Closes #18515 --- .github/workflows/checkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checkdocs.yml b/.github/workflows/checkdocs.yml index 917efc539891..36a4ff999e3a 100644 --- a/.github/workflows/checkdocs.yml +++ b/.github/workflows/checkdocs.yml @@ -117,7 +117,7 @@ jobs: run: grep -v '^#' .github/scripts/spellcheck.words > wordlist.txt - name: 'check Spelling' - uses: rojopolis/spellcheck-github-actions@35a02bae020e6999c5c37fabaf447f2eb8822ca7 # v0 + uses: rojopolis/spellcheck-github-actions@739a1e3ceb79a98a5d4a9bf76f351137f9d78892 # v0 with: config_path: .github/scripts/spellcheck.yaml From 39c2d4b54363609865fa49f0f0d7adff84a03d03 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Sep 2025 18:40:05 +0000 Subject: [PATCH 02/10] GHA: update github/codeql-action digest to 192325c Closes #18516 --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 25a8f8cbc0fa..9863f7624d2c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -52,10 +52,10 @@ jobs: persist-credentials: false - name: 'initialize' - uses: github/codeql-action/init@d3678e237b9c32a6c9bffb3315c335f976f3549f # v3 + uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # v3 with: languages: actions, python queries: security-extended - name: 'perform analysis' - uses: github/codeql-action/analyze@d3678e237b9c32a6c9bffb3315c335f976f3549f # v3 + uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # v3 From aa8a44ecfa0e46a839affb58c6640b514b062995 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Thu, 11 Sep 2025 11:20:08 +0200 Subject: [PATCH 03/10] GHA: fix and tweak installed packages for http3-linux and Windows-cross - explicitly install `libldap-dev` to not rely on test-specific packages installing it implicitly, to have the same `curl -V` output for each TLS backend build pair. Follow-up to 0455d8772a1af20ce63c46c5738582aa9b1b8441 #18509 - install `libev-dev` for tests. It's a runtime dependency for the local build of `nghttpx`. Missing it made pytest skip 178 tests. Also skewing the 'Gain' time. I estimate it to account for 3 minutes, making the total gain ~20 minutes. Follow-up to 0455d8772a1af20ce63c46c5738582aa9b1b8441 #18509 (It may be a better solution to disable libev for the local nghttp2 build, to avoid this hidden dependency.) - fix quiche jobs to use the local build of `libnghttp2`. - stop installing the `clang` package for Windows-cross. `clang` and `clang-tidy` tools are preinstalled on the Ubuntu 24.04 runner. Closes #18519 --- .github/workflows/http3-linux.yml | 7 ++++--- .github/workflows/windows.yml | 4 +--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/http3-linux.yml b/.github/workflows/http3-linux.yml index 1a7ff07d5f25..3443b1146466 100644 --- a/.github/workflows/http3-linux.yml +++ b/.github/workflows/http3-linux.yml @@ -476,6 +476,7 @@ jobs: - name: 'quiche' install_steps: skipall + PKG_CONFIG_PATH: /home/runner/nghttp2/build/lib/pkgconfig configure: >- LDFLAGS=-Wl,-rpath,/home/runner/quiche/target/release --with-openssl=/home/runner/quiche/quiche/deps/boringssl/src @@ -484,7 +485,7 @@ jobs: --enable-unity - name: 'quiche' - PKG_CONFIG_PATH: /home/runner/quiche/target/release + PKG_CONFIG_PATH: /home/runner/nghttp2/build/lib/pkgconfig:/home/runner/quiche/target/release generate: >- -DOPENSSL_ROOT_DIR=/home/runner/quiche/quiche/deps/boringssl/src -DUSE_QUICHE=ON @@ -495,7 +496,7 @@ jobs: env: INSTALL_PACKAGES: >- ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') && 'stunnel4 ' || '' }} - ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') && 'apache2 apache2-dev libnghttp2-dev vsftpd dante-server' || '' }} + ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') && 'apache2 apache2-dev libnghttp2-dev vsftpd dante-server libev-dev' || '' }} run: | sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list @@ -503,7 +504,7 @@ jobs: sudo rm -f /var/lib/man-db/auto-update sudo apt-get -o Dpkg::Use-Pty=0 install \ libtool autoconf automake pkgconf \ - libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libidn2-0-dev libuv1-dev \ + libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libidn2-0-dev libldap-dev libuv1-dev \ ${INSTALL_PACKAGES} \ ${MATRIX_INSTALL_PACKAGES} python3 -m venv ~/venv diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 0938142df92b..9acc8cbde659 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -721,11 +721,9 @@ jobs: - { build: 'cmake' , compiler: 'clang-tidy' } steps: - name: 'install packages' - env: - INSTALL_PACKAGES: ${{ matrix.compiler == 'clang-tidy' && 'clang' || '' }} run: | sudo rm -f /var/lib/man-db/auto-update - sudo apt-get -o Dpkg::Use-Pty=0 install gcc-mingw-w64-x86-64-win32 ${INSTALL_PACKAGES} + sudo apt-get -o Dpkg::Use-Pty=0 install gcc-mingw-w64-x86-64-win32 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 with: From bf6ae59ab1586e3cd97f27341e4964a9316dc3d5 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Thu, 11 Sep 2025 15:02:57 +0200 Subject: [PATCH 04/10] GHA/windows: drop repeated word from comment --- .github/workflows/windows.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 9acc8cbde659..b519af47d66c 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -950,9 +950,8 @@ jobs: # Use Ninja when running tests to avoid MSBuild heuristics picking # up "error messages" in the test log output and making the job fail. # Officially this requires the vcvarsall.bat MS-DOS batch file (as of - # VS2022). Since it integrates badly with CI steps and shell scripts - # scripts, reproduce the necessary build configuration manually, and - # without envs. + # VS2022). Since it integrates badly with CI steps and shell scripts, + # reproduce the necessary build configuration manually, without envs. [[ "$(uname -s)" = *'ARM64'* ]] && MSVC_HOST='arm64' || MSVC_HOST='x64' # x86 MSVC_ROOTD="$(cygpath --mixed --short-name "$PROGRAMFILES/Microsoft Visual Studio")" # to avoid spaces in directory names MSVC_ROOTU="$(/usr/bin/find "$(cygpath --unix "$MSVC_ROOTD/2022/Enterprise/vc/tools/msvc")" -mindepth 1 -maxdepth 1 -type d -name '*.*' | sort | tail -n 1)" From b178d58266d4d9805de6da913b5be25c0485b6c2 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Thu, 11 Sep 2025 12:59:22 +0200 Subject: [PATCH 05/10] quic: fix min TLS version handling When switching to TSLv1.2 as default in 9d8998c99408e1adf8eba629fad9f87b3235bdfa, this led to an explicit setting of 1.2 on QUIC connections when using quictls, overriding the already set min version of 1.3. This leads to a ClientHello with TLS 1.2+1.3 offered on a QUIC connect which is rejected by the Caddy server. Using ngtcp2 with OpenSSL 3.5+, GnuTLS or AWS-LC is not affected. Fixes #18518 Reported-by: fds242 on github Closes #18520 --- lib/vtls/openssl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index a49203ab07d2..5c22ad25dc94 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -2865,11 +2865,12 @@ static void ossl_trace(int direction, int ssl_ver, int content_type, #if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */ static CURLcode -ossl_set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx) +ossl_set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx, + unsigned int ssl_version_min) { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); /* first, TLS min version... */ - long curl_ssl_version_min = conn_config->version; + long curl_ssl_version_min = (long)ssl_version_min; long curl_ssl_version_max; /* convert curl min SSL version option to OpenSSL constant */ @@ -4110,7 +4111,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, ctx_options |= SSL_OP_NO_SSLv3; #if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */ - result = ossl_set_ssl_version_min_max(cf, octx->ssl_ctx); + result = ossl_set_ssl_version_min_max(cf, octx->ssl_ctx, ssl_version_min); #else result = ossl_set_ssl_version_min_max_legacy(&ctx_options, cf, data); #endif From 115fe808f2346b9c02d2720d8f575098e473a5d2 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Thu, 11 Sep 2025 14:12:04 +0200 Subject: [PATCH 06/10] ngtcp2: check error code on connect failure Access the error codes of ngtcp2 when a connect attempt failes. Trace the information for analysis. Treat errors as permanent failure by default, trigger retrying only when the server refused without indicating an error. Closes #18521 --- lib/vquic/curl_ngtcp2.c | 30 +++++++++++++++++++++++++----- tests/http/testenv/nghttpx.py | 7 ++++--- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c index 6470f1506d15..3f7c58d08af2 100644 --- a/lib/vquic/curl_ngtcp2.c +++ b/lib/vquic/curl_ngtcp2.c @@ -2578,11 +2578,31 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf, out: if(result == CURLE_RECV_ERROR && ctx->qconn && ngtcp2_conn_in_draining_period(ctx->qconn)) { - /* When a QUIC server instance is shutting down, it may send us a - * CONNECTION_CLOSE right away. Our connection then enters the DRAINING - * state. The CONNECT may work in the near future again. Indicate - * that as a "weird" reply. */ - result = CURLE_WEIRD_SERVER_REPLY; + const ngtcp2_ccerr *cerr = ngtcp2_conn_get_ccerr(ctx->qconn); + + result = CURLE_COULDNT_CONNECT; + if(cerr) { + CURL_TRC_CF(data, cf, "connect error, type=%d, code=%" + FMT_PRIu64, + cerr->type, (curl_uint64_t)cerr->error_code); + switch(cerr->type) { + case NGTCP2_CCERR_TYPE_VERSION_NEGOTIATION: + CURL_TRC_CF(data, cf, "error in version negotiation"); + break; + default: + if(cerr->error_code >= NGTCP2_CRYPTO_ERROR) { + CURL_TRC_CF(data, cf, "crypto error, tls alert=%u", + (unsigned int)(cerr->error_code & 0xffu)); + } + else if(cerr->error_code == NGTCP2_CONNECTION_REFUSED) { + CURL_TRC_CF(data, cf, "connection refused by server"); + /* When a QUIC server instance is shutting down, it may send us a + * CONNECTION_CLOSE with this code right away. We want + * to keep on trying in this case. */ + result = CURLE_WEIRD_SERVER_REPLY; + } + } + } } #ifndef CURL_DISABLE_VERBOSE_STRINGS diff --git a/tests/http/testenv/nghttpx.py b/tests/http/testenv/nghttpx.py index 0bd46ac3603c..dfb416334c5a 100644 --- a/tests/http/testenv/nghttpx.py +++ b/tests/http/testenv/nghttpx.py @@ -124,15 +124,16 @@ def reload(self, timeout: timedelta = timedelta(seconds=Env.SERVER_TIMEOUT)): running = self._process self._process = None os.kill(running.pid, signal.SIGQUIT) - end_wait = datetime.now() + timeout + end_wait = datetime.now() + timedelta(seconds=5) if not self.start(wait_live=False): self._process = running return False while datetime.now() < end_wait: try: log.debug(f'waiting for nghttpx({running.pid}) to exit.') - running.wait(2) + running.wait(1) log.debug(f'nghttpx({running.pid}) terminated -> {running.returncode}') + running = None break except subprocess.TimeoutExpired: log.warning(f'nghttpx({running.pid}), not shut down yet.') @@ -142,7 +143,7 @@ def reload(self, timeout: timedelta = timedelta(seconds=Env.SERVER_TIMEOUT)): os.kill(running.pid, signal.SIGKILL) running.terminate() running.wait(1) - return self.wait_live(timeout=timedelta(seconds=Env.SERVER_TIMEOUT)) + return self.wait_live(timeout=timeout) return False def wait_dead(self, timeout: timedelta): From 839b22863e2f3dfdceab91e66c23257bc8726863 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 11 Sep 2025 16:09:45 +0200 Subject: [PATCH 07/10] ssl-sessions.md: mark option experimental Also make managen output the experimental text with the correct prefix/margin for the ascii version. Closes #18523 --- docs/cmdline-opts/ssl-sessions.md | 1 + scripts/managen | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/cmdline-opts/ssl-sessions.md b/docs/cmdline-opts/ssl-sessions.md index bb1e251e732d..33ef984a3ec4 100644 --- a/docs/cmdline-opts/ssl-sessions.md +++ b/docs/cmdline-opts/ssl-sessions.md @@ -8,6 +8,7 @@ Help: Load/save SSL session tickets from/to this file Added: 8.12.0 Category: tls Multi: single +Experimental: yes See-also: - tls-earlydata Example: diff --git a/scripts/managen b/scripts/managen index 459b651240a6..1eb536a0e6d7 100755 --- a/scripts/managen +++ b/scripts/managen @@ -728,7 +728,8 @@ sub single { } if($experimental) { - push @leading, "**WARNING**: this option is experimental. Do not use in production.\n\n"; + my $pref = $manpage ? "" : "[1]"; + push @leading, "$pref**WARNING**: this option is experimental. Do not use in production.\n\n"; } my $pre = $manpage ? "\n": "[1]"; From 53f90cb3b5678de16a0129ff4f9f3f0e87dfd78b Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Thu, 11 Sep 2025 15:05:28 +0200 Subject: [PATCH 08/10] GHA/http3-linux: fix nghttpx build and other tweaks - fix `nghttp2` build to also build the `nghttpx` application. Restore required `libc-ares-dev`. Also confirm that `libev-dev` is required too. Document these requirements. Follow-up to 0455d8772a1af20ce63c46c5738582aa9b1b8441 #18509 - explicitly enable `nghttpx` for the `nghttp2` build to make it fail if requirements aren't met: ``` configure: error: applications were requested (--enable-app) but dependencies are not met. ``` - explicitly install brotli, zstd, zlib for the dependency builds. Of these, zstd and zlib are preinstalled. zlib is required for `nghttpx`. zstd and brotli doesn't seem to be used, but keep them there just in case and to match the test env. Follow-up to 0455d8772a1af20ce63c46c5738582aa9b1b8441 #18509 - enable brotli for `nghttpx`. It doesn't change the tests, and also cost almost nothing, so I figure why not. Closes #18522 --- .github/workflows/http3-linux.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/http3-linux.yml b/.github/workflows/http3-linux.yml index 3443b1146466..195437182f11 100644 --- a/.github/workflows/http3-linux.yml +++ b/.github/workflows/http3-linux.yml @@ -193,7 +193,10 @@ jobs: sudo rm -f /var/lib/man-db/auto-update sudo apt-get -o Dpkg::Use-Pty=0 install \ libtool autoconf automake pkgconf \ - nettle-dev libp11-kit-dev libev-dev autopoint bison gperf gtk-doc-tools libtasn1-bin # for gnutls + libbrotli-dev libzstd-dev zlib1g-dev \ + libev-dev \ + libc-ares-dev \ + nettle-dev libp11-kit-dev autopoint bison gperf gtk-doc-tools libtasn1-bin # for GnuTLS echo 'CC=gcc-12' >> "$GITHUB_ENV" echo 'CXX=g++-12' >> "$GITHUB_ENV" @@ -256,6 +259,7 @@ jobs: cd ~ git clone --quiet --depth=1 -b "${GNUTLS_VERSION}" https://github.com/gnutls/gnutls.git cd gnutls + # required: nettle-dev libp11-kit-dev libev-dev autopoint bison gperf gtk-doc-tools libtasn1-bin ./bootstrap ./configure --disable-dependency-tracking --prefix="$PWD"/build \ LDFLAGS="-Wl,-rpath,$PWD/build/lib -L$PWD/build/lib" \ @@ -332,10 +336,13 @@ jobs: cd nghttp2 git submodule update --init --depth=1 autoreconf -fi + # required (for nghttpx application): libc-ares-dev libev-dev zlib1g-dev + # optional (for nghttpx application): libbrotli-dev ./configure --disable-dependency-tracking --prefix="$PWD"/build \ PKG_CONFIG_PATH=/home/runner/quictls/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig \ LDFLAGS=-Wl,-rpath,/home/runner/quictls/build/lib \ - --enable-http3 + --with-libbrotlienc --with-libbrotlidec \ + --enable-app --enable-http3 make install linux: From c184f464f795dbdf8db354b9b2bc01891ddc4fdd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 11 Sep 2025 17:50:59 +0200 Subject: [PATCH 09/10] CURLOPT_MAXLIFETIME_CONN: make default 24 hours Set a default value to only reuse existing connections if less than 24 hours old. This makes the TLS certificate check get redone for the new connection. An application can still set it to zero. Closes #18527 --- docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.md | 14 ++++++++------ lib/url.c | 2 +- lib/urldata.h | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.md b/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.md index b29e61a2c3e5..8c1fbf82f86b 100644 --- a/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.md +++ b/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.md @@ -35,16 +35,18 @@ connection to have to be considered for reuse for this request. libcurl features a connection cache that holds previously used connections. When a new request is to be done, libcurl considers any connection that -matches for reuse. The CURLOPT_MAXLIFETIME_CONN(3) limit prevents -libcurl from trying too old connections for reuse. This can be used for -client-side load balancing. If a connection is found in the cache that is -older than this set *maxlifetime*, it is instead marked for closure. +matches for reuse. The CURLOPT_MAXLIFETIME_CONN(3) limit prevents libcurl from +trying too old connections for reuse. This can be used for client-side load +balancing. If a connection is found in the cache that is older than this set +*maxlifetime*, it is instead marked for closure. -If set to 0, this behavior is disabled: all connections are eligible for reuse. +If set to 0, this behavior is disabled: all connections are eligible for +reuse. # DEFAULT -0 seconds (i.e., disabled) +24 hours (since 8.17.0). Before that, the default was 0 seconds (i.e., +disabled) # %PROTOCOLS% diff --git a/lib/url.c b/lib/url.c index 45d44bac738f..283da6d68b50 100644 --- a/lib/url.c +++ b/lib/url.c @@ -488,7 +488,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT; set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */ set->conn_max_idle_ms = 118 * 1000; - set->conn_max_age_ms = 0; + set->conn_max_age_ms = 24 * 3600 * 1000; set->http09_allowed = FALSE; set->httpwant = CURL_HTTP_VERSION_NONE ; diff --git a/lib/urldata.h b/lib/urldata.h index cf181af641fd..a0ee614da838 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1390,9 +1390,9 @@ struct UserDefined { void *progress_client; /* pointer to pass to the progress callback */ void *ioctl_client; /* pointer to pass to the ioctl callback */ timediff_t conn_max_idle_ms; /* max idle time to allow a connection that - is to be reused */ + is to be reused */ timediff_t conn_max_age_ms; /* max time since creation to allow a - connection that is to be reused */ + connection that is to be reused */ curl_off_t filesize; /* size of file to upload, -1 means unknown */ long low_speed_limit; /* bytes/second */ long low_speed_time; /* number of seconds */ From 16cd81ed69b9123584dd73a6924a8f852dc2372a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 11 Sep 2025 16:52:40 +0200 Subject: [PATCH 10/10] urldata: FILE is not a list-only protocol The struct field thus does not depend on the presence of it Closes #18525 --- lib/urldata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/urldata.h b/lib/urldata.h index a0ee614da838..4f00c8c9a093 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -116,7 +116,7 @@ typedef unsigned int curl_prot_t; #define PROTO_FAMILY_SSH (CURLPROTO_SCP|CURLPROTO_SFTP) #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) || \ - !defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_FILE) + !defined(CURL_DISABLE_POP3) /* these protocols support CURLOPT_DIRLISTONLY */ #define CURL_LIST_ONLY_PROTOCOL 1 #endif