When TLS is verified via Apple SecTrust, openssl internal state is a
verification faiure (that is how it works, we use sectrust when openssl
fails to verify and natice ca store is enabled).
OpenSSL stores this verification status inside its TLS session objects.
On reuse, we see an unverified session and do not reuse it for a
verified connect attempt. While this is a performance penalty for most
connections, it *fails* on ftps:// transfers where servers expect
session reuse on DATA connections.
Fix this by remembering that TLS and a session was verified by sectrust
and allow reuse of such sessions for new connect attempts that also use
sectrust.
Closes#22235
By exposing and reusing existing custom type via `vtls/openss.h`.
Also:
- GHA/curl-for-win: test in CI by enabling building tests.
Cost is 45s per job, so limit it to the gcc job.
Seen with Windows x64 gcc (not tested in CI prior to this patch):
```
tests/libtest/lib1587.c:50:7: error: conversion from 'opt1587' {aka 'long long unsigned int'} to 'long int' may change value [-Werror=conversion]
50 | SSL_CTX_set_options(info->internals, opts);
| ^~~~~~~~~~~~~~~~~~~
tests/libtest/lib1587.c:59:7: error: conversion from 'opt1587' {aka 'long long unsigned int'} to 'long int' may change value [-Werror=conversion]
59 | SSL_set_options(info->internals, opts);
| ^~~~~~~~~~~~~~~
```
Ref: https://github.com/curl/curl/actions/runs/28258372229/job/83727170184?pr=22195#step:3:4884
Ref: da2f05e6f6#22198
Ref: 6163566461#22197
Follow-up to 3e40ccb875#21290
Follow-up to 2db8ae480f#17809#17801Closes#22195
- cmp-pkg-config.sh: replace `-r -f` with `-rf` to match rest of repo.
- configure.ac: add double quotes for robustness (not a bug).
- curl-openssl.m4: merge nested `if`s.
- CurlTests.c: drop `!= 0`, also to sync with m4.
- CurlTests.c: replace `example.com` with `localhost` in
`gethostbyname()` feature test code. (compile-only, not a bug)
- GHA/http3-linux: drop literal `true` from bool expression.
- lib650: drop redundant `&`.
- move variable/call to left-hand side of equality checks, where
missing.
- perl: detach `<`/`>` from filename in `open()`, where missing.
- schannel: apply two nit fixes lost in rebase.
- scripts/verify-release: drop redundant double quotes.
- scripts/verify-release: exit with error code on error.
- synctime: replace magic numbers with `sizeof()`.
- telnet: add missing parentheses to macro value.
- tests/Makefile.am: use single quotes.
- tool_operate: drop redundant `break` after `return` in VMS code.
- unit2413: drop unused NULL pointer + free call.
- unit2413: fix duplicate test case name.
- urlapi: drop redundant parentheses.
- urlapi: drop `CURL_UNCONST()` that became redundant.
Closes#22186
- GHA/windows: mention `IgnoreStandardErrorWarningFormat=true`
in comment.
- cmake: fix MIT/GNU GSS order in messages.
- drop some exclamation marks from messages.
- drop redundant ending newlines from messages.
- fold/unfold where possible.
- fix indent, whitespace, typos and other nits.
Closes#22185
Seen with clang-22:
```
lib/vtls/openssl.c:3538:14: error: implicit conversion from 'int' to enumeration type 'CURLcode' is invalid in C++ [-Werror,-Wimplicit-int-enum-cast]
3538 | result = SSL_ech_set1_server_names(octx->ssl,
| ~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3539 | peer->origin->hostname, outername,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3540 | 0 /* do send outer */);
| ~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
```
Ref: https://github.com/curl/curl/actions/runs/27769068896/job/82163712258#step:42:43
Cherry-picked from #22086Closes#22087
The DNS filter knows the peer it resolves and the code parts that want
the results know the peer as well. Pass it to lookup methods to make
sure results match.
Background: when tunneling, the resolved peer is not always the one that
other filters are looking for. Especially when HTTPS-RR results are
accessed in TLS filters, those will differ.
This prevents a HTTPS-RR for a proxy to be used for the origin when ECH
is activated. To make ECH work through a tunnel, we need to start an
additional resolve. Something to be fixed after 8.21.
Closes#22042
This PR makes the wolfssl TLS backend work properly for PQC key
exchanges. The following issues are fixed:
* WOLFSSL_HAVE_KYBER is not present anymore in upstream wolfssl (for a
long time actually), so it has no use and the ML-KEM functionality was
never turned on properly.
* Key share group selection (via --curves) is now handled via the
generic wolfSSL_CTX_set1_groups_list() method instead of the prior
wolfSSL_CTX_set1_curves_list() and the additonal PQC handling. This
removes a lot of PQC related special handling and the behavior now
matches the OpenSSL backend.
* The default QUIC group setting has been removed. For QUIC, the key
share as well as the list in the supported_groups extension is now
handled all within wolfssl. This also supports --curves properly now.
Closes#22030
- `N byte` -> `N-byte` or `N bytes`.
- INTERNALS.md: language tweaks.
- schannel: language tweak in comment/error message.
- socks_gssapi, socks_sspi: simplify composing an error message.
(at a cost of 8 extra constant string bytes.)
- m4/curl-compilers.m4: fix typo in link (in comment).
- contrithanks.sh: fix indent, drop stray `;` terminator.
- lib, src, tests: drop/fix a bunch of badwords.
- fix typos in comments.
- fix indent, stray spaces.
Some of these spotted by GitHub Code Quality and Copilot
Closes#22009
To contain the logic of checking for both `EWOULDBLOCK` and/or `EAGAIN`
depending on platform/availability. Also to avoid checking for both if
they mapp to the same value, and to avoid PP guards around use.
This also ensures `EAGAIN` is consistently not checked on Windows, where
headers defined it, but `SOCKERRNO` never returns it, because curl maps
it to `WSAGetLastError()`.
If they map to the same value, checking them both in an `if` expression
trips GCC warning `-Wlogical-op` (the same way it triggers duplicate
case value error in `switch`).
Also:
- replace two `switch()` statements with the new macro.
- tests/server/sws: make two outliers use the new macro that were only
checking for `EWOULDBLOCK` before this patch, in `connect_to()`.
- move variables to the left-side of expressions, where missing.
- rustls: use a variant of this macro that uses raw `EWOULDBLOCK`.
Tried tracing it back to the origins, but I couldn't figure out if
this is working as expected on all supported Windows versions in
Rust. It seems to be using `GetLastError()`, according to
https://docs.rs/system_error/0.2.0/system_error/, which would be
probably incorrect.
Notes:
- it's probably a good idea to assign `SOCKERRNO` to a variable before
passing it to this macro.
Cherry-picked from #21893Closes#21992
When schannel operates in front of a proxy, it needs to use the proxy
ssl configs, not the transfers ones. Choose the configs as it is done in
other TLS backends.
Prior to this change the client cert for the destination was mistakenly
also used as the client cert for the proxy.
Prior to this change the proxy server certificate info was mistakenly
saved as the destination cert info. However, if the destination was a
TLS connection, the real destination cert info would overwrite the
proxy cert info. libcurl currently does not support proxy server cert
info AFAICT (see discussion in #21986).
Closes https://github.com/curl/curl/pull/21986
Adjust code to avoid `-Wformat-signedness` warnings, while making sure
that enums are always cast to a known type when passing them to `printf`
functions, to support compilers and compiler settings where enums are
not default-size signed ints.
- cast integers printed as hex to `unsigned`. (63 times, 20 of them in
`mbedtls.c`)
- cast misc enums to `int` for printing. (31 times)
- cast `CURL_LOCK_DATA_*` enums to `int`. (4 times)
- cast `CURL_FORMADD_*` enums to `int`. (13 times)
- cast `CURLSHE_*` enums to `int`. (3 times)
- cast `CURLUE_*` enums to `int`. (33 times)
- cast `CURLMSG_*` enums to `int`. (6 times)
- cast `CURLE_*` enums to `int`. (~380 times)
- unit1675: fix mask.
Follow-up to 7c34365cce#21879
Ref: #18343 (initial attempt)
Closes#20848
Share common functions/structs between ngtcp2 HTTP/3 and the proxy
version.
Fix bugs in proxy implementation when it comes to stream and pollset
handling and transfer lifetimes.
Curl_multi_xfer_sockbuf_borrow: work without multi
When a connection gets shutdown by a share, the easy handle used is
share->admin and it does not have a multi handle. In that case let
Curl_multi_xfer_sockbuf_borrow() allocate a buffer to be freed on
release.
This happens when a TLS filter sends its last notify through a HTTP/3
proxy tunnel.
Closes#21871
Add bit `native_ca_store_opt` to keep the setting of
CURLOPT_(PROXY_)SSL_OPTIONS and use that to calculate every easy
transfer if a native CA store shall be used or not.
This avoids `native_ca_store` getting stuck on TRUE after being set
once.
Closes#21902
- Specify that the content is base64 encoded, rather than rely on
auto-detect.
- Remove unnecessary sanity check of the returned content type.
Closes https://github.com/curl/curl/pull/21760
- fix GnuTLS function name reference in `Curl_gtls_shared_creds_create()`
error message.
Spotted by GitHub Code Quality.
- unfold a line.
- in `Curl_gtls_verifyserver()`:
- report the failure of `gnutls_x509_crt_import()`.
Spotted by GitHub Code Quality.
- fix a minor inconsistency in error strings.
- drop redundant NULL checks for `config->issuercert`.
Closes#21850
Since aeb1a281ca ("gtls: fix OCSP stapling management"), the function
parses the stapled OCSP response and reads the certificate status via
gnutls_ocsp_resp_get_single(), but never calls gnutls_ocsp_resp_verify()
or gnutls_ocsp_resp_verify_direct(). A response with a forged or
corrupted signature is accepted without question.
Fix by calling gnutls_ocsp_resp_verify() against the trust list obtained
from the session credentials immediately after gnutls_ocsp_resp_import().
This handles both directly-signed responses and delegated OCSP responders
without requiring the issuer certificate to be present in the peer chain.
The missing check only affects the CURLOPT_SSL_VERIFYSTATUS code path
when CURLOPT_SSL_VERIFYPEER is disabled. With peer verification enabled,
gnutls_certificate_verify_peers2() independently catches the invalid
response via GNUTLS_CERT_INVALID_OCSP_STATUS before
gtls_verify_ocsp_status() is reached. As a result, no attack is possible
that is not already trivially achievable without OCSP stapling when peer
verification is off. This is a correctness and consistency fix, not a
security vulnerability.
Reported-by: Joshua Rogers
Closes#21677
closing a filter chain and reconnecting it again is a complication
that only the HTTP/1.x proxy filter used. Remove it from all filters.
Instead, a filter can return CURLE_AGAIN during the connect phase
and the cf-setup filter will tear down all "sub filters" and restart
over.
With this, a filter never resets to the initial phase but progresses
through connect -> connected -> shutdown -> destroy once.
Closes#21831
When a transfer goes against another origin than the initial one, do not
add the following to the ssl configuration: client cert, client key, srp
user/pass, pinned key.
Closes#21695
- H3 proxy: re-sync code with original source `curl_ngtcp2.c` to reduce
differences, and to apply missed minor fixes. Also apply clang-format.
Drop redundant `#undef`s, casts, `#endif` comments, includes, drop
intermediate variables, sync include and macro order.
Follow-up to e78b1b3ecc#21153
- INSTALL-CMAKE.md: move `CURL_ENABLE_SMB` to the enable section.
- tests/http/env: rename `tcpdmp` to `tcpdump` to match object variable.
- mbedtls: drop incorrect `mbedTLS 4+` comments.
(features are also supported by 3+, meaning it's always supported.)
- lib1648: rename a variable to match purpose.
- CIPHERS.md: alpha-sort link list.
- replace rare `X''` hex markup with `0x`.
- `IP v4/6` -> `IPv4/6`.
- 'version X.Y' -> 'vX.Y', where sensible.
- 'VX.Y' -> 'vX.Y', where sensible.
- fix indents, casing, newlines, typos.
Closes#21772
gnutls_ocsp_resp_get_single() was called with (void) discarding its
return value, so a failure (e.g. an OCSP response with no
SingleResponse entries) went undetected. The following switch() then
read an uninitialized gnutls_ocsp_cert_status_t, which is undefined
behaviour and could yield GNUTLS_OCSP_CERT_GOOD (0) depending on
stack contents, causing gtls_verify_ocsp_status to return CURLE_OK for
a response that was never successfully parsed.
Fix by initializing status to GNUTLS_OCSP_CERT_UNKNOWN and treating a
negative return from gnutls_ocsp_resp_get_single as an error.
Closes#21679
This patch adds two major proxy capabilities to curl (ngtcp2 QUIC):
- HTTP/3 Proxy CONNECT: Tunnel HTTP/1.1 or HTTP/2 traffic through an
HTTPS proxy that speaks HTTP/3 (QUIC) using the standard CONNECT
method over an HTTP/3 connection.
- MASQUE CONNECT-UDP: Tunnel HTTP/3 (QUIC) traffic through an HTTP
proxy (speaking HTTP/1.1, HTTP/2, or HTTP/3) using the extended
CONNECT method with the CONNECT-UDP protocol (RFC9297 & RFC9298).
Public API additions:
- `CURLPROXY_HTTPS3`: new proxy type constant for HTTP/3 proxy
- `--proxy-http3`: new CLI flag to negotiate HTTP/3 with HTTPS proxy
The implementation adds two new filters:
- `H3-PROXY` - enables negotiating HTTP/3 (QUIC) to the proxy and
running CONNECT/CONNECT-UDP through that proxy transport.
- `CAPSULE` - dedicated filter inserted between QUIC transport and
HTTP-PROXY to handle datagram capsule encapsulation/decapsulation.
Here is how the curl filter chaining looks in different scenarios:
- HTTP/3 Proxy CONNECT (tunneling TCP protocols over QUIC proxy):
conn -> HTTP/1.1 or HTTP/2 -> SSL -> HTTP-PROXY ->
H3-PROXY -> HAPPY-EYEBALLS -> UDP
- MASQUE CONNECT-UDP (tunneling QUIC over any proxy):
conn -> HTTP/3 -> CAPSULE -> HTTP-PROXY -> H3-PROXY ->
HAPPY-EYEBALLS -> UDP
conn -> HTTP/3 -> CAPSULE -> HTTP-PROXY -> H1-PROXY or H2-PROXY ->
SSL -> HAPPY-EYEBALLS -> TCP
- Both features currently require the ngtcp2 QUIC backend.
- Both features are experimental (disabled by default). Enable with
`--enable-proxy-http3`(autotools) or `-DUSE_PROXY_HTTP3=ON`(CMake).
Tests:
- tests/unit/unit3400.c: Unit tests for capsule protocol encode/decode
- tests/http/test_60_h3_proxy.py: Comprehensive pytest integration suite
- tests/http/testenv/h2o.py: Managing h2o instances with HTTP/1.1, HTTP/2,
and HTTP/3 (QUIC) listeners, proxy.connect and proxy.connect-udp enabled.
References:
RFC 9297 - HTTP Datagrams and the Capsule Protocol
RFC 9298 - Proxying UDP in HTTP
RFC 9000 §16 — Variable-Length Integer Encoding
Signed-off-by: Aritra Basu <aritrbas+gh@cisco.com>
Closes#21153
Since all API features we need for TLSv1.3 earlydata support do exist
only from version 3.7.2 onwards, make that the minimal version required.
Fixes#21750
Reported-by: Johannes Schlatow
Closes#21751
- Fix revoke_best_effort reading wrong ssl config.
Prior to this change the revoke_best_effort setting for the proxy was
wrongly ignored in favor of the same setting for the destination host.
In other words, CURLSSLOPT_REVOKE_BEST_EFFORT set via
CURLOPT_PROXY_SSL_OPTIONS did not apply to the proxy and
CURLSSLOPT_REVOKE_BEST_EFFORT set via CURLOPT_SSL_OPTIONS wrongly
applied to the proxy.
Closes https://github.com/curl/curl/pull/21683
cert_type, key, key_type, key_passwd and key_blob lived in
ssl_config_data but not in ssl_primary_config, so they were invisible to
match_ssl_primary_config() and to the TLS session cache peer key.
Two easy handles sharing a connection pool could reuse each other's
authenticated connections when they differed only on SSLKEY, SSLKEYTYPE,
KEYPASSWD, SSLCERTTYPE or SSLKEYBLOB. The second handle would silently
inherit the first handle's authenticated identity.
Promote all five fields into ssl_primary_config so the conn-reuse
predicate and session cache key cover the complete client credential
set. Also replace the fixed ":CCERT" session cache marker with the
actual clientcert path so sessions are not shared across different
client certificates.
Verified by test 3303 and 3304
Reported-By: Joshua Rogers (AISLE Research)
Closes#21667
Both are filesystem paths (or case-sensitive hash strings for
pinned_key). curl_strequal is case-insensitive and would treat
/etc/ssl/Crl.pem and /etc/ssl/crl.pem as the same file, unlike the other
path fields (CApath, CAfile, issuercert, clientcert) which already use
Curl_safecmp.
Closes#21668