From 68582e34c817f34a96fdf6f8e5fa8e692b22cdab Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Sun, 28 Apr 2024 16:03:34 +0800 Subject: [PATCH 01/22] Update to curl 8.7.1 --- Makefile.in | 2 +- README.md | 2 +- chrome/patches/curl-impersonate.patch | 544 ++++++++++++++------------ docker/alpine.dockerfile | 2 +- docker/debian.dockerfile | 2 +- docker/dockerfile.mustache | 2 +- docs/03_LIBCURL_IMPERSONATE_PYTHON.md | 2 +- win/build.sh | 2 +- 8 files changed, 311 insertions(+), 247 deletions(-) diff --git a/Makefile.in b/Makefile.in index e36ae352..b481884e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -15,7 +15,7 @@ BROTLI_VERSION := 1.0.9 BORING_SSL_COMMIT := d24a38200fef19150eef00cad35b138936c08767 NGHTTP2_VERSION := nghttp2-1.56.0 NGHTTP2_URL := https://github.com/nghttp2/nghttp2/releases/download/v1.56.0/nghttp2-1.56.0.tar.bz2 -CURL_VERSION := curl-8_5_0 +CURL_VERSION := curl-8_7_1 brotli_install_dir := $(abspath brotli-$(BROTLI_VERSION)/out/installed) brotli_static_libs := $(brotli_install_dir)/lib/libbrotlicommon-static.a $(brotli_install_dir)/lib/libbrotlidec-static.a diff --git a/README.md b/README.md index 366a9ee1..8f461f09 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ > 2. ZSTD compression support introduced in Chrome 123. > 3. X25519Kyber768 curve introduced in Chrome 124. > 4. More options for impersonation Akamai http/2 fingerprints, especially for Safari. -> 5. Upgrade to more recent version of curl, 8.5.0 as of April, 2024. +> 5. Upgrade to more recent version of curl, 8.7.1 as of April, 2024. > 6. Ability to change extension orders and enable/disable TLS grease. > 7. (In progress) Single binary to support both Webkit-based and Gecko-based browsers, i.e. Chrome and Firefox. diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index 7b227e3e..008e837d 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -1,8 +1,8 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index a54c2fff9..7d22d4e96 100644 +index 656aa7c74..5702de3ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -619,6 +619,29 @@ if(CURL_ZSTD) +@@ -598,6 +598,29 @@ if(CURL_ZSTD) endif() endif() @@ -33,17 +33,17 @@ index a54c2fff9..7d22d4e96 100644 macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE) cmake_push_check_state() diff --git a/Makefile.am b/Makefile.am -index c8afcb505..234125083 100644 +index 658189e47..1ebc38b5a 100644 --- a/Makefile.am +++ b/Makefile.am -@@ -131,13 +131,13 @@ CLEANFILES = $(VC14_LIBVCXPROJ) \ - $(VC14_SRCVCXPROJ) $(VC14_10_LIBVCXPROJ) $(VC14_10_SRCVCXPROJ) \ +@@ -132,13 +132,13 @@ CLEANFILES = $(VC14_LIBVCXPROJ) $(VC14_SRCVCXPROJ) \ + $(VC14_20_LIBVCXPROJ) $(VC14_20_SRCVCXPROJ) \ $(VC14_30_LIBVCXPROJ) $(VC14_30_SRCVCXPROJ) -bin_SCRIPTS = curl-config +bin_SCRIPTS = curl-impersonate-chrome-config - SUBDIRS = lib src + SUBDIRS = lib docs src scripts DIST_SUBDIRS = $(SUBDIRS) tests packages scripts include docs pkgconfigdir = $(libdir)/pkgconfig @@ -53,7 +53,7 @@ index c8afcb505..234125083 100644 # List of files required to generate VC IDE .dsp, .vcproj and .vcxproj files include lib/Makefile.inc diff --git a/configure.ac b/configure.ac -index d9b396376..cd3b845f4 100644 +index 49371a755..d6ac97712 100644 --- a/configure.ac +++ b/configure.ac @@ -1422,7 +1422,8 @@ if test X"$OPT_BROTLI" != Xno; then @@ -79,7 +79,7 @@ index d9b396376..cd3b845f4 100644 AC_CHECK_HEADERS(brotli/decode.h, curl_brotli_msg="enabled (libbrotlidec)" -@@ -4383,14 +4388,23 @@ if test "x$want_ech" != "xno"; then +@@ -4547,14 +4552,23 @@ if test "x$want_ech" != "xno"; then ECH_ENABLED=0 ECH_SUPPORT='' @@ -108,7 +108,7 @@ index d9b396376..cd3b845f4 100644 fi dnl now deal with whatever we found -@@ -4795,8 +4809,8 @@ AC_CONFIG_FILES([Makefile \ +@@ -4962,8 +4976,8 @@ AC_CONFIG_FILES([Makefile \ tests/http/clients/Makefile \ packages/Makefile \ packages/vms/Makefile \ @@ -146,52 +146,52 @@ index 54f92d931..ea5895e9b 100644 exit 1 diff --git a/export.sh b/export.sh new file mode 100755 -index 000000000..34b44cd2a +index 000000000..c237ee2ad --- /dev/null +++ b/export.sh @@ -0,0 +1,4 @@ +#!/bin/bash + -+git df curl-8_5_0 > chrome.patch ++git df curl-8_7_1 > chrome.patch +mv chrome.patch ../curl-impersonate/chrome/patches/curl-impersonate.patch diff --git a/include/curl/curl.h b/include/curl/curl.h -index cc24c0506..9cba4dd14 100644 +index b2377b789..0ff2cdfb4 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h -@@ -631,6 +631,7 @@ typedef enum { - CURLE_PROXY, /* 97 - proxy handshake error */ +@@ -632,6 +632,7 @@ typedef enum { CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */ CURLE_UNRECOVERABLE_POLL, /* 99 - poll/select returned fatal error */ -+ CURLE_ECH_REQUIRED , /* 100 - ECH tried but failed */ + CURLE_TOO_LARGE, /* 100 - a value/data met its maximum */ ++ CURLE_ECH_REQUIRED, /* 101 - ECH tried but failed */ CURL_LAST /* never use! */ } CURLcode; -@@ -2201,6 +2202,77 @@ typedef enum { - /* set a specific client IP for HAProxy PROXY protocol header? */ - CURLOPT(CURLOPT_HAPROXY_CLIENT_IP, CURLOPTTYPE_STRINGPOINT, 323), +@@ -2206,6 +2207,77 @@ typedef enum { + /* millisecond version */ + CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT_MS, CURLOPTTYPE_LONG, 324), + /* curl-impersonate: A list of headers used by the impersonated browser. + * If given, merged with CURLOPT_HTTPHEADER. */ -+ CURLOPT(CURLOPT_HTTPBASEHEADER, CURLOPTTYPE_SLISTPOINT, 324), ++ CURLOPT(CURLOPT_HTTPBASEHEADER, CURLOPTTYPE_SLISTPOINT, 1000), + + /* curl-impersonate: A list of TLS signature hash algorithms. + * See https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.4.1 */ -+ CURLOPT(CURLOPT_SSL_SIG_HASH_ALGS, CURLOPTTYPE_STRINGPOINT, 325), ++ CURLOPT(CURLOPT_SSL_SIG_HASH_ALGS, CURLOPTTYPE_STRINGPOINT, 1001), + + /* curl-impersonate: Whether to enable ALPS in TLS or not. + * See https://datatracker.ietf.org/doc/html/draft-vvv-tls-alps. + * Support for ALPS is minimal and is intended only for the TLS client + * hello to match. */ -+ CURLOPT(CURLOPT_SSL_ENABLE_ALPS, CURLOPTTYPE_LONG, 326), ++ CURLOPT(CURLOPT_SSL_ENABLE_ALPS, CURLOPTTYPE_LONG, 1002), + + /* curl-impersonate: Comma-separated list of certificate compression + * algorithms to use. These are published in the client hello. + * Supported algorithms are "zlib" and "brotli". + * See https://datatracker.ietf.org/doc/html/rfc8879 */ -+ CURLOPT(CURLOPT_SSL_CERT_COMPRESSION, CURLOPTTYPE_STRINGPOINT, 327), ++ CURLOPT(CURLOPT_SSL_CERT_COMPRESSION, CURLOPTTYPE_STRINGPOINT, 1003), + + /* Enable/disable TLS session ticket extension (RFC5077) */ -+ CURLOPT(CURLOPT_SSL_ENABLE_TICKET, CURLOPTTYPE_LONG, 328), ++ CURLOPT(CURLOPT_SSL_ENABLE_TICKET, CURLOPTTYPE_LONG, 1004), + + /* + * curl-impersonate: @@ -200,46 +200,46 @@ index cc24c0506..9cba4dd14 100644 + * ":method", ":authority", ":scheme", ":path" in the desired order of + * appearance in the HTTP/2 HEADERS frame. + */ -+ CURLOPT(CURLOPT_HTTP2_PSEUDO_HEADERS_ORDER, CURLOPTTYPE_STRINGPOINT, 329), ++ CURLOPT(CURLOPT_HTTP2_PSEUDO_HEADERS_ORDER, CURLOPTTYPE_STRINGPOINT, 1005), + + /* + * curl-impersonate: + * HTTP2 settings frame keys and values, format: 1:v;2:v;3:v + */ -+ CURLOPT(CURLOPT_HTTP2_SETTINGS, CURLOPTTYPE_STRINGPOINT, 330), ++ CURLOPT(CURLOPT_HTTP2_SETTINGS, CURLOPTTYPE_STRINGPOINT, 1006), + + /* + * curl-impersonate: Whether to enable Boringssl permute extensions + * See https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_set_permute_extensions. + */ -+ CURLOPT(CURLOPT_SSL_PERMUTE_EXTENSIONS, CURLOPTTYPE_LONG, 331), ++ CURLOPT(CURLOPT_SSL_PERMUTE_EXTENSIONS, CURLOPTTYPE_LONG, 1007), + + /* + * curl-impersonate: + * HTTP2 initial window update + */ -+ CURLOPT(CURLOPT_HTTP2_WINDOW_UPDATE, CURLOPTTYPE_LONG, 332), ++ CURLOPT(CURLOPT_HTTP2_WINDOW_UPDATE, CURLOPTTYPE_LONG, 1008), + + /* curl-impersonate: -+ * set ECH configuration, XXX, the official one is 324 ++ * set ECH configuration + */ -+ CURLOPT(CURLOPT_ECH, CURLOPTTYPE_STRINGPOINT, 333), ++ CURLOPT(CURLOPT_ECH, CURLOPTTYPE_STRINGPOINT, 1009), + + /* + * curl-impersonate: + * Set the initial streams settings for http2. + */ -+ CURLOPT(CURLOPT_HTTP2_STREAMS, CURLOPTTYPE_STRINGPOINT, 334), ++ CURLOPT(CURLOPT_HTTP2_STREAMS, CURLOPTTYPE_STRINGPOINT, 1010), + + /* curl-impersonate: + * enable tls grease + */ -+ CURLOPT(CURLOPT_TLS_GREASE, CURLOPTTYPE_LONG, 335), ++ CURLOPT(CURLOPT_TLS_GREASE, CURLOPTTYPE_LONG, 1011), + + /* curl-impersonate: + * set tls extension order + */ -+ CURLOPT(CURLOPT_TLS_EXTENSION_ORDER, CURLOPTTYPE_STRINGPOINT, 336), ++ CURLOPT(CURLOPT_TLS_EXTENSION_ORDER, CURLOPTTYPE_STRINGPOINT, 1012), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; @@ -359,10 +359,10 @@ index 1237c8e99..6b2961018 100644 libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS) diff --git a/lib/Makefile.inc b/lib/Makefile.inc -index e568ef953..298b16050 100644 +index 400e2b1ac..ff3e479aa 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc -@@ -171,6 +171,7 @@ LIB_CFILES = \ +@@ -177,6 +177,7 @@ LIB_CFILES = \ idn.c \ if2ip.c \ imap.c \ @@ -371,10 +371,10 @@ index e568ef953..298b16050 100644 inet_pton.c \ krb5.c \ diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake -index 339358ea3..a9cf400fb 100644 +index 0f4db6982..dfabbefca 100644 --- a/lib/curl_config.h.cmake +++ b/lib/curl_config.h.cmake -@@ -811,3 +811,6 @@ ${SIZEOF_TIME_T_CODE} +@@ -796,3 +796,6 @@ ${SIZEOF_TIME_T_CODE} /* Define to 1 to enable TLS-SRP support. */ #cmakedefine USE_TLS_SRP 1 @@ -433,10 +433,10 @@ index 3b536000a..d7135698f 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 322d1a41b..805613e6f 100644 +index dc4870608..7a12d9c4d 100644 --- a/lib/easy.c +++ b/lib/easy.c -@@ -74,6 +74,8 @@ +@@ -75,6 +75,8 @@ #include "dynbuf.h" #include "altsvc.h" #include "hsts.h" @@ -445,7 +445,7 @@ index 322d1a41b..805613e6f 100644 #include "easy_lock.h" -@@ -341,6 +343,203 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, +@@ -342,6 +344,203 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, return rc; } @@ -649,7 +649,7 @@ index 322d1a41b..805613e6f 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. -@@ -349,6 +548,8 @@ struct Curl_easy *curl_easy_init(void) +@@ -350,6 +549,8 @@ struct Curl_easy *curl_easy_init(void) { CURLcode result; struct Curl_easy *data; @@ -658,7 +658,7 @@ index 322d1a41b..805613e6f 100644 /* Make sure we inited the global SSL stuff */ global_init_lock(); -@@ -371,6 +572,29 @@ struct Curl_easy *curl_easy_init(void) +@@ -372,6 +573,29 @@ struct Curl_easy *curl_easy_init(void) return NULL; } @@ -688,7 +688,7 @@ index 322d1a41b..805613e6f 100644 return data; } -@@ -945,6 +1169,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) +@@ -952,6 +1176,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) outcurl->state.referer_alloc = TRUE; } @@ -702,17 +702,18 @@ index 322d1a41b..805613e6f 100644 /* 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]) { -@@ -1004,6 +1235,9 @@ fail: +@@ -1040,6 +1271,10 @@ fail: */ void curl_easy_reset(struct Curl_easy *data) { + char *env_target; + char *env_headers; + - Curl_free_request_state(data); ++ Curl_free_request_state(data); + Curl_req_hard_reset(&data->req, data); /* zero out UserDefined data: */ -@@ -1028,6 +1262,23 @@ void curl_easy_reset(struct Curl_easy *data) +@@ -1064,6 +1299,23 @@ void curl_easy_reset(struct Curl_easy *data) #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH) Curl_http_auth_cleanup_digest(data); #endif @@ -737,7 +738,7 @@ index 322d1a41b..805613e6f 100644 /* diff --git a/lib/easyoptions.c b/lib/easyoptions.c -index e69c658b0..027dd6f93 100644 +index 9c4438a10..608a4f549 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -86,6 +86,7 @@ struct curl_easyoption Curl_easyopts[] = { @@ -763,7 +764,7 @@ index e69c658b0..027dd6f93 100644 {"HTTPHEADER", CURLOPT_HTTPHEADER, CURLOT_SLIST, 0}, {"HTTPPOST", CURLOPT_HTTPPOST, CURLOT_OBJECT, 0}, {"HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL, CURLOT_LONG, 0}, -@@ -305,18 +312,23 @@ struct curl_easyoption Curl_easyopts[] = { +@@ -307,18 +314,23 @@ 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}, @@ -787,7 +788,7 @@ index e69c658b0..027dd6f93 100644 {"STDERR", CURLOPT_STDERR, CURLOT_OBJECT, 0}, {"STREAM_DEPENDS", CURLOPT_STREAM_DEPENDS, CURLOT_OBJECT, 0}, {"STREAM_DEPENDS_E", CURLOPT_STREAM_DEPENDS_E, CURLOT_OBJECT, 0}, -@@ -340,6 +352,8 @@ struct curl_easyoption Curl_easyopts[] = { +@@ -342,6 +354,8 @@ 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}, @@ -796,19 +797,19 @@ index e69c658b0..027dd6f93 100644 {"TRAILERDATA", CURLOPT_TRAILERDATA, CURLOT_CBPTR, 0}, {"TRAILERFUNCTION", CURLOPT_TRAILERFUNCTION, CURLOT_FUNCTION, 0}, {"TRANSFERTEXT", CURLOPT_TRANSFERTEXT, CURLOT_LONG, 0}, -@@ -373,6 +387,6 @@ struct curl_easyoption Curl_easyopts[] = { +@@ -375,6 +389,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { -- return ((CURLOPT_LASTENTRY%10000) != (323 + 1)); -+ return ((CURLOPT_LASTENTRY%10000) != (334 + 1)); +- return ((CURLOPT_LASTENTRY%10000) != (324 + 1)); ++ return ((CURLOPT_LASTENTRY%10000) != (1100 + 1)); } #endif diff --git a/lib/http.c b/lib/http.c -index be6d442e8..ca537314a 100644 +index 92c04e69c..84ece2a16 100644 --- a/lib/http.c +++ b/lib/http.c -@@ -90,6 +90,7 @@ +@@ -91,6 +91,7 @@ #include "ws.h" #include "c-hyper.h" #include "curl_ctype.h" @@ -816,7 +817,7 @@ index be6d442e8..ca537314a 100644 /* The last 3 #include files should be in this order */ #include "curl_printf.h" -@@ -1937,6 +1938,15 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, +@@ -1451,6 +1452,15 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, int numlists = 1; /* by default */ int i; @@ -832,7 +833,7 @@ index be6d442e8..ca537314a 100644 #ifndef CURL_DISABLE_PROXY enum proxy_use proxy; -@@ -1948,10 +1958,10 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, +@@ -1462,10 +1472,10 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, switch(proxy) { case HEADER_SERVER: @@ -845,7 +846,7 @@ index be6d442e8..ca537314a 100644 if(data->set.sep_headers) { h[1] = data->set.proxyheaders; numlists++; -@@ -1961,12 +1971,12 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, +@@ -1475,12 +1485,12 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, if(data->set.sep_headers) h[0] = data->set.proxyheaders; else @@ -860,7 +861,7 @@ index be6d442e8..ca537314a 100644 #endif /* loop through one or two lists */ -@@ -2202,6 +2212,108 @@ void Curl_http_method(struct Curl_easy *data, struct connectdata *conn, +@@ -1717,6 +1727,108 @@ void Curl_http_method(struct Curl_easy *data, struct connectdata *conn, *reqp = httpreq; } @@ -969,9 +970,9 @@ index be6d442e8..ca537314a 100644 CURLcode Curl_http_useragent(struct Curl_easy *data) { /* The User-Agent string might have been allocated in url.c already, because -@@ -3210,6 +3322,11 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) - http = data->req.p.http; - DEBUGASSERT(http); +@@ -2558,6 +2670,11 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) + if(result) + goto fail; + /* curl-impersonate: Add HTTP headers to impersonate real browsers. */ + result = Curl_http_merge_headers(data); @@ -980,8 +981,8 @@ index be6d442e8..ca537314a 100644 + result = Curl_http_host(data, conn); if(result) - return result; -@@ -4847,12 +4964,41 @@ static bool h2_non_field(const char *name, size_t namelen) + goto fail; +@@ -4269,12 +4386,41 @@ static bool h2_non_field(const char *name, size_t namelen) return FALSE; } @@ -1023,7 +1024,7 @@ index be6d442e8..ca537314a 100644 CURLcode result; DEBUGASSERT(req); -@@ -4886,25 +5032,56 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers, +@@ -4308,25 +4454,56 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers, Curl_dynhds_reset(h2_headers); Curl_dynhds_set_opts(h2_headers, DYNHDS_OPT_LOWERCASE); @@ -1093,7 +1094,7 @@ index be6d442e8..ca537314a 100644 } diff --git a/lib/http2.c b/lib/http2.c -index 973848484..36654499d 100644 +index 99d7f3b0e..9bf0653d7 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -51,6 +51,7 @@ @@ -1286,7 +1287,7 @@ index 973848484..36654499d 100644 static CURLcode h2_progress_egress(struct Curl_cfilter *cf, struct Curl_easy *data); -@@ -504,8 +635,22 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf, +@@ -491,8 +622,22 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf, } } @@ -1311,7 +1312,7 @@ index 973848484..36654499d 100644 if(rc) { failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)", nghttp2_strerror(rc), rc); -@@ -513,6 +658,16 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf, +@@ -500,6 +645,16 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf, goto out; } @@ -1328,7 +1329,7 @@ index 973848484..36654499d 100644 /* all set, traffic will be send on connect */ result = CURLE_OK; CURL_TRC_CF(data, cf, "[0] created h2 session%s", -@@ -1747,11 +1902,19 @@ out: +@@ -1716,11 +1871,19 @@ out: return rv; } @@ -1349,7 +1350,7 @@ index 973848484..36654499d 100644 } static int sweight_in_effect(const struct Curl_easy *data) -@@ -1759,6 +1922,7 @@ static int sweight_in_effect(const struct Curl_easy *data) +@@ -1728,6 +1891,7 @@ 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; @@ -1357,7 +1358,7 @@ index 973848484..36654499d 100644 } /* -@@ -1767,15 +1931,24 @@ static int sweight_in_effect(const struct Curl_easy *data) +@@ -1736,15 +1900,24 @@ static int sweight_in_effect(const struct Curl_easy *data) * struct. */ @@ -1371,7 +1372,7 @@ index 973848484..36654499d 100644 nghttp2_priority_spec *pri_spec) { struct Curl_data_priority *prio = &data->set.priority; - struct stream_ctx *depstream = H2_STREAM_CTX(prio->parent); + struct h2_stream_ctx *depstream = H2_STREAM_CTX(prio->parent); int32_t depstream_id = depstream? depstream->id:0; + // int32_t depstream_id = depstream? depstream->id:FIREFOX_DEFAULT_STREAM_DEP; + /* curl-impersonate: Set stream exclusive flag to true. */ @@ -1383,8 +1384,8 @@ index 973848484..36654499d 100644 data->state.priority = *prio; } -@@ -1792,20 +1965,24 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf, - struct stream_ctx *stream = H2_STREAM_CTX(data); +@@ -1761,20 +1934,24 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf, + struct h2_stream_ctx *stream = H2_STREAM_CTX(data); int rv = 0; + /* curl-impersonate: Check if stream exclusive flag is true. */ @@ -2463,10 +2464,10 @@ index 000000000..a9e1e4b45 + +#endif /* HEADER_CURL_IMPERSONATE_H */ diff --git a/lib/multi.c b/lib/multi.c -index 5456113be..85841f769 100644 +index ed9cac796..6ca666e4a 100644 --- a/lib/multi.c +++ b/lib/multi.c -@@ -396,7 +396,8 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ +@@ -401,7 +401,8 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ Curl_llist_init(&multi->msgsent, NULL); multi->multiplexing = TRUE; @@ -2477,7 +2478,7 @@ index 5456113be..85841f769 100644 #ifdef USE_WINSOCK multi->wsa_event = WSACreateEvent(); diff --git a/lib/setopt.c b/lib/setopt.c -index a08140cce..05468ff49 100644 +index 8a5a5d7c3..18e793209 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -51,6 +51,7 @@ @@ -2485,10 +2486,10 @@ index a08140cce..05468ff49 100644 #include "hsts.h" #include "tftp.h" +#include "slist.h" - + #include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" -@@ -710,6 +711,23 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) +@@ -717,6 +718,23 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) va_arg(param, char *)); break; @@ -2512,7 +2513,7 @@ index a08140cce..05468ff49 100644 #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXYHEADER: /* -@@ -2394,6 +2412,27 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) +@@ -2398,6 +2416,27 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) result = Curl_setstropt(&data->set.str[STRING_SSL_EC_CURVES], va_arg(param, char *)); break; @@ -2583,7 +2584,7 @@ index a08140cce..05468ff49 100644 #ifdef USE_UNIX_SOCKETS case CURLOPT_UNIX_SOCKET_PATH: data->set.abstract_unix_socket = FALSE; -@@ -3128,6 +3203,31 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) +@@ -3132,6 +3207,31 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.ws_raw_mode = raw; break; } @@ -2616,12 +2617,12 @@ index a08140cce..05468ff49 100644 case CURLOPT_QUICK_EXIT: data->set.quick_exit = (0 != va_arg(param, long)) ? 1L:0L; diff --git a/lib/strerror.c b/lib/strerror.c -index 0d5f9276f..232116383 100644 +index a900e78d1..e7d54905a 100644 --- a/lib/strerror.c +++ b/lib/strerror.c -@@ -319,6 +319,11 @@ curl_easy_strerror(CURLcode error) - case CURLE_UNRECOVERABLE_POLL: - return "Unrecoverable error in select/poll"; +@@ -322,6 +322,11 @@ curl_easy_strerror(CURLcode error) + case CURLE_TOO_LARGE: + return "A value or data field grew larger than allowed"; +#ifdef USE_ECH + case CURLE_ECH_REQUIRED: @@ -2632,10 +2633,10 @@ index 0d5f9276f..232116383 100644 case CURLE_OBSOLETE20: case CURLE_OBSOLETE24: diff --git a/lib/transfer.c b/lib/transfer.c -index 96f1fde75..4a57497c7 100644 +index e31d1d6db..66e106901 100644 --- a/lib/transfer.c +++ b/lib/transfer.c -@@ -104,7 +104,15 @@ char *Curl_checkheaders(const struct Curl_easy *data, +@@ -105,7 +105,15 @@ char *Curl_checkheaders(const struct Curl_easy *data, DEBUGASSERT(thislen); DEBUGASSERT(thisheader[thislen-1] != ':'); @@ -2653,10 +2654,10 @@ index 96f1fde75..4a57497c7 100644 Curl_headersep(head->data[thislen]) ) return head->data; diff --git a/lib/url.c b/lib/url.c -index b81785fe2..699e8037a 100644 +index 224b9f3e2..4027f44d5 100644 --- a/lib/url.c +++ b/lib/url.c -@@ -322,6 +322,11 @@ CURLcode Curl_close(struct Curl_easy **datap) +@@ -320,6 +320,20 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->state.aptr.proxyuser); Curl_safefree(data->state.aptr.proxypasswd); @@ -2665,10 +2666,19 @@ index b81785fe2..699e8037a 100644 + /* curl-impersonate: Free the dynamic list of headers. */ + curl_slist_free_all(data->state.merged_headers); + - #ifndef CURL_DISABLE_DOH - if(data->req.doh) { - Curl_dyn_free(&data->req.doh->probe[0].serverdoh); -@@ -468,6 +473,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) ++#ifndef CURL_DISABLE_DOH ++ if(data->req.doh) { ++ Curl_dyn_free(&data->req.doh->probe[0].serverdoh); ++ Curl_dyn_free(&data->req.doh->probe[1].serverdoh); ++ curl_slist_free_all(data->req.doh->headers); ++ Curl_safefree(data->req.doh); ++ } ++#endif ++ + #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API) + Curl_mime_cleanpart(data->state.formp); + Curl_safefree(data->state.formp); +@@ -458,6 +472,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->tcp_fastopen = FALSE; set->tcp_nodelay = TRUE; set->ssl_enable_alpn = TRUE; @@ -2676,7 +2686,7 @@ index b81785fe2..699e8037a 100644 set->expect_100_timeout = 1000L; /* Wait for a second by default. */ set->sep_headers = TRUE; /* separated header lists by default */ set->buffer_size = READBUFFER_SIZE; -@@ -3672,6 +3678,11 @@ static CURLcode create_conn(struct Curl_easy *data, +@@ -3664,6 +3679,11 @@ static CURLcode create_conn(struct Curl_easy *data, (default) */ if(data->set.ssl_enable_alpn) conn->bits.tls_enable_alpn = TRUE; @@ -2689,7 +2699,7 @@ index b81785fe2..699e8037a 100644 if(waitpipe) diff --git a/lib/urldata.h b/lib/urldata.h -index ff661482e..29b9d37fa 100644 +index ce28f25bb..447e24d2a 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -53,6 +53,15 @@ @@ -2705,10 +2715,10 @@ index ff661482e..29b9d37fa 100644 +# define CURLECH_CLA_CFG 4 +#endif + + struct curl_trc_featt; + #ifdef USE_WEBSOCKETS - /* CURLPROTO_GOPHERS (29) is the highest publicly used protocol bit number, - * the rest are internal information. If we use higher bits we only do this on -@@ -290,6 +299,8 @@ struct ssl_primary_config { +@@ -298,6 +307,8 @@ struct ssl_primary_config { char *password; /* TLS password (for, e.g., SRP) */ #endif char *curves; /* list of curves to use */ @@ -2717,7 +2727,7 @@ index ff661482e..29b9d37fa 100644 unsigned char ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */ unsigned int version_max; /* max supported version the client wants to use */ unsigned char version; /* what version the client wants to use */ -@@ -541,6 +552,9 @@ struct ConnectBits { +@@ -545,6 +556,9 @@ struct ConnectBits { BIT(multiplex); /* connection is multiplexed */ BIT(tcp_fastopen); /* use TCP Fast Open */ BIT(tls_enable_alpn); /* TLS ALPN extension? */ @@ -2727,7 +2737,7 @@ index ff661482e..29b9d37fa 100644 #ifndef CURL_DISABLE_DOH BIT(doh); #endif -@@ -1452,6 +1466,19 @@ struct UrlState { +@@ -1320,6 +1334,19 @@ struct UrlState { CURLcode hresult; /* used to pass return codes back from hyper callbacks */ #endif @@ -2744,10 +2754,10 @@ index ff661482e..29b9d37fa 100644 + */ + struct curl_slist *merged_headers; + - /* Dynamically allocated strings, MUST be freed before this struct is - killed. */ - struct dynamically_allocated_data { -@@ -1628,6 +1655,14 @@ enum dupstring { + #ifndef CURL_DISABLE_VERBOSE_STRINGS + struct curl_trc_feat *feat; /* opt. trace feature transfer is part of */ + #endif +@@ -1496,6 +1523,14 @@ enum dupstring { STRING_SSL_EC_CURVES, STRING_AWS_SIGV4, /* Parameters for V4 signature */ STRING_HAPROXY_CLIENT_IP, /* CURLOPT_HAPROXY_CLIENT_IP */ @@ -2762,7 +2772,7 @@ index ff661482e..29b9d37fa 100644 /* -- end of null-terminated strings -- */ -@@ -1921,6 +1956,9 @@ struct UserDefined { +@@ -1791,6 +1826,9 @@ struct UserDefined { BIT(tcp_keepalive); /* use TCP keepalives */ BIT(tcp_fastopen); /* use TCP Fast Open */ BIT(ssl_enable_alpn);/* TLS ALPN extension? */ @@ -2772,7 +2782,7 @@ index ff661482e..29b9d37fa 100644 BIT(path_as_is); /* allow dotdots? */ BIT(pipewait); /* wait for multiplex status before starting a new connection */ -@@ -1941,6 +1979,11 @@ struct UserDefined { +@@ -1811,6 +1849,11 @@ struct UserDefined { #ifdef USE_WEBSOCKETS BIT(ws_raw_mode); #endif @@ -2783,9 +2793,9 @@ index ff661482e..29b9d37fa 100644 + BIT(tls_grease); }; - struct Names { + #ifndef CURL_DISABLE_MIME diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c -index 8c8f43e83..030832aeb 100644 +index a3953f6c3..c854c08b4 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -79,9 +79,24 @@ @@ -2927,7 +2937,7 @@ index 8c8f43e83..030832aeb 100644 #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) typedef uint32_t sslerr_t; #else -@@ -2601,6 +2723,151 @@ static const char *tls_rt_type(int type) +@@ -2644,6 +2766,151 @@ static const char *tls_rt_type(int type) } } @@ -3079,7 +3089,7 @@ index 8c8f43e83..030832aeb 100644 /* * Our callback from the SSL/TLS layers. */ -@@ -3571,7 +3838,14 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3616,7 +3883,14 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, ctx_options = SSL_OP_ALL; #ifdef SSL_OP_NO_TICKET @@ -3095,7 +3105,7 @@ index 8c8f43e83..030832aeb 100644 #endif #ifdef SSL_OP_NO_COMPRESSION -@@ -3638,6 +3912,18 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3683,6 +3957,18 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, } #endif @@ -3114,7 +3124,7 @@ index 8c8f43e83..030832aeb 100644 if(ssl_cert || ssl_cert_blob || ssl_cert_type) { if(!result && !cert_stuff(data, backend->ctx, -@@ -3691,6 +3977,35 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3736,6 +4022,35 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, } #endif @@ -3150,7 +3160,7 @@ index 8c8f43e83..030832aeb 100644 #ifdef USE_OPENSSL_SRP if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) { char * const ssl_username = ssl_config->primary.username; -@@ -3716,6 +4031,38 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3761,6 +4076,38 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, } #endif @@ -3189,7 +3199,7 @@ index 8c8f43e83..030832aeb 100644 /* OpenSSL always tries to verify the peer, this only says whether it should * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with -@@ -3771,6 +4118,24 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3816,6 +4163,24 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, SSL_set_app_data(backend->handle, cf); @@ -3214,7 +3224,7 @@ index 8c8f43e83..030832aeb 100644 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) if(conn_config->verifystatus) -@@ -3794,6 +4159,21 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3839,6 +4204,21 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, } #endif @@ -3236,7 +3246,7 @@ index 8c8f43e83..030832aeb 100644 SSL_set_app_data(backend->handle, cf); connssl->reused_session = FALSE; -@@ -4005,6 +4385,60 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, +@@ -4050,6 +4430,60 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, negotiated_group_name? negotiated_group_name : "[blank]", OBJ_nid2sn(psigtype_nid)); @@ -3298,7 +3308,7 @@ index 8c8f43e83..030832aeb 100644 /* Sets data and len to negotiated protocol, len is 0 if no protocol was * negotiated diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c -index 34eda3e5a..eda3f6d58 100644 +index d13a3cb1b..5ec3db492 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -139,6 +139,9 @@ static const struct alpn_spec ALPN_SPEC_H11 = { @@ -3383,7 +3393,7 @@ index 34eda3e5a..eda3f6d58 100644 ctx->backend = calloc(1, Curl_ssl->sizeof_ssl_backend_data); if(!ctx->backend) { free(ctx); -@@ -1883,8 +1907,11 @@ static CURLcode cf_ssl_create(struct Curl_cfilter **pcf, +@@ -1885,8 +1909,11 @@ static CURLcode cf_ssl_create(struct Curl_cfilter **pcf, DEBUGASSERT(data->conn); @@ -3397,7 +3407,7 @@ index 34eda3e5a..eda3f6d58 100644 if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; -@@ -1934,6 +1961,7 @@ static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf, +@@ -1936,6 +1963,7 @@ static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf, struct ssl_connect_data *ctx; CURLcode result; bool use_alpn = conn->bits.tls_enable_alpn; @@ -3405,7 +3415,7 @@ index 34eda3e5a..eda3f6d58 100644 int httpwant = CURL_HTTP_VERSION_1_1; #ifdef USE_HTTP2 -@@ -1943,7 +1971,8 @@ static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf, +@@ -1945,7 +1973,8 @@ static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf, } #endif @@ -3416,7 +3426,7 @@ index 34eda3e5a..eda3f6d58 100644 result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h -index f1856bd33..fe9f5c266 100644 +index 744bbf8fd..3bd42ee9d 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -44,6 +44,8 @@ struct Curl_ssl_session; @@ -3429,7 +3439,7 @@ index f1856bd33..fe9f5c266 100644 ALPN_ACCEPTED "%s" #define VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR \ diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h -index af7ae552e..f22147e22 100644 +index 0361fa95a..417e6a689 100644 --- a/lib/vtls/vtls_int.h +++ b/lib/vtls/vtls_int.h @@ -70,6 +70,7 @@ struct ssl_connect_data { @@ -3465,10 +3475,10 @@ index 9db6b0f89..14c2f23e0 100644 Libs.private: @LIBCURL_LIBS@ Cflags: -I${includedir} @CPPFLAG_CURL_STATICLIB@ diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4 -index 35ba19866..3bab99f62 100644 +index 9a4547709..42bc87373 100644 --- a/m4/curl-compilers.m4 +++ b/m4/curl-compilers.m4 -@@ -382,42 +382,55 @@ AC_DEFUN([CURL_CONVERT_INCLUDE_TO_ISYSTEM], [ +@@ -381,42 +381,55 @@ AC_DEFUN([CURL_CONVERT_INCLUDE_TO_ISYSTEM], [ AC_REQUIRE([CURL_SHFUNC_SQUEEZE])dnl AC_REQUIRE([CURL_CHECK_COMPILER])dnl AC_MSG_CHECKING([convert -I options to -isystem]) @@ -3560,10 +3570,10 @@ index 35ba19866..3bab99f62 100644 diff --git a/scripts/singleuse.pl b/scripts/singleuse.pl -index b8a57f8d8..63c0e7a55 100755 +index 064990226..172bdc2d0 100755 --- a/scripts/singleuse.pl +++ b/scripts/singleuse.pl -@@ -51,6 +51,7 @@ my %api = ( +@@ -56,6 +56,7 @@ my %api = ( 'curl_easy_escape' => 'API', 'curl_easy_getinfo' => 'API', 'curl_easy_init' => 'API', @@ -3572,7 +3582,7 @@ index b8a57f8d8..63c0e7a55 100755 'curl_easy_perform' => 'API', 'curl_easy_recv' => 'API', diff --git a/src/Makefile.am b/src/Makefile.am -index dced53e0f..dee8a2fc3 100644 +index fcc9cfdf9..18766b7dc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,7 +43,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include \ @@ -3582,9 +3592,9 @@ index dced53e0f..dee8a2fc3 100644 -bin_PROGRAMS = curl +bin_PROGRAMS = curl-impersonate-chrome + if BUILD_DOCS SUBDIRS = ../docs - -@@ -55,9 +55,9 @@ AM_CPPFLAGS += -DBUILDING_CURL +@@ -57,9 +57,9 @@ AM_CPPFLAGS += -DBUILDING_CURL include Makefile.inc # CURL_FILES comes from Makefile.inc @@ -3596,7 +3606,7 @@ index dced53e0f..dee8a2fc3 100644 $(CURL_RCFILES): tool_version.h endif -@@ -70,9 +70,9 @@ CFLAGS += @CURL_CFLAG_EXTRAS@ +@@ -72,9 +72,9 @@ CFLAGS += @CURL_CFLAG_EXTRAS@ LIBS = $(BLANK_AT_MAKETIME) if USE_EXPLICIT_LIB_DEPS @@ -3609,10 +3619,10 @@ index dced53e0f..dee8a2fc3 100644 # if unit tests are enabled, build a static library to link them with diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c -index 906e23e14..5c6613a93 100644 +index 3259bc7a5..8e92fe0ad 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c -@@ -95,6 +95,15 @@ static void free_config_fields(struct OperationConfig *config) +@@ -96,6 +96,15 @@ static void free_config_fields(struct OperationConfig *config) Curl_safefree(config->proto_str); Curl_safefree(config->proto_redir_str); @@ -3628,7 +3638,7 @@ index 906e23e14..5c6613a93 100644 urlnode = config->url_list; while(urlnode) { struct getout *next = urlnode->next; -@@ -175,6 +184,14 @@ static void free_config_fields(struct OperationConfig *config) +@@ -176,6 +185,14 @@ static void free_config_fields(struct OperationConfig *config) Curl_safefree(config->aws_sigv4); Curl_safefree(config->proto_str); Curl_safefree(config->proto_redir_str); @@ -3644,7 +3654,7 @@ index 906e23e14..5c6613a93 100644 void config_free(struct OperationConfig *config) diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h -index 57e8fce52..b5d7019b1 100644 +index dfa74d81f..bf280f986 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -161,8 +161,16 @@ struct OperationConfig { @@ -3694,116 +3704,170 @@ index 57e8fce52..b5d7019b1 100644 struct GlobalConfig { diff --git a/src/tool_getparam.c b/src/tool_getparam.c -index 5fa1ace10..80277bbd9 100644 +index c6a9c9358..15e2ccdf4 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c -@@ -296,6 +296,20 @@ static const struct LongShort aliases[]= { - {"EC", "etag-save", ARG_FILENAME}, - {"ED", "etag-compare", ARG_FILENAME}, - {"EE", "curves", ARG_STRING}, -+ {"ET", "signature-hashes", ARG_STRING}, -+ {"EU", "alps", ARG_BOOL}, -+ {"EI", "cert-compression", ARG_STRING}, -+ {"EJ", "tls-session-ticket", ARG_BOOL}, -+ {"EK", "http2-pseudo-headers-order", ARG_STRING}, -+ {"EL", "http2-settings", ARG_STRING}, -+ {"EM", "tls-permute-extensions", ARG_BOOL}, -+ {"EN", "http2-window-update", ARG_STRING}, +@@ -358,6 +358,7 @@ struct LongShort { + static const struct LongShort aliases[]= { + {"abstract-unix-socket", ARG_FILE, ' ', C_ABSTRACT_UNIX_SOCKET}, + {"alpn", ARG_BOOL, ' ', C_ALPN}, ++ {"alps", ARG_BOOL, ' ', C_ALPS}, // curl-impersonate + {"alt-svc", ARG_STRG, ' ', C_ALT_SVC}, + {"anyauth", ARG_BOOL, ' ', C_ANYAUTH}, + {"append", ARG_BOOL, 'a', C_APPEND}, +@@ -368,6 +369,7 @@ static const struct LongShort aliases[]= { + {"cacert", ARG_FILE, ' ', C_CACERT}, + {"capath", ARG_FILE, ' ', C_CAPATH}, + {"cert", ARG_FILE, 'E', C_CERT}, ++ {"cert-compression", ARG_STRG, ' ', C_CERT_CERT_COMPRESSION}, // curl-impersonate + {"cert-status", ARG_BOOL, ' ', C_CERT_STATUS}, + {"cert-type", ARG_STRG, ' ', C_CERT_TYPE}, + {"ciphers", ARG_STRG, ' ', C_CIPHERS}, +@@ -404,6 +406,9 @@ static const struct LongShort aliases[]= { + {"doh-insecure", ARG_BOOL, ' ', C_DOH_INSECURE}, + {"doh-url" , ARG_STRG, ' ', C_DOH_URL}, + {"dump-header", ARG_FILE, 'D', C_DUMP_HEADER}, +#ifdef USE_ECH -+ {"ER", "ech", ARG_STRING}, ++ {"ech", ARG_STRG, ' ', C_ECH}, // curl-impersonate +#endif -+ {"EV", "http2-streams", ARG_STRING}, -+ {"EW", "tls-extension-order", ARG_STRING}, -+ {"EX", "tls-grease", ARG_BOOL}, - {"f", "fail", ARG_BOOL}, - {"fa", "fail-early", ARG_BOOL}, - {"fb", "styled-output", ARG_BOOL}, -@@ -2124,6 +2138,78 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ - GetStr(&config->ssl_ec_curves, nextarg); - break; - -+ case 'T': -+ /* --signature-hashes */ -+ GetStr(&config->ssl_sig_hash_algs, nextarg); -+ break; -+ -+ case 'U': -+ /* --alps */ -+ config->alps = toggle; -+ break; -+ -+ case 'I': -+ /* --cert-compression */ -+ GetStr(&config->ssl_cert_compression, nextarg); -+ break; -+ -+ case 'J': -+ /* --tls-session-ticket */ -+ config->noticket = (!toggle)?TRUE:FALSE; -+ break; -+ -+ case 'K': -+ /* --http2-pseudo-headers-order */ -+ GetStr(&config->http2_pseudo_headers_order, nextarg); -+ break; -+ -+ case 'L': -+ /* --http2-settings */ -+ GetStr(&config->http2_settings, nextarg); -+ break; -+ -+ case 'M': -+ /* --tls-permute-extensions */ -+ config->ssl_permute_extensions = toggle; -+ break; -+ -+ case 'N': -+ /* --http2-window-update */ -+ err = str2num(&config->http2_window_update, nextarg); -+ if(err) -+ return err; -+ if(config->http2_window_update < -1) -+ return PARAM_BAD_NUMERIC; -+ break; -+ -+ case 'V': -+ /* --http2-streams */ -+ GetStr(&config->http2_streams, nextarg); -+ break; -+ -+ case 'W': -+ /* --tls-extension-order */ -+ GetStr(&config->tls_extension_order, nextarg); -+ // printf("setting is %s\n", config->tls_extension_order); -+ break; -+ -+ case 'X': -+ /* --tls-grease */ -+ config->tls_grease = toggle; -+ break; -+ + {"egd-file", ARG_STRG, ' ', C_EGD_FILE}, + {"engine", ARG_STRG, ' ', C_ENGINE}, + {"eprt", ARG_BOOL, ' ', C_EPRT}, +@@ -447,6 +452,10 @@ static const struct LongShort aliases[]= { + {"http1.1", ARG_NONE, ' ', C_HTTP1_1}, + {"http2", ARG_NONE, ' ', C_HTTP2}, + {"http2-prior-knowledge", ARG_NONE, ' ', C_HTTP2_PRIOR_KNOWLEDGE}, ++ {"http2-pseudo-headers-order", ARG_STRG, ' ', C_HTTP2_PSEUDO_HEADERS_ORDER}, // curl-impersonate ++ {"http2-settings", ARG_STRG, ' ', C_HTTP2_SETTINGS}, // curl-impersonate ++ {"http2-window-update", ARG_STRG, ' ', C_HTTP2_WINDOW_UPDATE}, // curl-impersonate ++ {"http2-streams", ARG_STRG, ' ', C_HTTP2_STREAMS}, // curl-impersonate + {"http3", ARG_NONE, ' ', C_HTTP3}, + {"http3-only", ARG_NONE, ' ', C_HTTP3_ONLY}, + {"ignore-content-length", ARG_BOOL, ' ', C_IGNORE_CONTENT_LENGTH}, +@@ -564,6 +573,7 @@ static const struct LongShort aliases[]= { + {"sessionid", ARG_BOOL, ' ', C_SESSIONID}, + {"show-error", ARG_BOOL, 'S', C_SHOW_ERROR}, + {"silent", ARG_BOOL, 's', C_SILENT}, ++ {"signature-hashes", ARG_STRG, ' ', C_SIGNATURE_HASHES}, // curl-impersonate + {"socks4", ARG_STRG, ' ', C_SOCKS4}, + {"socks4a", ARG_STRG, ' ', C_SOCKS4A}, + {"socks5", ARG_STRG, ' ', C_SOCKS5}, +@@ -593,6 +603,10 @@ static const struct LongShort aliases[]= { + {"tftp-no-options", ARG_BOOL, ' ', C_TFTP_NO_OPTIONS}, + {"time-cond", ARG_STRG, 'z', C_TIME_COND}, + {"tls-max", ARG_STRG, ' ', C_TLS_MAX}, ++ {"tls-session-ticket", ARG_BOOL, ' ', C_TLS_SESSION_TICKET}, // curl-impersonate ++ {"tls-permute-extensions", ARG_BOOL, ' ', C_TLS_PERMUTE_EXTENSIONS}, // curl-impersonate ++ {"tls-extension-order", ARG_STRG, ' ', C_TLS_EXTENSION_ORDER}, // curl-impersonate ++ {"tls-grease", ARG_BOOL, ' ', C_TLS_GREASE}, // curl-impersonate + {"tls13-ciphers", ARG_STRG, ' ', C_TLS13_CIPHERS}, + {"tlsauthtype", ARG_STRG, ' ', C_TLSAUTHTYPE}, + {"tlspassword", ARG_STRG, ' ', C_TLSPASSWORD}, +@@ -1434,6 +1448,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ + case C_ALPN: /* --alpn */ + config->noalpn = (!toggle)?TRUE:FALSE; + break; ++ case C_ALPS: /* --alps curl-impersonate */ ++ config->alps = toggle; ++ break; + case C_LIMIT_RATE: /* --limit-rate */ + err = GetSizeParameter(global, nextarg, "rate", &value); + if(!err) { +@@ -1865,6 +1882,19 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ + case C_TLS_MAX: /* --tls-max */ + err = str2tls_max(&config->ssl_version_max, nextarg); + break; ++ case C_TLS_SESSION_TICKET: /* --tls-session-ticket curl-impersonate */ ++ config->noticket = (!toggle)?TRUE:FALSE; ++ break; ++ case C_TLS_PERMUTE_EXTENSIONS: /* --tls-permute-extensions curl-impersonate */ ++ config->ssl_permute_extensions = toggle; ++ break; ++ case C_TLS_EXTENSION_ORDER: /* --tls-permute-extensions curl-impersonate */ ++ err = getstr(&config->tls_extension_order, nextarg, ALLOW_BLANK); ++ if(err) return err; ++ break; ++ case C_TLS_GREASE: /* --tls-grease curl-impersonate */ ++ config->tls_grease = toggle; ++ break; + case C_SUPPRESS_CONNECT_HEADERS: /* --suppress-connect-headers */ + config->suppress_connect_headers = toggle; + break; +@@ -1914,6 +1944,28 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ + return PARAM_LIBCURL_DOESNT_SUPPORT; + sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE); + break; ++ case C_HTTP2_PSEUDO_HEADERS_ORDER: /* --http2-pseudo-headers-order curl-impersonate */ ++ if(!feature_http2) ++ return PARAM_LIBCURL_DOESNT_SUPPORT; ++ err = getstr(&config->http2_pseudo_headers_order, nextarg, ALLOW_BLANK); ++ break; ++ case C_HTTP2_SETTINGS: /* --http2-settings curl-impersonate */ ++ if(!feature_http2) ++ return PARAM_LIBCURL_DOESNT_SUPPORT; ++ err = getstr(&config->http2_settings, nextarg, ALLOW_BLANK); ++ if(err) return err; ++ break; ++ case C_HTTP2_WINDOW_UPDATE: /* --http2-window-update curl-impersonate */ ++ if(!feature_http2) ++ return PARAM_LIBCURL_DOESNT_SUPPORT; ++ err = str2num(&config->http2_window_update, nextarg); ++ if(config->http2_window_update < -1) return PARAM_BAD_NUMERIC; ++ break; ++ case C_HTTP2_STREAMS: /* --http2-streams curl-impersonate */ ++ if(!feature_http2) ++ return PARAM_LIBCURL_DOESNT_SUPPORT; ++ err = getstr(&config->http2_streams, nextarg, ALLOW_BLANK); ++ break; + case C_HTTP3: /* --http3: */ + /* Try HTTP/3, allow fallback */ + if(!feature_http3) +@@ -2033,6 +2085,18 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ + case C_DUMP_HEADER: /* --dump-header */ + err = getstr(&config->headerfile, nextarg, DENY_BLANK); + break; +#ifdef USE_ECH -+ case 'R': -+ if(strlen(nextarg) != 6 || !strncasecompare("GREASE", nextarg, 6)) { -+ warnf(global, "Only GREASE is supported for --ech."); -+ return PARAM_BAD_USE; /* */ -+ } -+ else { -+ /* Simple case: just a string, with a keyword */ -+ GetStr(&config->ech, nextarg); -+ } -+ break; ++ case C_ECH: /* --ech curl-impersonate */ ++ if(strlen(nextarg) != 6 || !strncasecompare("GREASE", nextarg, 6)) { ++ warnf(global, "Only GREASE is supported for --ech."); ++ return PARAM_BAD_USE; /* */ ++ } ++ else { ++ /* Simple case: just a string, with a keyword */ ++ getStr(&config->ech, nextarg, ALLOW_BLANK); ++ } ++ break; +#endif - default: /* unknown flag */ - err = PARAM_OPTION_UNKNOWN; - break; + case C_REFERER: { /* --referer */ + char *ptr = strstr(nextarg, ";auto"); + if(ptr) { +@@ -2051,6 +2115,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ + cleanarg(clearthis); + GetFileAndPassword(nextarg, &config->cert, &config->key_passwd); + break; ++ case C_CERT_COMPRESSION: /* --cert-compression curl-impersonate */ ++ err = getstr(nextarg, &config->ssl_cert_compression ALLOW_BLANK); ++ break; + case C_CACERT: /* --cacert */ + err = getstr(&config->cacert, nextarg, DENY_BLANK); + break; +@@ -2555,6 +2622,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ + case C_SILENT: /* --silent */ + global->silent = toggle; + break; ++ case C_SIGNATURE_HASHES: /* --signature-hashes */ ++ err = getstr(&config->ssl_sig_hash_algs, nextarg, ALLOW_BLANK); ++ break; + case C_SHOW_ERROR: /* --show-error */ + global->showerror = toggle; + break; diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c -index 4e7a6dd63..8093b7f8e 100644 +index 5d9364405..f346f8e0c 100644 --- a/src/tool_listhelp.c +++ b/src/tool_listhelp.c @@ -111,6 +111,27 @@ const struct helptxt helptext[] = { - {" --curves ", - "(EC) TLS key exchange algorithm(s) to request", + {" --curves ", + "(EC) TLS key exchange algorithms to request", CURLHELP_TLS}, + {" --signature-hashes ", + "TLS signature hash algorithm(s) to use", @@ -3852,10 +3916,10 @@ index 4e7a6dd63..8093b7f8e 100644 "Disable buffering of the output stream", CURLHELP_CURL}, diff --git a/src/tool_operate.c b/src/tool_operate.c -index c805b7732..4f948b09c 100644 +index 7e2c1eefe..467e638e1 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c -@@ -1522,6 +1522,26 @@ static CURLcode single_transfer(struct GlobalConfig *global, +@@ -1510,6 +1510,26 @@ static CURLcode single_transfer(struct GlobalConfig *global, return result; } @@ -3882,7 +3946,7 @@ index c805b7732..4f948b09c 100644 } /* (proto_http) */ if(proto_ftp) -@@ -1610,6 +1630,14 @@ static CURLcode single_transfer(struct GlobalConfig *global, +@@ -1598,6 +1618,14 @@ static CURLcode single_transfer(struct GlobalConfig *global, if(config->ssl_ec_curves) my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves); @@ -3897,7 +3961,7 @@ index c805b7732..4f948b09c 100644 if(config->writeout) my_setopt_str(curl, CURLOPT_CERTINFO, 1L); -@@ -1942,6 +1970,19 @@ static CURLcode single_transfer(struct GlobalConfig *global, +@@ -1930,6 +1958,19 @@ static CURLcode single_transfer(struct GlobalConfig *global, my_setopt_str(curl, CURLOPT_PROXY_TLS13_CIPHERS, config->proxy_cipher13_list); @@ -3917,7 +3981,7 @@ index c805b7732..4f948b09c 100644 /* new in libcurl 7.9.2: */ if(config->disable_epsv) /* disable it */ -@@ -2151,6 +2192,14 @@ static CURLcode single_transfer(struct GlobalConfig *global, +@@ -2139,6 +2180,14 @@ static CURLcode single_transfer(struct GlobalConfig *global, my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L); } @@ -3932,7 +3996,7 @@ index c805b7732..4f948b09c 100644 /* new in 7.40.0, abstract support added in 7.53.0 */ if(config->unix_socket_path) { if(config->abstract_unix_socket) { -@@ -2199,6 +2248,16 @@ static CURLcode single_transfer(struct GlobalConfig *global, +@@ -2187,6 +2236,16 @@ static CURLcode single_transfer(struct GlobalConfig *global, if(config->hsts) my_setopt_str(curl, CURLOPT_HSTS, config->hsts); @@ -3950,10 +4014,10 @@ index c805b7732..4f948b09c 100644 per->retry_sleep_default = (config->retry_delay) ? config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */ diff --git a/src/tool_setopt.c b/src/tool_setopt.c -index de3b78fab..e034c9848 100644 +index 656adbda8..638d427e2 100644 --- a/src/tool_setopt.c +++ b/src/tool_setopt.c -@@ -153,6 +153,8 @@ static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = { +@@ -163,6 +163,8 @@ static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = { NV1(CURLOPT_SSL_VERIFYHOST, 1), NV1(CURLOPT_SSL_ENABLE_NPN, 1), NV1(CURLOPT_SSL_ENABLE_ALPN, 1), diff --git a/docker/alpine.dockerfile b/docker/alpine.dockerfile index ba33647a..6ac2bb48 100644 --- a/docker/alpine.dockerfile +++ b/docker/alpine.dockerfile @@ -68,7 +68,7 @@ RUN cd ${NGHTTP2_VERSION} && \ make && make install # Download curl. -ARG CURL_VERSION=curl-8.5.0 +ARG CURL_VERSION=curl-8.7.1 RUN curl -o ${CURL_VERSION}.tar.xz https://curl.se/download/${CURL_VERSION}.tar.xz RUN tar xf ${CURL_VERSION}.tar.xz diff --git a/docker/debian.dockerfile b/docker/debian.dockerfile index 6feab202..74a27cdc 100644 --- a/docker/debian.dockerfile +++ b/docker/debian.dockerfile @@ -74,7 +74,7 @@ RUN cd ${NGHTTP2_VERSION} && \ make && make install # Download curl. -ARG CURL_VERSION=curl-8.5.0 +ARG CURL_VERSION=curl-8.7.1 RUN curl -o ${CURL_VERSION}.tar.xz https://curl.se/download/${CURL_VERSION}.tar.xz RUN tar xf ${CURL_VERSION}.tar.xz diff --git a/docker/dockerfile.mustache b/docker/dockerfile.mustache index d8eae9af..10b1155f 100644 --- a/docker/dockerfile.mustache +++ b/docker/dockerfile.mustache @@ -99,7 +99,7 @@ RUN cd ${NGHTTP2_VERSION} && \ make && make install # Download curl. -ARG CURL_VERSION=curl-8.5.0 +ARG CURL_VERSION=curl-8.7.1 RUN curl -o ${CURL_VERSION}.tar.xz https://curl.se/download/${CURL_VERSION}.tar.xz RUN tar xf ${CURL_VERSION}.tar.xz diff --git a/docs/03_LIBCURL_IMPERSONATE_PYTHON.md b/docs/03_LIBCURL_IMPERSONATE_PYTHON.md index d0c0de36..d181ff50 100644 --- a/docs/03_LIBCURL_IMPERSONATE_PYTHON.md +++ b/docs/03_LIBCURL_IMPERSONATE_PYTHON.md @@ -1,4 +1,4 @@ # Using libcurl-impersonate in Python scripts -You can use the Python binding [curl_cffi](https://github.com:yifeikong/curl_cffi), which works on Linux, macOS and Windows. +You can use the Python binding [curl_cffi](https://github.com/yifeikong/curl_cffi), which works on Linux, macOS and Windows. diff --git a/win/build.sh b/win/build.sh index 5e23d81a..12d19d93 100644 --- a/win/build.sh +++ b/win/build.sh @@ -38,7 +38,7 @@ export OPENSSL_LIBPATH=$PWD/boringssl/lib export OPENSSL_LIBS='-lssl -lcrypto' -CURL_VERSION=curl-8_5_0 +CURL_VERSION=curl-8_7_1 curl -L https://github.com/curl/curl/archive/${CURL_VERSION}.zip -o curl.zip unzip -q -o curl.zip From dd7d18e3fe548692f50a2540aa0d888b74d815d5 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Sun, 28 Apr 2024 23:07:59 +0800 Subject: [PATCH 02/22] WIP: save at 2024-04-28 23:07:59 --- chrome/patches/curl-impersonate.patch | 42 +++++++++++++++++---------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index 008e837d..9a4b9624 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -433,7 +433,7 @@ index 3b536000a..d7135698f 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 dc4870608..7a12d9c4d 100644 +index dc4870608..ac45a7da3 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -75,6 +75,8 @@ @@ -445,7 +445,7 @@ index dc4870608..7a12d9c4d 100644 #include "easy_lock.h" -@@ -342,6 +344,203 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, +@@ -342,6 +344,207 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, return rc; } @@ -590,6 +590,10 @@ index dc4870608..7a12d9c4d 100644 + ret = curl_easy_setopt(data, CURLOPT_TLS_EXTENSION_ORDER, opts->tls_extension_order); + } + ++ if(opts->http2_stream_weight) { ++ ret = curl_easy_setopt(data, CURLOPT_STREAM_WEIGHT, opts->http2_stream_weight); ++ } ++ + /* Always enable all supported compressions. */ + ret = curl_easy_setopt(data, CURLOPT_ACCEPT_ENCODING, ""); + if(ret) @@ -649,7 +653,7 @@ index dc4870608..7a12d9c4d 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. -@@ -350,6 +549,8 @@ struct Curl_easy *curl_easy_init(void) +@@ -350,6 +553,8 @@ struct Curl_easy *curl_easy_init(void) { CURLcode result; struct Curl_easy *data; @@ -658,7 +662,7 @@ index dc4870608..7a12d9c4d 100644 /* Make sure we inited the global SSL stuff */ global_init_lock(); -@@ -372,6 +573,29 @@ struct Curl_easy *curl_easy_init(void) +@@ -372,6 +577,29 @@ struct Curl_easy *curl_easy_init(void) return NULL; } @@ -688,7 +692,7 @@ index dc4870608..7a12d9c4d 100644 return data; } -@@ -952,6 +1176,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) +@@ -952,6 +1180,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) outcurl->state.referer_alloc = TRUE; } @@ -702,18 +706,17 @@ index dc4870608..7a12d9c4d 100644 /* 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]) { -@@ -1040,6 +1271,10 @@ fail: +@@ -1040,6 +1275,9 @@ fail: */ void curl_easy_reset(struct Curl_easy *data) { + char *env_target; + char *env_headers; + -+ Curl_free_request_state(data); Curl_req_hard_reset(&data->req, data); /* zero out UserDefined data: */ -@@ -1064,6 +1299,23 @@ void curl_easy_reset(struct Curl_easy *data) +@@ -1064,6 +1302,23 @@ void curl_easy_reset(struct Curl_easy *data) #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH) Curl_http_auth_cleanup_digest(data); #endif @@ -1094,7 +1097,7 @@ index 92c04e69c..84ece2a16 100644 } diff --git a/lib/http2.c b/lib/http2.c -index 99d7f3b0e..9bf0653d7 100644 +index 99d7f3b0e..324a12fff 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -51,6 +51,7 @@ @@ -1329,7 +1332,7 @@ index 99d7f3b0e..9bf0653d7 100644 /* all set, traffic will be send on connect */ result = CURLE_OK; CURL_TRC_CF(data, cf, "[0] created h2 session%s", -@@ -1716,11 +1871,19 @@ out: +@@ -1716,11 +1871,20 @@ out: return rv; } @@ -1338,7 +1341,8 @@ index 99d7f3b0e..9bf0653d7 100644 + * instead of NGINX default stream weight. + */ +#define CHROME_DEFAULT_STREAM_WEIGHT (256) -+#define FIREFOX_DEFAULT_STREAM_WEIGHT (42) ++#define SAFARI_DEFAULT_STREAM_WEIGHT (255) ++#define FIREFOX_DEFAULT_STREAM_WEIGHT (42) + static int sweight_wanted(const struct Curl_easy *data) { @@ -1350,7 +1354,7 @@ index 99d7f3b0e..9bf0653d7 100644 } static int sweight_in_effect(const struct Curl_easy *data) -@@ -1728,6 +1891,7 @@ static int sweight_in_effect(const struct Curl_easy *data) +@@ -1728,6 +1892,7 @@ 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; @@ -1358,7 +1362,7 @@ index 99d7f3b0e..9bf0653d7 100644 } /* -@@ -1736,15 +1900,24 @@ static int sweight_in_effect(const struct Curl_easy *data) +@@ -1736,15 +1901,25 @@ static int sweight_in_effect(const struct Curl_easy *data) * struct. */ @@ -1375,6 +1379,7 @@ index 99d7f3b0e..9bf0653d7 100644 struct h2_stream_ctx *depstream = H2_STREAM_CTX(prio->parent); int32_t depstream_id = depstream? depstream->id:0; + // int32_t depstream_id = depstream? depstream->id:FIREFOX_DEFAULT_STREAM_DEP; ++ + /* curl-impersonate: Set stream exclusive flag to true. */ + int exclusive = 1; nghttp2_priority_spec_init(pri_spec, depstream_id, @@ -1384,7 +1389,7 @@ index 99d7f3b0e..9bf0653d7 100644 data->state.priority = *prio; } -@@ -1761,20 +1934,24 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf, +@@ -1761,20 +1936,24 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf, struct h2_stream_ctx *stream = H2_STREAM_CTX(data); int rv = 0; @@ -1433,10 +1438,10 @@ index 80e183480..8ee390b7e 100644 * Store nghttp2 version info in this buffer. diff --git a/lib/impersonate.c b/lib/impersonate.c new file mode 100644 -index 000000000..ef2023033 +index 000000000..3f8ec2bf2 --- /dev/null +++ b/lib/impersonate.c -@@ -0,0 +1,970 @@ +@@ -0,0 +1,975 @@ +#include "curl_setup.h" + +#include @@ -2129,6 +2134,7 @@ index 000000000..ef2023033 + .http2_settings = "4:4194304;3:100", + .http2_window_update = 10485760, + .http2_pseudo_headers_order = "mspa", ++ .http2_stream_weight = 255, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2184,6 +2190,7 @@ index 000000000..ef2023033 + .http2_settings = "4:4194304;3:100", + .http2_window_update = 10485760, + .http2_pseudo_headers_order = "mspa", ++ .http2_stream_weight = 255, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2242,6 +2249,7 @@ index 000000000..ef2023033 + .http2_settings = "2:0;4:2097152;3:100", + .http2_window_update = 10485760, + .http2_pseudo_headers_order = "mspa", ++ .http2_stream_weight = 255, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2300,6 +2308,7 @@ index 000000000..ef2023033 + .http2_settings = "2:0;4:4194304;3:100", + .http2_window_update = 10485760, + .http2_pseudo_headers_order = "mspa", ++ .http2_stream_weight = 255, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2358,6 +2367,7 @@ index 000000000..ef2023033 + .http2_settings = "2:0;4:4194304;3:100", + .http2_window_update = 10485760, + .http2_pseudo_headers_order = "mspa", ++ .http2_stream_weight = 255, + .tls_extension_order = NULL, + .tls_grease = true + }, From 43362ef196e415a2d79096d4f7ef3bde3e00dd7c Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Sun, 28 Apr 2024 23:14:50 +0800 Subject: [PATCH 03/22] WIP: save at 2024-04-28 23:14:50 --- chrome/patches/curl-impersonate.patch | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index 9a4b9624..16656897 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -2419,10 +2419,10 @@ index 000000000..3f8ec2bf2 +}; diff --git a/lib/impersonate.h b/lib/impersonate.h new file mode 100644 -index 000000000..a9e1e4b45 +index 000000000..904d00dbe --- /dev/null +++ b/lib/impersonate.h -@@ -0,0 +1,50 @@ +@@ -0,0 +1,51 @@ +#ifndef HEADER_CURL_IMPERSONATE_H +#define HEADER_CURL_IMPERSONATE_H + @@ -2462,6 +2462,7 @@ index 000000000..a9e1e4b45 + const char *ech; + const char *tls_extension_order; + bool tls_grease; ++ int http2_stream_weight; + /* Other TLS options will come here in the future once they are + * configurable through curl_easy_setopt() */ +}; From 532905a560507177b4483142850c262795361302 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 29 Apr 2024 12:59:30 +0800 Subject: [PATCH 04/22] WIP: save at 2024-04-29 12:59:30 --- chrome/patches/curl-impersonate.patch | 96 ++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 15 deletions(-) diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index 16656897..f9b260aa 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -146,12 +146,17 @@ index 54f92d931..ea5895e9b 100644 exit 1 diff --git a/export.sh b/export.sh new file mode 100755 -index 000000000..c237ee2ad +index 000000000..7bced6879 --- /dev/null +++ b/export.sh -@@ -0,0 +1,4 @@ +@@ -0,0 +1,9 @@ +#!/bin/bash + ++# TODO: use cmake to generate mingw makefile, see: ++# ++# 1. https://github.com/curl/curl/pull/13244/files ++# 2. https://everything.curl.dev/build/windows.html ++ +git df curl-8_7_1 > chrome.patch +mv chrome.patch ../curl-impersonate/chrome/patches/curl-impersonate.patch diff --git a/include/curl/curl.h b/include/curl/curl.h @@ -3715,10 +3720,71 @@ index dfa74d81f..bf280f986 100644 struct GlobalConfig { diff --git a/src/tool_getparam.c b/src/tool_getparam.c -index c6a9c9358..15e2ccdf4 100644 +index c6a9c9358..c04aa954e 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c -@@ -358,6 +358,7 @@ struct LongShort { +@@ -77,6 +77,7 @@ static ParameterError getstr(char **str, const char *val, bool allowblank) + typedef enum { + C_ABSTRACT_UNIX_SOCKET, + C_ALPN, ++ C_ALPS, + C_ALT_SVC, + C_ANYAUTH, + C_APPEND, +@@ -87,6 +88,7 @@ typedef enum { + C_CACERT, + C_CAPATH, + C_CERT, ++ C_CERT_CERT_COMPRESSION, + C_CERT_STATUS, + C_CERT_TYPE, + C_CIPHERS, +@@ -123,6 +125,7 @@ typedef enum { + C_DOH_INSECURE, + C_DOH_URL, + C_DUMP_HEADER, ++ C_ECH, + C_EGD_FILE, + C_ENGINE, + C_EPRT, +@@ -166,6 +169,10 @@ typedef enum { + C_HTTP1_1, + C_HTTP2, + C_HTTP2_PRIOR_KNOWLEDGE, ++ C_HTTP2_PSEUDO_HEADERS_ORDER, ++ C_HTTP2_SETTINGS, ++ C_HTTP2_WINDOW_UPDATE, ++ C_HTTP2_STREAMS, + C_HTTP3, + C_HTTP3_ONLY, + C_IGNORE_CONTENT_LENGTH, +@@ -283,6 +290,7 @@ typedef enum { + C_SESSIONID, + C_SHOW_ERROR, + C_SILENT, ++ C_SIGNATURE_HASHES, + C_SOCKS4, + C_SOCKS4A, + C_SOCKS5, +@@ -299,6 +307,7 @@ typedef enum { + C_SSL_NO_REVOKE, + C_SSL_REQD, + C_SSL_REVOKE_BEST_EFFORT, ++ CURLOPT_SSL_PERMUTE_EXTENSIONS, + C_SSLV2, + C_SSLV3, + C_STDERR, +@@ -312,6 +321,9 @@ typedef enum { + C_TFTP_NO_OPTIONS, + C_TIME_COND, + C_TLS_MAX, ++ C_TLS_SESSION_TICKET, ++ C_TLS_EXTENSION_ORDER, ++ C_TLS_GREASE, + C_TLS13_CIPHERS, + C_TLSAUTHTYPE, + C_TLSPASSWORD, +@@ -358,6 +370,7 @@ struct LongShort { static const struct LongShort aliases[]= { {"abstract-unix-socket", ARG_FILE, ' ', C_ABSTRACT_UNIX_SOCKET}, {"alpn", ARG_BOOL, ' ', C_ALPN}, @@ -3726,7 +3792,7 @@ index c6a9c9358..15e2ccdf4 100644 {"alt-svc", ARG_STRG, ' ', C_ALT_SVC}, {"anyauth", ARG_BOOL, ' ', C_ANYAUTH}, {"append", ARG_BOOL, 'a', C_APPEND}, -@@ -368,6 +369,7 @@ static const struct LongShort aliases[]= { +@@ -368,6 +381,7 @@ static const struct LongShort aliases[]= { {"cacert", ARG_FILE, ' ', C_CACERT}, {"capath", ARG_FILE, ' ', C_CAPATH}, {"cert", ARG_FILE, 'E', C_CERT}, @@ -3734,7 +3800,7 @@ index c6a9c9358..15e2ccdf4 100644 {"cert-status", ARG_BOOL, ' ', C_CERT_STATUS}, {"cert-type", ARG_STRG, ' ', C_CERT_TYPE}, {"ciphers", ARG_STRG, ' ', C_CIPHERS}, -@@ -404,6 +406,9 @@ static const struct LongShort aliases[]= { +@@ -404,6 +418,9 @@ static const struct LongShort aliases[]= { {"doh-insecure", ARG_BOOL, ' ', C_DOH_INSECURE}, {"doh-url" , ARG_STRG, ' ', C_DOH_URL}, {"dump-header", ARG_FILE, 'D', C_DUMP_HEADER}, @@ -3744,7 +3810,7 @@ index c6a9c9358..15e2ccdf4 100644 {"egd-file", ARG_STRG, ' ', C_EGD_FILE}, {"engine", ARG_STRG, ' ', C_ENGINE}, {"eprt", ARG_BOOL, ' ', C_EPRT}, -@@ -447,6 +452,10 @@ static const struct LongShort aliases[]= { +@@ -447,6 +464,10 @@ static const struct LongShort aliases[]= { {"http1.1", ARG_NONE, ' ', C_HTTP1_1}, {"http2", ARG_NONE, ' ', C_HTTP2}, {"http2-prior-knowledge", ARG_NONE, ' ', C_HTTP2_PRIOR_KNOWLEDGE}, @@ -3755,7 +3821,7 @@ index c6a9c9358..15e2ccdf4 100644 {"http3", ARG_NONE, ' ', C_HTTP3}, {"http3-only", ARG_NONE, ' ', C_HTTP3_ONLY}, {"ignore-content-length", ARG_BOOL, ' ', C_IGNORE_CONTENT_LENGTH}, -@@ -564,6 +573,7 @@ static const struct LongShort aliases[]= { +@@ -564,6 +585,7 @@ static const struct LongShort aliases[]= { {"sessionid", ARG_BOOL, ' ', C_SESSIONID}, {"show-error", ARG_BOOL, 'S', C_SHOW_ERROR}, {"silent", ARG_BOOL, 's', C_SILENT}, @@ -3763,7 +3829,7 @@ index c6a9c9358..15e2ccdf4 100644 {"socks4", ARG_STRG, ' ', C_SOCKS4}, {"socks4a", ARG_STRG, ' ', C_SOCKS4A}, {"socks5", ARG_STRG, ' ', C_SOCKS5}, -@@ -593,6 +603,10 @@ static const struct LongShort aliases[]= { +@@ -593,6 +615,10 @@ static const struct LongShort aliases[]= { {"tftp-no-options", ARG_BOOL, ' ', C_TFTP_NO_OPTIONS}, {"time-cond", ARG_STRG, 'z', C_TIME_COND}, {"tls-max", ARG_STRG, ' ', C_TLS_MAX}, @@ -3774,7 +3840,7 @@ index c6a9c9358..15e2ccdf4 100644 {"tls13-ciphers", ARG_STRG, ' ', C_TLS13_CIPHERS}, {"tlsauthtype", ARG_STRG, ' ', C_TLSAUTHTYPE}, {"tlspassword", ARG_STRG, ' ', C_TLSPASSWORD}, -@@ -1434,6 +1448,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -1434,6 +1460,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_ALPN: /* --alpn */ config->noalpn = (!toggle)?TRUE:FALSE; break; @@ -3784,7 +3850,7 @@ index c6a9c9358..15e2ccdf4 100644 case C_LIMIT_RATE: /* --limit-rate */ err = GetSizeParameter(global, nextarg, "rate", &value); if(!err) { -@@ -1865,6 +1882,19 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -1865,6 +1894,19 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_TLS_MAX: /* --tls-max */ err = str2tls_max(&config->ssl_version_max, nextarg); break; @@ -3804,7 +3870,7 @@ index c6a9c9358..15e2ccdf4 100644 case C_SUPPRESS_CONNECT_HEADERS: /* --suppress-connect-headers */ config->suppress_connect_headers = toggle; break; -@@ -1914,6 +1944,28 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -1914,6 +1956,28 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ return PARAM_LIBCURL_DOESNT_SUPPORT; sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE); break; @@ -3833,7 +3899,7 @@ index c6a9c9358..15e2ccdf4 100644 case C_HTTP3: /* --http3: */ /* Try HTTP/3, allow fallback */ if(!feature_http3) -@@ -2033,6 +2085,18 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -2033,6 +2097,18 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_DUMP_HEADER: /* --dump-header */ err = getstr(&config->headerfile, nextarg, DENY_BLANK); break; @@ -3852,7 +3918,7 @@ index c6a9c9358..15e2ccdf4 100644 case C_REFERER: { /* --referer */ char *ptr = strstr(nextarg, ";auto"); if(ptr) { -@@ -2051,6 +2115,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -2051,6 +2127,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ cleanarg(clearthis); GetFileAndPassword(nextarg, &config->cert, &config->key_passwd); break; @@ -3862,7 +3928,7 @@ index c6a9c9358..15e2ccdf4 100644 case C_CACERT: /* --cacert */ err = getstr(&config->cacert, nextarg, DENY_BLANK); break; -@@ -2555,6 +2622,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -2555,6 +2634,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_SILENT: /* --silent */ global->silent = toggle; break; From 6d7a7665b0808589266392bcbca28b166b0a63bf Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Sun, 5 May 2024 19:29:16 +0800 Subject: [PATCH 05/22] Fix bugs in getparam --- chrome/patches/curl-impersonate.patch | 103 +++++++++++++------------- 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index f9b260aa..48e0d28d 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -438,7 +438,7 @@ index 3b536000a..d7135698f 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 dc4870608..ac45a7da3 100644 +index dc4870608..51d4d40cc 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -75,6 +75,8 @@ @@ -459,7 +459,7 @@ index dc4870608..ac45a7da3 100644 + * curl-impersonate: + * Actually call curl_easy_setopt() with all the needed options + * */ -+CURLcode _do_impersonate(struct Curl_easy *data, ++static CURLcode _do_impersonate(struct Curl_easy *data, + const struct impersonate_opts *opts, + int default_headers) +{ @@ -469,7 +469,7 @@ index dc4870608..ac45a7da3 100644 + + if(opts->target == NULL) { + DEBUGF(fprintf(stderr, "Error: unknown impersonation target '%s'\n", -+ target)); ++ opts->target)); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + @@ -746,7 +746,7 @@ index dc4870608..ac45a7da3 100644 /* diff --git a/lib/easyoptions.c b/lib/easyoptions.c -index 9c4438a10..608a4f549 100644 +index 9c4438a10..1869a5878 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -86,6 +86,7 @@ struct curl_easyoption Curl_easyopts[] = { @@ -810,7 +810,7 @@ index 9c4438a10..608a4f549 100644 int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (324 + 1)); -+ return ((CURLOPT_LASTENTRY%10000) != (1100 + 1)); ++ return ((CURLOPT_LASTENTRY%10000) != (1012 + 1)); } #endif diff --git a/lib/http.c b/lib/http.c @@ -2670,7 +2670,7 @@ index e31d1d6db..66e106901 100644 Curl_headersep(head->data[thislen]) ) return head->data; diff --git a/lib/url.c b/lib/url.c -index 224b9f3e2..4027f44d5 100644 +index 224b9f3e2..db07bfa40 100644 --- a/lib/url.c +++ b/lib/url.c @@ -320,6 +320,20 @@ CURLcode Curl_close(struct Curl_easy **datap) @@ -2694,15 +2694,16 @@ index 224b9f3e2..4027f44d5 100644 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API) Curl_mime_cleanpart(data->state.formp); Curl_safefree(data->state.formp); -@@ -458,6 +472,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) +@@ -458,6 +472,8 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->tcp_fastopen = FALSE; set->tcp_nodelay = TRUE; set->ssl_enable_alpn = TRUE; + set->ssl_enable_ticket = TRUE; ++ set->tls_grease = TRUE; set->expect_100_timeout = 1000L; /* Wait for a second by default. */ set->sep_headers = TRUE; /* separated header lists by default */ set->buffer_size = READBUFFER_SIZE; -@@ -3664,6 +3679,11 @@ static CURLcode create_conn(struct Curl_easy *data, +@@ -3664,6 +3680,11 @@ static CURLcode create_conn(struct Curl_easy *data, (default) */ if(data->set.ssl_enable_alpn) conn->bits.tls_enable_alpn = TRUE; @@ -2715,7 +2716,7 @@ index 224b9f3e2..4027f44d5 100644 if(waitpipe) diff --git a/lib/urldata.h b/lib/urldata.h -index ce28f25bb..447e24d2a 100644 +index ce28f25bb..90e1c09d8 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -53,6 +53,15 @@ @@ -2743,17 +2744,26 @@ index ce28f25bb..447e24d2a 100644 unsigned char ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */ unsigned int version_max; /* max supported version the client wants to use */ unsigned char version; /* what version the client wants to use */ -@@ -545,6 +556,9 @@ struct ConnectBits { +@@ -305,6 +316,7 @@ struct ssl_primary_config { + BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */ + BIT(verifystatus); /* set TRUE if certificate status must be checked */ + BIT(sessionid); /* cache session IDs or not */ ++ // BIT(grease); /* grease enabled? */ + }; + + struct ssl_config_data { +@@ -545,6 +557,10 @@ struct ConnectBits { BIT(multiplex); /* connection is multiplexed */ BIT(tcp_fastopen); /* use TCP Fast Open */ BIT(tls_enable_alpn); /* TLS ALPN extension? */ + BIT(tls_enable_alps); /* TLS ALPS extension? */ + BIT(tls_enable_ticket); /* TLS session ticket extension? */ + BIT(tls_permute_extensions); /* TLS extension permutations */ ++ BIT(tls_grease); /* TLS grease? */ #ifndef CURL_DISABLE_DOH BIT(doh); #endif -@@ -1320,6 +1334,19 @@ struct UrlState { +@@ -1320,6 +1336,19 @@ struct UrlState { CURLcode hresult; /* used to pass return codes back from hyper callbacks */ #endif @@ -2773,7 +2783,7 @@ index ce28f25bb..447e24d2a 100644 #ifndef CURL_DISABLE_VERBOSE_STRINGS struct curl_trc_feat *feat; /* opt. trace feature transfer is part of */ #endif -@@ -1496,6 +1523,14 @@ enum dupstring { +@@ -1496,6 +1525,14 @@ enum dupstring { STRING_SSL_EC_CURVES, STRING_AWS_SIGV4, /* Parameters for V4 signature */ STRING_HAPROXY_CLIENT_IP, /* CURLOPT_HAPROXY_CLIENT_IP */ @@ -2788,17 +2798,18 @@ index ce28f25bb..447e24d2a 100644 /* -- end of null-terminated strings -- */ -@@ -1791,6 +1826,9 @@ struct UserDefined { +@@ -1791,6 +1828,10 @@ struct UserDefined { BIT(tcp_keepalive); /* use TCP keepalives */ BIT(tcp_fastopen); /* use TCP Fast Open */ BIT(ssl_enable_alpn);/* TLS ALPN extension? */ + BIT(ssl_enable_alps);/* TLS ALPS extension? */ + BIT(ssl_enable_ticket); /* TLS session ticket extension */ + BIT(ssl_permute_extensions); /* TLS Permute extensions */ ++ BIT(tls_grease); /* TLS grease? */ BIT(path_as_is); /* allow dotdots? */ BIT(pipewait); /* wait for multiplex status before starting a new connection */ -@@ -1811,6 +1849,11 @@ struct UserDefined { +@@ -1811,6 +1852,10 @@ struct UserDefined { #ifdef USE_WEBSOCKETS BIT(ws_raw_mode); #endif @@ -2806,7 +2817,6 @@ index ce28f25bb..447e24d2a 100644 + int tls_ech; /* TLS ECH configuration */ +#endif + int http2_window_update; -+ BIT(tls_grease); }; #ifndef CURL_DISABLE_MIME @@ -3635,26 +3645,25 @@ index fcc9cfdf9..18766b7dc 100644 # if unit tests are enabled, build a static library to link them with diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c -index 3259bc7a5..8e92fe0ad 100644 +index 3259bc7a5..e46fd7539 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c -@@ -96,6 +96,15 @@ static void free_config_fields(struct OperationConfig *config) +@@ -96,6 +96,14 @@ static void free_config_fields(struct OperationConfig *config) Curl_safefree(config->proto_str); Curl_safefree(config->proto_redir_str); -+ // Impersonate ++ // curl-impersonate + Curl_safefree(config->ssl_sig_hash_algs); + Curl_safefree(config->ssl_cert_compression); + Curl_safefree(config->http2_pseudo_headers_order); + Curl_safefree(config->http2_settings); + Curl_safefree(config->http2_streams); + Curl_safefree(config->tls_extension_order); -+ // End Impersonate -+ ++ urlnode = config->url_list; while(urlnode) { struct getout *next = urlnode->next; -@@ -176,6 +185,14 @@ static void free_config_fields(struct OperationConfig *config) +@@ -176,6 +184,14 @@ static void free_config_fields(struct OperationConfig *config) Curl_safefree(config->aws_sigv4); Curl_safefree(config->proto_str); Curl_safefree(config->proto_redir_str); @@ -3720,7 +3729,7 @@ index dfa74d81f..bf280f986 100644 struct GlobalConfig { diff --git a/src/tool_getparam.c b/src/tool_getparam.c -index c6a9c9358..c04aa954e 100644 +index c6a9c9358..bdc9b4df6 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -77,6 +77,7 @@ static ParameterError getstr(char **str, const char *val, bool allowblank) @@ -3735,7 +3744,7 @@ index c6a9c9358..c04aa954e 100644 C_CACERT, C_CAPATH, C_CERT, -+ C_CERT_CERT_COMPRESSION, ++ C_CERT_COMPRESSION, C_CERT_STATUS, C_CERT_TYPE, C_CIPHERS, @@ -3766,20 +3775,13 @@ index c6a9c9358..c04aa954e 100644 C_SOCKS4, C_SOCKS4A, C_SOCKS5, -@@ -299,6 +307,7 @@ typedef enum { - C_SSL_NO_REVOKE, - C_SSL_REQD, - C_SSL_REVOKE_BEST_EFFORT, -+ CURLOPT_SSL_PERMUTE_EXTENSIONS, - C_SSLV2, - C_SSLV3, - C_STDERR, -@@ -312,6 +321,9 @@ typedef enum { +@@ -312,6 +320,10 @@ typedef enum { C_TFTP_NO_OPTIONS, C_TIME_COND, C_TLS_MAX, + C_TLS_SESSION_TICKET, + C_TLS_EXTENSION_ORDER, ++ C_TLS_PERMUTE_EXTENSIONS, + C_TLS_GREASE, C_TLS13_CIPHERS, C_TLSAUTHTYPE, @@ -3796,7 +3798,7 @@ index c6a9c9358..c04aa954e 100644 {"cacert", ARG_FILE, ' ', C_CACERT}, {"capath", ARG_FILE, ' ', C_CAPATH}, {"cert", ARG_FILE, 'E', C_CERT}, -+ {"cert-compression", ARG_STRG, ' ', C_CERT_CERT_COMPRESSION}, // curl-impersonate ++ {"cert-compression", ARG_STRG, ' ', C_CERT_COMPRESSION}, // curl-impersonate {"cert-status", ARG_BOOL, ' ', C_CERT_STATUS}, {"cert-type", ARG_STRG, ' ', C_CERT_TYPE}, {"ciphers", ARG_STRG, ' ', C_CIPHERS}, @@ -3816,27 +3818,28 @@ index c6a9c9358..c04aa954e 100644 {"http2-prior-knowledge", ARG_NONE, ' ', C_HTTP2_PRIOR_KNOWLEDGE}, + {"http2-pseudo-headers-order", ARG_STRG, ' ', C_HTTP2_PSEUDO_HEADERS_ORDER}, // curl-impersonate + {"http2-settings", ARG_STRG, ' ', C_HTTP2_SETTINGS}, // curl-impersonate -+ {"http2-window-update", ARG_STRG, ' ', C_HTTP2_WINDOW_UPDATE}, // curl-impersonate + {"http2-streams", ARG_STRG, ' ', C_HTTP2_STREAMS}, // curl-impersonate ++ {"http2-window-update", ARG_STRG, ' ', C_HTTP2_WINDOW_UPDATE}, // curl-impersonate {"http3", ARG_NONE, ' ', C_HTTP3}, {"http3-only", ARG_NONE, ' ', C_HTTP3_ONLY}, {"ignore-content-length", ARG_BOOL, ' ', C_IGNORE_CONTENT_LENGTH}, -@@ -564,6 +585,7 @@ static const struct LongShort aliases[]= { +@@ -563,6 +584,7 @@ static const struct LongShort aliases[]= { + {"service-name", ARG_STRG, ' ', C_SERVICE_NAME}, {"sessionid", ARG_BOOL, ' ', C_SESSIONID}, {"show-error", ARG_BOOL, 'S', C_SHOW_ERROR}, - {"silent", ARG_BOOL, 's', C_SILENT}, + {"signature-hashes", ARG_STRG, ' ', C_SIGNATURE_HASHES}, // curl-impersonate + {"silent", ARG_BOOL, 's', C_SILENT}, {"socks4", ARG_STRG, ' ', C_SOCKS4}, {"socks4a", ARG_STRG, ' ', C_SOCKS4A}, - {"socks5", ARG_STRG, ' ', C_SOCKS5}, -@@ -593,6 +615,10 @@ static const struct LongShort aliases[]= { +@@ -592,7 +614,11 @@ static const struct LongShort aliases[]= { + {"tftp-blksize", ARG_STRG, ' ', C_TFTP_BLKSIZE}, {"tftp-no-options", ARG_BOOL, ' ', C_TFTP_NO_OPTIONS}, {"time-cond", ARG_STRG, 'z', C_TIME_COND}, - {"tls-max", ARG_STRG, ' ', C_TLS_MAX}, -+ {"tls-session-ticket", ARG_BOOL, ' ', C_TLS_SESSION_TICKET}, // curl-impersonate -+ {"tls-permute-extensions", ARG_BOOL, ' ', C_TLS_PERMUTE_EXTENSIONS}, // curl-impersonate + {"tls-extension-order", ARG_STRG, ' ', C_TLS_EXTENSION_ORDER}, // curl-impersonate + {"tls-grease", ARG_BOOL, ' ', C_TLS_GREASE}, // curl-impersonate + {"tls-max", ARG_STRG, ' ', C_TLS_MAX}, ++ {"tls-permute-extensions", ARG_BOOL, ' ', C_TLS_PERMUTE_EXTENSIONS}, // curl-impersonate ++ {"tls-session-ticket", ARG_BOOL, ' ', C_TLS_SESSION_TICKET}, // curl-impersonate {"tls13-ciphers", ARG_STRG, ' ', C_TLS13_CIPHERS}, {"tlsauthtype", ARG_STRG, ' ', C_TLSAUTHTYPE}, {"tlspassword", ARG_STRG, ' ', C_TLSPASSWORD}, @@ -3850,7 +3853,7 @@ index c6a9c9358..c04aa954e 100644 case C_LIMIT_RATE: /* --limit-rate */ err = GetSizeParameter(global, nextarg, "rate", &value); if(!err) { -@@ -1865,6 +1894,19 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -1865,6 +1894,18 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_TLS_MAX: /* --tls-max */ err = str2tls_max(&config->ssl_version_max, nextarg); break; @@ -3860,9 +3863,8 @@ index c6a9c9358..c04aa954e 100644 + case C_TLS_PERMUTE_EXTENSIONS: /* --tls-permute-extensions curl-impersonate */ + config->ssl_permute_extensions = toggle; + break; -+ case C_TLS_EXTENSION_ORDER: /* --tls-permute-extensions curl-impersonate */ ++ case C_TLS_EXTENSION_ORDER: /* --tls-extension-order curl-impersonate */ + err = getstr(&config->tls_extension_order, nextarg, ALLOW_BLANK); -+ if(err) return err; + break; + case C_TLS_GREASE: /* --tls-grease curl-impersonate */ + config->tls_grease = toggle; @@ -3870,7 +3872,7 @@ index c6a9c9358..c04aa954e 100644 case C_SUPPRESS_CONNECT_HEADERS: /* --suppress-connect-headers */ config->suppress_connect_headers = toggle; break; -@@ -1914,6 +1956,28 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -1914,6 +1955,27 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ return PARAM_LIBCURL_DOESNT_SUPPORT; sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE); break; @@ -3883,7 +3885,6 @@ index c6a9c9358..c04aa954e 100644 + if(!feature_http2) + return PARAM_LIBCURL_DOESNT_SUPPORT; + err = getstr(&config->http2_settings, nextarg, ALLOW_BLANK); -+ if(err) return err; + break; + case C_HTTP2_WINDOW_UPDATE: /* --http2-window-update curl-impersonate */ + if(!feature_http2) @@ -3899,7 +3900,7 @@ index c6a9c9358..c04aa954e 100644 case C_HTTP3: /* --http3: */ /* Try HTTP/3, allow fallback */ if(!feature_http3) -@@ -2033,6 +2097,18 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -2033,6 +2095,18 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_DUMP_HEADER: /* --dump-header */ err = getstr(&config->headerfile, nextarg, DENY_BLANK); break; @@ -3911,24 +3912,24 @@ index c6a9c9358..c04aa954e 100644 + } + else { + /* Simple case: just a string, with a keyword */ -+ getStr(&config->ech, nextarg, ALLOW_BLANK); ++ getstr(&config->ech, nextarg, ALLOW_BLANK); + } + break; +#endif case C_REFERER: { /* --referer */ char *ptr = strstr(nextarg, ";auto"); if(ptr) { -@@ -2051,6 +2127,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -2051,6 +2125,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ cleanarg(clearthis); GetFileAndPassword(nextarg, &config->cert, &config->key_passwd); break; + case C_CERT_COMPRESSION: /* --cert-compression curl-impersonate */ -+ err = getstr(nextarg, &config->ssl_cert_compression ALLOW_BLANK); ++ err = getstr(&config->ssl_cert_compression, nextarg, ALLOW_BLANK); + break; case C_CACERT: /* --cacert */ err = getstr(&config->cacert, nextarg, DENY_BLANK); break; -@@ -2555,6 +2634,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -2555,6 +2632,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_SILENT: /* --silent */ global->silent = toggle; break; From 4aa94784ed5ea9225e7bf03c0d97c79cfee9ae0c Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 6 May 2024 00:25:48 +0800 Subject: [PATCH 06/22] Update dependencies --- Makefile.in | 6 +++--- docker/alpine.dockerfile | 6 +++--- docker/debian.dockerfile | 6 +++--- docker/dockerfile.mustache | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Makefile.in b/Makefile.in index b481884e..7cad557f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -9,12 +9,12 @@ SHELL := bash # MAKEFLAGS += --no-builtin-rules SUBJOBS := 4 -BROTLI_VERSION := 1.0.9 +BROTLI_VERSION := 1.1.0 # In case this is changed, update build-and-test-make.yml as well # In case this is changed, update build-and-test-make.yml as well BORING_SSL_COMMIT := d24a38200fef19150eef00cad35b138936c08767 -NGHTTP2_VERSION := nghttp2-1.56.0 -NGHTTP2_URL := https://github.com/nghttp2/nghttp2/releases/download/v1.56.0/nghttp2-1.56.0.tar.bz2 +NGHTTP2_VERSION := nghttp2-1.61.0 +NGHTTP2_URL := https://github.com/nghttp2/nghttp2/releases/download/v1.61.0/nghttp2-1.61.0.tar.bz2 CURL_VERSION := curl-8_7_1 brotli_install_dir := $(abspath brotli-$(BROTLI_VERSION)/out/installed) diff --git a/docker/alpine.dockerfile b/docker/alpine.dockerfile index 6ac2bb48..c3b17126 100644 --- a/docker/alpine.dockerfile +++ b/docker/alpine.dockerfile @@ -22,7 +22,7 @@ RUN apk add autoconf automake pkgconfig libtool RUN apk add g++ go unzip # Download and compile libbrotli -ARG BROTLI_VERSION=1.0.9 +ARG BROTLI_VERSION=1.1.0 RUN curl -L https://github.com/google/brotli/archive/refs/tags/v${BROTLI_VERSION}.tar.gz -o brotli-${BROTLI_VERSION}.tar.gz && \ tar xf brotli-${BROTLI_VERSION}.tar.gz RUN cd brotli-${BROTLI_VERSION} && \ @@ -55,8 +55,8 @@ RUN mkdir boringssl/build/lib && \ ln -s ../ssl/libssl.a boringssl/build/lib/libssl.a && \ cp -R boringssl/include boringssl/build -ARG NGHTTP2_VERSION=nghttp2-1.56.0 -ARG NGHTTP2_URL=https://github.com/nghttp2/nghttp2/releases/download/v1.56.0/nghttp2-1.56.0.tar.bz2 +ARG NGHTTP2_VERSION=nghttp2-1.61.0 +ARG NGHTTP2_URL=https://github.com/nghttp2/nghttp2/releases/download/v1.61.0/nghttp2-1.61.0.tar.bz2 # Download nghttp2 for HTTP/2.0 support. RUN curl -o ${NGHTTP2_VERSION}.tar.bz2 -L ${NGHTTP2_URL} diff --git a/docker/debian.dockerfile b/docker/debian.dockerfile index 74a27cdc..260ed308 100644 --- a/docker/debian.dockerfile +++ b/docker/debian.dockerfile @@ -28,7 +28,7 @@ RUN apt-get install -y xz-utils RUN apt-get install -y g++ golang-go unzip # Download and compile libbrotli -ARG BROTLI_VERSION=1.0.9 +ARG BROTLI_VERSION=1.1.0 RUN curl -L https://github.com/google/brotli/archive/refs/tags/v${BROTLI_VERSION}.tar.gz -o brotli-${BROTLI_VERSION}.tar.gz && \ tar xf brotli-${BROTLI_VERSION}.tar.gz RUN cd brotli-${BROTLI_VERSION} && \ @@ -61,8 +61,8 @@ RUN mkdir boringssl/build/lib && \ ln -s ../ssl/libssl.a boringssl/build/lib/libssl.a && \ cp -R boringssl/include boringssl/build -ARG NGHTTP2_VERSION=nghttp2-1.56.0 -ARG NGHTTP2_URL=https://github.com/nghttp2/nghttp2/releases/download/v1.56.0/nghttp2-1.56.0.tar.bz2 +ARG NGHTTP2_VERSION=nghttp2-1.61.0 +ARG NGHTTP2_URL=https://github.com/nghttp2/nghttp2/releases/download/v1.61.0/nghttp2-1.61.0.tar.bz2 # Download nghttp2 for HTTP/2.0 support. RUN curl -o ${NGHTTP2_VERSION}.tar.bz2 -L ${NGHTTP2_URL} diff --git a/docker/dockerfile.mustache b/docker/dockerfile.mustache index 10b1155f..f9ea67c3 100644 --- a/docker/dockerfile.mustache +++ b/docker/dockerfile.mustache @@ -53,7 +53,7 @@ RUN apk add g++ go unzip {{/alpine}} # Download and compile libbrotli -ARG BROTLI_VERSION=1.0.9 +ARG BROTLI_VERSION=1.1.0 RUN curl -L https://github.com/google/brotli/archive/refs/tags/v${BROTLI_VERSION}.tar.gz -o brotli-${BROTLI_VERSION}.tar.gz && \ tar xf brotli-${BROTLI_VERSION}.tar.gz RUN cd brotli-${BROTLI_VERSION} && \ @@ -86,8 +86,8 @@ RUN mkdir boringssl/build/lib && \ ln -s ../ssl/libssl.a boringssl/build/lib/libssl.a && \ cp -R boringssl/include boringssl/build -ARG NGHTTP2_VERSION=nghttp2-1.56.0 -ARG NGHTTP2_URL=https://github.com/nghttp2/nghttp2/releases/download/v1.56.0/nghttp2-1.56.0.tar.bz2 +ARG NGHTTP2_VERSION=nghttp2-1.61.0 +ARG NGHTTP2_URL=https://github.com/nghttp2/nghttp2/releases/download/v1.61.0/nghttp2-1.61.0.tar.bz2 # Download nghttp2 for HTTP/2.0 support. RUN curl -o ${NGHTTP2_VERSION}.tar.bz2 -L ${NGHTTP2_URL} From 8a5a853791dba5cf3c89bfa1cc04a201744e82a1 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 6 May 2024 15:35:37 +0800 Subject: [PATCH 07/22] backport curl br encoding patch --- Makefile.in | 4 +- chrome/patches/curl-impersonate.patch | 152 +++++++++++++++++++++++++- 2 files changed, 152 insertions(+), 4 deletions(-) diff --git a/Makefile.in b/Makefile.in index 7cad557f..41d73245 100644 --- a/Makefile.in +++ b/Makefile.in @@ -17,8 +17,9 @@ NGHTTP2_VERSION := nghttp2-1.61.0 NGHTTP2_URL := https://github.com/nghttp2/nghttp2/releases/download/v1.61.0/nghttp2-1.61.0.tar.bz2 CURL_VERSION := curl-8_7_1 +# https://github.com/google/brotli/commit/641bec0e30bea648b3da1cd90fc6b44deb429f71 brotli_install_dir := $(abspath brotli-$(BROTLI_VERSION)/out/installed) -brotli_static_libs := $(brotli_install_dir)/lib/libbrotlicommon-static.a $(brotli_install_dir)/lib/libbrotlidec-static.a +brotli_static_libs := $(brotli_install_dir)/lib/libbrotlicommon.a $(brotli_install_dir)/lib/libbrotlidec.a boringssl_install_dir := $(abspath boringssl/build) boringssl_static_libs := $(boringssl_install_dir)/lib/libssl.a $(boringssl_install_dir)/lib/libcrypto.a nghttp2_install_dir := $(abspath $(NGHTTP2_VERSION)/installed) @@ -144,6 +145,7 @@ $(brotli_static_libs): brotli-$(BROTLI_VERSION).tar.gz -DCMAKE_C_FLAGS="$(CFLAGS)" \ -DCMAKE_SYSTEM_NAME=$$system_name \ -DCMAKE_SYSTEM_PROCESSOR=$(host_cpu) \ + -DBUILD_SHARED_LIBS=OFF \ .. @cmake@ --build . --config Release --target install --parallel $(SUBJOBS) diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index 48e0d28d..d73fc845 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -53,7 +53,7 @@ index 658189e47..1ebc38b5a 100644 # List of files required to generate VC IDE .dsp, .vcproj and .vcxproj files include lib/Makefile.inc diff --git a/configure.ac b/configure.ac -index 49371a755..d6ac97712 100644 +index 49371a755..a19c12b95 100644 --- a/configure.ac +++ b/configure.ac @@ -1422,7 +1422,8 @@ if test X"$OPT_BROTLI" != Xno; then @@ -61,8 +61,8 @@ index 49371a755..d6ac97712 100644 dnl if given with a prefix, we set -L and -I based on that if test -n "$PREFIX_BROTLI"; then - LIB_BROTLI="-lbrotlidec" -+ # curl-impersonate: Use static libbrotli -+ LIB_BROTLI="-lbrotlidec-static -lbrotlicommon-static" ++ # curl-impersonate: Use static libbrotli, -static postfix dropped since brotli 1.1.0 ++ LIB_BROTLI="-lbrotlidec -lbrotlicommon" LD_BROTLI=-L${PREFIX_BROTLI}/lib$libsuff CPP_BROTLI=-I${PREFIX_BROTLI}/include DIR_BROTLI=${PREFIX_BROTLI}/lib$libsuff @@ -375,6 +375,55 @@ index 400e2b1ac..ff3e479aa 100644 inet_ntop.c \ inet_pton.c \ krb5.c \ +diff --git a/lib/content_encoding.c b/lib/content_encoding.c +index c1abf24e8..8e926dd2e 100644 +--- a/lib/content_encoding.c ++++ b/lib/content_encoding.c +@@ -300,7 +300,7 @@ static CURLcode deflate_do_write(struct Curl_easy *data, + struct zlib_writer *zp = (struct zlib_writer *) writer; + z_stream *z = &zp->z; /* zlib state structure */ + +- if(!(type & CLIENTWRITE_BODY)) ++ if(!(type & CLIENTWRITE_BODY) || !nbytes) + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + + /* Set the compressed input when this function is called */ +@@ -457,7 +457,7 @@ static CURLcode gzip_do_write(struct Curl_easy *data, + struct zlib_writer *zp = (struct zlib_writer *) writer; + z_stream *z = &zp->z; /* zlib state structure */ + +- if(!(type & CLIENTWRITE_BODY)) ++ if(!(type & CLIENTWRITE_BODY) || !nbytes) + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + + if(zp->zlib_init == ZLIB_INIT_GZIP) { +@@ -669,7 +669,7 @@ static CURLcode brotli_do_write(struct Curl_easy *data, + CURLcode result = CURLE_OK; + BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; + +- if(!(type & CLIENTWRITE_BODY)) ++ if(!(type & CLIENTWRITE_BODY) || !nbytes) + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + + if(!bp->br) +@@ -762,7 +762,7 @@ static CURLcode zstd_do_write(struct Curl_easy *data, + ZSTD_outBuffer out; + size_t errorCode; + +- if(!(type & CLIENTWRITE_BODY)) ++ if(!(type & CLIENTWRITE_BODY) || !nbytes) + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + + if(!zp->decomp) { +@@ -916,7 +916,7 @@ static CURLcode error_do_write(struct Curl_easy *data, + (void) buf; + (void) nbytes; + +- if(!(type & CLIENTWRITE_BODY)) ++ if(!(type & CLIENTWRITE_BODY) || !nbytes) + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + + failf(data, "Unrecognized content encoding type. " diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake index 0f4db6982..dfabbefca 100644 --- a/lib/curl_config.h.cmake @@ -4104,3 +4153,100 @@ index 656adbda8..638d427e2 100644 NV1(CURLOPT_TCP_NODELAY, 1), NV1(CURLOPT_PROXY_SSL_VERIFYPEER, 1), NV1(CURLOPT_PROXY_SSL_VERIFYHOST, 1), +diff --git a/tests/http/test_02_download.py b/tests/http/test_02_download.py +index 4db9c9d36..395fc862f 100644 +--- a/tests/http/test_02_download.py ++++ b/tests/http/test_02_download.py +@@ -394,6 +394,19 @@ class TestDownload: + r = client.run(args=[url]) + r.check_exit_code(0) + ++ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3']) ++ def test_02_28_get_compressed(self, env: Env, httpd, nghttpx, repeat, proto): ++ if proto == 'h3' and not env.have_h3(): ++ pytest.skip("h3 not supported") ++ count = 1 ++ urln = f'https://{env.authority_for(env.domain1brotli, proto)}/data-100k?[0-{count-1}]' ++ curl = CurlClient(env=env) ++ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[ ++ '--compressed' ++ ]) ++ r.check_exit_code(code=0) ++ r.check_response(count=count, http_status=200) ++ + def check_downloads(self, client, srcfile: str, count: int, + complete: bool = True): + for i in range(count): +diff --git a/tests/http/testenv/env.py b/tests/http/testenv/env.py +index a207059dc..13c5d6bd4 100644 +--- a/tests/http/testenv/env.py ++++ b/tests/http/testenv/env.py +@@ -129,10 +129,11 @@ class EnvConfig: + self.htdocs_dir = os.path.join(self.gen_dir, 'htdocs') + self.tld = 'http.curl.se' + self.domain1 = f"one.{self.tld}" ++ self.domain1brotli = f"brotli.one.{self.tld}" + self.domain2 = f"two.{self.tld}" + self.proxy_domain = f"proxy.{self.tld}" + self.cert_specs = [ +- CertificateSpec(domains=[self.domain1, 'localhost'], key_type='rsa2048'), ++ CertificateSpec(domains=[self.domain1, self.domain1brotli, 'localhost'], key_type='rsa2048'), + CertificateSpec(domains=[self.domain2], key_type='rsa2048'), + CertificateSpec(domains=[self.proxy_domain, '127.0.0.1'], key_type='rsa2048'), + CertificateSpec(name="clientsX", sub_specs=[ +@@ -376,6 +377,10 @@ class Env: + def domain1(self) -> str: + return self.CONFIG.domain1 + ++ @property ++ def domain1brotli(self) -> str: ++ return self.CONFIG.domain1brotli ++ + @property + def domain2(self) -> str: + return self.CONFIG.domain2 +diff --git a/tests/http/testenv/httpd.py b/tests/http/testenv/httpd.py +index c04c22699..b8615875a 100644 +--- a/tests/http/testenv/httpd.py ++++ b/tests/http/testenv/httpd.py +@@ -50,6 +50,7 @@ class Httpd: + 'alias', 'env', 'filter', 'headers', 'mime', 'setenvif', + 'socache_shmcb', + 'rewrite', 'http2', 'ssl', 'proxy', 'proxy_http', 'proxy_connect', ++ 'brotli', + 'mpm_event', + ] + COMMON_MODULES_DIRS = [ +@@ -203,6 +204,7 @@ class Httpd: + + def _write_config(self): + domain1 = self.env.domain1 ++ domain1brotli = self.env.domain1brotli + creds1 = self.env.get_credentials(domain1) + domain2 = self.env.domain2 + creds2 = self.env.get_credentials(domain2) +@@ -285,6 +287,24 @@ class Httpd: + f'', + f'', + ]) ++ # Alternate to domain1 with BROTLI compression ++ conf.extend([ # https host for domain1, h1 + h2 ++ f'', ++ f' ServerName {domain1brotli}', ++ f' Protocols h2 http/1.1', ++ f' SSLEngine on', ++ f' SSLCertificateFile {creds1.cert_file}', ++ f' SSLCertificateKeyFile {creds1.pkey_file}', ++ f' DocumentRoot "{self._docs_dir}"', ++ f' SetOutputFilter BROTLI_COMPRESS', ++ ]) ++ conf.extend(self._curltest_conf(domain1)) ++ if domain1 in self._extra_configs: ++ conf.extend(self._extra_configs[domain1]) ++ conf.extend([ ++ f'', ++ f'', ++ ]) + conf.extend([ # https host for domain2, no h2 + f'', + f' ServerName {domain2}', From a34a94bb9c758fcf69d2a334891bb28111a2fd00 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 6 May 2024 15:56:30 +0800 Subject: [PATCH 08/22] generate windows mingw makefiles --- win/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/win/build.sh b/win/build.sh index 12d19d93..e5b58641 100644 --- a/win/build.sh +++ b/win/build.sh @@ -61,6 +61,7 @@ sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' src/Makefile.mk sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' lib/Makefile.mk sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' src/Makefile.mk +cmake -B build -G "MinGW Makefiles" mingw32-make -f Makefile.dist mingw32-clean mingw32-make -f Makefile.dist mingw32 -j CFLAGS="-DUSE_HTTP2=1 -DUSE_WEBSOCKETS=1 -DUSE_ECH=1 -Wno-unused-variable" CFG=-ssl-zlib-nghttp2-idn2-brotli-zstd-ipv6 From 72a55174355c2762e89755b6f5dba217a38933cc Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 6 May 2024 16:13:22 +0800 Subject: [PATCH 09/22] Update Windows build command --- win/build.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/win/build.sh b/win/build.sh index e5b58641..58055d1b 100644 --- a/win/build.sh +++ b/win/build.sh @@ -61,9 +61,9 @@ sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' src/Makefile.mk sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' lib/Makefile.mk sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' src/Makefile.mk -cmake -B build -G "MinGW Makefiles" -mingw32-make -f Makefile.dist mingw32-clean -mingw32-make -f Makefile.dist mingw32 -j CFLAGS="-DUSE_HTTP2=1 -DUSE_WEBSOCKETS=1 -DUSE_ECH=1 -Wno-unused-variable" CFG=-ssl-zlib-nghttp2-idn2-brotli-zstd-ipv6 +cmake -G "MinGW Makefiles" +mingw32-make clean +mingw32-make -j CFLAGS="-DUSE_HTTP2=1 -DUSE_WEBSOCKETS=1 -DUSE_ECH=1 -Wno-unused-variable" CFG=-ssl-zlib-nghttp2-idn2-brotli-zstd-ipv6 mkdir -p ../dist mv lib/libcurl* ../dist/ From a9775c60f512073df870f403928717c225284192 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 6 May 2024 16:46:25 +0800 Subject: [PATCH 10/22] Enable with cmake --- win/build.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/win/build.sh b/win/build.sh index 58055d1b..11e41bb1 100644 --- a/win/build.sh +++ b/win/build.sh @@ -61,9 +61,18 @@ sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' src/Makefile.mk sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' lib/Makefile.mk sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' src/Makefile.mk -cmake -G "MinGW Makefiles" +cmake -G "MinGW Makefiles" \ + -DUSE_NGHTTP2=ON \ + -DENABLE_WEBSOCKETS=ON \ + -DUSE_ECH=ON \ + -DCURL_ZSTD=ON \ + -DCURL_BROTLI=ON \ + -DENABLE_IPV6=ON \ + -DCURL_ENABLE_SSL=ON \ + + mingw32-make clean -mingw32-make -j CFLAGS="-DUSE_HTTP2=1 -DUSE_WEBSOCKETS=1 -DUSE_ECH=1 -Wno-unused-variable" CFG=-ssl-zlib-nghttp2-idn2-brotli-zstd-ipv6 +mingw32-make -j CFLAGS="-Wno-unused-variable" CFG=-ssl-zlib-nghttp2-idn2-brotli-zstd-ipv6 mkdir -p ../dist mv lib/libcurl* ../dist/ From ea90c96d30783396c80816009edfb358abaa87a9 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 13 May 2024 11:55:36 +0800 Subject: [PATCH 11/22] Add options for exclusiveness --- chrome/curl_chrome100 | 2 + chrome/curl_chrome101 | 2 + chrome/curl_chrome104 | 2 + chrome/curl_chrome107 | 2 + chrome/curl_chrome110 | 2 + chrome/curl_chrome116 | 2 + chrome/curl_chrome119 | 2 + chrome/curl_chrome120 | 2 + chrome/curl_chrome123 | 2 + chrome/curl_chrome124 | 2 + chrome/curl_chrome99 | 2 + chrome/curl_chrome99_android | 2 + chrome/curl_edge101 | 2 + chrome/curl_edge99 | 2 + chrome/curl_safari15_3 | 2 + chrome/curl_safari15_5 | 2 + chrome/curl_safari17_0 | 2 + chrome/curl_safari17_2_ios | 2 + chrome/patches/curl-impersonate.patch | 210 ++++++++++++++++++-------- 19 files changed, 179 insertions(+), 67 deletions(-) diff --git a/chrome/curl_chrome100 b/chrome/curl_chrome100 index 085e1a63..30120ced 100755 --- a/chrome/curl_chrome100 +++ b/chrome/curl_chrome100 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;3:1000;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --tlsv1.2 --alps \ --cert-compression brotli \ diff --git a/chrome/curl_chrome101 b/chrome/curl_chrome101 index d77ef41d..90d4c43f 100755 --- a/chrome/curl_chrome101 +++ b/chrome/curl_chrome101 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;3:1000;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --tlsv1.2 --alps \ --cert-compression brotli \ diff --git a/chrome/curl_chrome104 b/chrome/curl_chrome104 index 0d9ed592..aa237e18 100755 --- a/chrome/curl_chrome104 +++ b/chrome/curl_chrome104 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;3:1000;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --tlsv1.2 --alps \ --cert-compression brotli \ diff --git a/chrome/curl_chrome107 b/chrome/curl_chrome107 index 32fad580..6fa69775 100755 --- a/chrome/curl_chrome107 +++ b/chrome/curl_chrome107 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;2:0;3:1000;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --tlsv1.2 --alps \ --cert-compression brotli \ diff --git a/chrome/curl_chrome110 b/chrome/curl_chrome110 index 50826dbd..c0b53f46 100755 --- a/chrome/curl_chrome110 +++ b/chrome/curl_chrome110 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;2:0;3:1000;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --tlsv1.2 --alps --tls-permute-extensions \ --cert-compression brotli \ diff --git a/chrome/curl_chrome116 b/chrome/curl_chrome116 index d5b14d45..13972f41 100755 --- a/chrome/curl_chrome116 +++ b/chrome/curl_chrome116 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;2:0;3:1000;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --tlsv1.2 --alps --tls-permute-extensions \ --cert-compression brotli \ diff --git a/chrome/curl_chrome119 b/chrome/curl_chrome119 index dd3629c9..75fad132 100755 --- a/chrome/curl_chrome119 +++ b/chrome/curl_chrome119 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;2:0;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --ech GREASE \ --tlsv1.2 --alps --tls-permute-extensions \ diff --git a/chrome/curl_chrome120 b/chrome/curl_chrome120 index 8218e242..d02ce4ff 100755 --- a/chrome/curl_chrome120 +++ b/chrome/curl_chrome120 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;2:0;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --ech GREASE \ --tlsv1.2 --alps --tls-permute-extensions \ diff --git a/chrome/curl_chrome123 b/chrome/curl_chrome123 index a4c50cc1..6a4dba96 100755 --- a/chrome/curl_chrome123 +++ b/chrome/curl_chrome123 @@ -26,6 +26,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;2:0;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --ech GREASE \ --tlsv1.2 --alps --tls-permute-extensions \ diff --git a/chrome/curl_chrome124 b/chrome/curl_chrome124 index 0b481ad6..0468a366 100755 --- a/chrome/curl_chrome124 +++ b/chrome/curl_chrome124 @@ -29,6 +29,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;2:0;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --ech GREASE \ --tlsv1.2 --alps --tls-permute-extensions \ diff --git a/chrome/curl_chrome99 b/chrome/curl_chrome99 index 20ef1cf4..2c643921 100755 --- a/chrome/curl_chrome99 +++ b/chrome/curl_chrome99 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;3:1000;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --tlsv1.2 --alps \ --cert-compression brotli \ diff --git a/chrome/curl_chrome99_android b/chrome/curl_chrome99_android index 79277699..5435fad8 100755 --- a/chrome/curl_chrome99_android +++ b/chrome/curl_chrome99_android @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;3:1000;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --tlsv1.2 --alps \ --cert-compression brotli \ diff --git a/chrome/curl_edge101 b/chrome/curl_edge101 index 6193dec1..d9dd10de 100755 --- a/chrome/curl_edge101 +++ b/chrome/curl_edge101 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;3:1000;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --tlsv1.2 --alps \ --cert-compression brotli \ diff --git a/chrome/curl_edge99 b/chrome/curl_edge99 index cd8e1a65..8e025be3 100755 --- a/chrome/curl_edge99 +++ b/chrome/curl_edge99 @@ -23,6 +23,8 @@ dir=${0%/*} --http2 \ --http2-settings '1:65536;3:1000;4:6291456;6:262144' \ --http2-window-update 15663105 \ + --http2-stream-weight 256 \ + --http2-stream-exclusive 1 \ --compressed \ --tlsv1.2 --alps \ --cert-compression brotli \ diff --git a/chrome/curl_safari15_3 b/chrome/curl_safari15_3 index 0d78f445..ef8cc1f9 100755 --- a/chrome/curl_safari15_3 +++ b/chrome/curl_safari15_3 @@ -18,6 +18,8 @@ dir=${0%/*} --http2-settings '4:4194304;3:100' \ --http2-pseudo-headers-order 'mspa' \ --http2-window-update 10485760 \ + --http2-stream-weight 255 \ + --http2-stream-exclusive 0 \ --compressed \ --tlsv1.0 --no-tls-session-ticket \ --tls-grease \ diff --git a/chrome/curl_safari15_5 b/chrome/curl_safari15_5 index a565cd6a..931d1dff 100755 --- a/chrome/curl_safari15_5 +++ b/chrome/curl_safari15_5 @@ -18,6 +18,8 @@ dir=${0%/*} --http2-settings '4:4194304;3:100' \ --http2-pseudo-headers-order 'mspa' \ --http2-window-update 10485760 \ + --http2-stream-weight 255 \ + --http2-stream-exclusive 0 \ --compressed \ --tlsv1.0 --no-tls-session-ticket \ --cert-compression zlib \ diff --git a/chrome/curl_safari17_0 b/chrome/curl_safari17_0 index 7c06c1dc..1ca523a9 100755 --- a/chrome/curl_safari17_0 +++ b/chrome/curl_safari17_0 @@ -21,6 +21,8 @@ dir=${0%/*} --http2-settings '2:0;4:4194304;3:100' \ --http2-pseudo-headers-order 'mspa' \ --http2-window-update 10485760 \ + --http2-stream-weight 255 \ + --http2-stream-exclusive 0 \ --compressed \ --tlsv1.0 --no-tls-session-ticket \ --cert-compression zlib \ diff --git a/chrome/curl_safari17_2_ios b/chrome/curl_safari17_2_ios index ca5c576d..e9743e00 100755 --- a/chrome/curl_safari17_2_ios +++ b/chrome/curl_safari17_2_ios @@ -21,6 +21,8 @@ dir=${0%/*} --http2-settings '2:0;4:2097152;3:100' \ --http2-pseudo-headers-order 'mspa' \ --http2-window-update 10485760 \ + --http2-stream-weight 255 \ + --http2-stream-exclusive 0 \ --compressed \ --tlsv1.0 --no-tls-session-ticket \ --cert-compression zlib \ diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index d73fc845..c1933e14 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -160,7 +160,7 @@ index 000000000..7bced6879 +git df curl-8_7_1 > chrome.patch +mv chrome.patch ../curl-impersonate/chrome/patches/curl-impersonate.patch diff --git a/include/curl/curl.h b/include/curl/curl.h -index b2377b789..0ff2cdfb4 100644 +index b2377b789..89271eafa 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -632,6 +632,7 @@ typedef enum { @@ -171,7 +171,7 @@ index b2377b789..0ff2cdfb4 100644 CURL_LAST /* never use! */ } CURLcode; -@@ -2206,6 +2207,77 @@ typedef enum { +@@ -2206,6 +2207,80 @@ typedef enum { /* millisecond version */ CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT_MS, CURLOPTTYPE_LONG, 324), @@ -245,6 +245,9 @@ index b2377b789..0ff2cdfb4 100644 + * set tls extension order + */ + CURLOPT(CURLOPT_TLS_EXTENSION_ORDER, CURLOPTTYPE_STRINGPOINT, 1012), ++ ++ /* curl-impersonate: Set stream exclusiveness, 0 or 1 */ ++ CURLOPT(CURLOPT_STREAM_EXCLUSIVE, CURLOPTTYPE_LONG, 1013), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; @@ -487,7 +490,7 @@ index 3b536000a..d7135698f 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 dc4870608..51d4d40cc 100644 +index dc4870608..f0b42fe8b 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -75,6 +75,8 @@ @@ -499,7 +502,7 @@ index dc4870608..51d4d40cc 100644 #include "easy_lock.h" -@@ -342,6 +344,207 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, +@@ -342,6 +344,211 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, return rc; } @@ -648,6 +651,10 @@ index dc4870608..51d4d40cc 100644 + ret = curl_easy_setopt(data, CURLOPT_STREAM_WEIGHT, opts->http2_stream_weight); + } + ++ if(opts->http2_stream_exclusive) { ++ ret = curl_easy_setopt(data, CURLOPT_STREAM_EXCLUSIVE, opts->http2_stream_exclusive); ++ } ++ + /* Always enable all supported compressions. */ + ret = curl_easy_setopt(data, CURLOPT_ACCEPT_ENCODING, ""); + if(ret) @@ -707,7 +714,7 @@ index dc4870608..51d4d40cc 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. -@@ -350,6 +553,8 @@ struct Curl_easy *curl_easy_init(void) +@@ -350,6 +557,8 @@ struct Curl_easy *curl_easy_init(void) { CURLcode result; struct Curl_easy *data; @@ -716,7 +723,7 @@ index dc4870608..51d4d40cc 100644 /* Make sure we inited the global SSL stuff */ global_init_lock(); -@@ -372,6 +577,29 @@ struct Curl_easy *curl_easy_init(void) +@@ -372,6 +581,29 @@ struct Curl_easy *curl_easy_init(void) return NULL; } @@ -746,7 +753,7 @@ index dc4870608..51d4d40cc 100644 return data; } -@@ -952,6 +1180,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) +@@ -952,6 +1184,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) outcurl->state.referer_alloc = TRUE; } @@ -760,7 +767,7 @@ index dc4870608..51d4d40cc 100644 /* 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]) { -@@ -1040,6 +1275,9 @@ fail: +@@ -1040,6 +1279,9 @@ fail: */ void curl_easy_reset(struct Curl_easy *data) { @@ -770,7 +777,7 @@ index dc4870608..51d4d40cc 100644 Curl_req_hard_reset(&data->req, data); /* zero out UserDefined data: */ -@@ -1064,6 +1302,23 @@ void curl_easy_reset(struct Curl_easy *data) +@@ -1064,6 +1306,23 @@ void curl_easy_reset(struct Curl_easy *data) #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH) Curl_http_auth_cleanup_digest(data); #endif @@ -795,7 +802,7 @@ index dc4870608..51d4d40cc 100644 /* diff --git a/lib/easyoptions.c b/lib/easyoptions.c -index 9c4438a10..1869a5878 100644 +index 9c4438a10..7dc93ce27 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -86,6 +86,7 @@ struct curl_easyoption Curl_easyopts[] = { @@ -821,7 +828,7 @@ index 9c4438a10..1869a5878 100644 {"HTTPHEADER", CURLOPT_HTTPHEADER, CURLOT_SLIST, 0}, {"HTTPPOST", CURLOPT_HTTPPOST, CURLOT_OBJECT, 0}, {"HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL, CURLOT_LONG, 0}, -@@ -307,18 +314,23 @@ struct curl_easyoption Curl_easyopts[] = { +@@ -307,22 +314,28 @@ 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}, @@ -845,7 +852,12 @@ index 9c4438a10..1869a5878 100644 {"STDERR", CURLOPT_STDERR, CURLOT_OBJECT, 0}, {"STREAM_DEPENDS", CURLOPT_STREAM_DEPENDS, CURLOT_OBJECT, 0}, {"STREAM_DEPENDS_E", CURLOPT_STREAM_DEPENDS_E, CURLOT_OBJECT, 0}, -@@ -342,6 +354,8 @@ struct curl_easyoption Curl_easyopts[] = { + {"STREAM_WEIGHT", CURLOPT_STREAM_WEIGHT, CURLOT_LONG, 0}, ++ {"STREAM_EXCLUSIVE", CURLOPT_STREAM_EXCLUSIVE, CURLOT_LONG, 0}, + {"SUPPRESS_CONNECT_HEADERS", CURLOPT_SUPPRESS_CONNECT_HEADERS, + CURLOT_LONG, 0}, + {"TCP_FASTOPEN", CURLOPT_TCP_FASTOPEN, CURLOT_LONG, 0}, +@@ -342,6 +355,8 @@ 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}, @@ -854,12 +866,12 @@ index 9c4438a10..1869a5878 100644 {"TRAILERDATA", CURLOPT_TRAILERDATA, CURLOT_CBPTR, 0}, {"TRAILERFUNCTION", CURLOPT_TRAILERFUNCTION, CURLOT_FUNCTION, 0}, {"TRANSFERTEXT", CURLOPT_TRANSFERTEXT, CURLOT_LONG, 0}, -@@ -375,6 +389,6 @@ struct curl_easyoption Curl_easyopts[] = { +@@ -375,6 +390,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (324 + 1)); -+ return ((CURLOPT_LASTENTRY%10000) != (1012 + 1)); ++ return ((CURLOPT_LASTENTRY%10000) != (1013 + 1)); } #endif diff --git a/lib/http.c b/lib/http.c @@ -1151,7 +1163,7 @@ index 92c04e69c..84ece2a16 100644 } diff --git a/lib/http2.c b/lib/http2.c -index 99d7f3b0e..324a12fff 100644 +index 99d7f3b0e..da160907e 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -51,6 +51,7 @@ @@ -1386,7 +1398,7 @@ index 99d7f3b0e..324a12fff 100644 /* all set, traffic will be send on connect */ result = CURLE_OK; CURL_TRC_CF(data, cf, "[0] created h2 session%s", -@@ -1716,11 +1871,20 @@ out: +@@ -1716,11 +1871,19 @@ out: return rv; } @@ -1404,19 +1416,10 @@ index 99d7f3b0e..324a12fff 100644 return data->set.priority.weight? - data->set.priority.weight : NGHTTP2_DEFAULT_WEIGHT; + data->set.priority.weight : CHROME_DEFAULT_STREAM_WEIGHT; -+ // data->set.priority.weight : FIREFOX_DEFAULT_STREAM_WEIGHT; } static int sweight_in_effect(const struct Curl_easy *data) -@@ -1728,6 +1892,7 @@ 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 : FIREFOX_DEFAULT_STREAM_WEIGHT; - } - - /* -@@ -1736,15 +1901,25 @@ static int sweight_in_effect(const struct Curl_easy *data) +@@ -1736,12 +1899,23 @@ static int sweight_in_effect(const struct Curl_easy *data) * struct. */ @@ -1434,16 +1437,13 @@ index 99d7f3b0e..324a12fff 100644 int32_t depstream_id = depstream? depstream->id:0; + // int32_t depstream_id = depstream? depstream->id:FIREFOX_DEFAULT_STREAM_DEP; + -+ /* curl-impersonate: Set stream exclusive flag to true. */ -+ int exclusive = 1; ++ /* curl-impersonate: Set stream exclusive flag based on user option. ++ * Use data->set, not data->state. ++ */ nghttp2_priority_spec_init(pri_spec, depstream_id, sweight_wanted(data), -- data->set.priority.exclusive); -+ exclusive); - data->state.priority = *prio; - } - -@@ -1761,20 +1936,24 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf, + data->set.priority.exclusive); +@@ -1761,20 +1935,24 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf, struct h2_stream_ctx *stream = H2_STREAM_CTX(data); int rv = 0; @@ -1492,10 +1492,10 @@ index 80e183480..8ee390b7e 100644 * Store nghttp2 version info in this buffer. diff --git a/lib/impersonate.c b/lib/impersonate.c new file mode 100644 -index 000000000..3f8ec2bf2 +index 000000000..b18b3a7b5 --- /dev/null +++ b/lib/impersonate.c -@@ -0,0 +1,975 @@ +@@ -0,0 +1,1007 @@ +#include "curl_setup.h" + +#include @@ -1544,6 +1544,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;3:1000;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -1588,6 +1590,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;3:1000;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -1632,6 +1636,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;3:1000;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -1676,6 +1682,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;3:1000;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -1720,6 +1728,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;2:0;3:1000;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -1765,6 +1775,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;2:0;3:1000;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -1810,6 +1822,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;2:0;3:1000;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -1855,6 +1869,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;2:0;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .ech = "GREASE", + .tls_extension_order = NULL, + .tls_grease = true @@ -1901,6 +1917,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;2:0;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .ech = "GREASE", + .tls_extension_order = NULL, + .tls_grease = true @@ -1947,6 +1965,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;2:0;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .ech = "GREASE", + .tls_extension_order = NULL, + .tls_grease = true @@ -1995,6 +2015,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;2:0;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .ech = "GREASE", + .tls_extension_order = NULL, + .tls_grease = true @@ -2040,6 +2062,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;3:1000;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2084,6 +2108,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;3:1000;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2128,6 +2154,8 @@ index 000000000..3f8ec2bf2 + }, + .http2_settings = "1:65536;3:1000;4:6291456;6:262144", + .http2_window_update = 15663105, ++ .http2_stream_weight = 256, ++ .http2_stream_exclusive = 1, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2189,6 +2217,7 @@ index 000000000..3f8ec2bf2 + .http2_window_update = 10485760, + .http2_pseudo_headers_order = "mspa", + .http2_stream_weight = 255, ++ .http2_stream_exclusive = 0, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2245,6 +2274,7 @@ index 000000000..3f8ec2bf2 + .http2_window_update = 10485760, + .http2_pseudo_headers_order = "mspa", + .http2_stream_weight = 255, ++ .http2_stream_exclusive = 0, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2304,6 +2334,7 @@ index 000000000..3f8ec2bf2 + .http2_window_update = 10485760, + .http2_pseudo_headers_order = "mspa", + .http2_stream_weight = 255, ++ .http2_stream_exclusive = 0, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2363,6 +2394,7 @@ index 000000000..3f8ec2bf2 + .http2_window_update = 10485760, + .http2_pseudo_headers_order = "mspa", + .http2_stream_weight = 255, ++ .http2_stream_exclusive = 0, + .tls_extension_order = NULL, + .tls_grease = true + }, @@ -2473,10 +2505,10 @@ index 000000000..3f8ec2bf2 +}; diff --git a/lib/impersonate.h b/lib/impersonate.h new file mode 100644 -index 000000000..904d00dbe +index 000000000..988a7f86a --- /dev/null +++ b/lib/impersonate.h -@@ -0,0 +1,51 @@ +@@ -0,0 +1,52 @@ +#ifndef HEADER_CURL_IMPERSONATE_H +#define HEADER_CURL_IMPERSONATE_H + @@ -2517,6 +2549,7 @@ index 000000000..904d00dbe + const char *tls_extension_order; + bool tls_grease; + int http2_stream_weight; ++ int http2_stream_exclusive; + /* Other TLS options will come here in the future once they are + * configurable through curl_easy_setopt() */ +}; @@ -2543,7 +2576,7 @@ index ed9cac796..6ca666e4a 100644 #ifdef USE_WINSOCK multi->wsa_event = WSACreateEvent(); diff --git a/lib/setopt.c b/lib/setopt.c -index 8a5a5d7c3..18e793209 100644 +index 8a5a5d7c3..70197acc1 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -51,6 +51,7 @@ @@ -2649,7 +2682,22 @@ index 8a5a5d7c3..18e793209 100644 #ifdef USE_UNIX_SOCKETS case CURLOPT_UNIX_SOCKET_PATH: data->set.abstract_unix_socket = FALSE; -@@ -3132,6 +3207,31 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) +@@ -2963,6 +3038,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + break; + #else + return CURLE_NOT_BUILT_IN; ++#endif ++ case CURLOPT_STREAM_EXCLUSIVE: ++#if defined(USE_HTTP2) || defined(USE_HTTP3) ++ arg = va_arg(param, long); ++ data->set.priority.exclusive = (int)arg; ++ break; ++#else ++ return CURLE_NOT_BUILT_IN; + #endif + case CURLOPT_STREAM_DEPENDS: + case CURLOPT_STREAM_DEPENDS_E: +@@ -3132,6 +3215,31 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.ws_raw_mode = raw; break; } @@ -3728,10 +3776,10 @@ index 3259bc7a5..e46fd7539 100644 void config_free(struct OperationConfig *config) diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h -index dfa74d81f..bf280f986 100644 +index dfa74d81f..349a46af6 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h -@@ -161,8 +161,16 @@ struct OperationConfig { +@@ -161,8 +161,18 @@ struct OperationConfig { bool crlf; char *customrequest; char *ssl_ec_curves; @@ -3742,13 +3790,15 @@ index dfa74d81f..bf280f986 100644 + char *http2_pseudo_headers_order; + char *http2_settings; + long http2_window_update; ++ long http2_stream_weight; ++ long http2_stream_exclusive; + char *http2_streams; + bool tls_grease; + char *tls_extension_order; long httpversion; bool http09_allowed; bool nobuffer; -@@ -192,6 +200,7 @@ struct OperationConfig { +@@ -192,6 +202,7 @@ struct OperationConfig { struct curl_slist *prequote; long ssl_version; long ssl_version_max; @@ -3756,7 +3806,7 @@ index dfa74d81f..bf280f986 100644 long proxy_ssl_version; long ip_version; long create_file_mode; /* CURLOPT_NEW_FILE_PERMS */ -@@ -268,6 +277,8 @@ struct OperationConfig { +@@ -268,6 +279,8 @@ struct OperationConfig { bool proxy_ssl_auto_client_cert; /* proxy version of ssl_auto_client_cert */ char *oauth_bearer; /* OAuth 2.0 bearer token */ bool noalpn; /* enable/disable TLS ALPN extension */ @@ -3765,7 +3815,7 @@ index dfa74d81f..bf280f986 100644 char *unix_socket_path; /* path to Unix domain socket */ bool abstract_unix_socket; /* path to an abstract Unix domain socket */ bool falsestart; -@@ -298,6 +309,11 @@ struct OperationConfig { +@@ -298,6 +311,11 @@ struct OperationConfig { struct State state; /* for create_transfer() */ bool rm_partial; /* on error, remove partially written output files */ @@ -3778,7 +3828,7 @@ index dfa74d81f..bf280f986 100644 struct GlobalConfig { diff --git a/src/tool_getparam.c b/src/tool_getparam.c -index c6a9c9358..bdc9b4df6 100644 +index c6a9c9358..2234eb78d 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -77,6 +77,7 @@ static ParameterError getstr(char **str, const char *val, bool allowblank) @@ -3805,18 +3855,20 @@ index c6a9c9358..bdc9b4df6 100644 C_EGD_FILE, C_ENGINE, C_EPRT, -@@ -166,6 +169,10 @@ typedef enum { +@@ -166,6 +169,12 @@ typedef enum { C_HTTP1_1, C_HTTP2, C_HTTP2_PRIOR_KNOWLEDGE, + C_HTTP2_PSEUDO_HEADERS_ORDER, + C_HTTP2_SETTINGS, + C_HTTP2_WINDOW_UPDATE, ++ C_HTTP2_STREAM_EXCLUSIVE, ++ C_HTTP2_STREAM_WEIGHT, + C_HTTP2_STREAMS, C_HTTP3, C_HTTP3_ONLY, C_IGNORE_CONTENT_LENGTH, -@@ -283,6 +290,7 @@ typedef enum { +@@ -283,6 +292,7 @@ typedef enum { C_SESSIONID, C_SHOW_ERROR, C_SILENT, @@ -3824,7 +3876,7 @@ index c6a9c9358..bdc9b4df6 100644 C_SOCKS4, C_SOCKS4A, C_SOCKS5, -@@ -312,6 +320,10 @@ typedef enum { +@@ -312,6 +322,10 @@ typedef enum { C_TFTP_NO_OPTIONS, C_TIME_COND, C_TLS_MAX, @@ -3835,7 +3887,7 @@ index c6a9c9358..bdc9b4df6 100644 C_TLS13_CIPHERS, C_TLSAUTHTYPE, C_TLSPASSWORD, -@@ -358,6 +370,7 @@ struct LongShort { +@@ -358,6 +372,7 @@ struct LongShort { static const struct LongShort aliases[]= { {"abstract-unix-socket", ARG_FILE, ' ', C_ABSTRACT_UNIX_SOCKET}, {"alpn", ARG_BOOL, ' ', C_ALPN}, @@ -3843,7 +3895,7 @@ index c6a9c9358..bdc9b4df6 100644 {"alt-svc", ARG_STRG, ' ', C_ALT_SVC}, {"anyauth", ARG_BOOL, ' ', C_ANYAUTH}, {"append", ARG_BOOL, 'a', C_APPEND}, -@@ -368,6 +381,7 @@ static const struct LongShort aliases[]= { +@@ -368,6 +383,7 @@ static const struct LongShort aliases[]= { {"cacert", ARG_FILE, ' ', C_CACERT}, {"capath", ARG_FILE, ' ', C_CAPATH}, {"cert", ARG_FILE, 'E', C_CERT}, @@ -3851,7 +3903,7 @@ index c6a9c9358..bdc9b4df6 100644 {"cert-status", ARG_BOOL, ' ', C_CERT_STATUS}, {"cert-type", ARG_STRG, ' ', C_CERT_TYPE}, {"ciphers", ARG_STRG, ' ', C_CIPHERS}, -@@ -404,6 +418,9 @@ static const struct LongShort aliases[]= { +@@ -404,6 +420,9 @@ static const struct LongShort aliases[]= { {"doh-insecure", ARG_BOOL, ' ', C_DOH_INSECURE}, {"doh-url" , ARG_STRG, ' ', C_DOH_URL}, {"dump-header", ARG_FILE, 'D', C_DUMP_HEADER}, @@ -3861,18 +3913,20 @@ index c6a9c9358..bdc9b4df6 100644 {"egd-file", ARG_STRG, ' ', C_EGD_FILE}, {"engine", ARG_STRG, ' ', C_ENGINE}, {"eprt", ARG_BOOL, ' ', C_EPRT}, -@@ -447,6 +464,10 @@ static const struct LongShort aliases[]= { +@@ -447,6 +466,12 @@ static const struct LongShort aliases[]= { {"http1.1", ARG_NONE, ' ', C_HTTP1_1}, {"http2", ARG_NONE, ' ', C_HTTP2}, {"http2-prior-knowledge", ARG_NONE, ' ', C_HTTP2_PRIOR_KNOWLEDGE}, + {"http2-pseudo-headers-order", ARG_STRG, ' ', C_HTTP2_PSEUDO_HEADERS_ORDER}, // curl-impersonate + {"http2-settings", ARG_STRG, ' ', C_HTTP2_SETTINGS}, // curl-impersonate ++ {"http2-stream-exclusive", ARG_STRG, ' ', C_HTTP2_STREAM_EXCLUSIVE}, // curl-impersonate ++ {"http2-stream-weight", ARG_STRG, ' ', C_HTTP2_STREAM_WEIGHT}, // curl-impersonate + {"http2-streams", ARG_STRG, ' ', C_HTTP2_STREAMS}, // curl-impersonate + {"http2-window-update", ARG_STRG, ' ', C_HTTP2_WINDOW_UPDATE}, // curl-impersonate {"http3", ARG_NONE, ' ', C_HTTP3}, {"http3-only", ARG_NONE, ' ', C_HTTP3_ONLY}, {"ignore-content-length", ARG_BOOL, ' ', C_IGNORE_CONTENT_LENGTH}, -@@ -563,6 +584,7 @@ static const struct LongShort aliases[]= { +@@ -563,6 +588,7 @@ static const struct LongShort aliases[]= { {"service-name", ARG_STRG, ' ', C_SERVICE_NAME}, {"sessionid", ARG_BOOL, ' ', C_SESSIONID}, {"show-error", ARG_BOOL, 'S', C_SHOW_ERROR}, @@ -3880,7 +3934,7 @@ index c6a9c9358..bdc9b4df6 100644 {"silent", ARG_BOOL, 's', C_SILENT}, {"socks4", ARG_STRG, ' ', C_SOCKS4}, {"socks4a", ARG_STRG, ' ', C_SOCKS4A}, -@@ -592,7 +614,11 @@ static const struct LongShort aliases[]= { +@@ -592,7 +618,11 @@ static const struct LongShort aliases[]= { {"tftp-blksize", ARG_STRG, ' ', C_TFTP_BLKSIZE}, {"tftp-no-options", ARG_BOOL, ' ', C_TFTP_NO_OPTIONS}, {"time-cond", ARG_STRG, 'z', C_TIME_COND}, @@ -3892,7 +3946,7 @@ index c6a9c9358..bdc9b4df6 100644 {"tls13-ciphers", ARG_STRG, ' ', C_TLS13_CIPHERS}, {"tlsauthtype", ARG_STRG, ' ', C_TLSAUTHTYPE}, {"tlspassword", ARG_STRG, ' ', C_TLSPASSWORD}, -@@ -1434,6 +1460,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -1434,6 +1464,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_ALPN: /* --alpn */ config->noalpn = (!toggle)?TRUE:FALSE; break; @@ -3902,7 +3956,7 @@ index c6a9c9358..bdc9b4df6 100644 case C_LIMIT_RATE: /* --limit-rate */ err = GetSizeParameter(global, nextarg, "rate", &value); if(!err) { -@@ -1865,6 +1894,18 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -1865,6 +1898,18 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_TLS_MAX: /* --tls-max */ err = str2tls_max(&config->ssl_version_max, nextarg); break; @@ -3921,7 +3975,7 @@ index c6a9c9358..bdc9b4df6 100644 case C_SUPPRESS_CONNECT_HEADERS: /* --suppress-connect-headers */ config->suppress_connect_headers = toggle; break; -@@ -1914,6 +1955,27 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -1914,6 +1959,39 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ return PARAM_LIBCURL_DOESNT_SUPPORT; sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE); break; @@ -3935,6 +3989,18 @@ index c6a9c9358..bdc9b4df6 100644 + return PARAM_LIBCURL_DOESNT_SUPPORT; + err = getstr(&config->http2_settings, nextarg, ALLOW_BLANK); + break; ++ case C_HTTP2_STREAM_EXCLUSIVE: ++ if(!feature_http2) ++ return PARAM_LIBCURL_DOESNT_SUPPORT; ++ err = str2num(&config->http2_stream_exclusive, nextarg); ++ if(config->http2_stream_exclusive < 0) return PARAM_BAD_NUMERIC; ++ break; ++ case C_HTTP2_STREAM_WEIGHT: ++ if(!feature_http2) ++ return PARAM_LIBCURL_DOESNT_SUPPORT; ++ err = str2num(&config->http2_stream_weight, nextarg); ++ if(config->http2_stream_weight < 0) return PARAM_BAD_NUMERIC; ++ break; + case C_HTTP2_WINDOW_UPDATE: /* --http2-window-update curl-impersonate */ + if(!feature_http2) + return PARAM_LIBCURL_DOESNT_SUPPORT; @@ -3949,7 +4015,7 @@ index c6a9c9358..bdc9b4df6 100644 case C_HTTP3: /* --http3: */ /* Try HTTP/3, allow fallback */ if(!feature_http3) -@@ -2033,6 +2095,18 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -2033,6 +2111,18 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_DUMP_HEADER: /* --dump-header */ err = getstr(&config->headerfile, nextarg, DENY_BLANK); break; @@ -3968,7 +4034,7 @@ index c6a9c9358..bdc9b4df6 100644 case C_REFERER: { /* --referer */ char *ptr = strstr(nextarg, ";auto"); if(ptr) { -@@ -2051,6 +2125,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -2051,6 +2141,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ cleanarg(clearthis); GetFileAndPassword(nextarg, &config->cert, &config->key_passwd); break; @@ -3978,7 +4044,7 @@ index c6a9c9358..bdc9b4df6 100644 case C_CACERT: /* --cacert */ err = getstr(&config->cacert, nextarg, DENY_BLANK); break; -@@ -2555,6 +2632,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ +@@ -2555,6 +2648,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_SILENT: /* --silent */ global->silent = toggle; break; @@ -4043,10 +4109,10 @@ index 5d9364405..f346f8e0c 100644 "Disable buffering of the output stream", CURLHELP_CURL}, diff --git a/src/tool_operate.c b/src/tool_operate.c -index 7e2c1eefe..467e638e1 100644 +index 7e2c1eefe..24b74d180 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c -@@ -1510,6 +1510,26 @@ static CURLcode single_transfer(struct GlobalConfig *global, +@@ -1510,6 +1510,36 @@ static CURLcode single_transfer(struct GlobalConfig *global, return result; } @@ -4065,6 +4131,16 @@ index 7e2c1eefe..467e638e1 100644 + CURLOPT_HTTP2_WINDOW_UPDATE, + config->http2_window_update); + ++ if(config->http2_stream_exclusive) ++ my_setopt(curl, ++ CURLOPT_STREAM_EXCLUSIVE, ++ config->http2_stream_exclusive); ++ ++ if(config->http2_stream_weight) ++ my_setopt(curl, ++ CURLOPT_STREAM_WEIGHT, ++ config->http2_stream_weight); ++ + if(config->http2_streams) + my_setopt_str(curl, + CURLOPT_HTTP2_STREAMS, @@ -4073,7 +4149,7 @@ index 7e2c1eefe..467e638e1 100644 } /* (proto_http) */ if(proto_ftp) -@@ -1598,6 +1618,14 @@ static CURLcode single_transfer(struct GlobalConfig *global, +@@ -1598,6 +1628,14 @@ static CURLcode single_transfer(struct GlobalConfig *global, if(config->ssl_ec_curves) my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves); @@ -4088,7 +4164,7 @@ index 7e2c1eefe..467e638e1 100644 if(config->writeout) my_setopt_str(curl, CURLOPT_CERTINFO, 1L); -@@ -1930,6 +1958,19 @@ static CURLcode single_transfer(struct GlobalConfig *global, +@@ -1930,6 +1968,19 @@ static CURLcode single_transfer(struct GlobalConfig *global, my_setopt_str(curl, CURLOPT_PROXY_TLS13_CIPHERS, config->proxy_cipher13_list); @@ -4108,7 +4184,7 @@ index 7e2c1eefe..467e638e1 100644 /* new in libcurl 7.9.2: */ if(config->disable_epsv) /* disable it */ -@@ -2139,6 +2180,14 @@ static CURLcode single_transfer(struct GlobalConfig *global, +@@ -2139,6 +2190,14 @@ static CURLcode single_transfer(struct GlobalConfig *global, my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L); } @@ -4123,7 +4199,7 @@ index 7e2c1eefe..467e638e1 100644 /* new in 7.40.0, abstract support added in 7.53.0 */ if(config->unix_socket_path) { if(config->abstract_unix_socket) { -@@ -2187,6 +2236,16 @@ static CURLcode single_transfer(struct GlobalConfig *global, +@@ -2187,6 +2246,16 @@ static CURLcode single_transfer(struct GlobalConfig *global, if(config->hsts) my_setopt_str(curl, CURLOPT_HSTS, config->hsts); From 79839714dc62ec2760fe9cf2c1c66bceac088886 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 13 May 2024 13:08:39 +0800 Subject: [PATCH 12/22] Update Windows build command --- win/build.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/win/build.sh b/win/build.sh index 11e41bb1..227678a8 100644 --- a/win/build.sh +++ b/win/build.sh @@ -61,6 +61,9 @@ sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' src/Makefile.mk sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' lib/Makefile.mk sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' src/Makefile.mk +# print all options +cmake -LAH + cmake -G "MinGW Makefiles" \ -DUSE_NGHTTP2=ON \ -DENABLE_WEBSOCKETS=ON \ @@ -69,6 +72,7 @@ cmake -G "MinGW Makefiles" \ -DCURL_BROTLI=ON \ -DENABLE_IPV6=ON \ -DCURL_ENABLE_SSL=ON \ + -DCURL_USE_OPENSSL=ON \ mingw32-make clean From 6b2938bd25b26ebe61ba009584a910d53f8b3a67 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 13 May 2024 18:54:02 +0800 Subject: [PATCH 13/22] Update Windows build command --- win/build.sh | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/win/build.sh b/win/build.sh index 227678a8..1f784fda 100644 --- a/win/build.sh +++ b/win/build.sh @@ -52,11 +52,11 @@ cd curl patchfile=../../chrome/patches/curl-impersonate.patch patch -p1 < $patchfile -sed -i 's/-shared/-s -static -shared/g' lib/Makefile.mk -sed -i 's/-static/-s -static/g' src/Makefile.mk - -sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' lib/Makefile.mk -sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' src/Makefile.mk +# sed -i 's/-shared/-s -static -shared/g' lib/Makefile.mk +# sed -i 's/-static/-s -static/g' src/Makefile.mk +# +# sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' lib/Makefile.mk +# sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' src/Makefile.mk sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' lib/Makefile.mk sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' src/Makefile.mk @@ -64,23 +64,31 @@ sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' src/Makefile.mk # print all options cmake -LAH -cmake -G "MinGW Makefiles" \ +cmake -B build -G "MinGW Makefiles" \ + -DENABLE_IPV6=ON \ + -DENABLE_UNICODE=ON \ -DUSE_NGHTTP2=ON \ -DENABLE_WEBSOCKETS=ON \ - -DUSE_ECH=ON \ - -DCURL_ZSTD=ON \ -DCURL_BROTLI=ON \ + -DCULR_ZLIB=ON \ + -DCURL_ZSTD=ON \ -DENABLE_IPV6=ON \ -DCURL_ENABLE_SSL=ON \ -DCURL_USE_OPENSSL=ON \ + -DUSE_ECH=ON \ + -DBUILD_STATIC_CURL=ON \ + -DBUILD_STATIC_LIBS=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_FLAGS=-Wno-unused-variable \ mingw32-make clean mingw32-make -j CFLAGS="-Wno-unused-variable" CFG=-ssl-zlib-nghttp2-idn2-brotli-zstd-ipv6 mkdir -p ../dist -mv lib/libcurl* ../dist/ -mv src/*.exe ../dist/ +ls build +mv build/lib/libcurl* ../dist/ +mv build/*.exe ../dist/ cd .. -dist/curl -V +dist/curl.exe -V From 9218c44822930f7a19f9fa829f4920da429c0e38 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 13 May 2024 19:03:51 +0800 Subject: [PATCH 14/22] Update Windows build command --- win/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/win/build.sh b/win/build.sh index 1f784fda..1a13b7f6 100644 --- a/win/build.sh +++ b/win/build.sh @@ -75,6 +75,7 @@ cmake -B build -G "MinGW Makefiles" \ -DENABLE_IPV6=ON \ -DCURL_ENABLE_SSL=ON \ -DCURL_USE_OPENSSL=ON \ + -DHAVE_BORINGSSL=1 \ -DUSE_ECH=ON \ -DBUILD_STATIC_CURL=ON \ -DBUILD_STATIC_LIBS=ON \ From 8552f645e9fc9a82c90a3406144aa2f93a57d19d Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 13 May 2024 19:13:36 +0800 Subject: [PATCH 15/22] Update Windows build command --- chrome/patches/curl-impersonate.patch | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index c1933e14..e4bbe8f4 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -1,10 +1,10 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 656aa7c74..5702de3ec 100644 +index 656aa7c74..594e9574a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -598,6 +598,29 @@ if(CURL_ZSTD) - endif() - endif() +@@ -627,6 +627,29 @@ macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE) + cmake_pop_check_state() + endmacro() +option(USE_ECH "Enable ECH support" OFF) +if(USE_ECH) @@ -29,9 +29,9 @@ index 656aa7c74..5702de3ec 100644 + endif() +endif() + - # Check symbol in OpenSSL-like TLS backends. - macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE) - cmake_push_check_state() + # Ensure that the OpenSSL fork actually supports QUIC. + macro(openssl_check_quic) + if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD) diff --git a/Makefile.am b/Makefile.am index 658189e47..1ebc38b5a 100644 --- a/Makefile.am From 2b601eeea67a8149616b4b8ae8978f5d49ab8842 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Thu, 13 Jun 2024 20:19:14 +0800 Subject: [PATCH 16/22] Loosen key usage check in boringssl --- chrome/patches/boringssl.patch | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/chrome/patches/boringssl.patch b/chrome/patches/boringssl.patch index 85183aee..1c331220 100644 --- a/chrome/patches/boringssl.patch +++ b/chrome/patches/boringssl.patch @@ -232,6 +232,20 @@ index c9facb699..eab61611e 100644 X509_STORE *cert_store = nullptr; LHASH_OF(SSL_SESSION) *sessions = nullptr; // Most session-ids that will be cached, default is +diff --git a/ssl/ssl_cert.cc b/ssl/ssl_cert.cc +index aa46a8bb6..4e5bddd89 100644 +--- a/ssl/ssl_cert.cc ++++ b/ssl/ssl_cert.cc +@@ -602,8 +602,7 @@ bool ssl_cert_check_key_usage(const CBS *in, enum ssl_key_usage_t bit) { + } + + if (!CBS_asn1_bitstring_has_bit(&bit_string, bit)) { +- OPENSSL_PUT_ERROR(SSL, SSL_R_KEY_USAGE_BIT_INCORRECT); +- return false; ++ // curl-impersonate: bypass the key usage check + } + + return true; diff --git a/ssl/ssl_cipher.cc b/ssl/ssl_cipher.cc index fd8cef95d..3d2c8ff6d 100644 --- a/ssl/ssl_cipher.cc From ac9672e5d2d4a8d43e0c7690740391d52af8b170 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 17 Jun 2024 00:49:05 +0800 Subject: [PATCH 17/22] Try to fix windows build again --- .github/workflows/build-win.yaml | 1 + chrome/patches/curl-impersonate.patch | 4 ++-- configure.ac | 2 +- win/build.sh | 31 ++++++++++++++++----------- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-win.yaml b/.github/workflows/build-win.yaml index b92c6fe7..e602c817 100644 --- a/.github/workflows/build-win.yaml +++ b/.github/workflows/build-win.yaml @@ -61,6 +61,7 @@ jobs: mingw-w64-${{ matrix.env }}-nasm mingw-w64-${{ matrix.env }}-gcc mingw-w64-${{ matrix.env }}-go + mingw-w64-${{ matrix.env }}-libuv - name: Copy and patch shell: msys2 {0} diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index e4bbe8f4..0c63a537 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -146,7 +146,7 @@ index 54f92d931..ea5895e9b 100644 exit 1 diff --git a/export.sh b/export.sh new file mode 100755 -index 000000000..7bced6879 +index 000000000..db9ea5ea9 --- /dev/null +++ b/export.sh @@ -0,0 +1,9 @@ @@ -157,7 +157,7 @@ index 000000000..7bced6879 +# 1. https://github.com/curl/curl/pull/13244/files +# 2. https://everything.curl.dev/build/windows.html + -+git df curl-8_7_1 > chrome.patch ++git diff curl-8_7_1 > chrome.patch +mv chrome.patch ../curl-impersonate/chrome/patches/curl-impersonate.patch diff --git a/include/curl/curl.h b/include/curl/curl.h index b2377b789..89271eafa 100644 diff --git a/configure.ac b/configure.ac index e1b79b28..f55f66e5 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([curl-impersonate], [0.7.0], [lwt@lwthiker.com]) +AC_INIT([curl-impersonate], [0.7.0], [lwt@lwthiker.com, kong@yifei.me]) AC_CANONICAL_BUILD AC_CANONICAL_HOST diff --git a/win/build.sh b/win/build.sh index 1a13b7f6..8b66aaa1 100644 --- a/win/build.sh +++ b/win/build.sh @@ -2,7 +2,7 @@ set -ex -mkdir build/ +mkdir -p build/ cd build/ # Download and patch boringssl @@ -19,7 +19,7 @@ patch -p1 < $patchfile sed -i 's/-ggdb//g' CMakeLists.txt sed -i 's/-Werror//g' CMakeLists.txt -cmake -G "Ninja" -S . -B lib -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc.exe -DOPENSSL_NO_ASM=1 +cmake -G "Ninja" -S . -B lib -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc.exe ninja -C lib crypto ssl mv lib/crypto/libcrypto.a lib/libcrypto.a mv lib/ssl/libssl.a lib/libssl.a @@ -33,8 +33,7 @@ export BROTLI_LIBS='-lbrotlidec -lbrotlicommon' export NGHTTP2_PATH=nghttp2_stub export LIBIDN2_PATH=idn2_stub export SSL=1 -export OPENSSL_PATH=$PWD/boringssl -export OPENSSL_LIBPATH=$PWD/boringssl/lib +export SSL_PATH=$PWD/boringssl export OPENSSL_LIBS='-lssl -lcrypto' @@ -52,19 +51,21 @@ cd curl patchfile=../../chrome/patches/curl-impersonate.patch patch -p1 < $patchfile -# sed -i 's/-shared/-s -static -shared/g' lib/Makefile.mk -# sed -i 's/-static/-s -static/g' src/Makefile.mk +sed -i 's/-shared/-s -static -shared/g' lib/Makefile.mk +sed -i 's/-static/-s -static/g' src/Makefile.mk # # sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' lib/Makefile.mk # sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' src/Makefile.mk -sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' lib/Makefile.mk -sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' src/Makefile.mk +# sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' lib/Makefile.mk +# sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' src/Makefile.mk # print all options -cmake -LAH +# cmake -LAH cmake -B build -G "MinGW Makefiles" \ + -DSSL_PATH=$PWD/boringssl \ + -DOPENSSL_LIBS='-lssl -lcrypto' \ -DENABLE_IPV6=ON \ -DENABLE_UNICODE=ON \ -DUSE_NGHTTP2=ON \ @@ -73,23 +74,29 @@ cmake -B build -G "MinGW Makefiles" \ -DCULR_ZLIB=ON \ -DCURL_ZSTD=ON \ -DENABLE_IPV6=ON \ - -DCURL_ENABLE_SSL=ON \ - -DCURL_USE_OPENSSL=ON \ + -DENABLE_SSL=ON \ + -DUSE_OPENSSL=ON \ -DHAVE_BORINGSSL=1 \ -DUSE_ECH=ON \ + -DHAVE_ECH=ON \ -DBUILD_STATIC_CURL=ON \ -DBUILD_STATIC_LIBS=ON \ + -DBUILD_CURL_EXE=ON \ + -DCURL_STATIC_CRT=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_FLAGS=-Wno-unused-variable \ +cd build mingw32-make clean mingw32-make -j CFLAGS="-Wno-unused-variable" CFG=-ssl-zlib-nghttp2-idn2-brotli-zstd-ipv6 +cd .. + mkdir -p ../dist ls build mv build/lib/libcurl* ../dist/ -mv build/*.exe ../dist/ +mv build/src/*.exe ../dist/ cd .. dist/curl.exe -V From bcbda248665fe244ea13f2fe979c1a4daf553293 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 17 Jun 2024 00:59:16 +0800 Subject: [PATCH 18/22] Add missing no_asm --- win/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/build.sh b/win/build.sh index 8b66aaa1..c107e40a 100644 --- a/win/build.sh +++ b/win/build.sh @@ -19,7 +19,7 @@ patch -p1 < $patchfile sed -i 's/-ggdb//g' CMakeLists.txt sed -i 's/-Werror//g' CMakeLists.txt -cmake -G "Ninja" -S . -B lib -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc.exe +cmake -G "Ninja" -S . -B lib -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc.exe -DOPENSSL_NO_ASM=1 ninja -C lib crypto ssl mv lib/crypto/libcrypto.a lib/libcrypto.a mv lib/ssl/libssl.a lib/libssl.a From 8a7e47cc3ffc49ad7e0ff1c8e2f18dbead7667c3 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Mon, 17 Jun 2024 01:05:10 +0800 Subject: [PATCH 19/22] Remove CRT build optioin --- win/build.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/win/build.sh b/win/build.sh index c107e40a..81775d24 100644 --- a/win/build.sh +++ b/win/build.sh @@ -82,7 +82,6 @@ cmake -B build -G "MinGW Makefiles" \ -DBUILD_STATIC_CURL=ON \ -DBUILD_STATIC_LIBS=ON \ -DBUILD_CURL_EXE=ON \ - -DCURL_STATIC_CRT=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_FLAGS=-Wno-unused-variable \ From 07257da35a7bad2fe02ec34369e1c40e45eb75a3 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Tue, 18 Jun 2024 14:16:59 +0800 Subject: [PATCH 20/22] Another tyr --- win/build.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/win/build.sh b/win/build.sh index 81775d24..3d326a8e 100644 --- a/win/build.sh +++ b/win/build.sh @@ -34,6 +34,8 @@ export NGHTTP2_PATH=nghttp2_stub export LIBIDN2_PATH=idn2_stub export SSL=1 export SSL_PATH=$PWD/boringssl +export OPENSSL_PATH=$PWD/boringssl +export OPENSSL_LIBPATH=$PWD/boringssl/lib export OPENSSL_LIBS='-lssl -lcrypto' @@ -51,17 +53,17 @@ cd curl patchfile=../../chrome/patches/curl-impersonate.patch patch -p1 < $patchfile -sed -i 's/-shared/-s -static -shared/g' lib/Makefile.mk -sed -i 's/-static/-s -static/g' src/Makefile.mk +# sed -i 's/-shared/-s -static -shared/g' lib/Makefile.mk +# sed -i 's/-static/-s -static/g' src/Makefile.mk # # sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' lib/Makefile.mk # sed -i 's/-DUSE_NGHTTP2/-DUSE_NGHTTP2 -DNGHTTP2_STATICLIB/g' src/Makefile.mk -# sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' lib/Makefile.mk -# sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' src/Makefile.mk +sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' lib/Makefile.mk +sed -i 's/-lidn2/-lidn2 -lunistring -liconv/g' src/Makefile.mk # print all options -# cmake -LAH +cmake -LAH cmake -B build -G "MinGW Makefiles" \ -DSSL_PATH=$PWD/boringssl \ @@ -71,17 +73,16 @@ cmake -B build -G "MinGW Makefiles" \ -DUSE_NGHTTP2=ON \ -DENABLE_WEBSOCKETS=ON \ -DCURL_BROTLI=ON \ - -DCULR_ZLIB=ON \ + -DCURL_ZLIB=ON \ -DCURL_ZSTD=ON \ -DENABLE_IPV6=ON \ - -DENABLE_SSL=ON \ - -DUSE_OPENSSL=ON \ + -DCURL_ENABLE_SSL=ON \ + -DCURL_USE_OPENSSL=ON \ -DHAVE_BORINGSSL=1 \ -DUSE_ECH=ON \ -DHAVE_ECH=ON \ -DBUILD_STATIC_CURL=ON \ -DBUILD_STATIC_LIBS=ON \ - -DBUILD_CURL_EXE=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_FLAGS=-Wno-unused-variable \ From bee2b952a01a157ed822ec5d8383d8d3f6cf1ab5 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Tue, 18 Jun 2024 20:06:37 +0800 Subject: [PATCH 21/22] WIP: add option for key_usage check --- chrome/patches/boringssl.patch | 73 +++++++++++++++++---------- chrome/patches/curl-impersonate.patch | 17 ++++--- 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/chrome/patches/boringssl.patch b/chrome/patches/boringssl.patch index 1c331220..d3adf2de 100644 --- a/chrome/patches/boringssl.patch +++ b/chrome/patches/boringssl.patch @@ -1,33 +1,39 @@ diff --git a/export.sh b/export.sh new file mode 100755 -index 000000000..2e1f397aa +index 000000000..678d1ca41 --- /dev/null +++ b/export.sh @@ -0,0 +1,4 @@ +#!/bin/bash + -+git df d24a382 > boringssl.patch ++git diff d24a382 > boringssl.patch +mv boringssl.patch ../curl-impersonate/chrome/patches/boringssl.patch diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h -index e500dd76e..487945969 100644 +index e500dd76e..e75bca26b 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h -@@ -1560,6 +1560,9 @@ OPENSSL_EXPORT int SSL_CTX_set_strict_cipher_list(SSL_CTX *ctx, +@@ -1560,6 +1560,12 @@ OPENSSL_EXPORT int SSL_CTX_set_strict_cipher_list(SSL_CTX *ctx, // garbage inputs, unless an empty cipher list results. OPENSSL_EXPORT int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str); +// curl-impersonate: set the extension order by given string +OPENSSL_EXPORT int SSL_CTX_set_extension_order(SSL_CTX *ctx, char *order); ++ ++// curl-impersonate ++OPENSSL_EXPORT int SSL_CTX_set_key_usage_check_enabled(SSL_CTX *ctx, int enabled); + // SSL_set_strict_cipher_list configures the cipher list for |ssl|, evaluating // |str| as a cipher string and returning error if |str| contains anything // meaningless. It returns one on success and zero on failure. -@@ -4583,6 +4586,9 @@ OPENSSL_EXPORT void SSL_CTX_set_grease_enabled(SSL_CTX *ctx, int enabled); +@@ -4583,6 +4589,12 @@ OPENSSL_EXPORT void SSL_CTX_set_grease_enabled(SSL_CTX *ctx, int enabled); // permute extensions. For now, this is only implemented for the ClientHello. OPENSSL_EXPORT void SSL_CTX_set_permute_extensions(SSL_CTX *ctx, int enabled); +// curl-impersonate +OPENSSL_EXPORT int SSL_CTX_set_extension_order(SSL_CTX *ctx, char *order); ++ ++// curl-impersonate ++OPENSSL_EXPORT int SSL_CTX_set_key_usage_check_enabled(SSL_CTX *ctx, int enabled); + // SSL_set_permute_extensions configures whether sockets on |ssl| should // permute extensions. For now, this is only implemented for the ClientHello. @@ -126,7 +132,7 @@ index b13400097..8b457b873 100644 if (!kExtensions[i].add_clienthello(hs, &extensions, &extensions, type)) { OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION); diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc -index 971ebd0b1..0005c6d79 100644 +index 971ebd0b1..effe5c920 100644 --- a/ssl/handshake_client.cc +++ b/ssl/handshake_client.cc @@ -215,14 +215,6 @@ static void ssl_get_client_disabled(const SSL_HANDSHAKE *hs, @@ -182,8 +188,18 @@ index 971ebd0b1..0005c6d79 100644 !ssl_encrypt_client_hello(hs, MakeConstSpan(ech_enc, ech_enc_len)) || !ssl_add_client_hello(hs)) { return ssl_hs_error; +@@ -1402,7 +1374,8 @@ static enum ssl_hs_wait_t do_send_client_key_exchange(SSL_HANDSHAKE *hs) { + ssl_key_usage_t intended_use = (alg_k & SSL_kRSA) + ? key_usage_encipherment + : key_usage_digital_signature; +- if (!ssl_cert_check_key_usage(&leaf_cbs, intended_use)) { ++ if (hs->config->key_usage_check_enabled && ++ !ssl_cert_check_key_usage(&leaf_cbs, intended_use)) { + if (hs->config->enforce_rsa_key_usage || + EVP_PKEY_id(hs->peer_pubkey.get()) != EVP_PKEY_RSA) { + return ssl_hs_error; diff --git a/ssl/internal.h b/ssl/internal.h -index c9facb699..eab61611e 100644 +index c9facb699..a32e9b4ba 100644 --- a/ssl/internal.h +++ b/ssl/internal.h @@ -574,9 +574,14 @@ BSSL_NAMESPACE_BEGIN @@ -202,50 +218,45 @@ index c9facb699..eab61611e 100644 // Bits for |algorithm_prf| (handshake digest). #define SSL_HANDSHAKE_MAC_DEFAULT 0x1 -@@ -2161,6 +2166,9 @@ bssl::UniquePtr tls13_create_session_with_ticket(SSL *ssl, +@@ -2161,6 +2166,12 @@ bssl::UniquePtr tls13_create_session_with_ticket(SSL *ssl, // for |hs|, if applicable. It returns true on success and false on error. bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs); +// curl-impersonate +bool ssl_set_extension_order(SSL_HANDSHAKE *hs); ++ ++// curl-impersonate ++bool ssl_set_key_usage_check_enabled(SSL_HANDSHAKE *hs); + // ssl_setup_key_shares computes client key shares and saves them in |hs|. It // returns true on success and false on failure. If |override_group_id| is zero, // it offers the default groups, including GREASE. If it is non-zero, it offers -@@ -3033,6 +3041,9 @@ struct SSL_CONFIG { +@@ -3033,6 +3044,12 @@ struct SSL_CONFIG { // crypto UniquePtr cipher_list; + // curl-impersonate + char *extension_order = nullptr; ++ ++ // curl-impersonate ++ int key_usage_check_enabled = 1; + // This is used to hold the local certificate used (i.e. the server // certificate for a server or the client certificate for a client). UniquePtr cert; -@@ -3490,6 +3501,9 @@ struct ssl_ctx_st { +@@ -3490,6 +3507,12 @@ struct ssl_ctx_st { bssl::UniquePtr cipher_list; + // curl-impersonate + char *extension_order = nullptr; ++ ++ // curl-impersonate ++ int key_usage_check_enabled = 1; + X509_STORE *cert_store = nullptr; LHASH_OF(SSL_SESSION) *sessions = nullptr; // Most session-ids that will be cached, default is -diff --git a/ssl/ssl_cert.cc b/ssl/ssl_cert.cc -index aa46a8bb6..4e5bddd89 100644 ---- a/ssl/ssl_cert.cc -+++ b/ssl/ssl_cert.cc -@@ -602,8 +602,7 @@ bool ssl_cert_check_key_usage(const CBS *in, enum ssl_key_usage_t bit) { - } - - if (!CBS_asn1_bitstring_has_bit(&bit_string, bit)) { -- OPENSSL_PUT_ERROR(SSL, SSL_R_KEY_USAGE_BIT_INCORRECT); -- return false; -+ // curl-impersonate: bypass the key usage check - } - - return true; diff --git a/ssl/ssl_cipher.cc b/ssl/ssl_cipher.cc index fd8cef95d..3d2c8ff6d 100644 --- a/ssl/ssl_cipher.cc @@ -477,18 +488,19 @@ index fd8cef95d..3d2c8ff6d 100644 "Not all ciphers are included in the cipher order"); diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc -index 58b68e675..15eb823b3 100644 +index 58b68e675..455ee4dd0 100644 --- a/ssl/ssl_lib.cc +++ b/ssl/ssl_lib.cc -@@ -657,6 +657,7 @@ SSL *SSL_new(SSL_CTX *ctx) { +@@ -657,6 +657,8 @@ SSL *SSL_new(SSL_CTX *ctx) { ssl->config->retain_only_sha256_of_client_certs = ctx->retain_only_sha256_of_client_certs; ssl->config->permute_extensions = ctx->permute_extensions; -+ ssl->config->extension_order = ctx->extension_order; ++ ssl->config->extension_order = ctx->extension_order; // curl-impersonate ++ ssl->config->key_usage_check_enabled = ctx->key_usage_check_enabled; // curl-impersonate ssl->config->aes_hw_override = ctx->aes_hw_override; ssl->config->aes_hw_override_value = ctx->aes_hw_override_value; ssl->config->tls13_cipher_policy = ctx->tls13_cipher_policy; -@@ -3015,6 +3016,12 @@ void SSL_CTX_set_permute_extensions(SSL_CTX *ctx, int enabled) { +@@ -3015,6 +3017,17 @@ void SSL_CTX_set_permute_extensions(SSL_CTX *ctx, int enabled) { ctx->permute_extensions = !!enabled; } @@ -497,6 +509,11 @@ index 58b68e675..15eb823b3 100644 + ctx->extension_order = order; + return 0; +} ++ ++int SSL_CTX_set_key_usage_check_enabled(SSL_CTX *ctx, int enabled) { ++ ctx->key_usage_check_enabled = enabled; ++ return 0; ++} + void SSL_set_permute_extensions(SSL *ssl, int enabled) { if (!ssl->config) { diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index 0c63a537..70c6b6ea 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -146,7 +146,7 @@ index 54f92d931..ea5895e9b 100644 exit 1 diff --git a/export.sh b/export.sh new file mode 100755 -index 000000000..db9ea5ea9 +index 000000000..7bced6879 --- /dev/null +++ b/export.sh @@ -0,0 +1,9 @@ @@ -157,7 +157,7 @@ index 000000000..db9ea5ea9 +# 1. https://github.com/curl/curl/pull/13244/files +# 2. https://everything.curl.dev/build/windows.html + -+git diff curl-8_7_1 > chrome.patch ++git df curl-8_7_1 > chrome.patch +mv chrome.patch ../curl-impersonate/chrome/patches/curl-impersonate.patch diff --git a/include/curl/curl.h b/include/curl/curl.h index b2377b789..89271eafa 100644 @@ -2918,7 +2918,7 @@ index ce28f25bb..90e1c09d8 100644 #ifndef CURL_DISABLE_MIME diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c -index a3953f6c3..c854c08b4 100644 +index a3953f6c3..7db90d69c 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -79,9 +79,24 @@ @@ -3283,7 +3283,7 @@ index a3953f6c3..c854c08b4 100644 #ifdef USE_OPENSSL_SRP if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) { char * const ssl_username = ssl_config->primary.username; -@@ -3761,6 +4076,38 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3761,6 +4076,41 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, } #endif @@ -3312,6 +3312,9 @@ index a3953f6c3..c854c08b4 100644 + SSL_CTX_set_extension_order(backend->ctx, data->set.str[STRING_TLS_EXTENSION_ORDER]); + } + ++ // curl-impersonate: disable key usage check ++ SSL_CTX_set_key_usage_check_enabled(backend->ctx, 1); ++ + if(conn_config->cert_compression && + add_cert_compression(data, + backend->ctx, @@ -3322,7 +3325,7 @@ index a3953f6c3..c854c08b4 100644 /* OpenSSL always tries to verify the peer, this only says whether it should * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with -@@ -3816,6 +4163,24 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3816,6 +4166,24 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, SSL_set_app_data(backend->handle, cf); @@ -3347,7 +3350,7 @@ index a3953f6c3..c854c08b4 100644 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) if(conn_config->verifystatus) -@@ -3839,6 +4204,21 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3839,6 +4207,21 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, } #endif @@ -3369,7 +3372,7 @@ index a3953f6c3..c854c08b4 100644 SSL_set_app_data(backend->handle, cf); connssl->reused_session = FALSE; -@@ -4050,6 +4430,60 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, +@@ -4050,6 +4433,60 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, negotiated_group_name? negotiated_group_name : "[blank]", OBJ_nid2sn(psigtype_nid)); From 26f8fe955d04dbe4136c79bdcecb2005d0d1aaa8 Mon Sep 17 00:00:00 2001 From: Yifei Kong Date: Wed, 19 Jun 2024 14:01:12 +0800 Subject: [PATCH 22/22] Add tls_key_usage_no_check option --- chrome/patches/curl-impersonate.patch | 63 +++++++++++++++------------ 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/chrome/patches/curl-impersonate.patch b/chrome/patches/curl-impersonate.patch index 70c6b6ea..e56bffdc 100644 --- a/chrome/patches/curl-impersonate.patch +++ b/chrome/patches/curl-impersonate.patch @@ -160,7 +160,7 @@ index 000000000..7bced6879 +git df curl-8_7_1 > chrome.patch +mv chrome.patch ../curl-impersonate/chrome/patches/curl-impersonate.patch diff --git a/include/curl/curl.h b/include/curl/curl.h -index b2377b789..89271eafa 100644 +index b2377b789..c614266e5 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -632,6 +632,7 @@ typedef enum { @@ -171,7 +171,7 @@ index b2377b789..89271eafa 100644 CURL_LAST /* never use! */ } CURLcode; -@@ -2206,6 +2207,80 @@ typedef enum { +@@ -2206,6 +2207,79 @@ typedef enum { /* millisecond version */ CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT_MS, CURLOPTTYPE_LONG, 324), @@ -236,18 +236,17 @@ index b2377b789..89271eafa 100644 + */ + CURLOPT(CURLOPT_HTTP2_STREAMS, CURLOPTTYPE_STRINGPOINT, 1010), + -+ /* curl-impersonate: -+ * enable tls grease -+ */ ++ /* curl-impersonate: enable tls grease */ + CURLOPT(CURLOPT_TLS_GREASE, CURLOPTTYPE_LONG, 1011), + -+ /* curl-impersonate: -+ * set tls extension order -+ */ ++ /* curl-impersonate: set tls extension order */ + CURLOPT(CURLOPT_TLS_EXTENSION_ORDER, CURLOPTTYPE_STRINGPOINT, 1012), + + /* curl-impersonate: Set stream exclusiveness, 0 or 1 */ + CURLOPT(CURLOPT_STREAM_EXCLUSIVE, CURLOPTTYPE_LONG, 1013), ++ ++ /* curl-impersonate: enable tls key usage check, defaults: on */ ++ CURLOPT(CURLOPT_TLS_KEY_USAGE_NO_CHECK, CURLOPTTYPE_LONG, 1014), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; @@ -802,7 +801,7 @@ index dc4870608..f0b42fe8b 100644 /* diff --git a/lib/easyoptions.c b/lib/easyoptions.c -index 9c4438a10..7dc93ce27 100644 +index 9c4438a10..680fd7afe 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -86,6 +86,7 @@ struct curl_easyoption Curl_easyopts[] = { @@ -857,16 +856,17 @@ index 9c4438a10..7dc93ce27 100644 {"SUPPRESS_CONNECT_HEADERS", CURLOPT_SUPPRESS_CONNECT_HEADERS, CURLOT_LONG, 0}, {"TCP_FASTOPEN", CURLOPT_TCP_FASTOPEN, CURLOT_LONG, 0}, -@@ -342,6 +355,8 @@ struct curl_easyoption Curl_easyopts[] = { +@@ -342,6 +355,9 @@ 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}, -+ {"TLS_GREASE", CURLOPT_TLS_GREASE, CURLOT_LONG, 0}, + {"TLS_EXTENSION_ORDER", CURLOPT_TLS_EXTENSION_ORDER, CURLOT_STRING, 0}, ++ {"TLS_GREASE", CURLOPT_TLS_GREASE, CURLOT_LONG, 0}, ++ {"TLS_KEY_USAGE_NO_CHECK", CURLOPT_TLS_KEY_USAGE_NO_CHECK, CURLOT_LONG, 0}, {"TRAILERDATA", CURLOPT_TRAILERDATA, CURLOT_CBPTR, 0}, {"TRAILERFUNCTION", CURLOPT_TRAILERFUNCTION, CURLOT_FUNCTION, 0}, {"TRANSFERTEXT", CURLOPT_TRANSFERTEXT, CURLOT_LONG, 0}, -@@ -375,6 +390,6 @@ struct curl_easyoption Curl_easyopts[] = { +@@ -375,6 +391,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { @@ -2576,7 +2576,7 @@ index ed9cac796..6ca666e4a 100644 #ifdef USE_WINSOCK multi->wsa_event = WSACreateEvent(); diff --git a/lib/setopt.c b/lib/setopt.c -index 8a5a5d7c3..70197acc1 100644 +index 8a5a5d7c3..3a78d3ac8 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -51,6 +51,7 @@ @@ -2639,7 +2639,7 @@ index 8a5a5d7c3..70197acc1 100644 #endif case CURLOPT_IPRESOLVE: arg = va_arg(param, long); -@@ -2936,6 +2975,42 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) +@@ -2936,6 +2975,45 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_SSL_ENABLE_ALPN: data->set.ssl_enable_alpn = (0 != va_arg(param, long)); break; @@ -2659,6 +2659,9 @@ index 8a5a5d7c3..70197acc1 100644 + result = Curl_setstropt(&data->set.str[STRING_TLS_EXTENSION_ORDER], + va_arg(param, char *)); + break; ++ case CURLOPT_TLS_KEY_USAGE_NO_CHECK: ++ data->set.tls_key_usage_no_check = (0 != va_arg(param, long)) ? TRUE : FALSE; ++ break; +#ifdef USE_HTTP2 + case CURLOPT_HTTP2_PSEUDO_HEADERS_ORDER: + result = Curl_setstropt(&data->set.str[STRING_HTTP2_PSEUDO_HEADERS_ORDER], @@ -2682,7 +2685,7 @@ index 8a5a5d7c3..70197acc1 100644 #ifdef USE_UNIX_SOCKETS case CURLOPT_UNIX_SOCKET_PATH: data->set.abstract_unix_socket = FALSE; -@@ -2963,6 +3038,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) +@@ -2963,6 +3041,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; #else return CURLE_NOT_BUILT_IN; @@ -2697,7 +2700,7 @@ index 8a5a5d7c3..70197acc1 100644 #endif case CURLOPT_STREAM_DEPENDS: case CURLOPT_STREAM_DEPENDS_E: -@@ -3132,6 +3215,31 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) +@@ -3132,6 +3218,31 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.ws_raw_mode = raw; break; } @@ -2813,7 +2816,7 @@ index 224b9f3e2..db07bfa40 100644 if(waitpipe) diff --git a/lib/urldata.h b/lib/urldata.h -index ce28f25bb..90e1c09d8 100644 +index ce28f25bb..1abb66c38 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -53,6 +53,15 @@ @@ -2895,7 +2898,7 @@ index ce28f25bb..90e1c09d8 100644 /* -- end of null-terminated strings -- */ -@@ -1791,6 +1828,10 @@ struct UserDefined { +@@ -1791,6 +1828,11 @@ struct UserDefined { BIT(tcp_keepalive); /* use TCP keepalives */ BIT(tcp_fastopen); /* use TCP Fast Open */ BIT(ssl_enable_alpn);/* TLS ALPN extension? */ @@ -2903,10 +2906,11 @@ index ce28f25bb..90e1c09d8 100644 + BIT(ssl_enable_ticket); /* TLS session ticket extension */ + BIT(ssl_permute_extensions); /* TLS Permute extensions */ + BIT(tls_grease); /* TLS grease? */ ++ BIT(tls_key_usage_no_check); /* TLS key_usage_check? */ BIT(path_as_is); /* allow dotdots? */ BIT(pipewait); /* wait for multiplex status before starting a new connection */ -@@ -1811,6 +1852,10 @@ struct UserDefined { +@@ -1811,6 +1853,10 @@ struct UserDefined { #ifdef USE_WEBSOCKETS BIT(ws_raw_mode); #endif @@ -2918,7 +2922,7 @@ index ce28f25bb..90e1c09d8 100644 #ifndef CURL_DISABLE_MIME diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c -index a3953f6c3..7db90d69c 100644 +index a3953f6c3..bddf3edce 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -79,9 +79,24 @@ @@ -3283,7 +3287,7 @@ index a3953f6c3..7db90d69c 100644 #ifdef USE_OPENSSL_SRP if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) { char * const ssl_username = ssl_config->primary.username; -@@ -3761,6 +4076,41 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3761,6 +4076,44 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, } #endif @@ -3306,14 +3310,17 @@ index a3953f6c3..7db90d69c 100644 + SSL_CTX_set_permute_extensions(backend->ctx, 1); + } + -+ /* curl-impersonate: Set TLS extensions order. -+ */ ++ /* curl-impersonate: Set TLS extensions order. */ + if(data->set.str[STRING_TLS_EXTENSION_ORDER]) { + SSL_CTX_set_extension_order(backend->ctx, data->set.str[STRING_TLS_EXTENSION_ORDER]); + } + -+ // curl-impersonate: disable key usage check -+ SSL_CTX_set_key_usage_check_enabled(backend->ctx, 1); ++ // curl-impersonate: Set key usage check ++ if(data->set.tls_key_usage_no_check) { ++ SSL_CTX_set_key_usage_check_enabled(backend->ctx, 0); ++ }else{ ++ SSL_CTX_set_key_usage_check_enabled(backend->ctx, 1); ++ } + + if(conn_config->cert_compression && + add_cert_compression(data, @@ -3325,7 +3332,7 @@ index a3953f6c3..7db90d69c 100644 /* OpenSSL always tries to verify the peer, this only says whether it should * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with -@@ -3816,6 +4166,24 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3816,6 +4169,24 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, SSL_set_app_data(backend->handle, cf); @@ -3350,7 +3357,7 @@ index a3953f6c3..7db90d69c 100644 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) if(conn_config->verifystatus) -@@ -3839,6 +4207,21 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, +@@ -3839,6 +4210,21 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, } #endif @@ -3372,7 +3379,7 @@ index a3953f6c3..7db90d69c 100644 SSL_set_app_data(backend->handle, cf); connssl->reused_session = FALSE; -@@ -4050,6 +4433,60 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, +@@ -4050,6 +4436,60 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, negotiated_group_name? negotiated_group_name : "[blank]", OBJ_nid2sn(psigtype_nid));