aboutsummaryrefslograw-logtreecommitdiffstats
diff options
context:
space:
mode:
authorlexiforest <45119583+lexiforest@users.noreply.github.com>2026-09-03 10:40:56 +0100
committerGitHub <noreply@github.com>2026-09-03 10:40:56 +0100
commita57afdb61b3e27ba8c1b461cc9ec3568674ed8ed (patch) (diff)
tree0205d3dba4680276d4740a858c00e881e103f01a
downloadcurl-impersonate-main.tar.gz
 
previous commita389715b26d064dfcf32b18b7a1d3eb753995a76 (Add version info to curl help)
Merge curl 8.22.0 (#309) HEADmain
-rw-r--r--CMakeLists.txt[diff] [file]4
-rw-r--r--docs/api.rst[diff] [file]9
-rw-r--r--patches/curl.patch[diff] [file]1343
3 files changed, 652 insertions, 704 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8a14d29..eba868f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,8 +40,8 @@ set(ZLIB_VERSION "1.3.1")
set(ZLIB_URL_HASH "SHA256=9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23")
set(ZSTD_VERSION "1.5.7")
set(ZSTD_URL_HASH "SHA256=eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3")
-set(CURL_VERSION "curl-8_21_0")
-set(CURL_URL_HASH "SHA256=ec753aa6f408a3ca9f0d6d5f7a77417aecd1544db13c03ae5d443612bf367364")
+set(CURL_VERSION "curl-8_22_0")
+set(CURL_URL_HASH "SHA256=222c6b5c1f368ac63aed59bce2774eb5def9e8e67e46e800be182e684d2845a3")
set(CURL_IMPERSONATE_VERSION "" CACHE STRING
"Override the curl-impersonate version (defaults to an exact clean Git tag or local)")
diff --git a/docs/api.rst b/docs/api.rst
index f9ed4f9..02f775d 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -88,6 +88,15 @@ TLS
Controls Firefox-style delegated credentials. e.g. ``ecdsa_secp256r1_sha256:ecdsa_secp384r1_sha384:ecdsa_secp521r1_sha512:ecdsa_sha1``
Command line: ``--tls-delegated-credentials <value>``.
+``CURLOPT_TLS_TRUST_ANCHORS`` (string)
+ Advertises requested trust anchor identifiers in the TLS ClientHello. The value is a
+ comma-separated list of relative OIDs in dotted-decimal notation, relative to the
+ ``1.3.6.1.4.1`` private-enterprise prefix. For example, ``32473.1,32473.2``. Spaces
+ and tabs around each identifier are ignored, and the identifiers are sent in random
+ order. An empty string advertises support without requesting a specific trust anchor.
+ This option does not change certificate verification or the local CA trust store.
+ Command line: ``--tls-trust-anchors <OID list>``.
+
``CURLOPT_TLS_RECORD_SIZE_LIMIT`` (long)
Controls Firefox-style TLS record size limit behavior. The typical value is ``16385``
Command line: ``--tls-record-size-limit <integer>``.
diff --git a/patches/curl.patch b/patches/curl.patch
index b8ba032..27e0df7 100644
--- a/patches/curl.patch
+++ b/patches/curl.patch
@@ -1,6 +1,6 @@
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
-index 0000000000..b2b73e37f7
+index 0000000000..d8a40d611a
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,104 @@
@@ -24,11 +24,11 @@ index 0000000000..b2b73e37f7
+- nghttp3, ../nghttp3
+- curl-impersonate, ../curl-impersonate
+
-+## Fork Delta (vs `curl-8_21_0`)
-+Baseline check: `git diff --stat curl-8_21_0`.
-+Current delta: **72 files changed, +7788/-462**.
++## Fork Delta (vs `curl-8_22_0`)
++Baseline check: `git diff --stat curl-8_22_0`.
++Current delta: **85 files changed, +8640/-487**.
+
-+- Impersonation core: `lib/impersonate.c` + `lib/impersonate.h` with 38 preset targets (Chrome/Edge/Firefox/Safari/Tor/OkHttp variants).
++- Impersonation core: `lib/impersonate.c` + `lib/impersonate.h` with 39 preset targets (Chrome/Edge/Firefox/Safari/Tor/OkHttp variants).
+- Public API additions: `curl_easy_impersonate()` and new `CURLOPT_*` for TLS/HTTP2 fingerprints (`CURLOPT_IMPERSONATE`, `CURLOPT_HTTPBASEHEADER`, `CURLOPT_HTTP2_SETTINGS`, `CURLOPT_TLS_EXTENSION_ORDER`, etc.).
+- Tooling additions: `curl-impersonate` and tuning flags such as `--impersonate`, `--http2-pseudo-headers-order`, `--tls-permute-extensions`, and `--proxy-credential-no-reuse`.
+- Network behavior changes: HTTP/2 priority/pseudo-header ordering, browser-style header merge, WebSocket impersonation, HTTP/3 fingerprint switching, and QUIC-over-SOCKS5 UDP ASSOCIATE (`socks5h` included).
@@ -109,12 +109,12 @@ index 0000000000..b2b73e37f7
+ behavior; ordinary option application belongs in `config2setopts.c`.
+- Keep generated/help option lists in their required alphabetical order.
diff --git a/CMake/Macros.cmake b/CMake/Macros.cmake
-index 953c1c6ee6..1174eb4181 100644
+index 503074a0a0..01c61aa131 100644
--- a/CMake/Macros.cmake
+++ b/CMake/Macros.cmake
@@ -45,7 +45,7 @@ macro(curl_internal_test _curl_test)
${PROJECT_BINARY_DIR}
- "${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c"
+ "${PROJECT_SOURCE_DIR}/CMake/CurlTests.c"
COMPILE_DEFINITIONS "-D${_curl_test}" ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS} ${CMAKE_REQUIRED_DEFINITIONS}
- LINK_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}"
+ LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}
@@ -122,10 +122,10 @@ index 953c1c6ee6..1174eb4181 100644
if(${_curl_test})
set(${_curl_test} 1 CACHE INTERNAL "curl test")
diff --git a/CMakeLists.txt b/CMakeLists.txt
-index e459b3d076..9dbdf8450d 100644
+index 693d93d014..3e5a69b6fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
-@@ -65,6 +65,13 @@ project(CURL
+@@ -66,6 +66,13 @@ project(CURL
VERSION "${_curl_version_sem}"
LANGUAGES C)
@@ -138,8 +138,8 @@ index e459b3d076..9dbdf8450d 100644
+
# CMake does not recognize some targets accurately. Touch up configuration manually as a workaround.
if(WINDOWS_STORE AND MINGW) # MinGW UWP build
- # CMake (as of v3.31.2) gets confused and applies the MSVC rc.exe command-line
-@@ -153,8 +160,8 @@ if(CURL_PATCHSTAMP)
+ # CMake (as of 3.31.2) gets confused and applies the MSVC rc.exe command-line
+@@ -154,8 +161,8 @@ if(CURL_PATCHSTAMP)
set(CURL_PATCHSTAMP "\"${CURL_PATCHSTAMP}\"")
endif()
@@ -150,7 +150,7 @@ index e459b3d076..9dbdf8450d 100644
set_property(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/include")
-@@ -858,9 +865,15 @@ if(CURL_USE_OPENSSL)
+@@ -870,9 +877,15 @@ if(CURL_USE_OPENSSL)
message(WARNING "AWS-LC/BoringSSL requires POSIX Threads.")
endif()
endif()
@@ -169,7 +169,7 @@ index e459b3d076..9dbdf8450d 100644
endif()
endif()
-@@ -2105,7 +2118,7 @@ endif()
+@@ -2115,7 +2128,7 @@ endif()
if(NOT CURL_DISABLE_INSTALL)
@@ -178,7 +178,7 @@ index e459b3d076..9dbdf8450d 100644
set(CC "${CMAKE_C_COMPILER}")
set(CONFIGURE_OPTIONS "")
set(CURLVERSION "${_curl_version}")
-@@ -2303,7 +2316,7 @@ if(NOT CURL_DISABLE_INSTALL)
+@@ -2314,7 +2327,7 @@ if(NOT CURL_DISABLE_INSTALL)
set(ENABLE_STATIC "no")
endif()
@@ -187,7 +187,7 @@ index e459b3d076..9dbdf8450d 100644
# Consumed variables:
# CC
# CONFIGURE_OPTIONS
-@@ -2325,8 +2338,8 @@ if(NOT CURL_DISABLE_INSTALL)
+@@ -2336,8 +2349,8 @@ if(NOT CURL_DISABLE_INSTALL)
# VERSIONNUM
configure_file(
"${PROJECT_SOURCE_DIR}/curl-config.in"
@@ -198,7 +198,7 @@ index e459b3d076..9dbdf8450d 100644
DESTINATION ${CMAKE_INSTALL_BINDIR}
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
-@@ -2463,7 +2476,7 @@ if(NOT CURL_DISABLE_INSTALL)
+@@ -2486,7 +2499,7 @@ if(NOT CURL_DISABLE_INSTALL)
endif()
if(BUILD_CURL_EXE)
@@ -208,17 +208,19 @@ index e459b3d076..9dbdf8450d 100644
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
diff --git a/Makefile.am b/Makefile.am
-index 83fdadf035..c2224a74fe 100644
+index c4e37231ce..6c7c1b2840 100644
--- a/Makefile.am
+++ b/Makefile.am
-@@ -68,13 +68,13 @@ EXTRA_DIST = CHANGES.md COPYING RELEASE-NOTES Dockerfile .clang-tidy.yml .editor
+@@ -75,7 +75,7 @@ EXTRA_DIST = \
DISTCLEANFILES = buildinfo.txt
-bin_SCRIPTS = curl-config
+bin_SCRIPTS = curl-impersonate-config
- SUBDIRS = lib docs src scripts
+ CURL_ETAGS_FILES = \
+ $(srcdir)/include/curl/curl.h \
+@@ -99,7 +99,7 @@ SUBDIRS = lib docs src scripts
DIST_SUBDIRS = $(SUBDIRS) tests projects include docs
pkgconfigdir = $(libdir)/pkgconfig
@@ -228,10 +230,10 @@ index 83fdadf035..c2224a74fe 100644
dist-hook:
rm -rf $(top_builddir)/tests/log
diff --git a/configure.ac b/configure.ac
-index a21847ea66..c39b6f4726 100644
+index 4c4fac2e2b..62ba99591d 100644
--- a/configure.ac
+++ b/configure.ac
-@@ -1631,7 +1631,11 @@ if test "x$OPT_BROTLI" != "xno"; then
+@@ -1630,7 +1630,11 @@ if test "x$OPT_BROTLI" != "xno"; then
CPPFLAGS="$CPPFLAGS $CPP_BROTLI"
LIBS="$LIB_BROTLI $LIBS"
@@ -244,7 +246,7 @@ index a21847ea66..c39b6f4726 100644
AC_CHECK_HEADERS(brotli/decode.h,
curl_brotli_msg="enabled (libbrotlidec)"
-@@ -5447,6 +5451,8 @@ SUPPORT_PROTOCOLS=`echo $SUPPORT_PROTOCOLS | tr ' ' '\012' | sort | tr '\012' '
+@@ -5517,6 +5521,8 @@ SUPPORT_PROTOCOLS=`echo $SUPPORT_PROTOCOLS | tr ' ' '\012' | sort | tr '\012' '
AC_SUBST(SUPPORT_PROTOCOLS)
@@ -253,19 +255,21 @@ index a21847ea66..c39b6f4726 100644
dnl squeeze whitespace out of some variables
squeeze CFLAGS
-@@ -5495,9 +5501,10 @@ AC_CONFIG_FILES([\
- tests/http/Makefile \
+@@ -5567,10 +5573,11 @@ AC_CONFIG_FILES([\
projects/Makefile \
- projects/vms/Makefile \
-- libcurl.pc
-+ libcurl-impersonate.pc:libcurl.pc.in
+ projects/vms/Makefile
])
-AC_CONFIG_FILES([curl-config], [chmod +x curl-config])
+-AC_CONFIG_FILES([libcurl.pc], [
+AC_CONFIG_FILES([curl-impersonate-config:curl-config.in],
+ [chmod +x curl-impersonate-config])
++AC_CONFIG_FILES([libcurl-impersonate.pc:libcurl.pc.in], [
+ dnl strip trailing spaces, duplicate spaces after colon, empty properties
+- "$SED" -e 's/ *$//g' -e 's/^Libs\.private: */Libs.private: /' -e '/^@<:@A-Za-z.@:>@*:$/d' libcurl.pc > libcurl.pc.tmp && mv libcurl.pc.tmp libcurl.pc
++ "$SED" -e 's/ *$//g' -e 's/^Libs\.private: */Libs.private: /' -e '/^@<:@A-Za-z.@:>@*:$/d' libcurl-impersonate.pc > libcurl-impersonate.pc.tmp && mv libcurl-impersonate.pc.tmp libcurl-impersonate.pc
+ ], [SED="$SED"])
AC_OUTPUT
- SUPPORT_PROTOCOLS_LOWER=`echo "$SUPPORT_PROTOCOLS" | tr A-Z a-z`
diff --git a/curl-config.in b/curl-config.in
index a1c8185875..b64f79a926 100644
--- a/curl-config.in
@@ -305,7 +309,7 @@ index 9c02530193..79395d0e55 100644
foreach(_man_misc IN LISTS _man_targets)
diff --git a/docs/Makefile.am b/docs/Makefile.am
-index fdc4511b5c..f0857aaeef 100644
+index d99dffe126..8eb5e22250 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -28,10 +28,10 @@ if BUILD_DOCS
@@ -440,7 +444,7 @@ index 0000000000..c1429c6c01
+CURLE_OK (0) means everything was OK, non-zero means an error occurred, see
+libcurl-errors(3).
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
-index 1eb628b800..fbf28a21e6 100644
+index f0dc077a94..3b8a60e62f 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -71,6 +71,7 @@ man_MANS = \
@@ -452,10 +456,10 @@ index 1eb628b800..fbf28a21e6 100644
CURLINFO_REDIRECT_TIME_T.3 \
CURLINFO_REDIRECT_URL.3 \
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
-index 5bad9a9842..60c8a40b9f 100644
+index 65279d6426..d0bfe91d06 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
-@@ -480,6 +480,7 @@ CURLINFO_PROXYAUTH_USED 8.12.0
+@@ -484,6 +484,7 @@ CURLINFO_PROXYAUTH_USED 8.12.0
CURLINFO_PTR 7.54.1
CURLINFO_QUEUE_TIME_T 8.6.0
CURLINFO_REDIRECT_COUNT 7.9.7
@@ -631,7 +635,7 @@ index 0000000000..b285a0fc9e
+**wcurl-impersonate** is licensed under the curl license
diff --git a/docs/wcurl.md b/docs/wcurl.md
deleted file mode 100644
-index f0ed42baf2..0000000000
+index 4137e98b35..0000000000
--- a/docs/wcurl.md
+++ /dev/null
@@ -1,154 +0,0 @@
@@ -672,8 +676,8 @@ index f0ed42baf2..0000000000
-picks sane defaults.
-
-If you need anything more complex, you can provide any of curl's supported
--parameters via the **--curl-options** option. Beware that you likely should be
--using curl directly if your use case is not covered.
+-parameters via the **--curl-options** option. Beware that you likely should
+-be using curl directly if your use case is not covered.
-
-By default, **wcurl** does:
-
@@ -791,7 +795,7 @@ index f0ed42baf2..0000000000
-**wcurl** is licensed under the curl license
diff --git a/export.sh b/export.sh
new file mode 100755
-index 0000000000..bc1a07122f
+index 0000000000..117cb3c816
--- /dev/null
+++ b/export.sh
@@ -0,0 +1,9 @@
@@ -802,13 +806,13 @@ index 0000000000..bc1a07122f
+# 1. https://github.com/curl/curl/pull/13244/files
+# 2. https://everything.curl.dev/build/windows.html
+
-+git df curl-8_21_0 -- . ':(exclude)tests/**' > chrome.patch
++git df curl-8_22_0 -- . ':(exclude)tests/**' > chrome.patch
+mv chrome.patch ../curl-impersonate/patches/curl.patch
diff --git a/include/curl/curl.h b/include/curl/curl.h
-index 7e59e43c4d..16c997ad25 100644
+index b904e49530..fe267f5831 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
-@@ -185,6 +185,10 @@ typedef enum {
+@@ -187,6 +187,10 @@ typedef enum {
/* Only use the custom method in the first request, always reset in the next */
#define CURLFOLLOW_FIRSTONLY 3L
@@ -819,7 +823,7 @@ index 7e59e43c4d..16c997ad25 100644
struct curl_httppost {
struct curl_httppost *next; /* next entry in the list */
char *name; /* pointer to allocated name */
-@@ -1137,6 +1141,11 @@ typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy,
+@@ -1147,6 +1151,11 @@ typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy,
/* 'long' argument with a set of values/bitmask */
#define CURLOPTTYPE_VALUES CURLOPTTYPE_LONG
@@ -831,9 +835,9 @@ index 7e59e43c4d..16c997ad25 100644
/*
* All CURLOPT_* values.
*/
-@@ -2262,6 +2271,163 @@ typedef enum {
- /* set TLS supported signature algorithms */
- CURLOPT(CURLOPT_SSL_SIGNATURE_ALGORITHMS, CURLOPTTYPE_STRINGPOINT, 328),
+@@ -2288,6 +2297,163 @@ typedef enum {
+ /* Space-separated list of components to sign for HTTP Message Signatures */
+ CURLOPT(CURLOPT_HTTPSIG_HEADERS, CURLOPTTYPE_STRINGPOINT, 332),
+ /* curl-impersonate: The master option for setting an impersonate target.
+ * Impersonation target format is "name[:yes|no]".
@@ -995,7 +999,7 @@ index 7e59e43c4d..16c997ad25 100644
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
-@@ -2996,7 +3162,14 @@ typedef enum {
+@@ -3022,7 +3188,14 @@ typedef enum {
CURLINFO_HTTPAUTH_USED = CURLINFO_LONG + 69,
CURLINFO_PROXYAUTH_USED = CURLINFO_LONG + 70,
CURLINFO_SIZE_DELIVERED = CURLINFO_OFF_T + 71,
@@ -1012,15 +1016,15 @@ index 7e59e43c4d..16c997ad25 100644
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
diff --git a/include/curl/curlver.h b/include/curl/curlver.h
-index 5cc0e27c61..fef56cbc65 100644
+index 98d10c4fc2..6c3087f996 100644
--- a/include/curl/curlver.h
+++ b/include/curl/curlver.h
@@ -32,7 +32,7 @@
/* This is the version number of the libcurl package from which this header
file origins: */
--#define LIBCURL_VERSION "8.21.0-DEV"
-+#define LIBCURL_VERSION "8.21.0-IMPERSONATE"
+-#define LIBCURL_VERSION "8.22.0-DEV"
++#define LIBCURL_VERSION "8.22.0-IMPERSONATE"
/* The numeric version number is also available "in parts" by using these
defines: */
@@ -1047,7 +1051,7 @@ index 197e6e7b92..8e0659ca66 100644
* NAME curl_easy_getinfo()
*
diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h
-index d600c73cdc..86a58c6088 100644
+index f2e4542772..f10923f4d8 100644
--- a/include/curl/typecheck-gcc.h
+++ b/include/curl/typecheck-gcc.h
@@ -428,8 +428,23 @@ CURLWARNING(Wcurl_easy_getinfo_err_curl_off_t,
@@ -1074,7 +1078,7 @@ index d600c73cdc..86a58c6088 100644
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \
(option) == CURLOPT_KEYPASSWD || \
-@@ -546,6 +561,8 @@ CURLWARNING(Wcurl_easy_getinfo_err_curl_off_t,
+@@ -549,6 +564,8 @@ CURLWARNING(Wcurl_easy_getinfo_err_curl_off_t,
#define curlcheck_slist_option(option) \
((option) == CURLOPT_HTTP200ALIASES || \
(option) == CURLOPT_HTTPHEADER || \
@@ -1083,7 +1087,7 @@ index d600c73cdc..86a58c6088 100644
(option) == CURLOPT_MAIL_RCPT || \
(option) == CURLOPT_POSTQUOTE || \
(option) == CURLOPT_PREQUOTE || \
-@@ -574,7 +591,9 @@ CURLWARNING(Wcurl_easy_getinfo_err_curl_off_t,
+@@ -577,7 +594,9 @@ CURLWARNING(Wcurl_easy_getinfo_err_curl_off_t,
/* true if info expects a pointer to struct curl_slist * argument */
#define curlcheck_slist_info(info) \
(((info) == CURLINFO_SSL_ENGINES) || \
@@ -1095,19 +1099,19 @@ index d600c73cdc..86a58c6088 100644
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
#define curlcheck_tlssessioninfo_info(info) \
diff --git a/lib/Makefile.am b/lib/Makefile.am
-index 8a2bd4e68e..593ed1af15 100644
+index 9a3189ce81..2b6c4255a6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
-@@ -32,7 +32,7 @@ EXTRA_DIST = config-mac.h config-os400.h config-riscos.h config-win32.h
- curl_config.h.in $(LIB_RCFILES) libcurl.def $(CMAKE_DIST) Makefile.soname \
- optiontable.pl
+@@ -38,7 +38,7 @@ EXTRA_DIST = \
+ optiontable.pl \
+ $(LIB_RCFILES)
-lib_LTLIBRARIES = libcurl.la
+lib_LTLIBRARIES = libcurl-impersonate.la
if BUILD_UNITTESTS
noinst_LTLIBRARIES = libcurlu.la
-@@ -77,63 +77,63 @@ if USE_UNITY
+@@ -83,63 +83,63 @@ if USE_UNITY
libcurl_unity.c: $(top_srcdir)/scripts/mk-unity.pl $(CSOURCES)
@PERL@ $(top_srcdir)/scripts/mk-unity.pl --include $(CSOURCES) > libcurl_unity.c
@@ -1190,10 +1194,10 @@ index 8a2bd4e68e..593ed1af15 100644
libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS
libcurlu_la_LDFLAGS = -static $(LIBCURL_PC_LIBS_PRIVATE)
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
-index 266ba52af3..54608e8cc2 100644
+index c4e26849aa..a314f155c6 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
-@@ -230,6 +230,7 @@ LIB_CFILES = \
+@@ -243,6 +243,7 @@ LIB_CFILES = \
idn.c \
if2ip.c \
imap.c \
@@ -1202,10 +1206,10 @@ index 266ba52af3..54608e8cc2 100644
llist.c \
macos.c \
diff --git a/lib/cf-ip-happy.c b/lib/cf-ip-happy.c
-index 963ccea94d..2b9691fdcc 100644
+index baca4682f0..f9ca9a36b4 100644
--- a/lib/cf-ip-happy.c
+++ b/lib/cf-ip-happy.c
-@@ -479,14 +479,14 @@ evaluate:
+@@ -477,14 +477,14 @@ evaluate:
CURL_TRC_CF(data, cf, "check for next A address: %s",
ai ? "found" : "none");
}
@@ -1226,7 +1230,7 @@ index 963ccea94d..2b9691fdcc 100644
if(bs->max_concurrent)
cf_ip_ballers_prune(bs, cf, data, bs->max_concurrent - 1);
diff --git a/lib/cf-setup.c b/lib/cf-setup.c
-index 119294a89a..92a9ec411c 100644
+index 2d77b1cb6d..7d105dcd08 100644
--- a/lib/cf-setup.c
+++ b/lib/cf-setup.c
@@ -98,7 +98,7 @@ static CURLcode cf_setup_add_socks(struct Curl_cfilter *cf,
@@ -1265,7 +1269,7 @@ index 119294a89a..92a9ec411c 100644
+ struct Curl_peer *peer =
+ Curl_conn_get_destination(cf->conn, cf->sockindex);
+
-+ result = Curl_cf_quic_insert_after(cf, origin, peer);
++ result = Curl_cf_quic_insert_after(cf, data, origin, peer);
+ if(result) {
+ CURL_TRC_CF(data, cf, "adding QUIC over SOCKS failed -> %d",
+ (int)result);
@@ -1277,10 +1281,10 @@ index 119294a89a..92a9ec411c 100644
#endif /* !CURL_DISABLE_HTTP && USE_HTTP3 && CURL_DISABLE_PROXY */
#ifdef USE_SSL
diff --git a/lib/cf-socket.c b/lib/cf-socket.c
-index 0741f2ba41..8fa6cfa667 100644
+index 870a98ecbd..201d57504e 100644
--- a/lib/cf-socket.c
+++ b/lib/cf-socket.c
-@@ -1126,6 +1126,53 @@ static CURLcode set_remote_ip(struct Curl_cfilter *cf,
+@@ -1135,6 +1135,53 @@ static CURLcode set_remote_ip(struct Curl_cfilter *cf,
return CURLE_OK;
}
@@ -1334,7 +1338,7 @@ index 0741f2ba41..8fa6cfa667 100644
/* to figure out the type of the socket safely, remove the possibly ORed
bits before comparing */
static int cf_socktype(int x)
-@@ -1171,6 +1218,16 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
+@@ -1224,6 +1271,16 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
if(result)
goto out;
@@ -1351,27 +1355,8 @@ index 0741f2ba41..8fa6cfa667 100644
#ifdef USE_IPV6
if(ctx->addr.family == AF_INET6) {
#ifdef USE_WINSOCK
-diff --git a/lib/cfilters.c b/lib/cfilters.c
-index fb1914d133..a0838b3a2a 100644
---- a/lib/cfilters.c
-+++ b/lib/cfilters.c
-@@ -755,11 +755,13 @@ CURLcode Curl_conn_adjust_pollset(struct Curl_easy *data,
- /* During connect time, connection filters may add sockets to the pollset
- * even when the transfer neither wants to send nor receive. And those
- * sockets, when having events, are served.
-- * Once connected however, a transfer that neither wants to send nor receive
-+ * Once connected however and before a shutdown starts,
-+ * a transfer that neither wants to send nor receive
- * will never call the connection filters. Any sockets added by the filters
- * will not change state and POLLIN/POLLOUT events will trigger forever,
- * making us busy loop. See #21671 */
- if(ps->n || !Curl_conn_is_connected(conn, FIRSTSOCKET) ||
-+ Curl_shutdown_started(data, FIRSTSOCKET) ||
- (conn->cfilter[SECONDARYSOCKET] &&
- !Curl_conn_is_connected(conn, SECONDARYSOCKET))) {
- for(i = 0; (i < 2) && !result && conn; ++i) {
diff --git a/lib/cookie.c b/lib/cookie.c
-index 91dc8d5fd0..7c50dd768b 100644
+index 3255668ec7..1a4cc53457 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -44,6 +44,9 @@
@@ -1384,39 +1369,20 @@ index 91dc8d5fd0..7c50dd768b 100644
/* Make sure cookies never expire further away in time than 400 days into the
future. (from RFC6265bis draft-19)
-@@ -980,7 +983,8 @@ CURLcode Curl_cookie_add(
- const char *domain, /* default domain */
- const char *path, /* full path used when this cookie is set, used
- to get default path for the cookie unless set */
-- bool secure) /* TRUE if connection is over secure origin */
-+ bool secure, /* TRUE if connection is over secure origin */
-+ bool record) /* TRUE for cookies received from a server */
- {
- struct Cookie comem;
- struct Cookie *co;
-@@ -1074,6 +1078,12 @@ CURLcode Curl_cookie_add(
+@@ -1092,6 +1095,12 @@ CURLcode Curl_cookie_add(struct Curl_easy *data,
if(co->expires && (co->expires < ci->next_expiration))
ci->next_expiration = co->expires;
-+ if(record) {
++ if(flags & COOKIE_RECORD) {
+ result = record_cookie_change(data, co);
+ if(result)
+ return result;
+ }
+
- if(httpheader)
+ if(flags & COOKIE_HTTPHEADER)
data->req.setcookies++;
-@@ -1177,7 +1187,7 @@ static CURLcode cookie_load(struct Curl_easy *data, const char *file,
- }
-
- result = Curl_cookie_add(data, ci, headerline, TRUE, lineptr, NULL,
-- NULL, TRUE);
-+ NULL, TRUE, FALSE);
- /* File reading cookie failures are not propagated back to the
- caller because there is no way to do that */
- }
-@@ -1496,6 +1506,39 @@ static char *get_netscape_format(const struct Cookie *co)
+@@ -1516,6 +1525,39 @@ static char *get_netscape_format(const struct Cookie *co)
co->value ? co->value : "");
}
@@ -1457,19 +1423,17 @@ index 91dc8d5fd0..7c50dd768b 100644
* cookie_output()
*
diff --git a/lib/cookie.h b/lib/cookie.h
-index b8ef8b8ea1..6a514ef089 100644
+index 973ec09547..434ac302a0 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
-@@ -117,7 +117,8 @@ CURLcode Curl_cookie_add(struct Curl_easy *data,
- const char *lineptr,
- const char *domain,
- const char *path,
-- bool secure) WARN_UNUSED_RESULT;
-+ bool secure,
-+ bool record) WARN_UNUSED_RESULT;
- CURLcode Curl_cookie_getlist(struct Curl_easy *data,
- bool *okay, const char *host,
- struct Curl_llist *list) WARN_UNUSED_RESULT;
+@@ -115,6 +115,7 @@ bool Curl_secure_context(struct Curl_easy *data, const char *host);
+ #define COOKIE_NOEXPIRE (1<<1) /* skip remove_expired() */
+ #define COOKIE_SECURE (1<<2) /* connection is over secure origin */
+ #define COOKIE_NOPSL (1<<3) /* skip PSL check */
++#define COOKIE_RECORD (1<<4) /* record accepted server cookie */
+ #define COOKIE_NOSESSION (1<<6) /* drop session cookies */
+
+ CURLcode Curl_cookie_add(struct Curl_easy *data,
diff --git a/lib/dynhds.c b/lib/dynhds.c
index 097306cec9..e58b4e8c71 100644
--- a/lib/dynhds.c
@@ -1527,10 +1491,10 @@ index d5337eb353..b2fb669979 100644
/**
* Return the n-th header entry or NULL if it does not exist.
diff --git a/lib/easy.c b/lib/easy.c
-index d60bdaed7b..97621e7fa4 100644
+index 04c5a003a0..6e16b66757 100644
--- a/lib/easy.c
+++ b/lib/easy.c
-@@ -70,10 +70,14 @@
+@@ -71,10 +71,14 @@
#include "setopt.h"
#include "http_digest.h"
#include "system_win32.h"
@@ -1545,7 +1509,7 @@ index d60bdaed7b..97621e7fa4 100644
#include "easy_lock.h"
-@@ -323,6 +327,403 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+@@ -330,6 +334,403 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
return rc;
}
@@ -1949,7 +1913,7 @@ index d60bdaed7b..97621e7fa4 100644
/*
* curl_easy_init() is the external interface to alloc, setup and init an
* easy handle that is returned. If anything goes wrong, NULL is returned.
-@@ -331,6 +732,8 @@ CURL *curl_easy_init(void)
+@@ -338,6 +739,8 @@ CURL *curl_easy_init(void)
{
CURLcode result;
struct Curl_easy *data;
@@ -1958,7 +1922,7 @@ index d60bdaed7b..97621e7fa4 100644
/* Make sure we inited the global SSL stuff */
global_init_lock();
-@@ -353,6 +756,30 @@ CURL *curl_easy_init(void)
+@@ -360,6 +763,30 @@ CURL *curl_easy_init(void)
return NULL;
}
@@ -1989,56 +1953,44 @@ index d60bdaed7b..97621e7fa4 100644
return data;
}
-@@ -1027,6 +1454,13 @@ CURL *curl_easy_duphandle(CURL *curl)
- goto fail;
- }
+@@ -1050,6 +1477,13 @@ CURL *curl_easy_duphandle(CURL *curl)
+ goto fail;
+ }
-+ if(data->state.base_headers) {
-+ outcurl->state.base_headers =
-+ Curl_slist_duplicate(data->state.base_headers);
-+ if(!outcurl->state.base_headers)
-+ goto fail;
-+ }
-+
- /* Reinitialize an SSL engine for the new handle
- * note: the engine name has already been copied by dupset */
- if(outcurl->set.str[STRING_SSL_ENGINE]) {
-@@ -1088,6 +1522,9 @@ fail:
- */
- void curl_easy_reset(CURL *curl)
- {
-+ char *env_target;
-+ char *env_headers;
++ if(data->state.base_headers) {
++ outcurl->state.base_headers =
++ Curl_slist_duplicate(data->state.base_headers);
++ if(!outcurl->state.base_headers)
++ goto fail;
++ }
+
- struct Curl_easy *data = curl;
- if(!GOOD_EASY_HANDLE(data))
- return;
-@@ -1120,6 +1557,23 @@ void curl_easy_reset(CURL *curl)
- Curl_http_auth_cleanup_digest(data);
+ /* Reinitialize an SSL engine for the new handle
+ * note: the engine name has already been copied by dupset */
+ str = CURL_EASY_STR(outcurl, STRING_SSL_ENGINE);
+@@ -1145,6 +1579,21 @@ void curl_easy_reset(CURL *curl)
+ Curl_http_auth_cleanup_digest(data);
#endif
- data->master_mid = UINT32_MAX;
-+ /*
-+ * curl-impersonate: Hook into curl_easy_reset() to set the required options
-+ * from an environment variable, just like in curl_easy_init().
-+ */
-+ env_target = curl_getenv("CURL_IMPERSONATE");
-+ if(env_target) {
-+ env_headers = curl_getenv("CURL_IMPERSONATE_HEADERS");
-+ if(env_headers) {
-+ curl_easy_impersonate(data, env_target,
-+ !curl_strequal(env_headers, "no"));
-+ curlx_free(env_headers);
-+ }
-+ else {
-+ curl_easy_impersonate(data, env_target, TRUE);
+ data->master_mid = UINT32_MAX;
++ /* Apply environment-selected impersonation after restoring defaults. */
++ {
++ char *env_target = curl_getenv("CURL_IMPERSONATE");
++ if(env_target) {
++ char *env_headers = curl_getenv("CURL_IMPERSONATE_HEADERS");
++ if(env_headers) {
++ (void)curl_easy_impersonate(data, env_target,
++ !curl_strequal(env_headers, "no"));
++ curlx_free(env_headers);
++ }
++ else
++ (void)curl_easy_impersonate(data, env_target, TRUE);
++ curlx_free(env_target);
++ }
+ }
-+ curlx_free(env_target);
-+ }
+ }
+ CURL_EAPI_LEAVE(&guard);
}
-
- /*
diff --git a/lib/easyoptions.c b/lib/easyoptions.c
-index 4c0b4f0ce4..d8341e62a1 100644
+index 1643ec3256..c245d1f3bb 100644
--- a/lib/easyoptions.c
+++ b/lib/easyoptions.c
@@ -99,6 +99,7 @@ const struct curl_easyoption Curl_easyopts[] = {
@@ -2078,8 +2030,8 @@ index 4c0b4f0ce4..d8341e62a1 100644
+ { "HTTPHEADER_ORDER", CURLOPT_HTTPHEADER_ORDER, CURLOT_STRING, 0 },
{ "HTTPPOST", CURLOPT_HTTPPOST, CURLOT_OBJECT, 0 },
{ "HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL, CURLOT_LONG, 0 },
- { "HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING, CURLOT_LONG, 0 },
-@@ -145,6 +166,7 @@ const struct curl_easyoption Curl_easyopts[] = {
+ { "HTTPSIG_ALGORITHM", CURLOPT_HTTPSIG_ALGORITHM, CURLOT_VALUES, 0 },
+@@ -149,6 +170,7 @@ const struct curl_easyoption Curl_easyopts[] = {
CURLOT_LONG, 0 },
{ "HTTP_VERSION", CURLOPT_HTTP_VERSION, CURLOT_VALUES, 0 },
{ "IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH, CURLOT_LONG, 0 },
@@ -2087,7 +2039,7 @@ index 4c0b4f0ce4..d8341e62a1 100644
{ "INFILE", CURLOPT_READDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS },
{ "INFILESIZE", CURLOPT_INFILESIZE, CURLOT_LONG, 0 },
{ "INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE, CURLOT_OFF_T, 0 },
-@@ -223,6 +245,8 @@ const struct curl_easyoption Curl_easyopts[] = {
+@@ -227,6 +249,8 @@ const struct curl_easyoption Curl_easyopts[] = {
{ "PROXY_CAINFO", CURLOPT_PROXY_CAINFO, CURLOT_STRING, 0 },
{ "PROXY_CAINFO_BLOB", CURLOPT_PROXY_CAINFO_BLOB, CURLOT_BLOB, 0 },
{ "PROXY_CAPATH", CURLOPT_PROXY_CAPATH, CURLOT_STRING, 0 },
@@ -2096,7 +2048,7 @@ index 4c0b4f0ce4..d8341e62a1 100644
{ "PROXY_CRLFILE", CURLOPT_PROXY_CRLFILE, CURLOT_STRING, 0 },
{ "PROXY_ISSUERCERT", CURLOPT_PROXY_ISSUERCERT, CURLOT_STRING, 0 },
{ "PROXY_ISSUERCERT_BLOB", CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOT_BLOB, 0 },
-@@ -251,6 +275,9 @@ const struct curl_easyoption Curl_easyopts[] = {
+@@ -255,6 +279,9 @@ const struct curl_easyoption Curl_easyopts[] = {
{ "PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE, CURLOT_LONG, 0 },
{ "PUT", CURLOPT_PUT, CURLOT_LONG, 0 },
{ "QUICK_EXIT", CURLOPT_QUICK_EXIT, CURLOT_LONG, 0 },
@@ -2106,7 +2058,7 @@ index 4c0b4f0ce4..d8341e62a1 100644
{ "QUOTE", CURLOPT_QUOTE, CURLOT_SLIST, 0 },
{ "RANDOM_FILE", CURLOPT_RANDOM_FILE, CURLOT_STRING, 0 },
{ "RANGE", CURLOPT_RANGE, CURLOT_STRING, 0 },
-@@ -289,6 +316,7 @@ const struct curl_easyoption Curl_easyopts[] = {
+@@ -293,6 +320,7 @@ const struct curl_easyoption Curl_easyopts[] = {
{ "SOCKS5_GSSAPI_NEC", CURLOPT_SOCKS5_GSSAPI_NEC, CURLOT_LONG, 0 },
{ "SOCKS5_GSSAPI_SERVICE", CURLOPT_SOCKS5_GSSAPI_SERVICE,
CURLOT_STRING, 0 },
@@ -2114,7 +2066,7 @@ index 4c0b4f0ce4..d8341e62a1 100644
{ "SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES, CURLOT_VALUES, 0 },
{ "SSH_COMPRESSION", CURLOPT_SSH_COMPRESSION, CURLOT_LONG, 0 },
{ "SSH_HOSTKEYDATA", CURLOPT_SSH_HOSTKEYDATA, CURLOT_CBPTR, 0 },
-@@ -313,23 +341,30 @@ const struct curl_easyoption Curl_easyopts[] = {
+@@ -317,23 +345,30 @@ const struct curl_easyoption Curl_easyopts[] = {
{ "SSLKEYTYPE", CURLOPT_SSLKEYTYPE, CURLOT_STRING, 0 },
{ "SSLKEY_BLOB", CURLOPT_SSLKEY_BLOB, CURLOT_BLOB, 0 },
{ "SSLVERSION", CURLOPT_SSLVERSION, CURLOT_VALUES, 0 },
@@ -2145,7 +2097,7 @@ index 4c0b4f0ce4..d8341e62a1 100644
{ "STREAM_WEIGHT", CURLOPT_STREAM_WEIGHT, CURLOT_LONG, 0 },
{ "SUPPRESS_CONNECT_HEADERS", CURLOPT_SUPPRESS_CONNECT_HEADERS,
CURLOT_LONG, 0 },
-@@ -351,6 +386,20 @@ const struct curl_easyoption Curl_easyopts[] = {
+@@ -355,6 +390,20 @@ const struct curl_easyoption Curl_easyopts[] = {
{ "TLSAUTH_PASSWORD", CURLOPT_TLSAUTH_PASSWORD, CURLOT_STRING, 0 },
{ "TLSAUTH_TYPE", CURLOPT_TLSAUTH_TYPE, CURLOT_STRING, 0 },
{ "TLSAUTH_USERNAME", CURLOPT_TLSAUTH_USERNAME, CURLOT_STRING, 0 },
@@ -2166,7 +2118,7 @@ index 4c0b4f0ce4..d8341e62a1 100644
{ "TRAILERDATA", CURLOPT_TRAILERDATA, CURLOT_CBPTR, 0 },
{ "TRAILERFUNCTION", CURLOPT_TRAILERFUNCTION, CURLOT_FUNCTION, 0 },
{ "TRANSFERTEXT", CURLOPT_TRANSFERTEXT, CURLOT_LONG, 0 },
-@@ -371,7 +420,12 @@ const struct curl_easyoption Curl_easyopts[] = {
+@@ -375,7 +424,12 @@ const struct curl_easyoption Curl_easyopts[] = {
{ "WRITEDATA", CURLOPT_WRITEDATA, CURLOT_CBPTR, 0 },
{ "WRITEFUNCTION", CURLOPT_WRITEFUNCTION, CURLOT_FUNCTION, 0 },
{ "WRITEHEADER", CURLOPT_HEADERDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS },
@@ -2179,16 +2131,16 @@ index 4c0b4f0ce4..d8341e62a1 100644
{ "XFERINFODATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, 0 },
{ "XFERINFOFUNCTION", CURLOPT_XFERINFOFUNCTION, CURLOT_FUNCTION, 0 },
{ "XOAUTH2_BEARER", CURLOPT_XOAUTH2_BEARER, CURLOT_STRING, 0 },
-@@ -385,6 +439,6 @@ const struct curl_easyoption Curl_easyopts[] = {
+@@ -389,6 +443,6 @@ const struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
-- return (CURLOPT_LASTENTRY % 10000) != (328 + 1);
+- return (CURLOPT_LASTENTRY % 10000) != (332 + 1);
+ return (CURLOPT_LASTENTRY % 10000) != (1040 + 1);
}
#endif
diff --git a/lib/getinfo.c b/lib/getinfo.c
-index fde4aa4ef2..18dd6ec953 100644
+index 23f1de270c..696d25a7fb 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -29,8 +29,39 @@
@@ -2231,7 +2183,7 @@ index fde4aa4ef2..18dd6ec953 100644
/*
* Initialize statistical and informational data.
*
-@@ -69,6 +100,10 @@ void Curl_initinfo(struct Curl_easy *data)
+@@ -63,6 +94,10 @@ void Curl_initinfo(struct Curl_easy *data)
curlx_safefree(info->contenttype);
curlx_safefree(info->wouldredirect);
@@ -2242,7 +2194,7 @@ index fde4aa4ef2..18dd6ec953 100644
memset(&info->primary, 0, sizeof(info->primary));
info->retry_after = 0;
-@@ -575,12 +610,22 @@ static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
+@@ -568,12 +603,22 @@ static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
case CURLINFO_COOKIELIST:
*param_slistp = Curl_cookie_list(data);
break;
@@ -2279,7 +2231,7 @@ index f5efe4185c..0b7ccc509f 100644
#endif /* HEADER_CURL_GETINFO_H */
diff --git a/lib/http.c b/lib/http.c
-index 83d0e01152..383105f239 100644
+index 4b79b2ab93..145e34b68a 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -48,6 +48,7 @@
@@ -2302,7 +2254,7 @@ index 83d0e01152..383105f239 100644
void Curl_http_neg_init(struct Curl_easy *data, struct http_negotiation *neg)
{
memset(neg, 0, sizeof(*neg));
-@@ -1268,6 +1270,17 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
+@@ -1299,6 +1301,17 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
return CURLE_OK;
}
@@ -2320,7 +2272,7 @@ index 83d0e01152..383105f239 100644
if(disallowport)
data->state.allow_port = FALSE;
-@@ -1726,6 +1739,17 @@ static const char *get_http_string(int httpversion)
+@@ -1762,6 +1775,17 @@ static const char *get_http_string(int httpversion)
}
}
@@ -2338,7 +2290,7 @@ index 83d0e01152..383105f239 100644
CURLcode Curl_add_custom_headers(struct Curl_easy *data,
bool is_connect, int httpversion,
struct dynbuf *req)
-@@ -1735,6 +1759,12 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
+@@ -1771,6 +1795,12 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
int numlists = 1; /* by default */
int i;
@@ -2351,7 +2303,7 @@ index 83d0e01152..383105f239 100644
#ifndef CURL_DISABLE_PROXY
enum Curl_proxy_use proxy;
-@@ -1745,10 +1775,11 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
+@@ -1781,10 +1811,11 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
switch(proxy) {
case HEADER_SERVER:
@@ -2365,7 +2317,7 @@ index 83d0e01152..383105f239 100644
if(data->set.sep_headers) {
h[1] = data->set.proxyheaders;
numlists++;
-@@ -1758,7 +1789,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
+@@ -1794,7 +1825,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
if(data->set.sep_headers)
h[0] = data->set.proxyheaders;
else
@@ -2374,7 +2326,7 @@ index 83d0e01152..383105f239 100644
break;
case HEADER_CONNECT_UDP:
if(data->set.sep_headers)
-@@ -1769,7 +1800,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
+@@ -1805,7 +1836,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
}
#else
(void)is_connect;
@@ -2383,7 +2335,7 @@ index 83d0e01152..383105f239 100644
#endif
/* loop through one or two lists */
-@@ -1829,6 +1860,12 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
+@@ -1872,6 +1903,12 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
else if(curlx_str_casecompare(&name, "Connection"))
/* Connection headers are handled specially */
;
@@ -2396,7 +2348,7 @@ index 83d0e01152..383105f239 100644
else if((httpversion >= 20) &&
curlx_str_casecompare(&name, "Transfer-Encoding"))
/* HTTP/2 does not support chunked requests */
-@@ -1979,6 +2016,110 @@ void Curl_http_method(struct Curl_easy *data,
+@@ -2024,6 +2061,110 @@ void Curl_http_method(struct Curl_easy *data,
*reqp = httpreq;
}
@@ -2457,10 +2409,10 @@ index 83d0e01152..383105f239 100644
+ * CURLOPT_HTTPHEADER, take it from there instead. */
+ if(!found &&
+ curl_strnequal(head->data, "User-Agent", prefix_len) &&
-+ data->set.str[STRING_USERAGENT] &&
-+ *data->set.str[STRING_USERAGENT]) {
++ CURL_EASY_STR(data, STRING_USERAGENT) &&
++ *CURL_EASY_STR(data, STRING_USERAGENT)) {
+ uagent = curl_maprintf("User-Agent: %s",
-+ data->set.str[STRING_USERAGENT]);
++ CURL_EASY_STR(data, STRING_USERAGENT));
+ if(!uagent) {
+ ret = CURLE_OUT_OF_MEMORY;
+ goto fail;
@@ -2504,59 +2456,23 @@ index 83d0e01152..383105f239 100644
+}
+
+
- static CURLcode http_useragent(struct Curl_easy *data)
+ static CURLcode http_set_aptr_host(struct Curl_easy *data)
{
- /* The User-Agent string might have been allocated already, because
-@@ -2005,45 +2146,10 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data)
- if(ptr &&
- (!data->state.this_is_a_follow ||
- Curl_peer_equal(data->state.initial_origin, data->state.origin))) {
--#ifndef CURL_DISABLE_COOKIES
-- /* If we have a given custom Host: header, we extract the hostname in
-- order to possibly use it for cookie reasons later on. We only allow the
-- custom Host: header if this is NOT a redirect, as setting Host: in the
-- redirected request is being out on thin ice. Except if the hostname
-- is the same as the first one! */
-- char *cookiehost;
-- CURLcode result = copy_custom_value(ptr, &cookiehost);
-- if(result)
-- return result;
-- if(!*cookiehost)
-- /* ignore empty data */
-- curlx_free(cookiehost);
-- else {
-- /* If the host begins with '[', we start searching for the port after
-- the bracket has been closed */
-- if(*cookiehost == '[') {
-- char *closingbracket;
-- /* since the 'cookiehost' is an allocated memory area that will be
-- freed later we cannot increment the pointer */
-- memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
-- closingbracket = strchr(cookiehost, ']');
-- if(closingbracket)
-- *closingbracket = 0;
-- }
-- else {
-- int startsearch = 0;
-- char *colon = strchr(cookiehost + startsearch, ':');
-- if(colon)
-- *colon = 0; /* The host must not include an embedded port number */
-- }
-- data->req.cookiehost = cookiehost;
-- }
--#endif
--
+ struct connectdata *conn = data->conn;
+@@ -2074,9 +2215,9 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data)
+ #endif
+
if(!curl_strequal("Host:", ptr)) {
-- aptr->host = curl_maprintf("Host:%s\r\n", &ptr[5]);
-- if(!aptr->host)
+- data->state.http_host = curl_maprintf("Host:%s", &ptr[5]);
+- if(!data->state.http_host)
- return CURLE_OUT_OF_MEMORY;
+ /* Emit custom Host with the other user headers to preserve order.
+ Cookies continue to match the URL origin. */
-+ aptr->host = NULL;
++ data->state.http_host = NULL;
}
}
else {
-@@ -2448,6 +2554,231 @@ static CURLcode addexpect(struct Curl_easy *data, struct dynbuf *r,
+@@ -2492,6 +2633,231 @@ static CURLcode addexpect(struct Curl_easy *data, struct dynbuf *r,
return CURLE_OK;
}
@@ -2694,7 +2610,7 @@ index 83d0e01152..383105f239 100644
+static CURLcode http_req_apply_header_order(struct Curl_easy *data,
+ struct dynbuf *r)
+{
-+ const char *order = data->set.str[STRING_HTTPHEADER_ORDER];
++ const char *order = CURL_EASY_STR(data, STRING_HTTPHEADER_ORDER);
+ struct http_hdr_line *lines = NULL;
+ struct dynbuf out;
+ struct dynbuf old;
@@ -2710,12 +2626,12 @@ index 83d0e01152..383105f239 100644
+
+ if(data->conn && data->conn->scheme &&
+ (data->conn->scheme->protocol & (CURLPROTO_WS | CURLPROTO_WSS)) &&
-+ data->set.str[STRING_WS_HTTPHEADER_ORDER])
-+ order = data->set.str[STRING_WS_HTTPHEADER_ORDER];
++ CURL_EASY_STR(data, STRING_WS_HTTPHEADER_ORDER))
++ order = CURL_EASY_STR(data, STRING_WS_HTTPHEADER_ORDER);
+ else if(data->conn &&
+ (Curl_conn_http_version(data, data->conn) == 30) &&
-+ data->set.str[STRING_HTTP3_HTTPHEADER_ORDER])
-+ order = data->set.str[STRING_HTTP3_HTTPHEADER_ORDER];
++ CURL_EASY_STR(data, STRING_HTTP3_HTTPHEADER_ORDER))
++ order = CURL_EASY_STR(data, STRING_HTTP3_HTTPHEADER_ORDER);
+
+ if(!order)
+ return CURLE_OK;
@@ -2788,16 +2704,16 @@ index 83d0e01152..383105f239 100644
static CURLcode http_add_content_hds(struct Curl_easy *data,
struct dynbuf *r,
int httpversion,
-@@ -2535,6 +2866,8 @@ static CURLcode http_cookies(struct Curl_easy *data,
+@@ -2579,6 +2945,8 @@ static CURLcode http_cookies(struct Curl_easy *data,
CURLcode result = CURLE_OK;
- char *addcookies = NULL;
+ const char *addcookies = NULL;
bool linecap = FALSE;
+ bool split = data->set.split_cookies &&
+ (Curl_conn_http_version(data, data->conn) >= 20);
- if(data->set.str[STRING_COOKIE] &&
+ if(CURL_EASY_STR(data, STRING_COOKIE) &&
!Curl_checkheaders(data, STRCONST("Cookie")) &&
Curl_auth_allowed_to_host(data))
-@@ -2559,6 +2892,22 @@ static CURLcode http_cookies(struct Curl_easy *data,
+@@ -2603,6 +2971,22 @@ static CURLcode http_cookies(struct Curl_easy *data,
struct Cookie *co = Curl_node_elem(n);
if(co->value) {
size_t add;
@@ -2820,7 +2736,7 @@ index 83d0e01152..383105f239 100644
if(!count) {
result = curlx_dyn_addn(r, STRCONST("Cookie: "));
if(result)
-@@ -2583,7 +2932,32 @@ static CURLcode http_cookies(struct Curl_easy *data,
+@@ -2627,7 +3011,32 @@ static CURLcode http_cookies(struct Curl_easy *data,
}
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
@@ -2854,7 +2770,7 @@ index 83d0e01152..383105f239 100644
if(!count)
result = curlx_dyn_addn(r, STRCONST("Cookie: "));
if(!result) {
-@@ -2591,7 +2965,7 @@ static CURLcode http_cookies(struct Curl_easy *data,
+@@ -2635,7 +3044,7 @@ static CURLcode http_cookies(struct Curl_easy *data,
count++;
}
}
@@ -2863,8 +2779,26 @@ index 83d0e01152..383105f239 100644
result = curlx_dyn_addn(r, STRCONST("\r\n"));
if(result)
-@@ -2919,8 +3293,7 @@ static CURLcode http_add_hd(struct Curl_easy *data,
- break;
+@@ -2827,7 +3236,7 @@ static CURLcode http_add_connection_hd(struct Curl_easy *data,
+ bool skip;
+
+ /* Add the 1st custom "Connection: " header, if there is one */
+- for(head = data->set.headers; head; head = head->next) {
++ for(head = Curl_http_request_headers(data); head; head = head->next) {
+ if(curl_strnequal(head->data, "Connection", 10) &&
+ Curl_headersep(head->data[10]) &&
+ !http_header_is_empty(head->data)) {
+@@ -2861,7 +3270,7 @@ static CURLcode http_add_connection_hd(struct Curl_easy *data,
+
+ /* Add all user-defined Connection: headers after the first */
+ skip = TRUE;
+- for(head = data->set.headers; head; head = head->next) {
++ for(head = Curl_http_request_headers(data); head; head = head->next) {
+ if(curl_strnequal(head->data, "Connection", 10) &&
+ Curl_headersep(head->data[10]) &&
+ !http_header_is_empty(head->data)) {
+@@ -2966,8 +3375,7 @@ static CURLcode http_add_hd(struct Curl_easy *data,
+ }
case H1_HD_ACCEPT:
- if(!Curl_checkheaders(data, STRCONST("Accept")))
@@ -2873,7 +2807,7 @@ index 83d0e01152..383105f239 100644
break;
case H1_HD_TE:
-@@ -3058,8 +3431,12 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
+@@ -3103,8 +3511,12 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
/* what kind of request do we need to send? */
Curl_http_method(data, &method, &httpreq);
@@ -2887,7 +2821,7 @@ index 83d0e01152..383105f239 100644
/* setup the authentication headers, how that method and host are known */
if(!result)
result = Curl_http_output_auth(data, data->conn, method, httpreq,
-@@ -3086,6 +3463,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
+@@ -3129,6 +3541,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto out;
}
@@ -2898,16 +2832,17 @@ index 83d0e01152..383105f239 100644
/* setup variables for the upcoming transfer and send */
Curl_xfer_setup_sendrecv(data, FIRSTSOCKET, -1);
result = Curl_req_send(data, &req, httpversion);
-@@ -3541,7 +3922,7 @@ static CURLcode http_header_s(struct Curl_easy *data,
- CURLcode result;
+@@ -3584,7 +4000,8 @@ static CURLcode http_header_s(struct Curl_easy *data,
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
- result = Curl_cookie_add(data, data->cookies, TRUE, FALSE, v, host,
-- data->state.up.path, secure_context);
-+ data->state.up.path, secure_context, TRUE);
+ result = Curl_cookie_add(data, data->cookies, v, host,
+ data->state.up.path,
+- COOKIE_HTTPHEADER | secure_context);
++ COOKIE_HTTPHEADER | COOKIE_RECORD |
++ secure_context);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
return result;
}
-@@ -4920,6 +5301,29 @@ static bool http_TE_has_token(const char *fvalue, const char *token)
+@@ -4963,6 +5380,29 @@ static bool http_TE_has_token(const char *fvalue, const char *token)
return FALSE;
}
@@ -2937,7 +2872,7 @@ index 83d0e01152..383105f239 100644
CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
struct httpreq *req, struct Curl_easy *data)
{
-@@ -4928,6 +5332,10 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
+@@ -4971,6 +5411,10 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
size_t i;
CURLcode result;
@@ -2948,7 +2883,7 @@ index 83d0e01152..383105f239 100644
DEBUGASSERT(req);
DEBUGASSERT(h2_headers);
-@@ -4957,20 +5365,46 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
+@@ -5000,20 +5444,46 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
Curl_dynhds_reset(h2_headers);
Curl_dynhds_set_opts(h2_headers, DYNHDS_OPT_LOWERCASE);
@@ -2960,14 +2895,14 @@ index 83d0e01152..383105f239 100644
+
+ /* curl-impersonate: order of pseudo headers is different from the default */
+ if(data->conn && Curl_conn_http_version(data, data->conn) == 30 &&
-+ data->set.str[STRING_HTTP3_PSEUDO_HEADERS_ORDER]) {
-+ order = data->set.str[STRING_HTTP3_PSEUDO_HEADERS_ORDER];
++ CURL_EASY_STR(data, STRING_HTTP3_PSEUDO_HEADERS_ORDER)) {
++ order = CURL_EASY_STR(data, STRING_HTTP3_PSEUDO_HEADERS_ORDER);
}
- if(!result && authority) {
- result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_AUTHORITY),
- authority, strlen(authority));
-+ else if(data->set.str[STRING_HTTP2_PSEUDO_HEADERS_ORDER]) {
-+ order = data->set.str[STRING_HTTP2_PSEUDO_HEADERS_ORDER];
++ else if(CURL_EASY_STR(data, STRING_HTTP2_PSEUDO_HEADERS_ORDER)) {
++ order = CURL_EASY_STR(data, STRING_HTTP2_PSEUDO_HEADERS_ORDER);
}
- if(!result && req->path) {
- result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_PATH),
@@ -3006,7 +2941,7 @@ index 83d0e01152..383105f239 100644
for(i = 0; !result && i < Curl_dynhds_count(&req->headers); ++i) {
e = Curl_dynhds_getn(&req->headers, i);
/* "TE" is special in that it is only permissible when it
-@@ -4983,6 +5417,8 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
+@@ -5026,6 +5496,8 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
else if(h2_permissible_field(e)) {
result = Curl_dynhds_add(h2_headers, e->name, e->namelen,
e->value, e->valuelen);
@@ -3016,7 +2951,7 @@ index 83d0e01152..383105f239 100644
}
diff --git a/lib/http2.c b/lib/http2.c
-index a820439ef4..f7581b4030 100644
+index 0cfdf20571..5262643d95 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -46,6 +46,7 @@
@@ -3024,10 +2959,10 @@ index a820439ef4..f7581b4030 100644
#include "curlx/dynbuf.h"
#include "headers.h"
+#include "curlx/strdup.h"
+ #include "curl_share.h"
#if NGHTTP2_VERSION_NUM < 0x010f00
- #error "nghttp2 1.15.0 or greater required"
-@@ -63,11 +64,13 @@
+@@ -64,11 +65,13 @@
/* on send into TLS, we want to accumulate small frames */
#define H2_NW_SEND_CHUNKS 1
/* this is how much we want "in flight" for a stream, unthrottled */
@@ -3043,7 +2978,7 @@ index a820439ef4..f7581b4030 100644
#else
#define H2_STREAM_WINDOW_SIZE_INITIAL H2_STREAM_WINDOW_SIZE_MAX
#endif
-@@ -81,9 +84,10 @@
+@@ -82,9 +85,10 @@
* the overall connection. Streams might become PAUSED which will block their
* received QUOTA in the connection window. If we run out of space, the server
* is blocked from sending us any data. See #10988 for an issue with this. */
@@ -3056,7 +2991,7 @@ index a820439ef4..f7581b4030 100644
#define H2_BINSETTINGS_LEN 80
struct cf_h2_ctx {
-@@ -215,17 +219,72 @@ static size_t populate_settings(nghttp2_settings_entry *iv,
+@@ -216,17 +220,72 @@ static size_t populate_settings(nghttp2_settings_entry *iv,
struct Curl_easy *data,
struct cf_h2_ctx *ctx)
{
@@ -3065,7 +3000,7 @@ index a820439ef4..f7581b4030 100644
+ /* curl-impersonate: set the HTTP/2 SETTINGS frame as instructed by the
+ * application. Format example: 1:65536;2:0;4:6291456;6:262144
+ * See https://httpwg.org/specs/rfc7540.html#SETTINGS. */
-+ const char *settings = data->set.str[STRING_HTTP2_SETTINGS];
++ const char *settings = CURL_EASY_STR(data, STRING_HTTP2_SETTINGS);
+ char *copy;
+ char *setting;
+ size_t i = 0;
@@ -3138,7 +3073,7 @@ index a820439ef4..f7581b4030 100644
}
static ssize_t populate_binsettings(uint8_t *binsettings,
-@@ -252,6 +311,101 @@ static CURLcode cf_h2_update_settings(struct cf_h2_ctx *ctx,
+@@ -253,6 +312,101 @@ static CURLcode cf_h2_update_settings(struct cf_h2_ctx *ctx,
return CURLE_OK;
}
@@ -3180,10 +3115,10 @@ index a820439ef4..f7581b4030 100644
+ char *copy;
+ char *stream;
+
-+ if(!data->set.str[STRING_HTTP2_STREAMS])
++ if(!CURL_EASY_STR(data, STRING_HTTP2_STREAMS))
+ return CURLE_OK;
+
-+ copy = curlx_strdup(data->set.str[STRING_HTTP2_STREAMS]);
++ copy = curlx_strdup(CURL_EASY_STR(data, STRING_HTTP2_STREAMS));
+ if(!copy)
+ return CURLE_OUT_OF_MEMORY;
+
@@ -3240,7 +3175,7 @@ index a820439ef4..f7581b4030 100644
#define H2_STREAM_CTX(ctx, data) \
((struct h2_stream_ctx *)( \
(data) ? Curl_uint32_hash_get(&(ctx)->streams, (data)->mid) : NULL))
-@@ -1748,18 +1902,26 @@ out:
+@@ -1754,18 +1908,26 @@ out:
return result;
}
@@ -3255,21 +3190,21 @@ index a820439ef4..f7581b4030 100644
static int sweight_wanted(const struct Curl_easy *data)
{
/* 0 weight is not set by user and we take the nghttp2 default one */
- return data->set.priority.weight ?
-- data->set.priority.weight : NGHTTP2_DEFAULT_WEIGHT;
-+ data->set.priority.weight : CHROME_DEFAULT_STREAM_WEIGHT;
+ return data->set.weight ?
+- data->set.weight : NGHTTP2_DEFAULT_WEIGHT;
++ data->set.weight : CHROME_DEFAULT_STREAM_WEIGHT;
}
static int sweight_in_effect(const struct Curl_easy *data)
{
/* 0 weight is not set by user and we take the nghttp2 default one */
- return data->state.priority.weight ?
-- data->state.priority.weight : NGHTTP2_DEFAULT_WEIGHT;
-+ data->state.priority.weight : CHROME_DEFAULT_STREAM_WEIGHT;
+ return data->state.weight ?
+- data->state.weight : NGHTTP2_DEFAULT_WEIGHT;
++ data->state.weight : CHROME_DEFAULT_STREAM_WEIGHT;
}
/*
-@@ -1768,12 +1930,22 @@ static int sweight_in_effect(const struct Curl_easy *data)
+@@ -1774,12 +1936,23 @@ static int sweight_in_effect(const struct Curl_easy *data)
* struct.
*/
@@ -3282,18 +3217,21 @@ index a820439ef4..f7581b4030 100644
static void h2_pri_spec(struct Curl_easy *data,
nghttp2_priority_spec *pri_spec)
{
- struct Curl_data_priority *prio = &data->set.priority;
-+
+- int prio = data->set.weight;
+- nghttp2_priority_spec_init(pri_spec, 0, sweight_wanted(data), FALSE);
+- data->state.weight = prio;
+ /* curl-impersonate: use the configured exclusive flag from data->set.
+ * The dependency ID can be changed to FIREFOX_DEFAULT_STREAM_DEP for the
+ * legacy Firefox priority path. */
- nghttp2_priority_spec_init(pri_spec, 0,
-- sweight_wanted(data), FALSE);
-+ sweight_wanted(data), prio->exclusive);
- data->state.priority = *prio;
++ nghttp2_priority_spec_init(pri_spec, 0,
++ sweight_wanted(data),
++ data->set.stream_exclusive);
++ data->state.weight = data->set.weight;
++ data->state.stream_exclusive = data->set.stream_exclusive;
}
-@@ -1790,18 +1962,23 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
+ /*
+@@ -1795,18 +1968,23 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
int rv = 0;
@@ -3301,7 +3239,7 @@ index a820439ef4..f7581b4030 100644
if(stream && stream->id > 0 &&
- (sweight_wanted(data) != sweight_in_effect(data))) {
+ ((sweight_wanted(data) != sweight_in_effect(data)) ||
-+ (data->set.priority.exclusive != data->state.priority.exclusive))) {
++ (data->set.stream_exclusive != data->state.stream_exclusive))) {
/* send new weight and/or dependency */
nghttp2_priority_spec pri_spec;
@@ -3324,18 +3262,18 @@ index a820439ef4..f7581b4030 100644
}
ctx->nw_out_blocked = 0;
-@@ -2114,7 +2291,9 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream,
+@@ -2117,7 +2295,9 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream,
/* Check the initial windows size of the transfer (rate-limits?) and
* send an updated settings on changes from previous value. */
initial_win_size = cf_h2_initial_win_size(data);
- if(initial_win_size != ctx->initial_win_size) {
+ /* curl-impersonate: keep an explicitly configured SETTINGS fingerprint. */
-+ if(!data->set.str[STRING_HTTP2_SETTINGS] &&
++ if(!CURL_EASY_STR(data, STRING_HTTP2_SETTINGS) &&
+ (initial_win_size != ctx->initial_win_size)) {
result = cf_h2_update_settings(ctx, initial_win_size);
if(result)
goto out;
-@@ -2127,11 +2306,13 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream,
+@@ -2130,11 +2310,13 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream,
case HTTPREQ_PUT:
data_prd.read_callback = req_body_read_callback;
data_prd.source.ptr = NULL;
@@ -3351,7 +3289,7 @@ index a820439ef4..f7581b4030 100644
NULL, data);
}
-@@ -2466,8 +2647,15 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf,
+@@ -2471,8 +2653,15 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf,
}
}
@@ -3369,7 +3307,7 @@ index a820439ef4..f7581b4030 100644
if(rc) {
failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
nghttp2_strerror(rc), rc);
-@@ -2475,6 +2663,20 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf,
+@@ -2480,6 +2669,20 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf,
goto out;
}
@@ -3391,7 +3329,7 @@ index a820439ef4..f7581b4030 100644
result = CURLE_OK;
CURL_TRC_CF(data, cf, "[0] created h2 session%s",
diff --git a/lib/http2.h b/lib/http2.h
-index e38dc5745c..95921f5a99 100644
+index c3270da1cc..807f0ad6ae 100644
--- a/lib/http2.h
+++ b/lib/http2.h
@@ -29,7 +29,8 @@
@@ -5880,7 +5818,7 @@ index 803f372041..24695366c3 100644
curl_easy_option_by_id
curl_easy_option_by_name
diff --git a/lib/mime.c b/lib/mime.c
-index 077e599e43..6f12cc10c8 100644
+index 6004375765..9aa99f9ebd 100644
--- a/lib/mime.c
+++ b/lib/mime.c
@@ -54,6 +54,61 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
@@ -5892,7 +5830,7 @@ index 077e599e43..6f12cc10c8 100644
+ const char *form_boundary = NULL;
+
+ if(easy)
-+ form_boundary = easy->set.str[STRING_FORM_BOUNDARY];
++ form_boundary = CURL_EASY_STR(easy, STRING_FORM_BOUNDARY);
+
+ if(form_boundary && curl_strequal(form_boundary, "webkit")) {
+ memcpy(mime->boundary, MIME_WEBKIT_BOUNDARY_PREFIX,
@@ -5945,7 +5883,7 @@ index 077e599e43..6f12cc10c8 100644
/* Quoted-printable character class table.
*
* We cannot rely on ctype functions since quoted-printable input data
-@@ -918,6 +973,7 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
+@@ -927,6 +982,7 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
size_t call_depth)
{
curl_mime *mime = (curl_mime *)instream;
@@ -5953,7 +5891,7 @@ index 077e599e43..6f12cc10c8 100644
size_t cursize = 0;
(void)size; /* Always 1 */
-@@ -945,10 +1001,10 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
+@@ -954,10 +1010,10 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
case MIMESTATE_BOUNDARY2:
if(part)
sz = readback_bytes(&mime->state, buffer, nitems, mime->boundary,
@@ -5966,7 +5904,7 @@ index 077e599e43..6f12cc10c8 100644
if(!sz) {
mimesetstate(&mime->state, MIMESTATE_CONTENT, part);
}
-@@ -1202,6 +1258,7 @@ CURLcode Curl_mime_duppart(struct Curl_easy *data,
+@@ -1211,6 +1267,7 @@ CURLcode Curl_mime_duppart(struct Curl_easy *data,
/* Create a mime handle. */
curl_mime *curl_mime_init(void *easy)
{
@@ -5974,7 +5912,7 @@ index 077e599e43..6f12cc10c8 100644
curl_mime *mime = curlx_malloc(sizeof(*mime));
if(mime) {
-@@ -1209,10 +1266,7 @@ curl_mime *curl_mime_init(void *easy)
+@@ -1218,10 +1275,7 @@ curl_mime *curl_mime_init(void *easy)
mime->firstpart = NULL;
mime->lastpart = NULL;
@@ -5986,7 +5924,7 @@ index 077e599e43..6f12cc10c8 100644
/* failed to get random separator, bail out */
curlx_free(mime);
return NULL;
-@@ -1567,7 +1621,7 @@ static curl_off_t multipart_size(curl_mime *mime)
+@@ -1576,7 +1630,7 @@ static curl_off_t multipart_size(curl_mime *mime)
if(!mime)
return 0; /* Not present -> empty. */
@@ -6037,10 +5975,10 @@ index e84f04051b..738b3a8335 100644
#define Curl_creader_set_mime(x, y) ((void)(x), CURLE_NOT_BUILT_IN)
#endif
diff --git a/lib/multi.c b/lib/multi.c
-index d6ae111d8e..0fd71c76b9 100644
+index fbefa6f30d..e7f93877f6 100644
--- a/lib/multi.c
+++ b/lib/multi.c
-@@ -262,7 +262,8 @@ struct Curl_multi *Curl_multi_handle(uint32_t xfer_table_size,
+@@ -265,7 +265,8 @@ struct Curl_multi *Curl_multi_handle(uint32_t xfer_table_size,
Curl_llist_init(&multi->msglist, NULL);
multi->multiplexing = TRUE;
@@ -6051,7 +5989,7 @@ index d6ae111d8e..0fd71c76b9 100644
#ifdef ENABLE_WAKEUP
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
diff --git a/lib/protocol.c b/lib/protocol.c
-index 8d57c058c6..6725bbeaea 100644
+index 3bfcd88ebe..71c753e135 100644
--- a/lib/protocol.c
+++ b/lib/protocol.c
@@ -458,7 +458,7 @@ const struct Curl_scheme Curl_scheme_wss = {
@@ -6064,10 +6002,10 @@ index 8d57c058c6..6725bbeaea 100644
};
diff --git a/lib/setopt.c b/lib/setopt.c
-index eb9ff2e396..7421f08b2e 100644
+index 0e15980b8f..f83d7d0c3a 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
-@@ -46,8 +46,10 @@
+@@ -45,8 +45,10 @@
#include "altsvc.h"
#include "hsts.h"
#include "tftp.h"
@@ -6078,8 +6016,8 @@ index eb9ff2e396..7421f08b2e 100644
#include "bufref.h"
#include "vauth/vauth.h"
-@@ -98,6 +100,95 @@ CURLcode Curl_setstropt(char **charp, const char *s)
- return CURLE_OK;
+@@ -89,6 +91,95 @@ CURLcode Curl_setstropt(struct Curl_easy *data,
+ return CURL_EASY_STR_SET(data, (uint8_t)id, s, slen);
}
+static bool setopt_valid_form_boundary(const char *value)
@@ -6174,7 +6112,7 @@ index eb9ff2e396..7421f08b2e 100644
CURLcode Curl_setblobopt(struct curl_blob **blobp,
const struct curl_blob *blob)
{
-@@ -307,6 +398,9 @@ static CURLcode setopt_HTTP_VERSION(struct Curl_easy *data, long arg)
+@@ -299,6 +390,9 @@ static CURLcode setopt_HTTP_VERSION(struct Curl_easy *data, long arg)
return CURLE_UNSUPPORTED_PROTOCOL;
}
data->set.httpwant = (unsigned char)arg;
@@ -6184,7 +6122,7 @@ index eb9ff2e396..7421f08b2e 100644
return CURLE_OK;
}
#endif /* !CURL_DISABLE_HTTP */
-@@ -343,6 +437,8 @@ CURLcode Curl_setopt_SSLVERSION(struct Curl_easy *data, CURLoption option,
+@@ -335,6 +429,8 @@ CURLcode Curl_setopt_SSLVERSION(struct Curl_easy *data, CURLoption option,
primary->version = (unsigned char)version;
primary->version_max = (unsigned int)version_max;
@@ -6193,7 +6131,7 @@ index eb9ff2e396..7421f08b2e 100644
}
return CURLE_OK;
}
-@@ -499,6 +595,9 @@ static CURLcode setopt_long_bool(struct Curl_easy *data, CURLoption option,
+@@ -455,6 +551,9 @@ static CURLcode setopt_long_bool(struct Curl_easy *data, CURLoption option,
*/
s->cookiesession = enabled;
break;
@@ -6203,7 +6141,7 @@ index eb9ff2e396..7421f08b2e 100644
#endif
case CURLOPT_AUTOREFERER:
/*
-@@ -586,6 +685,9 @@ static CURLcode setopt_long_bool(struct Curl_easy *data, CURLoption option,
+@@ -542,6 +641,9 @@ static CURLcode setopt_long_bool(struct Curl_easy *data, CURLoption option,
*/
s->proxy_transfer_mode = enabled;
break;
@@ -6213,7 +6151,7 @@ index eb9ff2e396..7421f08b2e 100644
#endif /* !CURL_DISABLE_PROXY */
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
case CURLOPT_SOCKS5_GSSAPI_NEC:
-@@ -776,6 +878,36 @@ static CURLcode setopt_long_bool(struct Curl_easy *data, CURLoption option,
+@@ -732,6 +834,36 @@ static CURLcode setopt_long_bool(struct Curl_easy *data, CURLoption option,
case CURLOPT_SSL_ENABLE_ALPN:
s->ssl_enable_alpn = enabled;
break;
@@ -6250,7 +6188,7 @@ index eb9ff2e396..7421f08b2e 100644
case CURLOPT_PATH_AS_IS:
s->path_as_is = enabled;
break;
-@@ -987,6 +1119,15 @@ static CURLcode setopt_long_ssl(struct Curl_easy *data, CURLoption option,
+@@ -943,6 +1075,15 @@ static CURLcode setopt_long_ssl(struct Curl_easy *data, CURLoption option,
#endif
case CURLOPT_SSL_ENABLE_NPN:
break;
@@ -6264,9 +6202,9 @@ index eb9ff2e396..7421f08b2e 100644
+ s->tls_use_new_alps_codepoint = !!arg;
+ break;
case CURLOPT_SSLENGINE_DEFAULT:
- curlx_safefree(s->str[STRING_SSL_ENGINE]);
+ CURL_EASY_STR_CLEAR(data, STRING_SSL_ENGINE);
result = Curl_ssl_set_engine_default(data);
-@@ -1064,7 +1205,7 @@ static CURLcode setopt_long_http(struct Curl_easy *data, CURLoption option,
+@@ -1020,7 +1161,7 @@ static CURLcode setopt_long_http(struct Curl_easy *data, CURLoption option,
switch(option) {
case CURLOPT_FOLLOWLOCATION:
@@ -6275,13 +6213,13 @@ index eb9ff2e396..7421f08b2e 100644
result = CURLE_BAD_FUNCTION_ARGUMENT;
else
s->http_follow_mode = (unsigned char)arg;
-@@ -1090,6 +1231,29 @@ static CURLcode setopt_long_http(struct Curl_easy *data, CURLoption option,
+@@ -1046,6 +1187,29 @@ static CURLcode setopt_long_http(struct Curl_easy *data, CURLoption option,
return httpauth(data, FALSE, (unsigned long)arg);
case CURLOPT_HTTP_VERSION:
return setopt_HTTP_VERSION(data, arg);
+ case CURLOPT_STREAM_EXCLUSIVE:
+#ifdef USE_HTTP2
-+ s->priority.exclusive = (int)arg;
++ s->stream_exclusive = !!arg;
+ break;
+#else
+ return CURLE_NOT_BUILT_IN;
@@ -6305,7 +6243,7 @@ index eb9ff2e396..7421f08b2e 100644
case CURLOPT_EXPECT_100_TIMEOUT_MS:
result = value_range(&arg, 0, 0, 0xffff);
if(!result)
-@@ -1393,6 +1557,23 @@ static CURLcode setopt_slist(struct Curl_easy *data, CURLoption option,
+@@ -1361,6 +1525,23 @@ static CURLcode setopt_slist(struct Curl_easy *data, CURLoption option,
*/
s->headers = slist;
break;
@@ -6329,41 +6267,27 @@ index eb9ff2e396..7421f08b2e 100644
#endif
#ifndef CURL_DISABLE_TELNET
case CURLOPT_TELNETOPTIONS:
-@@ -1484,6 +1665,9 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
+@@ -1472,6 +1653,9 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
#ifndef CURL_DISABLE_MIME
case CURLOPT_MIMEPOST:
result = setopt_mimepost(data, va_arg(param, curl_mime *));
-+ if(!result && s->str[STRING_FORM_BOUNDARY] && s->mimepostp)
++ if(!result && CURL_EASY_STR(data, STRING_FORM_BOUNDARY) && s->mimepostp)
+ result = Curl_mime_set_form_boundary(
+ data, (curl_mime *)s->mimepostp->arg);
break;
#endif /* !CURL_DISABLE_MIME */
#endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
-@@ -1571,11 +1755,11 @@ static CURLcode cookielist(struct Curl_easy *data, const char *ptr)
- if(checkprefix("Set-Cookie:", ptr))
- /* HTTP Header format line */
- result = Curl_cookie_add(data, data->cookies, TRUE, FALSE, ptr + 11,
-- NULL, NULL, TRUE);
-+ NULL, NULL, TRUE, FALSE);
- else
- /* Netscape format line */
- result = Curl_cookie_add(data, data->cookies, FALSE, FALSE, ptr, NULL,
-- NULL, TRUE);
-+ NULL, TRUE, FALSE);
- Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
- }
- return result;
-@@ -1998,6 +2182,9 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
+@@ -1987,6 +2171,9 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
if(Curl_ssl_supports(data, SSLSUPP_SSL_EC_CURVES))
- return Curl_setstropt(&s->str[STRING_SSL_EC_CURVES], ptr);
+ return Curl_setstropt(data, STRING_SSL_EC_CURVES, ptr);
return CURLE_NOT_BUILT_IN;
+ case CURLOPT_HTTP3_SSL_EC_CURVES:
+ /* Set HTTP/3-specific accepted curves in SSL connection setup. */
-+ return Curl_setstropt(&s->str[STRING_HTTP3_SSL_EC_CURVES], ptr);
++ return Curl_setstropt(data, STRING_HTTP3_SSL_EC_CURVES, ptr);
case CURLOPT_SSL_SIGNATURE_ALGORITHMS:
/*
* Set accepted signature algorithms.
-@@ -2494,12 +2681,112 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
+@@ -2495,6 +2682,105 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
return result;
}
@@ -6377,10 +6301,10 @@ index eb9ff2e396..7421f08b2e 100644
+ bool default_headers = TRUE;
+ char *p;
+ char *suffix;
-+ CURLcode result = Curl_setstropt(&s->str[STRING_IMPERSONATE], ptr);
++ CURLcode result = Curl_setstropt(data, STRING_IMPERSONATE, ptr);
+ if(result)
+ return result;
-+ p = s->str[STRING_IMPERSONATE];
++ p = CURL_UNCONST(CURL_EASY_STR(data, STRING_IMPERSONATE));
+ if(!p || !*p)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ suffix = strchr(p, ':');
@@ -6404,7 +6328,7 @@ index eb9ff2e396..7421f08b2e 100644
+ CURLcode result;
+ if(ptr && !setopt_valid_form_boundary(ptr))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
-+ result = Curl_setstropt(&s->str[STRING_FORM_BOUNDARY], ptr);
++ result = Curl_setstropt(data, STRING_FORM_BOUNDARY, ptr);
+#if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
+ if(!result && s->mimepostp)
+ result = Curl_mime_set_form_boundary(
@@ -6413,54 +6337,54 @@ index eb9ff2e396..7421f08b2e 100644
+ return result;
+ }
+ case CURLOPT_TLS_EXTENSION_ORDER:
-+ return Curl_setstropt(&s->str[STRING_TLS_EXTENSION_ORDER], ptr);
++ return Curl_setstropt(data, STRING_TLS_EXTENSION_ORDER, ptr);
+ case CURLOPT_HTTP2_PSEUDO_HEADERS_ORDER:
-+ return Curl_setstropt(&s->str[STRING_HTTP2_PSEUDO_HEADERS_ORDER], ptr);
++ return Curl_setstropt(data, STRING_HTTP2_PSEUDO_HEADERS_ORDER, ptr);
+ case CURLOPT_HTTP2_SETTINGS:
-+ return Curl_setstropt(&s->str[STRING_HTTP2_SETTINGS], ptr);
++ return Curl_setstropt(data, STRING_HTTP2_SETTINGS, ptr);
+ case CURLOPT_HTTPHEADER_ORDER:
+ if(!setopt_valid_http_header_order(ptr))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
-+ return Curl_setstropt(&s->str[STRING_HTTPHEADER_ORDER], ptr);
++ return Curl_setstropt(data, STRING_HTTPHEADER_ORDER, ptr);
+ case CURLOPT_HTTP3_HTTPHEADER_ORDER:
+ if(!setopt_valid_http_header_order(ptr))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
-+ return Curl_setstropt(&s->str[STRING_HTTP3_HTTPHEADER_ORDER], ptr);
++ return Curl_setstropt(data, STRING_HTTP3_HTTPHEADER_ORDER, ptr);
+ case CURLOPT_WS_HTTPHEADER_ORDER:
+ if(!setopt_valid_http_header_order(ptr))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
-+ return Curl_setstropt(&s->str[STRING_WS_HTTPHEADER_ORDER], ptr);
++ return Curl_setstropt(data, STRING_WS_HTTPHEADER_ORDER, ptr);
+ case CURLOPT_HTTP3_PSEUDO_HEADERS_ORDER:
-+ return Curl_setstropt(&s->str[STRING_HTTP3_PSEUDO_HEADERS_ORDER], ptr);
++ return Curl_setstropt(data, STRING_HTTP3_PSEUDO_HEADERS_ORDER, ptr);
+ case CURLOPT_HTTP3_SETTINGS:
-+ return Curl_setstropt(&s->str[STRING_HTTP3_SETTINGS], ptr);
++ return Curl_setstropt(data, STRING_HTTP3_SETTINGS, ptr);
+ case CURLOPT_QUIC_CID_LENGTH:
+ if(ptr && strcmp(ptr, "webkit") && strcmp(ptr, "firefox"))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
-+ return Curl_setstropt(&s->str[STRING_QUIC_CID_LENGTH], ptr);
++ return Curl_setstropt(data, STRING_QUIC_CID_LENGTH, ptr);
+ case CURLOPT_QUIC_TRANSPORT_PARAMETERS:
-+ return Curl_setstropt(&s->str[STRING_QUIC_TRANSPORT_PARAMETERS], ptr);
++ return Curl_setstropt(data, STRING_QUIC_TRANSPORT_PARAMETERS, ptr);
+ case CURLOPT_HTTP3_SIG_HASH_ALGS:
-+ return Curl_setstropt(&s->str[STRING_HTTP3_SIG_HASH_ALGS], ptr);
++ return Curl_setstropt(data, STRING_HTTP3_SIG_HASH_ALGS, ptr);
+ case CURLOPT_HTTP3_TLS_EXTENSION_ORDER:
-+ return Curl_setstropt(&s->str[STRING_HTTP3_TLS_EXTENSION_ORDER], ptr);
++ return Curl_setstropt(data, STRING_HTTP3_TLS_EXTENSION_ORDER, ptr);
+ case CURLOPT_HTTP2_STREAMS:
-+ return Curl_setstropt(&s->str[STRING_HTTP2_STREAMS], ptr);
++ return Curl_setstropt(data, STRING_HTTP2_STREAMS, ptr);
+ case CURLOPT_SSL_SIG_HASH_ALGS:
+ /* Backwards-compatible alias for
+ * CURLOPT_SSL_SIGNATURE_ALGORITHMS. */
-+ return Curl_setstropt(&s->str[STRING_SSL_SIGNATURE_ALGORITHMS], ptr);
++ return Curl_setstropt(data, STRING_SSL_SIGNATURE_ALGORITHMS, ptr);
+ case CURLOPT_SSL_CERT_COMPRESSION:
+ /* Set the comma-delimited list of TLS certificate compression
+ * algorithms. Supported values include "zlib" and "brotli". */
-+ return Curl_setstropt(&s->str[STRING_SSL_CERT_COMPRESSION], ptr);
++ return Curl_setstropt(data, STRING_SSL_CERT_COMPRESSION, ptr);
+ case CURLOPT_WS_SSL_CERT_COMPRESSION:
+ /* Set the TLS certificate compression algorithms for WebSocket. */
-+ return Curl_setstropt(&s->str[STRING_WS_SSL_CERT_COMPRESSION], ptr);
++ return Curl_setstropt(data, STRING_WS_SSL_CERT_COMPRESSION, ptr);
+ case CURLOPT_TLS_DELEGATED_CREDENTIALS:
-+ return Curl_setstropt(&s->str[STRING_TLS_DELEGATED_CREDENTIALS], ptr);
++ return Curl_setstropt(data, STRING_TLS_DELEGATED_CREDENTIALS, ptr);
+ case CURLOPT_TLS_TRUST_ANCHORS:
-+ return Curl_setstropt(&s->str[STRING_TLS_TRUST_ANCHORS], ptr);
++ return Curl_setstropt(data, STRING_TLS_TRUST_ANCHORS, ptr);
+ default:
+ return CURLE_UNKNOWN_OPTION;
+ }
@@ -6469,14 +6393,15 @@ index eb9ff2e396..7421f08b2e 100644
static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
char *ptr)
{
- typedef CURLcode (*ptrfunc)(struct Curl_easy *data, CURLoption option,
- char *ptr);
- static const ptrfunc setopt_call[] = {
+@@ -2506,6 +2792,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
+ #if defined(USE_SSL) || defined(USE_SSH)
+ setopt_cptr_ssl,
+ #endif
+ setopt_cptr_impersonate,
#ifndef CURL_DISABLE_PROXY
setopt_cptr_proxy,
#endif
-@@ -2892,6 +3179,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
+@@ -2893,6 +3180,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
way than being listed explicitly */
switch(option) {
case CURLOPT_HTTPHEADER:
@@ -6487,22 +6412,23 @@ index eb9ff2e396..7421f08b2e 100644
case CURLOPT_POSTQUOTE:
case CURLOPT_TELNETOPTIONS:
diff --git a/lib/socks.c b/lib/socks.c
-index 6c458c505d..05797eb28b 100644
+index 949f20c135..2c6dca6bc0 100644
--- a/lib/socks.c
+++ b/lib/socks.c
-@@ -40,8 +40,11 @@
+@@ -39,9 +39,12 @@
+ #include "select.h"
#include "cfilters.h"
- #include "cf-dns.h"
#include "connect.h"
+#include "cf-socket.h"
+#include "sockaddr.h"
#include "socks.h"
+ #include "vdns/cf-dns.h"
#include "curlx/inet_pton.h"
+#include "curlx/inet_ntop.h"
/* for the (SOCKS) connect state machine */
enum socks_state_t {
-@@ -94,19 +97,43 @@ static const char * const cf_socks_statename[] = {
+@@ -94,18 +97,42 @@ static const char * const cf_socks_statename[] = {
#define SOCKS_CHUNK_SIZE 1024
#define SOCKS_CHUNKS 1
@@ -6538,7 +6464,6 @@ index 6c458c505d..05797eb28b 100644
uint8_t proxy_type;
unsigned char version;
BIT(resolve_local);
- BIT(start_resolving);
BIT(socks4a);
+ BIT(udp_associate); /* use UDP ASSOCIATE instead of CONNECT */
+ BIT(udp_dest_set); /* destination cached for UDP headers */
@@ -6546,7 +6471,7 @@ index 6c458c505d..05797eb28b 100644
};
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-@@ -753,6 +780,78 @@ static CURLproxycode socks5_check_auth_resp(struct socks_ctx *sx,
+@@ -736,6 +763,78 @@ static CURLproxycode socks5_check_auth_resp(struct socks_ctx *sx,
return CURLPX_OK;
}
@@ -6625,7 +6550,7 @@ index 6c458c505d..05797eb28b 100644
static CURLproxycode socks5_req1_init(struct socks_ctx *sx,
struct Curl_cfilter *cf,
struct Curl_easy *data)
-@@ -765,7 +864,8 @@ static CURLproxycode socks5_req1_init(struct socks_ctx *sx,
+@@ -748,7 +847,8 @@ static CURLproxycode socks5_req1_init(struct socks_ctx *sx,
CURLcode result;
req[0] = 5; /* version (SOCKS5) */
@@ -6635,7 +6560,7 @@ index 6c458c505d..05797eb28b 100644
req[2] = 0; /* must be zero */
if(sx->resolve_local) {
/* rest of request is added after resolving */
-@@ -802,6 +902,38 @@ static CURLproxycode socks5_req1_init(struct socks_ctx *sx,
+@@ -785,6 +885,38 @@ static CURLproxycode socks5_req1_init(struct socks_ctx *sx,
destlen = (unsigned char)hostname_len; /* 1-byte length */
}
@@ -6674,7 +6599,7 @@ index 6c458c505d..05797eb28b 100644
req[3] = desttype;
req[4] = destlen;
hdlen = (desttype == 3) ? 5 : 4; /* no length byte for ip addresses */
-@@ -811,9 +943,12 @@ static CURLproxycode socks5_req1_init(struct socks_ctx *sx,
+@@ -794,9 +926,12 @@ static CURLproxycode socks5_req1_init(struct socks_ctx *sx,
result = Curl_bufq_write(&sx->iobuf, destination, destlen, &nwritten);
if(result || (nwritten != destlen))
return CURLPX_SEND_REQUEST;
@@ -6689,7 +6614,7 @@ index 6c458c505d..05797eb28b 100644
result = Curl_bufq_write(&sx->iobuf, req, 2, &nwritten);
if(result || (nwritten != 2))
return CURLPX_SEND_REQUEST;
-@@ -831,6 +966,7 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
+@@ -814,6 +949,7 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
char dest[MAX_IPADR_LEN]; /* printable address */
const unsigned char *destination = NULL;
unsigned char desttype = 1, destlen = 4;
@@ -6697,7 +6622,7 @@ index 6c458c505d..05797eb28b 100644
unsigned char req[2];
CURLcode result;
CURLproxycode presult = CURLPX_OK;
-@@ -903,6 +1039,12 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
+@@ -873,6 +1009,12 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
goto out;
}
@@ -6710,7 +6635,7 @@ index 6c458c505d..05797eb28b 100644
req[0] = desttype;
result = Curl_bufq_write(&sx->iobuf, req, 1, &nwritten);
if(result || (nwritten != 1)) {
-@@ -914,9 +1056,12 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
+@@ -884,9 +1026,12 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
presult = CURLPX_SEND_REQUEST;
goto out;
}
@@ -6725,7 +6650,7 @@ index 6c458c505d..05797eb28b 100644
result = Curl_bufq_write(&sx->iobuf, req, 2, &nwritten);
if(result || (nwritten != 2)) {
presult = CURLPX_SEND_REQUEST;
-@@ -1022,6 +1167,54 @@ static CURLproxycode socks5_recv_resp1(struct socks_ctx *sx,
+@@ -992,6 +1137,54 @@ static CURLproxycode socks5_recv_resp1(struct socks_ctx *sx,
return CURLPX_OK;
}
@@ -6780,16 +6705,7 @@ index 6c458c505d..05797eb28b 100644
/*
* This function logs in to a SOCKS5 proxy and sends the specifics to the final
* destination server.
-@@ -1126,6 +1319,8 @@ process_state:
- sxstate(sx, cf, data, SOCKS5_ST_REQ1_SEND);
- goto process_state;
- }
-+ /* curl-impersonate: locally resolve the QUIC target before caching it
-+ * for the SOCKS5 UDP header. */
- sx->start_resolving = TRUE;
- sxstate(sx, cf, data, SOCKS5_ST_RESOLVING);
- FALLTHROUGH();
-@@ -1160,6 +1355,11 @@ process_state:
+@@ -1128,6 +1321,11 @@ process_state:
return socks_failed(sx, cf, data, presult);
if(!done)
return CURLPX_OK;
@@ -6801,7 +6717,7 @@ index 6c458c505d..05797eb28b 100644
CURL_TRC_CF(data, cf, "SOCKS5 request granted.");
sxstate(sx, cf, data, SOCKS_ST_SUCCESS);
FALLTHROUGH();
-@@ -1177,9 +1377,100 @@ process_state:
+@@ -1145,9 +1343,100 @@ process_state:
}
}
@@ -6903,7 +6819,7 @@ index 6c458c505d..05797eb28b 100644
Curl_peer_unlink(&ctx->dest);
Curl_creds_unlink(&ctx->creds);
Curl_bufq_free(&ctx->iobuf);
-@@ -1236,6 +1527,22 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
+@@ -1202,6 +1491,22 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
else if(ctx->state != SOCKS_ST_SUCCESS)
goto out;
@@ -6926,7 +6842,7 @@ index 6c458c505d..05797eb28b 100644
#ifdef CURLVERBOSE
if(Curl_trc_is_verbose(data)) {
struct ip_quadruple ipquad;
-@@ -1261,6 +1568,171 @@ out:
+@@ -1227,6 +1532,171 @@ out:
return result;
}
@@ -7098,7 +7014,7 @@ index 6c458c505d..05797eb28b 100644
static CURLcode socks_cf_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
-@@ -1292,8 +1764,7 @@ static CURLcode socks_cf_adjust_pollset(struct Curl_cfilter *cf,
+@@ -1258,8 +1728,7 @@ static CURLcode socks_cf_adjust_pollset(struct Curl_cfilter *cf,
static void socks_proxy_cf_destroy(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
@@ -7108,7 +7024,7 @@ index 6c458c505d..05797eb28b 100644
cf->ctx = NULL;
}
-@@ -1304,6 +1775,14 @@ static CURLcode socks_cf_query(struct Curl_cfilter *cf,
+@@ -1270,6 +1739,14 @@ static CURLcode socks_cf_query(struct Curl_cfilter *cf,
struct socks_ctx *sx = cf->ctx;
switch(query) {
@@ -7123,7 +7039,7 @@ index 6c458c505d..05797eb28b 100644
case CF_QUERY_HOST_PORT:
if(sx) {
*pres1 = sx->dest->port;
-@@ -1334,17 +1813,29 @@ struct Curl_cftype Curl_cft_socks_proxy = {
+@@ -1300,17 +1777,29 @@ struct Curl_cftype Curl_cft_socks_proxy = {
Curl_cf_def_shutdown,
socks_cf_adjust_pollset,
Curl_cf_def_data_pending,
@@ -7155,7 +7071,7 @@ index 6c458c505d..05797eb28b 100644
uint8_t ip_version,
uint8_t proxy_type,
struct Curl_creds *creds)
-@@ -1366,6 +1857,13 @@ CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
+@@ -1340,6 +1829,13 @@ CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
failf(data, "unknown proxytype %d option given", proxy_type);
return CURLE_COULDNT_CONNECT;
}
@@ -7169,7 +7085,7 @@ index 6c458c505d..05797eb28b 100644
/* NUL byte already part of struct size */
ctx = curlx_calloc(1, sizeof(*ctx));
-@@ -1376,6 +1874,11 @@ CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
+@@ -1350,6 +1846,11 @@ CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
Curl_peer_link(&ctx->dest, dest);
ctx->ip_version = ip_version;
ctx->proxy_type = proxy_type;
@@ -7178,12 +7094,12 @@ index 6c458c505d..05797eb28b 100644
+ ctx->udp_associate =
+ (transport == TRNSPRT_QUIC) &&
+ !cf_at->conn->http_proxy.peer;
+ ctx->resolve_local = resolve_local;
Curl_creds_link(&ctx->creds, creds);
Curl_bufq_init2(&ctx->iobuf, SOCKS_CHUNK_SIZE, SOCKS_CHUNKS,
- BUFQ_OPT_SOFT_LIMIT);
-@@ -1384,7 +1887,7 @@ CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
- if(!result)
- Curl_conn_cf_insert_after(cf_at, cf);
+@@ -1366,7 +1867,7 @@ CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
+ }
+ }
else
- socks_proxy_ctx_free(ctx);
+ socks_proxy_ctx_free(ctx, data);
@@ -7226,11 +7142,11 @@ index d8e77c7f13..4ffeda15f3 100644
#endif /* HEADER_CURL_SOCKS_H */
diff --git a/lib/transfer.c b/lib/transfer.c
-index 1a4138f6c1..78b6591327 100644
+index 3b6c5c03dd..57ae90877a 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
-@@ -75,7 +75,25 @@
- #include "bufref.h"
+@@ -74,7 +74,25 @@
+ #include "rtsp.h"
#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
- !defined(CURL_DISABLE_IMAP)
@@ -7256,7 +7172,7 @@ index 1a4138f6c1..78b6591327 100644
/*
* checkheaders() checks the linked list of custom headers for a
* particular header (prefix). Provide the prefix without colon!
-@@ -90,7 +108,9 @@ char *Curl_checkheaders(const struct Curl_easy *data,
+@@ -89,7 +107,9 @@ char *Curl_checkheaders(const struct Curl_easy *data,
DEBUGASSERT(thislen);
DEBUGASSERT(thisheader[thislen - 1] != ':');
@@ -7268,7 +7184,7 @@ index 1a4138f6c1..78b6591327 100644
Curl_headersep(head->data[thislen]))
return head->data;
diff --git a/lib/transfer.h b/lib/transfer.h
-index 7507ce27bd..6c89e49ae2 100644
+index 0ad0d549ed..9bd7bfb3dc 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -25,6 +25,7 @@
@@ -7280,10 +7196,21 @@ index 7507ce27bd..6c89e49ae2 100644
const char *thisheader,
const size_t thislen);
diff --git a/lib/url.c b/lib/url.c
-index 505e08a7e1..b1199c1e22 100644
+index 6eeae43d0d..65ee37b69d 100644
--- a/lib/url.c
+++ b/lib/url.c
-@@ -270,6 +270,8 @@ CURLcode Curl_close(struct Curl_easy **datap)
+@@ -175,6 +175,10 @@ void Curl_freeset(struct Curl_easy *data)
+ curl_slist_free_all(data->state.cookielist);
+ data->state.cookielist = NULL;
+ #endif
++ curl_slist_free_all(data->state.base_headers);
++ data->state.base_headers = NULL;
++ curl_slist_free_all(data->state.merged_headers);
++ data->state.merged_headers = NULL;
+ }
+
+ /* free the URL pieces */
+@@ -267,6 +271,8 @@ CURLcode Curl_close(struct Curl_easy **datap)
curlx_safefree(data->state.most_recent_ftp_entrypath);
curlx_safefree(data->info.contenttype);
curlx_safefree(data->info.wouldredirect);
@@ -7292,18 +7219,15 @@ index 505e08a7e1..b1199c1e22 100644
/* No longer a dirty share, if it exists */
if(Curl_share_easy_unlink(data))
-@@ -288,6 +290,10 @@ CURLcode Curl_close(struct Curl_easy **datap)
- #ifndef CURL_DISABLE_RTSP
- curlx_safefree(data->state.aptr.rtsp_transport);
+@@ -281,7 +287,6 @@ CURLcode Curl_close(struct Curl_easy **datap)
+ #ifndef CURL_DISABLE_COOKIES
+ curlx_safefree(data->req.cookiehost);
#endif
-+ /* curl-impersonate: Free the list set by CURLOPT_HTTPBASEHEADER. */
-+ curl_slist_free_all(data->state.base_headers);
-+ /* curl-impersonate: Free the dynamic list of headers. */
-+ curl_slist_free_all(data->state.merged_headers);
-
+-
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API)
Curl_mime_cleanpart(data->state.formp);
-@@ -399,6 +405,7 @@ void Curl_init_userdefined(struct Curl_easy *data)
+ curlx_safefree(data->state.formp);
+@@ -395,6 +400,7 @@ void Curl_init_userdefined(struct Curl_easy *data)
Curl_setopt_SSLVERSION(data, CURLOPT_PROXY_SSLVERSION,
CURL_SSLVERSION_DEFAULT);
#endif
@@ -7311,7 +7235,7 @@ index 505e08a7e1..b1199c1e22 100644
#endif
#ifndef CURL_DISABLE_FTP
set->wildcard_enabled = FALSE;
-@@ -413,8 +420,16 @@ void Curl_init_userdefined(struct Curl_easy *data)
+@@ -409,8 +415,16 @@ void Curl_init_userdefined(struct Curl_easy *data)
set->tcp_fastopen = FALSE;
set->tcp_nodelay = TRUE;
set->ssl_enable_alpn = TRUE;
@@ -7328,7 +7252,7 @@ index 505e08a7e1..b1199c1e22 100644
set->buffer_size = READBUFFER_SIZE;
set->upload_buffer_size = UPLOADBUFFER_DEFAULT;
set->upload_flags = CURLULFLAG_SEEN;
-@@ -1296,6 +1311,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
+@@ -1202,6 +1216,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
#endif
conn->ip_version = data->set.ipver;
conn->bits.connect_only = (bool)data->set.connect_only;
@@ -7339,7 +7263,7 @@ index 505e08a7e1..b1199c1e22 100644
conn->transport_wanted = TRNSPRT_TCP; /* most of them are TCP streams */
/* Store the local bind parameters that will be used for this connection */
-@@ -2171,6 +2190,11 @@ static CURLcode url_create_needle(struct Curl_easy *data,
+@@ -2091,6 +2109,11 @@ static CURLcode url_create_needle(struct Curl_easy *data,
(default) */
if(data->set.ssl_enable_alpn)
needle->bits.tls_enable_alpn = TRUE;
@@ -7351,7 +7275,7 @@ index 505e08a7e1..b1199c1e22 100644
}
if(network_scheme) {
-@@ -2373,7 +2397,7 @@ static CURLcode url_find_or_create_conn(struct Curl_easy *data)
+@@ -2293,7 +2316,7 @@ static CURLcode url_find_or_create_conn(struct Curl_easy *data)
#endif
/* Complete the easy's SSL configuration for connection cache matching */
@@ -7360,7 +7284,7 @@ index 505e08a7e1..b1199c1e22 100644
if(result)
goto out;
-@@ -2421,7 +2445,6 @@ static CURLcode url_find_or_create_conn(struct Curl_easy *data)
+@@ -2338,7 +2361,6 @@ static CURLcode url_find_or_create_conn(struct Curl_easy *data)
/* We have decided that we want a new connection. We may not be able to do
that if we have reached the limit of how many connections we are
allowed to open. */
@@ -7368,11 +7292,19 @@ index 505e08a7e1..b1199c1e22 100644
if(waitpipe) {
/* There is a connection that *might* become usable for multiplexing
"soon", and we wait for that */
+@@ -2538,6 +2560,7 @@ CURLcode Curl_init_transfer(struct Curl_easy *data, struct connectdata *conn)
+ void Curl_data_priority_clear_state(struct Curl_easy *data)
+ {
+ data->state.weight = 0;
++ data->state.stream_exclusive = FALSE;
+ }
+
+ #endif /* USE_HTTP2 || USE_HTTP3 */
diff --git a/lib/urldata.h b/lib/urldata.h
-index d4d336d8db..e5a16ca84d 100644
+index 1c0101847b..6eb8c2383c 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
-@@ -193,6 +193,7 @@ struct ConnectBits {
+@@ -185,6 +185,7 @@ struct ConnectBits {
BIT(connect_only);
#ifndef CURL_DISABLE_PROXY
BIT(origin_is_proxy); /* if set, the connection's origin is a proxy */
@@ -7380,7 +7312,7 @@ index d4d336d8db..e5a16ca84d 100644
#endif
/* always modify bits.close with the connclose() and connkeep() macros! */
BIT(close); /* if set, we close the connection after this request */
-@@ -220,6 +221,14 @@ struct ConnectBits {
+@@ -212,6 +213,14 @@ struct ConnectBits {
BIT(multiplex); /* connection is multiplexed */
BIT(tcp_fastopen); /* use TCP Fast Open */
BIT(tls_enable_alpn); /* TLS ALPN extension? */
@@ -7395,8 +7327,8 @@ index d4d336d8db..e5a16ca84d 100644
BIT(sock_accepted); /* TRUE if the SECONDARYSOCKET was created with
accept() */
BIT(parallel_connect); /* set TRUE when a parallel connect attempt has
-@@ -417,6 +426,10 @@ struct PureInfo {
- uint32_t httpauthpicked; /* selected host auth type */
+@@ -409,6 +418,10 @@ struct PureInfo {
+ curl_off_t numconnects; /* how many new connections libcurl created */
char *contenttype; /* the content type of the object */
char *wouldredirect; /* URL this would have been redirected to if asked to */
+ struct curl_slist *cookiechanges; /* accepted Set-Cookie mutations */
@@ -7404,17 +7336,9 @@ index d4d336d8db..e5a16ca84d 100644
+ struct curl_slist *redirect_history; /* followed redirects */
+ struct curl_slist *redirect_history_tail; /* last followed redirect */
curl_off_t retry_after; /* info from Retry-After: header */
- uint32_t header_size; /* size of read header(s) in bytes */
-
-@@ -526,6 +539,7 @@ struct Curl_data_prio_node {
- */
- struct Curl_data_priority {
- int weight;
-+ BIT(exclusive);
- };
-
- /* Timers */
-@@ -673,6 +687,19 @@ struct UrlState {
+ const char *conn_scheme;
+ int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */
+@@ -600,6 +613,19 @@ struct UrlState {
curl_easy_setopt(COOKIEFILE) calls */
#endif
@@ -7434,7 +7358,15 @@ index d4d336d8db..e5a16ca84d 100644
#ifdef CURLVERBOSE
struct curl_trc_feat *feat; /* opt. trace feature transfer is part of */
#endif
-@@ -769,6 +796,8 @@ enum dupstring {
+@@ -625,6 +651,7 @@ struct UrlState {
+ #endif
+ #if defined(USE_HTTP2) || defined(USE_HTTP3)
+ int weight; /* shallow copy of data->set */
++ BIT(stream_exclusive); /* HTTP/2 dependency is exclusive */
+ #endif
+ uint16_t followlocation; /* redirect counter */
+ uint8_t retrycount; /* number of retries on a new connection, up to
+@@ -700,6 +727,8 @@ enum dupstring {
STRING_SSL_CRLFILE, /* CRL file to check certificate */
STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
STRING_SERVICE_NAME, /* Service name */
@@ -7443,7 +7375,7 @@ index d4d336d8db..e5a16ca84d 100644
#ifndef CURL_DISABLE_PROXY
STRING_CERT_PROXY, /* client certificate filename */
STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/
-@@ -867,6 +896,7 @@ enum dupstring {
+@@ -790,6 +819,7 @@ enum dupstring {
STRING_DNS_LOCAL_IP6,
#endif
STRING_SSL_EC_CURVES,
@@ -7451,7 +7383,7 @@ index d4d336d8db..e5a16ca84d 100644
#ifndef CURL_DISABLE_AWS
STRING_AWS_SIGV4, /* Parameters for V4 signature */
#endif
-@@ -875,6 +905,23 @@ enum dupstring {
+@@ -803,6 +833,23 @@ enum dupstring {
#endif
STRING_ECH_CONFIG, /* CURLOPT_ECH_CONFIG */
STRING_ECH_PUBLIC, /* CURLOPT_ECH_PUBLIC */
@@ -7474,8 +7406,8 @@ index d4d336d8db..e5a16ca84d 100644
+ STRING_TLS_TRUST_ANCHORS,
STRING_SSL_SIGNATURE_ALGORITHMS, /* CURLOPT_SSL_SIGNATURE_ALGORITHMS */
- /* -- end of null-terminated strings -- */
-@@ -956,6 +1003,8 @@ struct UserDefined {
+ STRING_LAST /* not used, an end-of-list marker */
+@@ -877,6 +924,8 @@ struct UserDefined {
download */
curl_off_t set_resume_from; /* continue [ftp] transfer from here */
struct curl_slist *headers; /* linked list of extra headers */
@@ -7484,7 +7416,7 @@ index d4d336d8db..e5a16ca84d 100644
struct curl_httppost *httppost; /* linked list of old POST data */
#if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
curl_mimepart *mimepostp; /* MIME/POST data. */
-@@ -1117,6 +1166,7 @@ struct UserDefined {
+@@ -1044,6 +1093,7 @@ struct UserDefined {
BIT(sep_headers); /* handle host and proxy headers separately */
#ifndef CURL_DISABLE_COOKIES
BIT(cookiesession); /* new cookie session? */
@@ -7492,7 +7424,7 @@ index d4d336d8db..e5a16ca84d 100644
#endif
BIT(crlf); /* convert crlf on ftp upload(?) */
#ifdef USE_SSH
-@@ -1133,6 +1183,7 @@ struct UserDefined {
+@@ -1060,6 +1110,7 @@ struct UserDefined {
BIT(get_filetime); /* get the time and get of the remote file */
#ifndef CURL_DISABLE_PROXY
BIT(tunnel_thru_httpproxy); /* use CONNECT through an HTTP proxy */
@@ -7500,7 +7432,7 @@ index d4d336d8db..e5a16ca84d 100644
#endif
BIT(prefer_ascii); /* ASCII rather than binary */
BIT(remote_append); /* append, not overwrite, on upload */
-@@ -1175,7 +1226,18 @@ struct UserDefined {
+@@ -1102,7 +1153,18 @@ struct UserDefined {
BIT(sasl_ir); /* Enable/disable SASL initial response */
BIT(tcp_keepalive); /* use TCP keepalives */
BIT(tcp_fastopen); /* use TCP Fast Open */
@@ -7519,12 +7451,7 @@ index d4d336d8db..e5a16ca84d 100644
BIT(path_as_is); /* allow dotdots? */
BIT(pipewait); /* wait for multiplex status before starting a new
connection */
-@@ -1197,10 +1259,15 @@ struct UserDefined {
- BIT(doh_verifystatus); /* DoH certificate status verification */
- #endif
- BIT(http09_allowed); /* allow HTTP/0.9 responses */
-+// BIT(grease); /* grease enabled? */
- #ifndef CURL_DISABLE_WEBSOCKETS
+@@ -1128,6 +1190,11 @@ struct UserDefined {
BIT(ws_raw_mode);
BIT(ws_no_auto_pong);
#endif
@@ -7532,11 +7459,12 @@ index d4d336d8db..e5a16ca84d 100644
+ int tls_record_size_limit;
+ int tls_key_shares_limit;
+ BIT(http2_no_priority);
++ BIT(stream_exclusive); /* HTTP/2 dependency is exclusive */
BIT(post301); /* keep POSTs as POSTs after a 301 request */
BIT(post302); /* keep POSTs as POSTs after a 302 request */
BIT(post303); /* keep POSTs as POSTs after a 303 request */
diff --git a/lib/version.c b/lib/version.c
-index 299caee9fb..89b1fc45f2 100644
+index c4cdde6377..9cdc4a0ea8 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -135,7 +135,11 @@ static void idn_version(char *buf, size_t bufsz)
@@ -7552,7 +7480,7 @@ index 299caee9fb..89b1fc45f2 100644
char *curl_version(void)
{
-@@ -255,6 +259,7 @@ char *curl_version(void)
+@@ -257,6 +261,7 @@ char *curl_version(void)
Curl_ldap_version(ldap_buf, sizeof(ldap_buf));
src[i++] = ldap_buf;
#endif
@@ -7561,17 +7489,17 @@ index 299caee9fb..89b1fc45f2 100644
DEBUGASSERT(i <= VERSION_PARTS);
diff --git a/lib/vquic/cf-ngtcp2-cmn.c b/lib/vquic/cf-ngtcp2-cmn.c
-index e1ca18cf69..ca4f2e94f8 100644
+index b1cfb68cbd..a0a6791648 100644
--- a/lib/vquic/cf-ngtcp2-cmn.c
+++ b/lib/vquic/cf-ngtcp2-cmn.c
-@@ -63,6 +63,7 @@
+@@ -62,6 +62,7 @@
#include "http1.h"
#include "select.h"
#include "sockaddr.h"
+#include "strcase.h"
#include "transfer.h"
#include "bufref.h"
- #include "vquic/vquic.h"
+ #include "vdns/cf-dns.h"
@@ -119,6 +120,7 @@ CURLcode Curl_cf_ngtcp2_ctx_init(struct cf_ngtcp2_ctx *ctx,
struct Curl_peer *origin,
struct Curl_peer *peer,
@@ -7594,7 +7522,7 @@ index e1ca18cf69..ca4f2e94f8 100644
void Curl_cf_ngtcp2_ctx_cleanup(struct cf_ngtcp2_ctx *ctx)
@@ -142,6 +145,7 @@ void Curl_cf_ngtcp2_ctx_cleanup(struct cf_ngtcp2_ctx *ctx)
- vquic_ctx_free(&ctx->q);
+ Curl_vquic_ctx_free(&ctx->q);
Curl_bufcp_free(&ctx->stream_bufcp);
curlx_dyn_free(&ctx->scratch);
+ curlx_dyn_free(&ctx->tp_raw);
@@ -8098,7 +8026,7 @@ index e1ca18cf69..ca4f2e94f8 100644
+ const ngtcp2_cid *scid,
+ struct Curl_easy *data)
+{
-+ const char *params = data->set.str[STRING_QUIC_TRANSPORT_PARAMETERS];
++ const char *params = CURL_EASY_STR(data, STRING_QUIC_TRANSPORT_PARAMETERS);
+ bool permute = Curl_ssl_http3_permute_extensions(data);
+ char *tmp;
+ char *p;
@@ -8346,11 +8274,11 @@ index e1ca18cf69..ca4f2e94f8 100644
}
#if defined(_MSC_VER) && defined(_DLL)
-@@ -898,31 +1624,60 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
+@@ -961,31 +1687,60 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
int rc;
int rv;
CURLcode result;
-+ const char *cid_profile = data->set.str[STRING_QUIC_CID_LENGTH];
++ const char *cid_profile = CURL_EASY_STR(data, STRING_QUIC_CID_LENGTH);
+ size_t dcidlen = NGTCP2_MAX_CIDLEN;
+ size_t scidlen = NGTCP2_MAX_CIDLEN;
const struct Curl_sockaddr_ex *sockaddr = NULL;
@@ -8391,7 +8319,7 @@ index e1ca18cf69..ca4f2e94f8 100644
- (void)Curl_qlogdir(data, ctx->scid.data, NGTCP2_MAX_CIDLEN, &qfd);
+ ctx->scid.datalen = scidlen;
+ if(!cid_profile && quic_has_empty_initial_scid(
-+ data->set.str[STRING_QUIC_TRANSPORT_PARAMETERS]))
++ CURL_EASY_STR(data, STRING_QUIC_TRANSPORT_PARAMETERS)))
+ ctx->scid.datalen = 0;
+ if(ctx->scid.datalen) {
+ result = Curl_rand(data, ctx->scid.data, ctx->scid.datalen);
@@ -8406,7 +8334,7 @@ index e1ca18cf69..ca4f2e94f8 100644
+ if(result)
+ return result;
- result = vquic_ctx_init(data, &ctx->q);
+ result = Curl_vquic_ctx_init(data, &ctx->q);
if(result)
return result;
@@ -8417,17 +8345,17 @@ index e1ca18cf69..ca4f2e94f8 100644
/* No direct socket - must be tunneled QUIC (CONNECT-UDP through proxy) */
ctx->q.sockfd = CURL_SOCKET_BAD;
}
-@@ -952,6 +1707,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
- ctx->conn_ref.get_conn = get_conn;
- ctx->conn_ref.user_data = cf;
+@@ -1004,6 +1759,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
+ ngtcp2_addr_init(&ctx->connected_path.remote,
+ &sockaddr->curl_sa_addr, (socklen_t)sockaddr->addrlen);
}
+
else {
/* Tunneled QUIC (e.g. CONNECT-UDP): get remote address
from the connected filter below */
-@@ -997,6 +1753,19 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
- ctx->conn_ref.user_data = cf;
- }
+@@ -1049,6 +1805,19 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
+ ctx->conn_ref.get_conn = get_conn;
+ ctx->conn_ref.user_data = cf;
+ if(curlx_dyn_len(&ctx->tp_raw)) {
+ ngtcp2_transport_params_raw raw = {
@@ -8445,7 +8373,7 @@ index e1ca18cf69..ca4f2e94f8 100644
result = Curl_vquic_tls_init(&ctx->tls, cf, data,
&ctx->ssl_peer, &ALPN_SPEC_H3,
cf_ngtcp2_tls_ctx_setup, &ctx->tls,
-@@ -1132,7 +1901,7 @@ out:
+@@ -1196,7 +1965,7 @@ out:
/* Direct UDP socket - get IP info for error reporting */
struct ip_quadruple ip;
@@ -8454,7 +8382,7 @@ index e1ca18cf69..ca4f2e94f8 100644
infof(data, "QUIC connect to %s port %u failed: %s",
ip.remote_ip, ip.remote_port, curl_easy_strerror(result));
}
-@@ -1767,14 +2536,34 @@ CURLcode Curl_cf_ngtcp2_cmn_set_expiry(struct Curl_cfilter *cf,
+@@ -1835,14 +2604,34 @@ CURLcode Curl_cf_ngtcp2_cmn_set_expiry(struct Curl_cfilter *cf,
return CURLE_OK;
}
@@ -8493,7 +8421,7 @@ index e1ca18cf69..ca4f2e94f8 100644
*
* Some servers use this as a keep-alive timer at a rather low
* value. We are doing HTTP/3 here and waiting for the response
-@@ -1784,10 +2573,10 @@ static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf,
+@@ -1852,10 +2641,10 @@ static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf,
if(!ctx->qconn)
return;
@@ -8507,7 +8435,7 @@ index e1ca18cf69..ca4f2e94f8 100644
}
else if(!Curl_uint32_hash_count(&ctx->streams)) {
ngtcp2_conn_set_keep_alive_timeout(ctx->qconn, UINT64_MAX);
-@@ -1795,11 +2584,11 @@ static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf,
+@@ -1863,11 +2652,11 @@ static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf,
}
else {
ngtcp2_duration keep_ns;
@@ -8522,7 +8450,7 @@ index e1ca18cf69..ca4f2e94f8 100644
(keep_ns / NGTCP2_MILLISECONDS));
}
}
-@@ -1885,7 +2674,10 @@ bool Curl_cf_ngtcp2_cmn_conn_is_alive(struct Curl_cfilter *cf,
+@@ -1954,7 +2743,10 @@ bool Curl_cf_ngtcp2_cmn_conn_is_alive(struct Curl_cfilter *cf,
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
bool alive = FALSE;
@@ -8534,7 +8462,7 @@ index e1ca18cf69..ca4f2e94f8 100644
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
-@@ -1893,18 +2685,19 @@ bool Curl_cf_ngtcp2_cmn_conn_is_alive(struct Curl_cfilter *cf,
+@@ -1962,18 +2754,19 @@ bool Curl_cf_ngtcp2_cmn_conn_is_alive(struct Curl_cfilter *cf,
if(!ctx->qconn || ctx->shutdown_started)
goto out;
@@ -8565,7 +8493,7 @@ index e1ca18cf69..ca4f2e94f8 100644
}
if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
-@@ -1921,6 +2714,11 @@ bool Curl_cf_ngtcp2_cmn_conn_is_alive(struct Curl_cfilter *cf,
+@@ -1990,6 +2783,11 @@ bool Curl_cf_ngtcp2_cmn_conn_is_alive(struct Curl_cfilter *cf,
CURL_TRC_CF(data, cf, "is_alive, progress ingress -> %d", (int)result);
alive = result ? FALSE : TRUE;
}
@@ -8578,10 +8506,10 @@ index e1ca18cf69..ca4f2e94f8 100644
out:
CF_DATA_RESTORE(cf, save);
diff --git a/lib/vquic/cf-ngtcp2-cmn.h b/lib/vquic/cf-ngtcp2-cmn.h
-index 88554edfb6..97a5ddd737 100644
+index e0c27a95f7..b4aa94baeb 100644
--- a/lib/vquic/cf-ngtcp2-cmn.h
+++ b/lib/vquic/cf-ngtcp2-cmn.h
-@@ -126,6 +126,7 @@ struct cf_ngtcp2_ctx {
+@@ -129,6 +129,7 @@ struct cf_ngtcp2_ctx {
struct curltime handshake_at; /* time connect handshake finished */
struct bufc_pool stream_bufcp; /* chunk pool for streams */
struct dynbuf scratch; /* temp buffer for header construction */
@@ -8589,7 +8517,7 @@ index 88554edfb6..97a5ddd737 100644
struct uint_hash streams; /* hash data->mid to h3_stream_ctx */
uint64_t used_bidi_streams; /* bidi streams we have opened */
uint64_t max_bidi_streams; /* max bidi streams we can open */
-@@ -152,6 +153,7 @@ CURLcode Curl_cf_ngtcp2_ctx_init(struct cf_ngtcp2_ctx *ctx,
+@@ -156,6 +157,7 @@ CURLcode Curl_cf_ngtcp2_ctx_init(struct cf_ngtcp2_ctx *ctx,
struct Curl_peer *origin,
struct Curl_peer *peer,
struct ssl_primary_config *sslc,
@@ -8598,7 +8526,7 @@ index 88554edfb6..97a5ddd737 100644
void Curl_cf_ngtcp2_ctx_cleanup(struct cf_ngtcp2_ctx *ctx);
void Curl_cf_ngtcp2_cmn_err_set(struct Curl_cfilter *cf,
diff --git a/lib/vquic/cf-ngtcp2-proxy.c b/lib/vquic/cf-ngtcp2-proxy.c
-index fd2840890f..19e0c2b777 100644
+index 89bf19cc27..aa83690920 100644
--- a/lib/vquic/cf-ngtcp2-proxy.c
+++ b/lib/vquic/cf-ngtcp2-proxy.c
@@ -176,12 +176,13 @@ static CURLcode cf_h3_proxy_ctx_init(struct cf_h3_proxy_ctx *ctx,
@@ -8616,7 +8544,7 @@ index fd2840890f..19e0c2b777 100644
if(!result)
result = h3_tunnel_stream_init(&ctx->tunnel, tunnel_peer,
TRNSPRT_IS_DGRAM(tunnel_transport));
-@@ -1244,7 +1245,7 @@ CURLcode Curl_cf_ngtcp2_proxy_create(struct Curl_cfilter **pcf,
+@@ -1257,7 +1258,7 @@ CURLcode Curl_cf_ngtcp2_proxy_create(struct Curl_cfilter **pcf,
goto out;
}
result = cf_h3_proxy_ctx_init(ctx, origin, peer, &conn->proxy_ssl_config,
@@ -8625,7 +8553,7 @@ index fd2840890f..19e0c2b777 100644
if(result)
goto out;
-@@ -1290,7 +1291,7 @@ CURLcode Curl_cf_ngtcp2_proxy_insert_after(struct Curl_cfilter *cf_at,
+@@ -1303,7 +1304,7 @@ CURLcode Curl_cf_ngtcp2_proxy_insert_after(struct Curl_cfilter *cf_at,
goto out;
result = cf_h3_proxy_ctx_init(ctx, origin, peer,
&cf_at->conn->proxy_ssl_config,
@@ -8635,12 +8563,12 @@ index fd2840890f..19e0c2b777 100644
goto out;
diff --git a/lib/vquic/cf-ngtcp2.c b/lib/vquic/cf-ngtcp2.c
-index be1a3257c3..5c79a9e613 100644
+index e3bca8774e..67a7f0d6e0 100644
--- a/lib/vquic/cf-ngtcp2.c
+++ b/lib/vquic/cf-ngtcp2.c
-@@ -412,10 +412,182 @@ static nghttp3_callbacks ngh3_callbacks = {
+@@ -423,10 +423,182 @@ static nghttp3_callbacks ngh3_callbacks = {
+ #pragma GCC diagnostic pop
#endif
- };
+static void h3_apply_setting(nghttp3_settings *settings,
+ unsigned long id, uint64_t value)
@@ -8747,7 +8675,7 @@ index be1a3257c3..5c79a9e613 100644
+ nghttp3_settings *settings,
+ struct Curl_easy *data)
+{
-+ const char *h3_settings = data->set.str[STRING_HTTP3_SETTINGS];
++ const char *h3_settings = CURL_EASY_STR(data, STRING_HTTP3_SETTINGS);
+ char *tmp;
+ char *setting;
+ size_t i = 0;
@@ -8814,14 +8742,14 @@ index be1a3257c3..5c79a9e613 100644
struct Curl_easy *data,
struct cf_ngtcp2_ctx *ctx)
{
-+ const char *h3_settings = data->set.str[STRING_HTTP3_SETTINGS];
++ const char *h3_settings = CURL_EASY_STR(data, STRING_HTTP3_SETTINGS);
+ nghttp3_settings_entry *h3iv = NULL;
+ size_t h3ivalloc = 0;
+ size_t h3ivlen = 0;
int rc;
if(ngtcp2_conn_get_streams_uni_left(ctx->qconn) < 3) {
-@@ -423,7 +595,16 @@ static CURLcode init_ngh3_conn(struct Curl_cfilter *cf,
+@@ -434,7 +606,16 @@ static CURLcode init_ngh3_conn(struct Curl_cfilter *cf,
return CURLE_QUIC_CONNECT_ERROR;
}
@@ -8838,7 +8766,7 @@ index be1a3257c3..5c79a9e613 100644
rc = nghttp3_conn_client_new(&ctx->h3conn,
&ngh3_callbacks,
-@@ -431,10 +612,23 @@ static CURLcode init_ngh3_conn(struct Curl_cfilter *cf,
+@@ -442,10 +623,23 @@ static CURLcode init_ngh3_conn(struct Curl_cfilter *cf,
Curl_nghttp3_mem(),
cf);
if(rc) {
@@ -8862,7 +8790,7 @@ index be1a3257c3..5c79a9e613 100644
return Curl_cf_ngtcp2_h3_init_ctrls(ctx, data);
}
-@@ -1105,7 +1299,7 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf,
+@@ -1118,7 +1312,7 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf,
goto out;
}
result = Curl_cf_ngtcp2_ctx_init(ctx, origin, peer,
@@ -8871,7 +8799,7 @@ index be1a3257c3..5c79a9e613 100644
if(!result)
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
if(result)
-@@ -1146,7 +1340,8 @@ CURLcode Curl_cf_ngtcp2_insert_after(struct Curl_cfilter *cf_at,
+@@ -1159,7 +1353,8 @@ CURLcode Curl_cf_ngtcp2_insert_after(struct Curl_cfilter *cf_at,
goto out;
}
result = Curl_cf_ngtcp2_ctx_init(ctx, origin, peer,
@@ -8882,10 +8810,10 @@ index be1a3257c3..5c79a9e613 100644
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
if(result)
diff --git a/lib/vquic/cf-quiche.c b/lib/vquic/cf-quiche.c
-index 31a3957ec3..db1d63db0a 100644
+index 934a56cada..bdd0d482c7 100644
--- a/lib/vquic/cf-quiche.c
+++ b/lib/vquic/cf-quiche.c
-@@ -110,7 +110,8 @@ static void h3_stream_hash_free(unsigned int id, void *stream);
+@@ -112,7 +112,8 @@ static void h3_stream_hash_free(unsigned int id, void *stream);
static CURLcode cf_quiche_ctx_init(struct cf_quiche_ctx *ctx,
struct Curl_peer *origin,
struct Curl_peer *peer,
@@ -8895,7 +8823,7 @@ index 31a3957ec3..db1d63db0a 100644
{
DEBUGASSERT(!ctx->initialized);
#ifdef DEBUG_QUICHE
-@@ -125,7 +126,7 @@ static CURLcode cf_quiche_ctx_init(struct cf_quiche_ctx *ctx,
+@@ -127,7 +128,7 @@ static CURLcode cf_quiche_ctx_init(struct cf_quiche_ctx *ctx,
BUFQ_OPT_SOFT_LIMIT);
ctx->data_recvd = 0;
ctx->initialized = TRUE;
@@ -8924,7 +8852,7 @@ index 31a3957ec3..db1d63db0a 100644
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
if(result)
diff --git a/lib/vquic/vquic-tls.c b/lib/vquic/vquic-tls.c
-index 58f139306a..5e9a7cf836 100644
+index 75e2f4e1e2..0f13057314 100644
--- a/lib/vquic/vquic-tls.c
+++ b/lib/vquic/vquic-tls.c
@@ -52,7 +52,8 @@
@@ -8961,20 +8889,20 @@ index e8d2418b06..37a74ba094 100644
/**
* Initialize the QUIC TLS instances based of the SSL configurations
diff --git a/lib/vquic/vquic.c b/lib/vquic/vquic.c
-index dfb8346c1a..602402e256 100644
+index bbc5777eac..c08e528427 100644
--- a/lib/vquic/vquic.c
+++ b/lib/vquic/vquic.c
-@@ -41,6 +41,9 @@
+@@ -52,6 +52,9 @@
#include "curlx/dynbuf.h"
#include "curlx/fopen.h"
#include "cfilters.h"
+#include "cf-socket.h"
+#include "sockaddr.h"
+#include "socks.h"
+ #include "vdns/cf-dns.h"
#include "vquic/cf-ngtcp2.h"
#include "vquic/cf-ngtcp2-cmn.h"
- #include "vquic/cf-ngtcp2-proxy.h"
-@@ -52,6 +55,38 @@
+@@ -64,6 +67,38 @@
#include "curlx/strerr.h"
#include "curlx/strparse.h"
@@ -9013,7 +8941,7 @@ index dfb8346c1a..602402e256 100644
#define NW_CHUNK_SIZE (64 * 1024)
#define NW_SEND_CHUNKS 1
-@@ -307,6 +342,38 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
+@@ -442,6 +477,38 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
size_t gsolen, size_t *psent)
{
CURLcode result;
@@ -9052,7 +8980,7 @@ index dfb8346c1a..602402e256 100644
#ifdef DEBUGBUILD
/* simulate network blocking/partial writes */
if(qctx->wblock_percent > 0) {
-@@ -492,7 +559,7 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
+@@ -687,7 +754,7 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
}
if(!cf->connected && SOCKERRNO == SOCKECONNREFUSED) {
struct ip_quadruple ip;
@@ -9061,7 +8989,7 @@ index dfb8346c1a..602402e256 100644
failf(data, "QUIC: connection to %s port %u refused",
ip.remote_ip, ip.remote_port);
result = CURLE_COULDNT_CONNECT;
-@@ -578,7 +645,7 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
+@@ -886,7 +953,7 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
}
if(!cf->connected && SOCKERRNO == SOCKECONNREFUSED) {
struct ip_quadruple ip;
@@ -9070,7 +8998,7 @@ index dfb8346c1a..602402e256 100644
failf(data, "QUIC: connection to %s port %u refused",
ip.remote_ip, ip.remote_port);
result = CURLE_COULDNT_CONNECT;
-@@ -649,7 +716,7 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf,
+@@ -958,7 +1025,7 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf,
}
if(!cf->connected && SOCKERRNO == SOCKECONNREFUSED) {
struct ip_quadruple ip;
@@ -9079,8 +9007,8 @@ index dfb8346c1a..602402e256 100644
failf(data, "QUIC: connection to %s port %u refused",
ip.remote_ip, ip.remote_port);
result = CURLE_COULDNT_CONNECT;
-@@ -692,7 +759,55 @@ CURLcode vquic_recv_packets(struct Curl_cfilter *cf,
- vquic_recv_pkts_cb *recv_cb, void *userp)
+@@ -1001,7 +1068,55 @@ CURLcode Curl_vquic_recv_packets(struct Curl_cfilter *cf,
+ Curl_vquic_recv_pkts_cb *recv_cb, void *userp)
{
CURLcode result;
-#ifdef HAVE_SENDMMSG
@@ -9134,9 +9062,9 @@ index dfb8346c1a..602402e256 100644
+ else
+#if defined(HAVE_SENDMMSG)
result = recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
- #elif defined(HAVE_SENDMSG)
- result = recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
-@@ -872,14 +987,7 @@ CURLcode Curl_conn_may_http3(struct Curl_easy *data,
+ #elif defined(HAVE_APPLE_MSG_X)
+ result = recvmsg_x_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+@@ -1200,14 +1315,7 @@ CURLcode Curl_conn_may_http3(struct Curl_easy *data,
failf(data, "HTTP/3 requested for non-HTTPS URL");
return CURLE_URL_MALFORMAT;
}
@@ -9152,12 +9080,12 @@ index dfb8346c1a..602402e256 100644
return CURLE_OK;
}
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
-index 010bbb9825..4cc9b96fc7 100644
+index dedd8f3e70..a65c5ddda6 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
-@@ -39,6 +39,7 @@
+@@ -37,6 +37,7 @@
+ #include "vtls/openssl.h"
#include "connect.h"
- #include "cf-dns.h"
#include "progress.h"
+#include "rand.h"
#include "vtls/vtls.h"
@@ -9307,7 +9235,7 @@ index 010bbb9825..4cc9b96fc7 100644
typedef uint32_t sslerr_t;
#else
typedef int numcert_t;
-@@ -2453,6 +2581,191 @@ static const char *tls_rt_type(int type)
+@@ -2443,6 +2571,191 @@ static const char *tls_rt_type(int type)
}
}
@@ -9499,7 +9427,7 @@ index 010bbb9825..4cc9b96fc7 100644
/*
* Our callback from the SSL/TLS layers.
*/
-@@ -3449,6 +3762,11 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
+@@ -3482,6 +3795,11 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
if(!CURLECH_ENABLED(data))
return CURLE_OK;
@@ -9511,7 +9439,7 @@ index 010bbb9825..4cc9b96fc7 100644
if(data->set.tls_ech == CURLECH_GREASE) {
infof(data, "ECH: will GREASE ClientHello");
#ifdef HAVE_BORINGSSL_LIKE
-@@ -3545,11 +3863,18 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
+@@ -3583,11 +3901,18 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
}
}
#endif /* HAVE_BORINGSSL_LIKE */
@@ -9532,7 +9460,7 @@ index 010bbb9825..4cc9b96fc7 100644
return CURLE_OK;
}
-@@ -3569,6 +3894,11 @@ static CURLcode ossl_init_ssl(struct ossl_ctx *octx,
+@@ -3607,6 +3932,11 @@ static CURLcode ossl_init_ssl(struct ossl_ctx *octx,
void *ssl_user_data,
Curl_ossl_init_session_reuse_cb *sess_reuse_cb)
{
@@ -9544,7 +9472,7 @@ index 010bbb9825..4cc9b96fc7 100644
/* Let's make an SSL structure */
if(octx->ssl)
SSL_free(octx->ssl);
-@@ -3580,6 +3910,34 @@ static CURLcode ossl_init_ssl(struct ossl_ctx *octx,
+@@ -3618,6 +3948,34 @@ static CURLcode ossl_init_ssl(struct ossl_ctx *octx,
SSL_set_app_data(octx->ssl, ssl_user_data);
@@ -9579,7 +9507,7 @@ index 010bbb9825..4cc9b96fc7 100644
#ifndef OPENSSL_NO_OCSP
if(Curl_ssl_cf_get_primary_config(cf)->verifystatus)
SSL_set_tlsext_status_type(octx->ssl, TLSEXT_STATUSTYPE_ocsp);
-@@ -3659,6 +4017,120 @@ static CURLcode ossl_init_method(struct Curl_cfilter *cf,
+@@ -3697,6 +4055,120 @@ static CURLcode ossl_init_method(struct Curl_cfilter *cf,
return *pmethod ? CURLE_OK : CURLE_SSL_CONNECT_ERROR;
}
@@ -9700,9 +9628,9 @@ index 010bbb9825..4cc9b96fc7 100644
CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
struct Curl_cfilter *cf,
struct Curl_easy *data,
-@@ -3759,7 +4231,15 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
- SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit must not be set.
- */
+@@ -3801,7 +4273,15 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
+ workarounds. In order to keep the secure workaround, the
+ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit must not be set. */
- ctx_options = SSL_OP_ALL | SSL_OP_NO_TICKET | SSL_OP_NO_COMPRESSION;
+ ctx_options = SSL_OP_ALL;
@@ -9717,7 +9645,7 @@ index 010bbb9825..4cc9b96fc7 100644
/* mitigate CVE-2010-4180 */
ctx_options &= ~(ctx_option_t)SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
-@@ -3815,10 +4295,29 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
+@@ -3857,10 +4337,29 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
/* We do retry writes sometimes from another buffer address */
SSL_CTX_set_mode(octx->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
@@ -9747,7 +9675,7 @@ index 010bbb9825..4cc9b96fc7 100644
if(!SSL_CTX_set_cipher_list(octx->ssl_ctx, ciphers)) {
failf(data, "failed setting cipher list: %s", ciphers);
return CURLE_SSL_CIPHER;
-@@ -3859,7 +4358,8 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
+@@ -3901,7 +4400,8 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
#endif
{
@@ -9757,7 +9685,7 @@ index 010bbb9825..4cc9b96fc7 100644
if(curves) {
#ifdef HAVE_BORINGSSL_LIKE
#define OSSL_CURVE_CAST(x) (x)
-@@ -3873,10 +4373,12 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
+@@ -3915,10 +4415,12 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
}
}
@@ -9772,7 +9700,7 @@ index 010bbb9825..4cc9b96fc7 100644
if(signature_algorithms) {
if(!SSL_CTX_set1_sigalgs_list(octx->ssl_ctx,
OSSL_SIGALG_CAST(signature_algorithms))) {
-@@ -3888,6 +4390,35 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
+@@ -3930,6 +4432,104 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
}
#endif
@@ -9805,13 +9733,6 @@ index 010bbb9825..4cc9b96fc7 100644
+ }
+#endif
+
- #if defined(HAVE_OPENSSL_SRP) && defined(USE_TLS_SRP)
- if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) {
- char * const ssl_username = ssl_config->primary.username;
-@@ -3913,6 +4444,76 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
- }
- #endif /* HAVE_OPENSSL_SRP && USE_TLS_SRP */
-
+#ifdef OPENSSL_IS_BORINGSSL
+ /* curl-impersonate:
+ * Configure BoringSSL to behave like Chrome.
@@ -9857,9 +9778,9 @@ index 010bbb9825..4cc9b96fc7 100644
+ }
+ }
+
-+ if(data->set.str[STRING_TLS_DELEGATED_CREDENTIALS])
++ if(CURL_EASY_STR(data, STRING_TLS_DELEGATED_CREDENTIALS))
+ SSL_CTX_set_delegated_credentials(
-+ octx->ssl_ctx, data->set.str[STRING_TLS_DELEGATED_CREDENTIALS]);
++ octx->ssl_ctx, CURL_EASY_STR(data, STRING_TLS_DELEGATED_CREDENTIALS));
+
+ if(data->set.tls_record_size_limit)
+ SSL_CTX_set_record_size_limit(octx->ssl_ctx,
@@ -9881,11 +9802,10 @@ index 010bbb9825..4cc9b96fc7 100644
+ conn_config->cert_compression))
+ return CURLE_SSL_CIPHER;
+#endif /* OPENSSL_IS_BORINGSSL */
-+
/* OpenSSL always tries to verify the peer. By setting the failure mode
* to NONE, we allow the connect to complete, regardless of the outcome.
* We then explicitly check the result and may try alternatives like
-@@ -4253,8 +4854,10 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
+@@ -4271,8 +4871,10 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
#endif
else {
result = CURLE_SSL_CONNECT_ERROR;
@@ -9898,7 +9818,7 @@ index 010bbb9825..4cc9b96fc7 100644
}
/* detail is already set to the SSL error above */
-@@ -4267,10 +4870,20 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
+@@ -4285,10 +4887,20 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
char extramsg[80] = "";
int sockerr = SOCKERRNO;
@@ -9922,7 +9842,7 @@ index 010bbb9825..4cc9b96fc7 100644
connssl->peer.origin->hostname, connssl->peer.origin->port);
}
-@@ -4282,6 +4895,22 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
+@@ -4300,6 +4912,22 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
connssl->connecting_state = ssl_connect_3;
Curl_ossl_report_handshake(data, octx);
@@ -9946,10 +9866,10 @@ index 010bbb9825..4cc9b96fc7 100644
if(CURLECH_ENABLED(data)) {
char *inner = NULL, *outer = NULL;
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
-index 82ce007b3d..7a7531c187 100644
+index f6cc370890..7aab258dcf 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
-@@ -123,6 +123,20 @@ static const struct alpn_spec *alpn_get_spec(http_majors wanted,
+@@ -120,6 +120,20 @@ static const struct alpn_spec *alpn_get_spec(http_majors wanted,
#endif
return &ALPN_SPEC_H11;
}
@@ -9970,7 +9890,7 @@ index 82ce007b3d..7a7531c187 100644
#endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_PROXY */
#endif /* USE_SSL */
-@@ -188,7 +202,8 @@ static bool ssl_prefs_check(struct Curl_easy *data)
+@@ -185,7 +199,8 @@ static bool ssl_prefs_check(struct Curl_easy *data)
}
static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data,
@@ -9980,7 +9900,7 @@ index 82ce007b3d..7a7531c187 100644
{
struct ssl_connect_data *ctx;
-@@ -199,6 +214,7 @@ static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data,
+@@ -196,6 +211,7 @@ static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data,
ctx->ssl_impl = Curl_ssl;
ctx->alpn = alpn;
@@ -9988,7 +9908,7 @@ index 82ce007b3d..7a7531c187 100644
Curl_bufq_init2(&ctx->earlydata, CURL_SSL_EARLY_MAX, 1, BUFQ_OPT_NO_SPARES);
ctx->backend = curlx_calloc(1, ctx->ssl_impl->sizeof_ssl_backend_data);
if(!ctx->backend) {
-@@ -914,7 +930,8 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *ssl_peer,
+@@ -898,7 +914,8 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *ssl_peer,
struct Curl_peer *peer,
struct ssl_primary_config *sslc,
const char *tls_id,
@@ -9998,7 +9918,7 @@ index 82ce007b3d..7a7531c187 100644
{
CURLcode result = CURLE_OUT_OF_MEMORY;
-@@ -946,8 +963,8 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *ssl_peer,
+@@ -930,8 +947,8 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *ssl_peer,
}
}
@@ -10009,7 +9929,7 @@ index 82ce007b3d..7a7531c187 100644
out:
if(result)
-@@ -1365,12 +1382,14 @@ static CURLcode cf_ssl_create(struct Curl_cfilter **pcf,
+@@ -1359,12 +1376,14 @@ static CURLcode cf_ssl_create(struct Curl_cfilter **pcf,
(void)conn;
/* We only support ALPN for HTTP so far. */
DEBUGASSERT(!conn->bits.tls_enable_alpn);
@@ -10026,7 +9946,7 @@ index 82ce007b3d..7a7531c187 100644
#endif
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
-@@ -1395,7 +1414,7 @@ static CURLcode cf_ssl_peer_init(struct Curl_cfilter *cf,
+@@ -1389,7 +1408,7 @@ static CURLcode cf_ssl_peer_init(struct Curl_cfilter *cf,
char tls_id[80];
connssl->ssl_impl->version(tls_id, sizeof(tls_id) - 1);
return Curl_ssl_peer_init(&connssl->peer, origin, peer, sslc,
@@ -10035,7 +9955,7 @@ index 82ce007b3d..7a7531c187 100644
}
CURLcode Curl_ssl_cfilter_add(struct Curl_easy *data,
-@@ -1447,9 +1466,9 @@ static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf,
+@@ -1453,9 +1472,9 @@ static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf,
CURLcode result;
/* ALPN is default, but if user explicitly disables it, obey */
bool use_alpn = (bool)data->set.ssl_enable_alpn;
@@ -10046,7 +9966,7 @@ index 82ce007b3d..7a7531c187 100644
#ifdef USE_HTTP2
if(conn->http_proxy.proxytype == CURLPROXY_HTTPS2) {
use_alpn = TRUE;
-@@ -1457,7 +1476,8 @@ static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf,
+@@ -1463,7 +1482,8 @@ static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf,
}
#endif
@@ -10057,7 +9977,7 @@ index 82ce007b3d..7a7531c187 100644
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
-index 96cb7d15ed..ca72a31d28 100644
+index 8ee22c8d5a..ca2d807bd8 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -64,6 +64,8 @@ struct dynbuf;
@@ -10080,10 +10000,10 @@ index 96cb7d15ed..ca72a31d28 100644
* Free all allocated data and reset peer information.
*/
diff --git a/lib/vtls/vtls_config.c b/lib/vtls/vtls_config.c
-index 4a9b69654b..3cf4f3ed1e 100644
+index 080d513bb5..6d1a69a5ed 100644
--- a/lib/vtls/vtls_config.c
+++ b/lib/vtls/vtls_config.c
-@@ -112,6 +112,51 @@ void Curl_ssl_config_init(struct ssl_primary_config *sslc)
+@@ -108,6 +108,51 @@ void Curl_ssl_config_init(struct ssl_primary_config *sslc)
sslc->cache_session = TRUE; /* caching by default */
}
@@ -10135,7 +10055,7 @@ index 4a9b69654b..3cf4f3ed1e 100644
void Curl_ssl_config_cleanup(struct ssl_primary_config *sslc)
{
if(sslc->deep_copy) {
-@@ -127,7 +172,13 @@ void Curl_ssl_config_cleanup(struct ssl_primary_config *sslc)
+@@ -123,7 +168,13 @@ void Curl_ssl_config_cleanup(struct ssl_primary_config *sslc)
curlx_safefree(sslc->issuercert_blob);
curlx_safefree(sslc->key_blob);
curlx_safefree(sslc->curves);
@@ -10149,7 +10069,7 @@ index 4a9b69654b..3cf4f3ed1e 100644
curlx_safefree(sslc->CRLfile);
curlx_safefree(sslc->cert_type);
curlx_safefree(sslc->key);
-@@ -152,6 +203,9 @@ static bool match_ssl_primary_config(struct Curl_easy *data,
+@@ -145,6 +196,9 @@ static bool match_ssl_primary_config(struct Curl_easy *data,
(c1->verifypeer == c2->verifypeer) &&
(c1->verifyhost == c2->verifyhost) &&
(c1->verifystatus == c2->verifystatus) &&
@@ -10159,7 +10079,7 @@ index 4a9b69654b..3cf4f3ed1e 100644
blobcmp(c1->cert_blob, c2->cert_blob) &&
blobcmp(c1->ca_info_blob, c2->ca_info_blob) &&
blobcmp(c1->issuercert_blob, c2->issuercert_blob) &&
-@@ -167,7 +221,15 @@ static bool match_ssl_primary_config(struct Curl_easy *data,
+@@ -156,7 +210,15 @@ static bool match_ssl_primary_config(struct Curl_easy *data,
curl_strequal(c1->cipher_list, c2->cipher_list) &&
curl_strequal(c1->cipher_list13, c2->cipher_list13) &&
curl_strequal(c1->curves, c2->curves) &&
@@ -10175,9 +10095,9 @@ index 4a9b69654b..3cf4f3ed1e 100644
Curl_safecmp(c1->CRLfile, c2->CRLfile) &&
Curl_safecmp(c1->pinned_key, c2->pinned_key) &&
curl_strequal(c1->cert_type, c2->cert_type) &&
-@@ -205,6 +267,9 @@ static bool clone_ssl_primary_config(struct ssl_primary_config *source,
- dest->verifyhost = source->verifyhost;
+@@ -195,6 +257,9 @@ static bool clone_ssl_primary_config(struct ssl_primary_config *source,
dest->verifystatus = source->verifystatus;
+ dest->native_ca_store = source->native_ca_store;
dest->cache_session = source->cache_session;
+ dest->enable_ticket = source->enable_ticket;
+ dest->http3_ssl_permute_extensions =
@@ -10185,7 +10105,7 @@ index 4a9b69654b..3cf4f3ed1e 100644
dest->ssl_options = source->ssl_options;
CLONE_BLOB(cert_blob);
-@@ -217,7 +282,13 @@ static bool clone_ssl_primary_config(struct ssl_primary_config *source,
+@@ -207,7 +272,13 @@ static bool clone_ssl_primary_config(struct ssl_primary_config *source,
CLONE_STRING(cipher_list13);
CLONE_STRING(pinned_key);
CLONE_STRING(curves);
@@ -10197,10 +10117,10 @@ index 4a9b69654b..3cf4f3ed1e 100644
+ CLONE_STRING(http3_tls_extension_order);
+ CLONE_STRING(trust_anchors);
CLONE_STRING(CRLfile);
- /* SSL credentials: client certificate, SRP auth */
+ /* SSL credentials: client certificate */
CLONE_STRING(clientcert);
-@@ -253,10 +324,13 @@ static void ssl_easy_config_compl_options(struct Curl_peer *origin,
- !!(options & CURLSSLOPT_AUTO_CLIENT_CERT);
+@@ -245,10 +316,13 @@ static char *ssl_easy_steal(struct Curl_easy *data, enum dupstring id)
+ return CURL_UNCONST(CURL_EASY_STR(data, id));
}
-CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
@@ -10213,45 +10133,47 @@ index 4a9b69654b..3cf4f3ed1e 100644
+ const bool is_wss = conn && conn->scheme &&
+ (conn->scheme->protocol & CURLPROTO_WSS);
#if defined(CURL_CA_PATH) || defined(CURL_CA_BUNDLE)
- struct UserDefined *set = &data->set;
CURLcode result;
-@@ -293,6 +367,27 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
- data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS];
+ #endif
+@@ -284,6 +358,29 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
+ ssl_easy_steal(data, STRING_SSL_SIGNATURE_ALGORITHMS);
sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
- sslc->primary.curves = data->set.str[STRING_SSL_EC_CURVES];
+ sslc->primary.curves = ssl_easy_steal(data, STRING_SSL_EC_CURVES);
+ sslc->primary.tls_extension_order =
-+ data->set.str[STRING_TLS_EXTENSION_ORDER];
++ ssl_easy_steal(data, STRING_TLS_EXTENSION_ORDER);
+ sslc->primary.cert_compression =
-+ data->set.str[STRING_SSL_CERT_COMPRESSION];
-+ sslc->primary.http3_curves = data->set.str[STRING_HTTP3_SSL_EC_CURVES];
++ ssl_easy_steal(data, STRING_SSL_CERT_COMPRESSION);
++ sslc->primary.http3_curves =
++ ssl_easy_steal(data, STRING_HTTP3_SSL_EC_CURVES);
+ sslc->primary.http3_signature_algorithms =
-+ data->set.str[STRING_HTTP3_SIG_HASH_ALGS];
++ ssl_easy_steal(data, STRING_HTTP3_SIG_HASH_ALGS);
+ sslc->primary.http3_tls_extension_order =
-+ data->set.str[STRING_HTTP3_TLS_EXTENSION_ORDER];
++ ssl_easy_steal(data, STRING_HTTP3_TLS_EXTENSION_ORDER);
+ sslc->primary.enable_ticket = data->set.ssl_enable_ticket;
-+ sslc->primary.trust_anchors = data->set.str[STRING_TLS_TRUST_ANCHORS];
++ sslc->primary.trust_anchors =
++ ssl_easy_steal(data, STRING_TLS_TRUST_ANCHORS);
+ sslc->primary.http3_ssl_permute_extensions =
+ Curl_ssl_http3_permute_extensions(data);
+
+ if(is_wss) {
+ if(data->set.ws_disable_session_ticket)
+ sslc->primary.enable_ticket = FALSE;
-+ if(data->set.str[STRING_WS_SSL_CERT_COMPRESSION])
++ if(CURL_EASY_STR(data, STRING_WS_SSL_CERT_COMPRESSION))
+ sslc->primary.cert_compression =
-+ data->set.str[STRING_WS_SSL_CERT_COMPRESSION];
++ ssl_easy_steal(data, STRING_WS_SSL_CERT_COMPRESSION);
+ }
/* Maybe these should not be used for another origin. But for
* backwards compatibility, keep them in. */
- sslc->primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
-@@ -358,6 +453,7 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
- sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
- sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
- sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
+ sslc->primary.issuercert = ssl_easy_steal(data, STRING_SSL_ISSUERCERT);
+@@ -346,6 +443,7 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
+ ssl_easy_steal(data, STRING_SSL_CIPHER13_LIST_PROXY);
+ sslc->primary.pinned_key =
+ ssl_easy_steal(data, STRING_SSL_PINNEDPUBLICKEY_PROXY);
+ sslc->primary.enable_ticket = data->set.ssl_enable_ticket;
- sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
sslc->primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO_PROXY];
-@@ -379,6 +475,18 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
+ sslc->primary.issuercert = ssl_easy_steal(data, STRING_SSL_ISSUERCERT_PROXY);
+@@ -362,6 +460,18 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
return CURLE_OK;
}
@@ -10271,12 +10193,12 @@ index 4a9b69654b..3cf4f3ed1e 100644
struct connectdata *conn)
{
diff --git a/lib/vtls/vtls_config.h b/lib/vtls/vtls_config.h
-index 44e691dd26..a4c0f8a706 100644
+index 8296604259..0921cb137b 100644
--- a/lib/vtls/vtls_config.h
+++ b/lib/vtls/vtls_config.h
-@@ -52,6 +52,12 @@ struct ssl_primary_config {
- char *password; /* TLS password (for, e.g., SRP) */
- #endif
+@@ -48,6 +48,12 @@ struct ssl_primary_config {
+ struct curl_blob *issuercert_blob;
+ struct curl_blob *key_blob;
char *curves; /* list of curves to use */
+ char *tls_extension_order; /* TLS extension order to use */
+ char *cert_compression; /* certificate compression algorithms */
@@ -10287,16 +10209,16 @@ index 44e691dd26..a4c0f8a706 100644
uint32_t version_max; /* max supported version the client wants to use */
uint8_t ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */
uint8_t version; /* what version the client wants to use */
-@@ -59,6 +65,8 @@ struct ssl_primary_config {
- BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
+@@ -56,6 +62,8 @@ struct ssl_primary_config {
BIT(verifystatus); /* set TRUE if certificate status must be checked */
+ BIT(native_ca_store); /* use the native CA store of operating system */
BIT(cache_session); /* cache session or not */
+ BIT(enable_ticket); /* enable the TLS session ticket extension */
+ BIT(http3_ssl_permute_extensions); /* HTTP/3 TLS extension permutation */
BIT(deep_copy); /* members are deep copies, eg. owned here */
};
-@@ -89,6 +97,14 @@ struct ssl_general_config {
+@@ -85,6 +93,14 @@ struct ssl_general_config {
void Curl_ssl_config_init(struct ssl_primary_config *sslc);
void Curl_ssl_config_cleanup(struct ssl_primary_config *sslc);
@@ -10311,7 +10233,7 @@ index 44e691dd26..a4c0f8a706 100644
/**
* Init the `data->set.ssl` and `data->set.proxy_ssl` for
* connection matching use.
-@@ -96,6 +112,12 @@ void Curl_ssl_config_cleanup(struct ssl_primary_config *sslc);
+@@ -92,6 +108,12 @@ void Curl_ssl_config_cleanup(struct ssl_primary_config *sslc);
CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
struct Curl_peer *origin);
@@ -10325,7 +10247,7 @@ index 44e691dd26..a4c0f8a706 100644
* Init SSL configs (main + proxy) for a new connection from the easy handle.
*/
diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h
-index fa5da6e4d5..45aeb422c2 100644
+index 7c1881b8d8..8727b9912f 100644
--- a/lib/vtls/vtls_int.h
+++ b/lib/vtls/vtls_int.h
@@ -114,6 +114,7 @@ struct ssl_connect_data {
@@ -10335,12 +10257,12 @@ index fa5da6e4d5..45aeb422c2 100644
+ const struct alpn_spec *alps; /* ALPS to use or NULL for none */
void *backend; /* vtls backend specific props */
struct cf_call_data call_data; /* data handle used in current call */
- struct curltime handshake_done; /* time when handshake finished */
+ struct Curl_ssl_session *session; /* TLS session in use or NULL */
diff --git a/lib/vtls/vtls_scache.c b/lib/vtls/vtls_scache.c
-index 98beeac036..7f673e354c 100644
+index c703302be8..f98241739a 100644
--- a/lib/vtls/vtls_scache.c
+++ b/lib/vtls/vtls_scache.c
-@@ -228,10 +228,16 @@ static CURLcode ssl_peer_key_add_vrfy(struct dynbuf *buf,
+@@ -227,10 +227,16 @@ static CURLcode ssl_peer_key_add_vrfy(struct dynbuf *buf,
static CURLcode ssl_peer_key_build(struct ssl_primary_config *ssl,
const struct ssl_peer *peer,
@@ -10357,7 +10279,7 @@ index 98beeac036..7f673e354c 100644
size_t key_len;
bool is_local = FALSE;
CURLcode result;
-@@ -260,6 +266,22 @@ static CURLcode ssl_peer_key_build(struct ssl_primary_config *ssl,
+@@ -259,6 +265,22 @@ static CURLcode ssl_peer_key_build(struct ssl_primary_config *ssl,
if(result)
goto out;
}
@@ -10380,7 +10302,7 @@ index 98beeac036..7f673e354c 100644
if(ssl->cipher_list) {
result = curlx_dyn_addf(&buf, ":CIPHER-%s", ssl->cipher_list);
if(result)
-@@ -270,17 +292,65 @@ static CURLcode ssl_peer_key_build(struct ssl_primary_config *ssl,
+@@ -269,17 +291,65 @@ static CURLcode ssl_peer_key_build(struct ssl_primary_config *ssl,
if(result)
goto out;
}
@@ -10451,7 +10373,7 @@ index 98beeac036..7f673e354c 100644
if(ssl->verifypeer) {
result = cf_ssl_peer_key_add_path(&buf, "CA", ssl->CAfile, &is_local);
if(result)
-@@ -356,7 +426,16 @@ CURLcode Curl_ssl_peer_key_make(const struct ssl_peer *peer,
+@@ -348,7 +418,16 @@ CURLcode Curl_ssl_peer_key_make(const struct ssl_peer *peer,
const char *tls_id,
char **ppeer_key)
{
@@ -10470,7 +10392,7 @@ index 98beeac036..7f673e354c 100644
struct Curl_ssl_scache {
diff --git a/lib/vtls/vtls_scache.h b/lib/vtls/vtls_scache.h
-index effb1d8f96..a0a8e2f596 100644
+index c9f35e800f..2f76a32755 100644
--- a/lib/vtls/vtls_scache.h
+++ b/lib/vtls/vtls_scache.h
@@ -66,6 +66,12 @@ CURLcode Curl_ssl_peer_key_make(const struct ssl_peer *peer,
@@ -10487,10 +10409,10 @@ index effb1d8f96..a0a8e2f596 100644
* An SSL session might not be configured or not available for
* "connect-only" transfers.
diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
-index 92eaa7a751..44618edc29 100644
+index 4b9facadf0..f06fdf74f8 100644
--- a/lib/vtls/wolfssl.c
+++ b/lib/vtls/wolfssl.c
-@@ -1129,9 +1129,11 @@ static CURLcode wssl_init_ciphers(struct Curl_easy *data,
+@@ -1144,9 +1144,11 @@ static CURLcode wssl_init_ciphers(struct Curl_easy *data,
static CURLcode wssl_init_curves(struct Curl_easy *data,
struct wssl_ctx *wctx,
@@ -10504,7 +10426,7 @@ index 92eaa7a751..44618edc29 100644
/* Without an explicit list, leave the key share group selection to
wolfSSL's own default. */
if(curves && !wssl_CTX_set1_groups_list(wctx->ssl_ctx, curves)) {
-@@ -1338,7 +1340,7 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx,
+@@ -1375,7 +1377,7 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx,
if(result)
goto out;
@@ -10514,7 +10436,7 @@ index 92eaa7a751..44618edc29 100644
goto out;
diff --git a/lib/ws.c b/lib/ws.c
-index 9820c3e4bd..fd125d35d4 100644
+index a7653df678..059d278ecf 100644
--- a/lib/ws.c
+++ b/lib/ws.c
@@ -27,6 +27,20 @@
@@ -10538,7 +10460,7 @@ index 9820c3e4bd..fd125d35d4 100644
#include "url.h"
#include "bufq.h"
#include "curlx/dynbuf.h"
-@@ -71,8 +85,225 @@
+@@ -70,8 +84,225 @@
#define WSBIT_MASK 0x80
/* buffer dimensioning */
@@ -10766,7 +10688,7 @@ index 9820c3e4bd..fd125d35d4 100644
/* a client-side WS frame decoder, parsing frame headers and
* payload, keeping track of current position and stats */
-@@ -102,6 +333,7 @@ struct ws_encoder {
+@@ -101,6 +332,7 @@ struct ws_encoder {
uint8_t mask[4]; /* 32-bit mask for this connection */
uint8_t firstbyte; /* first byte of frame we encode */
BIT(contfragment); /* set TRUE if the previous fragment sent was not final */
@@ -10774,7 +10696,7 @@ index 9820c3e4bd..fd125d35d4 100644
};
/* Control frames are allowed up to 125 characters, rfc6455, ch. 5.5 */
-@@ -753,9 +985,10 @@ static CURLcode ws_cw_write(struct Curl_easy *data,
+@@ -759,9 +991,10 @@ static CURLcode ws_cw_write(struct Curl_easy *data,
}
}
@@ -10788,7 +10710,7 @@ index 9820c3e4bd..fd125d35d4 100644
result = CURLE_RECV_ERROR;
}
-@@ -951,34 +1184,121 @@ static CURLcode ws_enc_write_payload(struct ws_encoder *enc,
+@@ -1009,34 +1242,121 @@ static CURLcode ws_enc_write_payload(struct ws_encoder *enc,
const uint8_t *buf, size_t buflen,
struct bufq *out, size_t *pnwritten)
{
@@ -10923,7 +10845,7 @@ index 9820c3e4bd..fd125d35d4 100644
}
static CURLcode ws_enc_add_pending(struct Curl_easy *data,
-@@ -1677,6 +1997,12 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
+@@ -1746,6 +2066,12 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
result = CURLE_AGAIN;
}
@@ -10936,7 +10858,7 @@ index 9820c3e4bd..fd125d35d4 100644
if(result == CURLE_AGAIN) {
CURL_TRC_WS(data, "flush EAGAIN, %zu bytes remain in buffer",
Curl_bufq_len(&ws->sendbuf));
-@@ -1686,10 +2012,6 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
+@@ -1755,10 +2081,6 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
failf(data, "[WS] flush, write error %d", (int)result);
return result;
}
@@ -10948,11 +10870,11 @@ index 9820c3e4bd..fd125d35d4 100644
}
return CURLE_OK;
diff --git a/libcurl.pc.in b/libcurl.pc.in
-index c0ba5244a8..b5e9cb4eed 100644
+index 8f7e35dd10..cfe32a66f0 100644
--- a/libcurl.pc.in
+++ b/libcurl.pc.in
-@@ -35,7 +35,7 @@ Description: Library to transfer files with HTTP, FTP, etc.
- Version: @CURLVERSION@
+@@ -39,7 +39,7 @@ Version: @CURLVERSION@
+ Source: https://curl.se/download/curl-@CURLVERSION@.tar.gz
Requires: @LIBCURL_PC_REQUIRES@
Requires.private: @LIBCURL_PC_REQUIRES_PRIVATE@
-Libs: -L${libdir} -lcurl @LIBCURL_PC_LIBS@
@@ -10961,7 +10883,7 @@ index c0ba5244a8..b5e9cb4eed 100644
Cflags: -I${includedir} @LIBCURL_PC_CFLAGS@
Cflags.private: @LIBCURL_PC_CFLAGS_PRIVATE@
diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4
-index 8b7da20caa..8f5aebac5b 100644
+index 5d838a318c..f3732daf33 100644
--- a/m4/curl-compilers.m4
+++ b/m4/curl-compilers.m4
@@ -395,43 +395,56 @@ AC_DEFUN([CURL_CONVERT_INCLUDE_TO_ISYSTEM], [
@@ -11058,16 +10980,17 @@ index 8b7da20caa..8f5aebac5b 100644
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
-index 7ffa98ed9b..523834b5bb 100644
+index dc3353f039..c56c7db8c6 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
-@@ -26,10 +26,15 @@ EXTRA_DIST = coverage.sh completion.pl firefox-db2pem.sh checksrc.pl \
- checksrc-all.pl mk-ca-bundle.pl mk-unity.pl schemetable.c cd2nroff nroff2cd \
+@@ -26,11 +26,16 @@ EXTRA_DIST = coverage.sh completion.pl firefox-db2pem.sh checksrc.pl \
+ checksrc-all.pl mk-ca-bundle.pl mk-unity.pl cd2nroff nroff2cd \
cdall cd2cd managen dmaketgz maketgz release-tools.sh verify-release \
- cmakelint.sh mdlinkcheck CMakeLists.txt perlcheck.sh pythonlint.sh \
-- spacecheck.pl randdisable wcurl top-complexity extract-unit-protos \
-+ spacecheck.pl randdisable wcurl-impersonate top-complexity extract-unit-protos \
- .checksrc badwords badwords-all badwords.txt top-length
+ cmakelint.sh cmakeopts.sh mdlinkcheck CMakeLists.txt perlcheck.sh \
+- pythonlint.sh spacecheck.pl randdisable wcurl top-complexity \
++ pythonlint.sh spacecheck.pl randdisable wcurl-impersonate top-complexity \
+ extract-unit-protos .checksrc badwords badwords-all badwords.txt top-length \
+ testnum
-dist_bin_SCRIPTS = wcurl
+dist_bin_SCRIPTS = wcurl-impersonate
@@ -11080,7 +11003,7 @@ index 7ffa98ed9b..523834b5bb 100644
if USE_ZSH_COMPLETION
ZSH_COMPLETION_FUNCTION_FILENAME = _curl
diff --git a/scripts/singleuse.pl b/scripts/singleuse.pl
-index fc6cc7f111..2cd18b8873 100755
+index 6332a9bfec..b8215d5cb1 100755
--- a/scripts/singleuse.pl
+++ b/scripts/singleuse.pl
@@ -65,6 +65,7 @@ my %api = (
@@ -11092,10 +11015,10 @@ index fc6cc7f111..2cd18b8873 100755
'curl_easy_perform' => 'API',
'curl_easy_recv' => 'API',
diff --git a/scripts/wcurl b/scripts/wcurl-impersonate
-similarity index 88%
+similarity index 89%
rename from scripts/wcurl
rename to scripts/wcurl-impersonate
-index a5c1f95e1c..8a1b6e6d52 100755
+index 5fb68275ef..fca6f6c587 100755
--- a/scripts/wcurl
+++ b/scripts/wcurl-impersonate
@@ -1,8 +1,9 @@
@@ -11140,8 +11063,8 @@ index a5c1f95e1c..8a1b6e6d52 100755
- the URL was done by wcurl, e.g.: The URL contained whitespace.
+ the URL was done by ${PROGRAM_NAME}, e.g.: The URL contained whitespace.
-- --dry-run: Do not actually execute curl, only print what would be invoked.
-+ --dry-run: Do not actually execute curl-impersonate, only print what would be invoked.
+- --dry-run: Do not actually execute curl, print what would be invoked.
++ --dry-run: Do not actually execute curl-impersonate, print what would be invoked.
-V, --version: Print version information.
@@ -11180,16 +11103,16 @@ index a5c1f95e1c..8a1b6e6d52 100755
readonly PER_URL_PARAMETERS="\
--fail \
--globoff \
-@@ -121,7 +125,7 @@ readonly PER_URL_PARAMETERS="\
- # 3A = :
- readonly UNSAFE_PERCENT_ENCODE="%2F %5C %3A"
+@@ -122,7 +126,7 @@ readonly PER_URL_PARAMETERS="\
+ # 7F = DEL
+ readonly UNSAFE_PERCENT_ENCODE="%2F %5C %3A %7F"
-# Whether to invoke curl or not.
+# Whether to invoke curl-impersonate or not.
DRY_RUN="false"
# Sanitize parameters.
-@@ -200,10 +204,10 @@ get_url_filename()
+@@ -213,10 +217,10 @@ get_url_filename()
# No slash means there was only a hostname and no path; return empty string.
}
@@ -11262,10 +11185,10 @@ index 69554ee490..d0052604bd 100644
# if unit tests are enabled, build a static library to link them with
if BUILD_UNITTESTS
diff --git a/src/config2setopts.c b/src/config2setopts.c
-index 8933668a2c..b6f71c3557 100644
+index b6c242dad6..3326a20d41 100644
--- a/src/config2setopts.c
+++ b/src/config2setopts.c
-@@ -383,6 +383,9 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl)
+@@ -392,6 +392,9 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl)
if(config->ssl_ec_curves)
MY_SETOPT_STR(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
@@ -11275,7 +11198,7 @@ index 8933668a2c..b6f71c3557 100644
if(config->ssl_signature_algorithms)
MY_SETOPT_STR(curl, CURLOPT_SSL_SIGNATURE_ALGORITHMS,
-@@ -422,9 +425,11 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl)
+@@ -431,9 +434,11 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl)
if(config->doh_verifystatus)
my_setopt_long(curl, CURLOPT_DOH_SSL_VERIFYSTATUS, 1);
@@ -11290,7 +11213,7 @@ index 8933668a2c..b6f71c3557 100644
if(config->proxy)
my_setopt_SSLVERSION(curl, CURLOPT_PROXY_SSLVERSION,
config->proxy_ssl_version);
-@@ -479,6 +484,63 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl)
+@@ -488,6 +493,64 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl)
"--proxy-tls13-ciphers", ssl_backend());
}
@@ -11320,12 +11243,13 @@ index 8933668a2c..b6f71c3557 100644
+ my_setopt_long(curl, CURLOPT_TLS_USE_NEW_ALPS_CODEPOINT, 1L);
+
+ if(config->tls_delegated_credentials)
-+ my_setopt_str(curl, CURLOPT_TLS_DELEGATED_CREDENTIALS, config->tls_delegated_credentials);
-+
++ my_setopt_str(curl, CURLOPT_TLS_DELEGATED_CREDENTIALS,
++ config->tls_delegated_credentials);
++
+ if(config->tls_record_size_limit)
+ my_setopt_long(curl, CURLOPT_TLS_RECORD_SIZE_LIMIT,
+ config->tls_record_size_limit);
-+
++
+ if(config->tls_key_shares_limit)
+ my_setopt_long(curl, CURLOPT_TLS_KEY_SHARES_LIMIT,
+ config->tls_key_shares_limit);
@@ -11354,7 +11278,7 @@ index 8933668a2c..b6f71c3557 100644
/* curl 7.16.0 */
if(config->disable_sessionid)
/* disable it */
-@@ -552,6 +614,9 @@ static CURLcode cookie_setopts(struct OperationConfig *config, CURL *curl)
+@@ -561,6 +624,9 @@ static CURLcode cookie_setopts(struct OperationConfig *config, CURL *curl)
MY_SETOPT_STR(curl, CURLOPT_COOKIEJAR, config->cookiejar);
my_setopt_long(curl, CURLOPT_COOKIESESSION, config->cookiesession);
@@ -11364,7 +11288,7 @@ index 8933668a2c..b6f71c3557 100644
return result;
}
-@@ -604,6 +669,84 @@ static CURLcode http_setopts(struct OperationConfig *config, CURL *curl,
+@@ -699,6 +765,84 @@ static CURLcode http_setopts(struct OperationConfig *config, CURL *curl,
if(config->hsts)
MY_SETOPT_STR(curl, CURLOPT_HSTS, config->hsts);
@@ -11449,7 +11373,7 @@ index 8933668a2c..b6f71c3557 100644
if(config->expect100timeout_ms > 0)
my_setopt_long(curl, CURLOPT_EXPECT_100_TIMEOUT_MS,
config->expect100timeout_ms);
-@@ -773,6 +916,10 @@ static CURLcode proxy_setopts(struct OperationConfig *config, CURL *curl)
+@@ -868,6 +1012,10 @@ static CURLcode proxy_setopts(struct OperationConfig *config, CURL *curl)
if(config->haproxy_clientip)
MY_SETOPT_STR(curl, CURLOPT_HAPROXY_CLIENT_IP, config->haproxy_clientip);
@@ -11457,10 +11381,10 @@ index 8933668a2c..b6f71c3557 100644
+ if(config->proxy_credential_no_reuse)
+ my_setopt_long(curl, CURLOPT_PROXY_CREDENTIAL_NO_REUSE, 1L);
+
- return result;
- }
+ MY_SETOPT_STR(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
-@@ -926,11 +1073,13 @@ CURLcode config2setopts(struct OperationConfig *config,
+ return result;
+@@ -949,11 +1097,13 @@ static CURLcode credentials_and_headers_setopts(struct OperationConfig *config,
my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, config->authtype);
my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
@@ -11475,8 +11399,8 @@ index 8933668a2c..b6f71c3557 100644
+ MY_SETOPT_STR(curl, CURLOPT_USERAGENT, config->useragent);
}
- result = http_setopts(config, curl, use_proto);
-@@ -939,6 +1088,13 @@ CURLcode config2setopts(struct OperationConfig *config,
+ MY_SETOPT_STR(curl, CURLOPT_KEYPASSWD, config->key_passwd);
+@@ -982,6 +1132,13 @@ static CURLcode transfer_setopts(struct OperationConfig *config,
if(result)
return result;
@@ -11487,11 +11411,11 @@ index 8933668a2c..b6f71c3557 100644
+ return result;
+ }
+
- my_setopt_long(curl, CURLOPT_LOW_SPEED_LIMIT, config->low_speed_limit);
- my_setopt_long(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
- my_setopt_offt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, config->sendpersecond);
+ if(config->mime_options)
+ my_setopt_long(curl, CURLOPT_MIME_OPTIONS, config->mime_options);
+
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
-index 3feb3e7824..e1d2740a6e 100644
+index 26b44f8438..575902ddb2 100644
--- a/src/tool_cfgable.c
+++ b/src/tool_cfgable.c
@@ -49,6 +49,8 @@ struct OperationConfig *config_alloc(void)
@@ -11503,7 +11427,7 @@ index 3feb3e7824..e1d2740a6e 100644
config->happy_eyeballs_timeout_ms = CURL_HET_DEFAULT;
config->http09_allowed = FALSE;
config->ftp_skip_ip = TRUE;
-@@ -106,6 +108,27 @@ static void free_config_fields(struct OperationConfig *config)
+@@ -100,6 +102,27 @@ static void free_config_fields(struct OperationConfig *config)
curlx_safefree(config->proto_str);
curlx_safefree(config->proto_redir_str);
@@ -11531,7 +11455,7 @@ index 3feb3e7824..e1d2740a6e 100644
urlnode = config->url_list;
while(urlnode) {
struct getout *next = urlnode->next;
-@@ -154,7 +177,7 @@ static void free_config_fields(struct OperationConfig *config)
+@@ -150,7 +173,7 @@ static void free_config_fields(struct OperationConfig *config)
curlx_safefree(config->etag_save_file);
curlx_safefree(config->etag_compare_file);
curlx_safefree(config->ssl_ec_curves);
@@ -11540,7 +11464,7 @@ index 3feb3e7824..e1d2740a6e 100644
curlx_safefree(config->request_target);
curlx_safefree(config->customrequest);
curlx_safefree(config->krblevel);
-@@ -169,6 +192,8 @@ static void free_config_fields(struct OperationConfig *config)
+@@ -166,6 +189,8 @@ static void free_config_fields(struct OperationConfig *config)
curl_slist_free_all(config->prequote);
curl_slist_free_all(config->headers);
@@ -11550,10 +11474,10 @@ index 3feb3e7824..e1d2740a6e 100644
curl_mime_free(config->mimepost);
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
-index 0f8bc6fe08..8274630246 100644
+index 7a587f6675..a25c9de8c7 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
-@@ -124,6 +124,7 @@ struct OperationConfig {
+@@ -118,6 +118,7 @@ struct OperationConfig {
char *proxy_key_type;
char *key_passwd;
char *proxy_key_passwd;
@@ -11561,7 +11485,7 @@ index 0f8bc6fe08..8274630246 100644
char *pubkey;
char *hostpubmd5;
char *hostpubsha256;
-@@ -132,15 +133,48 @@ struct OperationConfig {
+@@ -126,15 +127,48 @@ struct OperationConfig {
char *etag_compare_file;
char *customrequest;
char *ssl_ec_curves;
@@ -11610,7 +11534,7 @@ index 0f8bc6fe08..8274630246 100644
struct curl_slist *proxyheaders;
struct tool_mime *mimeroot;
struct tool_mime *mimecurrent;
-@@ -194,6 +228,9 @@ struct OperationConfig {
+@@ -192,6 +226,9 @@ struct OperationConfig {
long alivetime; /* keepalive-time */
long alivecnt; /* keepalive-cnt */
long gssapi_delegation;
@@ -11620,7 +11544,7 @@ index 0f8bc6fe08..8274630246 100644
long expect100timeout_ms;
long happy_eyeballs_timeout_ms; /* happy eyeballs timeout in milliseconds.
0 is valid. default: CURL_HET_DEFAULT. */
-@@ -220,6 +257,7 @@ struct OperationConfig {
+@@ -218,6 +255,7 @@ struct OperationConfig {
BIT(remote_name_all); /* --remote-name-all */
BIT(remote_time);
BIT(cookiesession); /* new session? */
@@ -11629,18 +11553,18 @@ index 0f8bc6fe08..8274630246 100644
BIT(tr_encoding); /* Transfer-Encoding please */
BIT(use_resume);
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
-index 35c01b1d92..3138bc6fe0 100644
+index ae3958d8c5..b6ece1dcbd 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -76,6 +76,7 @@ static ParameterError getstrn(char **str, const char *val,
- static const struct LongShort aliases[]= {
+ static const struct LongShort aliases[] = {
{"abstract-unix-socket", ARG_FILE, ' ', C_ABSTRACT_UNIX_SOCKET},
{"alpn", ARG_BOOL|ARG_NO|ARG_TLS, ' ', C_ALPN},
+ {"alps", ARG_BOOL, ' ', C_ALPS}, // curl-impersonate
{"alt-svc", ARG_STRG, ' ', C_ALT_SVC},
{"anyauth", ARG_NONE, ' ', C_ANYAUTH},
{"append", ARG_BOOL, 'a', C_APPEND},
-@@ -86,6 +87,7 @@ static const struct LongShort aliases[]= {
+@@ -86,6 +87,7 @@ static const struct LongShort aliases[] = {
{"cacert", ARG_FILE|ARG_TLS, ' ', C_CACERT},
{"capath", ARG_FILE|ARG_TLS, ' ', C_CAPATH},
{"cert", ARG_FILE|ARG_TLS|ARG_CLEAR, 'E', C_CERT},
@@ -11648,7 +11572,7 @@ index 35c01b1d92..3138bc6fe0 100644
{"cert-status", ARG_BOOL|ARG_TLS, ' ', C_CERT_STATUS},
{"cert-type", ARG_STRG|ARG_TLS, ' ', C_CERT_TYPE},
{"ciphers", ARG_STRG|ARG_TLS, ' ', C_CIPHERS},
-@@ -137,6 +139,7 @@ static const struct LongShort aliases[]= {
+@@ -137,6 +139,7 @@ static const struct LongShort aliases[] = {
{"false-start", ARG_BOOL, ' ', C_FALSE_START},
{"follow", ARG_BOOL, ' ', C_FOLLOW},
{"form", ARG_STRG, 'F', C_FORM},
@@ -11656,7 +11580,7 @@ index 35c01b1d92..3138bc6fe0 100644
{"form-escape", ARG_BOOL, ' ', C_FORM_ESCAPE},
{"form-string", ARG_STRG, ' ', C_FORM_STRING},
{"ftp-account", ARG_STRG, ' ', C_FTP_ACCOUNT},
-@@ -163,14 +166,32 @@ static const struct LongShort aliases[]= {
+@@ -163,13 +166,30 @@ static const struct LongShort aliases[] = {
{"hostpubmd5", ARG_STRG, ' ', C_HOSTPUBMD5},
{"hostpubsha256", ARG_STRG, ' ', C_HOSTPUBSHA256},
{"hsts", ARG_STRG|ARG_TLS, ' ', C_HSTS},
@@ -11684,12 +11608,18 @@ index 35c01b1d92..3138bc6fe0 100644
+ {"http3-tls-extension-order", ARG_STRG, ' ', C_HTTP3_TLS_EXTENSION_ORDER}, // curl-impersonate
+ {"http3-tls-permute-extensions", ARG_BOOL, ' ',
+ C_HTTP3_TLS_PERMUTE_EXTENSIONS}, /* curl-impersonate */
+ #ifndef CURL_DISABLE_HTTPSIG
+ {"httpsig-algo", ARG_STRG, ' ', C_HTTPSIG_ALGORITHM},
+ {"httpsig-headers", ARG_STRG, ' ', C_HTTPSIG_HEADERS},
+@@ -177,6 +197,7 @@ static const struct LongShort aliases[] = {
+ {"httpsig-keyid", ARG_STRG, ' ', C_HTTPSIG_KEYID},
+ #endif
{"ignore-content-length", ARG_BOOL, ' ', C_IGNORE_CONTENT_LENGTH},
+ {"impersonate", ARG_STRG, ' ', C_IMPERSONATE},
{"include", ARG_BOOL, ' ', C_INCLUDE},
{"insecure", ARG_BOOL, 'k', C_INSECURE},
{"interface", ARG_STRG, ' ', C_INTERFACE},
-@@ -195,6 +216,7 @@ static const struct LongShort aliases[]= {
+@@ -201,6 +222,7 @@ static const struct LongShort aliases[] = {
{"list-only", ARG_BOOL, 'l', C_LIST_ONLY},
{"local-port", ARG_STRG, ' ', C_LOCAL_PORT},
{"location", ARG_BOOL, 'L', C_LOCATION},
@@ -11697,7 +11627,7 @@ index 35c01b1d92..3138bc6fe0 100644
{"location-trusted", ARG_BOOL, ' ', C_LOCATION_TRUSTED},
{"login-options", ARG_STRG, ' ', C_LOGIN_OPTIONS},
{"mail-auth", ARG_STRG, ' ', C_MAIL_AUTH},
-@@ -246,6 +268,7 @@ static const struct LongShort aliases[]= {
+@@ -252,6 +274,7 @@ static const struct LongShort aliases[] = {
C_PROXY_CERT},
{"proxy-cert-type", ARG_STRG|ARG_TLS, ' ', C_PROXY_CERT_TYPE},
{"proxy-ciphers", ARG_STRG|ARG_TLS, ' ', C_PROXY_CIPHERS},
@@ -11705,7 +11635,7 @@ index 35c01b1d92..3138bc6fe0 100644
{"proxy-crlfile", ARG_FILE|ARG_TLS, ' ', C_PROXY_CRLFILE},
{"proxy-digest", ARG_BOOL, ' ', C_PROXY_DIGEST},
{"proxy-header", ARG_STRG, ' ', C_PROXY_HEADER},
-@@ -272,6 +295,8 @@ static const struct LongShort aliases[]= {
+@@ -280,6 +303,8 @@ static const struct LongShort aliases[] = {
{"proxy1.0", ARG_STRG, ' ', C_PROXY1_0},
{"proxytunnel", ARG_BOOL, 'p', C_PROXYTUNNEL},
{"pubkey", ARG_STRG, ' ', C_PUBKEY},
@@ -11714,7 +11644,7 @@ index 35c01b1d92..3138bc6fe0 100644
{"quote", ARG_STRG, 'Q', C_QUOTE},
{"random-file", ARG_FILE|ARG_DEPR, ' ', C_RANDOM_FILE},
{"range", ARG_STRG, 'r', C_RANGE},
-@@ -297,8 +322,8 @@ static const struct LongShort aliases[]= {
+@@ -305,8 +330,8 @@ static const struct LongShort aliases[] = {
{"sessionid", ARG_BOOL|ARG_NO, ' ', C_SESSIONID},
{"show-error", ARG_BOOL, 'S', C_SHOW_ERROR},
{"show-headers", ARG_BOOL, 'i', C_SHOW_HEADERS},
@@ -11725,7 +11655,7 @@ index 35c01b1d92..3138bc6fe0 100644
{"silent", ARG_BOOL, 's', C_SILENT},
{"skip-existing", ARG_BOOL, ' ', C_SKIP_EXISTING},
{"socks4", ARG_STRG, ' ', C_SOCKS4},
-@@ -311,6 +336,7 @@ static const struct LongShort aliases[]= {
+@@ -319,6 +344,7 @@ static const struct LongShort aliases[] = {
{"socks5-hostname", ARG_STRG, ' ', C_SOCKS5_HOSTNAME},
{"speed-limit", ARG_UNUM, 'Y', C_SPEED_LIMIT},
{"speed-time", ARG_UNUM, 'y', C_SPEED_TIME},
@@ -11733,7 +11663,7 @@ index 35c01b1d92..3138bc6fe0 100644
{"ssl", ARG_BOOL|ARG_TLS, ' ', C_SSL},
{"ssl-allow-beast", ARG_BOOL|ARG_TLS, ' ', C_SSL_ALLOW_BEAST},
{"ssl-auto-client-cert", ARG_BOOL|ARG_TLS, ' ',
-@@ -335,8 +361,18 @@ static const struct LongShort aliases[]= {
+@@ -343,8 +369,18 @@ static const struct LongShort aliases[] = {
{"tftp-blksize", ARG_UNUM, ' ', C_TFTP_BLKSIZE},
{"tftp-no-options", ARG_BOOL, ' ', C_TFTP_NO_OPTIONS},
{"time-cond", ARG_STRG, 'z', C_TIME_COND},
@@ -11750,9 +11680,9 @@ index 35c01b1d92..3138bc6fe0 100644
+ {"tls-trust-anchors", ARG_STRG, ' ', C_TLS_TRUST_ANCHORS}, // curl-impersonate
+ {"tls-use-new-alps-codepoint", ARG_BOOL, ' ', C_TLS_USE_NEW_ALPS_CODEPOINT}, // curl-impersonate
{"tls13-ciphers", ARG_STRG|ARG_TLS, ' ', C_TLS13_CIPHERS},
- {"tlsauthtype", ARG_STRG|ARG_TLS, ' ', C_TLSAUTHTYPE},
- {"tlspassword", ARG_STRG|ARG_TLS|ARG_CLEAR, ' ', C_TLSPASSWORD},
-@@ -368,6 +404,10 @@ static const struct LongShort aliases[]= {
+ {"tlsauthtype", ARG_STRG|ARG_TLS|ARG_DEPR, ' ', C_TLSAUTHTYPE},
+ {"tlspassword", ARG_STRG|ARG_TLS|ARG_CLEAR|ARG_DEPR, ' ', C_TLSPASSWORD},
+@@ -376,6 +412,10 @@ static const struct LongShort aliases[] = {
{"wdebug", ARG_BOOL, ' ', C_WDEBUG},
#endif
{"write-out", ARG_STRG, 'w', C_WRITE_OUT},
@@ -11763,7 +11693,7 @@ index 35c01b1d92..3138bc6fe0 100644
{"xattr", ARG_BOOL, ' ', C_XATTR},
};
-@@ -1305,9 +1345,14 @@ static ParameterError parse_header(struct OperationConfig *config,
+@@ -1313,9 +1353,14 @@ static ParameterError parse_header(struct OperationConfig *config,
curlx_dyn_init(&line, 1024 * 100);
while(my_get_line(file, &line, &error)) {
const char *ptr = curlx_dyn_ptr(&line);
@@ -11781,7 +11711,7 @@ index 35c01b1d92..3138bc6fe0 100644
if(err)
break;
}
-@@ -1325,6 +1370,10 @@ static ParameterError parse_header(struct OperationConfig *config,
+@@ -1333,6 +1378,10 @@ static ParameterError parse_header(struct OperationConfig *config,
}
if(cmd == C_PROXY_HEADER) /* --proxy-header */
err = add2list(&config->proxyheaders, nextarg);
@@ -11792,7 +11722,7 @@ index 35c01b1d92..3138bc6fe0 100644
else
err = add2list(&config->headers, nextarg);
}
-@@ -1834,6 +1883,9 @@ static ParameterError opt_bool(struct OperationConfig *config,
+@@ -1841,6 +1890,9 @@ static ParameterError opt_bool(struct OperationConfig *config,
case C_ALPN: /* --alpn */
config->noalpn = !toggle;
break;
@@ -11802,7 +11732,7 @@ index 35c01b1d92..3138bc6fe0 100644
case C_DISABLE_EPSV: /* --disable-epsv */
config->disable_epsv = toggle;
break;
-@@ -2009,6 +2061,34 @@ static ParameterError opt_bool(struct OperationConfig *config,
+@@ -2016,6 +2068,34 @@ static ParameterError opt_bool(struct OperationConfig *config,
case C_TLS_EARLYDATA: /* --tls-earlydata */
config->ssl_allow_earlydata = toggle;
break;
@@ -11837,7 +11767,7 @@ index 35c01b1d92..3138bc6fe0 100644
case C_SUPPRESS_CONNECT_HEADERS: /* --suppress-connect-headers */
config->suppress_connect_headers = toggle;
break;
-@@ -2135,6 +2215,9 @@ static ParameterError opt_bool(struct OperationConfig *config,
+@@ -2142,6 +2222,9 @@ static ParameterError opt_bool(struct OperationConfig *config,
case C_JUNK_SESSION_COOKIES: /* --junk-session-cookies */
config->cookiesession = toggle;
break;
@@ -11847,7 +11777,7 @@ index 35c01b1d92..3138bc6fe0 100644
case C_HEAD: /* --head */
config->no_body = toggle;
config->show_headers = toggle;
-@@ -2154,6 +2237,9 @@ static ParameterError opt_bool(struct OperationConfig *config,
+@@ -2161,6 +2244,9 @@ static ParameterError opt_bool(struct OperationConfig *config,
case C_LIST_ONLY: /* --list-only */
config->dirlistonly = toggle; /* only list names of the FTP directory */
break;
@@ -11857,7 +11787,7 @@ index 35c01b1d92..3138bc6fe0 100644
case C_MANUAL: /* --manual */
if(toggle) /* --no-manual shows no manual... */
return PARAM_MANUAL_REQUESTED;
-@@ -2213,6 +2299,9 @@ static ParameterError opt_bool(struct OperationConfig *config,
+@@ -2220,6 +2306,9 @@ static ParameterError opt_bool(struct OperationConfig *config,
case C_MPTCP: /* --mptcp */
config->mptcp = toggle;
break;
@@ -11867,7 +11797,7 @@ index 35c01b1d92..3138bc6fe0 100644
case C_LOCATION_TRUSTED: /* --location-trusted */
config->unrestricted_auth = toggle;
FALLTHROUGH();
-@@ -2680,6 +2769,112 @@ static ParameterError opt_string(struct OperationConfig *config,
+@@ -2713,6 +2802,112 @@ static ParameterError opt_string(struct OperationConfig *config,
err = PARAM_BAD_USE;
}
break;
@@ -11980,7 +11910,7 @@ index 35c01b1d92..3138bc6fe0 100644
case C_TRACE_CONFIG: /* --trace-config */
global->trace_set = TRUE;
if(set_trace_config(nextarg))
-@@ -2709,6 +2904,9 @@ static ParameterError opt_string(struct OperationConfig *config,
+@@ -2742,6 +2937,9 @@ static ParameterError opt_string(struct OperationConfig *config,
else
err = getstr(&config->hsts, nextarg, ALLOW_BLANK);
break;
@@ -11990,7 +11920,7 @@ index 35c01b1d92..3138bc6fe0 100644
case C_COOKIE: /* --cookie */
if(strchr(nextarg, '=')) {
/* A cookie string must have a =-letter */
-@@ -2870,8 +3068,14 @@ static ParameterError opt_string(struct OperationConfig *config,
+@@ -2860,8 +3058,14 @@ static ParameterError opt_string(struct OperationConfig *config,
case C_REQUEST_TARGET: /* --request-target */
err = getstr(&config->request_target, nextarg, DENY_BLANK);
break;
@@ -12006,7 +11936,7 @@ index 35c01b1d92..3138bc6fe0 100644
break;
case C_OUTPUT_DIR: /* --output-dir */
diff --git a/src/tool_getparam.h b/src/tool_getparam.h
-index 32476d3776..3fb231549b 100644
+index 92495a4de6..8bbfa25407 100644
--- a/src/tool_getparam.h
+++ b/src/tool_getparam.h
@@ -31,6 +31,7 @@
@@ -12033,7 +11963,7 @@ index 32476d3776..3fb231549b 100644
C_FORM_ESCAPE,
C_FORM_STRING,
C_FTP_ACCOUNT,
-@@ -118,14 +121,31 @@ typedef enum {
+@@ -118,18 +121,35 @@ typedef enum {
C_HOSTPUBMD5,
C_HOSTPUBSHA256,
C_HSTS,
@@ -12060,12 +11990,16 @@ index 32476d3776..3fb231549b 100644
+ C_HTTP3_SIG_HASH_ALGS,
+ C_HTTP3_TLS_EXTENSION_ORDER,
+ C_HTTP3_TLS_PERMUTE_EXTENSIONS,
+ C_HTTPSIG_ALGORITHM,
+ C_HTTPSIG_HEADERS,
+ C_HTTPSIG_KEY,
+ C_HTTPSIG_KEYID,
C_IGNORE_CONTENT_LENGTH,
+ C_IMPERSONATE,
C_INCLUDE,
C_INSECURE,
C_INTERFACE,
-@@ -147,6 +167,7 @@ typedef enum {
+@@ -151,6 +171,7 @@ typedef enum {
C_LIST_ONLY,
C_LOCAL_PORT,
C_LOCATION,
@@ -12073,7 +12007,7 @@ index 32476d3776..3fb231549b 100644
C_LOCATION_TRUSTED,
C_LOGIN_OPTIONS,
C_MAIL_AUTH,
-@@ -197,6 +218,7 @@ typedef enum {
+@@ -201,6 +222,7 @@ typedef enum {
C_PROXY_CERT,
C_PROXY_CERT_TYPE,
C_PROXY_CIPHERS,
@@ -12081,7 +12015,7 @@ index 32476d3776..3fb231549b 100644
C_PROXY_CRLFILE,
C_PROXY_DIGEST,
C_PROXY_HEADER,
-@@ -221,6 +243,8 @@ typedef enum {
+@@ -225,6 +247,8 @@ typedef enum {
C_PROXY1_0,
C_PROXYTUNNEL,
C_PUBKEY,
@@ -12090,7 +12024,7 @@ index 32476d3776..3fb231549b 100644
C_QUOTE,
C_RANDOM_FILE,
C_RANGE,
-@@ -246,6 +270,7 @@ typedef enum {
+@@ -250,6 +274,7 @@ typedef enum {
C_SESSIONID,
C_SHOW_ERROR,
C_SHOW_HEADERS,
@@ -12098,7 +12032,7 @@ index 32476d3776..3fb231549b 100644
C_SILENT,
C_SIGNATURE_ALGORITHMS,
C_SKIP_EXISTING,
-@@ -259,6 +284,7 @@ typedef enum {
+@@ -263,6 +288,7 @@ typedef enum {
C_SOCKS5_HOSTNAME,
C_SPEED_LIMIT,
C_SPEED_TIME,
@@ -12106,11 +12040,12 @@ index 32476d3776..3fb231549b 100644
C_SSL,
C_SSL_ALLOW_BEAST,
C_SSL_AUTO_CLIENT_CERT,
-@@ -280,7 +306,17 @@ typedef enum {
+@@ -283,8 +309,18 @@ typedef enum {
+ C_TFTP_BLKSIZE,
C_TFTP_NO_OPTIONS,
C_TIME_COND,
- C_TLS_EARLYDATA,
+ C_TLS_DELEGATED_CREDENTIALS,
+ C_TLS_EARLYDATA,
+ C_TLS_EXTENSION_ORDER,
+ C_TLS_GREASE,
+ C_TLS_KEY_SHARES_LIMIT,
@@ -12124,7 +12059,7 @@ index 32476d3776..3fb231549b 100644
C_TLS13_CIPHERS,
C_TLSAUTHTYPE,
C_TLSPASSWORD,
-@@ -310,6 +346,10 @@ typedef enum {
+@@ -314,6 +350,10 @@ typedef enum {
C_VERSION,
C_VLAN_PRIORITY,
C_WDEBUG,
@@ -12136,10 +12071,10 @@ index 32476d3776..3fb231549b 100644
C_XATTR
} cmdline_t;
diff --git a/src/tool_help.c b/src/tool_help.c
-index c9d76d5d20..7f0e0511db 100644
+index 597a6a554d..9f42b9bee2 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
-@@ -312,6 +312,11 @@ static bool is_debug(void)
+@@ -313,6 +313,11 @@ static bool is_debug(void)
void tool_version_info(void)
{
const char * const *builtin;
@@ -12151,7 +12086,7 @@ index c9d76d5d20..7f0e0511db 100644
if(is_debug())
curl_mfprintf(tool_stderr, "WARNING: this libcurl is Debug-enabled, "
"do not use in production\n\n");
-@@ -319,9 +324,9 @@ void tool_version_info(void)
+@@ -320,9 +325,9 @@ void tool_version_info(void)
curl_mprintf(CURL_ID "%s\n", curl_version());
#ifdef CURL_PATCHSTAMP
curl_mprintf("Release-Date: %s, security patched: %s\n",
@@ -12164,13 +12099,13 @@ index c9d76d5d20..7f0e0511db 100644
if(built_in_protos[0]) {
#ifndef CURL_DISABLE_IPFS
diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c
-index c0b0af792f..3ec29e07bc 100644
+index b6d3ddfd1d..69c5432a08 100644
--- a/src/tool_listhelp.c
+++ b/src/tool_listhelp.c
@@ -37,6 +37,9 @@ const struct helptxt helptext[] = {
{ " --abstract-unix-socket <path>",
"Connect via abstract Unix domain socket",
- CURLHELP_CONNECTION },
+ CURLHELP_CONNECTION | CURLHELP_HTTP },
+ { " --alps",
+ "Enable the ALPS TLS extension",
+ CURLHELP_TLS | CURLHELP_HTTP },
@@ -12187,7 +12122,7 @@ index c0b0af792f..3ec29e07bc 100644
{ " --cert-status",
"Verify server cert status OCSP-staple",
CURLHELP_TLS },
-@@ -209,6 +215,9 @@ const struct helptxt helptext[] = {
+@@ -210,6 +216,9 @@ const struct helptxt helptext[] = {
"Specify multipart MIME data",
CURLHELP_HTTP | CURLHELP_UPLOAD | CURLHELP_POST | CURLHELP_IMAP |
CURLHELP_SMTP },
@@ -12196,8 +12131,8 @@ index c0b0af792f..3ec29e07bc 100644
+ CURLHELP_HTTP | CURLHELP_UPLOAD | CURLHELP_POST },
{ " --form-escape",
"Escape form fields using backslash",
- CURLHELP_HTTP | CURLHELP_UPLOAD | CURLHELP_POST },
-@@ -297,15 +306,51 @@ const struct helptxt helptext[] = {
+ CURLHELP_HTTP | CURLHELP_UPLOAD | CURLHELP_POST | CURLHELP_IMAP |
+@@ -299,12 +308,45 @@ const struct helptxt helptext[] = {
{ " --http2-prior-knowledge",
"Use HTTP/2 without HTTP/1.1 Upgrade",
CURLHELP_HTTP },
@@ -12240,6 +12175,10 @@ index c0b0af792f..3ec29e07bc 100644
+ { " --http3-tls-permute-extensions",
+ "Permute HTTP/3 TLS extensions in ClientHello",
+ CURLHELP_TLS },
+ #ifndef CURL_DISABLE_HTTPSIG
+ { " --httpsig-algo <algorithm>",
+ "Algorithm for HTTP Message Signatures",
+@@ -328,6 +370,9 @@ const struct helptxt helptext[] = {
{ " --ignore-content-length",
"Ignore the size of the remote resource",
CURLHELP_HTTP | CURLHELP_FTP },
@@ -12249,7 +12188,7 @@ index c0b0af792f..3ec29e07bc 100644
{ "-k, --insecure",
"Allow insecure server connections",
CURLHELP_TLS | CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_SSH },
-@@ -436,6 +481,12 @@ const struct helptxt helptext[] = {
+@@ -460,6 +505,12 @@ const struct helptxt helptext[] = {
{ " --no-sessionid",
"Disable SSL session-ID reusing",
CURLHELP_TLS },
@@ -12262,7 +12201,7 @@ index c0b0af792f..3ec29e07bc 100644
{ " --noproxy <no-proxy-list>",
"List of hosts which do not use proxy",
CURLHELP_PROXY },
-@@ -530,6 +581,9 @@ const struct helptxt helptext[] = {
+@@ -555,6 +606,9 @@ const struct helptxt helptext[] = {
{ " --proxy-ciphers <list>",
"TLS 1.2 (1.1, 1.0) ciphers to use for proxy",
CURLHELP_PROXY | CURLHELP_TLS },
@@ -12272,7 +12211,7 @@ index c0b0af792f..3ec29e07bc 100644
{ " --proxy-crlfile <file>",
"Set a CRL list for proxy",
CURLHELP_PROXY | CURLHELP_TLS },
-@@ -602,6 +656,12 @@ const struct helptxt helptext[] = {
+@@ -627,6 +681,12 @@ const struct helptxt helptext[] = {
{ " --pubkey <key>",
"SSH Public key filename",
CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_SSH | CURLHELP_AUTH },
@@ -12285,7 +12224,7 @@ index c0b0af792f..3ec29e07bc 100644
{ "-Q, --quote <command>",
"Send command(s) to server before transfer",
CURLHELP_FTP | CURLHELP_SFTP },
-@@ -678,6 +738,9 @@ const struct helptxt helptext[] = {
+@@ -706,6 +766,9 @@ const struct helptxt helptext[] = {
{ " --sigalgs <list>",
"TLS signature algorithms to use",
CURLHELP_TLS },
@@ -12295,7 +12234,7 @@ index c0b0af792f..3ec29e07bc 100644
{ "-s, --silent",
"Silent mode",
CURLHELP_IMPORTANT | CURLHELP_VERBOSE },
-@@ -714,6 +777,9 @@ const struct helptxt helptext[] = {
+@@ -742,6 +805,9 @@ const struct helptxt helptext[] = {
{ "-y, --speed-time <seconds>",
"Trigger 'speed-limit' abort after this time",
CURLHELP_CONNECTION | CURLHELP_TIMEOUT },
@@ -12305,7 +12244,7 @@ index c0b0af792f..3ec29e07bc 100644
{ " --ssl",
"Try enabling TLS",
CURLHELP_TLS | CURLHELP_IMAP | CURLHELP_POP3 | CURLHELP_SMTP |
-@@ -776,6 +842,12 @@ const struct helptxt helptext[] = {
+@@ -804,6 +870,12 @@ const struct helptxt helptext[] = {
{ " --tls-max <VERSION>",
"Maximum allowed TLS version",
CURLHELP_TLS },
@@ -12318,7 +12257,7 @@ index c0b0af792f..3ec29e07bc 100644
{ " --tls13-ciphers <list>",
"TLS 1.3 cipher suites to use",
CURLHELP_TLS },
-@@ -860,6 +932,18 @@ const struct helptxt helptext[] = {
+@@ -888,6 +960,18 @@ const struct helptxt helptext[] = {
{ "-w, --write-out <format>",
"Output FORMAT after completion",
CURLHELP_VERBOSE },
@@ -12338,7 +12277,7 @@ index c0b0af792f..3ec29e07bc 100644
"Store metadata in extended file attributes",
CURLHELP_OUTPUT },
diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c
-index 18e2d1a625..66d719a066 100644
+index e425b36411..97d3316718 100644
--- a/src/tool_paramhlp.c
+++ b/src/tool_paramhlp.c
@@ -649,6 +649,12 @@ long delegation(const char *str)
@@ -12381,7 +12320,7 @@ index 18e2d1a625..66d719a066 100644
}
diff --git a/src/tool_setopt.c b/src/tool_setopt.c
-index 2174571ad4..c5f2309372 100644
+index 51e22756aa..a870faa043 100644
--- a/src/tool_setopt.c
+++ b/src/tool_setopt.c
@@ -156,6 +156,7 @@ const struct NameValue setopt_nv_CURLOPT_FOLLOWLOCATION[] = {
This site is maintained by Jamie Landeg-Jones <jamie@catflap.org>, and is not an official FreeBSD project, nor is it endorsed by the FreeBSD team.