From 2ae0fc7299825cc561197d3f23c90e52ae8db58b Mon Sep 17 00:00:00 2001 From: dartraiden Date: Sun, 10 Dec 2023 18:22:53 +0300 Subject: libcurl: update to 8.5.0 --- libs/libcurl/docs/CHANGES | 12691 ++++++++++++++------------- libs/libcurl/docs/THANKS | 42 + libs/libcurl/include/curl/curl.h | 26 +- libs/libcurl/include/curl/curlver.h | 8 +- libs/libcurl/include/curl/system.h | 37 +- libs/libcurl/src/CMakeLists.txt | 21 +- libs/libcurl/src/Makefile.am | 2 +- libs/libcurl/src/Makefile.in | 2 +- libs/libcurl/src/altsvc.c | 10 +- libs/libcurl/src/arpa_telnet.h | 9 +- libs/libcurl/src/asyn-ares.c | 149 +- libs/libcurl/src/asyn-thread.c | 50 +- libs/libcurl/src/base64.c | 1 + libs/libcurl/src/c-hyper.c | 106 +- libs/libcurl/src/cf-h1-proxy.c | 55 +- libs/libcurl/src/cf-h2-proxy.c | 67 +- libs/libcurl/src/cf-haproxy.c | 20 +- libs/libcurl/src/cf-https-connect.c | 54 +- libs/libcurl/src/cf-socket.c | 93 +- libs/libcurl/src/cfilters.c | 204 +- libs/libcurl/src/cfilters.h | 113 +- libs/libcurl/src/config-amigaos.h | 1 - libs/libcurl/src/config-dos.h | 1 - libs/libcurl/src/config-os400.h | 6 - libs/libcurl/src/config-plan9.h | 2 - libs/libcurl/src/config-riscos.h | 6 - libs/libcurl/src/config-win32.h | 116 +- libs/libcurl/src/config-win32ce.h | 5 +- libs/libcurl/src/conncache.c | 25 +- libs/libcurl/src/connect.c | 93 +- libs/libcurl/src/content_encoding.c | 281 +- libs/libcurl/src/content_encoding.h | 9 +- libs/libcurl/src/cookie.c | 32 +- libs/libcurl/src/curl_config.h.cmake | 27 +- libs/libcurl/src/curl_config.h.in | 12 +- libs/libcurl/src/curl_hmac.h | 3 +- libs/libcurl/src/curl_memory.h | 6 +- libs/libcurl/src/curl_multibyte.c | 4 +- libs/libcurl/src/curl_multibyte.h | 8 +- libs/libcurl/src/curl_ntlm_core.c | 9 + libs/libcurl/src/curl_ntlm_wb.c | 14 +- libs/libcurl/src/curl_path.h | 2 +- libs/libcurl/src/curl_rtmp.c | 2 +- libs/libcurl/src/curl_sasl.c | 3 + libs/libcurl/src/curl_setup.h | 151 +- libs/libcurl/src/curl_setup_once.h | 8 +- libs/libcurl/src/curl_sspi.h | 16 + libs/libcurl/src/curl_trc.c | 26 +- libs/libcurl/src/curl_trc.h | 108 +- libs/libcurl/src/doh.c | 43 +- libs/libcurl/src/dynbuf.c | 6 +- libs/libcurl/src/dynhds.c | 29 + libs/libcurl/src/dynhds.h | 9 + libs/libcurl/src/easy.c | 84 +- libs/libcurl/src/easy_lock.h | 9 + libs/libcurl/src/file.c | 8 +- libs/libcurl/src/fopen.c | 77 +- libs/libcurl/src/formdata.c | 8 +- libs/libcurl/src/ftp.c | 6 +- libs/libcurl/src/ftplistparser.c | 3 - libs/libcurl/src/functypes.h | 2 +- libs/libcurl/src/getenv.c | 5 +- libs/libcurl/src/hostasyn.c | 11 +- libs/libcurl/src/hostip.c | 115 +- libs/libcurl/src/hostip.h | 4 + libs/libcurl/src/hostip6.c | 7 +- libs/libcurl/src/hsts.c | 28 +- libs/libcurl/src/http.c | 236 +- libs/libcurl/src/http.h | 6 +- libs/libcurl/src/http2.c | 134 +- libs/libcurl/src/http_aws_sigv4.c | 11 +- libs/libcurl/src/http_chunks.c | 83 +- libs/libcurl/src/http_chunks.h | 4 +- libs/libcurl/src/http_proxy.c | 2 +- libs/libcurl/src/idn.c | 2 +- libs/libcurl/src/imap.c | 4 +- libs/libcurl/src/ldap.c | 20 +- libs/libcurl/src/libcurl.plist | 6 +- libs/libcurl/src/md4.c | 5 +- libs/libcurl/src/memdebug.c | 2 +- libs/libcurl/src/memdebug.h | 4 +- libs/libcurl/src/mime.c | 5 +- libs/libcurl/src/mprintf.c | 7 +- libs/libcurl/src/mqtt.c | 9 - libs/libcurl/src/multi.c | 295 +- libs/libcurl/src/multihandle.h | 15 +- libs/libcurl/src/netrc.c | 2 +- libs/libcurl/src/openldap.c | 54 +- libs/libcurl/src/pop3.c | 2 +- libs/libcurl/src/progress.c | 8 +- libs/libcurl/src/rand.c | 28 +- libs/libcurl/src/rand.h | 2 +- libs/libcurl/src/rename.c | 2 +- libs/libcurl/src/rtsp.c | 359 +- libs/libcurl/src/rtsp.h | 9 + libs/libcurl/src/select.c | 2 +- libs/libcurl/src/sendf.c | 326 +- libs/libcurl/src/sendf.h | 127 +- libs/libcurl/src/setopt.c | 220 +- libs/libcurl/src/setup-win32.h | 13 +- libs/libcurl/src/share.h | 10 +- libs/libcurl/src/smb.c | 9 +- libs/libcurl/src/smtp.c | 2 +- libs/libcurl/src/socketpair.c | 6 +- libs/libcurl/src/socketpair.h | 17 + libs/libcurl/src/socks.c | 48 +- libs/libcurl/src/strdup.c | 28 +- libs/libcurl/src/strdup.h | 3 +- libs/libcurl/src/strerror.c | 20 +- libs/libcurl/src/strerror.h | 2 +- libs/libcurl/src/system_win32.c | 4 +- libs/libcurl/src/system_win32.h | 6 +- libs/libcurl/src/tftp.c | 14 +- libs/libcurl/src/tftp.h | 3 + libs/libcurl/src/timediff.c | 2 +- libs/libcurl/src/timeval.c | 7 +- libs/libcurl/src/transfer.c | 277 +- libs/libcurl/src/url.c | 1187 ++- libs/libcurl/src/url.h | 9 +- libs/libcurl/src/urlapi.c | 45 +- libs/libcurl/src/urldata.h | 86 +- libs/libcurl/src/vauth/digest.c | 1 - libs/libcurl/src/version.c | 12 +- libs/libcurl/src/version_win32.c | 4 +- libs/libcurl/src/version_win32.h | 4 +- libs/libcurl/src/vquic/curl_msh3.c | 35 +- libs/libcurl/src/vquic/curl_ngtcp2.c | 360 +- libs/libcurl/src/vquic/curl_quiche.c | 249 +- libs/libcurl/src/vquic/vquic.c | 27 +- libs/libcurl/src/vquic/vquic_int.h | 6 + libs/libcurl/src/vssh/libssh.c | 46 +- libs/libcurl/src/vssh/libssh2.c | 262 +- libs/libcurl/src/vssh/ssh.h | 1 + libs/libcurl/src/vssh/wolfssh.c | 3 - libs/libcurl/src/vtls/bearssl.c | 54 +- libs/libcurl/src/vtls/gtls.c | 121 +- libs/libcurl/src/vtls/gtls.h | 6 +- libs/libcurl/src/vtls/keylog.c | 9 +- libs/libcurl/src/vtls/mbedtls.c | 10 +- libs/libcurl/src/vtls/mbedtls_threadlock.c | 2 +- libs/libcurl/src/vtls/openssl.c | 526 +- libs/libcurl/src/vtls/openssl.h | 21 +- libs/libcurl/src/vtls/rustls.c | 117 +- libs/libcurl/src/vtls/schannel.c | 174 +- libs/libcurl/src/vtls/schannel_int.h | 17 + libs/libcurl/src/vtls/schannel_verify.c | 64 +- libs/libcurl/src/vtls/sectransp.c | 40 +- libs/libcurl/src/vtls/vtls.c | 419 +- libs/libcurl/src/vtls/vtls.h | 80 +- libs/libcurl/src/vtls/vtls_int.h | 40 +- libs/libcurl/src/vtls/wolfssl.c | 37 +- libs/libcurl/src/vtls/x509asn1.c | 10 +- libs/libcurl/src/warnless.c | 12 +- libs/libcurl/src/warnless.h | 21 +- libs/libcurl/src/ws.c | 8 +- 155 files changed, 11752 insertions(+), 10025 deletions(-) (limited to 'libs/libcurl') diff --git a/libs/libcurl/docs/CHANGES b/libs/libcurl/docs/CHANGES index 8d56bf8e28..85fa4522fb 100644 --- a/libs/libcurl/docs/CHANGES +++ b/libs/libcurl/docs/CHANGES @@ -6,9540 +6,10369 @@ Changelog -Version 8.4.0 (11 Oct 2023) +Version 8.5.0 (6 Dec 2023) -Daniel Stenberg (11 Oct 2023) +Daniel Stenberg (6 Dec 2023) - RELEASE-NOTES: synced -- THANKS: add contributors from 8.4.0 - -Jay Satiro (11 Oct 2023) + The curl 8.5.0 release. -- socks: return error if hostname too long for remote resolve +Dan Fandrich (5 Dec 2023) - Prior to this change the state machine attempted to change the remote - resolve to a local resolve if the hostname was longer than 255 - characters. Unfortunately that did not work as intended and caused a - security issue. +- github/labeler: switch from the beta to labeler v5 - Bug: https://curl.se/docs/CVE-2023-38545.html + Some keys were renamed and the dot option was made default. -Stefan Eissing (10 Oct 2023) + Closes #12458 -- CI: remove slowed-network tests +Daniel Stenberg (5 Dec 2023) - - remove these tests as they are currently not reliable in our CI - setups. +- DEPRECATE: remove NTLM_WB in June 2024 - curl handles the test cases, but CI sometimes fails on these due to - additional conditions. Rather than mix them in, an additional CI job - will be added in the future that is specific to them. + Ref: https://curl.se/mail/lib-2023-12/0010.html - Closes https://github.com/curl/curl/pull/12075 + Closes #12451 -Jay Satiro (10 Oct 2023) +Jacob Hoffman-Andrews (4 Dec 2023) -- libcurl-env-dbg.3: move debug variables from libcurl-env.3 +- rustls: implement connect_blocking - - Move documentation of libcurl environment variables used only in debug - builds from libcurl-env into a separate document libcurl-env-dbg. + Closes #11647 - - Document more debug environment variables. +Daniel Stenberg (4 Dec 2023) - Previously undocumented or missing a description: +- examples/rtsp-options.c: add - CURL_ALTSVC_HTTP, CURL_DBG_SOCK_WBLOCK, CURL_DBG_SOCK_WPARTIAL, - CURL_DBG_QUIC_WBLOCK, CURL_DEBUG, CURL_DEBUG_SIZE, CURL_GETHOSTNAME, - CURL_HSTS_HTTP, CURL_FORCETIME, CURL_SMALLREQSEND, CURL_SMALLSENDS, - CURL_TIME. + Just a bare bones RTSP example using CURLOPT_RTSP_SESSION_ID and + CURLOPT_RTSP_REQUEST set to CURL_RTSPREQ_OPTIONS. - Closes https://github.com/curl/curl/pull/11811 + Closes #12452 -Dan Fandrich (9 Oct 2023) +Stefan Eissing (4 Dec 2023) -- test670: increase the test timeout +- ngtcp2: ignore errors on unknown streams - This should make it more immune to loaded servers. + - expecially in is_alive checks on connections, we might + see incoming packets on streams already forgotten and closed, + leading to errors reported by nghttp3. Ignore those. - Ref: #11328 + Closes #12449 -Stefan Eissing (9 Oct 2023) +Daniel Stenberg (4 Dec 2023) -- MQTT: improve receive of ACKs +- docs: make all examples in all libcurl man pages compile - - add `mq->recvbuf` to provide buffering of incomplete - ACK responses - - continue ACK reading until sufficient bytes available - - fixes test failures on low network receives + Closes #12448 - Closes #12071 +- checksrc.pl: support #line instructions -Viktor Szakats (9 Oct 2023) + makes it identify the correct source file and line -- quic: fix BoringSSL build +- GHA/man-examples: verify libcurl man page examples - Add guard around `SSL_CTX_set_ciphersuites()` use. +- verify-examples.pl: verify that all man page examples compile clean - Bug: https://github.com/curl/curl/pull/12065#issuecomment-1752171885 +- RELEASE-NOTES: synced - Follow-up to aa9a6a177017e4b74d33cdf85a3594900f4a7f81 +Graham Campbell (2 Dec 2023) - Co-authored-by: Jay Satiro - Reviewed-by: Daniel Stenberg - Closes #12067 +- http3: bump ngtcp2 and nghttp3 versions -Stefan Eissing (9 Oct 2023) + nghttp3 v1.1.0 + ngtcp2 v1.1.0 -- test1540: improve reliability + In docs and CI - - print that bytes have been received on pausing, but not how many + Closes #12446 - Closes #12069 +- CI/quiche: use `3.1.4+quic` consistently in CI workflows -- test2302: improve reliability + Closes #12447 - - make result print collected write data, unless - change in meta flags is detected - - will show same result even when data arrives via - several writecb invocations +Viktor Szakats (2 Dec 2023) - Closes #12068 +- test1545: disable deprecation warnings -Daniel Stenberg (9 Oct 2023) + Fixes: + https://ci.appveyor.com/project/curlorg/curl/builds/48631551/job/bhx74e0i66yr + p6pk#L1205 -- curl_easy_pause: set "in callback" true on exit if true + Same with details: + https://ci.appveyor.com/project/curlorg/curl/builds/48662893/job/ol8a78q9gmil + b6wt#L1263 + ``` + tests/libtest/lib1545.c:38:3: error: 'curl_formadd' is deprecated: since 7.56 + .0. Use curl_mime_init() [-Werror=deprecated-declarations] + 38 | curl_formadd(&m_formpost, &lastptr, CURLFORM_COPYNAME, "file", + | ^~~~~~~~~~~~ + [...] + ``` - Because it might have called another callback in the mean time that then - set the bit FALSE on exit. + Follow-up to 07a3cd83e0456ca17dfd8c3104af7cf45b7a1ff5 #12421 - Reported-by: Jay Satiro - Fixes #12059 - Closes #12061 + Fixes #12445 + Closes #12444 -Viktor Szakats (8 Oct 2023) +Daniel Stenberg (2 Dec 2023) -- h3: add support for ngtcp2 with AWS-LC builds +- INSTALL: update list of ports and CPU archs - ``` - curl 8.4.0-DEV (x86_64-apple-darwin) libcurl/8.4.0-DEV (SecureTransport) AWS- - LC/1.15.0 nghttp2/1.56.0 ngtcp2/0.19.1 nghttp3/0.15.0 - Release-Date: [unreleased] - Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps - mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp ws wss - Features: alt-svc AsynchDNS HSTS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefile Multi - SSL NTLM SSL threadsafe UnixSockets - ``` +- symbols-in-versions: the CLOSEPOLICY options are deprecated - Also delete an obsolete GnuTLS TODO and update the header comment in - `FindNGTCP2.cmake`. + The were used with the CURLOPT_CLOSEPOLICY option, which *never* worked. - Reviewed-by: Daniel Stenberg - Closes #12066 +z2_ (1 Dec 2023) -- build: do not publish `HAVE_BORINGSSL`, `HAVE_AWSLC` macros +- build: fix builds that disable protocols but not digest auth - Syncing this up with CMake. + - Build base64 functions if digest auth is not disabled. - Source code uses the built-in `OPENSSL_IS_AWSLC` and - `OPENSSL_IS_BORINSSL` macros to detect BoringSSL and AWS-LC. No help is - necessary from the build tools. + Prior to this change if some protocols were disabled but not digest auth + then a build error would occur due to missing base64 functions. - The one use of `HAVE_BORINGSSL` in the source turned out to be no longer - necessary for warning-free BoringSSL + Schannel builds. Ref: #1610 #2634 + Fixes https://github.com/curl/curl/issues/12440 + Closes https://github.com/curl/curl/pull/12442 - autotools detects this anyway for display purposes. - CMake detects this to decide whether to use the BoringSSL-specific - crypto lib with ngtcp2. It detects AWS-LC, but doesn't use the detection - result just yet (planned in #12066). +Michał Antoniak (1 Dec 2023) - Ref: #11964 +- connect: reduce number of transportation providers - Reviewed-by: Daniel Stenberg - Reviewed-by: Jay Satiro - Closes #12065 + Use only the ones necessary - the ones that are built-in. Saves a few + bytes in the resulting code. -Marc Hoersken (8 Oct 2023) + Closes #12438 -- CI: move distcheck job from Azure Pipelines to GitHub Actions +David Benjamin (1 Dec 2023) - This will allow for more trigger excludes within Azure Pipelines. +- vtls: consistently use typedef names for OpenSSL structs - Also fixes seemingly broken check with scripts/installcheck.sh. - Ref: 190374c74ec4e5247d9066544c86e8d095e1d7b5 + The foo_st names don't appear in OpenSSL public API documentation. The + FOO typedefs are more common. This header was already referencing + SSL_CTX via . There is a comment about avoiding + , but OpenSSL actually declares all the typedefs in + , which is already included by (and + every other OpenSSL header), so just use that. Though I've included it + just to be explicit. - Assisted-by: Philip Heiduck - Closes #9532 + (I'm also fairly sure including already triggers the + Schannel conflicts anyway. The comment was probably just out of date.) -Daniel Stenberg (8 Oct 2023) + Closes #12439 -- url: fall back to http/https proxy env-variable if ws/wss not set +Lau (1 Dec 2023) - Reported-by: Craig Andrews - Fixes #12031 - Closes #12058 +- libcurl-security.3: fix typo -Stefan Eissing (8 Oct 2023) + Fixed minimal typo. -- cf-socket: simulate slow/blocked receives in debug + Closes #12437 - add 2 env variables for non-UDP sockets: - 1. CURL_DBG_SOCK_RBLOCK: percentage of receive calls that randomly - should return EAGAIN - 2. CURL_DBG_SOCK_RMAX: max amount of bytes read from socket +Stefan Eissing (1 Dec 2023) - Closes #12035 +- ngtcp2: fix races in stream handling -- http2: refused stream handling for retry + - fix cases where ngtcp2 invokes callbacks on streams that + nghttp3 has already forgotten. Ignore the NGHTTP3_ERR_STREAM_NOT_FOUND + in these cases as it is normal behaviour. - - answer HTTP/2 streams refused via a GOAWAY from the server to - respond with CURLE_RECV_ERROR in order to trigger a retry - on another connection + Closes #12435 - Reported-by: black-desk on github - Ref #11859 - Closes #12054 +Emanuele Torre (1 Dec 2023) -Jay Satiro (8 Oct 2023) +- tool_writeout_json: fix JSON encoding of non-ascii bytes -- CURLOPT_DEBUGFUNCTION.3: warn about internal handles + char variables if unspecified can be either signed or unsigned depending + on the platform according to the C standard; in most platforms, they are + signed. - - Warn that the user's debug callback may be called with the handle - parameter set to an internal handle. + This meant that the *i<32 waas always true for bytes with the top bit + set. So they were always getting encoded as \uXXXX, and then since they + were also signed negative, they were getting extended with 1s causing + '\xe2' to be expanded to \uffffffe2, for example: - Without this warning the user may assume that the only handles their - debug callback receives are the easy handles on which they set - CURLOPT_DEBUGFUNCTION. + $ curl --variable 'v=“' --expand-write-out '{{v:json}}\n' file:///dev/nul + l + \uffffffe2\uffffff80\uffffff9c - This is a follow-up to f8cee8cc which changed DoH handles to inherit - the debug callback function set in the user's easy handle. As a result - those handles are now passed to the user's debug callback function. + I fixed this bug by making the code use explicitly unsigned char* + variables instead of char* variables. - Closes https://github.com/curl/curl/pull/12034 + Test 268 verifies -- url: fix typo + Reported-by: iconoclasthero + Closes #12434 -Daniel Stenberg (8 Oct 2023) +Stefan Eissing (1 Dec 2023) -- test458: verify --expand-output, expanding a file name accepting option +- cf-socket: TCP trace output local address used in connect - Verifies the fix in #12055 (commit f2c8086ff15e6e995e1) + Closes #12427 -- tool_getparam: accept variable expansion on file names too +Jay Satiro (1 Dec 2023) - Reported-by: PBudmark on github - Fixes #12048 - Closes #12055 +- CURLINFO_PRETRANSFER_TIME_T.3: fix time explanation -- RELEASE-NOTES: synced + - Change CURLINFO_PRETRANSFER_TIME_T explanation to say that it + includes protocol-specific instructions that trigger a transfer. -- multi: do CURLM_CALL_MULTI_PERFORM at two more places + Prior to this change it explicitly said that it did not include those + instructions in the time, but that is incorrect. - ... when it does a state transition but there is no particular socket or - timer activity. This was made apparent when commit b5bb84c removed a - superfluous timer expiry. + The change is a copy of the fixed explanation already in + CURLINFO_PRETRANSFER_TIME, fixed by ec8dcd7b. - Reported-by: Dan Fandrich. - Fixes #12033 - Closes #12056 + Reported-by: eeverettrbx@users.noreply.github.com -Viktor Szakats (7 Oct 2023) + Fixes https://github.com/curl/curl/issues/12431 + Closes https://github.com/curl/curl/pull/12432 -- GHA/linux: mbedtls 3.5.0 + minor dep bumps +Daniel Stenberg (30 Nov 2023) - Closes #12057 +- multi: during ratelimit multi_getsock should return no sockets -Dan Fandrich (7 Oct 2023) + ... as there is nothing to wait for then, it just waits. Otherwise, this + causes much more CPU work and updates than necessary during ratelimit + periods. -- CI: bump OpenLDAP package version on FreeBSD + Ref: https://curl.se/mail/lib-2023-11/0056.html + Closes #12430 - The old one is no longer available. +Dmitry Karpov (30 Nov 2023) -Marc Hoersken (7 Oct 2023) +- transfer: abort pause send when connection is marked for closing -- docs/libcurl/opts/Makefile.inc: add missing manpage files + This handles cases of some bi-directional "upgrade" scenarios + (i.e. WebSockets) where sending is paused until some "upgrade" handshake + is completed, but server rejects the handshake and closes the + connection. - Detected with #9532 + Closes #12428 -Dan Fandrich (7 Oct 2023) +Daniel Stenberg (28 Nov 2023) -- tests: fix a race condition in ftp server disconnect +- RELEASE-NOTES: synced - If a client disconnected and reconnected quickly, before the ftp server - had a chance to respond, the protocol message/ack (ping/pong) sequence - got out of sync, causing messages sent to the old client to be delivered - to the new. A disconnect must now be acknowledged and intermediate - requests thrown out until it is, which ensures that such synchronization - problems can't occur. This problem could affect ftp, pop3, imap and smtp - tests. +- openssl: when a session-ID is reused, skip OCSP stapling - Fixes #12002 - Closes #12049 + Fixes #12399 + Reported-by: Alexey Larikov + Closes #12418 -Viktor Szakats (7 Oct 2023) +- test1545: test doing curl_formadd twice with missing file -- appveyor: bump mingw-w64 job to gcc 13 (was: 8) + Reproduces #12410 + Verifies the fix + Closes #12421 - This sets gcc 6, 7, 9, 13 in our test mix (was: 6, 7, 8, 9). - Adding a modern gcc version to the tests. +- Curl_http_body: cleanup properly when Curl_getformdata errors - (The gcc 8 job used to take around 50 minutes. The new image with gcc 13 - finished in 32, 35, 34 minutes in the 3 test runs so far.) + Reported-by: yushicheng7788 on github + Based-on-work-by: yushicheng7788 on github + Fixes #12410 + Closes #12421 - It also adds a modern CMake version and OS env to our mingw-w64 builds. +- test1477: verify that libcurl-errors.3 and public headers are synced - Closes #12051 + The script errorcodes.pl extracts all error codes from all headers and + checks that they are all documented, then checks that all documented + error codes are also specified in a header file. -David Benjamin (6 Oct 2023) + Closes #12424 -- openssl: use X509_ALGOR_get0 instead of reaching into X509_ALGOR +- libcurl-errors.3: sync with current public headers - While the struct is still public in OpenSSL, there is a (somewhat - inconvenient) accessor. Use it to remain compatible if it becomes opaque - in the future. + Closes #12424 - Closes #12038 +Stefan Eissing (28 Nov 2023) -Daniel Stenberg (6 Oct 2023) +- test459: fix for parallel runs -- curl_easy_pause.3: mention it works within callbacks + - change warniing message to work better with varying filename + length. + - adapt test output check to new formatting - Reported-by: Maxim Dzhura - Bug: https://curl.se/mail/lib-2023-10/0010.html - Closes #12046 + Follow-up to 97ccc4479f77ba3191c6 + Closes #12423 -- curl_easy_pause.3: mention h2/h3 buffering +Daniel Stenberg (27 Nov 2023) - Asked-by: Maxim Dzhura - Ref: https://curl.se/mail/lib-2023-10/0011.html +- tool_cb_prg: make the carriage return fit for wide progress bars - Closes #12045 + When the progress bar was made max width (256 columns), the fly() + function attempted to generate its output buffer too long so that the + trailing carriage return would not fit and then the output would show + wrongly. The fly function is called when the expected total transfer is + unknown, which could be one or more progress calls before the actual + progress meter get shown when the expected transfer size is provided. -Viktor Szakats (6 Oct 2023) + This new take also replaces the msnprintf() call with a much simpler + memset() for speed. -- cmake: re-add missed C89 headers for specific detections + Reported-by: Tim Hill + Fixes #12407 + Closes #12415 - We removed C89 `setjmp.h` and `signal.h` detections and excluded them - from the global header list we use when detecting functions [1]. Then - missed to re-add these headers to the specific functions which need - them to be detected [2]. Fix this omission in this patch. +- tool_parsecfg: make warning output propose double-quoting - [1] Follow-up to 3795fcde995d96db641ddbcc8a04f9f0f03bef9f #11951 - [2] Follow-up to 96c29900bcec32dd6bc8e9857c8871ff4b8b8ed9 #11940 + When the config file parser detects a word that *probably* should be + quoted, mention double-quotes as a possible remedy. - Closes #12043 + Test 459 verifies. -Daniel Stenberg (6 Oct 2023) + Proposed-by: Jiehong on github + Fixes #12409 + Closes #12412 -- multi: set CURLM_CALL_MULTI_PERFORM after switch to DOING_MORE +Jay Satiro (26 Nov 2023) - Since there is nothing to wait for there. Avoids the test 1233 hang - reported in #12033. +- curl.rc: switch out the copyright symbol for plain ASCII - Reported-by: Dan Fandrich - Closes #12042 + .. like we already do for libcurl.rc. -Dan Fandrich (5 Oct 2023) + libcurl.rc copyright symbol used to cause a "non-ascii 8-bit codepoint" + warning so it was switched to ascii. -- test1903: actually verify the cookies after the test + Ref: https://github.com/curl/curl/commit/1ca62bb5#commitcomment-133474972 - The test otherwise could do just about anything (except leak memory in - debug mode) and its bad behaviour wouldn't be detected. Now, check the - resulting cookie file to ensure the cookies are still there. + Suggested-by: Robert Southee - Closes #12041 + Closes https://github.com/curl/curl/pull/12403 -- test: add missing s +Daniel Stenberg (26 Nov 2023) - The tests will otherwise fail if curl has them disabled. +- conncache: use the closure handle when disconnecting surplus connections -- test1906: set a lower timeout since it's hit on Windows + Use the closure handle for disconnecting connection cache entries so + that anything that happens during the disconnect is not stored and + associated with the 'data' handle which already just finished a transfer + and it is important that details from the unrelated disconnect does not + taint meta-data in the data handle. - msys2 builds actually hit the connect timeout in normal operation, so - lower the timeout from 5 minutes to 5 seconds to reduce test time. + Like storing the response code. - Ref: #11328 - Closes #12036 + This also adjust test 1506. Unfortunately it also removes a key part of + the test that verifies that a connection is closed since when this + output vanishes (because the closure handle is used), we don't know + exactly that the connection actually gets closed in this test... -Daniel Stenberg (5 Oct 2023) + Reported-by: ohyeaah on github + Fixes #12367 + Closes #12405 - RELEASE-NOTES: synced -Jay Satiro (5 Oct 2023) +Stefan Eissing (24 Nov 2023) -- idn: fix WinIDN null ptr deref on bad host +- quic: make eyeballers connect retries stop at weird replies - - Return CURLE_URL_MALFORMAT if IDN hostname cannot be converted from - UTF-8 to UTF-16. + - when a connect immediately goes into DRAINING state, do + not attempt retries in the QUIC connection filter. Instead, + return CURLE_WEIRD_SERVER_REPLY + - When eyeballing, interpret CURLE_WEIRD_SERVER_REPLY as an + inconclusive answer. When all addresses have been attempted, + rewind the address list once on an inconclusive answer. + - refs #11832 where connects were retried indefinitely until + the overall timeout fired - Prior to this change a failed conversion erroneously returned CURLE_OK - which meant 'decoded' pointer (what would normally point to the - punycode) would not be written to, remain NULL and be dereferenced - causing an access violation. + Closes #12400 - Closes https://github.com/curl/curl/pull/11983 +Daniel Stenberg (24 Nov 2023) -Dan Fandrich (4 Oct 2023) +- CI: verify libcurl function SYNPOSIS sections -- tests: close the shell used to start sshd + With the .github/scripits/verify-synopsis.pl script - This shell isn't needed once sshd starts, so use "exec" so it doesn't - stick around. + Closes #12402 - Closes #12032 +- docs/libcurl: SYNSOPSIS cleanup -Daniel Stenberg (4 Oct 2023) + - use the correct include file + - make sure they are declared as in the header file + - fix minor nroff syntax mistakes (missing .fi) -- base64: also build for curl + These are verified by verify-synopsis.pl, which extracts the SYNPOSIS + code and runs it through gcc. - Since the tool itself now uses the base64 code using the curlx way, it - needs to build also when the tool needs it. Starting now, the tool build - defines BULDING_CURL to allow lib-side code to use it. + Closes #12402 - Follow-up to 2e160c9c6525 +- sendf: fix comment typo - Closes #12010 +- fopen: allocate the dir after fopen -Eduard Strehlau (4 Oct 2023) + Move the allocation of the directory name down to after the fopen() call + to allow that shortcut code path to avoid a superfluous malloc+free + cycle. -- tests: Fix zombie processes left behind by FTP tests. + Follow-up to 73b65e94f35311 - ftpserver.pl correctly cleans up spawned server processes, - but forgets to wait for the shell used to spawn them. - This is barely noticeable during a normal testrun, - but causes process exhaustion and test failure - during a complete torture run of the FTP tests. + Closes #12398 - Fixes #12018 - Closes #12020 +Stefan Eissing (24 Nov 2023) -Dan Fandrich (4 Oct 2023) +- transfer: cleanup done+excess handling -- github/labeler: improve labeler matches + - add `SingleRequest->download_done` as indicator that + all download bytes have been received + - remove `stop_reading` bool from readwrite functions + - move excess body handling into client download writer -- test574: add a timeout to the test + Closes #12371 - This one hangs occasionally, so this will speed up a test run and allow - logs to be seen when it does. +Daniel Stenberg (23 Nov 2023) - Closes #12025 +- fopen: create new file using old file's mode -- tests: propagate errors in libtests + Because the function renames the temp file to the target name as a last + step, if the file was previously owned by a different user, not ORing + the old mode could otherwise end up creating a file that was no longer + readable by the original owner after save. - Use the test macros to automatically propagate some errors, and check - and log others while running the tests. This can help in debugging - exactly why a test has failed. + Reported-by: Loïc Yhuel + Fixes #12299 + Closes #12395 -- tests: set --expect100-timeout to improve test reliability +- test1476: require proxy - On an overloaded server, the default 1 second timeout can go by without - the test server having a chance to respond with the expected headers, - causing tests to fail. Increase the 1 second timeout to 99 seconds so - this failure mode is no longer a problem on test 1129. Some other tests - already set a high value, but make them consistently 99 seconds so if - something goes wrong the test is stalled for less time. + Follow-up from 323df4261c3542 - Ref: #11328 + Closes #12394 -- CI: ignore the "flaky" and "timing-dependent" test results in CMake +- fopen: create short(er) temporary file name - This was already done for automake builds but CMake builds were missed. - Test 1086 actually causes the test harness to crash with: + Only using random letters in the name plus a ".tmp" extension. Not by + appending characters to the final file name. - Warning: unable to close filehandle DWRITE properly: Broken pipe at C:/projec - ts/curl/tests/ftpserver.pl line 527 + Reported-by: Maksymilian Arciemowicz - Rather than fix it now, this change leaves test 1086 entirely skipped on - those builds that show this problem. + Closes #12388 - Follow-up to 589dca761 +Stefan Eissing (23 Nov 2023) - Ref: #11865 +- tests: git ignore generated second-hsts.txt file -Viktor Szakats (4 Oct 2023) + File is generated in test lib1900 -- cmake: improve OpenLDAP builds + Follow-up to 7cb03229d9e9c5 - - cmake: detect OpenLDAP based on function `ldap_init_fd`. - autotools does this. autotools also publishes this detection result - in `HAVE_LDAP_INIT_FD`. We don't mimic that with CMake as the source - doesn't use this value. (it might need to be remove-listed in - `scripts/cmp-config.pl` for future OpenLDAP test builds.) - This also deletes existing self-declaration method via the - CMake-specific `CURL_USE_OPENLDAP` configuration. + Closes #12393 - - cmake: define `LDAP_DEPRECATED=1` for OpenLDAP. - Like autotools does. This fixes a long list of these warnings: - ``` - /usr/local/opt/openldap/include/ldap.h:1049:5: warning: 'LDAP_DEPRECATED' i - s not defined, evaluates to 0 [-Wundef] - ``` +Viktor Szakats (23 Nov 2023) - - cmake: delete LDAP TODO comment no longer relevant. +- openssl: enable `infof_certstack` for 1.1 and LibreSSL 3.6 - Also: + Lower the barrier to enable `infof_certstack()` from OpenSSL 3 to + OpenSSL 1.1.x, and LibreSSL 3.6 or upper. - - autotools: replace domain name `dummy` with `0.0.0.0` in LDAP feature - detection functions. + With the caveat, that "group name" and "type name" are missing from + the log output with these TLS backends. - Ref: #11964 (effort to sync cmake detections with autotools) + Follow-up to b6e6d4ff8f253c8b8055bab9d4d6a10f9be109f3 #12030 - Closes #12024 + Reviewed-by: Daniel Stenberg + Closes #12385 -- cmake: fix unity builds for more build combinations +Daniel Stenberg (23 Nov 2023) - By using unique static function/variable names in source files - implementing these interfaces. +- urldata: fix typo in comment - - OpenLDAP combined with any SSH backend. +- CI: codespell - - MultiSSL with mbedTLS, OpenSSL, wolfSSL, SecureTransport. + The list of words to ignore is in the file + .github/scripts/codespell-ignore.txt - Closes #12027 + Closes #12390 -Daniel Stenberg (4 Oct 2023) +- lib: fix comment typos -- tests: remove leading spaces from some tags + Five separate ones, found by codespell - The threee tags ``, `` and `` were frequently used - with a leading space that this removes. The reason this habbit is so - widespread in testcases is probably that they have been copy and pasted. + Closes #12390 - Hence, fixing them all now might curb this practice from now on. +- test1476: verify cookie PSL mixed case - Closes #12028 +- cookie: lowercase the domain names before PSL checks -Viktor Szakats (4 Oct 2023) + Reported-by: Harry Sintonen -- GHA: bump actions/checkout + Closes #12387 - Follow-up to 2e0fa50fc16b9339f51e0a7bfff0352829323acb #11964 - Follow-up to c39585d9b7ef3cbfc1380812dec60e7b275b6af3 #12000 +Viktor Szakats (23 Nov 2023) - Closes #12023 +- openssl: fix building with v3 `no-deprecated` + add CI test -- spelling: fix codespell 2.2.6 typos + - build quictls with `no-deprecated` in CI to have test coverage for + this OpenSSL 3 configuration. - Closes #12019 + - don't call `OpenSSL_add_all_algorithms()`, `OpenSSL_add_all_digests()`. + The caller code is meant for OpenSSL 3, while these two functions were + only necessary before OpenSSL 1.1.0. They are missing from OpenSSL 3 + if built with option `no-deprecated`, causing build errors: + ``` + vtls/openssl.c:4097:3: error: call to undeclared function 'OpenSSL_add_all_ + algorithms'; ISO C99 and later do not support implicit function declaration + s [-Wimplicit-function-declaration] + vtls/openssl.c:4098:3: error: call to undeclared function 'OpenSSL_add_all_ + digests'; ISO C99 and later do not support implicit function declarations [ + -Wimplicit-function-declaration] + ``` + Ref: https://ci.appveyor.com/project/curlorg/curl-for-win/builds/48587418?f + ullLog=true#L7667 -Daniel Stenberg (3 Oct 2023) + Regression from b6e6d4ff8f253c8b8055bab9d4d6a10f9be109f3 #12030 + Bug: https://github.com/curl/curl/issues/12380#issuecomment-1822944669 + Reviewed-by: Alex Bozarth -- GHA: add workflow to compare configure vs cmake outputs + - vquic/curl_ngtcp2: fix using `SSL_get_peer_certificate` with + `no-deprecated` quictls 3 builds. + Do it by moving an existing solution for this from `vtls/openssl.c` + to `vtls/openssl.h` and adjusting caller code. + ``` + vquic/curl_ngtcp2.c:1950:19: error: implicit declaration of function 'SSL_g + et_peer_certificate'; did you mean 'SSL_get1_peer_certificate'? [-Wimplicit + -function-declaration] + ``` + Ref: https://github.com/curl/curl/actions/runs/6960723097/job/18940818625#s + tep:24:1178 - Uses scripts/cmp-config.pl two compare two curl_config.h files, - presumbly generated with configure and cmake. It displays the - differences and filters out a lot of known lines we ignore. + - curl_ntlm_core: fix `-Wunused-parameter`, `-Wunused-variable` and + `-Wunused-function` when trying to build curl with NTLM enabled but + without the necessary TLS backend (with DES) support. - The script also shows the matches that were *not* used. Possibly - subjects for removal. + Closes #12384 - Closes #11964 +- curl.h: delete Symbian OS references -- appveyor: enable test 571 + curl deprecated Symbian OS in 3d64031fa7a80ac4ae3fd09a5939196268b92f81 + via #5989. Delete references to it from public headers, because there + is no fresh release to use those headers with. - Follow-up from 8a940fd55c175f7 / #12013 + Reviewed-by: Dan Fandrich + Reviewed-by: Jay Satiro + Closes #12378 - Closes #12017 +- windows: use built-in `_WIN32` macro to detect Windows -Viktor Szakats (3 Oct 2023) + Windows compilers define `_WIN32` automatically. Windows SDK headers + or build env defines `WIN32`, or we have to take care of it. The + agreement seems to be that `_WIN32` is the preferred practice here. + Make the source code rely on that to detect we're building for Windows. -- build: alpha-sort source files for lib and src + Public `curl.h` was using `WIN32`, `__WIN32__` and `CURL_WIN32` for + Windows detection, next to the official `_WIN32`. After this patch it + only uses `_WIN32` for this. Also, make it stop defining `CURL_WIN32`. - Closes #12014 + There is a slight chance these break compatibility with Windows + compilers that fail to define `_WIN32`. I'm not aware of any obsolete + or modern compiler affected, but in case there is one, one possible + solution is to define this macro manually. -- cmake: delete old `HAVE_LDAP_URL_PARSE` logic + grepping for `WIN32` remains useful to discover Windows-specific code. - Left there by accident after adding proper detection for this. + Also: - Follow-up to 772f0d8edf1c3c2745543f42388ccec5a16ee2c0 #12006 + - extend `checksrc` to ensure we're not using `WIN32` anymore. - Ref: #11964 (effort to sync cmake detections with autotools) + - apply minor formatting here and there. - Closes #12015 + - delete unnecessary checks for `!MSDOS` when `_WIN32` is present. -Stefan Eissing (3 Oct 2023) + Co-authored-by: Jay Satiro + Reviewed-by: Daniel Stenberg -- tests: increase lib571 timeout from 3s to 30s + Closes #12376 - - 3s is too short for our CI, making this test fail occasionally - - test usually experiences no delay run locally, so 30s wont hurt +Stefan Eissing (22 Nov 2023) - Closes #12013 +- url: ConnectionExists revisited -Viktor Szakats (3 Oct 2023) + - have common pattern of `if not match, continue` + - revert pages long if()s to return early + - move dead connection check to later since it may + be relatively expensive + - check multiuse also when NOT building with NGHTTP2 + - for MULTIUSE bundles, verify that the inspected + connection indeed supports multiplexing when in use + (bundles may contain a mix of connection, afaict) -- cmake: fix unity with Windows Unicode + TrackMemory + Closes #12373 - Found the root cause of the startup crash in unity builds with Unicode - and TrackMemory enabled at the same time. +Daniel Stenberg (22 Nov 2023) - We must make sure that the `memdebug.h` header doesn't apply to - `lib/curl_multibyte.c` (as even noted in a comment there.) In unity - builds all headers apply to all sources, including `curl_multibyte.c`. - This probably resulted in an infinite loop on startup. +- CURLMOPT_MAX_CONCURRENT_STREAMS: make sure the set value is within range - Exclude this source from unity compilation with TrackMemory enabled, - in both libcurl and curl tool. Enable unity mode for a debug Unicode - CI job to keep it tested. Also delete the earlier workaround that - fully disabled unity for affected builds. + ... or use the default value. - Follow-up to d82b080f6374433ce7c98241329189ad2d3976f8 #12005 - Follow-up to 3f8fc25720900b14b7432f4bd93407ca15311719 #11095 + Also clarify the documentation language somewhat. - Closes #11928 + Closes #12382 -- cmake: disable unity mode with Windows Unicode + TrackMemory +- urldata: make maxconnects a 32 bit value - "TrackMemory" is `ENABLE_DEBUG=ON` (aka `ENABLE_CURLDEBUG=ON`, - aka `-DCURLDEBUG`). + "2^32 idle connections ought to be enough for anybody" - There is an issue with memory tracking and Unicode when built in "unity" - mode, which results in the curl tool crashing right on startup, even - without any command-line option. Interestingly this doesn't happen under - WINE (at least on the system I tested this on), but consistenly happens - on real Windows machines. Crash is 0xC0000374 heap corruption. Both - shared and static curl executables are affected. + Closes #12375 - This limitation probably won't hit too many people, but it remains - a TODO to find and fix the root cause and drop this workaround. +- FEATURES: update the URL phrasing - Example builds and runs: - https://ci.appveyor.com/project/curlorg/curl/builds/48169111/job/17cptxhtpubd - 7iwj#L313 (static) - https://ci.appveyor.com/project/curlorg/curl/builds/48169111/job/76e1ge758tby - qu9c#L317 (shared) + The URL is length limited since a while back so "no limit" simply is not + true anymore. Mention the URL RFC standard used instead. - Follow-up to 3f8fc25720900b14b7432f4bd93407ca15311719 #11095 + Closes #12383 - Ref: #11928 - Closes #12005 +- wolfssh: remove redundant static prototypes -- cmake: tidy-up `NOT_NEED_LBER_H` detection + vssh/wolfssh.c:346:18: error: redundant redeclaration of ‘wscp_recv’ [-We + rror=redundant-decls] - Follow-up to 772f0d8edf1c3c2745543f42388ccec5a16ee2c0 #12006 + Closes #12381 -- appveyor: rewrite batch in PowerShell + CI improvements +- setopt: remove superfluous use of ternary expressions - 1. Rewrite in PowerShell: + Closes #12374 - - rewrite MS-DOS batch build script in PowerShell. - - move some bash operations into native PowerShell. - - fixups for PowerShell insisting on failure when a command outputs - something to stderr. - - fix to actually run `curl -V` after every build. - (and exclude ARM64 builds.) - - also say why we skipped `curl -V` if we had to skip. - - fix CMake warnings about unused configuration variables, by adapting - these dynamically for build cases. - - dedupe OpenSSL path into a variable. - - disable `test1451` failing with a warning anyway due to missing python - impacket. (after trying and failing to install impacket) - PowerShell promotes these warnings to errors by PowerShell. We can also - suppress they wholesale if they start causing issues in the future, - like we already to with `autoreconf` and `./configure`. +- mime: store "form escape" as a single bit - PowerShell is better than MS-DOS batches, so the hope is this makes it - easier to extend and maintain the AppVeyor build logic. POSIX/bash isn't - supported inline by AppVeyor on Windows build machines, but we are okay - to keep it in an external script, so it's also an option. + Closes #12374 - 2. CI improvements: +- setopt: check CURLOPT_TFTP_BLKSIZE range on set - - enable tests for a "unity" build job. - - speed-up CI initialization by using shallow clones of the curl repo. - - speed-up CMake MSVC jobs with `TrackFileAccess=false`. - - enable parallelism in `VisualStudioSolution` builds. - - display CMake version before builds. - - always show the CPU in job names. - - tell which jobs are build-only in job names. - - move `TESTING:` value next to `DISABLED_TESTS:` in two jobs. - - add `config.log` (autotools) to dumped logs (need to enable manually). + ... instead of later when the transfer is about to happen. - 3. Style: + Closes #12374 - - use single-quotes in YAML like we do in other CI YAML files. - It also allows to drop quoting characters and lighter to write/read. - (keep double quotes for PowerShell strings needing expansion.) +Viktor Szakats (21 Nov 2023) - Closes #11999 +- build: add more picky warnings and fix them -- cmake: fix `HAVE_LDAP_SSL`, `HAVE_LDAP_URL_PARSE` on non-Windows + Enable more picky compiler warnings. I've found these options in the + nghttp3 project when implementing the CMake quick picky warning + functionality for it [1]. - - set `HAVE_LDAP_URL_PARSE` if `ldap_url_parse` function exists. - Before this patch we set it based it on the presence of `stricmp`, - which correctly enabled it on e.g. Windows, but was inaccurate for - other platforms. + `-Wunused-macros` was too noisy to keep around, but fixed a few issues + it revealed while testing. - - always set `HAVE_LDAP_SSL` if an LDAP backend is detected and - LDAPS is not explicitly disabled. This mimics autotools behaviour. - Previously we set it only for Windows LDAP. After this fix, LDAPS is - correctly enabled in default macOS builds. + - autotools: reflect the more precisely-versioned clang warnings. + Follow-up to 033f8e2a08eb1d3102f08c4d8c8e85470f8b460e #12324 + - autotools: sync between clang and gcc the way we set `no-multichar`. + - autotools: avoid setting `-Wstrict-aliasing=3` twice. + - autotools: disable `-Wmissing-noreturn` for MSYS gcc targets [2]. + It triggers in libtool-generated stub code. - - enable LDAP[S] for a CMake macOS CI job. Target OS X 10.9 (Mavericks) - to avoid deprecation warnings for LDAP API. + - lib/timeval: delete a redundant `!MSDOS` guard from a `WIN32` branch. - - always detect `HAVE_LDAP_SSL_H`, even with LDAPS explicitly disabled. - This doesn't make much sense, but let's do it to sync behaviour with - autotools. + - lib/curl_setup.h: delete duplicate declaration for `fileno`. + Added in initial commit ae1912cb0d494b48d514d937826c9fe83ec96c4d + (1999-12-29). This suggests this may not be needed anymore, but if + it does, we may restore this for those specific (non-Windows) systems. + - lib: delete unused macro `FTP_BUFFER_ALLOCSIZE` since + c1d6fe2aaa5a26e49a69a4f2495b3cc7a24d9394. + - lib: delete unused macro `isxdigit_ascii` since + f65f750742068f579f4ee6d8539ed9d5f0afcb85. + - lib/mqtt: delete unused macro `MQTT_HEADER_LEN`. + - lib/multi: delete unused macro `SH_READ`/`SH_WRITE`. + - lib/hostip: add `noreturn` function attribute via new `CURL_NORETURN` + macro. + - lib/mprintf: delete duplicate declaration for `Curl_dyn_vprintf`. + - lib/rand: fix `-Wunreachable-code` and related fallouts [3]. + - lib/setopt: fix `-Wunreachable-code-break`. + - lib/system_win32 and lib/timeval: fix double declarations for + `Curl_freq` and `Curl_isVistaOrGreater` in CMake UNITY mode [4]. + - lib/warnless: fix double declarations in CMake UNITY mode [5]. + This was due to force-disabling the header guard of `warnless.h` to + to reapply it to source code coming after `warnless.c` in UNITY + builds. This reapplied declarations too, causing the warnings. + Solved by adding a header guard for the lines that actually need + to be reapplied. + - lib/vauth/digest: fix `-Wunreachable-code-break` [6]. + - lib/vssh/libssh2: fix `-Wunreachable-code-break` and delete redundant + block. + - lib/vtls/sectransp: fix `-Wunreachable-code-break` [7]. + - lib/vtls/sectransp: suppress `-Wunreachable-code`. + Detected in `else` branches of dynamic feature checks, with results + known at compile-time, e.g. + ```c + if(SecCertificateCopySubjectSummary) /* -> true */ + ``` + Likely fixable as a separate micro-project, but given SecureTransport + is deprecated anyway, let's just silence these locally. + - src/tool_help: delete duplicate declaration for `helptext`. + - src/tool_xattr: fix `-Wunreachable-code`. + - tests: delete duplicate declaration for `unitfail` [8]. + - tests: delete duplicate declaration for `strncasecompare`. + - tests/libtest: delete duplicate declaration for `gethostname`. + Originally added in 687df5c8c39c370a59999b9afc0917d808d978b7 + (2010-08-02). + Got complicated later: c49e9683b85ba9d12cbb6eebc4ab2c8dba68fbdc + If there are still systems around with warnings, we may restore the + prototype, but limited for those systems. + - tests/lib2305: delete duplicate declaration for + `libtest_debug_config`. + - tests/h2-download: fix `-Wunreachable-code-break`. + + [1] https://github.com/ngtcp2/nghttp3/blob/a70edb08e954d690e8fb2c1df999b5a056 + f8bf9f/cmake/PickyWarningsC.cmake + [2] https://ci.appveyor.com/project/curlorg/curl/builds/48553586/job/3qkgjaui + qla5fj45?fullLog=true#L1675 + [3] https://github.com/curl/curl/actions/runs/6880886309/job/18716044703?pr=1 + 2331#step:7:72 + https://github.com/curl/curl/actions/runs/6883016087/job/18722707368?pr=1 + 2331#step:7:109 + [4] https://ci.appveyor.com/project/curlorg/curl/builds/48555101/job/9g15qkrr + iklpf1ut#L204 + [5] https://ci.appveyor.com/project/curlorg/curl/builds/48555101/job/9g15qkrr + iklpf1ut#L218 + [6] https://github.com/curl/curl/actions/runs/6880886309/job/18716042927?pr=1 + 2331#step:7:290 + [7] https://github.com/curl/curl/actions/runs/6891484996/job/18746659406?pr=1 + 2331#step:9:1193 + [8] https://github.com/curl/curl/actions/runs/6882803986/job/18722082562?pr=1 + 2331#step:33:1870 + + Closes #12331 + +Daniel Stenberg (21 Nov 2023) + +- transfer: avoid unreachable expression + + If curl_off_t and size_t have the same size (which is common on modern + 64 bit systems), a condition cannot occur which Coverity pointed + out. Avoid the warning by having the code conditionally only used if + curl_off_t actually is larger. + + Follow-up to 1cd2f0072fa482e25baa2 + + Closes #12370 + +Stefan Eissing (21 Nov 2023) + +- transfer: readwrite improvements + + - changed header/chunk/handler->readwrite prototypes to accept `buf`, + `blen` and a `pconsumed` pointer. They now get the buffer to work on + and report back how many bytes they consumed + - eliminated `k->str` in SingleRequest + - improved excess data handling to properly calculate with any body data + left in the headerb buffer + - eliminated `k->badheader` enum to only be a bool + + Closes #12283 + +Daniel Stenberg (21 Nov 2023) - - fix benign typo in variable name. +- RELEASE-NOTES: synced - Ref: #11964 (effort to sync cmake detections with autotools) +Jiří Hruška (21 Nov 2023) - Closes #12006 +- transfer: avoid calling the read callback again after EOF -- autotools: restore `HAVE_IOCTL_*` detections + Regression since 7f43f3dc5994d01b12 (7.84.0) - This restores `CURL_CHECK_FUNC_IOCTL` detection. I deleted it in - 4d73854462f30948acab12984b611e9e33ee41e6 and - c3456652a0c72d1845d08df9769667db7e159949 (2022-08), because the - `HAVE_IOCTL` result it generated was unused in the source. But, - I did miss the fact that this had two dependent checks: - `CURL_CHECK_FUNC_IOCTL_FIONBIO`, - `CURL_CHECK_FUNC_IOCTL_SIOCGIFADDR` that we do actually need: - `HAVE_IOCTL_FIONBIO`, `HAVE_IOCTL_SIOCGIFADDR`. + Bug: https://curl.se/mail/lib-2023-11/0017.html - Regression from 4d73854462f30948acab12984b611e9e33ee41e6 + Closes #12363 - Ref: #11964 (effort to sync cmake detections with autotools) +Daniel Stenberg (21 Nov 2023) - Closes #12008 +- doh: provide better return code for responses w/o addresses -Daniel Stenberg (2 Oct 2023) + Previously it was wrongly returning CURLE_OUT_OF_MEMORY when the + response did not contain any addresses. Now it more accurately returns + CURLE_COULDNT_RESOLVE_HOST. -- RELEASE-PROCEDURE.md: updated coming release dates + Reported-by: lRoccoon on github -- RELEASE-NOTES: synced + Fixes #12365 + Closes #12366 -Viktor Szakats (1 Oct 2023) +Stefan Eissing (21 Nov 2023) -- cmake: pre-cache `HAVE_POLL_FINE` on Windows +- HTTP/2, HTTP/3: handle detach of onoing transfers - Windows doesn't support `poll()`, so we can safely skip checking for - fine poll. + - refs #12356 where a UAF is reported when closing a connection + with a stream whose easy handle was cleaned up already + - handle DETACH events same as DONE events in h2/h3 filters - Closes #12003 + Fixes #12356 + Reported-by: Paweł Wegner + Closes #12364 -- gha: bump actions to latest versions +Viktor Szakats (20 Nov 2023) - - actions@checkout@v4 (from v3 and v2) +- autotools: stop setting `-std=gnu89` with `--enable-warnings` - - fsfe/reuse-action@v2 (from v1) + Do not alter the C standard when building with `--enable-warnings` when + building with gcc. - Closes #12000 + On one hand this alters warning results compared to a default build. + On the other, it may produce different binaries, which is unexpected. -Stefan Eissing (30 Sep 2023) + Also fix new warnings that appeared after removing `-std=gnu89`: -- h2: testcase and fix for pausing h2 streams + - include: fix public curl headers to use the correct printf mask for + `CURL_FORMAT_CURL_OFF_T` and `CURL_FORMAT_CURL_OFF_TU` with mingw-w64 + and Visual Studio 2013 and newer. This fixes the printf mask warnings + in examples and tests. E.g. [1] - - refs #11982 where it was noted that paused transfers may - close successfully without delivering the complete data - - made sample poc into tests/http/client/h2-pausing.c and - added test_02_27 to reproduce + - conncache: fix printf format string [2]. - Closes #11989 - Fixes #11982 - Reported-by: Harry Sintonen + - http2: fix potential null pointer dereference [3]. + (seen on Slackware with gcc 11.) -Viktor Szakats (30 Sep 2023) + - libssh: fix printf format string in SFTP code [4]. + Also make MSVC builds compatible with old CRT versions. -- cmake: validate `CURL_DEFAULT_SSL_BACKEND` config value + - libssh2: fix printf format string in SFTP code for MSVC. + Applying the same fix as for libssh above. - Before this patch CMake builds accepted any value and it was used at - runtime as-is. This patch make sure that the selected default backend - is also enabled in the build. It also enforces a full lowercase value. + - unit1395: fix `argument is null` and related issues [5]: + - stop calling `strcmp()` with NULL to avoid undefined behaviour. + - fix checking results if some of them were NULL. + - do not pass NULL to printf `%s`. - This improves reproducibility and brings CMake in sync with autotools - which already worked like described above. + - ci: keep a build job with `-std=gnu89` to continue testing for + C89-compliance. We can apply this to other gcc jobs as needed. + Ref: b23ce2cee7329bbf425f18b49973b7a5f23dfcb4 (2022-09-23) #9542 - Follow-up to 26c7feb8b9d51a57fab3325571b4bbfa03b11af0 #11774 + [1] https://dev.azure.com/daniel0244/curl/_build/results?buildId=18581&view=l + ogs&jobId=ccf9cc6d-2ef1-5cf2-2c09-30f0c14f923b + [2] https://github.com/curl/curl/actions/runs/6896854263/job/18763831142?pr=1 + 2346#step:6:67 + [3] https://github.com/curl/curl/actions/runs/6896854253/job/18763839238?pr=1 + 2346#step:30:214 + [4] https://github.com/curl/curl/actions/runs/6896854253/job/18763838007?pr=1 + 2346#step:29:895 + [5] https://github.com/curl/curl/actions/runs/6896854253/job/18763836775?pr=1 + 2346#step:33:1689 - Closes #11998 + Closes #12346 -- autotools: adjust `CURL_CA_PATH` value to CMake +- autotools: fix/improve gcc and Apple clang version detection - autotools was using the same value as CMake, but with an ending - slash. Delete the ending slash to match configurations. + - Before this patch we expected `n.n` `-dumpversion` output, but Ubuntu + may return `n-win32` (also with `-dumpfullversion`). Causing these + errors and failing to enable picky warnings: + ``` + ../configure: line 23845: test: : integer expression expected + ``` + Ref: https://github.com/libssh2/libssh2/actions/runs/6263453828/job/1700789 + 3718#step:5:143 - Ref: #11964 (effort to sync cmake detections with autotools) + Fix that by stripping any dash-suffix and handling a dotless (major-only) + version number by assuming `.0` in that case. - Closes #11997 + `9.3-posix`, `9.3-win32`, `6`, `9.3.0`, `11`, `11.2`, `11.2.0` + Ref: https://github.com/mamedev/mame/pull/9767 -- cmake: detect `sys/wait.h` and `netinet/udp.h` + - fix Apple clang version detection for releases between + 'Apple LLVM version 7.3.0' and 'Apple LLVM version 10.0.1' where the + version was under-detected as 3.7 llvm/clang equivalent. - Ref: #11964 (effort to sync cmake detections with autotools) + - fix Apple clang version detection for 'Apple clang version 11.0.0' + and newer where the Apple clang version was detected, instead of its + llvm/clang equivalent. - Closes #11996 + - display detected clang/gcc/icc compiler version. -Daniel Stenberg (30 Sep 2023) + Via libssh2: + - https://github.com/libssh2/libssh2/commit/00a3b88c51cdb407fbbb347a2e38c5c7d + 89875ad + https://github.com/libssh2/libssh2/pull/1187 + - https://github.com/libssh2/libssh2/commit/89ccc83c7da73e7ca3a112e3500081319 + 42b592e + https://github.com/libssh2/libssh2/pull/1232 -- lib: provide and use Curl_hexencode + Closes #12362 - Generates a lower case ASCII hex output from a binary input. +- autotools: delete LCC compiler support bits - Closes #11990 + Follow-up to fd7ef00f4305a2919e6950def1cf83d0110a4acd #12222 -- configure: check for the capath by default + Closes #12357 - ... if the chosen TLS backend supports it: OpenSSL, GnuTLS, mbedTLS or wolfSS - L +- cmake: add test for `DISABLE` options, add `CURL_DISABLE_HEADERS_API` - cmake: synced - - Assisted-by: Viktor Szakats - Closes #11987 + - tests: verify CMake `DISABLE` options. -- wolfssl: ignore errors in CA path + Make an exception for 2 CMake-only ones, and one more that's + using a different naming scheme, also in autotools and source. - The default wolfSSL_CTX_load_verify_locations() function is quite picky - with the certificates it loads and will for example return error if just - one of the certs has expired. + - cmake: add support for `CURL_DISABLE_HEADERS_API`. - With the *_ex() function and its WOLFSSL_LOAD_FLAG_IGNORE_ERR flag, it - behaves more similar to what OpenSSL does by default. + Suggested-by: Daniel Stenberg + Ref: https://github.com/curl/curl/pull/12345#pullrequestreview-1736238641 - Even the set of default certs on my Debian unstable has several expired - ones. + Closes #12353 - Assisted-by: Juliusz Sosinowicz - Assisted-by: Michael Osipov +Jacob Hoffman-Andrews (20 Nov 2023) - Closes #11987 +- hyper: temporarily remove HTTP/2 support -- create-dirs.d: clarify it also uses --output-dirs + The current design of the Hyper integration requires rebuilding the + Hyper clientconn for each request. However, building the clientconn + requires resending the HTTP/2 connection preface, which is incorrect + from a protocol perspective. That in turn causes servers to send GOAWAY + frames, effectively degrading performance to "no connection reuse" in + the best case. It may also be triggering some bugs where requests get + dropped entirely and reconnects take too long. - Reported-by: Robert Simpson - Fixes #11991 - Closes #11995 + This doesn't rule out HTTP/2 support with Hyper, but it may take a + redesign of the Hyper integration in order to make things work. -Viktor Szakats (30 Sep 2023) + Closes #12191 -- appveyor: fix yamlint issues, indent +Jay Satiro (20 Nov 2023) - Also: - - use double quotes in all batch if statements. +- schannel: fix unused variable warning - Closes #11994 + Bug: https://github.com/curl/curl/pull/12349#issuecomment-1818000846 + Reported-by: Viktor Szakats -- cmake: detect `HAVE_CLOCK_GETTIME_MONOTONIC_RAW` + Closes https://github.com/curl/curl/pull/12361 - Based on existing autotools logic. +Daniel Stenberg (19 Nov 2023) - Ref: #11964 (effort to sync cmake detections with autotools) +- url: find scheme with a "perfect hash" - Closes #11981 + Instead of a loop to scan over the potentially 30+ scheme names, this + uses a "perfect hash" table. This works fine because the set of schemes + is known and cannot change in a build. The hash algorithm and table size + is made to only make a single scheme index per table entry. -- cmake: detect `HAVE_GETADDRINFO_THREADSAFE` + The perfect hash is generated by a separate tool (scripts/schemetable.c) - Based on existing autotools logic. + Closes #12347 - autotools checks for old versions of the allowlisted target OSes and - disables this feature when seeing them. In CMake we assume we're running - on newer systems and enable regardless of OS version. +- scripts: add schemetable.c - autotools always runs all 3 probes for non-fast-tracked systems and - enables this feature if any one of them was successful. To save - configuration time, CMake stops at the first successful check. + This tool generates a scheme-matching table. - OpenBSD is not fast-tracked and then gets blocklisted as a generic BSD - system. I haven't double-checked if this is correct, but looks odd. + It iterates over a number of different initial and shift values in order + to find the hash algorithm that needs the smallest possible table. - Ref: #11964 (effort to sync cmake detections with autotools) + The generated hash function, table and table size then needs to be used + by the url.c:Curl_getn_scheme_handler() function. - Closes #11979 +Stefan Eissing (19 Nov 2023) -- cmake: fix `HAVE_WRITABLE_ARGV` detection +- vtls/vquic, keep peer name information together - Move detection before the creation of detection results in - `curl_config.h`. + - add `struct ssl_peer` to keep hostname, dispname and sni + for a filter + - allocate `sni` for use in VTLS backend + - eliminate `Curl_ssl_snihost()` and its use of the download buffer + - use ssl_peer in SSL and QUIC filters - Ref: #11964 (effort to sync cmake detections with autotools) + Closes #12349 - Closes #11978 +Viktor Szakats (18 Nov 2023) -- appveyor: minor improvements +- build: always revert `#pragma GCC diagnostic` after use - - run `curl -V` after builds to see if they run and with what features. - Except for one job where a CRT DLL is missing. And ARM64 which should - fail, but is silently not launched instead. + Before this patch some source files were overriding gcc warning options, + but without restoring them at the end of the file. In CMake UNITY builds + these options spilled over to the remainder of the source code, + effecitvely disabling them for a larger portion of the codebase than + intended. - - copy libcurl DLL next to curl tool and tests binaries in shared mode. - This makes it possible to run the tests. (We don't run tests after - these builds yet.) + `#pragma clang diagnostic` didn't have such issue in the codebase. - - list the DLLs and EXEs present after the builds. + Reviewed-by: Marcel Raad + Closes #12352 - - add `DEBUG` variable for CMake builds to allow disabling it, for - testing non-debug builds. (currently enabled for all) +- tidy-up: casing typos, delete unused Windows version aliases - - add commented lines that dump CMake configuration logs for debugging - build/auto-detection issues. + - cmake: fix casing of `UnixSockets` to match the rest of the codebase. - - add gcc version to jobs where missing. + - curl-compilers.m4: fix casing in a comment. - - switch a job to the native MSYS2 mingw-w64 toolchain. This adds gcc 9 - to the build mix. + - setup-win32: delete unused Windows version constant aliases. - - make `SHARED=OFF` and `OPENSSL=OFF` defaults global. + Reviewed-by: Marcel Raad + Closes #12351 - - delete a duplicate backslash. +- keylog: disable if unused - Closes #11976 + Fully disable keylog code if there is no TLS or QUIC subsystem using it. -- configure: replace adhoc domain with `localhost` in tests + Closes #12350 - Reviewed-by: Daniel Stenberg - Closes #11988 +- cmake: add `CURL_DISABLE_BINDLOCAL` option -- tidy-up: use more example domains + To match similar autotools option. - Also make use of the example TLD: - https://en.wikipedia.org/wiki/.example + Default is `ON`. Reviewed-by: Daniel Stenberg - Closes #11992 + Closes #12345 -Dan Fandrich (29 Sep 2023) +- url: fix `-Wzero-length-array` with no protocols -- runtests: display the test status if tests appear hung + Fixes: + ``` + ./lib/url.c:178:56: warning: use of an empty initializer is a C2x extension [ + -Wc2x-extensions] + 178 | static const struct Curl_handler * const protocols[] = { + | ^ + ./lib/url.c:178:56: warning: zero size arrays are an extension [-Wzero-length + -array] + ``` - It sometimes happens that a test hangs during a test run and never - returns. The test harness will wait indefinitely for the results and on - CI servers the CI job will eventually be killed after an hour or two. - At the end of a test run, if results haven't come in within a couple of - minutes, display the status of all test runners and what tests they're - running to help in debugging the problem. + Closes #12344 - This feature is really only kick in with parallel testing enabled, which - is fine because without parallel testing it's usually easy to tell what - test has hung. +- url: fix builds with `CURL_DISABLE_HTTP` - Closes #11980 + Fixes: + ``` + ./lib/url.c:456:35: error: no member named 'formp' in 'struct UrlState' + 456 | Curl_mime_cleanpart(data->state.formp); + | ~~~~~~~~~~~ ^ + ``` -- github/labeler: remove workaround for labeler + Regression from 74b87a8af13a155c659227f5acfa78243a8b2aa6 #11682 - This was added due to what seemed to be a bug regarding the sync-labels: - config option, but it looks like it wasn't necessary. + Closes #12343 - Follow-up to b2b0534e7 +- http: fix `-Wunused-parameter` with no auth and no proxy -Viktor Szakats (29 Sep 2023) + ``` + lib/http.c:734:26: warning: unused parameter 'proxy' [-Wunused-parameter] + bool proxy) + ^ + ``` -- docs: upgrade an URL to HTTPS in `BINDINGS.md` [ci skip] + Reviewed-by: Marcel Raad + Closes #12338 -Daniel Stenberg (29 Sep 2023) +Daniel Stenberg (16 Nov 2023) -- docs: replace made up domains with example.com +- TODO: Some TLS options are not offered for HTTPS proxies - in FAQ and MANUAL.md + Closes #12286 + Closes #12342 - - example.com was made for this purpose. +- RELEASE-NOTES: synced - - reduces the risk that one of those domains suddenly start hosting - something nasty and we provide links to them +- duphandle: make dupset() not return with pointers to old alloced data - Closes #11986 + As the blob pointers are to be duplicated, the function must not return + mid-function with lingering pointers to the old handle's allocated data, + as that would lead to double-free in OOM situations. -Michael Osipov (29 Sep 2023) + Make sure to clear all destination pointers first to avoid this risk. -- acinclude.m4: Document proper system truststore on FreeBSD + Closes #12337 - The default system truststore on FreeBSD has been /etc/ssl/certs for many - years now. It is managed canonically through certctl(8) and contains hashed - symlinks for OpenSSL and other TLS providers. - The previous ones require security/ca_root_nss which might not be installed o - r - will not contain any custom CA certificates. +Viktor Szakats (16 Nov 2023) - Closes #11985 +- http: fix `-Wunused-variable` compiler warning -Daniel Stenberg (29 Sep 2023) + Fix compiler warnings in builds with disabled auths, NTLM and SPNEGO. -- FAQ: How do I upgrade curl.exe in Windows? + E.g. with `CURL_DISABLE_BASIC_AUTH` + `CURL_DISABLE_BEARER_AUTH` + + `CURL_DISABLE_DIGEST_AUTH` + `CURL_DISABLE_NEGOTIATE_AUTH` + + `CURL_DISABLE_NTLM` on non-Windows. - This is a growing question, better answer it here to get somewhere to - point users to. + ``` + ./curl/lib/http.c:737:12: warning: unused variable 'result' [-Wunused-variabl + e] + CURLcode result = CURLE_OK; + ^ + ./curl/lib/http.c:995:18: warning: variable 'availp' set but not used [-Wunus + ed-but-set-variable] + unsigned long *availp; + ^ + ./curl/lib/http.c:996:16: warning: variable 'authp' set but not used [-Wunuse + d-but-set-variable] + struct auth *authp; + ^ + ``` - Closes #11984 + Regression from e92edfbef64448ef461117769881f3ed776dec4e #11490 -Viktor Szakats (28 Sep 2023) + Fixes #12228 + Closes #12335 -- cmake: pre-cache `HAVE_BASENAME` for mingw-w64 and MSVC +Jay Satiro (16 Nov 2023) - `basename` is present in mingw-w64, missing from MSVC. Pre-cache - accordingly to make configure faster. +- tool: support bold headers in Windows - Notice that `basename` has a bug so we later disable it even with - mingw-w64: - https://github.com/curl/curl/blob/781242ffa44a9f9b95b6da5ac5a1bf6372ec6257/li - b/curl_setup.h#L820-L825 + - If virtual terminal processing is enabled in Windows then use ANSI + escape codes Esc[1m and Esc[22m to turn bold on and off. - Closes #11974 + Suggested-by: Gisle Vanem -Daniel Stenberg (28 Sep 2023) + Ref: https://github.com/curl/curl/discussions/11770 -- cmake: add missing checks + Closes https://github.com/curl/curl/pull/12321 - - check for arc4random. To make rand.c use it accordingly. - - check for fcntl - - fix fseek detection - - add SIZEOF_CURL_SOCKET_T - - fix USE_UNIX_SOCKETS - - define HAVE_SNPRINTF to 1 - - check for fnmatch - - check for sched_yield - - remove HAVE_GETPPID duplicate from curl_config.h - - add HAVE_SENDMSG +Viktor Szakats (15 Nov 2023) - Ref: #11964 +- build: fix libssh2 + `CURL_DISABLE_DIGEST_AUTH` + `CURL_DISABLE_AWS` - Co-authored-by: Viktor Szakats - Closes #11973 + Builds with libssh2 + `-DCURL_DISABLE_DIGEST_AUTH=ON` + + `-DCURL_DISABLE_AWS=ON` in combination with either Schannel on Windows, + or `-DCURL_DISABLE_NTLM=ON` on other operating systems failed while + compiling due to a missing HMAC declaration. -- configure: remove unused checks + The reason is that HMAC is required by `lib/sha256.c` which publishes + `Curl_sha256it()` which is required by `lib/vssh/libssh2.c` when + building for libssh2 v1.8.2 (2019-05-25) or older. - - for sys/uio.h - - for fork - - for connect + Make sure to compile the HMAC bits for a successful build. - Ref: #11964 + Both HMAC and `Curl_sha256it()` rely on the same internals, so splitting + them into separate sources isn't practical. - Closes #11973 + Fixes: + ``` + [...] + In file included from ./curl/_x64-win-ucrt-cmake-llvm-bld/lib/CMakeFiles/libc + url_object.dir/Unity/unity_0_c.c:310: + ./curl/lib/sha256.c:527:42: error: array has incomplete element type 'const s + truct HMAC_params' + 527 | const struct HMAC_params Curl_HMAC_SHA256[] = { + | ^ + ./curl/lib/curl_sha256.h:34:21: note: forward declaration of 'struct HMAC_par + ams' + [...] + ``` -- lib: remove TIME_WITH_SYS_TIME + Regression from e92edfbef64448ef461117769881f3ed776dec4e #11490 - It is not used in any code anywhere. + Fixes #12273 + Closes #12332 - Ref: #11964 - Closes #11975 +Daniel Stenberg (15 Nov 2023) -- docs: update curl man page references +- duphandle: also free 'outcurl->cookies' in error path - Detected by the manpage-syntax update + Fixes memory-leak when OOM mid-function - Closes #11963 + Use plain free instead of safefree, since the entire struct is + freed below. -- manpage-syntax: verify curl man page references + Remove some free calls that is already freed in Curl_freeset() - 1. References to curl symbols are now checked that they indeed exist as - man pages. This for \f references as well as the names referenced in the - SEE ALSO section. + Closes #12329 - Allowlist curl.1 since it is not always built in builds +Viktor Szakats (15 Nov 2023) - 2. References to curl symbols that lack section now causes warning, since tha - t - will prevent them from getting linked properly +- config-win32: set `HAVE_SNPRINTF` for mingw-w64 - 3. Check for "bare" references to curl functions and warn, they should be - references + It's available in all mingw-w64 releases. We already pre-fill this + detection in CMake. - Closes #11963 + Closes #12325 -- cmake: add check for suseconds_t +- sasl: fix `-Wunused-function` compiler warning - And fix the HAVE_LONGLONG define + In builds with disabled auths. - Ref: #11964 - Closes #11977 + ``` + lib/curl_sasl.c:266:17: warning: unused function 'get_server_message' [-Wunus + ed-function] + static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data, + ^ + 1 warning generated. + ``` + Ref: https://github.com/curl/trurl/actions/runs/6871732122/job/18689066151#st + ep:3:3822 -Viktor Szakats (28 Sep 2023) + Reviewed-by: Daniel Stenberg + Closes #12326 -- tidy-up: whitespace fixes +- build: picky warning updates - Closes #11972 + - cmake: sync some picky gcc warnings with autotools. + - cmake, autotools: add `-Wold-style-definition` for clang too. + - cmake: more precise version info for old clang options. + - cmake: use `IN LISTS` syntax in `foreach()`. -- cmake: detect TLS-SRP in OpenSSL/wolfSSL/GnuTLS + Reviewed-by: Daniel Stenberg + Reviewed-by: Marcel Raad + Closes #12324 - With new option `CURL_DISABLE_SRP=ON` to force-disable it. - To match existing option and detection logic in autotools. +Daniel Stenberg (15 Nov 2023) - Also: - - fix detecting GnuTLS. - We assume `nettle` as a GnuTLS dependency. - - add CMake GnuTLS CI job. - - bump AppVeyor CMake OpenSSL MSVC job to OpenSSL 1.1.1 (from 1.0.2) - TLS-SRP fails to detect with 1.0.2 due to an OpenSSL header bug. - - fix compiler warning when building with GnuTLS and disabled TLS-SRP. - - fix comment typos, whitespace. +- urldata: move cookielist from UserDefined to UrlState - Ref: #11964 + 1. Because the value is not strictly set with a setopt option. - Closes #11967 + 2. Because otherwise when duping a handle when all the set.* fields are + first copied and an error happens (think out of memory mid-function), + the function would easily free the list *before* it was deep-copied, + which could lead to a double-free. -- tool: use our own stderr variable + Closes #12323 - Earlier this year we changed our own stderr variable to use the standard - name `stderr` (to avoid bugs where someone is using `stderr` instead of - the curl-tool specific variable). This solution needed to override the - standard `stderr` symbol via the preprocessor. This in turn didn't play - well with unity builds and caused curl tool to crash or stay silent due - to an uninitialized stderr. This was a hard to find issue, fixed by - manually breaking out one file from the unity sources. +Viktor Szakats (14 Nov 2023) - To avoid two these two tricks, this patch implements a different - solution: Restore using our own local variable for our stderr output and - leave `stderr` as-is. To avoid using `stderr` by mistake, add a - `checksrc` rule (based on logic we already used in lib for `strerror`) - that detects any `stderr` use in `src` and points to using our own - variable instead: `tool_stderr`. +- autotools: avoid passing `LDFLAGS` twice to libcurl - Follow-up to 06133d3e9b8aeb9e9ca0b3370c246bdfbfc8619e - Follow-up to 2f17a9b654121dd1ecf4fc043c6d08a9da3522db + autotools passes `LDFLAGS` automatically linker commands. curl's + `lib/Makefile.am` customizes libcurl linker flags. In that + customization, it added `LDFLAGS` to the custom flags. This resulted in + passing `LDFLAGS` _twice_ to the `libtool` command. - Closes #11958 + Most of the time this is benign, but some `LDFLAGS` options can break + the build when passed twice. One such example is passing `.o` files, + e.g. `crt*.o` files necessary when customizing the C runtime, e.g. for + MUSL builds. -Loïc Yhuel (28 Sep 2023) + Passing them twice resulted in duplicate symbol errors: + ``` + libtool: link: clang-15 --target=aarch64-unknown-linux-musl [...] /usr/lib/a + arch64-linux-musl/crt1.o [...] /usr/lib/aarch64-linux-musl/crt1.o [...] + ld.lld-15: error: duplicate symbol: _start + >>> defined at crt1.c + >>> /usr/lib/aarch64-linux-musl/crt1.o:(.text+0x0) + >>> defined at crt1.c + >>> /usr/lib/aarch64-linux-musl/crt1.o:(.text+0x0) + [...] + clang: error: linker command failed with exit code 1 (use -v to see invocatio + n) + ``` -- connect: only start the happy eyeballs timer when needed + This behaviour came with commit 1a593191c2769a47b8c3e4d9715ec9f6dddf5e36 + (2013-07-23) as a fix for bug https://curl.haxx.se/bug/view.cgi?id=1217. + The patch was a works-for-me hack that ended up merged in curl: + https://sourceforge.net/p/curl/bugs/1217/#06ef + With the root cause remaining unclear. - The timeout is only used when there is a second address family, for the - delayed eyeballer. + Perhaps the SUNPro 12 linker was sensitive to `-L` `-l` order, requiring + `-L` first? This would be unusual and suggests a bug in either the + linker or in `libtool`. - Closes #11939 + The curl build does pass the list of detected libs via its own + `LIBCURL_LIBS` variable, which ends up before `LDFLAGS` on the `libtool` + command line, but it's the job of `libtool` to ensure that even + a peculiar linker gets the options in the expected order. Also because + autotools passes `LDFLAGS` last, making it hardly possible to pass + anything after it. -Daniel Stenberg (28 Sep 2023) + Perhaps in the 10 years since this issue, this already got a fix + upstream. -- tool_operate: free 'gateway' correctly + This patch deletes `LDFLAGS` from our customized libcurl options, + leaving a single copy of them as passed by autotools automatically. - Pointed out by Coverity. The fix in 93885cf3a8d4e was incomplete. + Reverts 1a593191c2769a47b8c3e4d9715ec9f6dddf5e36 + Closes #12310 - Also removed repeated wording in IPFS related error messages. +- autotools: accept linker flags via `CURL_LDFLAGS_{LIB,BIN}` - Closes #11969 + To allow passing `LDFLAGS` specific to libcurl (`CURL_LDFLAGS_LIB`) and + curl tool (`CURL_LDFLAGS_BIN`). -Stefan Eissing (28 Sep 2023) + This makes it possible to build libcurl and curl with a single + invocation with lib- and tool-specific custom linker flags. -- lib: move handling of `data->req.writer_stack` into Curl_client_write() + Such flag can be enabling `.map` files, a `.def` file for libcurl DLL, + controlling static/shared, incl. requesting a static curl tool (with + `-static-libtool-libs`) while building both shared and static libcurl. - - move definitions from content_encoding.h to sendf.h - - move create/cleanup/add code into sendf.c - - installed content_encoding writers will always be called - on Curl_client_write(CLIENTWRITE_BODY) - - Curl_client_cleanup() frees writers and tempbuffers from - paused transfers, irregardless of protocol + curl-for-win uses the above and some more. - Closes #11908 + These options are already supported in `Makefile.mk`. CMake has built-in + variables for this. -Loïc Yhuel (28 Sep 2023) + Closes #12312 -- multi: round the timeout up to prevent early wakeups +Jay Satiro (14 Nov 2023) - Curl_timediff rounds down to the millisecond, so curl_multi_perform can - be called too early, then we get a timeout of 0 and call it again. +- tool_cb_hdr: add an additional parsing check - The code already handled the case of timeouts which expired less than - 1ms in the future. By rounding up, we make sure we will never ask the - platform to wake up too early. + - Don't dereference the past-the-end element when parsing the server's + Content-disposition header. - Closes #11938 + As 'p' is advanced it can point to the past-the-end element and prior + to this change 'p' could be dereferenced in that case. -Daniel Stenberg (28 Sep 2023) + Technically the past-the-end element is not out of bounds because dynbuf + (which manages the header line) automatically adds a null terminator to + every buffer and that is not included in the buffer length passed to + the header callback. -- RELEASE-NOTES: spell out that IPFS is via gateway + Closes https://github.com/curl/curl/pull/12320 -- RELEASE-NOTES: synced +Philip Heiduck (14 Nov 2023) -- tool_operate: avoid strlen() -1 on zero length content from file +- .cirrus.yml: freebsd 14 - Follow-up to 65b563a96a226649ba12cb1e + ensure curl works on latest freebsd version - Closes #11959 + Closes #12053 -- tool_operate: fix memory mixups +Daniel Stenberg (13 Nov 2023) - Switch to plain getenv() from curl_getenv() to avoid the allocation and - having to keep track of which free() or curl_free() that need to be - used. +- easy: in duphandle, init the cookies for the new handle - Coverity found issues and a memory leak. + ... not the source handle. - Follow-up to 65b563a96a226649ba12cb1e + Closes #12318 - Closes #11959 +- duphandle: use strdup to clone *COPYPOSTFIELDS if size is not set -Viktor Szakats (27 Sep 2023) + Previously it would unconditionally use the size, which is set to -1 + when strlen is requested. -- curl-functions.m4: fixup recent bad edits + Updated test 544 to verify. - Follow-up to 96c29900bcec32dd6bc8e9857c8871ff4b8b8ed9 #11940 + Closes #12317 - Closes #11966 +- RELEASE-NOTES: synced -Daniel Stenberg (27 Sep 2023) +- curl_easy_duphandle.3: clarify how HSTS and alt-svc are duped -- curl-functions.m4: fix include line + Closes #12315 - This made the getaddrinfo detection fail, but we did not spot it in the - CI because it graciously falled back to using legacy functions instead! +- urldata: move hstslist from 'set' to 'state' - Follow-up to 96c29900bcec (#11940) + To make it work properly with curl_easy_duphandle(). This, because + duphandle duplicates the entire 'UserDefined' struct by plain copy while + 'hstslist' is a linked curl_list of file names. This would lead to a + double-free when the second of the two involved easy handles were + closed. - Closes #11965 + Closes #12315 -- inet_ntop: add typecast to silence Coverity +- test1900: verify duphandle with HSTS using multiple files - CID 1024653: Integer handling issues (SIGN_EXTENSION) + Closes #12315 - Suspicious implicit sign extension: "src[i]" with type "unsigned char - const" (8 bits, unsigned) is promoted in "src[i] << (1 - i % 2 << 3)" to - type "int" (32 bits, signed), then sign-extended to type "unsigned long" - (64 bits, unsigned). If "src[i] << (1 - i % 2 << 3)" is greater than - 0x7FFFFFFF, the upper bits of the result will all be 1. +Goro FUJI (13 Nov 2023) - 111 words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); +- http: allow longer HTTP/2 request method names - The value will not be greater than 0x7FFFFFFF so this still cannot - happen. + - Increase the maximum request method name length from 11 to 23. - Also, switch to ints here instead of longs. The values stored are 16 bit - so at least no need to use 64 bit variables. Also, longs are 32 bit on - some platforms so this logic still needs to work with 32 bits. + For HTTP/1.1 and earlier there's not a specific limit in libcurl for + method length except that it is limited by the initial HTTP request + limit (DYN_HTTP_REQUEST). Prior to fc2f1e54 HTTP/2 was treated the same + and there was no specific limit. - Closes #11960 + According to Internet Assigned Numbers Authority (IANA) the longest + registered method is UPDATEREDIRECTREF which is 17 characters. -- docs: adapt SEE ALSO sections to new requirements + Also there are unregistered methods used by some companies that are + longer than 11 characters. - To please manpage-syntax.pl used by test 1173 + The limit was originally added by 61f52a97 but not used until fc2f1e54. - Closes #11957 + Ref: https://www.iana.org/assignments/http-methods/http-methods.xhtml -- manpage-syntax.pl: verify SEE ALSO syntax + Closes https://github.com/curl/curl/pull/12311 - - Enforce a single reference per .BR line - - Skip the quotes around the section number for example (3) - - Insist on trailing commas on all lines except the last - - Error on comma on the last SEE ALSO entry +Jay Satiro (12 Nov 2023) - - List the entries alpha-sorted, not enforced just recommended +- CURLOPT_CAINFO_BLOB.3: explain what CURL_BLOB_COPY does - Closes #11957 + - Add an explanation of the CURL_BLOB_COPY flag to CURLOPT_CAINFO_BLOB + and CURLOPT_PROXY_CAINFO_BLOB docs. -- connect: expire the timeout when trying next + All the other _BLOB option docs already have the same explanation. - ... so that it gets called again immediately and can continue trying - addresses to connect to. Otherwise it might unnecessarily wait for a - while there. + Closes https://github.com/curl/curl/pull/12277 - Fixes #11920 - Reported-by: Loïc Yhuel - Closes #11935 +Viktor Szakats (11 Nov 2023) -- http: remove wrong comment for http_should_fail +- tidy-up: dedupe Windows system libs in cmake - Reported-by: Christian Schmitz - Ref: #11936 - Closes #11941 + Reviewed-by: Daniel Stenberg + Closes #12307 -Dan Fandrich (26 Sep 2023) +Junho Choi (11 Nov 2023) -- tool_setopt: remove unused function tool_setopt_flags +- ci: test with latest quiche release (0.19.0) - This function is identical to tool_setopt_bitmask except that it treats - the argument as unsigned. + Closes #12180 - Closes #11943 +- quiche: use quiche_conn_peer_transport_params() -Viktor Szakats (26 Sep 2023) + In recent quiche, transport parameter API is separated + with quiche_conn_peer_transport_params(). + (https://github.com/cloudflare/quiche/pull/1575) + It breaks with bulding with latest(post 0.18.0) quiche. -- cmake: add feature checks for `memrchr` and `getifaddrs` + Closes #12180 - - `HAVE_MEMRCHR` for `memrchr`. - - `HAVE_GETIFADDRS` for `getifaddrs`. - This was present in `lib/curl_config.h.cmake` but missed the detection - logic. +Daniel Stenberg (11 Nov 2023) - To match existing autotools feature checks. +- Makefile: generate the VC 14.20 project files at dist-time - Closes #11954 + Follow-up to 28287092cc5a6d6ef8 (#12282) -- cmake: move global headers to specific checks + Closes #12290 - Before this patch we added standard headers unconditionally to the - global list of headers used for feature checks. This is unnecessary - and also doesn't help CMake 'Generate' performance. This patch moves - these headers to each feature check where they are actually needed. - Stop using `stddef.h`, as it seems unnecessary. +Sam James (11 Nov 2023) - I've used autotools' `m4/curl-functions.m4` to figure out these - dependencies. +- misc: fix -Walloc-size warnings - Also delete checking for the C89 standard header `time.h`, that I - missed in the earlier commit. + GCC 14 introduces a new -Walloc-size included in -Wextra which gives: - Ref: 96c29900bcec32dd6bc8e9857c8871ff4b8b8ed9 #11940 + ``` + src/tool_operate.c: In function ‘add_per_transfer’: + src/tool_operate.c:213:5: warning: allocation of insufficient size ‘1’ fo + r type ‘struct per_transfer’ with size ‘480’ [-Walloc-size] + 213 | p = calloc(sizeof(struct per_transfer), 1); + | ^ + src/var.c: In function ‘addvariable’: + src/var.c:361:5: warning: allocation of insufficient size ‘1’ for type + struct var’ with size ‘32’ [-Walloc-size] + 361 | p = calloc(sizeof(struct var), 1); + | ^ + ``` - Closes #11951 + The calloc prototype is: + ``` + void *calloc(size_t nmemb, size_t size); + ``` -- src/mkhelp: make generated code pass `checksrc` + So, just swap the number of members and size arguments to match the + prototype, as we're initialising 1 struct of size `sizeof(struct + ...)`. GCC then sees we're not doing anything wrong. - Closes #11955 + Closes #12292 -- tests: show which curl tool `runtests.pl` is using +Mark Gaiser (11 Nov 2023) - To help debugging when there is issue finding or running it. +- IPFS: bugfixes - Closes #11953 + - Fixed endianness bug in gateway file parsing + - Use IPFS_PATH in tests where IPFS_DATA was used + - Fixed typos from traling -> trailing + - Fixed broken link in IPFS.md -- CI/azure: make `MAKEFLAGS` global to parallelize all jobs + Follow-up to 859e88f6533f9e - https://dev.azure.com/daniel0244/curl/_build/results?buildId=17528 (before) - https://dev.azure.com/daniel0244/curl/_build/results?buildId=17545 (after, wi - th -j3) + Reported-by: Michael Kaufmann + Bug: https://github.com/curl/curl/pull/12152#issuecomment-1798214137 + Closes #12305 - Closes #11952 +Daniel Stenberg (11 Nov 2023) -- CI/azure: migrate old mingw MSYS1 jobs to MSYS2 +- VULN-DISCLOSURE-POLIC: remove broken link to hackerone - Also delete an accidental variable reference. + It should ideally soon not be done from hackerone anyway - Follow-up to 38029101e2d78ba125732b3bab6ec267b80a0e72 + Closes #12308 - Closes #11945 +Andrew Kurushin (11 Nov 2023) -Daniel Stenberg (26 Sep 2023) +- schannel: add CA cache support for files and memory blobs -- docs: add see also curl_multi_get_handles to some man pages + - Support CA bundle and blob caching. - Assisted-by: Jay Satiro + Cache timeout is 24 hours or can be set via CURLOPT_CA_CACHE_TIMEOUT. - Closes #11942 + Closes https://github.com/curl/curl/pull/12261 -Viktor Szakats (26 Sep 2023) +Daniel Stenberg (10 Nov 2023) -- cmake: assume `_fseeki64` and no `fseeko` on Windows +- RELEASE-NOTES: synced - `_fseeki64` is present in mingw-w64 1.0 (2011-09-26) headers, and - at least Watcom C 1.9 (2010) headers and MSVS 2008 [1]. +Charlie C (10 Nov 2023) - `fseeko` is not present in any of these. +- cmake: option to disable install & drop `curlu` target when unused - (mingw-w64 1.0 also offers `fseeko64`.) + This patch makes the following changes: + - adds the option `CURL_DISABLE_INSTALL` - to disable 'install' targets. + - Removes the target `curlu` when the option `BUILD_TESTING` is set to + `OFF` - to prevent it from being loaded in Visual Studio. - [1] https://github.com/curl/curl/pull/11944#issuecomment-1734995004 + Closes #12287 - Follow-up to 9c7165e96a3a9a2d0b7059c87c699b5ca8cdae93 #11918 +Kai Pastor (10 Nov 2023) - Closes #11950 +- cmake: fix multiple include of CURL package -- build: delete checks for C89 standard headers + Fixes errors on second `find_package(CURL)`. This is a frequent case + with transitive dependencies: + ``` + CMake Error at ...: + add_library cannot create ALIAS target "CURL::libcurl" because another + target with the same name already exists. + ``` - Delete checks and guards for standard C89 headers and assume these are - available: `stdio.h`, `string.h`, `time.h`, `setjmp.h`, `stdlib.h`, - `stddef.h`, `signal.h`. + Test to reproduce: + ```cmake + cmake_minimum_required(VERSION 3.27) # must be 3.18 or higher - Some of these we already used unconditionally, some others we only used - for feature checks. + project(curl) - Follow-up to 9c7165e96a3a9a2d0b7059c87c699b5ca8cdae93 #11918 (for `stdio.h` i - n CMake) + set(CURL_DIR "example/lib/cmake/CURL/") + find_package(CURL CONFIG REQUIRED) + find_package(CURL CONFIG REQUIRED) # fails - Closes #11940 + add_executable(main main.c) + target_link_libraries(main CURL::libcurl) + ``` -Stefan Eissing (26 Sep 2023) + Ref: https://cmake.org/cmake/help/latest/release/3.18.html#other-changes + Ref: https://cmake.org/cmake/help/v3.18/policy/CMP0107.html + Ref: #12300 + Assisted-by: Harry Mallon + Closes #11913 -- multiif.h: remove Curl_multi_dump declaration +Viktor Szakats (8 Nov 2023) - Follow-up to d850eea2 which removed the Curl_multi_dump definition. +- tidy-up: use `OPENSSL_VERSION_NUMBER` - Closes https://github.com/curl/curl/pull/11946 + Uniformly use `OPENSSL_VERSION_NUMBER` to check for OpenSSL version. + Before this patch some places used `OPENSSL_VERSION_MAJOR`. -Jay Satiro (26 Sep 2023) + Also fix `lib/md4.c`, which included `opensslconf.h`, but that doesn't + define any version number in these implementations: BoringSSL, AWS-LC, + LibreSSL, wolfSSL. (Only in mainline OpenSSL/quictls). Switch that to + `opensslv.h`. This wasn't causing a deeper problem because the code is + looking for v3, which is only provided by OpenSSL/quictls as of now. -- config-win32: define HAVE__FSEEKI64 + According to https://github.com/openssl/openssl/issues/17517, the macro + `OPENSSL_VERSION_NUMBER` is safe to use and not deprecated. - Follow-up to 9c7165e9 which added an fseeko wrapper to the lib that - calls _fseeki64 if it is available. + Reviewed-by: Marcel Raad + Closes #12298 - Closes https://github.com/curl/curl/pull/11944 +Daniel Stenberg (8 Nov 2023) -- docs: explain how PINNEDPUBLICKEY is independent of VERIFYPEER +- resolve.d: drop a multi use-sentence - - Explain that peer verification via CURLOPT_PINNEDPUBLICKEY takes place - even if peer verification via CURLOPT_SSL_VERIFYPEER is turned off. + Since the `multi:` keyword adds that message. - The behavior is verified by test2048. + Reported-by: 積丹尼 Dan Jacobson + Fixes https://github.com/curl/curl/discussions/12294 + Closes #12295 - Bug: https://github.com/curl/curl/issues/2935#issuecomment-418371872 - Reported-by: claudiusaiz@users.noreply.github.com +- content_encoding: make Curl_all_content_encodings allocless - Bug: https://github.com/curl/curl/discussions/11910 - Reported-by: Hakan Sunay Halil + - Fixes a memory leak pointed out by Coverity + - Also found by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail? + id=63947 + - Avoids unncessary allocations - Closes https://github.com/curl/curl/pull/11930 + Follow-up ad051e1cbec68b2456a22661b -Stefan Eissing (26 Sep 2023) + Closes #12289 -- openssl: improve ssl shutdown handling +Michael Kaufmann (7 Nov 2023) - - If SSL shutdown is not finished then make an additional call to - SSL_read to gather additional tracing. +- vtls: use ALPN "http/1.1" for HTTP/1.x, including HTTP/1.0 - - Fix http2 and h2-proxy filters to forward do_close() calls to the next - filter. + Some servers don't support the ALPN protocol "http/1.0" (e.g. IIS 10), + avoid it and use "http/1.1" instead. - For example h2 and SSL shutdown before and after this change: + This reverts commit df856cb5c9 (#10183). - Before: + Fixes #12259 + Closes #12285 - Curl_conn_close -> cf_hc_close -> Curl_conn_cf_discard_chain -> - ssl_cf_destroy +Daniel Stenberg (7 Nov 2023) - After: +- Makefile.am: drop vc10, vc11 and vc12 projects from dist - Curl_conn_close -> cf_hc_close -> cf_h2_close -> cf_setup_close -> - ssl_cf_close + They are end of life products. Support for generating them remain in the + repo for a while but this change drops them from distribution. - Note that currently the tracing does not show output on the connection - closure handle. Refer to discussion in #11878. + Closes #12288 - Ref: https://github.com/curl/curl/discussions/11878 +David Suter (7 Nov 2023) - Closes https://github.com/curl/curl/pull/11858 +- projects: add VC14.20 project files -Loïc Yhuel (26 Sep 2023) + Windows projects included VC14, VC14.10, VC14.30 but not VC14.20. + OpenSSL and Wolf SSL scripts mention VC14.20 so I don't see a reason why + this is missing. Updated the templates to produce a VC14.20 project. + Project opens in Visual Studio 2019 as expected. -- multi: fix small timeouts + Closes #12282 - Since Curl_timediff rounds down to the millisecond, timeouts which - expire in less than 1ms are considered as outdated and removed from the - list. We can use Curl_timediff_us instead, big timeouts could saturate - but this is not an issue. +Daniel Stenberg (7 Nov 2023) - Closes #11937 +- curl: move IPFS code into src/tool_ipfs.[ch] -Viktor Szakats (25 Sep 2023) + - convert ensure_trailing into ensure_trailing_slash + - strdup the URL string to own it proper + - use shorter variable names + - combine some expressions + - simplify error handling in ipfs_gateway() + - add MAX_GATEWAY_URL_LEN + proper bailout if maximum is reached + - ipfs-gateway.d polish and simplification + - shorten ipfs error message + make them "synthetic" -- cmake: fix stderr initialization in unity builds + Closes #12281 - Before this patch, in certain build configurations the curl tool may - not have displayed anything (debug, macOS), or crashed at startup - (debug, Windows). +Viktor Szakats (6 Nov 2023) - Follow-up to 3f8fc25720900b14b7432f4bd93407ca15311719 - Necessary after 2f17a9b654121dd1ecf4fc043c6d08a9da3522db +- build: delete support bits for obsolete Windows compilers - Closes #11929 + - Pelles C: Unclear status, failed to obtain a fresh copy a few months + ago. Possible website is HTTP-only. ~10 years ago I left this compiler + dealing with crashes and other issues with no response on the forum + for years. It has seen some activity in curl back in 2021. + - LCC: Last stable release in September 2002. + - Salford C: Misses winsock2 support, possibly abandoned? Last mentioned + in 2006. + - Borland C++: We dropped Borland C++ support in 2018. + - MS Visual C++ 6.0: Released in 1998. curl already requires VS 2010 + (or possibly 2008) as a minimum. -- cmake: fix missing `zlib.h` when compiling `libcurltool` + Closes #12222 - Came up while testing debug/testing build for Windows. I'm not sure why - it didn't come up in earlier tests with similar config. - `tool_hugehelp.c` might indeed require `zlib.h` and without linking - `CURL_LIBS` to the `curltool` target, CMake doesn't seem to add detected - dependency headers to the compiler command. +- build: delete `HAVE_STDINT_H` and `HAVE_INTTYPES_H` - ``` - [ 25%] Building C object src/CMakeFiles/curltool.dir/tool_hugehelp.c.obj - cd .../curl/bld-cmake-llvm-x64/src && /usr/local/opt/llvm/bin/clang - --target=x86_64-w64-mingw32 --sysroot=/usr/local/opt/mingw-w64/toolchain-x8 - 6_64 - -DCURLDEBUG -DCURL_STATICLIB -DHAVE_CONFIG_H -DUNICODE -DUNITTESTS -D_UNICO - DE - -I.../curl/include -I.../curl/lib -I.../curl/bld-cmake-llvm-x64/lib - -I.../curl/bld-cmake-llvm-x64/include -I.../curl/src -Wno-unused-command-li - ne-argument - -D_UCRT -DDEBUGBUILD -DHAS_ALPN -DUSE_MANUAL=1 -fuse-ld=lld -Wl,-s -static - -libgcc - -lucrt [...] -O3 -DNDEBUG -municode -MD - -MT src/CMakeFiles/curltool.dir/tool_hugehelp.c.obj - -MF CMakeFiles/curltool.dir/tool_hugehelp.c.obj.d - -o CMakeFiles/curltool.dir/tool_hugehelp.c.obj -c .../curl/bld-cmake-llvm-x - 64/src/tool_hugehelp.c - .../curl/bld-cmake-llvm-x64/src/tool_hugehelp.c:6:10: fatal error: 'zlib.h' f - ile not found - 6 | #include - | ^~~~~~~~ - ``` + We use `stdint.h` unconditionally in all places except one. These uses + are imposed by external dependencies / features. nghttp2, quic, wolfSSL + and `HAVE_MACH_ABSOLUTE_TIME` do require this C99 header. It means that + any of these features make curl require a C99 compiler. (In case of + MSVC, this means Visual Studio 2010 or newer.) - Follow-up to 39e7c22bb459c2e818f079984989a26a09741860 + This patch changes the single use of `stdint.h` guarded by + `HAVE_STDINT_H` to use `stdint.h` unconditionally. Also stop using + `inttypes.h` as an alternative there. `HAVE_INTTYPES_H` wasn't used + anywhere else, allowing to delete this feature check as well. - Closes #11927 + Closes #12275 -- cmake: fix duplicate symbols when linking tests +Daniel Stenberg (6 Nov 2023) - The linker resolves this automatically in non-unity builds. In unity - builds the linker cannot drop a single object with the duplicates, - resulting in these errors. The root issue is that we started including - certain objects both via both libcurlu and libcurltool libs. +- tool_operate: do not mix memory models - Regression from 39e7c22bb459c2e818f079984989a26a09741860 + Make sure 'inputpath' only points to memory allocated by libcurl so that + curl_free works correctly. + + Pointed out by Coverity + + Follow-up to 859e88f6533f9e1f890 + + Closes #12280 + +Stefan Eissing (6 Nov 2023) + +- lib: client writer, part 2, accounting + logging + + This PR has these changes: + + Renaming of unencode_* to cwriter, e.g. client writers + - documentation of sendf.h functions + - move max decode stack checks back to content_encoding.c + - define writer phase which was used as order before + - introduce phases for monitoring inbetween decode phases + - offering default implementations for init/write/close + + Add type paramter to client writer's do_write() + - always pass all writes through the writer stack + - writers who only care about BODY data will pass other writes unchanged + + add RAW and PROTOCOL client writers + - RAW used for Curl_debug() logging of CURLINFO_DATA_IN + - PROTOCOL used for updates to data->req.bytecount, max_filesize checks and + Curl_pgrsSetDownloadCounter() + - remove all updates of data->req.bytecount and calls to + Curl_pgrsSetDownloadCounter() and Curl_debug() from other code + - adjust test457 expected output to no longer see the excess write + + Closes #12184 + +Daniel Stenberg (6 Nov 2023) + +- VULN-DISCLOSURE-POLICY: escape sequences are not a security flaw + + Closes #12278 + +Viktor Szakats (6 Nov 2023) + +- rand: fix build error with autotools + LibreSSL + + autotools unexpectedly detects `arc4random` because it is also looking + into dependency libs. One dependency, LibreSSL, happens to publish an + `arc4random` function (via its shared lib before v3.7, also via static + lib as of v3.8.2). When trying to use this function in `lib/rand.c`, + its protoype is missing. To fix that, curl included a prototype, but + that used a C99 type without including `stdint.h`, causing: - Windows errors: ``` - [ 3%] Linking C executable unit1303.exe - [ 3%] Building C object tests/server/CMakeFiles/rtspd.dir/__/__/lib/curl_mul - tibyte.c.obj - ../../lib/libcurlu-d.a(unity_0.c.obj): In function `curlx_convert_UTF8_to_wch - ar': - C:/projects/curl/lib/curl_multibyte.c:44: multiple definition of `curlx_conve - rt_UTF8_to_wchar' - ../../src/libcurltool-d.a(unity_0.c.obj):C:/projects/curl/lib/curl_multibyte. - c:44: first defined here - ../../lib/libcurlu-d.a(unity_0.c.obj): In function `curlx_convert_wchar_to_UT - F8': - C:/projects/curl/lib/curl_multibyte.c:66: multiple definition of `curlx_conve - rt_wchar_to_UTF8' - ../../src/libcurltool-d.a(unity_0.c.obj):C:/projects/curl/lib/curl_multibyte. - c:66: first defined here - ../../lib/libcurlu-d.a(unity_0.c.obj): In function `curlx_win32_open': - C:/projects/curl/lib/curl_multibyte.c:92: multiple definition of `curlx_win32 - _open' - ../../src/libcurltool-d.a(unity_0.c.obj):C:/projects/curl/lib/curl_multibyte. - c:92: first defined here - ../../lib/libcurlu-d.a(unity_0.c.obj): In function `curlx_win32_fopen': - C:/projects/curl/lib/curl_multibyte.c:120: multiple definition of `curlx_win3 - 2_fopen' - ../../src/libcurltool-d.a(unity_0.c.obj):C:/projects/curl/lib/curl_multibyte. - c:120: first defined here - ../../lib/libcurlu-d.a(unity_0.c.obj): In function `curlx_win32_stat': - [...] + ../../lib/rand.c:37:1: error: unknown type name 'uint32_t' + 37 | uint32_t arc4random(void); + | ^ + 1 error generated. ``` - Ref: https://ci.appveyor.com/project/curlorg/curl/builds/48110107/job/nvlhpt9 - aa4ehny5q#L247 - macOS errors: - ``` - [ 56%] Linking C executable unit1302 - duplicate symbol '_curlx_sotouz' in: - ../../lib/libcurlu.a(unity_0_c.c.o) - ../../src/libcurltool.a(unity_0_c.c.o) - duplicate symbol '_curlx_sitouz' in: - ../../lib/libcurlu.a(unity_0_c.c.o) - ../../src/libcurltool.a(unity_0_c.c.o) - duplicate symbol '_curlx_uztosz' in: - ../../lib/libcurlu.a(unity_0_c.c.o) - ../../src/libcurltool.a(unity_0_c.c.o) - [...] - ``` - with config: - ``` - -DCMAKE_UNITY_BUILD=ON \ - -DENABLE_DEBUG=ON -DBUILD_TESTING=ON -DCMAKE_C_FLAGS=-DDEBUGBUILD \ - -DBUILD_SHARED_LIBS=ON \ - -DBUILD_STATIC_LIBS=OFF - ``` + This patch improves this by dropping the local prototype and instead + limiting `arc4random` use for non-OpenSSL builds. OpenSSL builds provide + their own random source anyway. - Closes #11926 + The better fix would be to teach autotools to not link dependency libs + while detecting `arc4random`. -- cmake: lib `CURL_STATICLIB` fixes (Windows) + LibreSSL publishing a non-namespaced `arc4random` tracked here: + https://github.com/libressl/portable/issues/928 - - always define `CURL_STATICLIB` when building libcurl for Windows. + Regression from 755ddbe901cd0c921fbc3ac5b3775c0dc683bc73 #10672 - This disables `__declspec(dllexport)` for exported libcurl symbols. - In normal mode (hide symbols) these exported symbols are specified - via `libcurl.def`. When not hiding symbols, all symbols are exported - by default. + Reviewed-by: Daniel Stenberg + Fixes #12257 + Closes #12274 - Regression from 1199308dbc902c52be67fc805c72dd2582520d30 +Daniel Stenberg (5 Nov 2023) - Fixes #11844 +- RELEASE-NOTES: synced - - fix to omit `libcurl.def` when not hiding private symbols. +- strdup: do Curl_strndup without strncpy - Regression from 2ebc74c36a19a1700af394c16855ce144d9878e3 + To avoid (false positive) gcc-13 compiler warnings. - - fix `ENABLED_DEBUG=ON` + shared curl tool Windows builds by also - omitting `libcurl.def` in this case, and exporting all symbols - instead. This ensures that a shared curl tool can access all debug - functions which are not normally exported from libcurl DLL. + Follow-up to 4855debd8a2c1cb - - delete `INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB"` for "objects" - target. + Assisted-by: Jay Satiro + Reported-by: Viktor Szakats + Fixes #12258 - Follow-up to 2ebc74c36a19a1700af394c16855ce144d9878e3 +Enno Boland (5 Nov 2023) - - delete duplicate `BUILDING_LIBCURL` definitions. +- HTTP: fix empty-body warning - - fix `HIDES_CURL_PRIVATE_SYMBOLS` to not overwrite earlier build settings. + This change fixes a compiler warning with gcc-12.2.0 when + `-DCURL_DISABLE_BEARER_AUTH=ON` is used. - Follow-up to 1199308dbc902c52be67fc805c72dd2582520d30 + /home/tox/src/curl/lib/http.c: In function 'Curl_http_input_auth': + /home/tox/src/curl/lib/http.c:1147:12: warning: suggest braces around emp + ty body in an 'else' statement [-Wempty-body] + 1147 | ; + | ^ - Closes #11914 + Closes #12262 -Daniel Stenberg (25 Sep 2023) +Daniel Stenberg (5 Nov 2023) -- RELEASE-NOTES: synced +- openssl: identify the "quictls" backend correctly -Dan Fandrich (25 Sep 2023) + Since vanilla OpenSSL does not support the QUIC API I think it helps + users to identify the correct OpenSSL fork in version output. The best + (crude) way to do that right now seems to be to check if ngtcp2 support + is enabled. -- tests: fix log directory path in IPFS tests + Closes #12270 - Hard-coding the log directory name fails with parallel tests. +Mark Gaiser (5 Nov 2023) - Follow-up to 65b563a96 +- curl: improved IPFS and IPNS URL support - Ref: #8805 + Previously just ipfs:// and ipns:// was supported, which is + too strict for some usecases. -Daniel Stenberg (25 Sep 2023) + This patch allows paths and query arguments to be used too. + Making this work according to normal http semantics: -- curl_multi_get_handles: get easy handles from a multi handle + ipfs:///foo/bar?key=val + ipns:///foo/bar?key=val - Closes #11750 + The gateway url support is changed. + It now only supports gateways in the form of: -Stefan Eissing (25 Sep 2023) + http:///foo/bar + http:// -- http: h1/h2 proxy unification + Query arguments here are explicitly not allowed and trigger an intended + malformed url error. - - use shared code for setting up the CONNECT request - when tunneling, used in HTTP/1.x and HTTP/2 proxying - - eliminate use of Curl_buffer_send() and other manipulations - of `data->req` or `data->state.ulbuf` + There also was a crash when IPFS_PATH was set with a non trailing + forward slash. This has been fixed. - Closes #11808 + Lastly, a load of test cases have been added to verify the above. -Natanael Copa (25 Sep 2023) + Reported-by: Steven Allen + Fixes #12148 + Closes #12152 -- lib: use wrapper for curl_mime_data fseek callback +Harry Mallon (5 Nov 2023) - fseek uses long offset which does not match with curl_off_t. This leads - to undefined behavior when calling the callback and caused failure on - arm 32 bit. +- docs: KNOWN_BUGS cleanup - Use a wrapper to solve this and use fseeko which uses off_t instead of - long. + * Remove other mention of hyper memory-leaks from `KNOWN_BUGS`. + Should have been removed in 629723ecf22a8eae78d64cceec2f3bdae703ec95 - Thanks to the nice people at Libera IRC #musl for helping finding this - out. + * Remove mention of aws-sigv4 sort query string from `KNOWN_BUGS`. + Fixed in #11806 - Fixes #11882 - Fixes #11900 - Closes #11918 + * Remove mention of aws-sigv4 query empty value problems -- configure: sort AC_CHECK_FUNCS + * Remove mention of aws-sigv4 missing amz-content-sha256 + Fixed in #9995 - No functional changes. +- http_aws_sigv4: canonicalise valueless query params -Daniel Stenberg (25 Sep 2023) + Fixes #8107 + Closes #12244 -- warnless: remove unused functions +Michael Kaufmann (4 Nov 2023) - Previously put there for use with the intel compiler +- docs: preserve the modification date when copying the prebuilt man page - Closes #11932 + The previously built man page "curl.1" must be copied with the original + modification date, otherwise the man page is never updated. -- GHA/linux: run singleuse to detect single-use global functions + This fixes a bug that has been introduced with commit 2568441cab. - Use --unit for configure --enable-debug builds + Reviewed-by: Dan Fandrich + Reviewed-by: Daniel Stenberg - Closes #11932 + Closes #12199 -- singleuse: add scan for use in other source codes +Daniel Stenberg (4 Nov 2023) - This should reduce false-positive to almost zero. Checks for presence in - unit tests if --unit is specified, which is intended for debug builds - where unit testing is enabled. +- docs: remove bold from some man page SYNOPSIS sections - Closes #11932 + In the name of consistency -- multi: remove Curl_multi_dump + Closes #12267 - A debug-only function that is basically never used. Removed to ease the - use of the singleuse script to detect non-static functions not used - outside the file where it is defined. +- openssl: two multi pointer checks should probably rather be asserts - Closes #11931 + ... so add the asserts now and consider removing the dynamic checks in a + future. -Viktor Szakats (24 Sep 2023) + Ref: #12261 + Closes #12264 -- tests: fix compiler warnings +boilingoden (4 Nov 2023) - Seen with llvm 17 on Windows x64. +- docs: add supported version for the json write-out - ``` - .../curl/tests/server/rtspd.c:136:13: warning: no previous extern declaration - for non-static variable 'logdir' [-Wmissing-variable-declarations] - 136 | const char *logdir = "log"; - | ^ - .../curl/tests/server/rtspd.c:136:7: note: declare 'static' if the variable i - s not intended to be used outside of this translation unit - 136 | const char *logdir = "log"; - | ^ - .../curl/tests/server/rtspd.c:137:6: warning: no previous extern declaration - for non-static variable 'loglockfile' [-Wmissing-variable-declarations] - 137 | char loglockfile[256]; - | ^ - .../curl/tests/server/rtspd.c:137:1: note: declare 'static' if the variable i - s not intended to be used outside of this translation unit - 137 | char loglockfile[256]; - | ^ - .../curl/tests/server/fake_ntlm.c:43:13: warning: no previous extern declarat - ion for non-static variable 'logdir' [-Wmissing-variable-declarations] - 43 | const char *logdir = "log"; - | ^ - .../curl/tests/server/fake_ntlm.c:43:7: note: declare 'static' if the variabl - e is not intended to be used outside of this translation unit - 43 | const char *logdir = "log"; - | ^ - .../curl/src/tool_doswin.c:350:8: warning: possible misuse of comma operator - here [-Wcomma] - 350 | ++d, ++s; - | ^ - .../curl/src/tool_doswin.c:350:5: note: cast expression to void to silence wa - rning - 350 | ++d, ++s; - | ^~~ - | (void)( ) - ``` + xref: https://curl.se/changes.html#7_70_0 - ``` - .../curl/tests/libtest/lib540.c:146:27: warning: result of comparison 'long' - > 2147483647 is always false [-Wtautological-type-limit-compare] - 146 | int itimeout = (L > (long)INT_MAX) ? INT_MAX : (int)L; - | ~ ^ ~~~~~~~~~~~~~ - 1 warning generated. + Closes #12266 - .../curl/tests/libtest/libntlmconnect.c:195:31: warning: result of comparison - 'long' > 2147483647 is always false [-Wtautological-type-limit-compare] - 195 | int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeo - ut; - | ~~~~~~~ ^ ~~~~~~~~~~~~~ - 1 warning generated. +Viktor Szakats (3 Nov 2023) - .../curl/tests/libtest/lib591.c:117:31: warning: result of comparison 'long' - > 2147483647 is always false [-Wtautological-type-limit-compare] - 117 | int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeo - ut; - | ~~~~~~~ ^ ~~~~~~~~~~~~~ - 1 warning generated. - .../curl/tests/libtest/lib597.c:99:31: warning: result of comparison 'long' > - 2147483647 is always false [-Wtautological-type-limit-compare] - 99 | int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeo - ut; - | ~~~~~~~ ^ ~~~~~~~~~~~~~ - 1 warning generated. - ``` +- appveyor: make VS2008-built curl tool runnable - Seen on macOS Intel: - ``` - .../curl/tests/server/sws.c:440:64: warning: field precision should have type - 'int', but argument has type 'size_t' (aka 'unsigned long') [-Wformat] - msnprintf(logbuf, sizeof(logbuf), "Got request: %s %.*s HTTP/%d.%d" - , - ~~^~ - 1 warning generated. - ``` + By linking the CRT statically. This avoids the error about missing + runtime DLL `MSVCR90.dll` when running the freshly built `curl.exe`. - Closes #11925 + Closes #12263 -Jay Satiro (24 Sep 2023) +Stefan Eissing (3 Nov 2023) -- url: fix netrc info message +- url: proxy ssl connection reuse fix - - Fix netrc info message to use the generic ".netrc" filename if the - user did not specify a netrc location. + - tunnel https proxy used for http: transfers does + no check if proxy-ssl configuration matches + - test cases added, test_10_12 fails on 8.4.0 - - Update --netrc doc to add that recent versions of curl on Windows - prefer .netrc over _netrc. + Closes #12255 + +Jay Satiro (3 Nov 2023) + +- curl_sspi: support more revocation error names in error messages + + - Add these revocation errors to sspi error list: + CRYPT_E_NO_REVOCATION_DLL, CRYPT_E_NO_REVOCATION_CHECK, + CRYPT_E_REVOCATION_OFFLINE and CRYPT_E_NOT_IN_REVOCATION_DATABASE. + + Prior to this change those error codes were not matched to their macro + name and instead shown as "unknown error". Before: - * Couldn't find host google.com in the (nil) file; using defaults + + schannel: next InitializeSecurityContext failed: + Unknown error (0x80092013) - The revocation function was + unable to check revocation because the revocation server was offline. After: - * Couldn't find host google.com in the .netrc file; using defaults - Closes https://github.com/curl/curl/pull/11904 + schannel: next InitializeSecurityContext failed: + CRYPT_E_REVOCATION_OFFLINE (0x80092013) - The revocation function was + unable to check revocation because the revocation server was offline. -Dan Fandrich (23 Sep 2023) + Bug: https://github.com/curl/curl/issues/12239 + Reported-by: Niracler Li -- wolfssh: do cleanup in Curl_ssh_cleanup + Closes https://github.com/curl/curl/pull/12241 - Closes: #11921 +- strdup: don't allow Curl_strndup to read past a null terminator -Daniel Stenberg (24 Sep 2023) + - Use malloc + strncpy instead of Curl_memdup to dupe the string before + null terminating it. -- tool_listhelp: regenerated + Prior to this change if Curl_strndup was passed a length longer than + the allocated string then it could copy out of bounds. - Polished the --ipfs-gateway description + This change is for posterity. Curl_strndup was added in the parent + commit and currently none of the calls to it pass a length that would + cause it to read past the allocated length of the input. - Fixed the --trace-config description + Follow-up to d3b3ba35. - The script also fixed some other small mistakes + Closes https://github.com/curl/curl/pull/12254 - Closes #11923 +Daniel Stenberg (2 Nov 2023) -Viktor Szakats (23 Sep 2023) +- lib: add and use Curl_strndup() -- Makefile.mk: always set `CURL_STATICLIB` for lib (Windows) + The Curl_strndup() function is similar to memdup(), but copies 'n' bytes + then adds a terminating null byte ('\0'). - Also fix to export all symbols in Windows debug builds, making - `-debug-dyn` builds work with `-DCURL_STATICLIB` set. + Closes #12251 - Ref: https://github.com/curl/curl/pull/11914 (same for CMake) +- CURPOST_POSTFIELDS.3: add CURLOPT_COPYPOSTFIELDS in SEE ALSO - Closes #11924 +Stefan Eissing (2 Nov 2023) -Daniel Stenberg (23 Sep 2023) +- pytest: use lower count in repeat tests -- quic: set ciphers/curves the same way regular TLS does + - lower large iteration counts in some tests somewhat for + the same coverage with less duration - for OpenSSL/BoringSSL + Closes #12248 - Fixes #11796 - Reported-by: Karthikdasari0423 on github - Assisted-by: Jay Satiro - Closes #11836 +Daniel Stenberg (2 Nov 2023) -- test457: verify --max-filesize with chunked encoding +- RELEASE-NOTES: synced -- lib: let the max filesize option stop too big transfers too +- docs: clarify that curl passes on input unfiltered - Previously it would only stop them from getting started if the size is - known to be too big then. + ... for several options. - Update the libcurl and curl docs accordingly. + Reported-by: Ophir Lojkine - Fixes #11810 - Reported-by: Elliot Killick - Assisted-by: Jay Satiro - Closes #11820 + Closes #12249 -Viktor Szakats (23 Sep 2023) +- urlapi: when URL encoding the fragment, pass in the right length -- mingw: delete support for legacy mingw.org toolchain + A benign bug because it would only add an extra null terminator. - Drop support for "old" / "legacy" / "classic" / "v1" / "mingw32" MinGW: - https://en.wikipedia.org/wiki/MinGW, https://osdn.net/projects/mingw/ - Its homepage used to be http://mingw.org/ [no HTTPS], and broken now. - It supported the x86 CPU only and used a old Windows API header and - implib set, often causing issues. It also misses most modern Windows - features, offering old versions of both binutils and gcc (no llvm/clang - support). It was last updated 2 years ago. + Made lib1560 get a test that runs this code. - curl now relies on toolchains based on the mingw-w64 project: - https://www.mingw-w64.org/ https://sourceforge.net/projects/mingw-w64/ - https://www.msys2.org/ https://github.com/msys2/msys2 - https://github.com/mstorsjo/llvm-mingw - (Also available via Linux and macOS package managers.) + Closes #12250 - Closes #11625 +Stefan Eissing (2 Nov 2023) -Mark Gaiser (23 Sep 2023) +- vtls: late clone of connection ssl config -- curl: add support for the IPFS protocols: + - perform connection cache matching against `data->set.ssl.primary` + and proxy counterpart + - fully clone connection ssl config only when connection is used - - ipfs:// - - ipns:// + Closes #12237 - This allows you tu use ipfs in curl like: - curl ipfs:// - and - curl ipns:// +- msh3: error when built with CURL_DISABLE_SOCKETPAIR set - For more information consult the readme at: - https://curl.se/docs/ipfs.html + Reported-by: Gisle Vanem + Closes #12252 + Fixes #12213 - Closes #8805 +Daniel Stenberg (2 Nov 2023) -Daniel Stenberg (23 Sep 2023) +- hsts: skip single-dot hostname -- bufq: remove Curl_bufq_skip_and_shift (unused) + Reported-by: Maksymilian Arciemowicz - Closes #11915 + Closes #12247 -- scripts/singleuse.pl: add curl_global_trace +- vtls: fix build without proxy -Viktor Szakats (22 Sep 2023) + Follow-up to bf0e278a3c54bc7fee7360da17c -- cmake: fix unity symbol collisions in h2 builds + closes #12243 - Regression from 331b89a319d0067fa1e6441719307cfef9c7960f +- docs/example/keepalive.c: show TCP keep-alive options - Reviewed-by: Daniel Stenberg - Reviewed-by: Jay Satiro - Closes #11912 + Closes #12242 -Daniel Stenberg (22 Sep 2023) +- lib1560: verify appending blank URL encoded query string -- RELEASE-NOTES: synced +- urlapi: skip appending NULL pointer query -Dan Fandrich (21 Sep 2023) + Reported-by: kirbyn17 on hackerone -- github/labeler: improve the match patterns + Closes #12240 - This includes new rules for setting the appleOS and logging labels and - matches on some example files. Also, enable dot mode for wildcard - matches in the .github directory. +- lib1560: verify setting host to "" with and without URL encode -Daniel Stenberg (21 Sep 2023) +- urlapi: avoid null deref if setting blank host to url encode -- upload-file.d: describe the file name slash/backslash handling + Reported-by: kirbyn17 on hackerone - Closes #11911 + Closes #12240 -Jakub Jelen (21 Sep 2023) +- dynbuf: assert for NULL pointer inputs -- libssh: cap SFTP packet size sent + Help us catch more mistakes. - Due to libssh limitations + Closes #12238 - Signed-off-by: Jakub Jelen +- HTTP3: ngtcp2 builds are no longer experimental - Closes #11804 + The other HTTP/3 backends are still experimental. -Daniel Stenberg (21 Sep 2023) + Closes #12235 -- curl.h: mark CURLSSLBACKEND_NSS as deprecated since 8.3.0 +Stefan Eissing (31 Oct 2023) - Closes #11905 +- vtls: cleanup SSL config management -- mailmap: unify Michael Osipov under a single email + - remove `Curl_ssl_get_config()`, no longer needed -Ted Lyngmo (21 Sep 2023) + Closes #12204 -- docs: use CURLSSLBACKEND_NONE +Daniel Stenberg (31 Oct 2023) - [ssl] use CURLSSLBACKEND_NONE instead of (curl_sslbackend)-1 in - documentation and examples. +- libcurl-thread.3: simplify the TLS section - Signed-off-by: Ted Lyngmo + All TLS libraries curl can use are threadsafe since OpenSSL 1.1.x, August + 2016. - Closes #11909 + Closes #12233 -Dan Fandrich (21 Sep 2023) +- configure: better --disable-http -- github/labeler: give the sync-labels config item a default value + - disable HTTPS-proxy as well, since it can't work without HTTP - This shouldn't be necessary and is likely a bug with this beta version - of the labeller. + - curl_setup: when HTTP is disabled, also disable all features that are + HTTP-only - Also, fix the negative matches for the documentation label. + - version: HTTPS-proxy only exists if HTTP support exists - Follow-up to dd12b452a - Closes #11907 + Closes #12223 -- github/labeler: fix up more the labeler config format +- http: consider resume with CURLOPT_FAILONERRROR and 416 to be fine - The new version didn't like the workaround we had for a bug in the - previous labeler version, and it should no longer be needed. + Finding a 'Content-Range:' in the response changed the handling. - Follow-up to dd12b452a - Closes #11906 + Add test case 1475 to verify -C - with 416 and Content-Range: header, + which is almost exactly like test 194 which instead uses a fixed -C + offset. Adjusted test 194 to also be considered fine. -- github/labeler: fix indenting to try to appease labeller + Fixes #10521 + Reported-by: Smackd0wn + Fixes #12174 + Reported-by: Anubhav Rai + Closes #12176 - Follow-up to dd12b452a +Stefan Eissing (30 Oct 2023) -Jay Satiro (21 Sep 2023) +- GHA: fix checkout of quictls repository to use correct branch name -- libssh2: fix error message on failed pubkey-from-file + Follow-up to c868b0e30f10cd0ac7 - - If libssh2_userauth_publickey_fromfile_ex returns -1 then show error - message "SSH public key authentication failed: Reason unknown (-1)". + Closes #12232 - When libssh2_userauth_publickey_fromfile_ex returns -1 it does so as a - generic error and therefore doesn't set an error message. AFAICT that is - not documented behavior. +Daniel Stenberg (30 Oct 2023) - Prior to this change libcurl retrieved the last set error message which - would be from a previous function failing. That resulted in misleading - auth failed error messages in verbose mode. +- docs/example/localport.c: show off CURLOPT_LOCALPORT - Bug: https://github.com/curl/curl/issues/11837#issue-1891827355 - Reported-by: consulion@users.noreply.github.com + Closes #12230 - Closes https://github.com/curl/curl/pull/11881 +- docs/examples/interface.c: show CURLOPT_INTERFACE use -Stefan Eissing (21 Sep 2023) + Although super simple. -- pytest: exclude test_03_goaway in CI runs due to timing dependency + Closes #12229 - Closes #11860 +Viktor Szakats (30 Oct 2023) -- lib: disambiguate Curl_client_write flag semantics +- build: fix compiler warning with auths disabled - - use CLIENTWRITE_BODY *only* when data is actually body data - - add CLIENTWRITE_INFO for meta data that is *not* a HEADER - - debug assertions that BODY/INFO/HEADER is not used mixed - - move `data->set.include_header` check into Curl_client_write - so protocol handlers no longer have to care - - add special in FTP for `data->set.include_header` for historic, - backward compatible reasons - - move unpausing of client writes from easy.c to sendf.c, so that - code is in one place and can forward flags correctly + ``` + ./curl/lib/http.c:979:12: warning: unused function 'is_valid_auth_separator' + [-Wunused-function] + static int is_valid_auth_separator(char ch) + ^ + 5 warnings generated. + ``` - Closes #11885 + Follow-up to e92edfbef64448ef461117769881f3ed776dec4e #11490 -Patrick Monnerat (21 Sep 2023) + Closes #12227 -- tftpd: always use curl's own tftp.h +- build: require Windows XP or newer - Using the system's provided arpa/tftp.h and optimizing, GCC 12 detects - and reports a stringop-overread warning: + After this patch we assume availability of `getaddrinfo` and + `freeaddrinfo`, first introduced in Windows XP. Meaning curl + now requires building for Windows XP as a minimum. - tftpd.c: In function ‘write_behind.isra’: - tftpd.c:485:12: warning: ‘write’ reading between 1 and 2147483647 bytes f - rom a region of size 0 [-Wstringop-overread] - 485 | return write(test->ofile, writebuf, count); - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - In file included from tftpd.c:71: - /usr/include/arpa/tftp.h:58:30: note: source object ‘tu_data’ of size 0 - 58 | char tu_data[0]; /* data or error stri - ng */ - | ^~~~~~~ + TODO: assume these also in autotools. - This occurs because writebuf points to this field and the latter - cannot be considered as being of dynamic length because it is not - the last field in the structure. Thus it is bound to its declared - size. + Ref: https://github.com/curl/curl/pull/12221#issuecomment-1783761806 + Closes #12225 - This commit always uses curl's own version of tftp.h where the - target field is last in its structure, effectively avoiding the - warning. +- appveyor: bump one job to OpenSSL 3.1 (was 1.1.1) - As HAVE_ARPA_TFTP_H is not used anymore, cmake/configure checks for - arpa/tftp.h are removed. + Use 3.1 with the modern runner image. - Closes #11897 + We still use 1.1.1 in 8 jobs. -Dan Fandrich (20 Sep 2023) + 1.1.1 is EOL since 2023-09-11: + https://www.openssl.org/blog/blog/2023/03/28/1.1.1-EOL/ -- test1474: make precheck more robust on non-Solaris systems + Also: + - add missing SSL-backend to job descriptions. + - tidy up CPU in job descriptions. - If uname -r returns something odd, perl could return an error code and - the test would be erroneously skipped. The qx// syntax avoid this. + Closes #12226 - Followup to 08f9b2148 +Daniel Stenberg (30 Oct 2023) -- github/labeler: switch to the 5 beta version +- RELEASE-NOTES: synced - This version adds an important feature that will allow more PRs to be - labelled. Rather than being limited to labeling PRs with files that - match a single glob, it can now label them if multiple changed files - match any one of a number of globs. +- GHA: bump ngtcp2, nghttp3, nghttp2 and quictls versions -Daniel Stenberg (20 Sep 2023) + ngtcp2 1.0.1 + nghttp3 1.0.0 + nghttp2 1.58.0 + quictls 3.1.4+quic -- lib: enable hmac for digest as well + also sync HTTP3.md with these changes - Previously a build that disabled NTLM and aws-sigv4 would fail to build - since the hmac was disabled, but it is also needed for digest auth. + Closes #12132 - Follow-up to e92edfbef64448ef +Kareem (29 Oct 2023) - Fixes #11890 - Reported-by: Aleksander Mazur - Closes #11896 +- wolfssl: add default case for wolfssl_connect_step1 switch -- idn: if idn2_check_version returns NULL, return error + Closes #12218 - ... this avoids a NULL dereference for this unusual case. +Jay Satiro (29 Oct 2023) - Reported-by: s0urc3_ on hackerone - Closes #11898 +- curl_setup: disallow Windows IPv6 builds missing getaddrinfo -- http: fix CURL_DISABLE_BEARER_AUTH breakage + - On Windows if IPv6 is enabled but getaddrinfo is missing then #error + the build. - When bearer auth was disabled, the if/else logic got wrong and caused - problems. + curl can be built with IPv6 support (ENABLE_IPV6) but without the + ability to resolve hosts to IPv6 addresses (HAVE_GETADDRINFO). On + Windows this is highly unlikely and should be considered a bad build + configuration. - Follow-up to e92edfbef64448ef461 - Fixes #11892 - Reported-by: Aleksander Mazur - Closes #11895 + Such a bad configuration has already given us a bug that was hard to + diagnose. See #12134 and #12136 for discussion. -Michael Osipov (20 Sep 2023) + Ref: https://github.com/curl/curl/issues/12134 + Ref: https://github.com/curl/curl/pull/12136 -- wolfssl: allow capath with CURLOPT_CAINFO_BLOB + Closes https://github.com/curl/curl/pull/12221 - Remain consistent with OpenSSL. While CAfile is nulled as documented - with CURLOPT_CAINFO_BLOB, CApath remains intact. +Nico Rieck (29 Oct 2023) - Closes #11886 +- openssl: make CURLSSLOPT_NATIVE_CA import Windows intermediate CAs -- wolfssl: use ssl_cafile/ssl_capath variables consistent with openssl.c + - If CURLSSLOPT_NATIVE_CA on Windows then import from intermediate CA + "CA" store after importing from root CA "ROOT" store. - Closes #11886 + This change allows curl to work in situations where a server does not + send all intermediate certs and they are present in the "CA" store (the + store with intermediate CAs). This is already allowed by the Schannel + backend. -Dan Fandrich (19 Sep 2023) + Also this change makes partial chain verification possible for those + certs since we allow partial chain verification by default for OpenSSL + (unless CURLSSLOPT_NO_PARTIALCHAIN). This is not allowed by the Schannel + backend. -- test1474: disable test on NetBSD, OpenBSD and Solaris 10 + Prior to this change CURLSSLOPT_NATIVE_CA only imported "ROOT" certs. - These kernels only send a fraction of the requested amount of the first - large block, invalidating the assumptions of the test and causing it to - fail. + Fixes https://github.com/curl/curl/issues/12155 + Closes https://github.com/curl/curl/pull/12185 - Assisted-by: Christian Weisgerber - Ref: https://curl.se/mail/lib-2023-09/0021.html - Closes #11888 +Viktor Szakats (28 Oct 2023) -Ryan Schmidt (20 Sep 2023) +- Makefile.mk: fix `-rtmp` option for non-Windows [ci skip] -- cmake, configure: also link with CoreServices +Daniel Stenberg (28 Oct 2023) - When linking with CoreFoundation, also link with CoreServices which is - apparently required to avoid an NSInvalidArgumentException in software - linking with libcurl on macOS Sonoma 14 and later. +- asyn-ares: handle no connection in the addrinfo callback - Fixes #11893 - Closes #11894 + To avoid crashing. -Marc Hoersken (19 Sep 2023) + Follow-up from 56a4db2 + Closes #12219 -- CI/azure: remove pip, wheel, cryptography, pyopenssl and impacket +Jay Satiro (28 Oct 2023) - These dependencies are now already included in the Docker image. +- hostip6: fix DEBUG_ADDRINFO builds - Ref: https://github.com/mback2k/curl-docker-winbuildenv/commit/2607a31bcab544 - b41d15606e97f38cf312c1ce56 + - Removed unused and incorrect parameter from dump_addrinfo(). - Closes #11889 + Bug: https://github.com/curl/curl/commit/56a4db2e#commitcomment-131050442 + Reported-by: Gisle Vanem -Daniel Stenberg (19 Sep 2023) + Closes https://github.com/curl/curl/pull/12212 -- wolfssl: if CURLOPT_CAINFO_BLOB is set, ignore the CA files +Viktor Szakats (28 Oct 2023) - Ref: #11883 - Reported-by: Michael Osipov - Closes #11884 +- Makefile.mk: restore `_mingw.h` for default `_WIN32_WINNT` -- RELEASE-NOTES: synced + In 8.4.0 we deleted `_mingw.h` as part of purging old-mingw support. + Turns out `_mingw.h` had the side-effect of setting a default + `_WIN32_WINNT` value expected by `lib/config-win32.h` to enable + `getaddrinfo` support in `Makefile.mk` mingw-w64 builds. This caused + disabling support for this unless specifying the value manually. -- test3103: CURLOPT_COOKIELIST test + Restore this header and update its comment to tell why we continue + to need it. -- cookie: set ->running in cookie_init even if data is NULL + This triggered a regression in official Windows curl builds starting + with 8.4.0_1. Fixed in 8.4.0_6. (8.5.0 will be using CMake.) - This is a regression introduced in b1b326ec500 (shipped in curl 8.1.0) + Regression from 38029101e2d78ba125732b3bab6ec267b80a0e72 #11625 - Test 3103 verifies. + Reported-by: zhengqwe on github + Helped-by: Nico Rieck + Fixes #12134 + Fixes #12136 + Closes #12217 - Fixes #11875 - Reported-by: wangp on github - Closes #11876 +- hostip: silence compiler warning `-Wparentheses-equality` -- test498: total header size for all redirects is larger than accepted + Seen with LLVM 17. -- http: use per-request counter to check too large headers + ``` + hostip.c:1336:22: warning: equality comparison with extraneous parentheses [- + Wparentheses-equality] + 1336 | (a->ai_family == PF_INET)) { + | ~~~~~~~~~~~~~^~~~~~~~~~ + hostip.c:1336:22: note: remove extraneous parentheses around the comparison t + o silence this warning + 1336 | (a->ai_family == PF_INET)) { + | ~ ^ ~ + hostip.c:1336:22: note: use '=' to turn this equality comparison into an assi + gnment + 1336 | (a->ai_family == PF_INET)) { + | ^~ + | = + 1 warning generated. + ``` - Not the counter that accumulates all headers over all redirects. + Follow-up to b651aba0962bb31353f55de4dc35f745952a1b10 #12145 - Follow-up to 3ee79c1674fd6 + Reviewed-by: Daniel Stenberg + Closes #12215 - Do a second check for 20 times the limit for the accumulated size for - all headers. +Stefan Eissing (27 Oct 2023) - Fixes #11871 - Reported-by: Joshix-1 on github - Closes #11872 +- doh: use PIPEWAIT when HTTP/2 is attempted -Jay Satiro (18 Sep 2023) + Closes #12214 -- THANKS: add Eric Murphy +Daniel Stenberg (27 Oct 2023) - He reported #11850 (quiche build error) but I forgot to add a - 'reported-by' entry in the fix 267e14f1. +- setopt: remove outdated cookie comment -Daniel Stenberg (18 Sep 2023) + Closes #12206 -- h2-proxy: remove left-over mistake in drain_tunnel() +Stefan Eissing (27 Oct 2023) - Left-over from 331b89a319 +- cfilter: provide call to tell connection to forget a socket - Reported-by: 南宫雪珊 + - fixed libssh.c workaround for a socket being closed by + the library + - eliminate the terrible hack in cf-socket.c to guess when + this happened and try not closing the socket again. + - fixes race in eyeballing when socket could have failed to + be closed for a discarded connect attempt - Closes https://github.com/curl/curl/pull/11877 + Closes #12207 -vvb2060 (18 Sep 2023) +- url: protocol handler lookup tidy-up -- lib: failf/infof compiler warnings + - rename lookup to what it does + - use ARRAYSIZE instead of NULL check for end + - offer alternate lookup for 0-terminated strings - Closes #11874 + Closes #12216 -Daniel Stenberg (17 Sep 2023) +Viktor Szakats (27 Oct 2023) -- rand: fix 'alnum': array is too small to include a terminating null character +- build: variadic macro tidy-ups - It was that small on purpose, but this change now adds the null byte to - avoid the error. + - delete unused `HAVE_VARIADIC_MACROS_C99/GCC` feature checks. + (both autotools and CMake.) + - delete duplicate `NULL` check in `Curl_trc_cf_infof()`. + - fix compiler warning in `CURL_DISABLE_VERBOSE_STRINGS` builds. + ``` + ./lib/cf-socket.c:122:41: warning: unused parameter 'data' [-Wunused-parame + ter] + static void nosigpipe(struct Curl_easy *data, + ^ + ``` + - fix `#ifdef` comments in `lib/curl_trc.{c,h}`. + - fix indentation in some `infof()` calls. - Follow-up to 3aa3cc9b052353b1 + Follow-up to dac293cfb7026b1ca4175d88b80f1432d3d3c684 #12167 - Reported-by: Dan Fandrich - Ref: #11838 - Closes #11870 + Cherry-picked from #12105 + Closes #12210 -Mathias Fuchs (16 Sep 2023) +- cmake: speed up threads setup for Windows -- cmake: fix the help text to the static build option in CMakeLists.txt + Win32 threads are always available. We enabled them unconditionally + (with `ENABLE_THREADED_RESOLVER`). CMake built-in thread detection + logic has this condition hard-coded for Windows as well (since at least + 2007). - Closes #11843 + Instead of doing all the work of detecting pthread combinations on + Windows, then discarding those results, skip these efforts and assume + built-in thread support when building for Windows. -John Haugabook (16 Sep 2023) + This saves 1-3 slow CMake configuration steps. -- MANUAL.md: change domain to example.com + Reviewed-by: Daniel Stenberg + Closes #12202 - Closes #11866 +- cmake: speed up zstd detection -Daniel Stenberg (16 Sep 2023) + Before this patch we detected the presence of a specific zstd API to + see if we can use the library. zstd published that API in its first + stable release: v1.0.0 (2016-08-31). -- doh: inherit DEBUGFUNCTION/DATA + Replace that method by detecting the zstd library version instead and + accepting if it's v1.0.0 or newer. Also display this detected version + and display a warning if the zstd found is unfit for curl. - When creating new transfers for doing DoH, they now inherit the debug - settings from the initiating transfer, so that the application can - redirect and handle the verbose output correctly even for the DoH - transfers. + We use the same version detection method as zstd itself, via its public + C header. - Reported-by: calvin2021y on github - Fixes #11864 - Closes #11869 + This deviates from autotools which keeps using the slow method of + looking for the API by building a test program. The outcome is the same + as long as zstd keeps offering this API. -Dan Fandrich (16 Sep 2023) + Ref: https://github.com/facebook/zstd/commit/5a0c8e24395079f8e8cdc90aa1659cd5 + ab1b7427 (2016-08-12, committed) + Ref: https://github.com/facebook/zstd/releases/tag/v0.8.1 (2016-08-18, first + released) + Ref: https://github.com/facebook/zstd/releases/tag/v1.0.0 -- http_aws_sigv4: fix sorting with empty parts + Reviewed-by: Daniel Stenberg + Closes #12200 - When comparing with an empty part, the non-empty one is always - considered greater-than. Previously, the two would be considered equal - which would randomly place empty parts amongst non-empty ones. This - showed as a test 439 failure on Solaris as it uses a different - implementation of qsort() that compares parts differently. +Daniel Stenberg (26 Oct 2023) - Fixes #11855 - Closes #11868 +- openssl: fix infof() to avoid compiler warning for %s with null -- CI: ignore the "flaky" and "timing-dependent" test results + vtls/openssl.c: In function ‘ossl_connect_step2’: + ../lib/curl_trc.h:120:10: error: ‘%s’ directive argument is null [-Werror + =format-overflow=] + 120 | Curl_infof(data, __VA_ARGS__); } while(0) + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + vtls/openssl.c:4008:5: note: in expansion of macro ‘infof’ + 4008 | infof(data, "SSL connection using %s / %s / %s / %s", + | ^~~~~ + vtls/openssl.c:4008:49: note: format string is defined here + 4008 | infof(data, "SSL connection using %s / %s / %s / %s", + | ^~ - CI builds will now run these tests, but will ignore the results if they - fail. The relevant tests are ones that are sensitive to timing or - have edge conditions that make them more likely to fail on CI servers, - which are often heavily overloaded and slow. + Follow-up to b6e6d4ff8f253c8b8055bab + Closes #12196 - This change only adds two additional tests to be ignored, since the - others already had the flaky keyword. +Stefan Eissing (26 Oct 2023) - Closes #11865 +- lib: apache style infof and trace macros/functions -- runtests: eliminate a warning on old perl versions + - test for a simplified C99 variadic check + - args to infof() in --disable-verbose are no longer disregarded but + must compile. - The warning "Use of implicit split to @_ is deprecated" showed between - perl versions about 5.8 through 5.11. + Closes #12167 + Fixes #12083 + Fixes #11880 + Fixes #11891 -- tests: log the test result code after each libtest +Daniel Stenberg (26 Oct 2023) - This makes it easier to determine the test status. Also, capitalize - FAILURE and ABORT messages in log lines to make them easier to spot. +- RELEASE-NOTES: synced -Harry Sintonen (16 Sep 2023) +Stefan Eissing (26 Oct 2023) -- misc: better random strings +- urldata: move async resolver state from easy handle to connectdata - Generate alphanumerical random strings. + - resolving is done for a connection, not for every transfer + - save create/dup/free of a cares channel for each transfer + - check values of setopt calls against a local channel if no + connection has been attached yet, when needed. - Prior this change curl used to create random hex strings. This was - mostly okay, but having alphanumerical random strings is better: The - strings have more entropy in the same space. + Closes #12198 - The MIME multipart boundary used to be mere 64-bits of randomness due - to being 16 hex chars. With these changes the boundary is 22 - alphanumerical chars, or little over 130 bits of randomness. +Daniel Stenberg (26 Oct 2023) - Closes #11838 +- CURLOPT_WRITEFUNCTION.3: clarify what libcurl returns for CURL_WRITEFUNC_ERRO + R -Daniel Stenberg (15 Sep 2023) + It returns CURLE_WRITE_ERROR. It was not previously stated clearly. -- cookie: reduce variable scope, add const + Reported-by: enWILLYado on github + Fixes #12201 + Closes #12203 -- cookie: do not store the expire or max-age strings +Viktor Szakats (25 Oct 2023) - Convert it to an expire time at once and save memory. +- autotools: update references to deleted `crypt-auth` option - Closes #11862 + Delete leftovers of the `crypt-auth` `./configure` option and + add the new ones that replaced them. -- cookie: remove unnecessary struct fields + Follow-up to e92edfbef64448ef461117769881f3ed776dec4e #11490 - Plus: reduce the hash table size from 256 to 63. It seems unlikely to - make much of a speed difference for most use cases but saves 1.5KB of - data per instance. + Reviewed-by: Daniel Stenberg + Closes #12194 - Closes #11862 +Stefan Eissing (25 Oct 2023) -- RELEASE-NOTES: synced +- lib: introduce struct easy_poll_set for poll information - Bumped to 8.4.0, the next presumed version + Connection filter had a `get_select_socks()` method, inspired by the + various `getsocks` functions involved during the lifetime of a + transfer. These, depending on transfer state (CONNECT/DO/DONE/ etc.), + return sockets to monitor and flag if this shall be done for POLLIN + and/or POLLOUT. -Dan Fandrich (14 Sep 2023) + Due to this design, sockets and flags could only be added, not + removed. This led to problems in filters like HTTP/2 where flow control + prohibits the sending of data until the peer increases the flow + window. The general transfer loop wants to write, adds POLLOUT, the + socket is writeable but no data can be written. -- test2600: remove special case handling for USE_ALARM_TIMEOUT + This leads to cpu busy loops. To prevent that, HTTP/2 did set the + `SEND_HOLD` flag of such a blocked transfer, so the transfer loop cedes + further attempts. This works if only one such filter is involved. If a + HTTP/2 transfer goes through a HTTP/2 proxy, two filters are + setting/clearing this flag and may step on each other's toes. - This was originally added to handle platforms that supported only 1 - second granularity in connect timeouts, but after some recent changes - the test currently permafails on several Windows platforms. + Connection filters `get_select_socks()` is replaced by + `adjust_pollset()`. They get passed a `struct easy_pollset` that keeps + up to `MAX_SOCKSPEREASYHANDLE` sockets and their `POLLIN|POLLOUT` + flags. This struct is initialized in `multi_getsock()` by calling the + various `getsocks()` implementations based on transfer state, as before. - The need for this special-case was removed in commit 8627416, which - increased the connect timeout in all cases to well above 1 second. + After protocol handlers/transfer loop have set the sockets and flags + they want, the `easy_pollset` is *always* passed to the filters. Filters + "higher" in the chain are called first, starting at the first + not-yet-connection one. Each filter may add sockets and/or change + flags. When all flags are removed, the socket itself is removed from the + pollset. - Fixes #11767 - Closes #11849 + Example: -Daniel Stenberg (14 Sep 2023) + * transfer wants to send, adds POLLOUT + * http/2 filter has a flow control block, removes POLLOUT and adds + POLLIN (it is waiting on a WINDOW_UPDATE from the server) + * TLS filter is connected and changes nothing + * h2-proxy filter also has a flow control block on its tunnel stream, + removes POLLOUT and adds POLLIN also. + * socket filter is connected and changes nothing + * The resulting pollset is then mixed together with all other transfers + and their pollsets, just as before. -- SECURITY-PROCESS.md. call it vulnerability disclosure policy + Use of `SEND_HOLD` is no longer necessary in the filters. - SECURITY-PROCESS.md -> VULN-DISCLOSURE-POLICY.md + All filters are adapted for the changed method. The handling in + `multi.c` has been adjusted, but its state handling the the protocol + handlers' `getsocks` method are untouched. - This a name commonly used for a document like this. This name helps - users find it. + The most affected filters are http/2, ngtcp2, quiche and h2-proxy. TLS + filters needed to be adjusted for the connecting handshake read/write + handling. - Closes #11852 + No noticeable difference in performance was detected in local scorecard + runs. -Junho Choi (14 Sep 2023) + Closes #11833 -- quiche: fix build error with --with-ca-fallback +Daniel Stenberg (25 Oct 2023) - - Fix build error when curl is built with --with-quiche - and --with-ca-fallback. +- tests/README: SOCKS tests are not using OpenSSH, it has its own server - - Add --with-ca-fallback to the quiche CI job. + Follow-up to 04fd67555cc - Fixes https://github.com/curl/curl/issues/11850 - Closes https://github.com/curl/curl/pull/11847 + Closes #12195 -Jay Satiro (14 Sep 2023) +Jacob Hoffman-Andrews (25 Oct 2023) -- escape: replace Curl_isunreserved with ISUNRESERVED +- tets: make test documentation more user-friendly - - Use the ALLCAPS version of the macro so that it is clear a macro is - being called that evaluates the variable multiple times. + Put the instructions to run tests right at the top of tests/README.md. - - Also capitalize macro isurlpuntcs => ISURLPUNTCS since it evaluates - a variable multiple times. + Give instructions to read the runtests.1 man page for information + about flags. Delete redundant copy of the flags documentation in the + README. - This is a follow-up to 291d225a which changed Curl_isunreserved into an - alias macro for ISUNRESERVED. The problem is the former is not easily - identified as a macro by the caller, which could lead to a bug. + Add a mention in README.md of the important parallelism flag, to make + test runs go much faster. - For example, ISUNRESERVED(*foo++) is easily identifiable as wrong but - Curl_isunreserved(*foo++) is not even though they both are the same. + Move documentation of output line format into the runtests.1 man page, + and update it with missing flags. - Closes https://github.com/curl/curl/pull/11846 + Fix the order of two flags in the man page. -Dan Fandrich (13 Sep 2023) + Closes #12193 -- tests: increase the default server logs lock timeout +Viktor Szakats (24 Oct 2023) - This timeout is used to wait for the server to finish writing its logs - before checking them against the expected values. An overloaded machine - could take more than the two seconds previously allocated, so increase - the timeout to 5 seconds. +- cmake: pre-fill rest of detection values for Windows - Ref: #11328 - Closes #11834 + The goal of this patch is to avoid unnecessary feature detection work + when doing Windows builds with CMake. Do this by pre-filling well-known + detection results for Windows and specifically for mingw-w64 and MSVC + compilers. Also limit feature checks to platforms where the results are + actually used. Drop a few redundant ones. And some tidying up. -- tests: increase TEST_HANG_TIMEOUT in two tests + - pre-fill remaining detection values in Windows CMake builds. - These tests had a 5 second timeout compared to 60 seconds for all other - tests. Make these consistent with the others for more reliability on - heavily-loaded machines. + Based on actual detection results observed in CI runs, preceding + similar work over libssh2 and matching up values with + `lib/config-win32.h`. - Ref: #11328 + This brings down CMake configuration time from 58 to 14 seconds on the + same local machine. -- test1056: disable on Windows + On AppVeyor CI this translates to: + - 128 seconds -> 50 seconds VS2022 MSVC with OpenSSL (per CMake job): + https://ci.appveyor.com/project/curlorg/curl/builds/48208419/job/4gw66ecr + jpy7necb#L296 + https://ci.appveyor.com/project/curlorg/curl/builds/48217440/job/8m4fwrr2 + fe249uo8#L186 + - 62 seconds -> 16 seconds VS2017 MINGW (per CMake job): + https://ci.appveyor.com/project/curlorg/curl/builds/48208419/job/s1y8q5iv + lcs7ub29?fullLog=true#L290 + https://ci.appveyor.com/project/curlorg/curl/builds/48217440/job/pchpxyjs + yc9kl13a?fullLog=true#L194 - This test relies on the IPv6 scope field being ignored when connecting to - ipv6-localhost (i.e. [::1%259999] is treated as [::1]). Maybe this is a bit - dodgy, but it works on all our test platforms except Windows. This - test was disabled manually on all Windows CI builds already, so instead - add an incompatible feature and precheck so it's skipped on Windows - everywhere automatically. + The formula is about 1-3 seconds delay for each detection. Almost all + of these trigger a full compile-link cycle behind the scenes, slow + even today, both cross and native, mingw-w64 and apparently MSVC too. + Enabling .map files or other custom build features slows it down + further. (Similar is expected for autotools configure.) -- test587: add a slight delay after test + - stop detecting `idn2.h` if idn2 was deselected. + autotools does this. - This test is designed to connect to the server, then immediately send a - few bytes and disconnect. In some situations, such as on a loaded - server, this doesn't give the server enough time to write its lock file - before its existence is checked. The test harness then fails to find the - server's input log file (because it hasn't been written yet) and fails - the test. By adding a short delay after the test, the HTTP server has - enough time to write its lock file which gives itself more time to write - its remaining files. + - stop detecting `idn2.h` if idn2 was not found. + This deviates from autotools. Source code requires both header and + lib, so this is still correct, but faster. - Ref: #11328 + - limit `ADDRESS_FAMILY` detection to Windows. -- tests: stop overriding the lock timeout + - normalize `HAVE_WIN32_WINNT` value to lowercase `0x0a12` format. - These tests reduce the server lock wait timeout which can increase - flakiness on loaded machines. Since this is merely an optimization, - eliminate them in favour of reliability. + - pre-fill `HAVE_WIN32_WINNT`-dependent detection results. + Saving 4 (slow) feature-detections in most builds: `getaddrinfo`, + `freeaddrinfo`, `inet_ntop`, `inet_pton` - Ref: #11328 + - fix pre-filled `HAVE_SYS_TIME_H`, `HAVE_SYS_PARAM_H`, + `HAVE_GETTIMEOFDAY` for mingw-w64. + Luckily this do not change build results, as `WIN32` took + priority over `HAVE_GETTIMEOFDAY` with the current source + code. -- tests: add some --expect100-timeout to reduce timing dependencies + - limit `HAVE_CLOCK_GETTIME_MONOTONIC_RAW` and + `HAVE_CLOCK_GETTIME_MONOTONIC` detections to non-Windows. + We're not using these in the source code for Windows. - These tests can fail when the test machine is so slow that the test HTTP - server didn't get a chance to complete before the client's one second - 100-continue timeout triggered. Increase that 1 second to 999 seconds so - this situation doesn't happen. + - reduce compiler warning noise in CMake internal logs: + - fix to include `winsock2.h` before `windows.h`. + Apply it to autotools test snippets too. + - delete previous `-D_WINSOCKAPI_=` hack that aimed to fix the above. + - cleanup `CMake/CurlTests.c` to emit less warnings. - Ref: #11328 + - delete redundant `HAVE_MACRO_SIGSETJMP` feature check. + It was the same check as `HAVE_SIGSETJMP`. -- test661: return from test early in case of curl error + - delete 'experimental' marking from `CURL_USE_OPENSSL`. -- tests: add the timing-dependent keyword on several tests + - show CMake version via `CMakeLists.txt`. + Credit to the `zlib-ng` project for the idea: + https://github.com/zlib-ng/zlib-ng/blob/61e181c8ae93dbf56040336179c9954078b + d1399/CMakeLists.txt#L7 - These are ones likely to fail on heavily-loaded machines that alter the - normal test timing. Most of these tests already had the flaky keyword - since this condition makes them more likely to fail on CI. + - make `CMake/CurlTests.c` pass `checksrc`. -- test1592: greatly increase the maximum test timeout + - `CMake/WindowsCache.cmake` tidy-ups. - It was too short to be reliable on heavily loaded CI machines, and - as a fail-safe only, it didn't need to be short. + - replace `WIN32` guard with `_WIN32` in `CMake/CurlTests.c`. - Ref: #11328 + Closes #12044 -- test: minor test cleanups +Jay Satiro (24 Oct 2023) - Remove an obsolete block of code in tests 2032 & 576. - Add a comment in test 1474. +- page-footer: clarify exit code 25 -- tests: quadruple the %FTPTIME2 and %FTPTIME3 timeouts + - Clarify that curl tool exit code 25 means an upload failed to start. - This gives more of a margin for error when running on overloaded CI - servers. + Exit code 25 is equivalent to CURLE_UPLOAD_FAILED (25). Prior to this + change the documentation only mentioned the case of FTP STOR failing. - Ref: #11328 + Reported-by: Emanuele Torre -- tests: improve SLOWDOWN test reliability by reducing sent data + Ref: https://github.com/curl/curl/blob/curl-8_4_0/docs/libcurl/libcurl-errors + .3#L113-L115 - These tests are run in SLOWDOWN mode which adds a 10 msec delay after - each character output, which means it takes at least 1.6 seconds (and - 320 kernel calls) just to get through the long welcome banner. On an - overloaded system, this can end up taking much more than 1.6 seconds, - and even more than the 7 or 16 second curl timeout that the tests rely - on, causing them to fail. Reducing the size of the welcome banner drops - the total number of characters sent before the transfer starts by more - than half, which reduces the opportunity for test-breaking slowdowns by - the same amount. + Fixes https://github.com/curl/curl/issues/12189 + Closes https://github.com/curl/curl/pull/12190 - Ref: #11328 +Daniel Stenberg (24 Oct 2023) -- test650: fix an end tag typo +- scripts/cijobs.pl: adjust for appveyor -Jay Satiro (13 Sep 2023) + Follow-up to a1d73a6bb -- tool_cb_wrt: fix debug assertion +Alex Bozarth (24 Oct 2023) - - Fix off-by-one out-of-bounds array index in Windows debug assertion. +- OpenSSL: Include SIG and KEM algorithms in verbose - Bug: https://github.com/curl/curl/commit/af3f4e41#r127212213 - Reported-by: Gisle Vanem + Currently the verbose output does not include which algorithms are used + for the signature and key exchange when using OpenSSL. Including the + algorithms used will enable better debugging when working on using new + algorithm implementations. Know what algorithms are used has become more + important with the fast growing research into new quantum-safe + algorithms. -Daniel Stenberg (13 Sep 2023) + This implementation includes a build time check for the OpenSSL version + to use a new function that will be included in OpenSSL 3.2 that was + introduced in openssl/openssl@6866824 -- ctype: add ISUNRESERVED() + Based-on-patch-by: Martin Schmatz + Closes #12030 - ... and make Curl_isunreserved() use that macro instead of providing a - separate funtion for the purpose. +Daniel Stenberg (23 Oct 2023) - Closes #11840 +- http2: provide an error callback and failf the message -Version 8.3.0 (13 Sep 2023) + Getting nghttp2's error message helps users understand what's going + on. For example when the connection is brought down due a forbidden + header is used - as that header is then not displayed by curl itself. -Daniel Stenberg (13 Sep 2023) + Example: -- RELEASE-NOTES: syn ced + curl: (92) Invalid HTTP header field was received: frame type: 1, + stream: 1, name: [upgrade], value: [h2,h2c] - curl 8.3.0 release + Ref: #12172 + Closes #12179 -- THANKS: contributors from 8.3.0 +Turiiya (23 Oct 2023) -Thorsten Klein (12 Sep 2023) +- BINDINGS: add V binding -- cmake: set SIZEOF_LONG_LONG in curl_config.h + Closes #12182 - in order to support 32bit builds regarding wolfssl CTC_SETTINGS +Daniel Stenberg (22 Oct 2023) - Closes #11839 +- configure: check for the fseeko declaration too -Jay Satiro (12 Sep 2023) + ... and make the code require both symbol and declaration. -- curl_ngtcp2: fix error message + This is because for Android, the symbol is always present in the lib at + build-time even when not actually available in run-time. -- http_aws_sigv4: handle no-value user header entries + Assisted-by: Viktor Szakats + Reported-by: 12932 on github + Fixes #12086 + Closes #12158 - - Handle user headers in format 'name:' and 'name;' with no value. +Viktor Szakats (22 Oct 2023) - The former is used when the user wants to remove an internal libcurl - header and the latter is used when the user actually wants to send a - no-value header in the format 'name:' (note the semi-colon is converted - by libcurl to a colon). +- cmake: fix OpenSSL quic detection in quiche builds - Prior to this change the AWS header import code did not special case - either of those and the generated AWS SignedHeaders would be incorrect. + An orphan call to `CheckQuicSupportInOpenSSL()` remained after a recent + update when checking QUIC for quiche. Move back QUIC detection to + a function and fixup callers to use that. Also make sure that quiche + gets QUIC from BoringSSL, because it doesn't support other forks at this + time. - Reported-by: apparentorder@users.noreply.github.com + Regression from dee310d54261f9a8416e87d50bccfe2cbe404949 #11555 - Ref: https://curl.se/docs/manpage.html#-H + Reported-by: Casey Bodley + Fixes #12160 + Closes #12162 - Fixes https://github.com/curl/curl/issues/11664 - Closes https://github.com/curl/curl/pull/11668 +Daniel Stenberg (22 Oct 2023) -Dan Fandrich (11 Sep 2023) +- RELEASE-NOTES: synced -- CI: run pytest with the -v option + bump to 8.5.0 for pending release - This lists of the test cases being run so it can be tracked over time. +Dan Fandrich (21 Oct 2023) - Closes #11824 +- test3103: add missing quotes around a test tag attribute -Daniel Stenberg (11 Sep 2023) +Loïc Yhuel (21 Oct 2023) -- HTTP3: the msquic backend is not functional +- tool: fix --capath when proxy support is disabled - I ask that we do not submit bugs for this backend just yet as we know it - does not fully work. + After 95e8515ca0, --capath always sets CURLOPT_PROXY_CAPATH, which fails + with CURLE_UNKNOWN_OPTION when proxy support is disabled. - Closes #11831 - Closes #11819 + Closes #12089 -- aws_sigv4: the query canon code miscounted URL encoded input +Daniel Stenberg (21 Oct 2023) - Added some extra ampersands to test 439 to verify "blank" query parts +- openldap: move the alloc of ldapconninfo to *connect() - Follow-up to fc76a24c53b08cdf + Fixes a minor memory leak on LDAP connection reuse. - Closes #11829 + Doing the allocation already in *setup_connection() is wrong since that + connect struct might get discarded early when an existing connection is + reused instead. -vvb2060 (11 Sep 2023) + Closes #12166 -- quic: don't set SNI if hostname is an IP address +- openldap: set the callback argument in oldap_do - We already do this for TLS connections. + ... to make sure it has the current 'data' pointer and not a stale old + one. - RFC 6066 says: Literal IPv4 and IPv6 addresses are not permitted in - "HostName". + Reported-by: Dan Fandrich + Closes #12166 - Ref: https://www.rfc-editor.org/rfc/rfc6066#section-3 +- gnutls: support CURLSSLOPT_NATIVE_CA - Fixes https://github.com/curl/curl/issues/11827 - Closes https://github.com/curl/curl/pull/11828 + Remove the CURL_CA_FALLBACK logic. That build option was added to allow + primarily OpenSSL to use the default paths for loading the CA certs. For + GnuTLS it was instead made to load the "system certs", which is + different and not desirable. -Daniel Stenberg (10 Sep 2023) + The native CA store loading is now asked for with this option. -- RELEASE-NOTES: synced + Follow-up to 7b55279d1d856 -Benoit Pierre (10 Sep 2023) + Co-authored-by: Jay Satiro -- configure: fix `HAVE_TIME_T_UNSIGNED` check + Closes #12137 - The syntax was incorrect (need a proper main body), and the test - condition was wrong (resulting in a signed `time_t` detected as - unsigned). +Stefan Eissing (21 Oct 2023) - Closes #11825 +- RTSP: improved RTP parser -Daniel Stenberg (9 Sep 2023) + - fix HTTP header parsing to report incomplete + lines it buffers as consumed! + - re-implement the RTP parser for interleave RTP + messages for robustness. It is now keeping its + state at the connection + - RTSP protocol handler "readwrite" implementation + now tracks if the response is before/in/after + header parsing or "in" a bod by calling + "Curl_http_readwrite_headers()" itself. This + allows it to know when non-RTP bytes are "junk" + or HEADER or BODY. + - tested with #12035 and various small receive + sizes where current master fails -- THANKS-filter: pszlazak on github + Closes #12052 -pszlazak (9 Sep 2023) +- http2: header conversion tightening -- include.d: explain headers not printed with --fail before 7.75.0 + - fold the code to convert dynhds to the nghttp2 structs + into a dynhds internal method + - saves code duplication + - pacifies compiler analyzers - Prior to 7.75.0 response headers were not printed if -f/--fail was used - and an error was reported by server. This was fixed in ab525c0 - (precedes 7.75.0). + Closes #12097 - Closes #11822 +Daniel Stenberg (21 Oct 2023) -Daniel Stenberg (8 Sep 2023) +- curl_ntlm_wb: fix elif typo -- http_aws_sigv4: skip the op if the query pair is zero bytes + Reported-by: Manfred Schwarb + Follow-up to d4314cdf65ae + Bug: https://github.com/curl/curl/commit/d4314cdf65aee295db627016934bd9eb621a + b077#r130551295 - Follow-up to fc76a24c53b08cdf +Dan Fandrich (20 Oct 2023) - Spotted by OSS-Fuzz +- test1683: remove commented-out check alternatives - Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=62175 - Closes #11823 + Python precheck/postcheck alternatives were included but commented out. + Since these are not used and perl is guaranteed to be available to run + the perl versions anyway, the Python ones are removed. -- cmdline-docs: use present tense, not future +Daniel Stenberg (20 Oct 2023) - + some smaller cleanups +- hostip: show the list of IPs when resolving is done - Closes #11821 + Getting 'curl.se' today then gets this verbose output which might help + debugging connectivity related matters. -- cmdline-docs: make sure to phrase it as "added in ...." + * Host curl.se:80 was resolved. + * IPv6: 2a04:4e42::347, 2a04:4e42:200::347, 2a04:4e42:400::347, + 2a04:4e42:600::347, 2a04:4e42:800::347, 2a04:4e42:a00::347, + 2a04:4e42:c00::347, 2a04:4e42:e00::347 + * IPv4: 151.101.193.91, 151.101.1.91, 151.101.65.91, 151.101.129.91 - References to things that were added or changed in a specific version - should be specified as "(added in [version]) for two reasons: + Co-authored-by: Jay Satiro + Closes #12145 - 1 - consistency +rilysh (20 Oct 2023) - 2 - to allow gen.pl to strip them out if deemed referring to too old - versions +- docs: fix function typo in curl_easy_option_next.3 - Closes #11821 + Closes #12170 -Jay Satiro (8 Sep 2023) +Daniel Stenberg (20 Oct 2023) -- docs: mark --ssl-revoke-best-effort as Schannel specific +- vssh: remove the #ifdef for Curl_ssh_init, use empty macro - Closes https://github.com/curl/curl/pull/11760 + In the same style as other init calls -Nathan Moinvaziri (8 Sep 2023) +- easy: remove duplicate wolfSSH init call -- schannel: fix ordering of cert chain info + It is already done in Curl_ssh_init() where it belongs. - - Use CERT_CONTEXT's pbCertEncoded to determine chain order. + Closes #12168 - CERT_CONTEXT from SECPKG_ATTR_REMOTE_CERT_CONTEXT contains - end-entity/server certificate in pbCertEncoded. We can use this pointer - to determine the order of certificates when enumerating hCertStore using - CertEnumCertificatesInStore. +- socks: make SOCKS5 use the CURLOPT_IPRESOLVE choice - This change is to help ensure that the ordering of the certificate chain - requested by the user via CURLINFO_CERTINFO has the same ordering on all - versions of Windows. + Fixes #11949 + Reported-by: Ammar Faizi + Closes #12163 - Prior to this change Schannel certificate order was reversed in 8986df80 - but that was later reverted in f540a39b when it was discovered that - Windows 11 22H2 does the reversal on its own. +- urldata: move the 'internal' boolean to the state struct - Ref: https://github.com/curl/curl/issues/9706 + ... where all the other state bits for the easy handles live. - Closes https://github.com/curl/curl/pull/11632 + Closes #12165 -Chris Talbot (8 Sep 2023) +- url: don't touch the multi handle when closing internal handles -- digest: Use hostname to generate spn instead of realm + Reported-by: Maksymilian Arciemowicz + Closes #12165 - In https://www.rfc-editor.org/rfc/rfc2831#section-2.1.2 +Faraz Fallahi (19 Oct 2023) - digest-uri-value should be serv-type "/" host , where host is: +- getenv: PlayStation doesn't have getenv() - The DNS host name or IP address for the service requested. The - DNS host name must be the fully-qualified canonical name of the - host. The DNS host name is the preferred form; see notes on server - processing of the digest-uri. + Closes #12140 - Realm may not be the host, so we must specify the host explicitly. +Daniel Stenberg (19 Oct 2023) - Note this change only affects the non-SSPI digest code. The digest code - used by SSPI builds already uses the hostname to generate the spn. +- transfer: only reset the FTP wildcard engine in CLEAR state - Ref: https://github.com/curl/curl/issues/11369 + To avoid the state machine to start over and redownload all the files + *again*. - Closes https://github.com/curl/curl/pull/11395 + Reported-by: lkordos on github + Regression from 843b3baa3e3cb228 (shipped in 8.1.0) + Bisect-by: Dan Fandrich + Fixes #11775 + Closes #12156 -Daniel Stenberg (7 Sep 2023) +Stefan Eissing (19 Oct 2023) -- docs: remove use of the word 'very' +- GHA: move mod_h2 version in CI to v2.0.25 - It is mostly superfluous. proselint would complain. + Closes #12157 - Closes #11818 +Daniel Stenberg (19 Oct 2023) -- curl_multi_remove_handle.3: clarify what happens with connection +- ntlm_wb: use pipe instead of socketpair when possible - Closes #11817 + Closes #12149 - RELEASE-NOTES: synced -- test439: verify query canonization for aws-sigv4 +- asyn-thread: use pipe instead of socketpair for IPC when available -- tool_operate: make aws-sigv4 not require TLS to be used + If pipe() is present. Less overhead. - Maybe not used too often, but we want it for testing and it should work. + Helped-by: Viktor Szakats + Closes #12146 -- http_aws_sigv4: canonicalize the query +Dan Fandrich (17 Oct 2023) - Percent encoding needs to be done using uppercase, and most - non-alphanumerical must be percent-encoded. +- tests: Fix Windows test helper tool search & use it for handle64 - Fixes #11794 - Reported-by: John Walker - Closes #11806 + The checkcmd() and checktestcmd() functions would not have worked on + Windows due to hard-coding the UNIX PATH separator character and not + adding .exe file extension. This meant that tools like stunnel, valgrind + and nghttpx would not have been found and used on Windows, and + inspection of previous test runs show none of those being found in pure + Windows CI builds. -Wyatt O'Day (7 Sep 2023) + With this fixed, they can be used to detect the handle64.exe program + before attempting to use it. When handle64.exe was called + unconditionally without it existing, it caused perl to abort the test + run with the error -- lib: add ability to disable auths individually + The running command stopped because the preference variable + "ErrorActionPreference" or common parameter is set to Stop: + sh: handle64.exe: command not found - Both with configure and cmake + Closes #12115 - Closes #11490 +Daniel Stenberg (17 Oct 2023) -Stefan Eissing (7 Sep 2023) +- multi: use pipe instead of socketpair to *wakeup() -- ngtcp2: fix handling of large requests + If pipe() is present. Less overhead. - - requests >64K are send in parts to the filter - - fix parsing of the request to assemble it correctly - from several sends - - open a QUIC stream only when the complete request has - been collected + Closes #12142 - Closes #11815 +Jay Satiro (17 Oct 2023) -- openssl: when CURLOPT_SSL_CTX_FUNCTION is registered, init x509 store before +- build: fix 'threadsafe' feature detection for older gcc - - we delay loading the x509 store to shorten the handshake time. - However an application callback installed via CURLOPT_SSL_CTX_FUNCTION - may need to have the store loaded and try to manipulate it. - - load the x509 store before invoking the app callback + - Add 'threadsafe' to the feature list shown during build if POSIX + threads are being used. - Fixes #11800 - Reported-by: guoxinvmware on github - Cloes #11805 + This is a follow-up to 5adb6000 which added support for building a + thread-safe libcurl with older versions of gcc where atomic is not + available but pthread is. -Daniel Stenberg (7 Sep 2023) + Reported-by: Dan Fandrich + Co-authored-by: Dan Fandrich -- krb5: fix "implicit conversion loses integer precision" warnings + Fixes https://github.com/curl/curl/issues/12125 + Closes https://github.com/curl/curl/pull/12127 - conversions to/from enum and unsigned chars +Daniel Stenberg (16 Oct 2023) - Closes #11814 +- test729: verify socks4a with excessive proxy user name length -Stefan Eissing (7 Sep 2023) +- socks: better buffer size checks for socks4a user and hostname -- pytest: improvements + Also limit the proxy user name to 255 bytes, which is the same limit as + in SOCKS5. - - set CURL_CI for pytest runs in CI environments - - exclude timing sensitive tests from CI runs - - for failed results, list only the log and stat of - the failed transfer + Reported-by: sd0 on hackerone + Closes #12139 - - fix type in http.c comment +- curl.h: on FreeBSD include sys/param.h instead of osreldate.h - Closes #11812 + Should things build on Playstation as well -- CI: move on to ngtcp2 v0.19.1 + Fixes #12107 + Reported-by: Faraz Fallahi + Closes #12123 - Closes #11809 +Marcin Rataj (16 Oct 2023) -Dan Fandrich (5 Sep 2023) +- tool_operate: fix links in ipfs errors -- CI: run Circle macOS builds on x86 for now + URL fragment links generated from headers in + https://curl.se/docs/ipfs.html are lowercase. - The ARM machines aren't ready for us and requesting them now causes - warnings e-mails to be sent to some PR pushers. + Closes #12133 - Ref: #11771 +Viktor Szakats (15 Oct 2023) -Viktor Szakats (5 Sep 2023) +- cmake: replace `check_library_exists_concat()` -- http3: adjust cast for ngtcp2 v0.19.0 + The idea of `check_library_exists_concat()` is that it detects an + optional component and adds it to the list of libs that we also use in + subsequent component checks. This caused problems when detecting + components with unnecessary dependencies that were not yet built. - ngtcp2 v0.19.0 made size of `ecn` member of `ngtcp2_pkt_info` - an `uint8_t` (was: `uint32_t`). Adjust our local cast accordingly. + CMake offers the `CMAKE_REQUIRED_LIBRARIES` variable to set libs used + for component checks, which we already use in most cases. That left 4 + uses of `check_library_exists_concat()`. Only one of these actually + needed the 'concat' feature (ldap/lber). - Fixes: - ``` - ./curl/lib/vquic/curl_ngtcp2.c:1912:12: warning: implicit conversion loses in - teger precision: 'uint32_t' (aka 'unsigned int') to 'uint8_t' (aka 'unsigned - char') [-Wimplicit-int-conversion] - pi.ecn = (uint32_t)ecn; - ~ ^~~~~~~~~~~~~ - ``` + Delete this function and replace it with standard + `check_library_exists()` and manual management of our `CURL_LIBS` + list we use when linking build targets. And special logic to handle the + ldap/lber case. - Also bump ngtcp2, nghttp3 and nghttp2 to their latest versions in our - docs and CI. + (We have a similar function for headers: `check_include_file_concat()`. + It works, but problematic for performance reasons and because it hides + the actual headers required in `check_symbol_exists()` calls.) - Ref: https://github.com/ngtcp2/ngtcp2/commit/80447281bbc94af53f8aa7a4cfc19175 - 782894a3 - Ref: https://github.com/ngtcp2/ngtcp2/pull/877 - Closes #11798 + Ref: #11537 #11558 + Fixes #11285 + Fixes #11648 + Closes #12070 -Stefan Eissing (5 Sep 2023) +LoRd_MuldeR (15 Oct 2023) -- http: fix sending of large requests +- tool_cb_wrt: fix write output for very old Windows versions - - refs #11342 where errors with git https interactions - were observed - - problem was caused by 1st sends of size larger than 64KB - which resulted in later retries of 64KB only - - limit sending of 1st block to 64KB - - adjust h2/h3 filters to cope with parsing the HTTP/1.1 - formatted request in chunks + - Pass missing parameter for 'lpNumberOfCharsWritten' to WriteConsoleW() + function. - - introducing Curl_nwrite() as companion to Curl_write() - for the many cases where the sockindex is already known + Apparently this parameter was *not* optional on older Windows versions. - Fixes #11342 (again) - Closes #11803 + Issue observed on Windows XP SP2. Issue not observed on Windows 7 SP1. + So at some point between those two Microsoft changed the behavior. -- pytest: fix check for slow_network skips to only apply when intended + Prior to this change, on those versions if parameter is NULL then the + function call fails with error ERROR_INVALID_ACCESS. - Closes #11801 + Regression since af3f4e41. -Daniel Stenberg (5 Sep 2023) + Ref: https://github.com/MicrosoftDocs/Console-Docs/issues/299 -- curl_url_get/set.3: add missing semicolon in SYNOPSIS + Fixes https://github.com/curl/curl/issues/12131 + Closes https://github.com/curl/curl/pull/12130 -- CURLOPT_URL.3: explain curl_url_set() uses the same parser +Jay Satiro (15 Oct 2023) -- CURLOPT_URL.3: add two URL API calls in the see-also section +- tool_urlglob: fix build for old gcc versions -Dan Fandrich (4 Sep 2023) + - Don't use __builtin_mul_overflow for GCC 4 and earlier. -- CI: add a 32-bit i686 Linux build + The function was added in GCC 5. - This is done by cross-compiling under regular x86_64 Linux. Since the - kernel offers backwards compatibility, the binaries can be tested as - normal. + Ref: https://gcc.gnu.org/gcc-5/changes.html - Closes #11799 + Reported-by: Dan Fandrich -- tests: fix a type warning on 32-bit x86 + Fixes https://github.com/curl/curl/issues/12124 + Closes https://github.com/curl/curl/pull/12128 -Viktor Szakats (4 Sep 2023) +Carlos Henrique Lima Melara (14 Oct 2023) -- tests: delete stray `.orig` file +- docs/libcurl: fix three minor man page format mistakes - Follow-up to 331b89a319d0067fa1e6441719307cfef9c7960f - Closes #11797 + Reported-by: Samuel Henrique -Daniel Stenberg (4 Sep 2023) + Closes https://github.com/curl/curl/pull/12126 -- RELEASE-NOTES: synced +Jay Satiro (14 Oct 2023) -Viktor Szakats (4 Sep 2023) +- tests/server: add more SOCKS5 handshake error checking -- lib: silence compiler warning in inet_ntop6 + - Add additional checking for missing and too-short SOCKS5 handshake + messages. - ``` - ./curl/lib/inet_ntop.c:121:21: warning: possible misuse of comma operator her - e [-Wcomma] - cur.base = i, cur.len = 1; - ^ - ./curl/lib/inet_ntop.c:121:9: note: cast expression to void to silence warnin - g - cur.base = i, cur.len = 1; - ^~~~~~~~~~~~ - (void)( ) - ``` + Prior to this change the SOCKS5 test server did not check that all parts + of the handshake were received successfully. If those parts were missing + or too short then the server would access uninitialized memory. - Closes #11790 + This issue was discovered in CI job 'memory-sanitizer' test results. + Test 2055 was failing due to the SOCKS5 test server not running. It was + not running because either it crashed or memory sanitizer aborted it + during Test 728. Test 728 connects to the SOCKS5 test server on a + redirect but does not send any data on purpose. The test server was not + prepared for that. -Daniel Stenberg (4 Sep 2023) + Reported-by: Dan Fandrich -- transfer: also stop the sending on closed connection + Fixes https://github.com/curl/curl/issues/12117 + Closes https://github.com/curl/curl/pull/12118 - Previously this cleared the receiving bit only but in some cases it is - also still sending (like a request-body) when disconnected and neither - direction can continue then. +Daniel Stenberg (14 Oct 2023) - Fixes #11769 - Reported-by: Oleg Jukovec - Closes #11795 +- RELEASE-NOTES: synced -John Bampton (4 Sep 2023) +Sohom Datta (14 Oct 2023) -- docs: change `sub-domain` to `subdomain` +- tool_getparam: limit --rate to be smaller than number of ms - https://en.wikipedia.org/wiki/Subdomain + Currently, curl allows users to specify absurd request rates that might + be higher than the number of milliseconds in the unit (ex: curl --rate + 3600050/h http://localhost:8080 does not error out despite there being + only 3600000ms in a hour). - Closes #11793 + This change adds a conditional check before the millisecond calculation + making sure that the number is not higher than the numerator (the unit) + If the number is higher, curl errors out with PARAM_NUMBER_TOO_LARGE -Stefan Eissing (4 Sep 2023) + Closes #12116 -- multi: more efficient pollfd count for poll +Daniel Stenberg (14 Oct 2023) - - do not use separate pollfds for sockets that have POLLIN+POLLOUT +- opts: fix two minor man page format mistakes - Closes #11792 +Jay Satiro (14 Oct 2023) -- http2: polish things around POST +- curl_trc: remove a bad assertion - - added test cases for various code paths - - fixed handling of blocked write when stream had - been closed inbetween attempts - - re-enabled DEBUGASSERT on send with smaller data size + - Remove DEBUGASSERT that an internal handle must not have user + private_data set before calling the user's debug callback. - - in debug builds, environment variables can be set to simulate a slow - network when sending data. cf-socket.c and vquic.c support - * CURL_DBG_SOCK_WBLOCK: percentage of send() calls that should be - answered with a EAGAIN. TCP/UNIX sockets. - This is chosen randomly. - * CURL_DBG_SOCK_WPARTIAL: percentage of data that shall be written - to the network. TCP/UNIX sockets. - Example: 80 means a send with 1000 bytes would only send 800 - This is applied to every send. - * CURL_DBG_QUIC_WBLOCK: percentage of send() calls that should be - answered with EAGAIN. QUIC only. - This is chosen randomly. + This is a follow-up to 0dc40b2a. The user can distinguish their easy + handle from an internal easy handle by setting CURLOPT_PRIVATE on their + easy handle. I had wrongly assumed that meant the user couldn't then + set CURLOPT_PRIVATE on an internal handle as well. - Closes #11756 + Bug: https://github.com/curl/curl/pull/12060#issuecomment-1754594697 + Reported-by: Daniel Stenberg -Daniel Stenberg (4 Sep 2023) + Closes https://github.com/curl/curl/pull/12104 -- docs: add curl_global_trace to some SEE ALSO sections +Dan Fandrich (13 Oct 2023) - Closes #11791 +- test613: stop showing an error on missing output file -- os400: fix checksrc nits + This test would show an error message if the output was missing during + the log post-processing step, but the message was not captured by the + test harness and wasn't useful since the normal golden log file + comparison would the problem more clearly. - Closes #11789 +Stefan Eissing (13 Oct 2023) -Nicholas Nethercote (3 Sep 2023) +- quic: manage connection idle timeouts -- hyper: remove `hyptransfer->endtask` + - configure a 120s idle timeout on our side of the connection + - track the timestamp when actual socket IO happens + - check IO timestamp to our *and* the peer's idle timeouts + in "is this connection alive" checks - `Curl_hyper_stream` needs to distinguish between two kinds of - `HYPER_TASK_EMPTY` tasks: (a) the `foreach` tasks it creates itself, and - (b) background tasks that hyper produces. It does this by recording the - address of any `foreach` task in `hyptransfer->endtask` before pushing - it into the executor, and then comparing that against the address of - tasks later polled out of the executor. + Reported-by: calvin2021y on github + Fixes #12064 + Closes #12077 - This works right now, but there is no guarantee from hyper that the - addresses are stable. `hyper_executor_push` says "The executor takes - ownership of the task, which should not be accessed again unless - returned back to the user with `hyper_executor_poll`". That wording is a - bit ambiguous but with my Rust programmer's hat on I read it as meaning - the task returned with `hyper_executor_poll` may be conceptually the - same as a task that was pushed, but that there are no other guarantees - and comparing addresses is a bad idea. +Dan Fandrich (13 Oct 2023) - This commit instead uses `hyper_task_set_userdata` to mark the `foreach` - task with a `USERDATA_RESP_BODY` value which can then be checked for, - removing the need for `hyptransfer->endtask`. This makes the code look - more like that hyper C API examples, which use userdata for every task - and never look at task addresses. +- CI: ignore test 286 on Appveyor gcc 9 build - Closes #11779 + This test fails sometimes with a super fast retry loop due to what may + just be a compiler bug. The test results are ignored on the one CI job + where it occurs because there seems to be nothing we can do to fix it. -Dave Cottlehuber (3 Sep 2023) + Fixes #12040 + Closes #12106 -- ws: fix spelling mistakes in examples and tests +Viktor Szakats (13 Oct 2023) - Closes #11784 +- lib: fix gcc warning in printf call -Daniel Stenberg (3 Sep 2023) + Do not pass NULL to printf %s. -- tool_filetime: make -z work with file dates before 1970 + Seen with gcc 13.2.0 on Debian: + ``` + .../curl/lib/connect.c:696:27: warning: '%s' directive argument is null [-Wfo + rmat-overflow=] + ``` + Ref: https://github.com/curl/curl-for-win/actions/runs/6476161689/job/1758442 + 6483#step:3:11104 - Fixes #11785 - Reported-by: Harry Sintonen - Closes #11786 + Ref: #10284 + Co-authored-by: Jay Satiro + Closes #12082 -Dan Fandrich (1 Sep 2023) +Alex Klyubin (13 Oct 2023) -- build: fix portability of mancheck and checksrc targets +- http2: safer invocation of populate_binsettings - At least FreeBSD preserves cwd across makefile lines, so rules - consisting of more than one "cd X; do_something" must be explicitly run - in a subshell to avoid this. This problem caused the Cirrus FreeBSD - build to fail when parallel make jobs were enabled. + populate_binsettings now returns a negative value on error, instead of a + huge positive value. Both places which call this function have been + updated to handle this change in its contract. -- CI: adjust labeler match patterns for new & obsolete files + The way populate_binsettings had been used prior to this change the huge + positive values -- due to signed->unsigned conversion of the potentially + negative result of nghttp2_pack_settings_payload which returns negative + values on error -- are not possible. But only because http2.c currently + always provides a large enough output buffer and provides H2 SETTINGS + IVs which pass the verification logic inside nghttp2. If the + verification logic were to change or if http2.c started passing in more + IVs without increasing the output buffer size, the overflow could become + reachable, and libcurl/curl might start leaking memory contents to + servers/proxies... -- configure: trust pkg-config when it's used for zlib + Closes #12101 - The library flags retrieved from pkg-config were later thrown out and - harded-coded, which negates the whole reason to use pkg-config. - Also, previously, the assumption was made that --libs-only-l and - --libs-only-L are the full decomposition of --libs, which is untrue and - would not allow linking against a static zlib. The new approach is - better in that it uses --libs, although only if --libs-only-l returns - nothing. +Daniel Stenberg (13 Oct 2023) - Bug: https://curl.se/mail/lib-2023-08/0081.html - Reported-by: Randall - Closes #11778 +- openssl: avoid BN_num_bits() NULL pointer derefs -Stefan Eissing (1 Sep 2023) + Reported-by: icy17 on github + Fixes #12099 + Closes #12100 -- CI/ngtcp2: clear wolfssl for when cache is ignored +- wolfssl: require WOLFSSL_SYS_CA_CERTS for loading system CA - Closes #11783 + This define is set in wolfssl's options.h file when this function and + feature is present. Handles both builds with the feature explicitly + disabled and wolfSSL versions before 5.5.2 - which introduced this API + call. -Daniel Stenberg (1 Sep 2023) + Closes #12108 -- RELEASE-NOTES: synced +- tool_urlglob: make multiply() bail out on negative values -Nicholas Nethercote (1 Sep 2023) + - Does not work correctly with negative values + - use __builtin_mul_overflow() on gcc -- hyper: fix a progress upload counter bug + Reported-by: Torben Dury + Closes #12102 - `Curl_pgrsSetUploadCounter` should be a passed a total count, not an - increment. +Loïc Yhuel (13 Oct 2023) - This changes the failing diff for test 579 with hyper from this: - ``` - Progress callback called with UL 0 out of 0[LF] - -Progress callback called with UL 8 out of 0[LF] - -Progress callback called with UL 16 out of 0[LF] - -Progress callback called with UL 26 out of 0[LF] - -Progress callback called with UL 61 out of 0[LF] - -Progress callback called with UL 66 out of 0[LF] - +Progress callback called with UL 29 out of 0[LF] - ``` - to this: - ``` - Progress callback called with UL 0 out of 0[LF] - -Progress callback called with UL 8 out of 0[LF] - -Progress callback called with UL 16 out of 0[LF] - -Progress callback called with UL 26 out of 0[LF] - -Progress callback called with UL 61 out of 0[LF] - -Progress callback called with UL 66 out of 0[LF] - +Progress callback called with UL 40 out of 0[LF] - ``` - Presumably a step in the right direction. +- cmake: fix CURL_DISABLE_GETOPTIONS - Closes #11780 + - Add CURL_DISABLE_GETOPTIONS to curl_config.h.cmake. -Daniel Stenberg (1 Sep 2023) + Prior to this change the option had no effect because it was missing + from that file. -- awssiv4: avoid freeing the date pointer on error + Closes https://github.com/curl/curl/pull/12091 - Since it was not allocated, don't free it even if it was wrong syntax +- easy_lock: add a pthread_mutex_t fallback - Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61908 + This allows to keep the init threadsafe with gcc < 4.9.0 (no C11 + atomics). - Follow-up to b137634ba3adb + Closes https://github.com/curl/curl/pull/12090 - Closes #11782 +Viktor Szakats (12 Oct 2023) -Stefan Eissing (1 Sep 2023) +- CI: add autotools, out-of-tree, debug build to distro check job -- CI: ngtcp2-linux: use separate caches for tls libraries + Add a job that builds curl from a generated source tarball sample, with + autotools, out-of-tree, in debug mode. - allow ever changing master for wolfssl + Ref: #12085 + Closes #12088 - Closes #11766 +Daniel Stenberg (12 Oct 2023) -- replace `master` as wolfssl-version with recent commit +- http: avoid Expect: 100-continue if Upgrade: is used -- wolfssl, use master again in CI + Reported-by: Daniel Jelinski + Fixes #12022 + Closes #12062 - - with the shared session update fix landed in master, it - is time to use that in our CI again +Jan Alexander Steffens (heftig) (12 Oct 2023) -Nicholas Nethercote (31 Aug 2023) +- docs: use SOURCE_DATE_EPOCH for generated manpages -- tests: fix formatting errors in `FILEFORMAT.md`. + This should make builds from Git reproducible. - Without the surrounding backticks, these tags get swallowed when the - markdown is rendered. + Closes #12092 - Closes #11777 +Daniel Stenberg (12 Oct 2023) -Viktor Szakats (31 Aug 2023) +- RELEASE-NOTES: synced -- cmake: add support for `CURL_DEFAULT_SSL_BACKEND` + Bumped to 8.4.1 - Allow overriding the default TLS backend via a CMake setting. +Viktor Szakats (12 Oct 2023) - E.g.: - `cmake [...] -DCURL_DEFAULT_SSL_BACKEND=mbedtls` +- cmake: fix `HAVE_H_ERRNO_ASSIGNABLE` detection - Accepted values: bearssl, gnutls, mbedtls, openssl, rustls, - schannel, secure-transport, wolfssl + Fix `HAVE_H_ERRNO_ASSIGNABLE` to not run, only compile its test snippet, + aligning this with autotools. This fixes an error when doing + cross-builds and also actually detects this feature. It affected systems + not allowlisted into this, e.g. SerenityOS. - The passed string is baked into the curl/libcurl binaries. - The value is case-insensitive. + We used this detection result to enable `HAVE_GETADDRINFO_THREADSAFE`. - We added a similar option to autotools in 2017 via - c7170e20d0a18ec8a514b4daa53bcdbb4dcb3a05. + Follow-up to 04a3a377d83fd72c4cf7a96c9cb6d44785e33264 #11979 + Ref: #12095 (closed in favour of this patch) + Ref: #11964 (effort to sync cmake detections with autotools) - TODO: Convert to lowercase to improve reproducibility. + Reported-by: Kartatz on Github + Assisted-by: Kartatz on Github + Fixes #12093 + Closes #12094 - Closes #11774 +- build: add `src/.checksrc` to source tarball -- sectransp: fix compiler warnings + Regression from e5bb88b8f824ed87620bd923552534c83c2a516e #11958 - https://github.com/curl/curl-for-win/actions/runs/6037489221/job/16381860220# - step:3:11046 - ``` - /Users/runner/work/curl-for-win/curl-for-win/curl/lib/vtls/sectransp.c:2435:1 - 4: warning: unused variable 'success' [-Wunused-variable] - OSStatus success; - ^ - /Users/runner/work/curl-for-win/curl-for-win/curl/lib/vtls/sectransp.c:3300:4 - 4: warning: unused parameter 'sha256len' [-Wunused-parameter] - size_t sha256len) - ^ - ``` + Bug: https://github.com/curl/curl/pull/11958#issuecomment-1757079071 + Reported-by: Romain Geissler + Fixes #12084 + Closes #12085 - Closes #11773 +Version 8.4.0 (11 Oct 2023) -- tidy-up: mostly whitespace nits +Daniel Stenberg (11 Oct 2023) - - delete completed TODO from `./CMakeLists.txt`. - - convert a C++ comment to C89 in `./CMake/CurlTests.c`. - - delete duplicate EOLs from EOF. - - add missing EOL at EOF. - - delete whitespace at EOL (except from expected test results). - - convert tabs to spaces. - - convert CRLF EOLs to LF in GHA yaml. - - text casing fixes in `./CMakeLists.txt`. - - fix a codespell typo in `packages/OS400/initscript.sh`. +- RELEASE-NOTES: synced - Closes #11772 +- THANKS: add contributors from 8.4.0 -Dan Fandrich (31 Aug 2023) +Jay Satiro (11 Oct 2023) -- CI: remove Windows builds from Cirrus, without replacement +- socks: return error if hostname too long for remote resolve - If we don't do this, all coverage on Cirrus will cease in a few days. By - removing the Windows builds, the FreeBSD one should still continue - as before. The Windows builds will need be moved to another service to - maintain test coverage. + Prior to this change the state machine attempted to change the remote + resolve to a local resolve if the hostname was longer than 255 + characters. Unfortunately that did not work as intended and caused a + security issue. - Closes #11771 + Bug: https://curl.se/docs/CVE-2023-38545.html -- CI: switch macOS ARM build from Cirrus to Circle CI +Stefan Eissing (10 Oct 2023) - Cirrus is drastically reducing their free tier on Sept. 1, so they will - no longer perform all these builds for us. All but one build has been - moved, with the LibreSSL one being dropped because of linking problems - on Circle. +- CI: remove slowed-network tests - One important note about this change is that Circle CI is currently - directing all these builds to x86_64 hardware, despite them requesting - ARM. This is because ARM nodes are scheduled to be available on the - free tier only in December. This reduces our architectural diversity - until then but it should automatically come back once those machines are - enabled. + - remove these tests as they are currently not reliable in our CI + setups. -- CI: use the right variable for BSD make + curl handles the test cases, but CI sometimes fails on these due to + additional conditions. Rather than mix them in, an additional CI job + will be added in the future that is specific to them. - BSD uses MAKEFLAGS instead of MAKE_FLAGS so it wasn't doing parallel - builds before. + Closes https://github.com/curl/curl/pull/12075 -- CI: drop the FreeBSD 12.X build +Jay Satiro (10 Oct 2023) - Cirrus' new free tier won't let us have many builds, so drop the - nonessential ones. The FreeBSD 13.X build will still give us the most - relevant FreeBSD coverage. +- libcurl-env-dbg.3: move debug variables from libcurl-env.3 -- CI: move the Alpine build from Cirrus to GHA + - Move documentation of libcurl environment variables used only in debug + builds from libcurl-env into a separate document libcurl-env-dbg. - Cirrus is reducing their free tier to next to nothing, so we must move - builds elsewhere. + - Document more debug environment variables. -Stefan Eissing (30 Aug 2023) + Previously undocumented or missing a description: -- test_07_upload.py: fix test_07_34 curl args + CURL_ALTSVC_HTTP, CURL_DBG_SOCK_WBLOCK, CURL_DBG_SOCK_WPARTIAL, + CURL_DBG_QUIC_WBLOCK, CURL_DEBUG, CURL_DEBUG_SIZE, CURL_GETHOSTNAME, + CURL_HSTS_HTTP, CURL_FORCETIME, CURL_SMALLREQSEND, CURL_SMALLSENDS, + CURL_TIME. - - Pass correct filename to --data-binary. + Closes https://github.com/curl/curl/pull/11811 - Prior to this change --data-binary was passed an incorrect filename due - to a missing separator in the arguments list. Since aacbeae7 curl will - error on incorrect filenames for POST. +Dan Fandrich (9 Oct 2023) - Fixes https://github.com/curl/curl/issues/11761 - Closes https://github.com/curl/curl/pull/11763 +- test670: increase the test timeout -Nicholas Nethercote (30 Aug 2023) + This should make it more immune to loaded servers. -- tests: document which tests fail due to hyper's lack of trailer support. + Ref: #11328 - Closes #11762 +Stefan Eissing (9 Oct 2023) -- docs: removing "pausing transfers" from HYPER.md. +- MQTT: improve receive of ACKs - It's a reference to #8600, which was fixed by #9070. + - add `mq->recvbuf` to provide buffering of incomplete + ACK responses + - continue ACK reading until sufficient bytes available + - fixes test failures on low network receives - Closes #11764 + Closes #12071 -Patrick Monnerat (30 Aug 2023) +Viktor Szakats (9 Oct 2023) -- os400: handle CURL_TEMP_PRINTF() while building bind source +- quic: fix BoringSSL build - Closes #11547 + Add guard around `SSL_CTX_set_ciphersuites()` use. -- os400: build test servers + Bug: https://github.com/curl/curl/pull/12065#issuecomment-1752171885 - Also fix a non-compliant main prototype in disabled.c. + Follow-up to aa9a6a177017e4b74d33cdf85a3594900f4a7f81 - Closes #11547 + Co-authored-by: Jay Satiro + Reviewed-by: Daniel Stenberg + Closes #12067 -- tests: fix compilation error for os400 +Stefan Eissing (9 Oct 2023) - OS400 uses BSD 4.3 setsockopt() prototype by default: this does not - define parameter as const, resulting in an error if actual parameter is - const. Remove the const keyword from the actual parameter cast: this - works in all conditions, even if the formal parameter uses it. +- test1540: improve reliability - Closes #11547 + - print that bytes have been received on pausing, but not how many -- os400: make programs and command name configurable + Closes #12069 - Closes #11547 +- test2302: improve reliability -- os400: move build configuration parameters to a separate script + - make result print collected write data, unless + change in meta flags is detected + - will show same result even when data arrives via + several writecb invocations - They can then easily be overriden in a script named "config400.override" - that is not part of the distribution. + Closes #12068 - Closes #11547 +Daniel Stenberg (9 Oct 2023) -- os400: implement CLI tool +- curl_easy_pause: set "in callback" true on exit if true - This is provided as a QADRT (ascii) program, a link to it in the IFS and - a minimal CL command. + Because it might have called another callback in the mean time that then + set the bit FALSE on exit. - Closes #11547 + Reported-by: Jay Satiro + Fixes #12059 + Closes #12061 -Matthias Gatto (30 Aug 2023) +Viktor Szakats (8 Oct 2023) -- lib: fix aws-sigv4 having date header twice in some cases +- h3: add support for ngtcp2 with AWS-LC builds - When the user was providing the header X-XXX-Date, the header was - re-added during signature computation, and we had it twice in the - request. + ``` + curl 8.4.0-DEV (x86_64-apple-darwin) libcurl/8.4.0-DEV (SecureTransport) AWS- + LC/1.15.0 nghttp2/1.56.0 ngtcp2/0.19.1 nghttp3/0.15.0 + Release-Date: [unreleased] + Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps + mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp ws wss + Features: alt-svc AsynchDNS HSTS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefile Multi + SSL NTLM SSL threadsafe UnixSockets + ``` - Reported-by: apparentorder@users.noreply.github.com + Also delete an obsolete GnuTLS TODO and update the header comment in + `FindNGTCP2.cmake`. - Signed-off-by: Matthias Gatto + Reviewed-by: Daniel Stenberg + Closes #12066 - Fixes: https://github.com/curl/curl/issues/11738 - Closes: https://github.com/curl/curl/pull/11754 +- build: do not publish `HAVE_BORINGSSL`, `HAVE_AWSLC` macros -Jay Satiro (30 Aug 2023) + Syncing this up with CMake. -- multi: remove 'processing: ' debug message + Source code uses the built-in `OPENSSL_IS_AWSLC` and + `OPENSSL_IS_BORINSSL` macros to detect BoringSSL and AWS-LC. No help is + necessary from the build tools. - - Remove debug message added by e024d566. + The one use of `HAVE_BORINGSSL` in the source turned out to be no longer + necessary for warning-free BoringSSL + Schannel builds. Ref: #1610 #2634 - Closes https://github.com/curl/curl/pull/11759 + autotools detects this anyway for display purposes. + CMake detects this to decide whether to use the BoringSSL-specific + crypto lib with ngtcp2. It detects AWS-LC, but doesn't use the detection + result just yet (planned in #12066). -- ftp: fix temp write of ipv6 address + Ref: #11964 - - During the check to differentiate between a port and IPv6 address - without brackets, write the binary IPv6 address to an in6_addr. + Reviewed-by: Daniel Stenberg + Reviewed-by: Jay Satiro + Closes #12065 - Prior to this change the binary IPv6 address was erroneously written to - a sockaddr_in6 'sa6' when it should have been written to its in6_addr - member 'sin6_addr'. There's no fallout because no members of 'sa6' are - accessed before it is later overwritten. +Marc Hoersken (8 Oct 2023) - Closes https://github.com/curl/curl/pull/11747 +- CI: move distcheck job from Azure Pipelines to GitHub Actions -- tool: change some fopen failures from warnings to errors + This will allow for more trigger excludes within Azure Pipelines. - - Error on missing input file for --data, --data-binary, - --data-urlencode, --header, --variable, --write-out. + Also fixes seemingly broken check with scripts/installcheck.sh. + Ref: 190374c74ec4e5247d9066544c86e8d095e1d7b5 - Prior to this change if a user of the curl tool specified an input file - for one of the above options and that file could not be opened then it - would be treated as zero length data instead of an error. For example, a - POST using `--data @filenametypo` would cause a zero length POST which - is probably not what the user intended. + Assisted-by: Philip Heiduck + Closes #9532 - Closes https://github.com/curl/curl/pull/11677 +Daniel Stenberg (8 Oct 2023) -- hostip: fix typo +- url: fall back to http/https proxy env-variable if ws/wss not set -Davide Masserut (29 Aug 2023) + Reported-by: Craig Andrews + Fixes #12031 + Closes #12058 -- tool: avoid including leading spaces in the Location hyperlink +Stefan Eissing (8 Oct 2023) - Co-authored-by: Dan Fandrich +- cf-socket: simulate slow/blocked receives in debug - Closes #11735 + add 2 env variables for non-UDP sockets: + 1. CURL_DBG_SOCK_RBLOCK: percentage of receive calls that randomly + should return EAGAIN + 2. CURL_DBG_SOCK_RMAX: max amount of bytes read from socket -Daniel Stenberg (29 Aug 2023) + Closes #12035 -- SECURITY-PROCESS.md: not a sec issue: Tricking user to run a cmdline +- http2: refused stream handling for retry - Closes #11757 + - answer HTTP/2 streams refused via a GOAWAY from the server to + respond with CURLE_RECV_ERROR in order to trigger a retry + on another connection -- connect: stop halving the remaining timeout when less than 600 ms left + Reported-by: black-desk on github + Ref #11859 + Closes #12054 - When curl wants to connect to a host, it always has a TIMEOUT. The - maximum time it is allowed to spend until a connect is confirmed. +Jay Satiro (8 Oct 2023) - curl will try to connect to each of the IP adresses returned for the - host. Two loops, one for each IP family. +- CURLOPT_DEBUGFUNCTION.3: warn about internal handles - During the connect loop, while curl has more than one IP address left to - try within a single address family, curl has traditionally allowed (time - left/2) for *this* connect attempt. This, to not get stuck on the - initial addresses in case the timeout but still allow later addresses to - get attempted. - - This has the downside that when users set a very short timeout and the - host has a large number of IP addresses, the effective result might be - that every attempt gets a little too short time. + - Warn that the user's debug callback may be called with the handle + parameter set to an internal handle. - This change stop doing the divided-by-two if the total time left is - below a threshold. This threshold is 600 milliseconds. + Without this warning the user may assume that the only handles their + debug callback receives are the easy handles on which they set + CURLOPT_DEBUGFUNCTION. - Closes #11693 + This is a follow-up to f8cee8cc which changed DoH handles to inherit + the debug callback function set in the user's easy handle. As a result + those handles are now passed to the user's debug callback function. -- asyn-ares: reduce timeout to 2000ms + Closes https://github.com/curl/curl/pull/12034 - When UDP packets get lost this makes for slightly faster retries. This - lower timeout is used by @c-ares itself by default starting next - release. +- url: fix typo - Closes #11753 +Daniel Stenberg (8 Oct 2023) -John Bampton (29 Aug 2023) +- test458: verify --expand-output, expanding a file name accepting option -- misc: remove duplicate words + Verifies the fix in #12055 (commit f2c8086ff15e6e995e1) - Closes #11740 +- tool_getparam: accept variable expansion on file names too -Daniel Stenberg (29 Aug 2023) + Reported-by: PBudmark on github + Fixes #12048 + Closes #12055 - RELEASE-NOTES: synced -- wolfSSL: avoid the OpenSSL compat API when not needed +- multi: do CURLM_CALL_MULTI_PERFORM at two more places - ... and instead call wolfSSL functions directly. + ... when it does a state transition but there is no particular socket or + timer activity. This was made apparent when commit b5bb84c removed a + superfluous timer expiry. - Closes #11752 + Reported-by: Dan Fandrich. + Fixes #12033 + Closes #12056 -Viktor Szakats (28 Aug 2023) +Viktor Szakats (7 Oct 2023) -- lib: fix null ptr derefs and uninitialized vars (h2/h3) +- GHA/linux: mbedtls 3.5.0 + minor dep bumps - Fixing compiler warnings with gcc 13.2.0 in unity builds. + Closes #12057 - Assisted-by: Jay Satiro - Assisted-by: Stefan Eissing - Closes #11739 +Dan Fandrich (7 Oct 2023) -Jay Satiro (28 Aug 2023) +- CI: bump OpenLDAP package version on FreeBSD -- secureserver.pl: fix stunnel version parsing + The old one is no longer available. - - Allow the stunnel minor-version version part to be zero. +Marc Hoersken (7 Oct 2023) - Prior to this change with the stunnel version scheme of . - if either part was 0 then version parsing would fail, causing - secureserver.pl to fail with error "No stunnel", causing tests that use - the SSL protocol to be skipped. As a practical matter this bug can only - be caused by a minor-version part of 0, since the major-version part is - always greater than 0. +- docs/libcurl/opts/Makefile.inc: add missing manpage files - Closes https://github.com/curl/curl/pull/11722 + Detected with #9532 -- secureserver.pl: fix stunnel path quoting +Dan Fandrich (7 Oct 2023) - - Store the stunnel path in the private variable $stunnel unquoted and - instead quote it in the command strings. +- tests: fix a race condition in ftp server disconnect - Prior to this change the quoted stunnel path was passed to perl's file - operators which cannot handle quoted paths. For example: + If a client disconnected and reconnected quickly, before the ftp server + had a chance to respond, the protocol message/ack (ping/pong) sequence + got out of sync, causing messages sent to the old client to be delivered + to the new. A disconnect must now be acknowledged and intermediate + requests thrown out until it is, which ensures that such synchronization + problems can't occur. This problem could affect ftp, pop3, imap and smtp + tests. - $stunnel = "\"/C/Program Files (x86)/stunnel/bin/tstunnel\""; - if(-x $stunnel or -x "$stunnel") - # false even if path exists and is executable + Fixes #12002 + Closes #12049 - Our other test scripts written in perl, unlike this one, use servers.pm - which has a global $stunnel variable with the path stored unquoted and - therefore those scripts don't have this problem. +Viktor Szakats (7 Oct 2023) - Closes https://github.com/curl/curl/pull/11721 +- appveyor: bump mingw-w64 job to gcc 13 (was: 8) -Daniel Stenberg (28 Aug 2023) + This sets gcc 6, 7, 9, 13 in our test mix (was: 6, 7, 8, 9). + Adding a modern gcc version to the tests. -- altsvc: accept and parse IPv6 addresses in response headers + (The gcc 8 job used to take around 50 minutes. The new image with gcc 13 + finished in 32, 35, 34 minutes in the 3 test runs so far.) - Store numerical IPv6 addresses in the alt-svc file with the brackets - present. + It also adds a modern CMake version and OS env to our mingw-w64 builds. - Verify with test 437 and 438 + Closes #12051 - Fixes #11737 - Reported-by: oliverpool on github - Closes #11743 +David Benjamin (6 Oct 2023) -- libtest: use curl_free() to free libcurl allocated data +- openssl: use X509_ALGOR_get0 instead of reaching into X509_ALGOR - In several test programs. These mistakes are not detected or a problem - as long as memdebug.h is included, as that provides the debug wrappers - for all memory functions in the same style libcurl internals do it, - which makes curl_free and free effectively the same call. + While the struct is still public in OpenSSL, there is a (somewhat + inconvenient) accessor. Use it to remain compatible if it becomes opaque + in the future. - Reported-by: Nicholas Nethercote - Closes #11746 + Closes #12038 -Jay Satiro (28 Aug 2023) +Daniel Stenberg (6 Oct 2023) -- disable.d: explain --disable not implemented prior to 7.50.0 +- curl_easy_pause.3: mention it works within callbacks - Option -q/--disable was added in 5.0 but only -q was actually - implemented. Later --disable was implemented in e200034 (precedes - 7.49.0), but incorrectly, and fixed in 6dbc23c (precedes 7.50.0). + Reported-by: Maxim Dzhura + Bug: https://curl.se/mail/lib-2023-10/0010.html + Closes #12046 - Reported-by: pszlazak@users.noreply.github.com +- curl_easy_pause.3: mention h2/h3 buffering - Fixes https://github.com/curl/curl/issues/11710 - Closes #11712 + Asked-by: Maxim Dzhura + Ref: https://curl.se/mail/lib-2023-10/0011.html -Nicholas Nethercote (28 Aug 2023) + Closes #12045 -- hyper: fix ownership problems +Viktor Szakats (6 Oct 2023) - Some of these changes come from comparing `Curl_http` and - `start_CONNECT`, which are similar, and adding things to them that are - present in one and missing in another. +- cmake: re-add missed C89 headers for specific detections - The most important changes: - - In `start_CONNECT`, add a missing `hyper_clientconn_free` call on the - happy path. - - In `start_CONNECT`, add a missing `hyper_request_free` on the error - path. - - In `bodysend`, add a missing `hyper_body_free` on an early-exit path. - - In `bodysend`, remove an unnecessary `hyper_body_free` on a different - error path that would cause a double-free. - https://docs.rs/hyper/latest/hyper/ffi/fn.hyper_request_set_body.html - says of `hyper_request_set_body`: "This takes ownership of the - hyper_body *, you must not use it or free it after setting it on the - request." This is true even if `hyper_request_set_body` returns an - error; I confirmed this by looking at the hyper source code. + We removed C89 `setjmp.h` and `signal.h` detections and excluded them + from the global header list we use when detecting functions [1]. Then + missed to re-add these headers to the specific functions which need + them to be detected [2]. Fix this omission in this patch. - Other changes are minor but make things slightly nicer. + [1] Follow-up to 3795fcde995d96db641ddbcc8a04f9f0f03bef9f #11951 + [2] Follow-up to 96c29900bcec32dd6bc8e9857c8871ff4b8b8ed9 #11940 - Closes #11745 + Closes #12043 -Daniel Stenberg (28 Aug 2023) +Daniel Stenberg (6 Oct 2023) -- multi.h: the 'revents' field of curl_waitfd is supported +- multi: set CURLM_CALL_MULTI_PERFORM after switch to DOING_MORE - Since 6d30f8ebed34e7276 + Since there is nothing to wait for there. Avoids the test 1233 hang + reported in #12033. - Reported-by: Nicolás Ojeda Bär - Ref: #11748 - Closes #11749 + Reported-by: Dan Fandrich + Closes #12042 -Gerome Fournier (27 Aug 2023) +Dan Fandrich (5 Oct 2023) -- tool_paramhlp: improve str2num(): avoid unnecessary call to strlen() +- test1903: actually verify the cookies after the test - Closes #11742 + The test otherwise could do just about anything (except leak memory in + debug mode) and its bad behaviour wouldn't be detected. Now, check the + resulting cookie file to ensure the cookies are still there. -Daniel Stenberg (27 Aug 2023) + Closes #12041 -- docs: mention critical files in same directories as curl saves +- test: add missing s - ... cannot be fully protected. Don't do it. + The tests will otherwise fail if curl has them disabled. - Co-authored-by: Jay Satiro - Reported-by: Harry Sintonen - Fixes #11530 - Closes #11701 +- test1906: set a lower timeout since it's hit on Windows -John Hawthorn (26 Aug 2023) + msys2 builds actually hit the connect timeout in normal operation, so + lower the timeout from 5 minutes to 5 seconds to reduce test time. -- OpenSSL: clear error queue after SSL_shutdown + Ref: #11328 + Closes #12036 - We've seen errors left in the OpenSSL error queue (specifically, - "shutdown while in init") by adding some logging it revealed that the - source was this file. +Daniel Stenberg (5 Oct 2023) - Since we call SSL_read and SSL_shutdown here, but don't check the return - code for an error, we should clear the OpenSSL error queue in case one - was raised. +- RELEASE-NOTES: synced - This didn't affect curl because we call ERR_clear_error before every - write operation (a0dd9df9ab35528eb9eb669e741a5df4b1fb833c), but when - libcurl is used in a process with other OpenSSL users, they may detect - an OpenSSL error pushed by libcurl's SSL_shutdown as if it was their - own. +Jay Satiro (5 Oct 2023) - Co-authored-by: Satana de Sant'Ana +- idn: fix WinIDN null ptr deref on bad host - Closes #11736 + - Return CURLE_URL_MALFORMAT if IDN hostname cannot be converted from + UTF-8 to UTF-16. -Alexander Kanavin (25 Aug 2023) + Prior to this change a failed conversion erroneously returned CURLE_OK + which meant 'decoded' pointer (what would normally point to the + punycode) would not be written to, remain NULL and be dereferenced + causing an access violation. -- tests: update cookie expiry dates to far in the future + Closes https://github.com/curl/curl/pull/11983 - This allows testing Y2038 with system time set to after that, so that - actual Y2038 issues can be exposed, and not masked by expiry errors. +Dan Fandrich (4 Oct 2023) - Fixes #11576 - Closes #11610 +- tests: close the shell used to start sshd -John Bampton (25 Aug 2023) + This shell isn't needed once sshd starts, so use "exec" so it doesn't + stick around. -- misc: fix spelling + Closes #12032 - Closes #11733 +Daniel Stenberg (4 Oct 2023) -Daniel Stenberg (25 Aug 2023) +- base64: also build for curl -- cmdline-opts/page-header: clarify stronger that !opt == URL + Since the tool itself now uses the base64 code using the curlx way, it + needs to build also when the tool needs it. Starting now, the tool build + defines BULDING_CURL to allow lib-side code to use it. - Everything provided on the command line that is not an option (or an - argument to an option) is treated as a URL. + Follow-up to 2e160c9c6525 - Closes #11734 + Closes #12010 -- tests/runner: fix %else handling +Eduard Strehlau (4 Oct 2023) - Getting the show state proper for %else and %endif did not properly work - in nested cases. +- tests: Fix zombie processes left behind by FTP tests. - Follow-up to 3d089c41ea9 + ftpserver.pl correctly cleans up spawned server processes, + but forgets to wait for the shell used to spawn them. + This is barely noticeable during a normal testrun, + but causes process exhaustion and test failure + during a complete torture run of the FTP tests. - Closes #11731 + Fixes #12018 + Closes #12020 -Nicholas Nethercote (25 Aug 2023) +Dan Fandrich (4 Oct 2023) -- docs: Remove mention of #10803 from `KNOWN_BUGS`. +- github/labeler: improve labeler matches - Because the leaks have been fixed. +- test574: add a timeout to the test -- c-hyper: fix another memory leak in `Curl_http`. + This one hangs occasionally, so this will speed up a test run and allow + logs to be seen when it does. - There is a `hyper_clientconn_free` call on the happy path, but not one - on the error path. This commit adds one. + Closes #12025 - Fixes the second memory leak reported by Valgrind in #10803. +- tests: propagate errors in libtests - Fixes #10803 - Closes #11729 + Use the test macros to automatically propagate some errors, and check + and log others while running the tests. This can help in debugging + exactly why a test has failed. -- c-hyper: fix a memory leak in `Curl_http`. +- tests: set --expect100-timeout to improve test reliability - A request created with `hyper_request_new` must be consumed by either - `hyper_clientconn_send` or `hyper_request_free`. + On an overloaded server, the default 1 second timeout can go by without + the test server having a chance to respond with the expected headers, + causing tests to fail. Increase the 1 second timeout to 99 seconds so + this failure mode is no longer a problem on test 1129. Some other tests + already set a high value, but make them consistently 99 seconds so if + something goes wrong the test is stalled for less time. - This is not terrifically clear from the hyper docs -- - `hyper_request_free` is documented only with "Free an HTTP request if - not going to send it on a client" -- but a perusal of the hyper code - confirms it. + Ref: #11328 - This commit adds a `hyper_request_free` to the `error:` path in - `Curl_http` so that the request is consumed when an error occurs after - the request is created but before it is sent. +- CI: ignore the "flaky" and "timing-dependent" test results in CMake - Fixes the first memory leak reported by Valgrind in #10803. + This was already done for automake builds but CMake builds were missed. + Test 1086 actually causes the test harness to crash with: - Closes #11729 + Warning: unable to close filehandle DWRITE properly: Broken pipe at C:/projec + ts/curl/tests/ftpserver.pl line 527 -Daniel Stenberg (25 Aug 2023) + Rather than fix it now, this change leaves test 1086 entirely skipped on + those builds that show this problem. -- RELEASE-NOTES: synced + Follow-up to 589dca761 -John Bampton (25 Aug 2023) + Ref: #11865 -- misc: spellfixes +Viktor Szakats (4 Oct 2023) - Closes #11730 +- cmake: improve OpenLDAP builds -Daniel Stenberg (25 Aug 2023) + - cmake: detect OpenLDAP based on function `ldap_init_fd`. + autotools does this. autotools also publishes this detection result + in `HAVE_LDAP_INIT_FD`. We don't mimic that with CMake as the source + doesn't use this value. (it might need to be remove-listed in + `scripts/cmp-config.pl` for future OpenLDAP test builds.) + This also deletes existing self-declaration method via the + CMake-specific `CURL_USE_OPENLDAP` configuration. -- tests: add support for nested %if conditions + - cmake: define `LDAP_DEPRECATED=1` for OpenLDAP. + Like autotools does. This fixes a long list of these warnings: + ``` + /usr/local/opt/openldap/include/ldap.h:1049:5: warning: 'LDAP_DEPRECATED' i + s not defined, evaluates to 0 [-Wundef] + ``` - Provides more flexiblity to test cases. + - cmake: delete LDAP TODO comment no longer relevant. - Also warn and bail out if there is an '%else' or %endif' without a - preceeding '%if'. + Also: - Ref: #11610 - Closes #11728 + - autotools: replace domain name `dummy` with `0.0.0.0` in LDAP feature + detection functions. -- time-cond.d: mention what happens on a missing file + Ref: #11964 (effort to sync cmake detections with autotools) - Closes #11727 + Closes #12024 -Christian Hesse (24 Aug 2023) +- cmake: fix unity builds for more build combinations -- docs/cmdline-opts: match the current output + By using unique static function/variable names in source files + implementing these interfaces. - The release date has been added in output, reflect that in documentation. + - OpenLDAP combined with any SSH backend. - Closes #11723 + - MultiSSL with mbedTLS, OpenSSL, wolfSSL, SecureTransport. -Daniel Stenberg (24 Aug 2023) + Closes #12027 -- lib: minor comment corrections +Daniel Stenberg (4 Oct 2023) -- docs: rewrite to present tense +- tests: remove leading spaces from some tags - ... instead of using future tense. + The threee tags ``, `` and `` were frequently used + with a leading space that this removes. The reason this habbit is so + widespread in testcases is probably that they have been copy and pasted. - + numerous cleanups and improvements - + stick to "reuse" not "re-use" - + fewer contractions + Hence, fixing them all now might curb this practice from now on. - Closes #11713 + Closes #12028 -- urlapi: setting a blank URL ("") is not an ok URL +Viktor Szakats (4 Oct 2023) - Test it in 1560 - Fixes #11714 - Reported-by: ad0p on github - Closes #11715 +- GHA: bump actions/checkout -- spelling: use 'reuse' not 're-use' in code and elsewhere + Follow-up to 2e0fa50fc16b9339f51e0a7bfff0352829323acb #11964 + Follow-up to c39585d9b7ef3cbfc1380812dec60e7b275b6af3 #12000 - Unify the spelling as both versions were previously used intermittently + Closes #12023 - Closes #11717 +- spelling: fix codespell 2.2.6 typos -Michael Osipov (23 Aug 2023) + Closes #12019 -- system.h: add CURL_OFF_T definitions on HP-UX with HP aCC +Daniel Stenberg (3 Oct 2023) - HP-UX on IA64 provides two modes: 32 and 64 bit while 32 bit being the - default one. Use "long long" in 32 bit mode and just "long" in 64 bit - mode. +- GHA: add workflow to compare configure vs cmake outputs - Closes #11718 + Uses scripts/cmp-config.pl two compare two curl_config.h files, + presumbly generated with configure and cmake. It displays the + differences and filters out a lot of known lines we ignore. -Dan Fandrich (22 Aug 2023) + The script also shows the matches that were *not* used. Possibly + subjects for removal. -- tests: don't call HTTP errors OK in test cases + Closes #11964 - Some HTTP errors codes were accompanied by the text OK, which causes - some cognitive dissonance when reading them. +- appveyor: enable test 571 -- http: close the connection after a late 417 is received + Follow-up from 8a940fd55c175f7 / #12013 - In this situation, only part of the data has been sent before aborting - so the connection is no longer usable. + Closes #12017 - Assisted-by: Jay Satiro - Fixes #11678 - Closes #11679 +Viktor Szakats (3 Oct 2023) -- runtests: slightly increase the longest log file displayed +- build: alpha-sort source files for lib and src - The new limit provides enough space for a 64 KiB data block to be logged - in a trace file, plus a few lines at the start and end for context. This - happens to be the amount of data sent at a time in a PUT request. + Closes #12014 -- tests: add delay command to the HTTP server +- cmake: delete old `HAVE_LDAP_URL_PARSE` logic - This adds a delay after client connect. + Left there by accident after adding proper detection for this. -Daniel Stenberg (22 Aug 2023) + Follow-up to 772f0d8edf1c3c2745543f42388ccec5a16ee2c0 #12006 -- cirrus: install everthing with pkg, avoid pip + Ref: #11964 (effort to sync cmake detections with autotools) - Assisted-by: Sevan Janiyan + Closes #12015 - Closes #11711 +Stefan Eissing (3 Oct 2023) -- curl_url*.3: update function descriptions +- tests: increase lib571 timeout from 3s to 30s - - expand and clarify several descriptions - - avoid using future tense all over + - 3s is too short for our CI, making this test fail occasionally + - test usually experiences no delay run locally, so 30s wont hurt - Closes #11708 + Closes #12013 -- RELEASE-NOTES: synced +Viktor Szakats (3 Oct 2023) -Stefan Eissing (21 Aug 2023) +- cmake: fix unity with Windows Unicode + TrackMemory -- CI/cirrus: disable python install on FreeBSD + Found the root cause of the startup crash in unity builds with Unicode + and TrackMemory enabled at the same time. - - python cryptography package does not build build FreeBSD - - install just mentions "error" - - this gets the build and the main test suite going again + We must make sure that the `memdebug.h` header doesn't apply to + `lib/curl_multibyte.c` (as even noted in a comment there.) In unity + builds all headers apply to all sources, including `curl_multibyte.c`. + This probably resulted in an infinite loop on startup. - Closes #11705 + Exclude this source from unity compilation with TrackMemory enabled, + in both libcurl and curl tool. Enable unity mode for a debug Unicode + CI job to keep it tested. Also delete the earlier workaround that + fully disabled unity for affected builds. -- test2600: fix flakiness on low cpu + Follow-up to d82b080f6374433ce7c98241329189ad2d3976f8 #12005 + Follow-up to 3f8fc25720900b14b7432f4bd93407ca15311719 #11095 - - refs #11355 where failures to to low cpu resources in CI - are reported - - vastly extend CURLOPT_CONNECTTIMEOUT_MS and max durations - to test cases - - trigger Curl_expire() in test filter to allow re-checks before - the usual 1second interval + Closes #11928 - Closes #11690 +- cmake: disable unity mode with Windows Unicode + TrackMemory -Maksim Sciepanienka (20 Aug 2023) + "TrackMemory" is `ENABLE_DEBUG=ON` (aka `ENABLE_CURLDEBUG=ON`, + aka `-DCURLDEBUG`). -- tool_urlglob: use the correct format specifier for curl_off_t in msnprintf + There is an issue with memory tracking and Unicode when built in "unity" + mode, which results in the curl tool crashing right on startup, even + without any command-line option. Interestingly this doesn't happen under + WINE (at least on the system I tested this on), but consistenly happens + on real Windows machines. Crash is 0xC0000374 heap corruption. Both + shared and static curl executables are affected. - Closes #11698 + This limitation probably won't hit too many people, but it remains + a TODO to find and fix the root cause and drop this workaround. -Daniel Stenberg (20 Aug 2023) + Example builds and runs: + https://ci.appveyor.com/project/curlorg/curl/builds/48169111/job/17cptxhtpubd + 7iwj#L313 (static) + https://ci.appveyor.com/project/curlorg/curl/builds/48169111/job/76e1ge758tby + qu9c#L317 (shared) -- test687/688: two more basic --xattr tests + Follow-up to 3f8fc25720900b14b7432f4bd93407ca15311719 #11095 - Closes #11697 + Ref: #11928 + Closes #12005 -- cmdline-opts/docs: mentioned the negative option part +- cmake: tidy-up `NOT_NEED_LBER_H` detection - ... for --no-alpn and --no-buffer in the same style done for other --no- - options: + Follow-up to 772f0d8edf1c3c2745543f42388ccec5a16ee2c0 #12006 - "Note that this is the negated option name documented." +- appveyor: rewrite batch in PowerShell + CI improvements - Closes #11695 + 1. Rewrite in PowerShell: -Emanuele Torre (19 Aug 2023) + - rewrite MS-DOS batch build script in PowerShell. + - move some bash operations into native PowerShell. + - fixups for PowerShell insisting on failure when a command outputs + something to stderr. + - fix to actually run `curl -V` after every build. + (and exclude ARM64 builds.) + - also say why we skipped `curl -V` if we had to skip. + - fix CMake warnings about unused configuration variables, by adapting + these dynamically for build cases. + - dedupe OpenSSL path into a variable. + - disable `test1451` failing with a warning anyway due to missing python + impacket. (after trying and failing to install impacket) + PowerShell promotes these warnings to errors by PowerShell. We can also + suppress they wholesale if they start causing issues in the future, + like we already to with `autoreconf` and `./configure`. -- tool/var: also error when expansion result starts with NUL + PowerShell is better than MS-DOS batches, so the hope is this makes it + easier to extend and maintain the AppVeyor build logic. POSIX/bash isn't + supported inline by AppVeyor on Windows build machines, but we are okay + to keep it in an external script, so it's also an option. - Expansions whose output starts with NUL were being expanded to the empty - string, and not being recognised as values that contain a NUL byte, and - should error. + 2. CI improvements: - Closes #11694 + - enable tests for a "unity" build job. + - speed-up CI initialization by using shallow clones of the curl repo. + - speed-up CMake MSVC jobs with `TrackFileAccess=false`. + - enable parallelism in `VisualStudioSolution` builds. + - display CMake version before builds. + - always show the CPU in job names. + - tell which jobs are build-only in job names. + - move `TESTING:` value next to `DISABLED_TESTS:` in two jobs. + - add `config.log` (autotools) to dumped logs (need to enable manually). -Daniel Stenberg (19 Aug 2023) + 3. Style: -- tests: add 'large-time' as a testable feature + - use single-quotes in YAML like we do in other CI YAML files. + It also allows to drop quoting characters and lighter to write/read. + (keep double quotes for PowerShell strings needing expansion.) - This allows test cases to require this feature to run and to be used in - %if conditions. + Closes #11999 - Large here means larger than 32 bits. Ie does not suffer from y2038. +- cmake: fix `HAVE_LDAP_SSL`, `HAVE_LDAP_URL_PARSE` on non-Windows - Closes #11696 + - set `HAVE_LDAP_URL_PARSE` if `ldap_url_parse` function exists. + Before this patch we set it based it on the presence of `stricmp`, + which correctly enabled it on e.g. Windows, but was inaccurate for + other platforms. -- tests/Makefile: add check-translatable-options.pl to tarball + - always set `HAVE_LDAP_SSL` if an LDAP backend is detected and + LDAPS is not explicitly disabled. This mimics autotools behaviour. + Previously we set it only for Windows LDAP. After this fix, LDAPS is + correctly enabled in default macOS builds. - Used in test 1544 + - enable LDAP[S] for a CMake macOS CI job. Target OS X 10.9 (Mavericks) + to avoid deprecation warnings for LDAP API. - Follow-up to ae806395abc8c + - always detect `HAVE_LDAP_SSL_H`, even with LDAPS explicitly disabled. + This doesn't make much sense, but let's do it to sync behaviour with + autotools. -- gen.pl: fix a long version generation mistake + - fix benign typo in variable name. - Too excessive escaping made the parsing not find the correct long names - later and instead add "wrong" links. + Ref: #11964 (effort to sync cmake detections with autotools) - Follow-up to 439ff2052e219 + Closes #12006 - Reported-by: Lukas Tribus - Fixes #11688 - Closes #11689 +- autotools: restore `HAVE_IOCTL_*` detections -- lib: move mimepost data from ->req.p.http to ->state + This restores `CURL_CHECK_FUNC_IOCTL` detection. I deleted it in + 4d73854462f30948acab12984b611e9e33ee41e6 and + c3456652a0c72d1845d08df9769667db7e159949 (2022-08), because the + `HAVE_IOCTL` result it generated was unused in the source. But, + I did miss the fact that this had two dependent checks: + `CURL_CHECK_FUNC_IOCTL_FIONBIO`, + `CURL_CHECK_FUNC_IOCTL_SIOCGIFADDR` that we do actually need: + `HAVE_IOCTL_FIONBIO`, `HAVE_IOCTL_SIOCGIFADDR`. - When the legacy CURLOPT_HTTPPOST option is used, it gets converted into - the modem mimpost struct at first use. This data is (now) kept for the - entire transfer and not only per single HTTP request. This re-enables - rewind in the beginning of the second request instead of in end of the - first, as brought by 1b39731. + Regression from 4d73854462f30948acab12984b611e9e33ee41e6 - The request struct is per-request data only. + Ref: #11964 (effort to sync cmake detections with autotools) - Extend test 650 to verify. + Closes #12008 - Fixes #11680 - Reported-by: yushicheng7788 on github - Closes #11682 +Daniel Stenberg (2 Oct 2023) -Patrick Monnerat (17 Aug 2023) +- RELEASE-PROCEDURE.md: updated coming release dates -- os400: do not check translatable options at build time +- RELEASE-NOTES: synced - Now that there is a test for this, the build time check is not needed - anymore. +Viktor Szakats (1 Oct 2023) - Closes #11650 +- cmake: pre-cache `HAVE_POLL_FINE` on Windows -- test1554: check translatable string options in OS400 wrapper + Windows doesn't support `poll()`, so we can safely skip checking for + fine poll. - This test runs a perl script that checks all string options are properly - translated by the OS400 character code conversion wrapper. It also - verifies these options are listed in alphanumeric order in the wrapper - switch statement. + Closes #12003 - Closes #11650 +- gha: bump actions to latest versions -Daniel Stenberg (17 Aug 2023) + - actions@checkout@v4 (from v3 and v2) -- unit3200: skip testing if function is not present + - fsfe/reuse-action@v2 (from v1) - Fake a successful run since we have no easy mechanism to skip this test - for this advanced condition. + Closes #12000 -- unit2600: fix build warning if built without verbose messages +Stefan Eissing (30 Sep 2023) -- test1608: make it build and get skipped without shuffle DNS support +- h2: testcase and fix for pausing h2 streams -- lib: --disable-bindlocal builds curl without local binding support + - refs #11982 where it was noted that paused transfers may + close successfully without delivering the complete data + - made sample poc into tests/http/client/h2-pausing.c and + added test_02_27 to reproduce -- test1304: build and skip without netrc support + Closes #11989 + Fixes #11982 + Reported-by: Harry Sintonen -- lib: build fixups when built with most things disabled +Viktor Szakats (30 Sep 2023) - Closes #11687 +- cmake: validate `CURL_DEFAULT_SSL_BACKEND` config value -- workflows/macos.yml: disable zstd and alt-svc in the http-only build + Before this patch CMake builds accepted any value and it was used at + runtime as-is. This patch make sure that the selected default backend + is also enabled in the build. It also enforces a full lowercase value. - Closes #11683 + This improves reproducibility and brings CMake in sync with autotools + which already worked like described above. -Stefan Eissing (17 Aug 2023) + Follow-up to 26c7feb8b9d51a57fab3325571b4bbfa03b11af0 #11774 -- bearssl: handshake fix, provide proper get_select_socks() implementation + Closes #11998 - - bring bearssl handshake times down from +200ms down to other TLS backends - - vtls: improve generic get_select_socks() implementation - - tests: provide Apache with a suitable ssl session cache +- autotools: adjust `CURL_CA_PATH` value to CMake - Closes #11675 + autotools was using the same value as CMake, but with an ending + slash. Delete the ending slash to match configurations. -- tests: TLS session sharing test + Ref: #11964 (effort to sync cmake detections with autotools) - - test TLS session sharing with special test client - - expect failure with wolfSSL - - disable flaky wolfSSL test_02_07b + Closes #11997 - Closes #11675 +- cmake: detect `sys/wait.h` and `netinet/udp.h` -Daniel Stenberg (17 Aug 2023) + Ref: #11964 (effort to sync cmake detections with autotools) -- CURLOPT_*TIMEOUT*: extend and clarify + Closes #11996 - Closes #11686 +Daniel Stenberg (30 Sep 2023) -- urlapi: return CURLUE_BAD_HOSTNAME if puny2idn encoding fails +- lib: provide and use Curl_hexencode - And document it. Only return out of memory when it actually is a memory - problem. + Generates a lower case ASCII hex output from a binary input. - Pointed-out-by: Jacob Mealey - Closes #11674 + Closes #11990 -Mathew Benson (17 Aug 2023) +- configure: check for the capath by default -- cmake: add GnuTLS option + ... if the chosen TLS backend supports it: OpenSSL, GnuTLS, mbedTLS or wolfSS + L - - Option to use GNUTLS was missing. Hence was not able to use GNUTLS - with ngtcp2 for http3. + cmake: synced - Closes #11685 + Assisted-by: Viktor Szakats + Closes #11987 -Daniel Stenberg (16 Aug 2023) +- wolfssl: ignore errors in CA path -- RELEASE-NOTES: synced + The default wolfSSL_CTX_load_verify_locations() function is quite picky + with the certificates it loads and will for example return error if just + one of the certs has expired. -- http: remove the p_pragma struct field + With the *_ex() function and its WOLFSSL_LOAD_FLAG_IGNORE_ERR flag, it + behaves more similar to what OpenSSL does by default. - unused since 40e8b4e52 (2008) + Even the set of default certs on my Debian unstable has several expired + ones. - Closes #11681 + Assisted-by: Juliusz Sosinowicz + Assisted-by: Michael Osipov -Jay Satiro (16 Aug 2023) + Closes #11987 -- CURLINFO_CERTINFO.3: better explain curl_certinfo struct +- create-dirs.d: clarify it also uses --output-dirs - Closes https://github.com/curl/curl/pull/11666 + Reported-by: Robert Simpson + Fixes #11991 + Closes #11995 -- CURLINFO_TLS_SSL_PTR.3: clarify a recommendation +Viktor Szakats (30 Sep 2023) - - Remove the out-of-date SSL backend list supported by - CURLOPT_SSL_CTX_FUNCTION. +- appveyor: fix yamlint issues, indent - It makes more sense to just refer to that document instead of having - a separate list that has to be kept in sync. + Also: + - use double quotes in all batch if statements. - Closes https://github.com/curl/curl/pull/11665 + Closes #11994 -- write-out.d: clarify %{time_starttransfer} +- cmake: detect `HAVE_CLOCK_GETTIME_MONOTONIC_RAW` - sync it up with CURLINFO_STARTTRANSFER_TIME_T + Based on existing autotools logic. -Daniel Stenberg (15 Aug 2023) + Ref: #11964 (effort to sync cmake detections with autotools) -- transfer: don't set TIMER_STARTTRANSFER on first send + Closes #11981 - The time stamp is for measuring the first *received* byte +- cmake: detect `HAVE_GETADDRINFO_THREADSAFE` - Fixes #11669 - Reported-by: JazJas on github - Closes #11670 + Based on existing autotools logic. -trrui-huawei (15 Aug 2023) + autotools checks for old versions of the allowlisted target OSes and + disables this feature when seeing them. In CMake we assume we're running + on newer systems and enable regardless of OS version. -- quiche: enable quiche to handle timeout events + autotools always runs all 3 probes for non-fast-tracked systems and + enables this feature if any one of them was successful. To save + configuration time, CMake stops at the first successful check. - In parallel with ngtcp2, quiche also offers the `quiche_conn_on_timeout` - interface for the application to invoke upon timer - expiration. Therefore, invoking the `on_timeout` function of the - Connection is crucial to ensure seamless functionality of quiche with - timeout events. + OpenBSD is not fast-tracked and then gets blocklisted as a generic BSD + system. I haven't double-checked if this is correct, but looks odd. - Closes #11654 + Ref: #11964 (effort to sync cmake detections with autotools) -- quiche: adjust quiche `QUIC_IDLE_TIMEOUT` to 60s + Closes #11979 - Set the `QUIC_IDLE_TIMEOUT` parameter to match ngtcp2 for consistency. +- cmake: fix `HAVE_WRITABLE_ARGV` detection -Daniel Stenberg (15 Aug 2023) + Move detection before the creation of detection results in + `curl_config.h`. -- KNOWN_BUGS: LDAPS requests to ActiveDirectory server hang + Ref: #11964 (effort to sync cmake detections with autotools) - Closes #9580 + Closes #11978 -- imap: add a check for failing strdup() +- appveyor: minor improvements -- imap: remove the only sscanf() call in the IMAP code + - run `curl -V` after builds to see if they run and with what features. + Except for one job where a CRT DLL is missing. And ARM64 which should + fail, but is silently not launched instead. - Avoids the use of a stack buffer. + - copy libcurl DLL next to curl tool and tests binaries in shared mode. + This makes it possible to run the tests. (We don't run tests after + these builds yet.) - Closes #11673 + - list the DLLs and EXEs present after the builds. -- imap: use a dynbuf in imap_atom + - add `DEBUG` variable for CMake builds to allow disabling it, for + testing non-debug builds. (currently enabled for all) - Avoid a calculation + malloc. Build the output in a dynbuf. + - add commented lines that dump CMake configuration logs for debugging + build/auto-detection issues. - Closes #11672 + - add gcc version to jobs where missing. -Marin Hannache (14 Aug 2023) + - switch a job to the native MSYS2 mingw-w64 toolchain. This adds gcc 9 + to the build mix. -- http: do not require a user name when using CURLAUTH_NEGOTIATE + - make `SHARED=OFF` and `OPENSSL=OFF` defaults global. - In order to get Negotiate (SPNEGO) authentication to work in HTTP you - used to be required to provide a (fake) user name (this concerned both - curl and the lib) because the code wrongly only considered - authentication if there was a user name provided, as in: + - delete a duplicate backslash. - curl -u : --negotiate https://example.com/ + Closes #11976 - This commit leverages the `struct auth` want member to figure out if the - user enabled CURLAUTH_NEGOTIATE, effectively removing the requirement of - setting a user name both in curl and the lib. +- configure: replace adhoc domain with `localhost` in tests - Signed-off-by: Marin Hannache - Reported-by: Enrico Scholz - Fixes https://sourceforge.net/p/curl/bugs/440/ - Fixes #1161 - Closes #9047 + Reviewed-by: Daniel Stenberg + Closes #11988 -Viktor Szakats (13 Aug 2023) +- tidy-up: use more example domains -- build: streamline non-UWP wincrypt detections + Also make use of the example TLD: + https://en.wikipedia.org/wiki/.example - - with CMake, use the variable `WINDOWS_STORE` to detect an UWP build - and disable our non-UWP-compatible use the Windows crypto API. This - allows to drop two dynamic feature checks. + Reviewed-by: Daniel Stenberg + Closes #11992 - `WINDOWS_STORE` is true when invoking CMake with - `CMAKE_SYSTEM_NAME` == `WindowsStore`. Introduced in CMake v3.1. +Dan Fandrich (29 Sep 2023) - Ref: https://cmake.org/cmake/help/latest/variable/WINDOWS_STORE.html +- runtests: display the test status if tests appear hung - - with autotools, drop the separate feature check for `wincrypt.h`. On - one hand this header has been present for long (even Borland C 5.5 had - it from year 2000), on the other we used the check result solely to - enable another check for certain crypto functions. This fails anyway - with the header not present. We save one dynamic feature check at the - configure stage. + It sometimes happens that a test hangs during a test run and never + returns. The test harness will wait indefinitely for the results and on + CI servers the CI job will eventually be killed after an hour or two. + At the end of a test run, if results haven't come in within a couple of + minutes, display the status of all test runners and what tests they're + running to help in debugging the problem. - Reviewed-by: Marcel Raad - Closes #11657 + This feature is really only kick in with parallel testing enabled, which + is fine because without parallel testing it's usually easy to tell what + test has hung. -Nicholas Nethercote (13 Aug 2023) + Closes #11980 -- docs/HYPER.md: update hyper build instructions +- github/labeler: remove workaround for labeler - Nightly Rust and `-Z unstable-options` are not needed. + This was added due to what seemed to be a bug regarding the sync-labels: + config option, but it looks like it wasn't necessary. - The instructions here now match the hyper docs exactly: - https://github.com/hyperium/hyper/commit/bd7928f3dd6a8461f0f0fdf7ee0fd95c2f15 - 6f88 + Follow-up to b2b0534e7 - Closes #11662 +Viktor Szakats (29 Sep 2023) -Daniel Stenberg (13 Aug 2023) +- docs: upgrade an URL to HTTPS in `BINDINGS.md` [ci skip] -- RELEASE-NOTES: synced +Daniel Stenberg (29 Sep 2023) -- urlapi: CURLU_PUNY2IDN - convert from punycode to IDN name +- docs: replace made up domains with example.com - Asssisted-by: Jay Satiro - Closes #11655 + in FAQ and MANUAL.md -- spellcheck: adapt to backslashed minuses + - example.com was made for this purpose. - As the curl.1 has more backslashed minus, the cleanup sed lines xneed to - adapt. + - reduces the risk that one of those domains suddenly start hosting + something nasty and we provide links to them - Adjusted some docs slighly. + Closes #11986 - Follow-up to 439ff2052e +Michael Osipov (29 Sep 2023) - Closes #11663 +- acinclude.m4: Document proper system truststore on FreeBSD -- gen: escape more minus + The default system truststore on FreeBSD has been /etc/ssl/certs for many + years now. It is managed canonically through certctl(8) and contains hashed + symlinks for OpenSSL and other TLS providers. + The previous ones require security/ca_root_nss which might not be installed o + r + will not contain any custom CA certificates. - Detected since it was still hard to search for option names using dashes - in the middle in the man page. + Closes #11985 - Closes #11660 +Daniel Stenberg (29 Sep 2023) -- cookie-jar.d: enphasize that this option is ONLY writing cookies +- FAQ: How do I upgrade curl.exe in Windows? - Reported-by: Dan Jacobson - Tweaked-by: Jay Satiro - Ref: #11642 - Closes #11661 + This is a growing question, better answer it here to get somewhere to + point users to. -Nicholas Nethercote (11 Aug 2023) + Closes #11984 -- docs/HYPER.md: document a workaround for a link error +Viktor Szakats (28 Sep 2023) - Closes #11653 +- cmake: pre-cache `HAVE_BASENAME` for mingw-w64 and MSVC -Jay Satiro (11 Aug 2023) + `basename` is present in mingw-w64, missing from MSVC. Pre-cache + accordingly to make configure faster. -- schannel: verify hostname independent of verify cert + Notice that `basename` has a bug so we later disable it even with + mingw-w64: + https://github.com/curl/curl/blob/781242ffa44a9f9b95b6da5ac5a1bf6372ec6257/li + b/curl_setup.h#L820-L825 - Prior to this change when CURLOPT_SSL_VERIFYPEER (verifypeer) was off - and CURLOPT_SSL_VERIFYHOST (verifyhost) was on we did not verify the - hostname in schannel code. + Closes #11974 - This fixes KNOWN_BUG 2.8 "Schannel disable CURLOPT_SSL_VERIFYPEER and - verify hostname". We discussed a fix several years ago in #3285 but it - went stale. +Daniel Stenberg (28 Sep 2023) - Assisted-by: Daniel Stenberg +- cmake: add missing checks - Bug: https://curl.haxx.se/mail/lib-2018-10/0113.html - Reported-by: Martin Galvan + - check for arc4random. To make rand.c use it accordingly. + - check for fcntl + - fix fseek detection + - add SIZEOF_CURL_SOCKET_T + - fix USE_UNIX_SOCKETS + - define HAVE_SNPRINTF to 1 + - check for fnmatch + - check for sched_yield + - remove HAVE_GETPPID duplicate from curl_config.h + - add HAVE_SENDMSG - Ref: https://github.com/curl/curl/pull/3285 + Ref: #11964 - Fixes https://github.com/curl/curl/issues/3284 - Closes https://github.com/curl/curl/pull/10056 + Co-authored-by: Viktor Szakats + Closes #11973 -Daniel Stenberg (11 Aug 2023) +- configure: remove unused checks -- curl_quiche: remove superfluous NULL check + - for sys/uio.h + - for fork + - for connect - 'stream' is always non-NULL at this point + Ref: #11964 - Pointed out by Coverity + Closes #11973 - Closes #11656 +- lib: remove TIME_WITH_SYS_TIME -- curl/urlapi.h: tiny typo + It is not used in any code anywhere. -- github/labeler: make HYPER.md set Hyper and not TLS + Ref: #11964 + Closes #11975 -- docs/cmdline-opts/gen.pl: hide "added in" before 7.50.0 +- docs: update curl man page references - 7.50.0 shipped on Jul 21 2016, over seven years ago. We no longer need - to specify version changes for earlier releases in the generated output. + Detected by the manpage-syntax update - This ups the limit from the previous 7.30.0 (Apr 12 2013) + Closes #11963 - This hides roughly 35 "added in" mentions. +- manpage-syntax: verify curl man page references - Closes #11651 + 1. References to curl symbols are now checked that they indeed exist as + man pages. This for \f references as well as the names referenced in the + SEE ALSO section. -Jay Satiro (10 Aug 2023) + Allowlist curl.1 since it is not always built in builds -- bug_report: require reporters to specify curl and os versions + 2. References to curl symbols that lack section now causes warning, since tha + t + will prevent them from getting linked properly - - Change curl version and os sections from single-line input to - multi-line textarea. + 3. Check for "bare" references to curl functions and warn, they should be + references - - Require curl version and os sections to be filled out before report - can be submitted. + Closes #11963 - Closes https://github.com/curl/curl/pull/11636 +- cmake: add check for suseconds_t -Daniel Stenberg (9 Aug 2023) + And fix the HAVE_LONGLONG define -- gen.pl: replace all single quotes with aq + Ref: #11964 + Closes #11977 - - this prevents man from using a unicode sequence for them - - which then allows search to work properly +Viktor Szakats (28 Sep 2023) - Closes #11645 +- tidy-up: whitespace fixes -Viktor Szakats (9 Aug 2023) + Closes #11972 -- cmake: fix to use variable for the curl namespace +- cmake: detect TLS-SRP in OpenSSL/wolfSSL/GnuTLS - Replace (wrong) literal with a variable to specify the curl - namespace. + With new option `CURL_DISABLE_SRP=ON` to force-disable it. + To match existing option and detection logic in autotools. - Follow-up to 1199308dbc902c52be67fc805c72dd2582520d30 #11505 + Also: + - fix detecting GnuTLS. + We assume `nettle` as a GnuTLS dependency. + - add CMake GnuTLS CI job. + - bump AppVeyor CMake OpenSSL MSVC job to OpenSSL 1.1.1 (from 1.0.2) + TLS-SRP fails to detect with 1.0.2 due to an OpenSSL header bug. + - fix compiler warning when building with GnuTLS and disabled TLS-SRP. + - fix comment typos, whitespace. - Reported-by: balikalina on Github - Fixes https://github.com/curl/curl/commit/1199308dbc902c52be67fc805c72dd25825 - 20d30#r123923098 - Closes #11629 + Ref: #11964 -- cmake: allow `SHARE_LIB_OBJECT=ON` on all platforms + Closes #11967 - 2ebc74c36a19a1700af394c16855ce144d9878e3 #11546 introduced sharing - libcurl objects for shared and static targets. +- tool: use our own stderr variable - The above automatically enabled for Windows builds, with an option to - disable with `SHARE_LIB_OBJECT=OFF`. + Earlier this year we changed our own stderr variable to use the standard + name `stderr` (to avoid bugs where someone is using `stderr` instead of + the curl-tool specific variable). This solution needed to override the + standard `stderr` symbol via the preprocessor. This in turn didn't play + well with unity builds and caused curl tool to crash or stay silent due + to an uninitialized stderr. This was a hard to find issue, fixed by + manually breaking out one file from the unity sources. - This patch extend this feature to all platforms as a manual option. - You can enable it by setting `SHARE_LIB_OBJECT=ON`. Then shared objects - are built in PIC mode, meaning the static lib will also have PIC code. + To avoid two these two tricks, this patch implements a different + solution: Restore using our own local variable for our stderr output and + leave `stderr` as-is. To avoid using `stderr` by mistake, add a + `checksrc` rule (based on logic we already used in lib for `strerror`) + that detects any `stderr` use in `src` and points to using our own + variable instead: `tool_stderr`. - [EXPERIMENTAL] + Follow-up to 06133d3e9b8aeb9e9ca0b3370c246bdfbfc8619e + Follow-up to 2f17a9b654121dd1ecf4fc043c6d08a9da3522db - Closes #11627 + Closes #11958 -- cmake: assume `wldap32` availability on Windows +Loïc Yhuel (28 Sep 2023) - This system library first shipped with Windows ME, available as an extra - install for some older releases (according to [1]). The import library - was present already in old MinGW 3.4.2 (year 2007). +- connect: only start the happy eyeballs timer when needed - Drop the feature check and its associated `HAVE_WLDAP32` variable. + The timeout is only used when there is a second address family, for the + delayed eyeballer. - To manually disable `wldap32`, you can use the `USE_WIN32_LDAP=OFF` - CMake option, like before. + Closes #11939 - [1]: https://dlcdn.apache.org/httpd/binaries/win32/LEGACY.html +Daniel Stenberg (28 Sep 2023) - Reviewed-by: Jay Satiro - Closes #11624 +- tool_operate: free 'gateway' correctly -Daniel Stenberg (9 Aug 2023) + Pointed out by Coverity. The fix in 93885cf3a8d4e was incomplete. -- page-header: move up a URL paragraph from GLOBBING to URL + Also removed repeated wording in IPFS related error messages. -- variable.d: output the function names table style + Closes #11969 - Also correct the url function name in the header +Stefan Eissing (28 Sep 2023) - Closes #11641 +- lib: move handling of `data->req.writer_stack` into Curl_client_write() -- haproxy-clientip.d: remove backticks + - move definitions from content_encoding.h to sendf.h + - move create/cleanup/add code into sendf.c + - installed content_encoding writers will always be called + on Curl_client_write(CLIENTWRITE_BODY) + - Curl_client_cleanup() frees writers and tempbuffers from + paused transfers, irregardless of protocol - This is not markdown + Closes #11908 - Follow-up to 0a75964d0d94a4 +Loïc Yhuel (28 Sep 2023) - Closes #11639 +- multi: round the timeout up to prevent early wakeups -- RELEASE-NOTES: synced + Curl_timediff rounds down to the millisecond, so curl_multi_perform can + be called too early, then we get a timeout of 0 and call it again. -- gen.pl: escape all dashes (ascii minus) to avoid unicode hyphens + The code already handled the case of timeouts which expired less than + 1ms in the future. By rounding up, we make sure we will never ask the + platform to wake up too early. - Reported-by: FC Stegerman - Fixes #11635 - Closes #11637 + Closes #11938 -- cmdline-opts/page-header: reorder, clean up +Daniel Stenberg (28 Sep 2023) - - removed some unnecessary blurb to focus - - moved up the more important URL details - - put "globbing" into its own subtitle and moved down a little - - mention the online man page in the version section +- RELEASE-NOTES: spell out that IPFS is via gateway - Closes #11638 +- RELEASE-NOTES: synced -- c-hyper: adjust the hyper to curlcode conversion +- tool_operate: avoid strlen() -1 on zero length content from file - Closes #11621 + Follow-up to 65b563a96a226649ba12cb1e -- test2306: make it use a persistent connection + Closes #11959 - + enable verbose already from the start +- tool_operate: fix memory mixups - Closes #11621 + Switch to plain getenv() from curl_getenv() to avoid the allocation and + having to keep track of which free() or curl_free() that need to be + used. -eppesuig (8 Aug 2023) + Coverity found issues and a memory leak. -- list-only.d: mention SFTP as supported protocol + Follow-up to 65b563a96a226649ba12cb1e - Closes #11628 + Closes #11959 -Daniel Stenberg (8 Aug 2023) +Viktor Szakats (27 Sep 2023) -- request.d: use .TP for protocol "labels" +- curl-functions.m4: fixup recent bad edits - To render the section nicer in man page. + Follow-up to 96c29900bcec32dd6bc8e9857c8871ff4b8b8ed9 #11940 - Closes #11630 + Closes #11966 -- cf-haproxy: make CURLOPT_HAPROXY_CLIENT_IP set the *source* IP +Daniel Stenberg (27 Sep 2023) - ... as documented. +- curl-functions.m4: fix include line - Update test 3201 and 3202 accordingly. + This made the getaddrinfo detection fail, but we did not spot it in the + CI because it graciously falled back to using legacy functions instead! - Reported-by: Markus Sommer - Fixes #11619 - Closes #11626 + Follow-up to 96c29900bcec (#11940) -- page-footer: QLOGDIR works with ngtcp2 and quiche + Closes #11965 - It previously said "both" backends which is confusing as we currently - have three... +- inet_ntop: add typecast to silence Coverity - Closes #11631 + CID 1024653: Integer handling issues (SIGN_EXTENSION) -Stefan Eissing (8 Aug 2023) + Suspicious implicit sign extension: "src[i]" with type "unsigned char + const" (8 bits, unsigned) is promoted in "src[i] << (1 - i % 2 << 3)" to + type "int" (32 bits, signed), then sign-extended to type "unsigned long" + (64 bits, unsigned). If "src[i] << (1 - i % 2 << 3)" is greater than + 0x7FFFFFFF, the upper bits of the result will all be 1. -- http3: quiche, handshake optimization, trace cleanup + 111 words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); - - load x509 store after clienthello - - cleanup of tracing + The value will not be greater than 0x7FFFFFFF so this still cannot + happen. - Closes #11618 + Also, switch to ints here instead of longs. The values stored are 16 bit + so at least no need to use 64 bit variables. Also, longs are 32 bit on + some platforms so this logic still needs to work with 32 bits. -Daniel Stenberg (8 Aug 2023) + Closes #11960 -- ngtcp2: remove dead code +- docs: adapt SEE ALSO sections to new requirements - 'result' is always zero (CURLE_OK) at this point + To please manpage-syntax.pl used by test 1173 - Detected by Coverity + Closes #11957 - Closes #11622 +- manpage-syntax.pl: verify SEE ALSO syntax -Viktor Szakats (8 Aug 2023) + - Enforce a single reference per .BR line + - Skip the quotes around the section number for example (3) + - Insist on trailing commas on all lines except the last + - Error on comma on the last SEE ALSO entry -- openssl: auto-detect `SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED` + - List the entries alpha-sorted, not enforced just recommended - OpenSSL 1.1.1 defines this macro, but no ealier version, or any of the - popular forks (yet). Use the macro itself to detect its presence, - replacing the hard-wired fork-specific conditions. + Closes #11957 - This way the feature will enable automatically when forks implement it, - while also shorter and possibly requiring less future maintenance. +- connect: expire the timeout when trying next - Follow-up to 94241a9e78397a2aaf89a213e6ada61e7de7ee02 #6721 + ... so that it gets called again immediately and can continue trying + addresses to connect to. Otherwise it might unnecessarily wait for a + while there. - Reviewed-by: Jay Satiro - Closes #11617 + Fixes #11920 + Reported-by: Loïc Yhuel + Closes #11935 -- openssl: use `SSL_CTX_set_ciphersuites` with LibreSSL 3.4.1 +- http: remove wrong comment for http_should_fail - LibreSSL 3.4.1 (2021-10-14) added support for - `SSL_CTX_set_ciphersuites`. + Reported-by: Christian Schmitz + Ref: #11936 + Closes #11941 - Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.4.1-relnotes.txt +Dan Fandrich (26 Sep 2023) - Reviewed-by: Jay Satiro - Closes #11616 +- tool_setopt: remove unused function tool_setopt_flags -- openssl: use `SSL_CTX_set_keylog_callback` with LibreSSL 3.5.0 + This function is identical to tool_setopt_bitmask except that it treats + the argument as unsigned. - LibreSSL 3.5.0 (2022-02-24) added support for - `SSL_CTX_set_keylog_callback`. + Closes #11943 - Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.5.0-relnotes.txt +Viktor Szakats (26 Sep 2023) - Reviewed-by: Jay Satiro - Closes #11615 +- cmake: add feature checks for `memrchr` and `getifaddrs` -- cmake: drop `HAVE_LIBWINMM` and `HAVE_LIBWS2_32` feature checks + - `HAVE_MEMRCHR` for `memrchr`. + - `HAVE_GETIFADDRS` for `getifaddrs`. + This was present in `lib/curl_config.h.cmake` but missed the detection + logic. - - `HAVE_LIBWINMM` was detected but unused. The `winmm` system library is - also not used by curl, but it is by its optional dependency `librtmp`. - Change the logic to always add `winmm` when `USE_LIBRTMP` is set. This - library has been available since the early days of Windows. + To match existing autotools feature checks. - - `HAVE_LIBWS2_32` detected `ws2_32` lib on Windows. This lib is present - since Windows 95 OSR2 (AFAIR). Winsock1 already wasn't supported and - other existing logic already assumed this lib being present, so delete - the check and replace the detection variable with `WIN32` and always - add `ws2_32` on Windows. + Closes #11954 - Closes #11612 +- cmake: move global headers to specific checks -Daniel Gustafsson (8 Aug 2023) + Before this patch we added standard headers unconditionally to the + global list of headers used for feature checks. This is unnecessary + and also doesn't help CMake 'Generate' performance. This patch moves + these headers to each feature check where they are actually needed. + Stop using `stddef.h`, as it seems unnecessary. -- crypto: ensure crypto initialization works + I've used autotools' `m4/curl-functions.m4` to figure out these + dependencies. - Make sure that context initialization during hash setup works to avoid - going forward with the risk of a null pointer dereference. + Also delete checking for the C89 standard header `time.h`, that I + missed in the earlier commit. - Reported-by: Philippe Antoine on HackerOne - Assisted-by: Jay Satiro - Assisted-by: Daniel Stenberg + Ref: 96c29900bcec32dd6bc8e9857c8871ff4b8b8ed9 #11940 - Closes #11614 + Closes #11951 -Viktor Szakats (7 Aug 2023) +- src/mkhelp: make generated code pass `checksrc` -- openssl: switch to modern init for LibreSSL 2.7.0+ + Closes #11955 - LibreSSL 2.7.0 (2018-03-21) introduced automatic initialization, - `OPENSSL_init_ssl()` function and deprecated the old, manual init - method, as seen in OpenSSL 1.1.0. Switch to the modern method when - available. +- tests: show which curl tool `runtests.pl` is using - Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.7.0-relnotes.txt + To help debugging when there is issue finding or running it. - Reviewed-by: Daniel Stenberg - Closes #11611 - -Daniel Stenberg (7 Aug 2023) - -- gskit: remove - - We remove support for building curl with gskit. - - - This is a niche TLS library, only running on some IBM systems - - no regular curl contributors use this backend - - no CI builds use or verify this backend - - gskit, or the curl adaption for it, lacks many modern TLS features - making it an inferior solution - - build breakages in this code take weeks or more to get detected - - fixing gskit code is mostly done "flying blind" - - This removal has been advertized in DEPRECATED in Jan 2, 2023 and it has - been mentioned on the curl-library mailing list. + Closes #11953 - It could be brought back, this is not a ban. Given proper effort and - will, gskit support is welcome back into the curl TLS backend family. +- CI/azure: make `MAKEFLAGS` global to parallelize all jobs - Closes #11460 + https://dev.azure.com/daniel0244/curl/_build/results?buildId=17528 (before) + https://dev.azure.com/daniel0244/curl/_build/results?buildId=17545 (after, wi + th -j3) -- RELEASE-NOTES: synced + Closes #11952 -Dan Fandrich (7 Aug 2023) +- CI/azure: migrate old mingw MSYS1 jobs to MSYS2 -- THANKS-filter: add a name typo + Also delete an accidental variable reference. -Stefan Eissing (7 Aug 2023) + Follow-up to 38029101e2d78ba125732b3bab6ec267b80a0e72 -- http3/ngtcp2: shorten handshake, trace cleanup + Closes #11945 - - shorten handshake timing by delayed x509 store load (OpenSSL) - as we do for HTTP/2 - - cleanup of trace output, align with HTTP/2 output +Daniel Stenberg (26 Sep 2023) - Closes #11609 +- docs: add see also curl_multi_get_handles to some man pages -Daniel Stenberg (7 Aug 2023) + Assisted-by: Jay Satiro -- headers: accept leading whitespaces on first response header + Closes #11942 - This is a bad header fold but since the popular browsers accept this - violation, so does curl now. Unless built with hyper. +Viktor Szakats (26 Sep 2023) - Add test 1473 to verify and adjust test 2306. +- cmake: assume `_fseeki64` and no `fseeko` on Windows - Reported-by: junsik on github - Fixes #11605 - Closes #11607 + `_fseeki64` is present in mingw-w64 1.0 (2011-09-26) headers, and + at least Watcom C 1.9 (2010) headers and MSVS 2008 [1]. -- include/curl/mprintf.h: add __attribute__ for the prototypes + `fseeko` is not present in any of these. - - if gcc or clang is used - - if __STDC_VERSION__ >= 199901L, which means greater than C90 - - if not using mingw - - if CURL_NO_FMT_CHECKS is not defined + (mingw-w64 1.0 also offers `fseeko64`.) - Closes #11589 + [1] https://github.com/curl/curl/pull/11944#issuecomment-1734995004 -- tests: fix bad printf format flags in test code + Follow-up to 9c7165e96a3a9a2d0b7059c87c699b5ca8cdae93 #11918 -- tests: fix header scan tools for attribute edits in mprintf.h + Closes #11950 -- cf-socket: log successful interface bind +- build: delete checks for C89 standard headers - When the setsockopt SO_BINDTODEVICE operation succeeds, output that in - the verbose output. + Delete checks and guards for standard C89 headers and assume these are + available: `stdio.h`, `string.h`, `time.h`, `setjmp.h`, `stdlib.h`, + `stddef.h`, `signal.h`. - Ref: #11599 - Closes #11608 + Some of these we already used unconditionally, some others we only used + for feature checks. -- CURLOPT_SSL_VERIFYPEER.3: mention it does not load CA certs when disabled + Follow-up to 9c7165e96a3a9a2d0b7059c87c699b5ca8cdae93 #11918 (for `stdio.h` i + n CMake) - Ref: #11457 - Closes #11606 + Closes #11940 -- CURLOPT_SSL_VERIFYPEER.3: add two more see also options +Stefan Eissing (26 Sep 2023) - CURLINFO_CAINFO and CURLINFO_CAPATH +- multiif.h: remove Curl_multi_dump declaration - Closes #11603 + Follow-up to d850eea2 which removed the Curl_multi_dump definition. -- KNOWN_BUGS: aws-sigv4 does not behave well with AWS VPC Lattice + Closes https://github.com/curl/curl/pull/11946 - Closes #11007 +Jay Satiro (26 Sep 2023) -Graham Campbell (6 Aug 2023) +- config-win32: define HAVE__FSEEKI64 -- CI: use openssl 3.0.10+quic, nghttp3 0.14.0, ngtcp2 0.18.0 + Follow-up to 9c7165e9 which added an fseeko wrapper to the lib that + calls _fseeki64 if it is available. - Closes #11585 + Closes https://github.com/curl/curl/pull/11944 -Daniel Stenberg (6 Aug 2023) +- docs: explain how PINNEDPUBLICKEY is independent of VERIFYPEER -- TODO: add *5* entries for aws-sigv4 + - Explain that peer verification via CURLOPT_PINNEDPUBLICKEY takes place + even if peer verification via CURLOPT_SSL_VERIFYPEER is turned off. - Closes #7559 - Closes #8107 - Closes #8810 - Closes #9717 - Closes #10129 + The behavior is verified by test2048. -- TODO: LDAP Certificate-Based Authentication + Bug: https://github.com/curl/curl/issues/2935#issuecomment-418371872 + Reported-by: claudiusaiz@users.noreply.github.com - Closes #9641 + Bug: https://github.com/curl/curl/discussions/11910 + Reported-by: Hakan Sunay Halil -Stefan Eissing (6 Aug 2023) + Closes https://github.com/curl/curl/pull/11930 -- http2: cleanup trace messages +Stefan Eissing (26 Sep 2023) - - more compact format with bracketed stream id - - all frames traced in and out +- openssl: improve ssl shutdown handling - Closes #11592 + - If SSL shutdown is not finished then make an additional call to + SSL_read to gather additional tracing. -Daniel Stenberg (6 Aug 2023) + - Fix http2 and h2-proxy filters to forward do_close() calls to the next + filter. -- tests/tftpd+mqttd: make variables static to silence picky warnings + For example h2 and SSL shutdown before and after this change: - Closes #11594 + Before: -- docs/cmdline: remove repeated working for negotiate + ntlm + Curl_conn_close -> cf_hc_close -> Curl_conn_cf_discard_chain -> + ssl_cf_destroy - The extra wording is added automatically by the gen.pl tool + After: - Closes #11597 + Curl_conn_close -> cf_hc_close -> cf_h2_close -> cf_setup_close -> + ssl_cf_close -- docs/cmdline: add small "warning" to verbose options + Note that currently the tracing does not show output on the connection + closure handle. Refer to discussion in #11878. - "Note that verbose output of curl activities and network traffic might - contain sensitive data, including user names, credentials or secret data - content. Be aware and be careful when sharing trace logs with others." + Ref: https://github.com/curl/curl/discussions/11878 - Closes #11596 + Closes https://github.com/curl/curl/pull/11858 -- RELEASE-NOTES: synced +Loïc Yhuel (26 Sep 2023) -- pingpong: don't use *bump_headersize +- multi: fix small timeouts - We use that for HTTP(S) only. + Since Curl_timediff rounds down to the millisecond, timeouts which + expire in less than 1ms are considered as outdated and removed from the + list. We can use Curl_timediff_us instead, big timeouts could saturate + but this is not an issue. - Follow-up to 3ee79c1674fd6 + Closes #11937 - Closes #11590 +Viktor Szakats (25 Sep 2023) -- urldata: remove spurious parenthesis to unbreak no-proxy build +- cmake: fix stderr initialization in unity builds - Follow-up to e12b39e13382 + Before this patch, in certain build configurations the curl tool may + not have displayed anything (debug, macOS), or crashed at startup + (debug, Windows). - Closes #11591 + Follow-up to 3f8fc25720900b14b7432f4bd93407ca15311719 + Necessary after 2f17a9b654121dd1ecf4fc043c6d08a9da3522db -- easy: don't call Curl_trc_opt() in disabled-verbose builds + Closes #11929 - Follow-up to e12b39e133822c6a0 +- cmake: fix missing `zlib.h` when compiling `libcurltool` - Closes #11588 + Came up while testing debug/testing build for Windows. I'm not sure why + it didn't come up in earlier tests with similar config. + `tool_hugehelp.c` might indeed require `zlib.h` and without linking + `CURL_LIBS` to the `curltool` target, CMake doesn't seem to add detected + dependency headers to the compiler command. -- http: use %u for printfing int + ``` + [ 25%] Building C object src/CMakeFiles/curltool.dir/tool_hugehelp.c.obj + cd .../curl/bld-cmake-llvm-x64/src && /usr/local/opt/llvm/bin/clang + --target=x86_64-w64-mingw32 --sysroot=/usr/local/opt/mingw-w64/toolchain-x8 + 6_64 + -DCURLDEBUG -DCURL_STATICLIB -DHAVE_CONFIG_H -DUNICODE -DUNITTESTS -D_UNICO + DE + -I.../curl/include -I.../curl/lib -I.../curl/bld-cmake-llvm-x64/lib + -I.../curl/bld-cmake-llvm-x64/include -I.../curl/src -Wno-unused-command-li + ne-argument + -D_UCRT -DDEBUGBUILD -DHAS_ALPN -DUSE_MANUAL=1 -fuse-ld=lld -Wl,-s -static + -libgcc + -lucrt [...] -O3 -DNDEBUG -municode -MD + -MT src/CMakeFiles/curltool.dir/tool_hugehelp.c.obj + -MF CMakeFiles/curltool.dir/tool_hugehelp.c.obj.d + -o CMakeFiles/curltool.dir/tool_hugehelp.c.obj -c .../curl/bld-cmake-llvm-x + 64/src/tool_hugehelp.c + .../curl/bld-cmake-llvm-x64/src/tool_hugehelp.c:6:10: fatal error: 'zlib.h' f + ile not found + 6 | #include + | ^~~~~~~~ + ``` - Follow-up to 3ee79c1674fd6f99e8efca5 + Follow-up to 39e7c22bb459c2e818f079984989a26a09741860 - Closes #11587 + Closes #11927 -Goro FUJI (3 Aug 2023) +- cmake: fix duplicate symbols when linking tests -- vquic: show stringified messages for errno + The linker resolves this automatically in non-unity builds. In unity + builds the linker cannot drop a single object with the duplicates, + resulting in these errors. The root issue is that we started including + certain objects both via both libcurlu and libcurltool libs. - Closes #11584 + Regression from 39e7c22bb459c2e818f079984989a26a09741860 -Stefan Eissing (3 Aug 2023) + Windows errors: + ``` + [ 3%] Linking C executable unit1303.exe + [ 3%] Building C object tests/server/CMakeFiles/rtspd.dir/__/__/lib/curl_mul + tibyte.c.obj + ../../lib/libcurlu-d.a(unity_0.c.obj): In function `curlx_convert_UTF8_to_wch + ar': + C:/projects/curl/lib/curl_multibyte.c:44: multiple definition of `curlx_conve + rt_UTF8_to_wchar' + ../../src/libcurltool-d.a(unity_0.c.obj):C:/projects/curl/lib/curl_multibyte. + c:44: first defined here + ../../lib/libcurlu-d.a(unity_0.c.obj): In function `curlx_convert_wchar_to_UT + F8': + C:/projects/curl/lib/curl_multibyte.c:66: multiple definition of `curlx_conve + rt_wchar_to_UTF8' + ../../src/libcurltool-d.a(unity_0.c.obj):C:/projects/curl/lib/curl_multibyte. + c:66: first defined here + ../../lib/libcurlu-d.a(unity_0.c.obj): In function `curlx_win32_open': + C:/projects/curl/lib/curl_multibyte.c:92: multiple definition of `curlx_win32 + _open' + ../../src/libcurltool-d.a(unity_0.c.obj):C:/projects/curl/lib/curl_multibyte. + c:92: first defined here + ../../lib/libcurlu-d.a(unity_0.c.obj): In function `curlx_win32_fopen': + C:/projects/curl/lib/curl_multibyte.c:120: multiple definition of `curlx_win3 + 2_fopen' + ../../src/libcurltool-d.a(unity_0.c.obj):C:/projects/curl/lib/curl_multibyte. + c:120: first defined here + ../../lib/libcurlu-d.a(unity_0.c.obj): In function `curlx_win32_stat': + [...] + ``` + Ref: https://ci.appveyor.com/project/curlorg/curl/builds/48110107/job/nvlhpt9 + aa4ehny5q#L247 -- trace: make tracing available in non-debug builds + macOS errors: + ``` + [ 56%] Linking C executable unit1302 + duplicate symbol '_curlx_sotouz' in: + ../../lib/libcurlu.a(unity_0_c.c.o) + ../../src/libcurltool.a(unity_0_c.c.o) + duplicate symbol '_curlx_sitouz' in: + ../../lib/libcurlu.a(unity_0_c.c.o) + ../../src/libcurltool.a(unity_0_c.c.o) + duplicate symbol '_curlx_uztosz' in: + ../../lib/libcurlu.a(unity_0_c.c.o) + ../../src/libcurltool.a(unity_0_c.c.o) + [...] + ``` + with config: + ``` + -DCMAKE_UNITY_BUILD=ON \ + -DENABLE_DEBUG=ON -DBUILD_TESTING=ON -DCMAKE_C_FLAGS=-DDEBUGBUILD \ + -DBUILD_SHARED_LIBS=ON \ + -DBUILD_STATIC_LIBS=OFF + ``` - Add --trace-config to curl + Closes #11926 - Add curl_global_trace() to libcurl +- cmake: lib `CURL_STATICLIB` fixes (Windows) - Closes #11421 + - always define `CURL_STATICLIB` when building libcurl for Windows. -Daniel Stenberg (3 Aug 2023) + This disables `__declspec(dllexport)` for exported libcurl symbols. + In normal mode (hide symbols) these exported symbols are specified + via `libcurl.def`. When not hiding symbols, all symbols are exported + by default. -- TODO: remove "Support intermediate & root pinning for PINNEDPUBLICKEY" + Regression from 1199308dbc902c52be67fc805c72dd2582520d30 - See also https://github.com/curl/curl/pull/7507 + Fixes #11844 -- TODO: add "WebSocket read callback" + - fix to omit `libcurl.def` when not hiding private symbols. - remove "Upgrade to websockets" as we already have this + Regression from 2ebc74c36a19a1700af394c16855ce144d9878e3 - Closes #11402 + - fix `ENABLED_DEBUG=ON` + shared curl tool Windows builds by also + omitting `libcurl.def` in this case, and exporting all symbols + instead. This ensures that a shared curl tool can access all debug + functions which are not normally exported from libcurl DLL. -- test497: verify rejecting too large incoming headers + - delete `INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB"` for "objects" + target. -- http: return error when receiving too large header set + Follow-up to 2ebc74c36a19a1700af394c16855ce144d9878e3 - To avoid abuse. The limit is set to 300 KB for the accumulated size of - all received HTTP headers for a single response. Incomplete research - suggests that Chrome uses a 256-300 KB limit, while Firefox allows up to - 1MB. + - delete duplicate `BUILDING_LIBCURL` definitions. - Closes #11582 + - fix `HIDES_CURL_PRIVATE_SYMBOLS` to not overwrite earlier build settings. -Stefan Eissing (3 Aug 2023) + Follow-up to 1199308dbc902c52be67fc805c72dd2582520d30 -- http2: upgrade tests and add fix for non-existing stream + Closes #11914 - - check in h2 filter recv that stream actually exists - and return error if not - - add test for parallel, extreme h2 upgrades that fail if - connections get reused before fully switched - - add h2 upgrade upload test just for completeness +Daniel Stenberg (25 Sep 2023) - Closes #11563 +- RELEASE-NOTES: synced -Viktor Szakats (3 Aug 2023) +Dan Fandrich (25 Sep 2023) -- tests: ensure `libcurl.def` contains all exports +- tests: fix log directory path in IPFS tests - Add `test1279` to verify that `libcurl.def` lists all exported API - functions found in libcurl headers. + Hard-coding the log directory name fails with parallel tests. - Also: + Follow-up to 65b563a96 - - extend test suite XML `stdout` tag with the `loadfile` attribute. + Ref: #8805 - - fix `tests/extern-scan.pl` and `test1135` to include websocket API. +Daniel Stenberg (25 Sep 2023) - - use all headers (sorted) in `test1135` instead of a manual list. +- curl_multi_get_handles: get easy handles from a multi handle - - add options `--sort`, `--heading=` to `tests/extern-scan.pl`. + Closes #11750 - - add `libcurl.def` to the auto-labeler GHA task. +Stefan Eissing (25 Sep 2023) - Follow-up to 2ebc74c36a19a1700af394c16855ce144d9878e3 +- http: h1/h2 proxy unification - Closes #11570 + - use shared code for setting up the CONNECT request + when tunneling, used in HTTP/1.x and HTTP/2 proxying + - eliminate use of Curl_buffer_send() and other manipulations + of `data->req` or `data->state.ulbuf` -Daniel Stenberg (2 Aug 2023) + Closes #11808 -- url: change default value for CURLOPT_MAXREDIRS to 30 +Natanael Copa (25 Sep 2023) - It was previously unlimited by default, but that's not a sensible - default. While changing this has a remote risk of breaking an existing - use case, I figure it is more likely to actually save users from loops. +- lib: use wrapper for curl_mime_data fseek callback - Closes #11581 + fseek uses long offset which does not match with curl_off_t. This leads + to undefined behavior when calling the callback and caused failure on + arm 32 bit. -- lib: fix a few *printf() flag mistakes + Use a wrapper to solve this and use fseeko which uses off_t instead of + long. - Reported-by: Gisle Vanem - Ref: #11574 - Closes #11579 + Thanks to the nice people at Libera IRC #musl for helping finding this + out. -Samuel Chiang (2 Aug 2023) + Fixes #11882 + Fixes #11900 + Closes #11918 -- openssl: make aws-lc version support OCSP +- configure: sort AC_CHECK_FUNCS - And bump version in CI + No functional changes. - Closes #11568 +Daniel Stenberg (25 Sep 2023) -Daniel Stenberg (2 Aug 2023) +- warnless: remove unused functions -- tool: make the length argument an int for printf()-.* flags + Previously put there for use with the intel compiler - Closes #11578 + Closes #11932 -- tool_operate: fix memory leak when SSL_CERT_DIR is used +- GHA/linux: run singleuse to detect single-use global functions - Detected by Coverity + Use --unit for configure --enable-debug builds - Follow-up to 29bce9857a12b6cfa726a5 + Closes #11932 - Closes #11577 +- singleuse: add scan for use in other source codes -- tool/var: free memory on OOM + This should reduce false-positive to almost zero. Checks for presence in + unit tests if --unit is specified, which is intended for debug builds + where unit testing is enabled. - Coverity detected this memory leak in OOM situation + Closes #11932 - Follow-up to 2e160c9c652504e +- multi: remove Curl_multi_dump - Closes #11575 + A debug-only function that is basically never used. Removed to ease the + use of the singleuse script to detect non-static functions not used + outside the file where it is defined. -Viktor Szakats (2 Aug 2023) + Closes #11931 -- gha: bump libressl and mbedtls versions +Viktor Szakats (24 Sep 2023) - Closes #11573 +- tests: fix compiler warnings -Jay Satiro (2 Aug 2023) + Seen with llvm 17 on Windows x64. -- schannel: fix user-set legacy algorithms in Windows 10 & 11 + ``` + .../curl/tests/server/rtspd.c:136:13: warning: no previous extern declaration + for non-static variable 'logdir' [-Wmissing-variable-declarations] + 136 | const char *logdir = "log"; + | ^ + .../curl/tests/server/rtspd.c:136:7: note: declare 'static' if the variable i + s not intended to be used outside of this translation unit + 136 | const char *logdir = "log"; + | ^ + .../curl/tests/server/rtspd.c:137:6: warning: no previous extern declaration + for non-static variable 'loglockfile' [-Wmissing-variable-declarations] + 137 | char loglockfile[256]; + | ^ + .../curl/tests/server/rtspd.c:137:1: note: declare 'static' if the variable i + s not intended to be used outside of this translation unit + 137 | char loglockfile[256]; + | ^ + .../curl/tests/server/fake_ntlm.c:43:13: warning: no previous extern declarat + ion for non-static variable 'logdir' [-Wmissing-variable-declarations] + 43 | const char *logdir = "log"; + | ^ + .../curl/tests/server/fake_ntlm.c:43:7: note: declare 'static' if the variabl + e is not intended to be used outside of this translation unit + 43 | const char *logdir = "log"; + | ^ + .../curl/src/tool_doswin.c:350:8: warning: possible misuse of comma operator + here [-Wcomma] + 350 | ++d, ++s; + | ^ + .../curl/src/tool_doswin.c:350:5: note: cast expression to void to silence wa + rning + 350 | ++d, ++s; + | ^~~ + | (void)( ) + ``` - - If the user set a legacy algorithm list (CURLOPT_SSL_CIPHER_LIST) then - use the SCHANNEL_CRED legacy structure to pass the list to Schannel. + ``` + .../curl/tests/libtest/lib540.c:146:27: warning: result of comparison 'long' + > 2147483647 is always false [-Wtautological-type-limit-compare] + 146 | int itimeout = (L > (long)INT_MAX) ? INT_MAX : (int)L; + | ~ ^ ~~~~~~~~~~~~~ + 1 warning generated. - - If the user set both a legacy algorithm list and a TLS 1.3 cipher list - then abort. + .../curl/tests/libtest/libntlmconnect.c:195:31: warning: result of comparison + 'long' > 2147483647 is always false [-Wtautological-type-limit-compare] + 195 | int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeo + ut; + | ~~~~~~~ ^ ~~~~~~~~~~~~~ + 1 warning generated. - Although MS doesn't document it, Schannel will not negotiate TLS 1.3 - when SCHANNEL_CRED is used. That means setting a legacy algorithm list - limits the user to earlier versions of TLS. + .../curl/tests/libtest/lib591.c:117:31: warning: result of comparison 'long' + > 2147483647 is always false [-Wtautological-type-limit-compare] + 117 | int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeo + ut; + | ~~~~~~~ ^ ~~~~~~~~~~~~~ + 1 warning generated. + .../curl/tests/libtest/lib597.c:99:31: warning: result of comparison 'long' > + 2147483647 is always false [-Wtautological-type-limit-compare] + 99 | int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeo + ut; + | ~~~~~~~ ^ ~~~~~~~~~~~~~ + 1 warning generated. + ``` - Prior to this change, since 8beff435 (precedes 7.85.0), libcurl would - ignore legacy algorithms in Windows 10 1809 and later. + Seen on macOS Intel: + ``` + .../curl/tests/server/sws.c:440:64: warning: field precision should have type + 'int', but argument has type 'size_t' (aka 'unsigned long') [-Wformat] + msnprintf(logbuf, sizeof(logbuf), "Got request: %s %.*s HTTP/%d.%d" + , + ~~^~ + 1 warning generated. + ``` - Reported-by: zhihaoy@users.noreply.github.com + Closes #11925 - Fixes https://github.com/curl/curl/pull/10741 - Closes https://github.com/curl/curl/pull/10746 +Jay Satiro (24 Sep 2023) -Daniel Stenberg (2 Aug 2023) +- url: fix netrc info message -- variable.d: setting a variable again overwrites it + - Fix netrc info message to use the generic ".netrc" filename if the + user did not specify a netrc location. - Reported-by: Niall McGee - Bug: https://twitter.com/niallmcgee/status/1686523075423322113 - Closes #11571 + - Update --netrc doc to add that recent versions of curl on Windows + prefer .netrc over _netrc. -Jay Satiro (2 Aug 2023) + Before: + * Couldn't find host google.com in the (nil) file; using defaults -- CURLOPT_PROXY_SSL_OPTIONS.3: sync formatting - - - Re-wrap CURLSSLOPT_ALLOW_BEAST description. + After: + * Couldn't find host google.com in the .netrc file; using defaults -Daniel Stenberg (2 Aug 2023) + Closes https://github.com/curl/curl/pull/11904 -- RELEASE-NOTES: synced +Dan Fandrich (23 Sep 2023) -- resolve: use PF_INET6 family lookups when CURL_IPRESOLVE_V6 is set +- wolfssh: do cleanup in Curl_ssh_cleanup - Previously it would always do PF_UNSPEC if CURL_IPRESOLVE_V4 is not - used, thus unnecessarily asking for addresses that will not be used. + Closes: #11921 - Reported-by: Joseph Tharayil - Fixes #11564 - Closes #11565 +Daniel Stenberg (24 Sep 2023) -- docs: link to the website versions instead of markdowns +- tool_listhelp: regenerated - ... to make the links work when the markdown is converted to webpages on - https://curl.se + Polished the --ipfs-gateway description - Reported-by: Maurício Meneghini Fauth - Fixes https://github.com/curl/curl-www/issues/272 - Closes #11569 + Fixed the --trace-config description -Viktor Szakats (1 Aug 2023) + The script also fixed some other small mistakes -- cmake: cache more config and delete unused ones + Closes #11923 - - cache more Windows config results for faster initialization. +Viktor Szakats (23 Sep 2023) - - delete unused config macros `HAVE_SYS_UTSNAME_H`, `HAVE_SSL_H`. +- Makefile.mk: always set `CURL_STATICLIB` for lib (Windows) - - delete dead references to `sys/utsname.h`. + Also fix to export all symbols in Windows debug builds, making + `-debug-dyn` builds work with `-DCURL_STATICLIB` set. - Closes #11551 + Ref: https://github.com/curl/curl/pull/11914 (same for CMake) -- egd: delete feature detection and related source code + Closes #11924 - EGD is Entropy Gathering Daemon, a socket-based entropy source supported - by pre-OpenSSL v1.1 versions and now deprecated. curl also deprecated it - a while ago. +Daniel Stenberg (23 Sep 2023) - Its detection in CMake was broken all along because OpenSSL libs were - not linked at the point of feature check. +- quic: set ciphers/curves the same way regular TLS does - Delete detection from both cmake and autotools, along with the related - source snippet, and the `--with-egd-socket=` `./configure` option. + for OpenSSL/BoringSSL - Closes #11556 + Fixes #11796 + Reported-by: Karthikdasari0423 on github + Assisted-by: Jay Satiro + Closes #11836 -Stefan Eissing (1 Aug 2023) +- test457: verify --max-filesize with chunked encoding -- tests: fix h3 server check and parallel instances +- lib: let the max filesize option stop too big transfers too - - fix check for availability of nghttpx server - - add `tcp` frontend config for same port as quic, as - without this, port 3000 is bound which clashes for parallel - testing + Previously it would only stop them from getting started if the size is + known to be too big then. - Closes #11553 + Update the libcurl and curl docs accordingly. -Daniel Stenberg (1 Aug 2023) + Fixes #11810 + Reported-by: Elliot Killick + Assisted-by: Jay Satiro + Closes #11820 -- docs/cmdline-opts: spellfixes, typos and polish +Viktor Szakats (23 Sep 2023) - To make them accepted by the spell checker +- mingw: delete support for legacy mingw.org toolchain - Closes #11562 + Drop support for "old" / "legacy" / "classic" / "v1" / "mingw32" MinGW: + https://en.wikipedia.org/wiki/MinGW, https://osdn.net/projects/mingw/ + Its homepage used to be http://mingw.org/ [no HTTPS], and broken now. + It supported the x86 CPU only and used a old Windows API header and + implib set, often causing issues. It also misses most modern Windows + features, offering old versions of both binutils and gcc (no llvm/clang + support). It was last updated 2 years ago. -- CI/spellcheck: build curl.1 and spellcheck it + curl now relies on toolchains based on the mingw-w64 project: + https://www.mingw-w64.org/ https://sourceforge.net/projects/mingw-w64/ + https://www.msys2.org/ https://github.com/msys2/msys2 + https://github.com/mstorsjo/llvm-mingw + (Also available via Linux and macOS package managers.) - Added acceptable words + Closes #11625 - Closes #11562 +Mark Gaiser (23 Sep 2023) -Alexander Jaeger (1 Aug 2023) +- curl: add support for the IPFS protocols: -- misc: fix various typos + - ipfs:// + - ipns:// - Closes #11561 + This allows you tu use ipfs in curl like: + curl ipfs:// + and + curl ipns:// -Daniel Stenberg (1 Aug 2023) + For more information consult the readme at: + https://curl.se/docs/ipfs.html -- http2: avoid too early connection re-use/multiplexing + Closes #8805 - HTTP/1 connections that are upgraded to HTTP/2 should not be picked up - for reuse and multiplexing by other handles until the 101 switching - process is completed. +Daniel Stenberg (23 Sep 2023) - Lots-of-debgging-by: Stefan Eissing - Reported-by: Richard W.M. Jones - Bug: https://curl.se/mail/lib-2023-07/0045.html - Closes #11557 +- bufq: remove Curl_bufq_skip_and_shift (unused) -- Revert "KNOWN_BUGS: build for iOS simulator on macOS 13.2 with Xcode 14" + Closes #11915 - This reverts commit 2e8a3d7cb73c85a9aa151e263315f8a496dbb9d4. +- scripts/singleuse.pl: add curl_global_trace - It's a user error for supplying incomplete information to the build system. +Viktor Szakats (22 Sep 2023) - Reported-by: Ryan Schmidt - Ref: https://github.com/curl/curl/issues/11215#issuecomment-1658729367 +- cmake: fix unity symbol collisions in h2 builds -Viktor Szakats (1 Aug 2023) + Regression from 331b89a319d0067fa1e6441719307cfef9c7960f -- cmake: add support for single libcurl compilation pass + Reviewed-by: Daniel Stenberg + Reviewed-by: Jay Satiro + Closes #11912 - Before this patch CMake builds used two separate compilation passes to - build the shared and static libcurl respectively. This patch allows to - reduce that to a single pass if the target platform and build settings - allow it. +Daniel Stenberg (22 Sep 2023) - This reduces CMake build times when building both static and shared - libcurl at the same time, making these dual builds an almost zero-cost - option. +- RELEASE-NOTES: synced - Enable this feature for Windows builds, where the difference between the - two passes was the use of `__declspec(dllexport)` attribute for exported - API functions for the shared builds. This patch replaces this method - with the use of `libcurl.def` at DLL link time. +Dan Fandrich (21 Sep 2023) - Also update `Makefile.mk` to use `libcurl.def` to export libcurl API - symbols on Windows. This simplifies (or fixes) this build method (e.g. - in curl-for-win, which generated a `libcurl.def` from `.h` files using - an elaborate set of transformations). +- github/labeler: improve the match patterns - `libcurl.def` has the maintenance cost of keeping the list of public - libcurl API symbols up-to-date. This list seldom changes, so the cost - is low. + This includes new rules for setting the appleOS and logging labels and + matches on some example files. Also, enable dot mode for wildcard + matches in the .github directory. - Closes #11546 +Daniel Stenberg (21 Sep 2023) -- cmake: detect `SSL_set0_wbio` in OpenSSL +- upload-file.d: describe the file name slash/backslash handling - Present in OpenSSL 1.1.0 and BoringSSL. - Missing from LibreSSL 3.8.0. + Closes #11911 - Follow-up to f39472ea9f4f4e12cfbc0500c4580a8d52ce4a59 +Jakub Jelen (21 Sep 2023) - While here, also fix `RAND_egd()` detection which was broken, likely all - along. This feature is probably broken with CMake builds and also - requires a sufficiently obsolete OpenSSL version, so this part of the - update was not tested. +- libssh: cap SFTP packet size sent - Closes #11555 + Due to libssh limitations -- cmake: fixup H2 duplicate symbols for unity builds + Signed-off-by: Jakub Jelen - Closes #11550 + Closes #11804 -Pablo Busse (1 Aug 2023) +Daniel Stenberg (21 Sep 2023) -- openssl: Support async cert verify callback +- curl.h: mark CURLSSLBACKEND_NSS as deprecated since 8.3.0 - - Update the OpenSSL connect state machine to handle - SSL_ERROR_WANT_RETRY_VERIFY. + Closes #11905 - This allows libcurl users that are using custom certificate validation - to suspend processing while waiting for external I/O during certificate - validation. +- mailmap: unify Michael Osipov under a single email - Closes https://github.com/curl/curl/pull/11499 +Ted Lyngmo (21 Sep 2023) -Jay Satiro (1 Aug 2023) +- docs: use CURLSSLBACKEND_NONE -- tool_cb_wrt: fix invalid unicode for windows console + [ssl] use CURLSSLBACKEND_NONE instead of (curl_sslbackend)-1 in + documentation and examples. - - Suppress an incomplete UTF-8 sequence at the end of the buffer. + Signed-off-by: Ted Lyngmo - - Attempt to reconstruct incomplete UTF-8 sequence from prior call(s) - in current call. + Closes #11909 - Prior to this change, in Windows console UTF-8 sequences split between - two or more calls to the write callback would cause invalid "replacement - characters" U+FFFD to be printed instead of the actual Unicode - character. This is because in Windows only UTF-16 encoded characters are - printed to the console, therefore we convert the UTF-8 contents to - UTF-16, which cannot be done with partial UTF-8 sequences. +Dan Fandrich (21 Sep 2023) - Reported-by: Maksim Arhipov +- github/labeler: give the sync-labels config item a default value - Fixes https://github.com/curl/curl/issues/9841 - Closes https://github.com/curl/curl/pull/10890 + This shouldn't be necessary and is likely a bug with this beta version + of the labeller. -Daniel Stenberg (1 Aug 2023) + Also, fix the negative matches for the documentation label. -- sectransp: prevent CFRelease() of NULL + Follow-up to dd12b452a + Closes #11907 - When SecCertificateCopyCommonName() returns NULL, the common_name - pointer remains set to NULL which apparently when calling CFRelease() on - (sometimes?) crashes. +- github/labeler: fix up more the labeler config format - Reported-by: Guillaume Algis - Fixes #9194 - Closes #11554 + The new version didn't like the workaround we had for a bug in the + previous labeler version, and it should no longer be needed. -Jay Satiro (1 Aug 2023) + Follow-up to dd12b452a + Closes #11906 -- vtls: clarify "ALPN: offers" message +- github/labeler: fix indenting to try to appease labeller - Before: - * ALPN: offers h2,http/1.1 + Follow-up to dd12b452a - After: - * ALPN: curl offers h2,http/1.1 +Jay Satiro (21 Sep 2023) - Bug: https://curl.se/mail/lib-2023-07/0041.html - Reported-by: Richard W.M. Jones - Closes #11544 +- libssh2: fix error message on failed pubkey-from-file -Daniel Stenberg (1 Aug 2023) + - If libssh2_userauth_publickey_fromfile_ex returns -1 then show error + message "SSH public key authentication failed: Reason unknown (-1)". -- urlapi: make sure zoneid is also duplicated in curl_url_dup + When libssh2_userauth_publickey_fromfile_ex returns -1 it does so as a + generic error and therefore doesn't set an error message. AFAICT that is + not documented behavior. - Add several curl_url_dup() tests to the general lib1560 test. + Prior to this change libcurl retrieved the last set error message which + would be from a previous function failing. That resulted in misleading + auth failed error messages in verbose mode. - Reported-by: Rutger Broekhoff - Bug: https://curl.se/mail/lib-2023-07/0047.html - Closes #11549 + Bug: https://github.com/curl/curl/issues/11837#issue-1891827355 + Reported-by: consulion@users.noreply.github.com -Sergey (1 Aug 2023) + Closes https://github.com/curl/curl/pull/11881 -- urlapi: fix heap buffer overflow +Stefan Eissing (21 Sep 2023) - `u->path = Curl_memdup(path, pathlen + 1);` accesses bytes after the null-ter - minator. +- pytest: exclude test_03_goaway in CI runs due to timing dependency - ``` - ==2676==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x04d48c75 a - t pc 0x0112708a bp 0x006fb7e0 sp 0x006fb3c4 - READ of size 78 at 0x04d48c75 thread T0 - #0 0x1127089 in __asan_wrap_memcpy D:\a\_work\1\s\src\vctools\asan\llvm\c - ompiler-rt\lib\sanitizer_common\sanitizer_common_interceptors.inc:840 - #1 0x1891a0e in Curl_memdup C:\actions-runner\_work\client\client\third_p - arty\curl\lib\strdup.c:97 - #2 0x18db4b0 in parseurl C:\actions-runner\_work\client\client\third_part - y\curl\lib\urlapi.c:1297 - #3 0x18db819 in parseurl_and_replace C:\actions-runner\_work\client\clien - t\third_party\curl\lib\urlapi.c:1342 - #4 0x18d6e39 in curl_url_set C:\actions-runner\_work\client\client\third_ - party\curl\lib\urlapi.c:1790 - #5 0x1877d3e in parseurlandfillconn C:\actions-runner\_work\client\client - \third_party\curl\lib\url.c:1768 - #6 0x1871acf in create_conn C:\actions-runner\_work\client\client\third_p - arty\curl\lib\url.c:3403 - #7 0x186d8dc in Curl_connect C:\actions-runner\_work\client\client\third_ - party\curl\lib\url.c:3888 - #8 0x1856b78 in multi_runsingle C:\actions-runner\_work\client\client\thi - rd_party\curl\lib\multi.c:1982 - #9 0x18531e3 in curl_multi_perform C:\actions-runner\_work\client\client\ - third_party\curl\lib\multi.c:2756 - ``` + Closes #11860 - Closes #11560 +- lib: disambiguate Curl_client_write flag semantics -Daniel Stenberg (31 Jul 2023) + - use CLIENTWRITE_BODY *only* when data is actually body data + - add CLIENTWRITE_INFO for meta data that is *not* a HEADER + - debug assertions that BODY/INFO/HEADER is not used mixed + - move `data->set.include_header` check into Curl_client_write + so protocol handlers no longer have to care + - add special in FTP for `data->set.include_header` for historic, + backward compatible reasons + - move unpausing of client writes from easy.c to sendf.c, so that + code is in one place and can forward flags correctly -- curl: make %output{} in -w specify a file to write to + Closes #11885 - It can be used multiple times. Use %output{>>name} to append. +Patrick Monnerat (21 Sep 2023) - Add docs. Test 990 and 991 verify. +- tftpd: always use curl's own tftp.h - Idea: #11400 - Suggested-by: ed0d2b2ce19451f2 - Closes #11416 + Using the system's provided arpa/tftp.h and optimizing, GCC 12 detects + and reports a stringop-overread warning: + + tftpd.c: In function ‘write_behind.isra’: + tftpd.c:485:12: warning: ‘write’ reading between 1 and 2147483647 bytes f + rom a region of size 0 [-Wstringop-overread] + 485 | return write(test->ofile, writebuf, count); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + In file included from tftpd.c:71: + /usr/include/arpa/tftp.h:58:30: note: source object ‘tu_data’ of size 0 + 58 | char tu_data[0]; /* data or error stri + ng */ + | ^~~~~~~ + + This occurs because writebuf points to this field and the latter + cannot be considered as being of dynamic length because it is not + the last field in the structure. Thus it is bound to its declared + size. + + This commit always uses curl's own version of tftp.h where the + target field is last in its structure, effectively avoiding the + warning. + + As HAVE_ARPA_TFTP_H is not used anymore, cmake/configure checks for + arpa/tftp.h are removed. + + Closes #11897 + +Dan Fandrich (20 Sep 2023) + +- test1474: make precheck more robust on non-Solaris systems + + If uname -r returns something odd, perl could return an error code and + the test would be erroneously skipped. The qx// syntax avoid this. + + Followup to 08f9b2148 + +- github/labeler: switch to the 5 beta version + + This version adds an important feature that will allow more PRs to be + labelled. Rather than being limited to labeling PRs with files that + match a single glob, it can now label them if multiple changed files + match any one of a number of globs. + +Daniel Stenberg (20 Sep 2023) + +- lib: enable hmac for digest as well + + Previously a build that disabled NTLM and aws-sigv4 would fail to build + since the hmac was disabled, but it is also needed for digest auth. + + Follow-up to e92edfbef64448ef + + Fixes #11890 + Reported-by: Aleksander Mazur + Closes #11896 + +- idn: if idn2_check_version returns NULL, return error + + ... this avoids a NULL dereference for this unusual case. + + Reported-by: s0urc3_ on hackerone + Closes #11898 + +- http: fix CURL_DISABLE_BEARER_AUTH breakage + + When bearer auth was disabled, the if/else logic got wrong and caused + problems. + + Follow-up to e92edfbef64448ef461 + Fixes #11892 + Reported-by: Aleksander Mazur + Closes #11895 + +Michael Osipov (20 Sep 2023) + +- wolfssl: allow capath with CURLOPT_CAINFO_BLOB + + Remain consistent with OpenSSL. While CAfile is nulled as documented + with CURLOPT_CAINFO_BLOB, CApath remains intact. + + Closes #11886 + +- wolfssl: use ssl_cafile/ssl_capath variables consistent with openssl.c + + Closes #11886 + +Dan Fandrich (19 Sep 2023) + +- test1474: disable test on NetBSD, OpenBSD and Solaris 10 + + These kernels only send a fraction of the requested amount of the first + large block, invalidating the assumptions of the test and causing it to + fail. + + Assisted-by: Christian Weisgerber + Ref: https://curl.se/mail/lib-2023-09/0021.html + Closes #11888 + +Ryan Schmidt (20 Sep 2023) + +- cmake, configure: also link with CoreServices + + When linking with CoreFoundation, also link with CoreServices which is + apparently required to avoid an NSInvalidArgumentException in software + linking with libcurl on macOS Sonoma 14 and later. + + Fixes #11893 + Closes #11894 + +Marc Hoersken (19 Sep 2023) + +- CI/azure: remove pip, wheel, cryptography, pyopenssl and impacket + + These dependencies are now already included in the Docker image. + + Ref: https://github.com/mback2k/curl-docker-winbuildenv/commit/2607a31bcab544 + b41d15606e97f38cf312c1ce56 + + Closes #11889 + +Daniel Stenberg (19 Sep 2023) + +- wolfssl: if CURLOPT_CAINFO_BLOB is set, ignore the CA files + + Ref: #11883 + Reported-by: Michael Osipov + Closes #11884 - RELEASE-NOTES: synced -- tool: add "variable" support +- test3103: CURLOPT_COOKIELIST test - Add support for command line variables. Set variables with --variable - name=content or --variable name@file (where "file" can be stdin if set - to a single dash (-)). +- cookie: set ->running in cookie_init even if data is NULL - Variable content is expanded in option parameters using "{{name}}" - (without the quotes) if the option name is prefixed with - "--expand-". This gets the contents of the variable "name" inserted, or - a blank if the name does not exist as a variable. Insert "{{" verbatim - in the string by prefixing it with a backslash, like "\\{{". + This is a regression introduced in b1b326ec500 (shipped in curl 8.1.0) - Import an environment variable with --variable %name. It makes curl exit - with an error if the environment variable is not set. It can also rather - get a default value if the variable does not exist, using =content or - @file like shown above. + Test 3103 verifies. - Example: get the USER environment variable into the URL: + Fixes #11875 + Reported-by: wangp on github + Closes #11876 - --variable %USER - --expand-url = "https://example.com/api/{{USER}}/method" +- test498: total header size for all redirects is larger than accepted - When expanding variables, curl supports a set of functions that can make - the variable contents more convenient to use. It can trim leading and - trailing white space with "trim", output the contents as a JSON quoted - string with "json", URL encode it with "url" and base 64 encode it with - "b64". To apply functions to a variable expansion, add them colon - separated to the right side of the variable. They are then performed in - a left to right order. +- http: use per-request counter to check too large headers - Example: get the contents of a file called $HOME/.secret into a variable - called "fix". Make sure that the content is trimmed and percent-encoded - sent as POST data: + Not the counter that accumulates all headers over all redirects. - --variable %HOME=/home/default - --expand-variable fix@{{HOME}}/.secret - --expand-data "{{fix:trim:url}}" - https://example.com/ + Follow-up to 3ee79c1674fd6 - Documented. Many new test cases. + Do a second check for 20 times the limit for the accumulated size for + all headers. + + Fixes #11871 + Reported-by: Joshix-1 on github + Closes #11872 + +Jay Satiro (18 Sep 2023) + +- THANKS: add Eric Murphy + + He reported #11850 (quiche build error) but I forgot to add a + 'reported-by' entry in the fix 267e14f1. + +Daniel Stenberg (18 Sep 2023) + +- h2-proxy: remove left-over mistake in drain_tunnel() + + Left-over from 331b89a319 + + Reported-by: 南宫雪珊 + + Closes https://github.com/curl/curl/pull/11877 + +vvb2060 (18 Sep 2023) + +- lib: failf/infof compiler warnings + + Closes #11874 + +Daniel Stenberg (17 Sep 2023) + +- rand: fix 'alnum': array is too small to include a terminating null character + + It was that small on purpose, but this change now adds the null byte to + avoid the error. + + Follow-up to 3aa3cc9b052353b1 + + Reported-by: Dan Fandrich + Ref: #11838 + Closes #11870 + +Mathias Fuchs (16 Sep 2023) + +- cmake: fix the help text to the static build option in CMakeLists.txt + + Closes #11843 + +John Haugabook (16 Sep 2023) + +- MANUAL.md: change domain to example.com + + Closes #11866 + +Daniel Stenberg (16 Sep 2023) + +- doh: inherit DEBUGFUNCTION/DATA + + When creating new transfers for doing DoH, they now inherit the debug + settings from the initiating transfer, so that the application can + redirect and handle the verbose output correctly even for the DoH + transfers. + + Reported-by: calvin2021y on github + Fixes #11864 + Closes #11869 + +Dan Fandrich (16 Sep 2023) + +- http_aws_sigv4: fix sorting with empty parts + + When comparing with an empty part, the non-empty one is always + considered greater-than. Previously, the two would be considered equal + which would randomly place empty parts amongst non-empty ones. This + showed as a test 439 failure on Solaris as it uses a different + implementation of qsort() that compares parts differently. + + Fixes #11855 + Closes #11868 + +- CI: ignore the "flaky" and "timing-dependent" test results + + CI builds will now run these tests, but will ignore the results if they + fail. The relevant tests are ones that are sensitive to timing or + have edge conditions that make them more likely to fail on CI servers, + which are often heavily overloaded and slow. + + This change only adds two additional tests to be ignored, since the + others already had the flaky keyword. + + Closes #11865 + +- runtests: eliminate a warning on old perl versions + + The warning "Use of implicit split to @_ is deprecated" showed between + perl versions about 5.8 through 5.11. + +- tests: log the test result code after each libtest + + This makes it easier to determine the test status. Also, capitalize + FAILURE and ABORT messages in log lines to make them easier to spot. + +Harry Sintonen (16 Sep 2023) + +- misc: better random strings + + Generate alphanumerical random strings. + + Prior this change curl used to create random hex strings. This was + mostly okay, but having alphanumerical random strings is better: The + strings have more entropy in the same space. + + The MIME multipart boundary used to be mere 64-bits of randomness due + to being 16 hex chars. With these changes the boundary is 22 + alphanumerical chars, or little over 130 bits of randomness. + + Closes #11838 + +Daniel Stenberg (15 Sep 2023) + +- cookie: reduce variable scope, add const + +- cookie: do not store the expire or max-age strings + + Convert it to an expire time at once and save memory. + + Closes #11862 + +- cookie: remove unnecessary struct fields + + Plus: reduce the hash table size from 256 to 63. It seems unlikely to + make much of a speed difference for most use cases but saves 1.5KB of + data per instance. + + Closes #11862 + +- RELEASE-NOTES: synced + + Bumped to 8.4.0, the next presumed version + +Dan Fandrich (14 Sep 2023) + +- test2600: remove special case handling for USE_ALARM_TIMEOUT + + This was originally added to handle platforms that supported only 1 + second granularity in connect timeouts, but after some recent changes + the test currently permafails on several Windows platforms. + + The need for this special-case was removed in commit 8627416, which + increased the connect timeout in all cases to well above 1 second. + + Fixes #11767 + Closes #11849 + +Daniel Stenberg (14 Sep 2023) + +- SECURITY-PROCESS.md. call it vulnerability disclosure policy + + SECURITY-PROCESS.md -> VULN-DISCLOSURE-POLICY.md + + This a name commonly used for a document like this. This name helps + users find it. + + Closes #11852 + +Junho Choi (14 Sep 2023) + +- quiche: fix build error with --with-ca-fallback + + - Fix build error when curl is built with --with-quiche + and --with-ca-fallback. + + - Add --with-ca-fallback to the quiche CI job. + + Fixes https://github.com/curl/curl/issues/11850 + Closes https://github.com/curl/curl/pull/11847 + +Jay Satiro (14 Sep 2023) + +- escape: replace Curl_isunreserved with ISUNRESERVED + + - Use the ALLCAPS version of the macro so that it is clear a macro is + being called that evaluates the variable multiple times. + + - Also capitalize macro isurlpuntcs => ISURLPUNTCS since it evaluates + a variable multiple times. + + This is a follow-up to 291d225a which changed Curl_isunreserved into an + alias macro for ISUNRESERVED. The problem is the former is not easily + identified as a macro by the caller, which could lead to a bug. + + For example, ISUNRESERVED(*foo++) is easily identifiable as wrong but + Curl_isunreserved(*foo++) is not even though they both are the same. + + Closes https://github.com/curl/curl/pull/11846 + +Dan Fandrich (13 Sep 2023) + +- tests: increase the default server logs lock timeout + + This timeout is used to wait for the server to finish writing its logs + before checking them against the expected values. An overloaded machine + could take more than the two seconds previously allocated, so increase + the timeout to 5 seconds. + + Ref: #11328 + Closes #11834 + +- tests: increase TEST_HANG_TIMEOUT in two tests + + These tests had a 5 second timeout compared to 60 seconds for all other + tests. Make these consistent with the others for more reliability on + heavily-loaded machines. + + Ref: #11328 + +- test1056: disable on Windows + + This test relies on the IPv6 scope field being ignored when connecting to + ipv6-localhost (i.e. [::1%259999] is treated as [::1]). Maybe this is a bit + dodgy, but it works on all our test platforms except Windows. This + test was disabled manually on all Windows CI builds already, so instead + add an incompatible feature and precheck so it's skipped on Windows + everywhere automatically. + +- test587: add a slight delay after test + + This test is designed to connect to the server, then immediately send a + few bytes and disconnect. In some situations, such as on a loaded + server, this doesn't give the server enough time to write its lock file + before its existence is checked. The test harness then fails to find the + server's input log file (because it hasn't been written yet) and fails + the test. By adding a short delay after the test, the HTTP server has + enough time to write its lock file which gives itself more time to write + its remaining files. + + Ref: #11328 + +- tests: stop overriding the lock timeout + + These tests reduce the server lock wait timeout which can increase + flakiness on loaded machines. Since this is merely an optimization, + eliminate them in favour of reliability. + + Ref: #11328 + +- tests: add some --expect100-timeout to reduce timing dependencies + + These tests can fail when the test machine is so slow that the test HTTP + server didn't get a chance to complete before the client's one second + 100-continue timeout triggered. Increase that 1 second to 999 seconds so + this situation doesn't happen. + + Ref: #11328 + +- test661: return from test early in case of curl error + +- tests: add the timing-dependent keyword on several tests + + These are ones likely to fail on heavily-loaded machines that alter the + normal test timing. Most of these tests already had the flaky keyword + since this condition makes them more likely to fail on CI. + +- test1592: greatly increase the maximum test timeout + + It was too short to be reliable on heavily loaded CI machines, and + as a fail-safe only, it didn't need to be short. + + Ref: #11328 + +- test: minor test cleanups + + Remove an obsolete block of code in tests 2032 & 576. + Add a comment in test 1474. + +- tests: quadruple the %FTPTIME2 and %FTPTIME3 timeouts + + This gives more of a margin for error when running on overloaded CI + servers. + + Ref: #11328 + +- tests: improve SLOWDOWN test reliability by reducing sent data + + These tests are run in SLOWDOWN mode which adds a 10 msec delay after + each character output, which means it takes at least 1.6 seconds (and + 320 kernel calls) just to get through the long welcome banner. On an + overloaded system, this can end up taking much more than 1.6 seconds, + and even more than the 7 or 16 second curl timeout that the tests rely + on, causing them to fail. Reducing the size of the welcome banner drops + the total number of characters sent before the transfer starts by more + than half, which reduces the opportunity for test-breaking slowdowns by + the same amount. + + Ref: #11328 + +- test650: fix an end tag typo + +Jay Satiro (13 Sep 2023) + +- tool_cb_wrt: fix debug assertion + + - Fix off-by-one out-of-bounds array index in Windows debug assertion. + + Bug: https://github.com/curl/curl/commit/af3f4e41#r127212213 + Reported-by: Gisle Vanem + +Daniel Stenberg (13 Sep 2023) + +- ctype: add ISUNRESERVED() + + ... and make Curl_isunreserved() use that macro instead of providing a + separate funtion for the purpose. + + Closes #11840 + +Version 8.3.0 (13 Sep 2023) + +Daniel Stenberg (13 Sep 2023) + +- RELEASE-NOTES: syn ced + + curl 8.3.0 release - Co-brainstormed-by: Emanuele Torre - Assisted-by: Jat Satiro - Closes #11346 +- THANKS: contributors from 8.3.0 -- KNOWN_BUGS: cygwin: make install installs curl-config.1 twice +Thorsten Klein (12 Sep 2023) - Closes #8839 +- cmake: set SIZEOF_LONG_LONG in curl_config.h -- KNOWN_BUGS: build for iOS simulator on macOS 13.2 with Xcode 14 + in order to support 32bit builds regarding wolfssl CTC_SETTINGS - Closes #11215 + Closes #11839 -- KNOWN_BUGS: cmake outputs: no version information available +Jay Satiro (12 Sep 2023) - Closes #11158 +- curl_ngtcp2: fix error message -- KNOWN_BUGS: APOP authentication fails on POP3 +- http_aws_sigv4: handle no-value user header entries - Closes #10073 + - Handle user headers in format 'name:' and 'name;' with no value. -- KNOWN_BUGS: hyper is slow + The former is used when the user wants to remove an internal libcurl + header and the latter is used when the user actually wants to send a + no-value header in the format 'name:' (note the semi-colon is converted + by libcurl to a colon). - Closes #11203 + Prior to this change the AWS header import code did not special case + either of those and the generated AWS SignedHeaders would be incorrect. -Patrick Monnerat (31 Jul 2023) + Reported-by: apparentorder@users.noreply.github.com -- configure, cmake, lib: more form api deprecation + Ref: https://curl.se/docs/manpage.html#-H - Introduce a --enable-form-api configure option to control its inclusion - in builds. The condition name defined for it is CURL_DISABLE_FORM_API. + Fixes https://github.com/curl/curl/issues/11664 + Closes https://github.com/curl/curl/pull/11668 - Form api code is dependent of MIME: configure and CMake handle this - dependency automatically: CMake by making it a dependent option - explicitly, configure by inheriting the MIME value by default and - rejecting explicit incompatible values. +Dan Fandrich (11 Sep 2023) - "form-api" is now a new hidden test feature. +- CI: run pytest with the -v option - Update libcurl modules to respect this option and adjust tests - accordingly. + This lists of the test cases being run so it can be tracked over time. - Closes #9621 + Closes #11824 -Daniel Stenberg (31 Jul 2023) +Daniel Stenberg (11 Sep 2023) -- mailmap: add Derzsi Dániel +- HTTP3: the msquic backend is not functional -Derzsi Dániel (31 Jul 2023) + I ask that we do not submit bugs for this backend just yet as we know it + does not fully work. -- wolfssl: support loading system CA certificates + Closes #11831 + Closes #11819 - Closes #11452 +- aws_sigv4: the query canon code miscounted URL encoded input -Viktor Szakats (30 Jul 2023) + Added some extra ampersands to test 439 to verify "blank" query parts -- nss: delete more NSS references + Follow-up to fc76a24c53b08cdf - Fix the distcheck CI failure and delete more NSS references. + Closes #11829 - Follow-up to 7c8bae0d9c9b2dfeeb008b9a316117d7b9675175 +vvb2060 (11 Sep 2023) - Reviewed-by: Marcel Raad - Reviewed-by: Daniel Stenberg - Closes #11548 +- quic: don't set SNI if hostname is an IP address -Daniel Stenberg (29 Jul 2023) + We already do this for TLS connections. -- nss: remove support for this TLS library + RFC 6066 says: Literal IPv4 and IPv6 addresses are not permitted in + "HostName". - Closes #11459 + Ref: https://www.rfc-editor.org/rfc/rfc6066#section-3 -Ryan Schmidt (29 Jul 2023) + Fixes https://github.com/curl/curl/issues/11827 + Closes https://github.com/curl/curl/pull/11828 -- macOS: fix target detection more +Daniel Stenberg (10 Sep 2023) - Now SCDynamicStoreCopyProxies is called (and the required frameworks are - linked in) on all versions of macOS and only on macOS. Fixes crash due - to undefined symbol when built with the macOS 10.11 SDK or earlier. +- RELEASE-NOTES: synced - CURL_OSX_CALL_COPYPROXIES is renamed to CURL_MACOS_CALL_COPYPROXIES and - is now only defined when SCDynamicStoreCopyProxies will actually be - called. Previously, it was defined when ENABLE_IPV6 was not defined but - SCDynamicStoreCopyProxies is not called in that case. +Benoit Pierre (10 Sep 2023) - TARGET_OS_OSX is only defined in the macOS 10.12 SDK and later and only - when dynamic targets are enabled. TARGET_OS_MAC is always defined but - means any Mac OS or derivative including macOS, iOS, tvOS, and watchOS. - TARGET_OS_IPHONE means any Darwin OS other than macOS. +- configure: fix `HAVE_TIME_T_UNSIGNED` check - Follow-up to c73b2f82 + The syntax was incorrect (need a proper main body), and the test + condition was wrong (resulting in a signed `time_t` detected as + unsigned). - Fixes #11502 - Closes #11516 + Closes #11825 -Daniel Stenberg (29 Jul 2023) +Daniel Stenberg (9 Sep 2023) -- tool_operate: allow SSL_CERT_FILE and SSL_CERT_DIR +- THANKS-filter: pszlazak on github - ... used at once. +pszlazak (9 Sep 2023) - Reported-by: Gabriel Corona - Fixes #11325 - Closes #11531 +- include.d: explain headers not printed with --fail before 7.75.0 -Thomas M. DuBuisson (29 Jul 2023) + Prior to 7.75.0 response headers were not printed if -f/--fail was used + and an error was reported by server. This was fixed in ab525c0 + (precedes 7.75.0). -- CI: remove Lift's configuration + Closes #11822 - The Lift tool is being retired. Their site reads: +Daniel Stenberg (8 Sep 2023) - "Sonatype Lift will be retiring on Sep 12, 2023, with its analysis - stopping on Aug 12, 2023." +- http_aws_sigv4: skip the op if the query pair is zero bytes - Closes #11541 + Follow-up to fc76a24c53b08cdf -Nathan Moinvaziri (29 Jul 2023) + Spotted by OSS-Fuzz -- Revert "schannel: reverse the order of certinfo insertions" + Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=62175 + Closes #11823 - This reverts commit 8986df802db9b5338d9d50a54232ebae4dbcf6dd. +- cmdline-docs: use present tense, not future - Windows does not guarantee a particular certificate ordering, even - though TLS may have its own ordering/relationship guarantees. Recent - versions of Windows 11 reversed the ordering of ceritifcates returned by - CertEnumCertificatesInStore, therefore this commit no longer works as - initially intended. libcurl makes no guarantees about certificate - ordering if the operating system can't. + + some smaller cleanups - Ref: https://github.com/curl/curl/issues/9706 + Closes #11821 - Closes https://github.com/curl/curl/pull/11536 +- cmdline-docs: make sure to phrase it as "added in ...." -wangzhikun (29 Jul 2023) + References to things that were added or changed in a specific version + should be specified as "(added in [version]) for two reasons: -- winbuild: improve check for static zlib + 1 - consistency - - Check for zlib static library name zlibstatic.lib. + 2 - to allow gen.pl to strip them out if deemed referring to too old + versions - zlib's static library has a different name depending on how it was - built. zlibstatic.lib is output by cmake. zlibstat.lib is output by - their pre-generated Visual Studio project files (in the contrib - directory) and defines ZLIB_WINAPI (ie it's meant to use stdcall - instead of cdecl if you end up exporting the zlib functions). + Closes #11821 - Prior to this change the makefile only checked for the latter. +Jay Satiro (8 Sep 2023) - Closes https://github.com/curl/curl/pull/11521 +- docs: mark --ssl-revoke-best-effort as Schannel specific -Daniel Stenberg (29 Jul 2023) + Closes https://github.com/curl/curl/pull/11760 -- configure: use the pkg-config --libs-only-l flag for libssh2 +Nathan Moinvaziri (8 Sep 2023) - ... instead of --libs, as that one also returns -L flags. +- schannel: fix ordering of cert chain info - Reported-by: Wilhelm von Thiele - Fixes #11538 - Closes #11539 + - Use CERT_CONTEXT's pbCertEncoded to determine chain order. -Viktor Szakats (29 Jul 2023) + CERT_CONTEXT from SECPKG_ATTR_REMOTE_CERT_CONTEXT contains + end-entity/server certificate in pbCertEncoded. We can use this pointer + to determine the order of certificates when enumerating hCertStore using + CertEnumCertificatesInStore. -- cmake: support building static and shared libcurl in one go + This change is to help ensure that the ordering of the certificate chain + requested by the user via CURLINFO_CERTINFO has the same ordering on all + versions of Windows. - This patch adds the ability to build a static and shared libcurl library - in a single build session. It also adds an option to select which one to - use when building the curl executable. + Prior to this change Schannel certificate order was reversed in 8986df80 + but that was later reverted in f540a39b when it was discovered that + Windows 11 22H2 does the reversal on its own. - New build options: - - `BUILD_STATIC_LIBS`. Default: `OFF`. - Enabled automatically if `BUILD_SHARED_LIBS` is `OFF`. - - `BUILD_STATIC_CURL`. Default: `OFF`. - Requires `BUILD_STATIC_LIBS` enabled. - Enabled automatically if building static libcurl only. - - `STATIC_LIB_SUFFIX`. Default: empty. - - `IMPORT_LIB_SUFFIX`. Default: `_imp` if implib filename would collide - with static lib name (typically with MSVC) in Windows builds. - Otherwise empty. + Ref: https://github.com/curl/curl/issues/9706 - Also: + Closes https://github.com/curl/curl/pull/11632 - - Stop setting the `CURL_STATICLIB` macro via `curl_config.h`, and pass - it directly to the compiler. This also allows to delete a condition - from `tests/server/CMakeLists.txt`. +Chris Talbot (8 Sep 2023) - - Complete a TODO by following the logic used in autotools (also for - `LIBCURL_NO_SHARED`), and set `-DCURL_STATICLIB` in `Cflags:` of - `libcurl.pc` for _static-only_ curl builds. +- digest: Use hostname to generate spn instead of realm - - Convert an existing CI test to build both shared and static libcurl. + In https://www.rfc-editor.org/rfc/rfc2831#section-2.1.2 - Closes #11505 + digest-uri-value should be serv-type "/" host , where host is: -Stefan Eissing (28 Jul 2023) + The DNS host name or IP address for the service requested. The + DNS host name must be the fully-qualified canonical name of the + host. The DNS host name is the preferred form; see notes on server + processing of the digest-uri. -- CI/awslc: add cache for build awslc library + Realm may not be the host, so we must specify the host explicitly. - Closes #11535 + Note this change only affects the non-SSPI digest code. The digest code + used by SSPI builds already uses the hostname to generate the spn. -- GHA/linux.yml: add caching + Ref: https://github.com/curl/curl/issues/11369 - Closes #11532 + Closes https://github.com/curl/curl/pull/11395 -Daniel Stenberg (27 Jul 2023) +Daniel Stenberg (7 Sep 2023) -- RELEASE-NOTES: synced +- docs: remove use of the word 'very' - Bump working version to 8.3.0 + It is mostly superfluous. proselint would complain. -- url: remove infof() output for "still name resolving" + Closes #11818 - The message does not help and might get spewed a lot during times. +- curl_multi_remove_handle.3: clarify what happens with connection - Reported-by: yushicheng7788 on github - Fixes #11394 - Closes #11529 + Closes #11817 -- KNOWN_BUGS: cygwin: "WARNING: UNPROTECTED PRIVATE KEY FILE!" +- RELEASE-NOTES: synced - Closes #11244 +- test439: verify query canonization for aws-sigv4 -Stefan Eissing (27 Jul 2023) +- tool_operate: make aws-sigv4 not require TLS to be used -- CI: quiche updates + Maybe not used too often, but we want it for testing and it should work. - - remove quiche from standard `linux` workflow - - add mod_h2 caching to quiche workflow - - rename quiche to quiche-linux - - move version definitions into env section +- http_aws_sigv4: canonicalize the query - Closes #11528 + Percent encoding needs to be done using uppercase, and most + non-alphanumerical must be percent-encoded. -- http2: disable asssertion blocking OSSFuzz testing + Fixes #11794 + Reported-by: John Walker + Closes #11806 - - not clear how this triggers and it blocks OSSFuzz testing other - things. Since we handle the case with an error return, disabling the - assertion for now seems the best way forward. +Wyatt O'Day (7 Sep 2023) - Fixes #11500 - Closes #11519 +- lib: add ability to disable auths individually -- http2: fix in h2 proxy tunnel: progress in ingress on sending + Both with configure and cmake - - depending on what is tunneled, the proxy may never get invoked for - receiving data explicitly. Not progressing ingress may lead to stalls - due to missed WINDOW_UPDATEs. + Closes #11490 - CI: - - add a chache for building mod_h2 +Stefan Eissing (7 Sep 2023) - Closes #11527 +- ngtcp2: fix handling of large requests -- CI ngtcp2+quictls: use nghttpx cache as in quiche build + - requests >64K are send in parts to the filter + - fix parsing of the request to assemble it correctly + from several sends + - open a QUIC stream only when the complete request has + been collected -Jay Satiro (27 Jul 2023) + Closes #11815 -- bearssl: don't load CA certs when peer verification is disabled +- openssl: when CURLOPT_SSL_CTX_FUNCTION is registered, init x509 store before - We already do this for other SSL backends. + - we delay loading the x509 store to shorten the handshake time. + However an application callback installed via CURLOPT_SSL_CTX_FUNCTION + may need to have the store loaded and try to manipulate it. + - load the x509 store before invoking the app callback - Bug: https://github.com/curl/curl/pull/11457#issuecomment-1644587473 - Reported-by: kyled-dell@users.noreply.github.com + Fixes #11800 + Reported-by: guoxinvmware on github + Cloes #11805 - Closes https://github.com/curl/curl/pull/11497 +Daniel Stenberg (7 Sep 2023) -Daniel Stenberg (26 Jul 2023) +- krb5: fix "implicit conversion loses integer precision" warnings -- easy: remove #ifdefs to make code easier on the eye + conversions to/from enum and unsigned chars - Closes #11525 + Closes #11814 -Stefan Eissing (26 Jul 2023) +Stefan Eissing (7 Sep 2023) -- GHA: adding quiche workflow +- pytest: improvements - - adding separate quiche workflow to also build nghttpx server for testing + - set CURL_CI for pytest runs in CI environments + - exclude timing sensitive tests from CI runs + - for failed results, list only the log and stat of + the failed transfer - Closes #11517 + - fix type in http.c comment -Version 8.2.1 (26 Jul 2023) + Closes #11812 -Daniel Stenberg (26 Jul 2023) +- CI: move on to ngtcp2 v0.19.1 -- RELEASE-NOTES: synced + Closes #11809 - curl 8.2.1 release +Dan Fandrich (5 Sep 2023) -- THANKS: add contributors from 8.2.1 +- CI: run Circle macOS builds on x86 for now -- docs: provide more see also for cipher options + The ARM machines aren't ready for us and requesting them now causes + warnings e-mails to be sent to some PR pushers. - More cross references. Hide nroff errors. + Ref: #11771 - Closes #11513 +Viktor Szakats (5 Sep 2023) -- docs: mark two TLS options for TLS, not SSL +- http3: adjust cast for ngtcp2 v0.19.0 - Closes #11514 + ngtcp2 v0.19.0 made size of `ecn` member of `ngtcp2_pkt_info` + an `uint8_t` (was: `uint32_t`). Adjust our local cast accordingly. -Brad Harder (25 Jul 2023) + Fixes: + ``` + ./curl/lib/vquic/curl_ngtcp2.c:1912:12: warning: implicit conversion loses in + teger precision: 'uint32_t' (aka 'unsigned int') to 'uint8_t' (aka 'unsigned + char') [-Wimplicit-int-conversion] + pi.ecn = (uint32_t)ecn; + ~ ^~~~~~~~~~~~~ + ``` -- curl_multi_wait.3: fix arg quoting to doc macro .BR + Also bump ngtcp2, nghttp3 and nghttp2 to their latest versions in our + docs and CI. - Closes #11511 + Ref: https://github.com/ngtcp2/ngtcp2/commit/80447281bbc94af53f8aa7a4cfc19175 + 782894a3 + Ref: https://github.com/ngtcp2/ngtcp2/pull/877 + Closes #11798 -Daniel Stenberg (24 Jul 2023) +Stefan Eissing (5 Sep 2023) -- RELEASE-NOTES: synced +- http: fix sending of large requests -Viktor Szakats (24 Jul 2023) + - refs #11342 where errors with git https interactions + were observed + - problem was caused by 1st sends of size larger than 64KB + which resulted in later retries of 64KB only + - limit sending of 1st block to 64KB + - adjust h2/h3 filters to cope with parsing the HTTP/1.1 + formatted request in chunks -- cmake: update ngtcp2 detection + - introducing Curl_nwrite() as companion to Curl_write() + for the many cases where the sockindex is already known - Replace `OpenSSL` with `quictls` to follow the same change - in the v0.17.0 ngtcp2 release. + Fixes #11342 (again) + Closes #11803 - Follow-up to e0093b4b732f6495b0fb1cd6747cbfedcdcf63ed +- pytest: fix check for slow_network skips to only apply when intended - Closes #11508 + Closes #11801 -Stefan Eissing (24 Jul 2023) +Daniel Stenberg (5 Sep 2023) -- http: VLH, very large header test and fixes +- curl_url_get/set.3: add missing semicolon in SYNOPSIS - - adding tests using very large passwords in auth - - fixes general http sending to treat h3 like h2, and - not like http1.1 - - eliminate H2_HEADER max definitions and use the commmon - DYN_HTTP_REQUEST everywhere, different limits do not help - - fix http2 handling of requests denied by nghttp2 on send - to immediately report the refused stream +- CURLOPT_URL.3: explain curl_url_set() uses the same parser - Closes #11509 +- CURLOPT_URL.3: add two URL API calls in the see-also section -Andrei Rybak (23 Jul 2023) +Dan Fandrich (4 Sep 2023) -- CONTRIBUTE: drop mention of copyright year ranges +- CI: add a 32-bit i686 Linux build - Year ranges in copyrights were dropped in commits [1] and [2]. - Verification of year ranges in copyrights was dropped from script - 'scripts/copyright.pl' in commit [3]. However, the corresponding - passages in file 'docs/CONTRIBUTE.md' weren't updated. + This is done by cross-compiling under regular x86_64 Linux. Since the + kernel offers backwards compatibility, the binaries can be tested as + normal. - Drop mentions of copyright year ranges from 'docs/CONTRIBUTE.md'. + Closes #11799 - [1] 2bc1d775f (copyright: update all copyright lines and remove year - ranges, 2023-01-02) - [2] c46761bd8 (tests/http: remove year ranges from copyrights, - 2023-03-14) - [3] 0e293bacb (copyright.pl: cease doing year verifications, 2023-01-28) +- tests: fix a type warning on 32-bit x86 - Closes #11504 +Viktor Szakats (4 Sep 2023) -- CONTRIBUTE: fix syntax in commit message description +- tests: delete stray `.orig` file - File 'docs/CONTRIBUTE.md' includes a description of how one should write - commit messages in the curl project. Different possible parts of the - message are enclosed in square brackets. One exception is the section - describing how the curl project doesn't use "Signed-off-by" commit - trailers [1], which is enclosed in an opening curly brace paired with a - closing square bracket. + Follow-up to 331b89a319d0067fa1e6441719307cfef9c7960f + Closes #11797 - Fix the enclosing square brackets in description of "Signed-off-by" - trailers in commit messages in file 'docs/CONTRIBUTE.md'. +Daniel Stenberg (4 Sep 2023) - [1] See description of option '--signoff' in Git documentation: - https://git-scm.com/docs/git-commit +- RELEASE-NOTES: synced - Closes #11504 +Viktor Szakats (4 Sep 2023) -Daniel Stenberg (23 Jul 2023) +- lib: silence compiler warning in inet_ntop6 -- src/mkhelp: strip off escape sequences + ``` + ./curl/lib/inet_ntop.c:121:21: warning: possible misuse of comma operator her + e [-Wcomma] + cur.base = i, cur.len = 1; + ^ + ./curl/lib/inet_ntop.c:121:9: note: cast expression to void to silence warnin + g + cur.base = i, cur.len = 1; + ^~~~~~~~~~~~ + (void)( ) + ``` - At some point the nroff command stopped stripping off escape sequences, - so then this script needs to do the job instead. + Closes #11790 - Reported-by: VictorVG on github - Fixes #11501 - Closes #11503 +Daniel Stenberg (4 Sep 2023) -- KNOWN_BUGS: building for old macOS fails with gcc +- transfer: also stop the sending on closed connection - Closes #11441 + Previously this cleared the receiving bit only but in some cases it is + also still sending (like a request-body) when disconnected and neither + direction can continue then. -Jacob Hoffman-Andrews (22 Jul 2023) + Fixes #11769 + Reported-by: Oleg Jukovec + Closes #11795 -- rustls: update rustls-ffi 0.10.0 +John Bampton (4 Sep 2023) - This brings in version 0.21.0 of the upstream rustls implementation, - which notable includes support for IP address certificates. +- docs: change `sub-domain` to `subdomain` - Closes #10865 + https://en.wikipedia.org/wiki/Subdomain -Brad Harder (22 Jul 2023) + Closes #11793 -- websocket: rename arguments/variables to match docs +Stefan Eissing (4 Sep 2023) - Pedantry/semantic-alignment between functions, docs, comments with - respect to websocket protocol code; No functional change intended. +- multi: more efficient pollfd count for poll - * "totalsize", "framesize" becomes "fragsize" (we deal in frame fragments). + - do not use separate pollfds for sockets that have POLLIN+POLLOUT - * "sendflags" becomes "flags" + Closes #11792 - * use canonical CURL *handle +- http2: polish things around POST - Closes #11493 + - added test cases for various code paths + - fixed handling of blocked write when stream had + been closed inbetween attempts + - re-enabled DEBUGASSERT on send with smaller data size -Jan Macku (21 Jul 2023) + - in debug builds, environment variables can be set to simulate a slow + network when sending data. cf-socket.c and vquic.c support + * CURL_DBG_SOCK_WBLOCK: percentage of send() calls that should be + answered with a EAGAIN. TCP/UNIX sockets. + This is chosen randomly. + * CURL_DBG_SOCK_WPARTIAL: percentage of data that shall be written + to the network. TCP/UNIX sockets. + Example: 80 means a send with 1000 bytes would only send 800 + This is applied to every send. + * CURL_DBG_QUIC_WBLOCK: percentage of send() calls that should be + answered with EAGAIN. QUIC only. + This is chosen randomly. -- bug_report: use issue forms instead of markdown template + Closes #11756 - Issue forms allow you to define web-like input forms using YAML - syntax. It allows you to guide the reporter to get the required - information. +Daniel Stenberg (4 Sep 2023) - Signed-off-by: Jan Macku - Closes #11474 +- docs: add curl_global_trace to some SEE ALSO sections -Daniel Stenberg (21 Jul 2023) + Closes #11791 -- TODO: Obey Retry-After in redirects +- os400: fix checksrc nits - (remove "Set custom client ip when using haproxy protocol" which was - shipped in 8.2.0) + Closes #11789 - Mentioned-by: Yair Lenga - Closes #11447 +Nicholas Nethercote (3 Sep 2023) -- RELEASE-NOTES: synced +- hyper: remove `hyptransfer->endtask` -Oliver Roberts (21 Jul 2023) + `Curl_hyper_stream` needs to distinguish between two kinds of + `HYPER_TASK_EMPTY` tasks: (a) the `foreach` tasks it creates itself, and + (b) background tasks that hyper produces. It does this by recording the + address of any `foreach` task in `hyptransfer->endtask` before pushing + it into the executor, and then comparing that against the address of + tasks later polled out of the executor. -- amissl: fix AmiSSL v5 detection + This works right now, but there is no guarantee from hyper that the + addresses are stable. `hyper_executor_push` says "The executor takes + ownership of the task, which should not be accessed again unless + returned back to the user with `hyper_executor_poll`". That wording is a + bit ambiguous but with my Rust programmer's hat on I read it as meaning + the task returned with `hyper_executor_poll` may be conceptually the + same as a task that was pushed, but that there are no other guarantees + and comparing addresses is a bad idea. - Due to changes in the AmiSSL SDK, the detection needed adjusting. + This commit instead uses `hyper_task_set_userdata` to mark the `foreach` + task with a `USERDATA_RESP_BODY` value which can then be checked for, + removing the need for `hyptransfer->endtask`. This makes the code look + more like that hyper C API examples, which use userdata for every task + and never look at task addresses. - Closes #11477 + Closes #11779 -Alois Klink (21 Jul 2023) +Dave Cottlehuber (3 Sep 2023) -- unittest/makefile: remove unneeded unit1621_LDADD +- ws: fix spelling mistakes in examples and tests - The `unit1621_LDADD` variable has the exact same value as the `LDADD` - flag in `Makefile.am`, except without `@LDFLAGS@ @LIBCURL_LIBS@`. + Closes #11784 - This was originally added by [98e6629][], but I can't see any reason - why it exists, so we should remove it to clean things up. +Daniel Stenberg (3 Sep 2023) - [98e6629]: https://github.com/curl/curl/commit/98e6629154044e4ab1ee7cff8351c7 - ebcb131e88 +- tool_filetime: make -z work with file dates before 1970 - Closes #11494 + Fixes #11785 + Reported-by: Harry Sintonen + Closes #11786 -- unittest/makefile: remove unneeded unit1394_LDADD +Dan Fandrich (1 Sep 2023) - These custom `unit1394_LDADD` and similar automake overrides are no - longer neded. They were originally added by added by [8dac7be][] for - metalink support, but are no longer after [265b14d][] removed metalink. +- build: fix portability of mancheck and checksrc targets - [8dac7be]: https://github.com/curl/curl/commit/8dac7be438512a8725d3c71e9139bd - fdcac1ed8c - [265b14d]: https://github.com/curl/curl/commit/265b14d6b37c4298bd5556fabcbc37 - d36f911693 + At least FreeBSD preserves cwd across makefile lines, so rules + consisting of more than one "cd X; do_something" must be explicitly run + in a subshell to avoid this. This problem caused the Cirrus FreeBSD + build to fail when parallel make jobs were enabled. - Closes #11494 +- CI: adjust labeler match patterns for new & obsolete files -- cmake: add `libcurlu`/`libcurltool` for unit tests +- configure: trust pkg-config when it's used for zlib - Add a `libcurlu`/`libcurltool` static library that is compiled only for - unit tests. We use `EXCLUDE_FROM_ALL` to make sure that they're not - built by default, they're only built if unit tests are built. + The library flags retrieved from pkg-config were later thrown out and + harded-coded, which negates the whole reason to use pkg-config. + Also, previously, the assumption was made that --libs-only-l and + --libs-only-L are the full decomposition of --libs, which is untrue and + would not allow linking against a static zlib. The new approach is + better in that it uses --libs, although only if --libs-only-l returns + nothing. - These libraries allow us to compile every unit test with CMake. + Bug: https://curl.se/mail/lib-2023-08/0081.html + Reported-by: Randall + Closes #11778 - Closes #11446 +Stefan Eissing (1 Sep 2023) -Daniel Stenberg (21 Jul 2023) +- CI/ngtcp2: clear wolfssl for when cache is ignored -- test979: test -u with redirect to (the same) absolute host + Closes #11783 - Verifies #11492 +Daniel Stenberg (1 Sep 2023) -- transfer: do not clear the credentials on redirect to absolute URL +- RELEASE-NOTES: synced - Makes test 979 work. Regression shipped in 8.2.0 from commit - dd4d1a26959f63a2c +Nicholas Nethercote (1 Sep 2023) - Fixes #11486 - Reported-by: Cloudogu Siebels - Closes #11492 +- hyper: fix a progress upload counter bug -Jon Rumsey (20 Jul 2023) + `Curl_pgrsSetUploadCounter` should be a passed a total count, not an + increment. -- os400: correct EXPECTED_STRING_LASTZEROTERMINATED + This changes the failing diff for test 579 with hyper from this: + ``` + Progress callback called with UL 0 out of 0[LF] + -Progress callback called with UL 8 out of 0[LF] + -Progress callback called with UL 16 out of 0[LF] + -Progress callback called with UL 26 out of 0[LF] + -Progress callback called with UL 61 out of 0[LF] + -Progress callback called with UL 66 out of 0[LF] + +Progress callback called with UL 29 out of 0[LF] + ``` + to this: + ``` + Progress callback called with UL 0 out of 0[LF] + -Progress callback called with UL 8 out of 0[LF] + -Progress callback called with UL 16 out of 0[LF] + -Progress callback called with UL 26 out of 0[LF] + -Progress callback called with UL 61 out of 0[LF] + -Progress callback called with UL 66 out of 0[LF] + +Progress callback called with UL 40 out of 0[LF] + ``` + Presumably a step in the right direction. - Correct EXPECTED_STRING_LASTZEROTERMINATED to account for - CURLOPT_HAPROXY_CLIENT_IP which requires EBCDIC to ASCII conversion when - passed into curl_easy_setopt(). + Closes #11780 - Closes #11476 +Daniel Stenberg (1 Sep 2023) -Oliver Roberts (20 Jul 2023) +- awssiv4: avoid freeing the date pointer on error -- amissl: add missing signal.h include + Since it was not allocated, don't free it even if it was wrong syntax - In some environments, signal.h is already included, but not in others - which cause compilation to fail, so explictly include it. + Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61908 - Closes #11478 + Follow-up to b137634ba3adb -- amigaos: fix sys/mbuf.h m_len macro clash + Closes #11782 - The updated Curl_http_req_make and Curl_http_req_make2 functions spawned - a parameter called m_len. The AmigaOS networking headers, derived from - NetBSD, contain "#define m_len m_hdr.mh_len" which clashes with - this. Since we do not actually use mbuf, force the include file to be - ignored, removing the clash. +Stefan Eissing (1 Sep 2023) - Closes #11479 +- CI: ngtcp2-linux: use separate caches for tls libraries -Daniel Stenberg (20 Jul 2023) + allow ever changing master for wolfssl -- socks: print ipv6 address within brackets + Closes #11766 - Fixes #11483 - Closes #11484 +- replace `master` as wolfssl-version with recent commit -Christian Schmitz (20 Jul 2023) +- wolfssl, use master again in CI -- libcurl-errors.3: add CURLUE_OK + - with the shared session update fix landed in master, it + is time to use that in our CI again - Closes #11488 +Nicholas Nethercote (31 Aug 2023) -Oliver Roberts (20 Jul 2023) +- tests: fix formatting errors in `FILEFORMAT.md`. -- cfilters: rename close/connect functions to avoid clashes + Without the surrounding backticks, these tags get swallowed when the + markdown is rendered. - Rename `close` and `connect` in `struct Curl_cftype` for - consistency and to avoid clashes with macros of the same name - (the standard AmigaOS networking connect() function is implemented - via a macro). + Closes #11777 - Closes #11491 +Viktor Szakats (31 Aug 2023) -Stefan Eissing (20 Jul 2023) +- cmake: add support for `CURL_DEFAULT_SSL_BACKEND` -- http2: fix regression on upload EOF handling + Allow overriding the default TLS backend via a CMake setting. - - a regression introduced by c9ec85121110d7cbbbed2990024222c8f5b8afe5 - where optimization of small POST bodies leads to a new code path - for such uploads that did not trigger the "done sending" event - - add triggering this event for early "upload_done" situations + E.g.: + `cmake [...] -DCURL_DEFAULT_SSL_BACKEND=mbedtls` - Fixes #11485 - Closes #11487 - Reported-by: Aleksander Mazur + Accepted values: bearssl, gnutls, mbedtls, openssl, rustls, + schannel, secure-transport, wolfssl -Daniel Stenberg (19 Jul 2023) + The passed string is baked into the curl/libcurl binaries. + The value is case-insensitive. -- configure: check for nghttp2_session_get_stream_local_window_size + We added a similar option to autotools in 2017 via + c7170e20d0a18ec8a514b4daa53bcdbb4dcb3a05. - The http2 code uses it now. Introduced in nghttp2 1.15.0 (Sep 2016) + TODO: Convert to lowercase to improve reproducibility. - Fixes #11470 - Reported-by: Paul Howarth - Closes #11473 + Closes #11774 -Stefan Eissing (19 Jul 2023) +- sectransp: fix compiler warnings -- quiche: fix segfault and other things + https://github.com/curl/curl-for-win/actions/runs/6037489221/job/16381860220# + step:3:11046 + ``` + /Users/runner/work/curl-for-win/curl-for-win/curl/lib/vtls/sectransp.c:2435:1 + 4: warning: unused variable 'success' [-Wunused-variable] + OSStatus success; + ^ + /Users/runner/work/curl-for-win/curl-for-win/curl/lib/vtls/sectransp.c:3300:4 + 4: warning: unused parameter 'sha256len' [-Wunused-parameter] + size_t sha256len) + ^ + ``` - - refs #11449 where a segfault is reported when IP Eyeballing did - not immediately connect but made several attempts - - The transfer initiating the eyeballing was initialized too early, - leadding to references to the filter instance that was then - replaced in the subsequent eyeball attempts. That led to a use - after free in the buffer handling for the transfer - - transfers are initiated now more lazy (like in the ngtcp2 filter), - when the stream is actually opened - - suppress reporting on quiche event errors for "other" transfers - than the current one to not fail a transfer due to faults in - another one. - - revert recent return value handling for quiche_h3_recv_body() - to not indicate an error but an EAGAIN situation. We wish quiche - would document what functions return. + Closes #11773 - Fixes #11449 - Closes #11469 - Reported-by: ウさん +- tidy-up: mostly whitespace nits -Daniel Stenberg (19 Jul 2023) + - delete completed TODO from `./CMakeLists.txt`. + - convert a C++ comment to C89 in `./CMake/CurlTests.c`. + - delete duplicate EOLs from EOF. + - add missing EOL at EOF. + - delete whitespace at EOL (except from expected test results). + - convert tabs to spaces. + - convert CRLF EOLs to LF in GHA yaml. + - text casing fixes in `./CMakeLists.txt`. + - fix a codespell typo in `packages/OS400/initscript.sh`. -- hostip: return IPv6 first for localhost resolves + Closes #11772 - Fixes #11465 - Reported-by: Chilledheart on github - Closes #11466 +Dan Fandrich (31 Aug 2023) + +- CI: remove Windows builds from Cirrus, without replacement -Harry Sintonen (19 Jul 2023) + If we don't do this, all coverage on Cirrus will cease in a few days. By + removing the Windows builds, the FreeBSD one should still continue + as before. The Windows builds will need be moved to another service to + maintain test coverage. -- tool: fix tool_seek_cb build when SIZEOF_CURL_OFF_T > SIZEOF_OFF_T + Closes #11771 - - a variable was renamed, and some use of it wasn't. this fixes the - build. +- CI: switch macOS ARM build from Cirrus to Circle CI - Closes #11468 + Cirrus is drastically reducing their free tier on Sept. 1, so they will + no longer perform all these builds for us. All but one build has been + moved, with the LibreSSL one being dropped because of linking problems + on Circle. -Stefan Eissing (19 Jul 2023) + One important note about this change is that Circle CI is currently + directing all these builds to x86_64 hardware, despite them requesting + ARM. This is because ARM nodes are scheduled to be available on the + free tier only in December. This reduces our architectural diversity + until then but it should automatically come back once those machines are + enabled. -- quiche: fix lookup of transfer at multi +- CI: use the right variable for BSD make - - refs #11449 where weirdness in quiche multi connection tranfers was - observed - - fixes lookup of transfer for a quiche event to take the connection - into account - - formerly, a transfer with the same stream_id, but on another connection - could be found + BSD uses MAKEFLAGS instead of MAKE_FLAGS so it wasn't doing parallel + builds before. - Closes #11462 +- CI: drop the FreeBSD 12.X build -Daniel Stenberg (19 Jul 2023) + Cirrus' new free tier won't let us have many builds, so drop the + nonessential ones. The FreeBSD 13.X build will still give us the most + relevant FreeBSD coverage. -- RELEASE-NOTES: synced +- CI: move the Alpine build from Cirrus to GHA - bump to 8.2.1 + Cirrus is reducing their free tier to next to nothing, so we must move + builds elsewhere. -John Haugabook (19 Jul 2023) +Stefan Eissing (30 Aug 2023) -- ciphers.d: put URL in first column +- test_07_upload.py: fix test_07_34 curl args - This makes the URL turn into a link properly when "webified". + - Pass correct filename to --data-binary. - Fixes https://github.com/curl/curl-www/issues/270 - Closes #11464 + Prior to this change --data-binary was passed an incorrect filename due + to a missing separator in the arguments list. Since aacbeae7 curl will + error on incorrect filenames for POST. -Version 8.2.0 (19 Jul 2023) + Fixes https://github.com/curl/curl/issues/11761 + Closes https://github.com/curl/curl/pull/11763 -Daniel Stenberg (19 Jul 2023) +Nicholas Nethercote (30 Aug 2023) -- RELEASE-NOTES: synced +- tests: document which tests fail due to hyper's lack of trailer support. - 8.2.0 release + Closes #11762 -- THANKS-filter: strip out "GitHub" +- docs: removing "pausing transfers" from HYPER.md. -- THANKS: add contributors from 8.2.0 + It's a reference to #8600, which was fixed by #9070. -- RELEASE-PROCEDURE.md: adjust the release dates + Closes #11764 -Stefan Eissing (17 Jul 2023) +Patrick Monnerat (30 Aug 2023) -- quiche: fix defects found in latest coverity report +- os400: handle CURL_TEMP_PRINTF() while building bind source - Closes #11455 + Closes #11547 -Daniel Stenberg (17 Jul 2023) +- os400: build test servers -- quiche: avoid NULL deref in debug logging + Also fix a non-compliant main prototype in disabled.c. - Coverity reported "Dereference after null check" + Closes #11547 - If stream is NULL and the function exits, the logging must not deref it. +- tests: fix compilation error for os400 - Closes #11454 + OS400 uses BSD 4.3 setsockopt() prototype by default: this does not + define parameter as const, resulting in an error if actual parameter is + const. Remove the const keyword from the actual parameter cast: this + works in all conditions, even if the formal parameter uses it. -Stefan Eissing (17 Jul 2023) + Closes #11547 -- http2: treat initial SETTINGS as a WINDOW_UPDATE +- os400: make programs and command name configurable - - refs #11426 where spurious stalls on large POST requests - are reported - - the issue seems to involve the following - * first stream on connection adds up to 64KB of POST - data, which is the max default HTTP/2 stream window size - transfer is set to HOLD - * initial SETTINGS from server arrive, enlarging the stream - window. But no WINDOW_UPDATE is received. - * curl stalls - - the fix un-HOLDs a stream on receiving SETTINGS, not - relying on a WINDOW_UPDATE from lazy servers + Closes #11547 - Closes #11450 +- os400: move build configuration parameters to a separate script -Daniel Stenberg (17 Jul 2023) + They can then easily be overriden in a script named "config400.override" + that is not part of the distribution. -- ngtcp2: assigning timeout, but value is overwritten before used + Closes #11547 - Reported by Coverity +- os400: implement CLI tool - Closes #11453 + This is provided as a QADRT (ascii) program, a link to it in the IFS and + a minimal CL command. -- krb5: add typecast to please Coverity + Closes #11547 -Derzsi Dániel (16 Jul 2023) +Matthias Gatto (30 Aug 2023) -- wolfssl: support setting CA certificates as blob +- lib: fix aws-sigv4 having date header twice in some cases - Closes #11445 + When the user was providing the header X-XXX-Date, the header was + re-added during signature computation, and we had it twice in the + request. -- wolfssl: detect when TLS 1.2 support is not built into wolfssl + Reported-by: apparentorder@users.noreply.github.com - Closes #11444 + Signed-off-by: Matthias Gatto -Graham Campbell (15 Jul 2023) + Fixes: https://github.com/curl/curl/issues/11738 + Closes: https://github.com/curl/curl/pull/11754 -- CI: bump nghttp2 from 1.55.0 to 1.55.1 +Jay Satiro (30 Aug 2023) - Closes #11442 +- multi: remove 'processing: ' debug message -Daniel Stenberg (15 Jul 2023) + - Remove debug message added by e024d566. -- curl: return error when asked to use an unsupported HTTP version + Closes https://github.com/curl/curl/pull/11759 - When one of the following options are used but the libcurl in use does - not support it: +- ftp: fix temp write of ipv6 address - --http2 - --http2-prior-knowledge - --proxy-http2 + - During the check to differentiate between a port and IPv6 address + without brackets, write the binary IPv6 address to an in6_addr. - Closes #11440 + Prior to this change the binary IPv6 address was erroneously written to + a sockaddr_in6 'sa6' when it should have been written to its in6_addr + member 'sin6_addr'. There's no fallout because no members of 'sa6' are + accessed before it is later overwritten. -Chris Paulson-Ellis (14 Jul 2023) + Closes https://github.com/curl/curl/pull/11747 -- cf-socket: don't bypass fclosesocket callback if cancelled before connect +- tool: change some fopen failures from warnings to errors - After upgrading to 8.1.2 from 7.84.0, I found that sockets were being - closed without calling the fclosesocket callback if a request was - cancelled after the associated socket was created, but before the socket - was connected. This lead to an imbalance of fopensocket & fclosesocket - callbacks, causing problems with a custom event loop integration using - the multi-API. + - Error on missing input file for --data, --data-binary, + --data-urlencode, --header, --variable, --write-out. - This was caused by cf_socket_close() calling sclose() directly instead - of calling socket_close() if the socket was not active. For regular TCP - client connections, the socket is activated by cf_socket_active(), which - is only called when the socket completes the connect. + Prior to this change if a user of the curl tool specified an input file + for one of the above options and that file could not be opened then it + would be treated as zero length data instead of an error. For example, a + POST using `--data @filenametypo` would cause a zero length POST which + is probably not what the user intended. - As far as I can tell, this issue has existed since 7.88.0. That is, - since the code in question was introduced by: - commit 71b7e0161032927cdfb4e75ea40f65b8898b3956 - Author: Stefan Eissing - Date: Fri Dec 30 09:14:55 2022 +0100 + Closes https://github.com/curl/curl/pull/11677 - lib: connect/h2/h3 refactor +- hostip: fix typo - Closes #11439 +Davide Masserut (29 Aug 2023) -Daniel Stenberg (13 Jul 2023) +- tool: avoid including leading spaces in the Location hyperlink -- tool_parsecfg: accept line lengths up to 10M + Co-authored-by: Dan Fandrich - Bumped from 100K set in 47dd957daff9 + Closes #11735 - Reported-by: Antoine du Hamel - Fixes #11431 - Closes #11435 +Daniel Stenberg (29 Aug 2023) -Stefan Eissing (13 Jul 2023) +- SECURITY-PROCESS.md: not a sec issue: Tricking user to run a cmdline -- CI: brew fix for openssl in default path + Closes #11757 - If brew install/update links openssl into /usr/local, it will be found - before anything we add with `-isystem path` to CPP/LDLFAGS. Get rid of - that by unlinking the keg. +- connect: stop halving the remaining timeout when less than 600 ms left - Fixes #11413 - Closes #11436 + When curl wants to connect to a host, it always has a TIMEOUT. The + maximum time it is allowed to spend until a connect is confirmed. -Daniel Stenberg (13 Jul 2023) + curl will try to connect to each of the IP adresses returned for the + host. Two loops, one for each IP family. -- RELEASE-NOTES: synced + During the connect loop, while curl has more than one IP address left to + try within a single address family, curl has traditionally allowed (time + left/2) for *this* connect attempt. This, to not get stuck on the + initial addresses in case the timeout but still allow later addresses to + get attempted. -Ondřej Koláček (13 Jul 2023) + This has the downside that when users set a very short timeout and the + host has a large number of IP addresses, the effective result might be + that every attempt gets a little too short time. -- sectransp: fix EOF handling + This change stop doing the divided-by-two if the total time left is + below a threshold. This threshold is 600 milliseconds. - Regression since the large refactor from 2022 + Closes #11693 - Closes #11427 +- asyn-ares: reduce timeout to 2000ms -Daniel Stenberg (13 Jul 2023) + When UDP packets get lost this makes for slightly faster retries. This + lower timeout is used by @c-ares itself by default starting next + release. -- checksrc: quote the file name to work with "funny" letters + Closes #11753 - Closes #11437 +John Bampton (29 Aug 2023) -Karthikdasari0423 (13 Jul 2023) +- misc: remove duplicate words -- HTTP3.md: ngtcp2 updated to v0.17.0 and nghttp3 to v0.13.0 + Closes #11740 - Follow-up to e0093b4b732f6 +Daniel Stenberg (29 Aug 2023) - Closes #11433 +- RELEASE-NOTES: synced -Daniel Stenberg (13 Jul 2023) +- wolfSSL: avoid the OpenSSL compat API when not needed -- CURLOPT_MIMEPOST.3: clarify what setting to NULL means + ... and instead call wolfSSL functions directly. - Follow-up to e08382a208d4e480 + Closes #11752 - Closes #11430 +Viktor Szakats (28 Aug 2023) -Tatsuhiro Tsujikawa (12 Jul 2023) +- lib: fix null ptr derefs and uninitialized vars (h2/h3) -- ngtcp2: build with 0.17.0 and nghttp3 0.13.0 + Fixing compiler warnings with gcc 13.2.0 in unity builds. - - ngtcp2_crypto_openssl was renamed to ngtcp2_crypto_quictls. + Assisted-by: Jay Satiro + Assisted-by: Stefan Eissing + Closes #11739 - Closes #11428 +Jay Satiro (28 Aug 2023) -- CI: Bump ngtcp2, nghttp3, and nghttp2 +- secureserver.pl: fix stunnel version parsing - Closes #11428 + - Allow the stunnel minor-version version part to be zero. -James Fuller (11 Jul 2023) + Prior to this change with the stunnel version scheme of . + if either part was 0 then version parsing would fail, causing + secureserver.pl to fail with error "No stunnel", causing tests that use + the SSL protocol to be skipped. As a practical matter this bug can only + be caused by a minor-version part of 0, since the major-version part is + always greater than 0. -- example/maxconnects: set maxconnect example + Closes https://github.com/curl/curl/pull/11722 - Closes #11343 +- secureserver.pl: fix stunnel path quoting -Pontakorn Prasertsuk (11 Jul 2023) + - Store the stunnel path in the private variable $stunnel unquoted and + instead quote it in the command strings. -- http2: send HEADER & DATA together if possible + Prior to this change the quoted stunnel path was passed to perl's file + operators which cannot handle quoted paths. For example: - Closes #11420 + $stunnel = "\"/C/Program Files (x86)/stunnel/bin/tstunnel\""; + if(-x $stunnel or -x "$stunnel") + # false even if path exists and is executable -Daniel Stenberg (11 Jul 2023) + Our other test scripts written in perl, unlike this one, use servers.pm + which has a global $stunnel variable with the path stored unquoted and + therefore those scripts don't have this problem. -- CI: use wolfSSL 5.6.3 in builds + Closes https://github.com/curl/curl/pull/11721 - No using master anymore +Daniel Stenberg (28 Aug 2023) - Closes #11424 +- altsvc: accept and parse IPv6 addresses in response headers -SaltyMilk (11 Jul 2023) + Store numerical IPv6 addresses in the alt-svc file with the brackets + present. -- fopen: optimize + Verify with test 437 and 438 - Closes #11419 + Fixes #11737 + Reported-by: oliverpool on github + Closes #11743 -Daniel Stenberg (11 Jul 2023) +- libtest: use curl_free() to free libcurl allocated data -- cmake: make use of snprintf + In several test programs. These mistakes are not detected or a problem + as long as memdebug.h is included, as that provides the debug wrappers + for all memory functions in the same style libcurl internals do it, + which makes curl_free and free effectively the same call. - Follow-up to 935b1bd4544a23a91d68 + Reported-by: Nicholas Nethercote + Closes #11746 - Closes #11423 +Jay Satiro (28 Aug 2023) -Stefan Eissing (11 Jul 2023) +- disable.d: explain --disable not implemented prior to 7.50.0 -- macOS: fix taget detection + Option -q/--disable was added in 5.0 but only -q was actually + implemented. Later --disable was implemented in e200034 (precedes + 7.49.0), but incorrectly, and fixed in 6dbc23c (precedes 7.50.0). - - TARGET_OS_OSX is not always defined on macOS - - this leads to missing symbol Curl_macos_init() - - TargetConditionals.h seems to define these only when - dynamic targets are enabled (somewhere?) - - this PR fixes that on my macOS 13.4.1 - - I have no clue why CI builds worked without it + Reported-by: pszlazak@users.noreply.github.com - Follow-up to c7308592fb8ba213fc2c1 - Closes #11417 + Fixes https://github.com/curl/curl/issues/11710 + Closes #11712 -Stan Hu (9 Jul 2023) +Nicholas Nethercote (28 Aug 2023) -- hostip.c: Move macOS-specific calls into global init call +- hyper: fix ownership problems - https://github.com/curl/curl/pull/7121 introduced a macOS system call - to `SCDynamicStoreCopyProxies`, which is invoked every time an IP - address needs to be resolved. + Some of these changes come from comparing `Curl_http` and + `start_CONNECT`, which are similar, and adding things to them that are + present in one and missing in another. - However, this system call is not thread-safe, and macOS will kill the - process if the system call is run first in a fork. To make it possible - for the parent process to call this once and prevent the crash, only - invoke this system call in the global initialization routine. + The most important changes: + - In `start_CONNECT`, add a missing `hyper_clientconn_free` call on the + happy path. + - In `start_CONNECT`, add a missing `hyper_request_free` on the error + path. + - In `bodysend`, add a missing `hyper_body_free` on an early-exit path. + - In `bodysend`, remove an unnecessary `hyper_body_free` on a different + error path that would cause a double-free. + https://docs.rs/hyper/latest/hyper/ffi/fn.hyper_request_set_body.html + says of `hyper_request_set_body`: "This takes ownership of the + hyper_body *, you must not use it or free it after setting it on the + request." This is true even if `hyper_request_set_body` returns an + error; I confirmed this by looking at the hyper source code. - In addition, this change is beneficial because it: + Other changes are minor but make things slightly nicer. - 1. Avoids extra macOS system calls for every IP lookup. - 2. Consolidates macOS-specific initialization in a separate file. + Closes #11745 - Fixes #11252 - Closes #11254 +Daniel Stenberg (28 Aug 2023) -Daniel Stenberg (9 Jul 2023) +- multi.h: the 'revents' field of curl_waitfd is supported -- docs: use a space after RFC when spelling out RFC numbers + Since 6d30f8ebed34e7276 - Closes #11382 + Reported-by: Nicolás Ojeda Bär + Ref: #11748 + Closes #11749 -Margu (9 Jul 2023) +Gerome Fournier (27 Aug 2023) -- imap-append.c: update to make it more likely to work +- tool_paramhlp: improve str2num(): avoid unnecessary call to strlen() - Fixes #10300 - Closes #11397 + Closes #11742 -Emanuele Torre (9 Jul 2023) +Daniel Stenberg (27 Aug 2023) -- tool_writeout_json: fix encoding of control characters +- docs: mention critical files in same directories as curl saves - Control characters without a special escape sequence e.g. %00 or %06 - were being encoded as "u0006" instead of "\u0006". + ... cannot be fully protected. Don't do it. - Ref: https://github.com/curl/trurl/pull/214#discussion_r1257487858 - Closes #11414 + Co-authored-by: Jay Satiro + Reported-by: Harry Sintonen + Fixes #11530 + Closes #11701 -Stefan Eissing (9 Jul 2023) +John Hawthorn (26 Aug 2023) -- http3/ngtcp2: upload EAGAIN handling +- OpenSSL: clear error queue after SSL_shutdown - - refs #11389 where IDLE timeouts on upload are reported - - reword ngtcp2 expiry handling to apply to both send+recv - calls into the filter - - EAGAIN uploads similar to the recent changes in HTTP/2, e.g. - report success only when send data was ACKed. - - HOLD sending of EAGAINed uploads to avoid cpu busy loops - - rename internal function for consistency with HTTP/2 - implementation + We've seen errors left in the OpenSSL error queue (specifically, + "shutdown while in init") by adding some logging it revealed that the + source was this file. - Fixes #11389 - Closes #11390 + Since we call SSL_read and SSL_shutdown here, but don't check the return + code for an error, we should clear the OpenSSL error queue in case one + was raised. -Brian Nixon (9 Jul 2023) + This didn't affect curl because we call ERR_clear_error before every + write operation (a0dd9df9ab35528eb9eb669e741a5df4b1fb833c), but when + libcurl is used in a process with other OpenSSL users, they may detect + an OpenSSL error pushed by libcurl's SSL_shutdown as if it was their + own. -- tool_easysrc.h: correct `easysrc_perform` for `CURL_DISABLE_LIBCURL_OPTION` + Co-authored-by: Satana de Sant'Ana - Closes #11398 + Closes #11736 -Daniel Stenberg (9 Jul 2023) +Alexander Kanavin (25 Aug 2023) -- RELEASE-NOTES: synced +- tests: update cookie expiry dates to far in the future -- transfer: clear credentials when redirecting to absolute URL + This allows testing Y2038 with system time set to after that, so that + actual Y2038 issues can be exposed, and not masked by expiry errors. - Make sure the user and password for the second request is taken from the - redirected-to URL. + Fixes #11576 + Closes #11610 - Add test case 899 to verify. +John Bampton (25 Aug 2023) - Reported-by: James Lucas - Fixes #11410 - Closes #11412 +- misc: fix spelling -Stefan Eissing (8 Jul 2023) + Closes #11733 -- hyper: fix EOF handling on input +Daniel Stenberg (25 Aug 2023) - We ran out of disc space due to an infinite loop with debug logging +- cmdline-opts/page-header: clarify stronger that !opt == URL - Fixes #11377 - Closes #11385 - Reported-by: Dan Fandrich + Everything provided on the command line that is not an option (or an + argument to an option) is treated as a URL. -- http2: raise header limitations above and beyond + Closes #11734 - - not quite to infinity - - rewrote the implementation of our internal HTTP/1.x request - parsing to work with very large lines using dynbufs. - - new default limit is `DYN_HTTP_REQUEST`, aka 1MB, which - is also the limit of curl's general HTTP request processing. +- tests/runner: fix %else handling - Fixes #11405 - Closes #11407 + Getting the show state proper for %else and %endif did not properly work + in nested cases. -Juan Cruz Viotti (8 Jul 2023) + Follow-up to 3d089c41ea9 -- curl_easy_nextheader.3: add missing open parenthesis examples + Closes #11731 - Closes #11409 - Signed-off-by: Juan Cruz Viotti +Nicholas Nethercote (25 Aug 2023) -Dan Fandrich (7 Jul 2023) +- docs: Remove mention of #10803 from `KNOWN_BUGS`. -- CI: enable verbose test output on pytest + Because the leaks have been fixed. - This shows individual pass/fail status on tests and makes this output - consistent with other jobs' pytest invocations. +- c-hyper: fix another memory leak in `Curl_http`. -Stefan Eissing (28 Jun 2023) + There is a `hyper_clientconn_free` call on the happy path, but not one + on the error path. This commit adds one. -- http2: fix crash in handling stream weights + Fixes the second memory leak reported by Valgrind in #10803. - - Delay the priority handling until the stream has been opened. + Fixes #10803 + Closes #11729 - - Add test2404 to reproduce and verify. +- c-hyper: fix a memory leak in `Curl_http`. - Weights may change "on the run", which is why there are checks in - general egress handling. These must not trigger when the stream has not - been opened yet. + A request created with `hyper_request_new` must be consumed by either + `hyper_clientconn_send` or `hyper_request_free`. - Reported-by: jbgoog@users.noreply.github.com + This is not terrifically clear from the hyper docs -- + `hyper_request_free` is documented only with "Free an HTTP request if + not going to send it on a client" -- but a perusal of the hyper code + confirms it. - Fixes https://github.com/curl/curl/issues/11379 - Closes https://github.com/curl/curl/pull/11384 + This commit adds a `hyper_request_free` to the `error:` path in + `Curl_http` so that the request is consumed when an error occurs after + the request is created but before it is sent. -- tests/http: Add mod_h2 directive `H2ProxyRequests` + Fixes the first memory leak reported by Valgrind in #10803. - master of mod_h2 now requires H2ProxyRequests directives for forward - proxying with HTTP/2 to work. + Closes #11729 - Ref: https://github.com/icing/mod_h2/commit/3897a7086 +Daniel Stenberg (25 Aug 2023) - Closes https://github.com/curl/curl/pull/11392 +- RELEASE-NOTES: synced -Dan Fandrich (28 Jun 2023) +John Bampton (25 Aug 2023) -- CI: make Appveyor job names unique +- misc: spellfixes - Two otherwise identical mingw-w64 jobs now have their differing compiler - versions mentioned in their names. + Closes #11730 -Sheshadri.V (25 Jun 2023) +Daniel Stenberg (25 Aug 2023) -- curl.h: include for vxworks +- tests: add support for nested %if conditions - Closes #11356 + Provides more flexiblity to test cases. -Dan Fandrich (24 Jun 2023) + Also warn and bail out if there is an '%else' or %endif' without a + preceeding '%if'. -- CI: enable parallel make in more builds + Ref: #11610 + Closes #11728 - Most CI services provide at least two cores, so enable parallel make - jobs to take advantage of that for builds. Some dependencies aren't safe - to build in parallel so leave those as-is. Also, rename a few - workflows to eliminate duplicate names and provide a better idea what - they're about. +- time-cond.d: mention what happens on a missing file -- CI: don't install impacket if tests are not run + Closes #11727 - It just wastes time and bandwidth and isn't even used. +Christian Hesse (24 Aug 2023) -divinity76 (24 Jun 2023) +- docs/cmdline-opts: match the current output -- configure: the --without forms of the options are also gone + The release date has been added in output, reflect that in documentation. - --without-darwin-ssl and --without-metalink + Closes #11723 - Closes #11378 +Daniel Stenberg (24 Aug 2023) -Daniel Stenberg (23 Jun 2023) +- lib: minor comment corrections -- configure: add check for ldap_init_fd +- docs: rewrite to present tense - ... as otherwise the configure script will say it is OpenLDAP in the - summary, but not set the USE_OPENLDAP define, therefor not using the - intended OpenLDAP code paths. + ... instead of using future tense. - Regression since 4d7385446 (7.85.0) - Fixes #11372 - Closes #11374 - Reported-by: vlkl-sap on github + + numerous cleanups and improvements + + stick to "reuse" not "re-use" + + fewer contractions -Michał Petryka (23 Jun 2023) + Closes #11713 -- cmake: stop CMake from quietly ignoring missing Brotli +- urlapi: setting a blank URL ("") is not an ok URL - The CMake project was set to `QUIET` for Brotli instead of - `REQUIRED`. This makes builds unexpectedly ignore missing Brotli even - when `CURL_BROTLI` is enabled. + Test it in 1560 + Fixes #11714 + Reported-by: ad0p on github + Closes #11715 - Closes #11376 +- spelling: use 'reuse' not 're-use' in code and elsewhere -Emanuele Torre (22 Jun 2023) + Unify the spelling as both versions were previously used intermittently -- docs: add more .IP after .RE to fix indentation of generate paragraphs + Closes #11717 - follow-up from 099f41e097c030077b8ec078f2c2d4038d31353b +Michael Osipov (23 Aug 2023) - I just thought of checking all the other files with .RE, and I found 6 - other files that were missing .IP at the end. +- system.h: add CURL_OFF_T definitions on HP-UX with HP aCC - Closes #11375 + HP-UX on IA64 provides two modes: 32 and 64 bit while 32 bit being the + default one. Use "long long" in 32 bit mode and just "long" in 64 bit + mode. -Stefan Eissing (22 Jun 2023) + Closes #11718 -- http2: h2 and h2-PROXY connection alive check fixes +Dan Fandrich (22 Aug 2023) - - fix HTTP/2 check to not declare a connection dead when - the read attempt results in EAGAIN - - add H2-PROXY alive check as for HTTP/2 that was missing - and is needed - - add attach/detach around Curl_conn_is_alive() and remove - these in filter methods - - add checks for number of connections used in some test_10 - proxy tunneling tests +- tests: don't call HTTP errors OK in test cases - Closes #11368 + Some HTTP errors codes were accompanied by the text OK, which causes + some cognitive dissonance when reading them. -- http2: error stream resets with code CURLE_HTTP2_STREAM +- http: close the connection after a late 417 is received - - refs #11357, where it was reported that HTTP/1.1 downgrades - no longer works - - fixed with suggested change - - added test_05_03 and a new handler in the curltest module - to reproduce that downgrades work + In this situation, only part of the data has been sent before aborting + so the connection is no longer usable. - Fixes #11357 - Closes #11362 - Reported-by: Jay Satiro + Assisted-by: Jay Satiro + Fixes #11678 + Closes #11679 -Daniel Stenberg (22 Jun 2023) +- runtests: slightly increase the longest log file displayed -- connect-timeout.d: mention that the DNS lookup is included + The new limit provides enough space for a 64 KiB data block to be logged + in a trace file, plus a few lines at the start and end for context. This + happens to be the amount of data sent at a time in a PUT request. - Closes #11370 +- tests: add delay command to the HTTP server -Emanuele Torre (22 Jun 2023) + This adds a delay after client connect. -- quote.d: fix indentation of generated paragraphs +Daniel Stenberg (22 Aug 2023) - quote.d was missing a .IP at the end which caused the paragraphs - generated for See-also, Multi, and Example to not be indented correctly. +- cirrus: install everthing with pkg, avoid pip - I also remove a redundant "This option can be used multiple times.", and - replaced .IP "item" with .TP .B "item" to make more clear which lines - are part of the list of commands and which aren't. + Assisted-by: Sevan Janiyan - Closes #11371 + Closes #11711 -Paul Wise (22 Jun 2023) +- curl_url*.3: update function descriptions -- checksrc: modernise perl file open + - expand and clarify several descriptions + - avoid using future tense all over - Use regular variables and separate file open modes from filenames. + Closes #11708 - Suggested by perlcritic +- RELEASE-NOTES: synced - Copied from https://github.com/curl/trurl/commit/f2784a9240f47ee28a845 +Stefan Eissing (21 Aug 2023) - Closes #11358 +- CI/cirrus: disable python install on FreeBSD -Dan Fandrich (21 Jun 2023) + - python cryptography package does not build build FreeBSD + - install just mentions "error" + - this gets the build and the main test suite going again -- runtests: work around a perl without SIGUSR1 + Closes #11705 - At least msys2 perl v5.32.1 doesn't seem to define this signal. Since - this signal is only used for debugging, just ignore if setting it fails. +- test2600: fix flakiness on low cpu - Reported-by: Marcel Raad - Fixes #11350 - Closes #11366 + - refs #11355 where failures to to low cpu resources in CI + are reported + - vastly extend CURLOPT_CONNECTTIMEOUT_MS and max durations + to test cases + - trigger Curl_expire() in test filter to allow re-checks before + the usual 1second interval -- runtests: include missing valgrind package + Closes #11690 - use valgrind was missing which caused torture tests with valgrind - enabled to fail. +Maksim Sciepanienka (20 Aug 2023) - Reported-by: Daniel Stenberg - Fixes #11364 - Closes #11365 +- tool_urlglob: use the correct format specifier for curl_off_t in msnprintf -- runtests: use more consistent failure lines + Closes #11698 - After a test failure log a consistent log message to make it easier to - parse the log file. Also, log a consistent message with "ignored" for - failures that cause the test to be not considered at all. These should - perhaps be counted in the skipped category, but this commit does not - change that behaviour. +Daniel Stenberg (20 Aug 2023) -- runtests: consistently write the test check summary block +- test687/688: two more basic --xattr tests - The memory check character was erroneously omitted if the memory - checking file was not available for some reason, making the block of - characters an inconsistent length. + Closes #11697 -- test2600: fix the description +- cmdline-opts/docs: mentioned the negative option part - It looks like it was cut-and-pasted. + ... for --no-alpn and --no-buffer in the same style done for other --no- + options: - Closes #11354 + "Note that this is the negated option name documented." -Daniel Stenberg (21 Jun 2023) + Closes #11695 -- TODO: "Support HTTP/2 for HTTP(S) proxies" *done* +Emanuele Torre (19 Aug 2023) -humbleacolyte (21 Jun 2023) +- tool/var: also error when expansion result starts with NUL -- cf-socket: move ctx declaration under HAVE_GETPEERNAME + Expansions whose output starts with NUL were being expanded to the empty + string, and not being recognised as values that contain a NUL byte, and + should error. - Closes #11352 + Closes #11694 -Daniel Stenberg (20 Jun 2023) +Daniel Stenberg (19 Aug 2023) -- RELEASE-NOTES: synced +- tests: add 'large-time' as a testable feature -- example/connect-to: show CURLOPT_CONNECT_TO + This allows test cases to require this feature to run and to be used in + %if conditions. - Closes #11340 + Large here means larger than 32 bits. Ie does not suffer from y2038. -Stefan Eissing (20 Jun 2023) + Closes #11696 -- hyper: unslow +- tests/Makefile: add check-translatable-options.pl to tarball - - refs #11203 where hyper was reported as being slow - - fixes hyper_executor_poll to loop until it is out of - tasks as advised by @seanmonstar in https://github.com/hyperium/hyper/issue - s/3237 - - added a fix in hyper io handling for detecting EAGAIN - - added some debug logs to see IO results - - pytest http/1.1 test cases pass - - pytest h2 test cases fail on connection reuse. HTTP/2 - connection reuse does not seem to work. Hyper submits - a request on a reused connection, curl's IO works and - thereafter hyper declares `Hyper: [1] operation was canceled: connection cl - osed` - on stderr without any error being logged before. + Used in test 1544 - Fixes #11203 - Reported-by: Gisle Vanem - Advised-by: Sean McArthur - Closes #11344 + Follow-up to ae806395abc8c -- HTTP/2: upload handling fixes +- gen.pl: fix a long version generation mistake - - fixes #11242 where 100% CPU on uploads was reported - - fixes possible stalls on last part of a request body when - that information could not be fully send on the connection - due to an EAGAIN - - applies the same EGAIN handling to HTTP/2 proxying + Too excessive escaping made the parsing not find the correct long names + later and instead add "wrong" links. - Reported-by: Sergey Alirzaev - Fixed #11242 - Closes #11342 + Follow-up to 439ff2052e219 -Daniel Stenberg (20 Jun 2023) + Reported-by: Lukas Tribus + Fixes #11688 + Closes #11689 -- example/opensslthreadlock: remove +- lib: move mimepost data from ->req.p.http to ->state - This shows how to setup OpenSSL mutex callbacks, but this is not - necessary since OpenSSL 1.1.0 - meaning that no currently supported - OpenSSL version requires this anymore + When the legacy CURLOPT_HTTPPOST option is used, it gets converted into + the modem mimpost struct at first use. This data is (now) kept for the + entire transfer and not only per single HTTP request. This re-enables + rewind in the beginning of the second request instead of in end of the + first, as brought by 1b39731. - Closes #11341 + The request struct is per-request data only. -Dan Fandrich (19 Jun 2023) + Extend test 650 to verify. -- libtest: display the times after a test timeout error + Fixes #11680 + Reported-by: yushicheng7788 on github + Closes #11682 - This is to help with test failure debugging. +Patrick Monnerat (17 Aug 2023) - Ref: #11328 - Closes #11329 +- os400: do not check translatable options at build time -- test2600: bump a test timeout + Now that there is a test for this, the build time check is not needed + anymore. - Case 1 failed at least once on GHA by going 30 msec too long. + Closes #11650 - Ref: #11328 +- test1554: check translatable string options in OS400 wrapper -- runtests: better detect and handle pipe errors in the controller + This test runs a perl script that checks all string options are properly + translated by the OS400 character code conversion wrapper. It also + verifies these options are listed in alphanumeric order in the wrapper + switch statement. - Errors reading and writing to the pipes are now better detected and - propagated up to the main test loop so it can be cleanly shut down. Such - errors are usually due to a runner dying so it doesn't make much sense - to try to continue the test run. + Closes #11650 -- runtests: cleanly abort the runner if the controller dies +Daniel Stenberg (17 Aug 2023) - If the controller dies unexpectedly, have the runner stop its servers - and exit cleanly. Otherwise, the orphaned servers will stay running in - the background. +- unit3200: skip testing if function is not present -- runtests: improve error logging + Fake a successful run since we have no easy mechanism to skip this test + for this advanced condition. - Give more information about test harness error conditions to help figure - out what might be wrong. Print some internal test state when SIGUSR1 is - sent to runtests.pl. +- unit2600: fix build warning if built without verbose messages - Ref: #11328 +- test1608: make it build and get skipped without shuffle DNS support -- runtests: better handle ^C during slow tests +- lib: --disable-bindlocal builds curl without local binding support - Since the SIGINT handler now just sets a flag that must be checked in the - main controller loop, make sure that runs periodically. Rather than - blocking on a response from a test runner near the end of the test run, - add a short timeout to allow it. +- test1304: build and skip without netrc support -- runtests: rename server command file +- lib: build fixups when built with most things disabled - The name ftpserver.cmd was historical and has been used for more than - ftp for many years now. Rename it to plain server.cmd to reduce - confusion. + Closes #11687 -- tests: improve reliability of TFTP tests +- workflows/macos.yml: disable zstd and alt-svc in the http-only build - Stop checking the timeout used by the client under test (for most - tests). The timeout will change if the TFTP test server is slow (such as - happens on an overprovisioned CI server) because the client will retry - and reduce its timeout, and the actual value is not important for most - tests. + Closes #11683 - test285 is changed a different way, by increasing the connect timeout. - This improves test coverage by allowing the changed timeout value to be - checked, but improves reliability with a carefully-chosen timeout that - not only allows twice the time to respond as before, but also allows - several retries before the client will change its timeout value. +Stefan Eissing (17 Aug 2023) - Ref: #11328 +- bearssl: handshake fix, provide proper get_select_socks() implementation -Daniel Stenberg (19 Jun 2023) + - bring bearssl handshake times down from +200ms down to other TLS backends + - vtls: improve generic get_select_socks() implementation + - tests: provide Apache with a suitable ssl session cache -- cf-socket: skip getpeername()/getsockname for TFTP + Closes #11675 - Since the socket is not connected then the call fails. When the call - fails, failf() is called to write an error message that is then - surviving and is returned when the *real* error occurs later. The - earlier, incorrect, error therefore hides the actual error message. +- tests: TLS session sharing test - This could be seen in stderr for test 1007 + - test TLS session sharing with special test client + - expect failure with wolfSSL + - disable flaky wolfSSL test_02_07b - Test 1007 has now been extended to verify the stderr message. + Closes #11675 - Closes #11332 +Daniel Stenberg (17 Aug 2023) -- example/crawler: make it use a few more options +- CURLOPT_*TIMEOUT*: extend and clarify - For show, but reasonable + Closes #11686 -- libcurl-ws.3: mention raw mode +- urlapi: return CURLUE_BAD_HOSTNAME if puny2idn encoding fails - Closes #11339 + And document it. Only return out of memory when it actually is a memory + problem. -- example/default-scheme: set the default scheme for schemeless URLs + Pointed-out-by: Jacob Mealey + Closes #11674 - Closes #11338 +Mathew Benson (17 Aug 2023) -- example/hsts-preload: show one way to HSTS preload +- cmake: add GnuTLS option - Closes #11337 + - Option to use GNUTLS was missing. Hence was not able to use GNUTLS + with ngtcp2 for http3. -- examples/http-options: show how to send "OPTIONS *" + Closes #11685 - With CURLOPT_REQUEST_TARGET. +Daniel Stenberg (16 Aug 2023) - Also add use of CURLOPT_QUICK_EXIT to show. +- RELEASE-NOTES: synced - Closes #11333 +- http: remove the p_pragma struct field -- examples: make use of CURLOPT_(REDIR_|)PROTOCOLS_STR + unused since 40e8b4e52 (2008) - To show how to use them + Closes #11681 - Closes #11334 +Jay Satiro (16 Aug 2023) -- examples/smtp-mime: use CURLOPT_MAIL_RCPT_ALLOWFAILS +- CURLINFO_CERTINFO.3: better explain curl_certinfo struct - For show + Closes https://github.com/curl/curl/pull/11666 - Closes #11335 +- CURLINFO_TLS_SSL_PTR.3: clarify a recommendation -- http: rectify the outgoing Cookie: header field size check + - Remove the out-of-date SSL backend list supported by + CURLOPT_SSL_CTX_FUNCTION. - Previously it would count the size of the entire outgoing request and - not just the size of only the Cookie: header field - which was the - intention. + It makes more sense to just refer to that document instead of having + a separate list that has to be kept in sync. - This could make the check be off by several hundred bytes in some cases. + Closes https://github.com/curl/curl/pull/11665 - Closes #11331 +- write-out.d: clarify %{time_starttransfer} -Jay Satiro (17 Jun 2023) + sync it up with CURLINFO_STARTTRANSFER_TIME_T -- lib: fix some format specifiers +Daniel Stenberg (15 Aug 2023) - - Use CURL_FORMAT_CURL_OFF_T where %zd was erroneously used for some - curl_off_t variables. +- transfer: don't set TIMER_STARTTRANSFER on first send - - Use %zu where %zd was erroneously used for some size_t variables. + The time stamp is for measuring the first *received* byte - Prior to this change some of the Windows CI tests were failing because - in Windows 32-bit targets have a 32-bit size_t and a 64-bit curl_off_t. - When %zd was used for some curl_off_t variables then only the lower - 32-bits was read and the upper 32-bits would be read for part or all of - the next specifier. + Fixes #11669 + Reported-by: JazJas on github + Closes #11670 - Fixes https://github.com/curl/curl/issues/11327 - Closes https://github.com/curl/curl/pull/11321 +trrui-huawei (15 Aug 2023) -Marcel Raad (16 Jun 2023) +- quiche: enable quiche to handle timeout events -- test427: add `cookies` feature and keyword + In parallel with ngtcp2, quiche also offers the `quiche_conn_on_timeout` + interface for the application to invoke upon timer + expiration. Therefore, invoking the `on_timeout` function of the + Connection is crucial to ensure seamless functionality of quiche with + timeout events. - This test doesn't work with `--disable-cookies`. + Closes #11654 - Closes https://github.com/curl/curl/pull/11320 +- quiche: adjust quiche `QUIC_IDLE_TIMEOUT` to 60s -Chris Talbot (15 Jun 2023) + Set the `QUIC_IDLE_TIMEOUT` parameter to match ngtcp2 for consistency. -- imap: Provide method to disable SASL if it is advertised +Daniel Stenberg (15 Aug 2023) - - Implement AUTH=+LOGIN for CURLOPT_LOGIN_OPTIONS to prefer plaintext - LOGIN over SASL auth. +- KNOWN_BUGS: LDAPS requests to ActiveDirectory server hang - Prior to this change there was no method to be able to fall back to - LOGIN if an IMAP server advertises SASL capabilities. However, this may - be desirable for e.g. a misconfigured server. + Closes #9580 - Per: https://www.ietf.org/rfc/rfc5092.html#section-3.2 +- imap: add a check for failing strdup() - ";AUTH=" looks to be the correct way to specify what - authenication method to use, regardless of SASL or not. +- imap: remove the only sscanf() call in the IMAP code - Closes https://github.com/curl/curl/pull/10041 + Avoids the use of a stack buffer. -Daniel Stenberg (15 Jun 2023) + Closes #11673 -- RELEASE-NOTES: synced +- imap: use a dynbuf in imap_atom -- examples/multi-debugcallback.c: avoid the bool typedef + Avoid a calculation + malloc. Build the output in a dynbuf. - Apparently this cannot be done in c23 + Closes #11672 - Reported-by: Cristian Rodríguez - Fixes #11299 - Closes #11319 +Marin Hannache (14 Aug 2023) -- docs/libcurl/libcurl.3: cleanups and improvements +- http: do not require a user name when using CURLAUTH_NEGOTIATE - Closes #11317 + In order to get Negotiate (SPNEGO) authentication to work in HTTP you + used to be required to provide a (fake) user name (this concerned both + curl and the lib) because the code wrongly only considered + authentication if there was a user name provided, as in: -- libcurl-ws.3: fix typo + curl -u : --negotiate https://example.com/ -- curl_ws_*.3: enhance + This commit leverages the `struct auth` want member to figure out if the + user enabled CURLAUTH_NEGOTIATE, effectively removing the requirement of + setting a user name both in curl and the lib. - - all: SEE ALSO the libcurl-ws man page - - send: add example and return value information - - meta: mention that the returned data is read-only + Signed-off-by: Marin Hannache + Reported-by: Enrico Scholz + Fixes https://sourceforge.net/p/curl/bugs/440/ + Fixes #1161 + Closes #9047 - Closes #11318 +Viktor Szakats (13 Aug 2023) -- docs/libcurl/libcurl-ws.3: see also CURLOPT_WS_OPTIONS +- build: streamline non-UWP wincrypt detections -- docs/libcurl/libcurl-ws.3: minor polish + - with CMake, use the variable `WINDOWS_STORE` to detect an UWP build + and disable our non-UWP-compatible use the Windows crypto API. This + allows to drop two dynamic feature checks. -- libcurl-ws.3. WebSocket API overview + `WINDOWS_STORE` is true when invoking CMake with + `CMAKE_SYSTEM_NAME` == `WindowsStore`. Introduced in CMake v3.1. - Closes #11314 + Ref: https://cmake.org/cmake/help/latest/variable/WINDOWS_STORE.html -- libcurl-url.3: also mention CURLUPART_ZONEID + - with autotools, drop the separate feature check for `wincrypt.h`. On + one hand this header has been present for long (even Borland C 5.5 had + it from year 2000), on the other we used the check result solely to + enable another check for certain crypto functions. This fails anyway + with the header not present. We save one dynamic feature check at the + configure stage. - ... and sort the two part-using lists alphabetically + Reviewed-by: Marcel Raad + Closes #11657 -Marcel Raad (14 Jun 2023) +Nicholas Nethercote (13 Aug 2023) -- fopen: fix conversion warning on 32-bit Android +- docs/HYPER.md: update hyper build instructions - When building for 32-bit ARM or x86 Android, `st_mode` is defined as - `unsigned int` instead of `mode_t`, resulting in a - -Wimplicit-int-conversion clang warning because `mode_t` is - `unsigned short`. Add a cast to silence the warning. + Nightly Rust and `-Z unstable-options` are not needed. - Ref: https://android.googlesource.com/platform/bionic/+/refs/tags/ndk-r25c/li - bc/include/sys/stat.h#86 - Closes https://github.com/curl/curl/pull/11313 + The instructions here now match the hyper docs exactly: + https://github.com/hyperium/hyper/commit/bd7928f3dd6a8461f0f0fdf7ee0fd95c2f15 + 6f88 -- http2: fix variable type + Closes #11662 - `max_recv_speed` is `curl_off_t`, so using `size_t` might result in - -Wconversion GCC warnings for 32-bit `size_t`. Visible in the NetBSD - ARM autobuilds. +Daniel Stenberg (13 Aug 2023) - Closes https://github.com/curl/curl/pull/11312 +- RELEASE-NOTES: synced -Daniel Stenberg (13 Jun 2023) +- urlapi: CURLU_PUNY2IDN - convert from punycode to IDN name -- vtls: fix potentially uninitialized local variable warnings + Asssisted-by: Jay Satiro + Closes #11655 - Follow-up from a4a5e438ae533c +- spellcheck: adapt to backslashed minuses - Closes #11310 + As the curl.1 has more backslashed minus, the cleanup sed lines xneed to + adapt. -- timeval: use CLOCK_MONOTONIC_RAW if available + Adjusted some docs slighly. - Reported-by: Harry Sintonen - Ref: #11288 - Closes #11291 + Follow-up to 439ff2052e -Stefan Eissing (12 Jun 2023) + Closes #11663 -- tool: add curl command line option `--trace-ids` +- gen: escape more minus - - added and documented --trace-ids to prepend (after the timestamp) - the transfer and connection identifiers to each verbose log line - - format is [n-m] with `n` being the transfer id and `m` being the - connection id. In case there is not valid connection id, print 'x'. - - Log calls with a handle that has no transfer id yet, are written - without any ids. + Detected since it was still hard to search for option names using dashes + in the middle in the man page. - Closes #11185 + Closes #11660 -- lib: add CURLINFO_CONN_ID and CURLINFO_XFER_ID +- cookie-jar.d: enphasize that this option is ONLY writing cookies - - add an `id` long to Curl_easy, -1 on init - - once added to a multi (or its own multi), it gets - a non-negative number assigned by the connection cache - - `id` is unique among all transfers using the same - cache until reaching LONG_MAX where it will wrap - around. So, not unique eternally. - - CURLINFO_CONN_ID returns the connection id attached to - data or, if none present, data->state.lastconnect_id - - variables and type declared in tool for write out + Reported-by: Dan Jacobson + Tweaked-by: Jay Satiro + Ref: #11642 + Closes #11661 - Closes #11185 +Nicholas Nethercote (11 Aug 2023) -Daniel Stenberg (12 Jun 2023) +- docs/HYPER.md: document a workaround for a link error -- CURLOPT_INFILESIZE.3: mention -1 triggers chunked + Closes #11653 - Ref: #11300 - Closes #11304 +Jay Satiro (11 Aug 2023) -Philip Heiduck (12 Jun 2023) +- schannel: verify hostname independent of verify cert -- CI: openssl-3.0.9+quic + Prior to this change when CURLOPT_SSL_VERIFYPEER (verifypeer) was off + and CURLOPT_SSL_VERIFYHOST (verifyhost) was on we did not verify the + hostname in schannel code. - Closes #11296 + This fixes KNOWN_BUG 2.8 "Schannel disable CURLOPT_SSL_VERIFYPEER and + verify hostname". We discussed a fix several years ago in #3285 but it + went stale. -Karthikdasari0423 (12 Jun 2023) + Assisted-by: Daniel Stenberg -- HTTP3.md: update openssl version + Bug: https://curl.haxx.se/mail/lib-2018-10/0113.html + Reported-by: Martin Galvan - Closes #11297 + Ref: https://github.com/curl/curl/pull/3285 -Daniel Stenberg (12 Jun 2023) + Fixes https://github.com/curl/curl/issues/3284 + Closes https://github.com/curl/curl/pull/10056 -- vtls: avoid memory leak if sha256 call fails +Daniel Stenberg (11 Aug 2023) - ... in the pinned public key handling function. +- curl_quiche: remove superfluous NULL check - Reported-by: lizhuang0630 on github - Fixes #11306 - Closes #11307 + 'stream' is always non-NULL at this point -- examples/ipv6: disable on win32 + Pointed out by Coverity - I can't make if_nametoindex() work there + Closes #11656 - Follow-up to c23dc42f3997acf23 +- curl/urlapi.h: tiny typo - Closes #11305 +- github/labeler: make HYPER.md set Hyper and not TLS -- tool_operate: allow cookie lines up to 8200 bytes +- docs/cmdline-opts/gen.pl: hide "added in" before 7.50.0 - Since this option might set multiple cookies in the same line, it does - not make total sense to cap this at 4096 bytes, which is the limit for a - single cookie name or value. + 7.50.0 shipped on Jul 21 2016, over seven years ago. We no longer need + to specify version changes for earlier releases in the generated output. - Closes #11303 + This ups the limit from the previous 7.30.0 (Apr 12 2013) -- test427: verify sending more cookies than fit in a 8190 bytes line + This hides roughly 35 "added in" mentions. - curl will then only populate the header with cookies that fit, dropping - ones that otherwise would have been sent + Closes #11651 - Ref: https://curl.se/mail/lib-2023-06/0020.html +Jay Satiro (10 Aug 2023) - Closes #11303 +- bug_report: require reporters to specify curl and os versions -- testutil: allow multiple %-operators on the same line + - Change curl version and os sections from single-line input to + multi-line textarea. - Closes #11303 + - Require curl version and os sections to be filled out before report + can be submitted. -Oleg Jukovec (12 Jun 2023) + Closes https://github.com/curl/curl/pull/11636 -- docs: update CURLOPT_UPLOAD.3 +Daniel Stenberg (9 Aug 2023) - The behavior of CURLOPT_UPLOAD differs from what is described in the - documentation. The option automatically adds the 'Transfer-Encoding: - chunked' header if the upload size is unknown. +- gen.pl: replace all single quotes with aq - Closes #11300 + - this prevents man from using a unicode sequence for them + - which then allows search to work properly -Daniel Stenberg (12 Jun 2023) + Closes #11645 -- RELEASE-NOTES: synced +Viktor Szakats (9 Aug 2023) -- CURLOPT_AWS_SIGV4.3: remove unused variable from example +- cmake: fix to use variable for the curl namespace - Closes #11302 + Replace (wrong) literal with a variable to specify the curl + namespace. -- examples/https.c: use CURLOPT_CA_CACHE_TIMEOUT + Follow-up to 1199308dbc902c52be67fc805c72dd2582520d30 #11505 - for demonstration purposes + Reported-by: balikalina on Github + Fixes https://github.com/curl/curl/commit/1199308dbc902c52be67fc805c72dd25825 + 20d30#r123923098 + Closes #11629 - Closes #11290 +- cmake: allow `SHARE_LIB_OBJECT=ON` on all platforms -- example/ipv6: feature CURLOPT_ADDRESS_SCOPE in use + 2ebc74c36a19a1700af394c16855ce144d9878e3 #11546 introduced sharing + libcurl objects for shared and static targets. - Closes #11282 + The above automatically enabled for Windows builds, with an option to + disable with `SHARE_LIB_OBJECT=OFF`. -Karthikdasari0423 (10 Jun 2023) + This patch extend this feature to all platforms as a manual option. + You can enable it by setting `SHARE_LIB_OBJECT=ON`. Then shared objects + are built in PIC mode, meaning the static lib will also have PIC code. -- docs: Update HTTP3.md for newer ngtcp2 and nghttp3 + [EXPERIMENTAL] - Follow-up to fb9b9b58 + Closes #11627 - Ref: #11184 - Closes #11295 +- cmake: assume `wldap32` availability on Windows -Dan Fandrich (10 Jun 2023) + This system library first shipped with Windows ME, available as an extra + install for some older releases (according to [1]). The import library + was present already in old MinGW 3.4.2 (year 2007). -- docs: update the supported ngtcp2 and nghttp3 versions + Drop the feature check and its associated `HAVE_WLDAP32` variable. - Follow-up to cae9d10b + To manually disable `wldap32`, you can use the `USE_WIN32_LDAP=OFF` + CMake option, like before. - Ref: #11184 - Closes #11294 + [1]: https://dlcdn.apache.org/httpd/binaries/win32/LEGACY.html -- tests: fix error messages & handling around sockets + Reviewed-by: Jay Satiro + Closes #11624 - The wrong error code was checked on Windows on UNIX socket failures, - which could have caused all UNIX sockets to be reported as having - errored and the tests therefore skipped. Also, a useless error message - was displayed on socket errors in many test servers on Windows because - strerror() doesn't work on WinSock error codes; perror() is overridden - there to work on all errors and is used instead. +Daniel Stenberg (9 Aug 2023) - Ref #11258 - Closes #11265 +- page-header: move up a URL paragraph from GLOBBING to URL -Daniel Stenberg (9 Jun 2023) +- variable.d: output the function names table style -- CURLOPT_SSH_PRIVATE_KEYFILE.3: expand on the file search + Also correct the url function name in the header - Reported-by: atjg on github - Ref: #11287 - Closes #11289 + Closes #11641 -Stefan Eissing (9 Jun 2023) +- haproxy-clientip.d: remove backticks -- ngtcp2: use ever increasing timestamp in io + This is not markdown - - ngtcp2 v0.16.0 asserts that timestamps passed to its function - will only ever increase. - - Use a context shared between ingress/egress operations that - uses a shared timestamp, regularly updated during calls. + Follow-up to 0a75964d0d94a4 - Closes #11288 + Closes #11639 -Daniel Stenberg (9 Jun 2023) +- RELEASE-NOTES: synced -- GHA: use nghttp2 1.54.0 for the ngtcp2 jobs +- gen.pl: escape all dashes (ascii minus) to avoid unicode hyphens -Philip Heiduck (9 Jun 2023) + Reported-by: FC Stegerman + Fixes #11635 + Closes #11637 -- GHA: ngtcp2: use 0.16.0 and nghttp3 0.12.0 +- cmdline-opts/page-header: reorder, clean up -Daniel Stenberg (9 Jun 2023) + - removed some unnecessary blurb to focus + - moved up the more important URL details + - put "globbing" into its own subtitle and moved down a little + - mention the online man page in the version section -- ngtcp2: build with 0.16.0 and nghttp3 0.12.0 + Closes #11638 - - moved to qlog_write - - crypto => encryption - - CRYPTO => ENCRYPTION - - removed "_is_" - - ngtcp2_conn_shutdown_stream_read and - ngtcp2_conn_shutdown_stream_write got flag arguments - - the nghttp3_callbacks struct got a recv_settings callback +- c-hyper: adjust the hyper to curlcode conversion - Closes #11184 + Closes #11621 -- example/http2-download: set CURLOPT_BUFFERSIZE +- test2306: make it use a persistent connection - Primarily because no other example sets it, and remove the disabling of - the certificate check because we should not recommend that. + + enable verbose already from the start - Closes #11284 + Closes #11621 -- example/crawler: also set CURLOPT_AUTOREFERER +eppesuig (8 Aug 2023) - Could make sense, and it was not used in any example before. +- list-only.d: mention SFTP as supported protocol - Closes #11283 + Closes #11628 -Wyatt OʼDay (9 Jun 2023) +Daniel Stenberg (8 Aug 2023) -- tls13-ciphers.d: include Schannel +- request.d: use .TP for protocol "labels" - Closes #11271 + To render the section nicer in man page. -Daniel Stenberg (9 Jun 2023) + Closes #11630 -- curl_pushheader_byname/bynum.3: document in their own man pages +- cf-haproxy: make CURLOPT_HAPROXY_CLIENT_IP set the *source* IP - These two functions were added in 7.44.0 when CURLMOPT_PUSHFUNCTION was - introduced but always lived a life in the shadows, embedded in the - CURLMOPT_PUSHFUNCTION man page. Until now. + ... as documented. - It makes better sense and gives more visibility to document them in - their own stand-alone man pages. + Update test 3201 and 3202 accordingly. - Closes #11286 + Reported-by: Markus Sommer + Fixes #11619 + Closes #11626 -- curl_mprintf.3: minor fix of the example +- page-footer: QLOGDIR works with ngtcp2 and quiche -- curl_url_set: enforce the max string length check for all parts + It previously said "both" backends which is confusing as we currently + have three... - Update the docs and test 1559 accordingly + Closes #11631 - Closes #11273 +Stefan Eissing (8 Aug 2023) -- examples/ftpuploadresume.c: add use of CURLOPT_ACCEPTTIMEOUT_MS +- http3: quiche, handshake optimization, trace cleanup - For show + - load x509 store after clienthello + - cleanup of tracing - Closes #11277 + Closes #11618 -- examples/unixsocket.c: example using CURLOPT_UNIX_SOCKET_PATH +Daniel Stenberg (8 Aug 2023) - and alternatively CURLOPT_ABSTRACT_UNIX_SOCKET +- ngtcp2: remove dead code - Closes #11276 + 'result' is always zero (CURLE_OK) at this point -Anssi Kolehmainen (8 Jun 2023) + Detected by Coverity -- docs: fix missing parameter names in examples + Closes #11622 - Closes #11278 +Viktor Szakats (8 Aug 2023) -Daniel Stenberg (8 Jun 2023) +- openssl: auto-detect `SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED` -- urlapi: have *set(PATH) prepend a slash if one is missing + OpenSSL 1.1.1 defines this macro, but no ealier version, or any of the + popular forks (yet). Use the macro itself to detect its presence, + replacing the hard-wired fork-specific conditions. - Previously the code would just do that for the path when extracting the - full URL, which made a subsequent curl_url_get() of the path to - (unexpectedly) still return it without the leading path. + This way the feature will enable automatically when forks implement it, + while also shorter and possibly requiring less future maintenance. - Amend lib1560 to verify this. Clarify the curl_url_set() docs about it. + Follow-up to 94241a9e78397a2aaf89a213e6ada61e7de7ee02 #6721 - Bug: https://curl.se/mail/lib-2023-06/0015.html - Closes #11272 - Reported-by: Pedro Henrique + Reviewed-by: Jay Satiro + Closes #11617 -Dan Fandrich (7 Jun 2023) +- openssl: use `SSL_CTX_set_ciphersuites` with LibreSSL 3.4.1 -- runtests; give each server a unique log lock file + LibreSSL 3.4.1 (2021-10-14) added support for + `SSL_CTX_set_ciphersuites`. - Logs are written by several servers and all of them must be finished - writing before the test results can be determined. This means each - server must have its own lock file rather than sharing a single one, - which is how it was done up to now. Previously, the first server to - complete a test would clear the lock before the other server was done, - which caused flaky tests. + Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.4.1-relnotes.txt - Lock files are now all found in their own directory, so counting locks - equals counting the files in that directory. The result is that the - proxy logs are now reliably written which actually changes the expected - output for two tests. + Reviewed-by: Jay Satiro + Closes #11616 - Fixes #11231 - Closes #11259 +- openssl: use `SSL_CTX_set_keylog_callback` with LibreSSL 3.5.0 -- runtests: make test file directories in log/N + LibreSSL 3.5.0 (2022-02-24) added support for + `SSL_CTX_set_keylog_callback`. - Test files in subdirectories were not created after parallel test log - directories were moved down a level due to a now-bad comparison. + Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.5.0-relnotes.txt - Follow-up to 92d7dd39 + Reviewed-by: Jay Satiro + Closes #11615 - Ref #11264 - Closes #11267 +- cmake: drop `HAVE_LIBWINMM` and `HAVE_LIBWS2_32` feature checks -Daniel Stenberg (7 Jun 2023) + - `HAVE_LIBWINMM` was detected but unused. The `winmm` system library is + also not used by curl, but it is by its optional dependency `librtmp`. + Change the logic to always add `winmm` when `USE_LIBRTMP` is set. This + library has been available since the early days of Windows. -- ws: make the curl_ws_meta() return pointer a const + - `HAVE_LIBWS2_32` detected `ws2_32` lib on Windows. This lib is present + since Windows 95 OSR2 (AFAIR). Winsock1 already wasn't supported and + other existing logic already assumed this lib being present, so delete + the check and replace the detection variable with `WIN32` and always + add `ws2_32` on Windows. - The returned info is read-only for the user. + Closes #11612 - Closes #11261 +Daniel Gustafsson (8 Aug 2023) -- RELEASE-NOTES: synced +- crypto: ensure crypto initialization works -- runtests: move parallel log dirs from logN to log/N + Make sure that context initialization during hash setup works to avoid + going forward with the risk of a null pointer dereference. - Having several hundreds of them in there gets annoying. + Reported-by: Philippe Antoine on HackerOne + Assisted-by: Jay Satiro + Assisted-by: Daniel Stenberg - Closes #11264 + Closes #11614 -Dan Fandrich (7 Jun 2023) +Viktor Szakats (7 Aug 2023) -- test447: move the test file into %LOGDIR +- openssl: switch to modern init for LibreSSL 2.7.0+ -Viktor Szakats (7 Jun 2023) + LibreSSL 2.7.0 (2018-03-21) introduced automatic initialization, + `OPENSSL_init_ssl()` function and deprecated the old, manual init + method, as seen in OpenSSL 1.1.0. Switch to the modern method when + available. -- cmake: add support for "unity" builds + Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.7.0-relnotes.txt - Aka "jumbo" or "amalgamation" builds. It means to compile all sources - per target as a single C source. This is experimental. + Reviewed-by: Daniel Stenberg + Closes #11611 - You can enable it by passing `-DCMAKE_UNITY_BUILD=ON` to cmake. - It requires CMake 3.16 or newer. +Daniel Stenberg (7 Aug 2023) - It makes builds (much) faster, allows for better optimizations and tends - to promote less ambiguous code. +- gskit: remove - Also add a new AppVeyor CI job and convert an existing one to use - "unity" mode (one MSVC, one MinGW), and enable it for one macOS CI job. + We remove support for building curl with gskit. - Fix related issues: - - add missing include guard to `easy_lock.h`. - - rename static variables and functions (and a macro) with names reused - across sources, or shadowed by local variables. - - add an `#undef` after use. - - add a missing `#undef` before use. - - move internal definitions from `ftp.h` to `ftp.c`. - - `curl_memory.h` fixes to make it work when included repeatedly. - - stop building/linking curlx bits twice for a static-mode curl tool. - These caused doubly defined symbols in unity builds. - - silence missing extern declarations compiler warning for ` _CRT_glob`. - - fix extern declarations for `tool_freq` and `tool_isVistaOrGreater`. - - fix colliding static symbols in debug mode: `debugtime()` and - `statename`. - - rename `ssl_backend_data` structure to unique names for each - TLS-backend, along with the `ssl_connect_data` struct member - referencing them. This required adding casts for each access. - - add workaround for missing `[P]UNICODE_STRING` types in certain Windows - builds when compiling `lib/ldap.c`. To support "unity" builds, we had - to enable `SCHANNEL_USE_BLACKLISTS` for Schannel (a Windows - `schannel.h` option) _globally_. This caused an indirect inclusion of - Windows `schannel.h` from `ldap.c` via `winldap.h` to have it enabled - as well. This requires `[P]UNICODE_STRING` types, which is apperantly - not defined automatically (as seen with both MSVS and mingw-w64). - This patch includes `` to fix it. - Ref: https://github.com/curl/curl/runs/13987772013 - Ref: https://dev.azure.com/daniel0244/curl/_build/results?buildId=15827&vie - w=logs&jobId=2c9f582d-e278-56b6-4354-f38a4d851906&j=2c9f582d-e278-56b6-4354-f - 38a4d851906&t=90509b00-34fa-5a81-35d7-5ed9569d331c - - tweak unity builds to compile `lib/memdebug.c` separately in memory - trace builds to avoid PP confusion. - - force-disable unity for test programs. - - do not compile and link libcurl sources to libtests _twice_ when libcurl - is built in static mode. + - This is a niche TLS library, only running on some IBM systems + - no regular curl contributors use this backend + - no CI builds use or verify this backend + - gskit, or the curl adaption for it, lacks many modern TLS features + making it an inferior solution + - build breakages in this code take weeks or more to get detected + - fixing gskit code is mostly done "flying blind" - KNOWN ISSUES: - - running tests with unity builds may fail in cases. - - some build configurations/env may not compile in unity mode. E.g.: - https://ci.appveyor.com/project/curlorg/curl/builds/47230972/job/51wfesgnfu - auwl8q#L250 + This removal has been advertized in DEPRECATED in Jan 2, 2023 and it has + been mentioned on the curl-library mailing list. - Ref: https://github.com/libssh2/libssh2/issues/1034 - Ref: https://cmake.org/cmake/help/latest/prop_tgt/UNITY_BUILD.html - Ref: https://en.wikipedia.org/wiki/Unity_build + It could be brought back, this is not a ban. Given proper effort and + will, gskit support is welcome back into the curl TLS backend family. - Closes #11095 + Closes #11460 -Daniel Stenberg (7 Jun 2023) +- RELEASE-NOTES: synced -- examples/websocket.c: websocket example using CONNECT_ONLY +Dan Fandrich (7 Aug 2023) - Closes #11262 +- THANKS-filter: add a name typo -- websocket-cb: example doing WebSocket download using callback +Stefan Eissing (7 Aug 2023) - Very basic +- http3/ngtcp2: shorten handshake, trace cleanup - Closes #11260 + - shorten handshake timing by delayed x509 store load (OpenSSL) + as we do for HTTP/2 + - cleanup of trace output, align with HTTP/2 output -- test/.gitignore: ignore log* + Closes #11609 -Dan Fandrich (5 Jun 2023) +Daniel Stenberg (7 Aug 2023) -- runtests: document the -j parallel testing option +- headers: accept leading whitespaces on first response header - Reported-by: Daniel Stenberg - Ref: #10818 - Closes #11255 + This is a bad header fold but since the popular browsers accept this + violation, so does curl now. Unless built with hyper. -- runtests: create multiple test runners when requested + Add test 1473 to verify and adjust test 2306. - Parallel testing is enabled by using a nonzero value for the -j option - to runtests.pl. Performant values seem to be about 7*num CPU cores, or - 1.3*num CPU cores if Valgrind is in use. + Reported-by: junsik on github + Fixes #11605 + Closes #11607 - Flaky tests due to improper log locking (bug #11231) are exacerbated - while parallel testing, so it is not enabled by default yet. +- include/curl/mprintf.h: add __attribute__ for the prototypes - Fixes #10818 - Closes #11246 + - if gcc or clang is used + - if __STDC_VERSION__ >= 199901L, which means greater than C90 + - if not using mingw + - if CURL_NO_FMT_CHECKS is not defined -- runtests: handle repeating tests in multiprocess mode + Closes #11589 - Such as what happens with the --repeat option. Some functions are - changed to pass the runner ID instead of relying on the non-unique test - number. +- tests: fix bad printf format flags in test code - Ref: #10818 +- tests: fix header scan tools for attribute edits in mprintf.h -- runtests: buffer logmsg while running singletest() +- cf-socket: log successful interface bind - This allows all messages relating to a single test case to be displayed - together at the end of the test. + When the setsockopt SO_BINDTODEVICE operation succeeds, output that in + the verbose output. - Ref: #10818 + Ref: #11599 + Closes #11608 -- runtests: call initserverconfig() in the runner +- CURLOPT_SSL_VERIFYPEER.3: mention it does not load CA certs when disabled - This must be done so variables pick up the runner's unique $LOGDIR. + Ref: #11457 + Closes #11606 - Ref: #10818 +- CURLOPT_SSL_VERIFYPEER.3: add two more see also options -- runtests: use a per-runner random seed + CURLINFO_CAINFO and CURLINFO_CAPATH - Each runner needs a unique random seed to reduce the chance of port - number collisions. The new scheme uses a consistent per-runner source of - randomness which results in deterministic behaviour, as it did before. + Closes #11603 - Ref: #10818 +- KNOWN_BUGS: aws-sigv4 does not behave well with AWS VPC Lattice -- runtests: complete main test loop refactor for multiple runners + Closes #11007 - The main test loop is now able to handle multiple runners, or no - additional runner processes at all. At most one process is still - created, however. +Graham Campbell (6 Aug 2023) - Ref: #10818 +- CI: use openssl 3.0.10+quic, nghttp3 0.14.0, ngtcp2 0.18.0 -- runtests: prepare main test loop for multiple runners + Closes #11585 - Some variables are expanded to arrays and hashes so that multiple - runners can be used for running tests. +Daniel Stenberg (6 Aug 2023) - Ref: #10818 +- TODO: add *5* entries for aws-sigv4 -Stefan Eissing (5 Jun 2023) + Closes #7559 + Closes #8107 + Closes #8810 + Closes #9717 + Closes #10129 -- bufq: make write/pass methods more robust +- TODO: LDAP Certificate-Based Authentication - - related to #11242 where curl enters busy loop when - sending http2 data to the server + Closes #9641 - Closes #11247 +Stefan Eissing (6 Aug 2023) -Boris Verkhovskiy (5 Jun 2023) +- http2: cleanup trace messages -- tool_getparam: fix comment + - more compact format with bracketed stream id + - all frames traced in and out - Closes #11253 + Closes #11592 -Raito Bezarius (5 Jun 2023) +Daniel Stenberg (6 Aug 2023) -- haproxy: add --haproxy-clientip flag to spoof client IPs +- tests/tftpd+mqttd: make variables static to silence picky warnings - CURLOPT_HAPROXY_CLIENT_IP in the library + Closes #11594 - Closes #10779 +- docs/cmdline: remove repeated working for negotiate + ntlm -Daniel Stenberg (5 Jun 2023) + The extra wording is added automatically by the gen.pl tool -- curl: add --ca-native and --proxy-ca-native + Closes #11597 - These are two boolean options to ask curl to use the native OS's CA - store when verifying TLS servers. For peers and for proxies - respectively. +- docs/cmdline: add small "warning" to verbose options - They currently only have an effect for curl on Windows when built to use - OpenSSL for TLS. + "Note that verbose output of curl activities and network traffic might + contain sensitive data, including user names, credentials or secret data + content. Be aware and be careful when sharing trace logs with others." - Closes #11049 + Closes #11596 -Viktor Szakats (5 Jun 2023) +- RELEASE-NOTES: synced -- build: drop unused/redundant `HAVE_WINLDAP_H` +- pingpong: don't use *bump_headersize - Sources did not use it. Autotools used it when checking for the - `winldap` library, which is redundant. + We use that for HTTP(S) only. - With CMake, detection was broken: - ``` - Run Build Command(s):/usr/local/Cellar/cmake/3.26.3/bin/cmake -E env VERBOSE= - 1 /usr/bin/make -f Makefile cmTC_2d8fe/fast && /Library/Developer/CommandLine - Tools/usr/bin/make -f CMakeFiles/cmTC_2d8fe.dir/build.make CMakeFiles/cmTC_2 - d8fe.dir/build - Building C object CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj - /usr/local/opt/llvm/bin/clang --target=x86_64-w64-mingw32 --sysroot=/usr/loca - l/opt/mingw-w64/toolchain-x86_64 -D_WINSOCKAPI_="" -I/my/quictls/x64-ucrt/usr - /include -I/my/zlib/x64-ucrt/usr/include -I/my/brotli/x64-ucrt/usr/include -W - no-unused-command-line-argument -D_UCRT -DCURL_HIDDEN_SYMBOLS -DHAVE_SSL_SE - T0_WBIO -DHAS_ALPN -DNGHTTP2_STATICLIB -DNGHTTP3_STATICLIB -DNGTCP2_STATICLIB - -DUSE_MANUAL=1 -fuse-ld=lld -Wl,-s -static-libgcc -lucrt -Wextra -Wall -p - edantic -Wbad-function-cast -Wconversion -Winline -Wmissing-declarations -Wmi - ssing-prototypes -Wnested-externs -Wno-long-long -Wno-multichar -Wpointer-ari - th -Wshadow -Wsign-compare -Wundef -Wunused -Wwrite-strings -Wcast-align -Wde - claration-after-statement -Wempty-body -Wendif-labels -Wfloat-equal -Wignored - -qualifiers -Wno-format-nonliteral -Wno-sign-conversion -Wno-system-headers - - Wstrict-prototypes -Wtype-limits -Wvla -Wshift-sign-overflow -Wshorten-64-to- - 32 -Wdouble-promotion -Wenum-conversion -Wunused-const-variable -Wcomma -Wmis - sing-variable-declarations -Wassign-enum -Wextra-semi-stmt -MD -MT CMakeFile - s/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj -MF CMakeFiles/cmTC_2d8fe.dir/HAVE_WINL - DAP_H.c.obj.d -o CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj -c /my/curl/b - ld-cmake-llvm-x64-shared/CMakeFiles/CMakeScratch/TryCompile-3JP6dR/HAVE_WINLD - AP_H.c - In file included from /my/curl/bld-cmake-llvm-x64-shared/CMakeFiles/CMakeScra - tch/TryCompile-3JP6dR/HAVE_WINLDAP_H.c:2: - In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi - ngw32/include/winldap.h:17: - In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi - ngw32/include/schnlsp.h:9: - In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi - ngw32/include/schannel.h:10: - /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mingw32/include/wincrypt - .h:5041:254: error: unknown type name 'PSYSTEMTIME' - WINIMPM PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate (HCRYPTPROV_OR_ - NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey, PCERT_NAME_BLOB pSubjectIssuerBlob, - DWORD dwFlags, PCRYPT_KEY_PROV_INFO pKeyProvInfo, PCRYPT_ALGORITHM_IDENTIFIER - pSignatureAlgorithm, PSYSTEMTIME pStartTime, PSYSTEMTIME pEndTime, PCERT_EXT - ENSIONS pExtensions); - - - - ^ - /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mingw32/include/wincrypt - .h:5041:278: error: unknown type name 'PSYSTEMTIME' - WINIMPM PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate (HCRYPTPROV_OR_ - NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey, PCERT_NAME_BLOB pSubjectIssuerBlob, - DWORD dwFlags, PCRYPT_KEY_PROV_INFO pKeyProvInfo, PCRYPT_ALGORITHM_IDENTIFIER - pSignatureAlgorithm, PSYSTEMTIME pStartTime, PSYSTEMTIME pEndTime, PCERT_EXT - ENSIONS pExtensions); - - - - ^ - 2 errors generated. - make[1]: *** [CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj] Error 1 - make: *** [cmTC_2d8fe/fast] Error 2 - exitCode: 2 - ``` + Follow-up to 3ee79c1674fd6 - Cherry-picked from #11095 88e4a21ff70ccef391cf99c8165281ff81374503 - Reviewed-by: Daniel Stenberg - Closes #11245 + Closes #11590 -Daniel Stenberg (5 Jun 2023) +- urldata: remove spurious parenthesis to unbreak no-proxy build -- urlapi: scheme starts with alpha + Follow-up to e12b39e13382 - Add multiple tests to lib1560 to verify + Closes #11591 - Fixes #11249 - Reported-by: ad0p on github - Closes #11250 +- easy: don't call Curl_trc_opt() in disabled-verbose builds -- RELEASE-NOTES: synced + Follow-up to e12b39e133822c6a0 -- CURLOPT_MAIL_RCPT_ALLOWFAILS: replace CURLOPT_MAIL_RCPT_ALLLOWFAILS + Closes #11588 - Deprecate the name using three Ls and prefer the name with two. +- http: use %u for printfing int - Replaces #10047 - Closes #11218 + Follow-up to 3ee79c1674fd6f99e8efca5 -- tests/servers: generate temp names in /tmp for unix domain sockets + Closes #11587 - ... instead of putting them in the regular pid directories because - systems generally have strict length requirements for the path name to - be shorter than 107 bytes and we easily hit that boundary otherwise. +Goro FUJI (3 Aug 2023) - The new concept generates two random names: one for the socks daemon and - one for http. +- vquic: show stringified messages for errno - Reported-by: Andy Fiddaman - Fixes #11152 - Closes #11166 + Closes #11584 -Stefan Eissing (2 Jun 2023) +Stefan Eissing (3 Aug 2023) -- http2: better support for --limit-rate +- trace: make tracing available in non-debug builds - - leave transfer loop when --limit-rate is in effect and has - been received - - adjust stream window size to --limit-rate plus some slack - to make the server observe the pacing we want - - add test case to confirm behaviour + Add --trace-config to curl - Closes #11115 + Add curl_global_trace() to libcurl -- curl_log: evaluate log statement only when transfer is verbose + Closes #11421 - Closes #11238 +Daniel Stenberg (3 Aug 2023) -Daniel Stenberg (2 Jun 2023) +- TODO: remove "Support intermediate & root pinning for PINNEDPUBLICKEY" -- libssh2: provide error message when setting host key type fails + See also https://github.com/curl/curl/pull/7507 - Ref: https://curl.se/mail/archive-2023-06/0001.html +- TODO: add "WebSocket read callback" - Closes #11240 + remove "Upgrade to websockets" as we already have this -Igor Todorovski (2 Jun 2023) + Closes #11402 -- system.h: remove __IBMC__/__IBMCPP__ guards and apply to all z/OS compiles +- test497: verify rejecting too large incoming headers - Closes #11241 +- http: return error when receiving too large header set -Daniel Stenberg (2 Jun 2023) + To avoid abuse. The limit is set to 300 KB for the accumulated size of + all received HTTP headers for a single response. Incomplete research + suggests that Chrome uses a 256-300 KB limit, while Firefox allows up to + 1MB. -- docs/SECURITY-PROCESS.md: link to example of previous critical flaw + Closes #11582 -Mark Seuffert (2 Jun 2023) +Stefan Eissing (3 Aug 2023) -- README.md: updated link to opencollective +- http2: upgrade tests and add fix for non-existing stream - Closes #11232 + - check in h2 filter recv that stream actually exists + and return error if not + - add test for parallel, extreme h2 upgrades that fail if + connections get reused before fully switched + - add h2 upgrade upload test just for completeness -Daniel Stenberg (1 Jun 2023) + Closes #11563 -- libssh2: use custom memory functions +Viktor Szakats (3 Aug 2023) - Because of how libssh2_userauth_keyboard_interactive_ex() works: the - libcurl callback allocates memory that is later free()d by libssh2, we - must set the custom memory functions. +- tests: ensure `libcurl.def` contains all exports + + Add `test1279` to verify that `libcurl.def` lists all exported API + functions found in libcurl headers. - Reverts 8b5f100db388ee60118c08aa28 + Also: - Ref: https://github.com/libssh2/libssh2/issues/1078 - Closes #11235 + - extend test suite XML `stdout` tag with the `loadfile` attribute. -- test447: test PUTting a file that grows + - fix `tests/extern-scan.pl` and `test1135` to include websocket API. - ... and have curl trim the end when it reaches the expected total amount - of bytes instead of over-sending. + - use all headers (sorted) in `test1135` instead of a manual list. - Reported-by: JustAnotherArchivist on github - Closes #11223 + - add options `--sort`, `--heading=` to `tests/extern-scan.pl`. -- curl: count uploaded data to stop at the originally given size + - add `libcurl.def` to the auto-labeler GHA task. - Closes #11223 - Fixes #11222 - Reported-by: JustAnotherArchivist on github + Follow-up to 2ebc74c36a19a1700af394c16855ce144d9878e3 -- tool: remove exclamation marks from error/warning messages + Closes #11570 -- tool: use errorf() for error output +Daniel Stenberg (2 Aug 2023) - Convert a number of fprintf() calls. +- url: change default value for CURLOPT_MAXREDIRS to 30 -- tool: remove newlines from all helpf/notef/warnf/errorf calls + It was previously unlimited by default, but that's not a sensible + default. While changing this has a remote risk of breaking an existing + use case, I figure it is more likely to actually save users from loops. - Make voutf() always add one. + Closes #11581 - Closes #11226 +- lib: fix a few *printf() flag mistakes -- tests/servers.pm: pick unused port number with a server socket + Reported-by: Gisle Vanem + Ref: #11574 + Closes #11579 - This change replaces the previous method of picking a port number at - random to try to start servers on, then retrying up to ten times with - new random numbers each time, with a function that creates a server - socket on port zero, thereby getting a suitable random port set by the - kernel. That server socket is then closed and that port number is used - to setup the actual test server on. +Samuel Chiang (2 Aug 2023) - There is a risk that *another* server can be started on the machine in - the time gap, but the server verification feature will detect that. +- openssl: make aws-lc version support OCSP - Closes #11220 + And bump version in CI -- RELEASE-NOTES: synced + Closes #11568 - bump to 8.2.0 +Daniel Stenberg (2 Aug 2023) -Alejandro R. Sedeño (31 May 2023) +- tool: make the length argument an int for printf()-.* flags -- configure: fix run-compiler for old /bin/sh + Closes #11578 - If you try to assign and export on the same line on some older /bin/sh - implementations, it complains: +- tool_operate: fix memory leak when SSL_CERT_DIR is used - ``` - $ export "NAME=value" - NAME=value: is not an identifier - ``` + Detected by Coverity - This commit rewrites run-compiler's assignments and exports to work with - old /bin/sh, splitting assignment and export into two separate - statements, and only quote the value. So now we have: + Follow-up to 29bce9857a12b6cfa726a5 - ``` - NAME="value" - export NAME - ``` + Closes #11577 - While we're here, make the same change to the two supporting - assign+export lines preceeding the script to be consistent with how - exports work throughout the rest of configure.ac. +- tool/var: free memory on OOM - Closes #11228 + Coverity detected this memory leak in OOM situation -Philip Heiduck (31 May 2023) + Follow-up to 2e160c9c652504e -- circleci: install impacket & wolfssl 5.6.0 + Closes #11575 - Closes #11221 +Viktor Szakats (2 Aug 2023) -Daniel Stenberg (31 May 2023) +- gha: bump libressl and mbedtls versions -- tool_urlglob: use curl_off_t instead of longs + Closes #11573 - To handle more globs better (especially on Windows) +Jay Satiro (2 Aug 2023) - Closes #11224 +- schannel: fix user-set legacy algorithms in Windows 10 & 11 -Dan Fandrich (30 May 2023) + - If the user set a legacy algorithm list (CURLOPT_SSL_CIPHER_LIST) then + use the SCHANNEL_CRED legacy structure to pass the list to Schannel. -- scripts: Fix GHA matrix job detection in cijobs.pl + - If the user set both a legacy algorithm list and a TLS 1.3 cipher list + then abort. - The parsing is pretty brittle and it broke detecting some jobs at some - point. Also, detect if Windows is used in GHA. + Although MS doesn't document it, Schannel will not negotiate TLS 1.3 + when SCHANNEL_CRED is used. That means setting a legacy algorithm list + limits the user to earlier versions of TLS. -- runtests: abort test run after failure without -a + Prior to this change, since 8beff435 (precedes 7.85.0), libcurl would + ignore legacy algorithms in Windows 10 1809 and later. - This was broken in a recent refactor and test runs would not stop. + Reported-by: zhihaoy@users.noreply.github.com - Follow-up to d4a1b5b6 + Fixes https://github.com/curl/curl/pull/10741 + Closes https://github.com/curl/curl/pull/10746 - Reported-by: Daniel Stenberg - Fixes #11225 - Closes #11227 +Daniel Stenberg (2 Aug 2023) -Version 8.1.2 (30 May 2023) +- variable.d: setting a variable again overwrites it -Daniel Stenberg (30 May 2023) + Reported-by: Niall McGee + Bug: https://twitter.com/niallmcgee/status/1686523075423322113 + Closes #11571 -- RELEASE-NOTES: synced +Jay Satiro (2 Aug 2023) - 8.1.2 release +- CURLOPT_PROXY_SSL_OPTIONS.3: sync formatting -- THANKS: contributors from 8.1.2 + - Re-wrap CURLSSLOPT_ALLOW_BEAST description. -- lib1560: verify more scheme guessing +Daniel Stenberg (2 Aug 2023) - - on 2nd level domains - - on names without dots +- RELEASE-NOTES: synced - As mentioned in #11161, "imap.com" will be guessed IMAP +- resolve: use PF_INET6 family lookups when CURL_IPRESOLVE_V6 is set - Closes #11219 + Previously it would always do PF_UNSPEC if CURL_IPRESOLVE_V4 is not + used, thus unnecessarily asking for addresses that will not be used. -- page-header: minor wording polish in the URL segment + Reported-by: Joseph Tharayil + Fixes #11564 + Closes #11565 - Closes #11217 +- docs: link to the website versions instead of markdowns -- page-header: mention curl version and how to figure out current release + ... to make the links work when the markdown is converted to webpages on + https://curl.se - Closes #11216 + Reported-by: Maurício Meneghini Fauth + Fixes https://github.com/curl/curl-www/issues/272 + Closes #11569 -- RELEASE-NOTES: synced +Viktor Szakats (1 Aug 2023) -- configure: without pkg-config and no custom path, use -lnghttp2 +- cmake: cache more config and delete unused ones - Reported-by: correctmost on github - Fixes #11186 - Closes #11210 + - cache more Windows config results for faster initialization. -Stefan Eissing (28 May 2023) + - delete unused config macros `HAVE_SYS_UTSNAME_H`, `HAVE_SSL_H`. -- curl: cache the --trace-time value for a second + - delete dead references to `sys/utsname.h`. - - caches HH:MM:SS computed and reuses it for logging during - the same second. - - common function for plain log line start formatting + Closes #11551 - Closes #11211 +- egd: delete feature detection and related source code -Kev Jackson (28 May 2023) + EGD is Entropy Gathering Daemon, a socket-based entropy source supported + by pre-OpenSSL v1.1 versions and now deprecated. curl also deprecated it + a while ago. -- libcurl.m4: remove trailing 'dnl' that causes this to break autoconf + Its detection in CMake was broken all along because OpenSSL libs were + not linked at the point of feature check. - Closes #11212 + Delete detection from both cmake and autotools, along with the related + source snippet, and the `--with-egd-socket=` `./configure` option. -Stefan Eissing (26 May 2023) + Closes #11556 -- http3: send EOF indicator early as possible +Stefan Eissing (1 Aug 2023) - - ngtcp2 and quiche implementations relied on the DONE_SEND event - to forward the EOF for uploads to the libraries. This often - result in a last 0 length EOF data. Tracking the amount of - data left to upload allows EOF indication earlier. - - refs #11205 where CloudFlare DoH servers did not like to - receive the initial upload DATA without EOF and returned - a 400 Bad Request +- tests: fix h3 server check and parallel instances - Reported-by: Sergey Fionov - Fixes #11205 - Closes #11207 + - fix check for availability of nghttpx server + - add `tcp` frontend config for same port as quic, as + without this, port 3000 is bound which clashes for parallel + testing -Daniel Stenberg (26 May 2023) + Closes #11553 -- scripts/contri*sh: no longer grep -v ' ' +Daniel Stenberg (1 Aug 2023) - Originally these scripts filtered out names that have no space so that - they better avoid nick names not intended for credits. Such names are - not too commonly used, plus we now give credit even to those. +- docs/cmdline-opts: spellfixes, typos and polish - Additionally: non-latin names, like Asian, don't have spaces at all so - they were also filtered out and had to be manually added which made it - an error-prone operation where Asian names eventually easily fell off by - mistake. + To make them accepted by the spell checker - Closes #11206 + Closes #11562 -- cf-socket: restore Curl_sock_assign_addr() +- CI/spellcheck: build curl.1 and spellcheck it - Regression since it was not private. Also used by msh3.c + Added acceptable words - Follow-up to 8e85764b7bd7f05f5 - Reported-by: Gisle Vanem - Fixes #11202 - Closes #11204 + Closes #11562 -- RELEASE-NOTES: synced +Alexander Jaeger (1 Aug 2023) - Taken down to 8.1.2 now for pending patch release +- misc: fix various typos -- libssh: when keyboard-interactive auth fails, try password + Closes #11561 - The state machine had a mistake in that it would not carry on to that - next step. +Daniel Stenberg (1 Aug 2023) - This also adds a verbose output what methods that are available from the - server and renames the macros that change to the next auth methods to - try. +- http2: avoid too early connection re-use/multiplexing - Reported-by: 左潇峰 - Fixes #11196 - Closes #11197 + HTTP/1 connections that are upgraded to HTTP/2 should not be picked up + for reuse and multiplexing by other handles until the 101 switching + process is completed. -Emanuele Torre (25 May 2023) + Lots-of-debgging-by: Stefan Eissing + Reported-by: Richard W.M. Jones + Bug: https://curl.se/mail/lib-2023-07/0045.html + Closes #11557 -- configure: fix build with arbitrary CC and LD_LIBRARY_PATH +- Revert "KNOWN_BUGS: build for iOS simulator on macOS 13.2 with Xcode 14" - Since ./configure and processes that inherit its environment variables - are the only callers of the run-compiler script, we can just save the - current value of the LD_LIBRARY_PATH and CC variables to another pair of - environment variables, and make run-compiler a static script that - simply restores CC and LD_LIBRARY_PATH to the saved value, and before - running the compiler. + This reverts commit 2e8a3d7cb73c85a9aa151e263315f8a496dbb9d4. - This avoids having to inject the values of the variables in the script, - possibly causing problems if they contains spaces, quotes, and other - special characters. + It's a user error for supplying incomplete information to the build system. - Also add exports in the script just in case LD_LIBRARY_PATH and CC are - not already in the environment. + Reported-by: Ryan Schmidt + Ref: https://github.com/curl/curl/issues/11215#issuecomment-1658729367 - follow-up from 471dab2 +Viktor Szakats (1 Aug 2023) - Closes #11182 +- cmake: add support for single libcurl compilation pass -Daniel Stenberg (25 May 2023) + Before this patch CMake builds used two separate compilation passes to + build the shared and static libcurl respectively. This patch allows to + reduce that to a single pass if the target platform and build settings + allow it. -- urlapi: remove superfluous host name check + This reduces CMake build times when building both static and shared + libcurl at the same time, making these dual builds an almost zero-cost + option. - ... as it is checked later more proper. + Enable this feature for Windows builds, where the difference between the + two passes was the use of `__declspec(dllexport)` attribute for exported + API functions for the shared builds. This patch replaces this method + with the use of `libcurl.def` at DLL link time. - Closes #11195 + Also update `Makefile.mk` to use `libcurl.def` to export libcurl API + symbols on Windows. This simplifies (or fixes) this build method (e.g. + in curl-for-win, which generated a `libcurl.def` from `.h` files using + an elaborate set of transformations). -Stefan Eissing (25 May 2023) + `libcurl.def` has the maintenance cost of keeping the list of public + libcurl API symbols up-to-date. This list seldom changes, so the cost + is low. -- http2: fix EOF handling on uploads with auth negotiation + Closes #11546 - - doing a POST with `--digest` does an override on the initial request - with `Content-Length: 0`, but the http2 filter was unaware of that - and expected the originally request body. It did therefore not - send a final DATA frame with EOF flag to the server. - - The fix overrides any initial notion of post size when the `done_send` - event is triggered by the transfer loop, leading to the EOF that - is necessary. - - refs #11194. The fault did not happen in testing, as Apache httpd - never tries to read the request body of the initial request, - sends the 401 reply and closes the stream. The server used in the - reported issue however tried to read the EOF and timed out on the - request. +- cmake: detect `SSL_set0_wbio` in OpenSSL - Reported-by: Aleksander Mazur - Fixes #11194 - Cloes #11200 + Present in OpenSSL 1.1.0 and BoringSSL. + Missing from LibreSSL 3.8.0. -Daniel Stenberg (23 May 2023) + Follow-up to f39472ea9f4f4e12cfbc0500c4580a8d52ce4a59 -- RELEASE-NOTES: synced + While here, also fix `RAND_egd()` detection which was broken, likely all + along. This feature is probably broken with CMake builds and also + requires a sufficiently obsolete OpenSSL version, so this part of the + update was not tested. - bump to 8.2.0 + Closes #11555 -- lib: remove unused functions, make single-use static +- cmake: fixup H2 duplicate symbols for unity builds - Closes #11174 + Closes #11550 -- scripts/singleuse.pl: add more API calls +Pablo Busse (1 Aug 2023) -Christian Hesse (23 May 2023) +- openssl: Support async cert verify callback -- configure: quote the assignments for run-compiler + - Update the OpenSSL connect state machine to handle + SSL_ERROR_WANT_RETRY_VERIFY. - Building for multilib failed, as the compiler command contains an - extra argument. That needs quoting. + This allows libcurl users that are using custom certificate validation + to suspend processing while waiting for external I/O during certificate + validation. - Regression from b78ca50cb3dda361f9c1 + Closes https://github.com/curl/curl/pull/11499 - Fixes #11179 - Closes #11180 +Jay Satiro (1 Aug 2023) -Daniel Stenberg (23 May 2023) +- tool_cb_wrt: fix invalid unicode for windows console -- misc: fix spelling mistakes + - Suppress an incomplete UTF-8 sequence at the end of the buffer. - Reported-by: musvaage on github - Fixes #11171 - Closes #11172 + - Attempt to reconstruct incomplete UTF-8 sequence from prior call(s) + in current call. -Version 8.1.1 (23 May 2023) + Prior to this change, in Windows console UTF-8 sequences split between + two or more calls to the write callback would cause invalid "replacement + characters" U+FFFD to be printed instead of the actual Unicode + character. This is because in Windows only UTF-16 encoded characters are + printed to the console, therefore we convert the UTF-8 contents to + UTF-16, which cannot be done with partial UTF-8 sequences. -Daniel Stenberg (23 May 2023) + Reported-by: Maksim Arhipov -- RELEASE-NOTES: synced + Fixes https://github.com/curl/curl/issues/9841 + Closes https://github.com/curl/curl/pull/10890 - curl 8.1.1 +Daniel Stenberg (1 Aug 2023) -- THANKS: contributors from the 8.1.1 release +- sectransp: prevent CFRelease() of NULL -Dan Fandrich (22 May 2023) + When SecCertificateCopyCommonName() returns NULL, the common_name + pointer remains set to NULL which apparently when calling CFRelease() on + (sometimes?) crashes. -- docs: fix fuzzing documentation link + Reported-by: Guillaume Algis + Fixes #9194 + Closes #11554 - Follow-up to 4c712a1b +Jay Satiro (1 Aug 2023) -- CI: add an Alpine build with MUSL +- vtls: clarify "ALPN: offers" message - MUSL is another libc implementation which has its own unique issues - worth testing. + Before: + * ALPN: offers h2,http/1.1 - Ref: #11140 - Closes #11178 + After: + * ALPN: curl offers h2,http/1.1 -- runtests: add a missing \n at the end of a log message + Bug: https://curl.se/mail/lib-2023-07/0041.html + Reported-by: Richard W.M. Jones + Closes #11544 -correctmost on github (22 May 2023) +Daniel Stenberg (1 Aug 2023) -- SECURITY-PROCESS.md: link security advisory doc and fix typo +- urlapi: make sure zoneid is also duplicated in curl_url_dup - Closes #11177 + Add several curl_url_dup() tests to the general lib1560 test. -Daniel Stenberg (22 May 2023) + Reported-by: Rutger Broekhoff + Bug: https://curl.se/mail/lib-2023-07/0047.html + Closes #11549 -- TODO: build curl with Windows Unicode support +Sergey (1 Aug 2023) - Closes #7229 +- urlapi: fix heap buffer overflow -- KNOWN_BUGS: hyper memory-leaks + `u->path = Curl_memdup(path, pathlen + 1);` accesses bytes after the null-ter + minator. - Closes #10803 + ``` + ==2676==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x04d48c75 a + t pc 0x0112708a bp 0x006fb7e0 sp 0x006fb3c4 + READ of size 78 at 0x04d48c75 thread T0 + #0 0x1127089 in __asan_wrap_memcpy D:\a\_work\1\s\src\vctools\asan\llvm\c + ompiler-rt\lib\sanitizer_common\sanitizer_common_interceptors.inc:840 + #1 0x1891a0e in Curl_memdup C:\actions-runner\_work\client\client\third_p + arty\curl\lib\strdup.c:97 + #2 0x18db4b0 in parseurl C:\actions-runner\_work\client\client\third_part + y\curl\lib\urlapi.c:1297 + #3 0x18db819 in parseurl_and_replace C:\actions-runner\_work\client\clien + t\third_party\curl\lib\urlapi.c:1342 + #4 0x18d6e39 in curl_url_set C:\actions-runner\_work\client\client\third_ + party\curl\lib\urlapi.c:1790 + #5 0x1877d3e in parseurlandfillconn C:\actions-runner\_work\client\client + \third_party\curl\lib\url.c:1768 + #6 0x1871acf in create_conn C:\actions-runner\_work\client\client\third_p + arty\curl\lib\url.c:3403 + #7 0x186d8dc in Curl_connect C:\actions-runner\_work\client\client\third_ + party\curl\lib\url.c:3888 + #8 0x1856b78 in multi_runsingle C:\actions-runner\_work\client\client\thi + rd_party\curl\lib\multi.c:1982 + #9 0x18531e3 in curl_multi_perform C:\actions-runner\_work\client\client\ + third_party\curl\lib\multi.c:2756 + ``` -Stefan Eissing (22 May 2023) + Closes #11560 -- http/2: unstick uploads +Daniel Stenberg (31 Jul 2023) - - refs #11157 and #11175 where uploads get stuck or lead to RST streams - - fixes our h2 send behaviour to continue sending in the nghttp2 session - as long as it wants to. This will empty our send buffer as long as - the remote stream/connection window allows. - - in case the window is exhausted, the data remaining in the send buffer - will wait for a WINDOW_UPDATE from the server. Which is a socket event - that engages our transfer loop again - - the problem in the issue was that we did not exhaust the window, but - left data in the sendbuffer and no further socket events did happen. - The server was just waiting for us to send more. - - relatedly, there was an issue fixed that closing a stream with KEEP_HOLD - set kept the transfer from shutting down - as it should have - leading - to a timeout. +- curl: make %output{} in -w specify a file to write to - Closes #11176 + It can be used multiple times. Use %output{>>name} to append. -Daniel Stenberg (21 May 2023) + Add docs. Test 990 and 991 verify. -- workflows/macos: add a job using gcc + debug + secure transport + Idea: #11400 + Suggested-by: ed0d2b2ce19451f2 + Closes #11416 -Jay Satiro (21 May 2023) +- RELEASE-NOTES: synced -- lib: fix conversion warnings with gcc on macOS +- tool: add "variable" support -Daniel Stenberg (21 May 2023) + Add support for command line variables. Set variables with --variable + name=content or --variable name@file (where "file" can be stdin if set + to a single dash (-)). -- sectransp.c: make the code c89 compatible + Variable content is expanded in option parameters using "{{name}}" + (without the quotes) if the option name is prefixed with + "--expand-". This gets the contents of the variable "name" inserted, or + a blank if the name does not exist as a variable. Insert "{{" verbatim + in the string by prefixing it with a backslash, like "\\{{". - Follow-up to dd2bb485521c2ec713001b3a + Import an environment variable with --variable %name. It makes curl exit + with an error if the environment variable is not set. It can also rather + get a default value if the variable does not exist, using =content or + @file like shown above. - Reported-by: FeignClaims on github - Fixes #11155 - Closes #11159 + Example: get the USER environment variable into the URL: -Emanuele Torre (21 May 2023) + --variable %USER + --expand-url = "https://example.com/api/{{USER}}/method" -- Revert "urlapi: respect CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY for redirect - s" + When expanding variables, curl supports a set of functions that can make + the variable contents more convenient to use. It can trim leading and + trailing white space with "trim", output the contents as a JSON quoted + string with "json", URL encode it with "url" and base 64 encode it with + "b64". To apply functions to a variable expansion, add them colon + separated to the right side of the variable. They are then performed in + a left to right order. - This reverts commit df6c2f7b544f1f35f2a3e0be11f345affeb6fe9c. - (It only keep the test case that checks redirection to an absolute URL - without hostname and CURLU_NO_AUTHORITY). + Example: get the contents of a file called $HOME/.secret into a variable + called "fix". Make sure that the content is trimmed and percent-encoded + sent as POST data: - I originally wanted to make CURLU_ALLOW_SPACE accept spaces in the - hostname only because I thought - curl_url_set(CURLUPART_URL, CURLU_ALLOW_SPACE) was already accepting - them, and they were only not being accepted in the hostname when - curl_url_set(CURLUPART_URL) was used for a redirection. + --variable %HOME=/home/default + --expand-variable fix@{{HOME}}/.secret + --expand-data "{{fix:trim:url}}" + https://example.com/ - That is not actually the case, urlapi never accepted hostnames with - spaces, and a hostname with a space in it never makes sense. - I probably misread the output of my original test when I they were - normally accepted when using CURLU_ALLOW_SPACE, and not redirecting. + Documented. Many new test cases. - Some other URL parsers seems to allow space in the host part of the URL, - e.g. both python3's urllib.parse module, and Chromium's javascript URL - object allow spaces (chromium percent escapes the spaces with %20), - (they also both ignore TABs, and other whitespace characters), but those - URLs with spaces in the hostname are useless, neither python3's requests - module nor Chromium's window.location can actually use them. + Co-brainstormed-by: Emanuele Torre + Assisted-by: Jat Satiro + Closes #11346 - There is no reason to add support for URLs with spaces in the host, - since it was not a inconsistency bug; let's revert that patch before it - makes it into release. Sorry about that. +- KNOWN_BUGS: cygwin: make install installs curl-config.1 twice - I also reverted the extra check for CURLU_NO_AUTHORITY since that does - not seem to be necessary, CURLU_NO_AUTHORITY already worked for - redirects. + Closes #8839 - Closes #11169 +- KNOWN_BUGS: build for iOS simulator on macOS 13.2 with Xcode 14 -Dan Fandrich (20 May 2023) + Closes #11215 -- runtests: use the correct fd after select +- KNOWN_BUGS: cmake outputs: no version information available - The code was using the wrong fd when determining which runner was ready - with a response. + Closes #11158 - Ref: #10818 - Closes #11160 +- KNOWN_BUGS: APOP authentication fails on POP3 -- test425: fix the log directory for the upload + Closes #10073 - This must be %LOGDIR to let it work with parallel tests. +- KNOWN_BUGS: hyper is slow - Ref: #10969 + Closes #11203 -- runtests: handle interrupted reads from IPC pipes +Patrick Monnerat (31 Jul 2023) - These can be interrupted by signals, especially SIGINT to shut down, and - must be restarted so the IPC call arrives correctly. If the read just - returns an error instead, the IPC calling state will go out of sync and - a proper shutdown won't happen. +- configure, cmake, lib: more form api deprecation - Ref: #10818 + Introduce a --enable-form-api configure option to control its inclusion + in builds. The condition name defined for it is CURL_DISABLE_FORM_API. -Stefan Eissing (20 May 2023) + Form api code is dependent of MIME: configure and CMake handle this + dependency automatically: CMake by making it a dependent option + explicitly, configure by inheriting the MIME value by default and + rejecting explicit incompatible values. -- http2: upload improvements + "form-api" is now a new hidden test feature. - Make send buffer smaller to have progress and "upload done" reporting - closer to reality. Fix handling of send "drain" condition to no longer - trigger once the transfer loop reports it is done sending. Also do not - trigger the send "drain" on RST streams. + Update libcurl modules to respect this option and adjust tests + accordingly. - Background: - - a upload stall was reported in #11157 that timed out - - test_07_33a reproduces a problem with such a stall if the - server 404s the request and RSTs the stream. - - test_07_33b verifies a successful PUT, using the parameters - from #11157 and checks success + Closes #9621 - Ref: #11157 - Closes #11165 +Daniel Stenberg (31 Jul 2023) -- http2: increase stream window size to 10 MB +- mailmap: add Derzsi Dániel - Reported-by: pandada8 on github +Derzsi Dániel (31 Jul 2023) - Fixes #11162 - Closes #11167 +- wolfssl: support loading system CA certificates -Daniel Stenberg (20 May 2023) + Closes #11452 -- lib: rename struct 'http_req' to 'httpreq' +Viktor Szakats (30 Jul 2023) - Because FreeBSD 14 kidnapped the name. - Ref: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=271526 +- nss: delete more NSS references - Fixes #11163 - Closes #11164 + Fix the distcheck CI failure and delete more NSS references. -Viktor Szakats (20 May 2023) + Follow-up to 7c8bae0d9c9b2dfeeb008b9a316117d7b9675175 -- cmake: avoid `list(PREPEND)` for compatibility + Reviewed-by: Marcel Raad + Reviewed-by: Daniel Stenberg + Closes #11548 - `list(PREPEND)` requires CMake v3.15, our minimum is v3.7. +Daniel Stenberg (29 Jul 2023) - Ref: https://cmake.org/cmake/help/latest/command/list.html#prepend +- nss: remove support for this TLS library - Regression from 1e3319a167d2f32d295603167486e9e88af9bb4e + Closes #11459 - Reported-by: Keitagit-kun on Github - Fixes #11141 - Closes #11144 +Ryan Schmidt (29 Jul 2023) -Daniel Stenberg (19 May 2023) +- macOS: fix target detection more -- RELEASE-NOTES: synced + Now SCDynamicStoreCopyProxies is called (and the required frameworks are + linked in) on all versions of macOS and only on macOS. Fixes crash due + to undefined symbol when built with the macOS 10.11 SDK or earlier. -Stefan Eissing (19 May 2023) + CURL_OSX_CALL_COPYPROXIES is renamed to CURL_MACOS_CALL_COPYPROXIES and + is now only defined when SCDynamicStoreCopyProxies will actually be + called. Previously, it was defined when ENABLE_IPV6 was not defined but + SCDynamicStoreCopyProxies is not called in that case. -- ngtcp2: proper handling of uint64_t when adjusting send buffer + TARGET_OS_OSX is only defined in the macOS 10.12 SDK and later and only + when dynamic targets are enabled. TARGET_OS_MAC is always defined but + means any Mac OS or derivative including macOS, iOS, tvOS, and watchOS. + TARGET_OS_IPHONE means any Darwin OS other than macOS. - Fixes #11149 - Closes #11153 + Follow-up to c73b2f82 -- ngtcp2: fix compiler warning about possible null-deref + Fixes #11502 + Closes #11516 - - compiler analyzer did not include the call context for this - static function where the condition had already been checked. - - eleminating the problem by making stream a call parameter +Daniel Stenberg (29 Jul 2023) - Fixes #11147 - Closes #11151 +- tool_operate: allow SSL_CERT_FILE and SSL_CERT_DIR -Emanuele Torre (19 May 2023) + ... used at once. -- docs: document that curl_url_cleanup(NULL) is a safe no-op + Reported-by: Gabriel Corona + Fixes #11325 + Closes #11531 - This has always been the case, but it was not documented. +Thomas M. DuBuisson (29 Jul 2023) - The paragraph was copied verbatim from curl_easy_cleanup.3 +- CI: remove Lift's configuration - Closes #11150 + The Lift tool is being retired. Their site reads: -Antoine Pitrou (19 May 2023) + "Sonatype Lift will be retiring on Sep 12, 2023, with its analysis + stopping on Aug 12, 2023." -- select: avoid returning an error on EINTR from select() or poll() + Closes #11541 - This was already done for the poll() and select() calls - made directly from Curl_poll(), but was missed in - Curl_wait_ms(), which is called when there are no fds - to wait on. +Nathan Moinvaziri (29 Jul 2023) - Fixes #11135 - Closes #11143 +- Revert "schannel: reverse the order of certinfo insertions" -Daniel Stenberg (19 May 2023) + This reverts commit 8986df802db9b5338d9d50a54232ebae4dbcf6dd. -- vquic.c: make recvfrom_packets static, avoid compiler warning + Windows does not guarantee a particular certificate ordering, even + though TLS may have its own ordering/relationship guarantees. Recent + versions of Windows 11 reversed the ordering of ceritifcates returned by + CertEnumCertificatesInStore, therefore this commit no longer works as + initially intended. libcurl makes no guarantees about certificate + ordering if the operating system can't. - warning: no previous prototype for 'recvfrom_packets' + Ref: https://github.com/curl/curl/issues/9706 - Reported-by: Keitagit-kun on github - Fixes #11146 - Closes #11148 + Closes https://github.com/curl/curl/pull/11536 -- urlapi: allow numerical parts in the host name +wangzhikun (29 Jul 2023) - It can only be an IPv4 address if all parts are all digits and no more than - four parts, otherwise it is a host name. Even slightly wrong IPv4 will now be - passed through as a host name. +- winbuild: improve check for static zlib - Regression from 17a15d88467 shipped in 8.1.0 + - Check for zlib static library name zlibstatic.lib. - Extended test 1560 accordingly. + zlib's static library has a different name depending on how it was + built. zlibstatic.lib is output by cmake. zlibstat.lib is output by + their pre-generated Visual Studio project files (in the contrib + directory) and defines ZLIB_WINAPI (ie it's meant to use stdcall + instead of cdecl if you end up exporting the zlib functions). - Reported-by: Pavel Kalyugin - Fixes #11129 - Closes #11131 + Prior to this change the makefile only checked for the latter. -Emilio Cobos Álvarez (19 May 2023) + Closes https://github.com/curl/curl/pull/11521 -- http2: double http request parser max line length +Daniel Stenberg (29 Jul 2023) - This works around #11138, by doubling the limit, and should be a - relatively safe fix. +- configure: use the pkg-config --libs-only-l flag for libssh2 - Ideally the buffer would grow as needed and there would be no need for a - limit? But that might be follow-up material. + ... instead of --libs, as that one also returns -L flags. - Fixes #11138 - Closes #11139 + Reported-by: Wilhelm von Thiele + Fixes #11538 + Closes #11539 -Emanuele Torre (18 May 2023) +Viktor Szakats (29 Jul 2023) -- configure: fix --help alignment +- cmake: support building static and shared libcurl in one go - AC_ARG_ENABLE seems to only trim off whitespace from the start and end - of its help-string argument, while prepending two spaces of indentation - to all lines. + This patch adds the ability to build a static and shared libcurl library + in a single build session. It also adds an option to select which one to + use when building the curl executable. - This means that the two spaces of indentation between the --enable-rtsp - and the --disable-rtsp line were not removed causing ./configure --help - to print: + New build options: + - `BUILD_STATIC_LIBS`. Default: `OFF`. + Enabled automatically if `BUILD_SHARED_LIBS` is `OFF`. + - `BUILD_STATIC_CURL`. Default: `OFF`. + Requires `BUILD_STATIC_LIBS` enabled. + Enabled automatically if building static libcurl only. + - `STATIC_LIB_SUFFIX`. Default: empty. + - `IMPORT_LIB_SUFFIX`. Default: `_imp` if implib filename would collide + with static lib name (typically with MSVC) in Windows builds. + Otherwise empty. - Optional Features: - [...] - --enable-rtsp Enable RTSP support - --disable-rtsp Disable RTSP support + Also: - I removed the indentation to fix the issue, now it prints: + - Stop setting the `CURL_STATICLIB` macro via `curl_config.h`, and pass + it directly to the compiler. This also allows to delete a condition + from `tests/server/CMakeLists.txt`. - Optional Features: - [...] - --enable-rtsp Enable RTSP support - --disable-rtsp Disable RTSP support + - Complete a TODO by following the logic used in autotools (also for + `LIBCURL_NO_SHARED`), and set `-DCURL_STATICLIB` in `Cflags:` of + `libcurl.pc` for _static-only_ curl builds. - The --enable-hsts and --disable-hsts lines had the same problems, and - have been fixed too. + - Convert an existing CI test to build both shared and static libcurl. - Closes #11142 + Closes #11505 -Deal(一线灵) (18 May 2023) +Stefan Eissing (28 Jul 2023) -- cmake: repair cross compiling +- CI/awslc: add cache for build awslc library - It cannot *run* code for testing purposes when cross-compiling. + Closes #11535 - Closes #11130 +- GHA/linux.yml: add caching -Daniel Stenberg (18 May 2023) + Closes #11532 -- configure: generate a script to run the compiler +Daniel Stenberg (27 Jul 2023) - in the CURL_RUN_IFELSE macro, with LD_LIBRARY_PATH set to the value of - the configure invoke, and not the value that might be used later, - intended for the execution of the output the compiler ouputs. +- RELEASE-NOTES: synced - For example when the compiler uses the same library (like libz) that - configure checks for. + Bump working version to 8.3.0 - Reported-by: Jonas Bülow - Fixes #11114 - Closes #11120 +- url: remove infof() output for "still name resolving" -Stefan Eissing (18 May 2023) + The message does not help and might get spewed a lot during times. -- cf-socket: completely remove the disabled USE_RECV_BEFORE_SEND_WORKAROUND + Reported-by: yushicheng7788 on github + Fixes #11394 + Closes #11529 - Closes #11118 +- KNOWN_BUGS: cygwin: "WARNING: UNPROTECTED PRIVATE KEY FILE!" -Emanuele Torre (18 May 2023) + Closes #11244 -- urlapi: respect CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY for redirects +Stefan Eissing (27 Jul 2023) - curl_url_set(uh, CURLUPART_URL, redirurl, flags) was not respecing - CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY in the host part of redirurl - when redirecting to an absolute URL. +- CI: quiche updates - Closes #11136 + - remove quiche from standard `linux` workflow + - add mod_h2 caching to quiche workflow + - rename quiche to quiche-linux + - move version definitions into env section -Colin Cross (18 May 2023) + Closes #11528 -- hostip: move easy_lock.h include above curl_memory.h +- http2: disable asssertion blocking OSSFuzz testing - Similar to #9561, move easy_lock.h above curl_memory.h to fix building - against musl libc. + - not clear how this triggers and it blocks OSSFuzz testing other + things. Since we handle the case with an error return, disabling the + assertion for now seems the best way forward. - Closes #11140 + Fixes #11500 + Closes #11519 -Hind Montassif (18 May 2023) +- http2: fix in h2 proxy tunnel: progress in ingress on sending -- curl_easy_getinfo: clarify on return data types + - depending on what is tunneled, the proxy may never get invoked for + receiving data explicitly. Not progressing ingress may lead to stalls + due to missed WINDOW_UPDATEs. - Closes #11126 + CI: + - add a chache for building mod_h2 -Emanuele Torre (18 May 2023) + Closes #11527 -- checksrc: disallow spaces before labels +- CI ngtcp2+quictls: use nghttpx cache as in quiche build - Out of 415 labels throughout the code base, 86 of those labels were - not at the start of the line. Which means labels always at the start of - the line is the favoured style overall with 329 instances. +Jay Satiro (27 Jul 2023) - Out of the 86 labels not at the start of the line: - * 75 were indented with the same indentation level of the following line - * 8 were indented with exactly one space - * 2 were indented with one fewer indentation level then the following - line - * 1 was indented with the indentation level of the following line minus - three space (probably unintentional) +- bearssl: don't load CA certs when peer verification is disabled - Co-Authored-By: Viktor Szakats + We already do this for other SSL backends. - Closes #11134 + Bug: https://github.com/curl/curl/pull/11457#issuecomment-1644587473 + Reported-by: kyled-dell@users.noreply.github.com -Daniel Stenberg (18 May 2023) + Closes https://github.com/curl/curl/pull/11497 -- cookie: update the comment on cookie length and size limits +Daniel Stenberg (26 Jul 2023) - To refer to the proper cookie RFC and the upcoming RFC refresh. +- easy: remove #ifdefs to make code easier on the eye - Closes #11127 + Closes #11525 -- url: provide better error message when URLs fail to parse +Stefan Eissing (26 Jul 2023) - By providing the URL API error message into the error message. +- GHA: adding quiche workflow - Ref: #11129 - Closes #11137 + - adding separate quiche workflow to also build nghttpx server for testing -- RELEASE-NOTES: synced + Closes #11517 - bumped to 8.1.1 +Version 8.2.1 (26 Jul 2023) -Jon Rumsey (18 May 2023) +Daniel Stenberg (26 Jul 2023) -- os400: update chkstrings.c +- RELEASE-NOTES: synced - Compensate changes for recent changes to urldata.h to reclassify - STRING_AWS_SIGV4. + curl 8.2.1 release - Fixes #11132 - Closes #11133 +- THANKS: add contributors from 8.2.1 -Version 8.1.0 (17 May 2023) +- docs: provide more see also for cipher options -Daniel Stenberg (17 May 2023) + More cross references. Hide nroff errors. -- RELEASE-NOTES: synced + Closes #11513 -- THANKS: contributors from the 8.1.0 release +- docs: mark two TLS options for TLS, not SSL -- hostip: include easy_lock.h before using GLOBAL_INIT_IS_THREADSAFE + Closes #11514 - Since that header file is the only place that define can be defined. +Brad Harder (25 Jul 2023) - Reported-by: Marc Deslauriers +- curl_multi_wait.3: fix arg quoting to doc macro .BR - Follow-up to 13718030ad4b3209 + Closes #11511 - Closes #11121 +Daniel Stenberg (24 Jul 2023) -Thomas Taylor (16 May 2023) +- RELEASE-NOTES: synced -- aws-sigv4.d: fix region identifier in example +Viktor Szakats (24 Jul 2023) - Closes #11117 +- cmake: update ngtcp2 detection -Philip Heiduck (15 May 2023) + Replace `OpenSSL` with `quictls` to follow the same change + in the v0.17.0 ngtcp2 release. -- mlc_config.json: remove this linkcheck CI job config file + Follow-up to e0093b4b732f6495b0fb1cd6747cbfedcdcf63ed - Closes #11113 + Closes #11508 -Daniel Silverstone (15 May 2023) +Stefan Eissing (24 Jul 2023) -- ssh: Add support for libssh2 read timeout +- http: VLH, very large header test and fixes - Hook the new (1.11.0 or newer) libssh2 support for setting a read timeout - into the SERVER_RESPONSE_TIMEOUT option. With this done, clients can use - the standard curl response timeout setting to also control the time that - libssh2 will wait for packets from a slow server. This is necessary to - enable use of very slow SFTP servers. + - adding tests using very large passwords in auth + - fixes general http sending to treat h3 like h2, and + not like http1.1 + - eliminate H2_HEADER max definitions and use the commmon + DYN_HTTP_REQUEST everywhere, different limits do not help + - fix http2 handling of requests denied by nghttp2 on send + to immediately report the refused stream - Signed-off-by: Daniel Silverstone + Closes #11509 - Closes #10965 +Andrei Rybak (23 Jul 2023) -Osama Albahrani (14 May 2023) +- CONTRIBUTE: drop mention of copyright year ranges -- GIT-INFO: add --with-openssl + Year ranges in copyrights were dropped in commits [1] and [2]. + Verification of year ranges in copyrights was dropped from script + 'scripts/copyright.pl' in commit [3]. However, the corresponding + passages in file 'docs/CONTRIBUTE.md' weren't updated. - Closes #11110 + Drop mentions of copyright year ranges from 'docs/CONTRIBUTE.md'. -Daniel Stenberg (13 May 2023) + [1] 2bc1d775f (copyright: update all copyright lines and remove year + ranges, 2023-01-02) + [2] c46761bd8 (tests/http: remove year ranges from copyrights, + 2023-03-14) + [3] 0e293bacb (copyright.pl: cease doing year verifications, 2023-01-28) -- RELEASE-NOTES: synced + Closes #11504 -Marcel Raad (13 May 2023) +- CONTRIBUTE: fix syntax in commit message description -- md(4|5): don't use deprecated iOS functions + File 'docs/CONTRIBUTE.md' includes a description of how one should write + commit messages in the curl project. Different possible parts of the + message are enclosed in square brackets. One exception is the section + describing how the curl project doesn't use "Signed-off-by" commit + trailers [1], which is enclosed in an opening curly brace paired with a + closing square bracket. - They are marked as deprecated in iOS 13.0, which might result in - warnings-as-errors. + Fix the enclosing square brackets in description of "Signed-off-by" + trailers in commit messages in file 'docs/CONTRIBUTE.md'. - Also, use `*_MIN_REQUIRED` instead of `*_MIN_ALLOWED`, which seems to - be what's currently used. + [1] See description of option '--signoff' in Git documentation: + https://git-scm.com/docs/git-commit - Bug: https://github.com/curl/curl/issues/11098 - Closes https://github.com/curl/curl/pull/11102 + Closes #11504 -- md4: only build when used +Daniel Stenberg (23 Jul 2023) - Its only usage in curl_ntlm_core.c is guarded by `USE_CURL_NTLM_CORE`, - so let's use this here too. +- src/mkhelp: strip off escape sequences - Ref: https://github.com/curl/curl/issues/11098 - Closes https://github.com/curl/curl/pull/11102 + At some point the nroff command stopped stripping off escape sequences, + so then this script needs to do the job instead. -Vítor Galvão (12 May 2023) + Reported-by: VictorVG on github + Fixes #11501 + Closes #11503 -- write-out.d: Use response_code in example +- KNOWN_BUGS: building for old macOS fails with gcc - Closes #11107 + Closes #11441 -Shohei Maeda (12 May 2023) +Jacob Hoffman-Andrews (22 Jul 2023) -- url: fix null dispname for --connect-to option +- rustls: update rustls-ffi 0.10.0 - Closes #11106 + This brings in version 0.21.0 of the upstream rustls implementation, + which notable includes support for IP address certificates. -Daniel Stenberg (12 May 2023) + Closes #10865 -- test2306: verify getting a second response with folded headers +Brad Harder (22 Jul 2023) - Reproduces the isue #11101 and verifies the fix. +- websocket: rename arguments/variables to match docs - Verifies a17b2a503f + Pedantry/semantic-alignment between functions, docs, comments with + respect to websocket protocol code; No functional change intended. -- headers: clear (possibly) lingering pointer in init + * "totalsize", "framesize" becomes "fragsize" (we deal in frame fragments). - The "prevhead" pointer is used for the headers storage but was not - cleared correctly in init, which made it possible to act up when a - handle is reused. + * "sendflags" becomes "flags" - Reported-by: Steve Herrell - Fixes #11101 - Closes #11103 + * use canonical CURL *handle -- RELEASE-NOTES: synced + Closes #11493 -- ngtcp2: use 0.15.0 +Jan Macku (21 Jul 2023) - - nghttp3 0.11.0 - - nghttp2 1.53.0 +- bug_report: use issue forms instead of markdown template - Adapt to new API calls + Issue forms allow you to define web-like input forms using YAML + syntax. It allows you to guide the reporter to get the required + information. - Closes #11031 + Signed-off-by: Jan Macku + Closes #11474 -Jay Satiro (10 May 2023) +Daniel Stenberg (21 Jul 2023) -- openssl: fix indent +- TODO: Obey Retry-After in redirects -Daniel Stenberg (10 May 2023) + (remove "Set custom client ip when using haproxy protocol" which was + shipped in 8.2.0) -- CURLOPT_DNS_CACHE_TIMEOUT.3: fix spelling + Mentioned-by: Yair Lenga + Closes #11447 - Follow-up to 9ed7d56e044f5aa1b29 +- RELEASE-NOTES: synced - Closes #11096 +Oliver Roberts (21 Jul 2023) -- hostip: use time_t for storing oldest DNS entry +- amissl: fix AmiSSL v5 detection - Theoretically, the oldest time could overflow an int. In practice that - won't happen, but let's do this to please analyzers. + Due to changes in the AmiSSL SDK, the detection needed adjusting. - Follow-up to 9ed7d56e044f5aa1b2928ccde6245d0 + Closes #11477 - Pointed out by Coverity. - Closes #11094 +Alois Klink (21 Jul 2023) -- http: free the url before storing a new copy +- unittest/makefile: remove unneeded unit1621_LDADD - To avoid a memory-leak. + The `unit1621_LDADD` variable has the exact same value as the `LDADD` + flag in `Makefile.am`, except without `@LDFLAGS@ @LIBCURL_LIBS@`. - Reported-by: Hiroki Kurosawa + This was originally added by [98e6629][], but I can't see any reason + why it exists, so we should remove it to clean things up. - Closes #11093 + [98e6629]: https://github.com/curl/curl/commit/98e6629154044e4ab1ee7cff8351c7 + ebcb131e88 -- compressed.d: clarify the words on "not notifying headers" + Closes #11494 - Reported-by: Dylan Anthony - Fixes #11091 - Closes #11092 +- unittest/makefile: remove unneeded unit1394_LDADD -- libssh2: free fingerprint better + These custom `unit1394_LDADD` and similar automake overrides are no + longer neded. They were originally added by added by [8dac7be][] for + metalink support, but are no longer after [265b14d][] removed metalink. - Reported-by: Wei Chong Tan - Closes #11088 + [8dac7be]: https://github.com/curl/curl/commit/8dac7be438512a8725d3c71e9139bd + fdcac1ed8c + [265b14d]: https://github.com/curl/curl/commit/265b14d6b37c4298bd5556fabcbc37 + d36f911693 -- CURLOPT_IPRESOLVE.3: clarify that this for host names, not IP addresses + Closes #11494 - Reported-by: Harry Sintonen - Closes #11087 +- cmake: add `libcurlu`/`libcurltool` for unit tests -- hostip: enforce a maximum DNS cache size independent of timeout value + Add a `libcurlu`/`libcurltool` static library that is compiled only for + unit tests. We use `EXCLUDE_FROM_ALL` to make sure that they're not + built by default, they're only built if unit tests are built. - To reduce the damage an application can cause if using -1 or other - ridiculous timeout values and letting the cache live long times. + These libraries allow us to compile every unit test with CMake. - The maximum number of entries in the DNS cache is now totally - arbitrarily and hard-coded set to 29999. + Closes #11446 - Closes #11084 +Daniel Stenberg (21 Jul 2023) -- hostip: store dns timeout as 'int' +- test979: test -u with redirect to (the same) absolute host - ... because it set and held as an 'int' elsewhere and can never be - larger. + Verifies #11492 -- RELEASE-NOTES: synced +- transfer: do not clear the credentials on redirect to absolute URL -- tool_operate: refuse (--data or --form) and --continue-at combo + Makes test 979 work. Regression shipped in 8.2.0 from commit + dd4d1a26959f63a2c - libcurl assumes that a --continue-at resumption is done to continue an - upload using the read callback and neither --data nor --form use - that and thus won't do what the user wants. Whatever the user wants - with this strange combination. + Fixes #11486 + Reported-by: Cloudogu Siebels + Closes #11492 - Add test 426 to verify. +Jon Rumsey (20 Jul 2023) - Reported-by: Smackd0wn on github - Fixes #11081 - Closes #11083 +- os400: correct EXPECTED_STRING_LASTZEROTERMINATED -- transfer: refuse POSTFIELDS + RESUME_FROM combo + Correct EXPECTED_STRING_LASTZEROTERMINATED to account for + CURLOPT_HAPROXY_CLIENT_IP which requires EBCDIC to ASCII conversion when + passed into curl_easy_setopt(). - The code assumes that such a resume is wanting to continue an upload - using the read callback, and since POSTFIELDS is done without callback - libcurl will just misbehave. + Closes #11476 - This combo will make the transfer fail with CURLE_BAD_FUNCTION_ARGUMENT - with an explanation in the error message. +Oliver Roberts (20 Jul 2023) - Reported-by: Smackd0wn on github - Fixes #11081 - Closes #11083 +- amissl: add missing signal.h include -- ipv4.d/ipv6.d: they are "mutex", not "boolean" + In some environments, signal.h is already included, but not in others + which cause compilation to fail, so explictly include it. - ... which for example means they do not have --no-* versions. + Closes #11478 - Reported-by: Harry Sintonen - Fixes #11085 - Closes #11086 +- amigaos: fix sys/mbuf.h m_len macro clash -- docs/SECURITY-ADVISORY.md: how to write a curl security advisory + The updated Curl_http_req_make and Curl_http_req_make2 functions spawned + a parameter called m_len. The AmigaOS networking headers, derived from + NetBSD, contain "#define m_len m_hdr.mh_len" which clashes with + this. Since we do not actually use mbuf, force the include file to be + ignored, removing the clash. - Closes #11080 + Closes #11479 -nobedee on github (5 May 2023) +Daniel Stenberg (20 Jul 2023) -- MANUAL.md: add dict example for looking up a single definition +- socks: print ipv6 address within brackets - Closes #11077 + Fixes #11483 + Closes #11484 -Dan Fandrich (5 May 2023) +Christian Schmitz (20 Jul 2023) -- runtests: fix -c option when run with valgrind +- libcurl-errors.3: add CURLUE_OK - The curl binary argument wasn't being quoted properly. This seems to - have broken at some point after quoting was added in commit 606b29fe. + Closes #11488 - Reported-by: Daniel Stenberg - Ref: #11073 - Fixes #11074 - Closes #11076 +Oliver Roberts (20 Jul 2023) -- runtests: support creating more than one runner process +- cfilters: rename close/connect functions to avoid clashes - The controller currently only creates and uses one, but more are now - possible. + Rename `close` and `connect` in `struct Curl_cftype` for + consistency and to avoid clashes with macros of the same name + (the standard AmigaOS networking connect() function is implemented + via a macro). - Ref: #10818 + Closes #11491 -- runtests: spawn a new process for the test runner +Stefan Eissing (20 Jul 2023) - When the -j option is given, a new process is spawned in which the test - programs are run and from which test servers are started. Only one - process can be started at once, but this is sufficient to test that the - infrastructure can isolate those functions in a new task. There should - be no visible difference between the two modes at the moment. +- http2: fix regression on upload EOF handling - Ref: #10818 - Closes #11064 + - a regression introduced by c9ec85121110d7cbbbed2990024222c8f5b8afe5 + where optimization of small POST bodies leads to a new code path + for such uploads that did not trigger the "done sending" event + - add triggering this event for early "upload_done" situations -- runtests: turn singletest() into a state machine + Fixes #11485 + Closes #11487 + Reported-by: Aleksander Mazur - This allows it to run in a non-blocking manner. +Daniel Stenberg (19 Jul 2023) - Ref: #10818 +- configure: check for nghttp2_session_get_stream_local_window_size -- runtests: change runner interface to be asynchronous + The http2 code uses it now. Introduced in nghttp2 1.15.0 (Sep 2016) - Program arguments are marshalled and then written to the end of a pipe - which is later read from and the arguments unmarshalled before the - desired function is called normally. The function return values are - then marshalled and written into another pipe when is later read from - and unmarshalled before being returned to the caller. + Fixes #11470 + Reported-by: Paul Howarth + Closes #11473 - The implementation is currently blocking but can be made non-blocking - without any changes to the API. This allows calling multiple runners - without blocking in the future. +Stefan Eissing (19 Jul 2023) - Ref: #10818 +- quiche: fix segfault and other things -- runtests: call citest_finishtest in singletest + - refs #11449 where a segfault is reported when IP Eyeballing did + not immediately connect but made several attempts + - The transfer initiating the eyeballing was initialized too early, + leadding to references to the filter instance that was then + replaced in the subsequent eyeball attempts. That led to a use + after free in the buffer handling for the transfer + - transfers are initiated now more lazy (like in the ngtcp2 filter), + when the stream is actually opened + - suppress reporting on quiche event errors for "other" transfers + than the current one to not fail a transfer due to faults in + another one. + - revert recent return value handling for quiche_h3_recv_body() + to not indicate an error but an EAGAIN situation. We wish quiche + would document what functions return. - This is where citest_starttest is called. + Fixes #11449 + Closes #11469 + Reported-by: ウさん - Ref: #10818 +Daniel Stenberg (19 Jul 2023) -- runtests: add a runner initialization function +- hostip: return IPv6 first for localhost resolves - This sets up the runner environment to start running tests. + Fixes #11465 + Reported-by: Chilledheart on github + Closes #11466 - Ref: #10818 +Harry Sintonen (19 Jul 2023) -- runtests: remove directory from server filename variables +- tool: fix tool_seek_cb build when SIZEOF_CURL_OFF_T > SIZEOF_OFF_T - There will soon be multiple log directories so the paths will no longer - be static in runtests.pl. Also, get rid of $SERVER2IN which was not - used. + - a variable was renamed, and some use of it wasn't. this fixes the + build. - Ref: #10818 + Closes #11468 -- runtests: reduce package exports after refactoring +Stefan Eissing (19 Jul 2023) - Some recent refactoring made these export no longer necessary. Also, - stop displaying the Unix socket paths at startup since there will soon - be many of them and they're not that interesting. +- quiche: fix lookup of transfer at multi - Ref: #10818 + - refs #11449 where weirdness in quiche multi connection tranfers was + observed + - fixes lookup of transfer for a quiche event to take the connection + into account + - formerly, a transfer with the same stream_id, but on another connection + could be found -- runtests: use a function to obtain $LOGDIR for a test + Closes #11462 - This will no longer be static soon. +Daniel Stenberg (19 Jul 2023) - Ref: #10818 +- RELEASE-NOTES: synced -Jay Satiro (5 May 2023) + bump to 8.2.1 -- tool_cb_hdr: Fix 'Location:' formatting for early VTE terminals +John Haugabook (19 Jul 2023) - - Disable hyperlink formatting for the 'Location:' header value in VTE - 0.48.1 and earlier, since it is buggy in some of those versions. +- ciphers.d: put URL in first column - Prior to this change those terminals may show the location header value - as gibberish or show it twice. + This makes the URL turn into a link properly when "webified". - Ref: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda#backw - ard-compatibility + Fixes https://github.com/curl/curl-www/issues/270 + Closes #11464 - Fixes https://github.com/curl/curl/issues/10428 - Closes https://github.com/curl/curl/pull/11071 +Version 8.2.0 (19 Jul 2023) -François Michel (3 May 2023) +Daniel Stenberg (19 Jul 2023) -- quiche: disable pacing while pacing is not actually performed +- RELEASE-NOTES: synced - Closes #11068 + 8.2.0 release -Daniel Stenberg (2 May 2023) +- THANKS-filter: strip out "GitHub" -- easy_cleanup: require a "good" handle to act +- THANKS: add contributors from 8.2.0 - By insisting that the passed in handle is "good" (the magic number is - intact), this can limit the potential damage if a bad pointer is passed - in. Like when this function is called twice on the same handle pointer. +- RELEASE-PROCEDURE.md: adjust the release dates - Ref: #10964 - Closes #11061 +Stefan Eissing (17 Jul 2023) -Andreas Falkenhahn (1 May 2023) +- quiche: fix defects found in latest coverity report -- amiga: Fix CA certificate paths for AmiSSL and MorphOS + Closes #11455 - AmiSSL stores certificates in `AmiSSL:Certs` and MorphOS stores them in - `MOSSYS:Data/SSL/curl-ca-bundle.crt`. +Daniel Stenberg (17 Jul 2023) - Closes https://github.com/curl/curl/pull/11059 +- quiche: avoid NULL deref in debug logging -Daniel Stenberg (30 Apr 2023) + Coverity reported "Dereference after null check" -- http2: (void)-mark when we explicitly ignore the return code + If stream is NULL and the function exits, the logging must not deref it. - When h2_progress_egress() is called. Pointed out by Coverity. + Closes #11454 - Closes #11057 +Stefan Eissing (17 Jul 2023) -- checksrc: find bad indentation in conditions without open brace +- http2: treat initial SETTINGS as a WINDOW_UPDATE - If the previous line starts with if/while/for AND ends with a closed - parenthesis and there's an equal number of open and closed parentheses - on that line, verify that this line is indented $indent more steps, if - not a cpp line. + - refs #11426 where spurious stalls on large POST requests + are reported + - the issue seems to involve the following + * first stream on connection adds up to 64KB of POST + data, which is the max default HTTP/2 stream window size + transfer is set to HOLD + * initial SETTINGS from server arrive, enlarging the stream + window. But no WINDOW_UPDATE is received. + * curl stalls + - the fix un-HOLDs a stream on receiving SETTINGS, not + relying on a WINDOW_UPDATE from lazy servers - Also adjust the fall-out from this fix. + Closes #11450 - Closes #11054 +Daniel Stenberg (17 Jul 2023) -Diogo Teles Sant'Anna (28 Apr 2023) +- ngtcp2: assigning timeout, but value is overwritten before used -- CI: Set minimal permissions on workflow ngtcp2-quictls.yml + Reported by Coverity - Signed-off-by: Diogo Teles Sant'Anna + Closes #11453 - Closes #11055 +- krb5: add typecast to please Coverity -Dan Fandrich (28 Apr 2023) +Derzsi Dániel (16 Jul 2023) -- CI: use another glob syntax for matching files on Appveyor +- wolfssl: support setting CA certificates as blob - The previous globbing syntax was not matching files recursively in - directories, so try appending a /* to more closely match the examples at - https://www.appveyor.com/docs/how-to/filtering-commits/ + Closes #11445 -Daniel Stenberg (28 Apr 2023) +- wolfssl: detect when TLS 1.2 support is not built into wolfssl -- multi: add multi-ignore logic to multi_socket_action + Closes #11444 - The multi-ignore logic that was previously applied to - curl_multi_perform() (#10750) is here applied to the loop within - curl_multi_socket_action() to make it use the same optimization: most - handles have the same signal-ignore option state so this drastically - reduces the number of ignore/unignore calls per libcurl function invoke. +Graham Campbell (15 Jul 2023) - Follow-up to bc90308328afb8 +- CI: bump nghttp2 from 1.55.0 to 1.55.1 - Closes #11045 + Closes #11442 -Stefan Eissing (28 Apr 2023) +Daniel Stenberg (15 Jul 2023) -- http2: do flow window accounting for cancelled streams +- curl: return error when asked to use an unsupported HTTP version - - nghttp2 does not free connection level window flow for - aborted streams - - when closing transfers, make sure that any buffered - response data is "given back" to the flow control window - - add tests test_02_22 and test_02_23 to reproduce + When one of the following options are used but the libcurl in use does + not support it: - Closes #11052 + --http2 + --http2-prior-knowledge + --proxy-http2 -- pingpong: fix compiler warning "assigning an enum to unsigned char" + Closes #11440 - Closes #11050 +Chris Paulson-Ellis (14 Jul 2023) -Daniel Stenberg (28 Apr 2023) +- cf-socket: don't bypass fclosesocket callback if cancelled before connect -- configure: fix detection of apxs (for httpd) + After upgrading to 8.1.2 from 7.84.0, I found that sockets were being + closed without calling the fclosesocket callback if a request was + cancelled after the associated socket was created, but before the socket + was connected. This lead to an imbalance of fopensocket & fclosesocket + callbacks, causing problems with a custom event loop integration using + the multi-API. - The condition check was turned the wrong way around! + This was caused by cf_socket_close() calling sclose() directly instead + of calling socket_close() if the socket was not active. For regular TCP + client connections, the socket is activated by cf_socket_active(), which + is only called when the socket completes the connect. - Closes #11051 + As far as I can tell, this issue has existed since 7.88.0. That is, + since the code in question was introduced by: + commit 71b7e0161032927cdfb4e75ea40f65b8898b3956 + Author: Stefan Eissing + Date: Fri Dec 30 09:14:55 2022 +0100 -Viktor Szakats (28 Apr 2023) + lib: connect/h2/h3 refactor -- ci: `-Wno-vla` no longer necessary + Closes #11439 - We handle this issue in the source now. +Daniel Stenberg (13 Jul 2023) - Follow-up to b725fe1944b45406676ea3aff333ae3085a848d9 +- tool_parsecfg: accept line lengths up to 10M - Reviewed-by: Marcel Raad - Reviewed-by: Daniel Stenberg - Closes #11048 + Bumped from 100K set in 47dd957daff9 -Marcel Raad (28 Apr 2023) + Reported-by: Antoine du Hamel + Fixes #11431 + Closes #11435 -- tests/http: make curl_setup.h the first include +Stefan Eissing (13 Jul 2023) - This is required for the macros there to take effect for system - libraries. Specifically, including the system libraries first led to - warnings about `_FILE_OFFSET_BITS` being redefined in curl_config.h on - the Solaris autobuilds for ws-data.c and ws-pingpong.c. - Also make the curl includes come first for the other source files here - for consistency. +- CI: brew fix for openssl in default path - Closes https://github.com/curl/curl/pull/11046 + If brew install/update links openssl into /usr/local, it will be found + before anything we add with `-isystem path` to CPP/LDLFAGS. Get rid of + that by unlinking the keg. -Emanuele Torre (27 Apr 2023) + Fixes #11413 + Closes #11436 -- checksrc: check for spaces before the colon of switch labels +Daniel Stenberg (13 Jul 2023) - Closes #11047 +- RELEASE-NOTES: synced -Daniel Stenberg (27 Apr 2023) +Ondřej Koláček (13 Jul 2023) -- RELEASE-NOTES: synced +- sectransp: fix EOF handling -- libssh: tell it to use SFTP non-blocking + Regression since the large refactor from 2022 - Reported-by: Andreas Huebner - Fixes #11020 - Closes #11039 + Closes #11427 -Stefan Eissing (27 Apr 2023) +Daniel Stenberg (13 Jul 2023) -- http2: enlarge the connection window +- checksrc: quote the file name to work with "funny" letters - - fixes stalled connections + Closes #11437 - - Make the connection window large enough, so that there is - some room left should 99/100 streams be PAUSED by the application +Karthikdasari0423 (13 Jul 2023) - Reported-by: Paweł Wegner - Fixes #10988 - Closes #11043 +- HTTP3.md: ngtcp2 updated to v0.17.0 and nghttp3 to v0.13.0 -Daniel Stenberg (27 Apr 2023) + Follow-up to e0093b4b732f6 -- checksrc: fix SPACEBEFOREPAREN for conditions starting with "*" + Closes #11433 - The open paren check wants to warn for spaces before open parenthesis - for if/while/for but also for any function call. In order to avoid - catching function pointer declarations, the logic allows a space if the - first character after the open parenthesis is an asterisk. +Daniel Stenberg (13 Jul 2023) - I also spotted what we did not include "switch" in the check but we should. +- CURLOPT_MIMEPOST.3: clarify what setting to NULL means - This check is a little lame, but we reduce this problem by not allowing - that space for if/while/for/switch. + Follow-up to e08382a208d4e480 - Reported-by: Emanuele Torre - Closes #11044 + Closes #11430 -- docs: minor polish +Tatsuhiro Tsujikawa (12 Jul 2023) - - "an HTTP*" (not "a") - - remove a few contractions - - remove a spurious "a" - - reduce use of "I" in texts +- ngtcp2: build with 0.17.0 and nghttp3 0.13.0 - Closes #11040 + - ngtcp2_crypto_openssl was renamed to ngtcp2_crypto_quictls. -- ws: fix CONT opcode check + Closes #11428 - Detected by Coverity. Follow-up to 930c00c259 +- CI: Bump ngtcp2, nghttp3, and nghttp2 - Closes #11037 + Closes #11428 -Dan Fandrich (27 Apr 2023) +James Fuller (11 Jul 2023) -- CI: switch the awslc builds to build out-of-tree +- example/maxconnects: set maxconnect example - This is a common configuration that should be tested to avoid - regressions. The awsls cmake build was already out-of-tree so the - automake build now joins it. + Closes #11343 - Ref: #11006 +Pontakorn Prasertsuk (11 Jul 2023) -- tests/http: fix out-of-tree builds +- http2: send HEADER & DATA together if possible - Add both lib/ directories (src & build) to the search path so - curl_setup.h and its dependencies can be found. + Closes #11420 - Followup-to acd82c8b +Daniel Stenberg (11 Jul 2023) - Ref: #11006 - Closes #11036 +- CI: use wolfSSL 5.6.3 in builds -Daniel Stenberg (27 Apr 2023) + No using master anymore -- urlapi: make internal function start with Curl_ + Closes #11424 - Curl_url_set_authority() it is. +SaltyMilk (11 Jul 2023) - Follow-up to acd82c8bfd +- fopen: optimize - Closes #11035 + Closes #11419 -YX Hao (26 Apr 2023) +Daniel Stenberg (11 Jul 2023) -- cf-socket: turn off IPV6_V6ONLY on Windows if it is supported +- cmake: make use of snprintf - IPV6_V6ONLY refs: - https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses - https://github.com/golang/go/blob/master/src/net/ipsock_posix.go - https://en.wikipedia.org/wiki/Unix-like - https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-o - ptions + Follow-up to 935b1bd4544a23a91d68 - default value refs: - https://datatracker.ietf.org/doc/html/rfc3493#section-5.3 - https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html#proc-sys-net - -ipv6-variables + Closes #11423 - Closes #10975 +Stefan Eissing (11 Jul 2023) -Daniel Stenberg (26 Apr 2023) +- macOS: fix taget detection -- urldata: shrink *select_bits int => unsigned char + - TARGET_OS_OSX is not always defined on macOS + - this leads to missing symbol Curl_macos_init() + - TargetConditionals.h seems to define these only when + dynamic targets are enabled (somewhere?) + - this PR fixes that on my macOS 13.4.1 + - I have no clue why CI builds worked without it - - dselect_bits - - cselect_bits + Follow-up to c7308592fb8ba213fc2c1 + Closes #11417 - ... are using less than 8 bits. Changed types and moved them towards - the end of the structs to fit better. +Stan Hu (9 Jul 2023) - Closes #11025 +- hostip.c: Move macOS-specific calls into global init call -Stefan Eissing (26 Apr 2023) + https://github.com/curl/curl/pull/7121 introduced a macOS system call + to `SCDynamicStoreCopyProxies`, which is invoked every time an IP + address needs to be resolved. -- tests/http: more tests with specific clients + However, this system call is not thread-safe, and macOS will kill the + process if the system call is run first in a fork. To make it possible + for the parent process to call this once and prevent the crash, only + invoke this system call in the global initialization routine. - - Makefile support for building test specific clients in tests/http/clients - - auto-make of clients when invoking pytest - - added test_09_02 for server PUSH_PROMISEs using clients/h2-serverpush - - added test_02_21 for lib based downloads and pausing/unpausing transfers + In addition, this change is beneficial because it: - curl url parser: - - added internal method `curl_url_set_authority()` for setting the - authority part of a url (used for PUSH_PROMISE) + 1. Avoids extra macOS system calls for every IP lookup. + 2. Consolidates macOS-specific initialization in a separate file. - http2: - - made logging of PUSH_PROMISE handling nicer + Fixes #11252 + Closes #11254 - Placing python test requirements in requirements.txt files - - separate files to base test suite and http tests since use - and module lists differ - - using the files in the gh workflows +Daniel Stenberg (9 Jul 2023) - websocket test cases, fixes for we and bufq - - bufq: account for spare chunks in space calculation - - bufq: reset chunks that are skipped empty - - ws: correctly encode frames with 126 bytes payload - - ws: update frame meta information on first call of collect - callback that fills user buffer - - test client ws-data: some test/reporting improvements +- docs: use a space after RFC when spelling out RFC numbers - Closes #11006 + Closes #11382 -Jay Satiro (26 Apr 2023) +Margu (9 Jul 2023) -- libssh2: fix crash in keyboard callback +- imap-append.c: update to make it more likely to work - - Always set the libssh2 'abstract' user-pointer to the libcurl easy - handle associated with the ssh session, so it is always passed to the - ssh keyboard callback. + Fixes #10300 + Closes #11397 - Prior to this change and since 8b5f100 (precedes curl 8.0.0), if libcurl - was built without CURL_DEBUG then it could crash during the ssh auth - phase due to a null dereference in the ssh keyboard callback. +Emanuele Torre (9 Jul 2023) - Reported-by: Andreas Falkenhahn +- tool_writeout_json: fix encoding of control characters - Fixes https://github.com/curl/curl/pull/11024 - Closes https://github.com/curl/curl/pull/11026 + Control characters without a special escape sequence e.g. %00 or %06 + were being encoded as "u0006" instead of "\u0006". -Daniel Stenberg (26 Apr 2023) + Ref: https://github.com/curl/trurl/pull/214#discussion_r1257487858 + Closes #11414 -- docs: clarify that more backends have HTTPS proxy support +Stefan Eissing (9 Jul 2023) - Closes #11033 +- http3/ngtcp2: upload EAGAIN handling -- KNOWN_BUGS: remove two not-bugs + - refs #11389 where IDLE timeouts on upload are reported + - reword ngtcp2 expiry handling to apply to both send+recv + calls into the filter + - EAGAIN uploads similar to the recent changes in HTTP/2, e.g. + report success only when send data was ACKed. + - HOLD sending of EAGAINed uploads to avoid cpu busy loops + - rename internal function for consistency with HTTP/2 + implementation - - 11.7 signal-based resolver timeouts + Fixes #11389 + Closes #11390 - Not considered a bug anymore but just implementation details. People - should avoid using timeouts with the synchronous name resolver. +Brian Nixon (9 Jul 2023) - - 11.16 libcurl uses renames instead of locking for atomic operations +- tool_easysrc.h: correct `easysrc_perform` for `CURL_DISABLE_LIBCURL_OPTION` - Not a bug, just a description of how it works + Closes #11398 - Closes #11032 +Daniel Stenberg (9 Jul 2023) -Harry Sintonen (26 Apr 2023) +- RELEASE-NOTES: synced -- hostip: add locks around use of global buffer for alarm() +- transfer: clear credentials when redirecting to absolute URL - When building with the sync name resolver and timeout ability we now - require thread-safety to be present to enable it. + Make sure the user and password for the second request is taken from the + redirected-to URL. - Closes #11030 + Add test case 899 to verify. -Daniel Stenberg (26 Apr 2023) + Reported-by: James Lucas + Fixes #11410 + Closes #11412 -- curl_path: bring back support for SFTP path ending in /~ +Stefan Eissing (8 Jul 2023) - libcurl used to do a directory listing for this case (even though the - documentation says a URL needs to end in a slash for this), but - 4e2b52b5f7a3 modified the behavior. +- hyper: fix EOF handling on input - This change brings back a directory listing for SFTP paths that are - specified exactly as /~ in the URL. + We ran out of disc space due to an infinite loop with debug logging - Reported-by: Pavel Mayorov - Fixes #11001 - Closes #11023 + Fixes #11377 + Closes #11385 + Reported-by: Dan Fandrich -Emanuele Torre (26 Apr 2023) +- http2: raise header limitations above and beyond -- docs/libcurl/curl_*escape.3: rename "url" argument to "input"/"string" + - not quite to infinity + - rewrote the implementation of our internal HTTP/1.x request + parsing to work with very large lines using dynbufs. + - new default limit is `DYN_HTTP_REQUEST`, aka 1MB, which + is also the limit of curl's general HTTP request processing. - Also reword the DESCRIPTION section to mention "input"/"string" argument - in bold. + Fixes #11405 + Closes #11407 - Closes #11027 +Juan Cruz Viotti (8 Jul 2023) -- docs/libcurl: minor cleanups +- curl_easy_nextheader.3: add missing open parenthesis examples - I was reading curl_unescape(3) and I noticed that there was an extra - space after the open parenthesis in the SYNOPSIS; I removed the extra - space. + Closes #11409 + Signed-off-by: Juan Cruz Viotti - I also ran a few grep -r commands to find and remove extra spaces - after '(' in other files, and to find and replace uses of `T*' instead - of `T *'. Some of the instances of `T*` where unnecessary casts that I - removed. +Dan Fandrich (7 Jul 2023) - I also fixed a comment that was misaligned in CURLMOPT_SOCKETFUNCTION.3. +- CI: enable verbose test output on pytest - And I fixed some formatting inconsistencies: in curl_unescape(3), all - function parameter were mentioned with bold text except length, that was - mentioned as 'length'; and, in curl_easy_unescape(3), all parameters - were mentioned in bold text except url that was italicised. Now they are - all mentioned in bold. - Documentation is not very consistent in how function parameter are - formatted: many pages italicise them, and others display them in bold - text; but I think it makes sense to at least be consistent with - formatting within the same page. + This shows individual pass/fail status on tests and makes this output + consistent with other jobs' pytest invocations. - Closes #11027 +Stefan Eissing (28 Jun 2023) -Daniel Stenberg (26 Apr 2023) +- http2: fix crash in handling stream weights -- man pages: simplify the .TH sections + - Delay the priority handling until the stream has been opened. - - remove the version numbers - - simplify the texts + - Add test2404 to reproduce and verify. - The date and version number will be put there for releases when maketgz - runs the updatemanpages.pl script. + Weights may change "on the run", which is why there are checks in + general egress handling. These must not trigger when the stream has not + been opened yet. - Closes #11029 + Reported-by: jbgoog@users.noreply.github.com -- hostcheck: fix host name wildcard checking + Fixes https://github.com/curl/curl/issues/11379 + Closes https://github.com/curl/curl/pull/11384 - The leftmost "label" of the host name can now only match against single - '*'. Like the browsers have worked for a long time. +- tests/http: Add mod_h2 directive `H2ProxyRequests` - - extended unit test 1397 for this - - move some SOURCE variables from unit/Makefile.am to unit/Makefile.inc + master of mod_h2 now requires H2ProxyRequests directives for forward + proxying with HTTP/2 to work. - Reported-by: Hiroki Kurosawa - Closes #11018 + Ref: https://github.com/icing/mod_h2/commit/3897a7086 -Dan Fandrich (25 Apr 2023) + Closes https://github.com/curl/curl/pull/11392 -- smbserver: remove temporary files before exit +Dan Fandrich (28 Jun 2023) - Each execution of test 1451 would leave a file in /tmp before. Since - Windows can't delete a file while it's open, all the temporary file - names are stored and deleted on exit. +- CI: make Appveyor job names unique - Closes #10990 + Two otherwise identical mingw-w64 jobs now have their differing compiler + versions mentioned in their names. -Stefan Eissing (25 Apr 2023) +Sheshadri.V (25 Jun 2023) -- Websocket en-/decoding +- curl.h: include for vxworks - - state is fully kept at connection, since curl_ws_send() and - curl_ws_rec() have lifetime beyond usual transfers - - no more limit on frame sizes + Closes #11356 - Reported-by: simplerobot on github - Fixes #10962 - Closes #10999 +Dan Fandrich (24 Jun 2023) -Patrick Monnerat (25 Apr 2023) +- CI: enable parallel make in more builds -- urldata: copy CURLOPT_AWS_SIGV4 value on handle duplication + Most CI services provide at least two cores, so enable parallel make + jobs to take advantage of that for builds. Some dependencies aren't safe + to build in parallel so leave those as-is. Also, rename a few + workflows to eliminate duplicate names and provide a better idea what + they're about. - Prior to this change STRING_AWS_SIGV4 (CURLOPT_AWS_SIGV4) was wrongly - marked as binary data that could not be duplicated. +- CI: don't install impacket if tests are not run - Without this fix, this option's value is not copied upon calling - curl_easy_duphandle(). + It just wastes time and bandwidth and isn't even used. - Closes https://github.com/curl/curl/pull/11021 +divinity76 (24 Jun 2023) -Stefan Eissing (25 Apr 2023) +- configure: the --without forms of the options are also gone -- http3: expire unpaused transfers in all HTTP/3 backends + --without-darwin-ssl and --without-metalink - Closes #11005 + Closes #11378 -- http2: always EXPIRE_RUN_NOW unpaused http/2 transfers +Daniel Stenberg (23 Jun 2023) - - just increasing the http/2 flow window does not necessarily - make a server send new data. It may already have exhausted - the window before +- configure: add check for ldap_init_fd - Closes #11005 + ... as otherwise the configure script will say it is OpenLDAP in the + summary, but not set the USE_OPENLDAP define, therefor not using the + intended OpenLDAP code paths. -- http2: pass `stream` to http2_handle_stream_close to avoid NULL checks + Regression since 4d7385446 (7.85.0) + Fixes #11372 + Closes #11374 + Reported-by: vlkl-sap on github - Closes #11005 +Michał Petryka (23 Jun 2023) -- h2/h3: replace `state.drain` counter with `state.dselect_bits` +- cmake: stop CMake from quietly ignoring missing Brotli - - `drain` was used by http/2 and http/3 implementations to indicate - that the transfer requires send/recv independant from its socket - poll state. Intended as a counter, it was used as bool flag only. - - a similar mechanism exists on `connectdata->cselect_bits` where - specific protocols can indicate something similar, only for the - whole connection. - - `cselect_bits` are cleard in transfer.c on use and, importantly, - also set when the transfer loop expended its `maxloops` tries. - `drain` was not cleared by transfer and the http2/3 implementations - had to take care of that. - - `dselect_bits` is cleared *and* set by the transfer loop. http2/3 - does no longer clear it, only set when new events happen. + The CMake project was set to `QUIET` for Brotli instead of + `REQUIRED`. This makes builds unexpectedly ignore missing Brotli even + when `CURL_BROTLI` is enabled. - This change unifies the handling of socket poll overrides, extending - `cselect_bits` by a easy handle specific value and a common treatment in - transfers. + Closes #11376 - Closes #11005 +Emanuele Torre (22 Jun 2023) -Daniel Stenberg (25 Apr 2023) +- docs: add more .IP after .RE to fix indentation of generate paragraphs -- socketpair: verify with a random value + follow-up from 099f41e097c030077b8ec078f2c2d4038d31353b - ... instead of using the curl time struct, since it would use a few - uninitialized bytes and the sanitizers would complain. This is a neater - approach I think. + I just thought of checking all the other files with .RE, and I found 6 + other files that were missing .IP at the end. - Reported-by: Boris Kuschel - Fixes #10993 - Closes #11015 + Closes #11375 -Stefan Eissing (25 Apr 2023) +Stefan Eissing (22 Jun 2023) -- HTTP3: document the ngtcp2/nghttp3 versions to use for building curl +- http2: h2 and h2-PROXY connection alive check fixes - - refs #11011 to clarify this for people building curl themselves + - fix HTTP/2 check to not declare a connection dead when + the read attempt results in EAGAIN + - add H2-PROXY alive check as for HTTP/2 that was missing + and is needed + - add attach/detach around Curl_conn_is_alive() and remove + these in filter methods + - add checks for number of connections used in some test_10 + proxy tunneling tests - Closes #11019 + Closes #11368 -Daniel Stenberg (25 Apr 2023) +- http2: error stream resets with code CURLE_HTTP2_STREAM -- lib: unify the upload/method handling + - refs #11357, where it was reported that HTTP/1.1 downgrades + no longer works + - fixed with suggested change + - added test_05_03 and a new handler in the curltest module + to reproduce that downgrades work - By making sure we set state.upload based on the set.method value and not - independently as set.upload, we reduce confusion and mixup risks, both - internally and externally. + Fixes #11357 + Closes #11362 + Reported-by: Jay Satiro - Closes #11017 +Daniel Stenberg (22 Jun 2023) -- RELEASE-NOTES: synced +- connect-timeout.d: mention that the DNS lookup is included -Dan Fandrich (24 Apr 2023) + Closes #11370 -- CI: don't run CI jobs if only another CI was changed +Emanuele Torre (22 Jun 2023) - A few paths were missed in the last commit, as well as a job added since - then. +- quote.d: fix indentation of generated paragraphs - Followup-to 395b9175 + quote.d was missing a .IP at the end which caused the paragraphs + generated for See-also, Multi, and Example to not be indented correctly. -- CI: adjust labeler match patterns + I also remove a redundant "This option can be used multiple times.", and + replaced .IP "item" with .TP .B "item" to make more clear which lines + are part of the list of commands and which aren't. -- runtests: support buffering log messages in runner & servers + Closes #11371 - Log messages generated with logmsg can now be buffered and returned from - the runner as a return value. This will be needed with parallel testing - to allow all messages for one test to be displayed together instead of - interspersed with messages of multiple tests. Buffering can be disabled - by setting a logging callback function with setlogfunc, which is - currently being done to preserve existing logging behaviour for now. +Paul Wise (22 Jun 2023) - Some additional output is generated in verbose and debugprotocol modes, - which don't always use logmsg. These modes also impact some servers - which generate extra messages. No attempt is made to buffer everything - if these modes are enabled. +- checksrc: modernise perl file open - Ref: #10818 - Closes #11016 + Use regular variables and separate file open modes from filenames. -- runtests: more consistently use logmsg in server control code + Suggested by perlcritic - Also, display an error when sshversioninfo returns one. + Copied from https://github.com/curl/trurl/commit/f2784a9240f47ee28a845 - Ref: #10818 + Closes #11358 -- runtests: create runner functions for clearlocks and stopservers +Dan Fandrich (21 Jun 2023) - runtests.pl now uses runner for all server actions beyond the initial - variable configuration. +- runtests: work around a perl without SIGUSR1 - Ref: #10818 + At least msys2 perl v5.32.1 doesn't seem to define this signal. Since + this signal is only used for debugging, just ignore if setting it fails. -- runtests: tightened servers package exports + Reported-by: Marcel Raad + Fixes #11350 + Closes #11366 - The defaults are intended for runtests.pl, whereas runner.pm needs to - explicitly specify them. +- runtests: include missing valgrind package -- runtests: display logs on server failure in singletest() + use valgrind was missing which caused torture tests with valgrind + enabled to fail. - This is closer to the place where logs are displayed on test failure. - Also, only display these logs if -p is given, which is the same flag - that controls display of test failure logs. Some server log files - need to be deleted later so that they stay around long enough to be - displayed on failure. + Reported-by: Daniel Stenberg + Fixes #11364 + Closes #11365 - Ref: #10818 +- runtests: use more consistent failure lines -- runtests: turn a print into a logmsg + After a test failure log a consistent log message to make it easier to + parse the log file. Also, log a consistent message with "ignored" for + failures that cause the test to be not considered at all. These should + perhaps be counted in the skipped category, but this commit does not + change that behaviour. - Also enable another couple of useful messages in verbose mode. +- runtests: consistently write the test check summary block - Ref: #10818 + The memory check character was erroneously omitted if the memory + checking file was not available for some reason, making the block of + characters an inconsistent length. -Daniel Stenberg (24 Apr 2023) +- test2600: fix the description -- http: store the password in the correct variable + It looks like it was cut-and-pasted. - Typo from fc2f1e547a4a, detected by Coverity (because there's dead code - due to this). + Closes #11354 - Closes #11002 +Daniel Stenberg (21 Jun 2023) -Stefan Eissing (24 Apr 2023) +- TODO: "Support HTTP/2 for HTTP(S) proxies" *done* -- HTTP3/quiche: terminate h1 response header when no body is sent +humbleacolyte (21 Jun 2023) - - fixes a failure in test2501 where a response without body was missing - the final empty line +- cf-socket: move ctx declaration under HAVE_GETPEERNAME - Closes #11003 + Closes #11352 -Dan Fandrich (22 Apr 2023) +Daniel Stenberg (20 Jun 2023) -- runtests: move showdiff into runtests.pl +- RELEASE-NOTES: synced - It's not used anywhere else. +- example/connect-to: show CURLOPT_CONNECT_TO -- devtest: add a new script for testing the test harness + Closes #11340 - This is currently useful for starting a test server on its own without - an associated test, which can be used for interactive curl testing or - for validating parts of the test harness itself. More commands can be - added to perform additional functions in the future. +Stefan Eissing (20 Jun 2023) - Ref: #10818 - Closes #11008 +- hyper: unslow -- runtests: refactor the main test loop into two + - refs #11203 where hyper was reported as being slow + - fixes hyper_executor_poll to loop until it is out of + tasks as advised by @seanmonstar in https://github.com/hyperium/hyper/issue + s/3237 + - added a fix in hyper io handling for detecting EAGAIN + - added some debug logs to see IO results + - pytest http/1.1 test cases pass + - pytest h2 test cases fail on connection reuse. HTTP/2 + connection reuse does not seem to work. Hyper submits + a request on a reused connection, curl's IO works and + thereafter hyper declares `Hyper: [1] operation was canceled: connection cl + osed` + on stderr without any error being logged before. - The test loop now has an initial loop that first runs through all - possible tests to build a set of those to attempt on this run based on - features and keywords and only then goes through that new list to run - them. This actually makes it three loops through all tests cases, as - there is an existing loop that gathers possible test numbers from the - test files on disk. + Fixes #11203 + Reported-by: Gisle Vanem + Advised-by: Sean McArthur + Closes #11344 - This has two minor effects on the output: all the tests that will be - skipped are displayed at the start (instead of being interspersed with - other tests) and the -l option no longer shows a count of tests at the - end or a (misleading) statement that tests have run successfully. The - skipped tests are also omitted from the test results sent to AppVeyor - and Azure in CI builds. +- HTTP/2: upload handling fixes - Another effect is a reduction in the amount of work considered part of - the "Test definition reading and preparation time" reported with -r - making those figures slightly lower than before. + - fixes #11242 where 100% CPU on uploads was reported + - fixes possible stalls on last part of a request body when + that information could not be fully send on the connection + due to an EAGAIN + - applies the same EGAIN handling to HTTP/2 proxying - Ref: #10818 + Reported-by: Sergey Alirzaev + Fixed #11242 + Closes #11342 -- runtests: track only the current test timings in runner.pm +Daniel Stenberg (20 Jun 2023) - This avoids passing these data through through global variables, which - soon won't be possible. +- example/opensslthreadlock: remove - Ref: #10818 + This shows how to setup OpenSSL mutex callbacks, but this is not + necessary since OpenSSL 1.1.0 - meaning that no currently supported + OpenSSL version requires this anymore -- runtests: skip test preprocessing when doing -l + Closes #11341 - This speeds up the output tremendously by avoiding unnecessary work. +Dan Fandrich (19 Jun 2023) -- runtests: simplify value returned regarding use of valgrind +- libtest: display the times after a test timeout error - As a side effect this will now also show in verbose mode that valgrind - is being skipped on tests that explicitly disable it, such as 600. + This is to help with test failure debugging. - Ref: #10818 + Ref: #11328 + Closes #11329 -- runtests: fix quoting in Appveyor and Azure test integration +- test2600: bump a test timeout - Test 1442's name was not quoted correctly so wasn't registered in - Appveyor and it had the wrong name in Azure. The JSON string quotes were - also invalid, even though both servers happened to accept it regardless. + Case 1 failed at least once on GHA by going 30 msec too long. - Closes #11010 + Ref: #11328 -Daniel Stenberg (19 Apr 2023) +- runtests: better detect and handle pipe errors in the controller -- RELEASE-NOTES: synced + Errors reading and writing to the pipes are now better detected and + propagated up to the main test loop so it can be cleanly shut down. Such + errors are usually due to a runner dying so it doesn't make much sense + to try to continue the test run. -Dan Fandrich (18 Apr 2023) +- runtests: cleanly abort the runner if the controller dies -- runtests: spread out the port numbers used by servers + If the controller dies unexpectedly, have the runner stop its servers + and exit cleanly. Otherwise, the orphaned servers will stay running in + the background. - The server ports are chosen randomly for each server, but the random - ranges chosen were inconsistently-sized and overlapping. Now, they are - spread out more so at least the first random port chosen for each server - is guaranteed to not also be chosen by another server. The starting port - numbers are also raised to put them in the Ephemeral Port range—not the - range defined by RFC 6335 but the one used by Linux, which starts lower - and gives us more room to work with. +- runtests: improve error logging - Reported-by: Daniel Stenberg + Give more information about test harness error conditions to help figure + out what might be wrong. Print some internal test state when SIGUSR1 is + sent to runtests.pl. -- runtests: fix problems on failure + Ref: #11328 - The verify time must be set in this case, like all cases. An error - message needs to be displayed as well. +- runtests: better handle ^C during slow tests -- runtests: fix perl warning when is wrong + Since the SIGINT handler now just sets a flag that must be checked in the + main controller loop, make sure that runs periodically. Rather than + blocking on a response from a test runner near the end of the test run, + add a short timeout to allow it. -- runtests: don't try to stop stunnel before trying again +- runtests: rename server command file - Calling stopserver() before retrying stunnel due to an error would stop - the dependent server (such as HTTP) meaning stunnel would have nothing - to talk to when it came up. Don't try to force a stop when it didn't - actually start. Also, don't mark the server as bad for future use when - it starts up on a retry. + The name ftpserver.cmd was historical and has been used for more than + ftp for many years now. Rename it to plain server.cmd to reduce + confusion. - Reported-by: eaglegai at github - Tested-by: eaglegai at github - Fixes #10976 +- tests: improve reliability of TFTP tests -- runtests: don't accidentally randomly choose the same port + Stop checking the timeout used by the client under test (for most + tests). The timeout will change if the TFTP test server is slow (such as + happens on an overprovisioned CI server) because the client will retry + and reduce its timeout, and the actual value is not important for most + tests. - If a server couldn't be started on a port, a new one is randomly chosen - and the server is tried again. Avoid accidentally using a - randomly-chosen 0 port offset by adding 1 to the random number. + test285 is changed a different way, by increasing the connect timeout. + This improves test coverage by allowing the changed timeout value to be + checked, but improves reliability with a carefully-chosen timeout that + not only allows twice the time to respond as before, but also allows + several retries before the client will change its timeout value. - Found-by: Daniel Stenberg + Ref: #11328 -- runtests: don't attempt to use a port we know is in use +Daniel Stenberg (19 Jun 2023) - This reduces the startup time when there is a known conflict on the - random port chosen for a server. This was already done for stunnel, but - now it's done for all servers. +- cf-socket: skip getpeername()/getsockname for TFTP -- http-server: fix server name in a log message + Since the socket is not connected then the call fails. When the call + fails, failf() is called to write an error message that is then + surviving and is returned when the *real* error occurs later. The + earlier, incorrect, error therefore hides the actual error message. - This changed when the file was renamed in commit cbf57176 + This could be seen in stderr for test 1007 -- runtests: refactor into more packages + Test 1007 has now been extended to verify the stderr message. - testutil.pm now contains a few miscellaneous functions that are used in - several places but have no better place to live. subvariables moves to - servers.pm since most variables that it substitutes relate to servers, - so this is the most appropriate place. Rename a few functions for better - naming consistency. + Closes #11332 - Ref: #10818 - Closes #10995 +- example/crawler: make it use a few more options -- runtests: call timestampskippedevents() in singletest + For show, but reasonable - ..rather than by the runner +- libcurl-ws.3: mention raw mode -- runtests: assume a newer Valgrind by default + Closes #11339 - The tests for an older Valgrind version should probably just be deleted, - given that they're testing for an 18-year-old version. +- example/default-scheme: set the default scheme for schemeless URLs -- runtests: refactor test runner code into runner.pm + Closes #11338 - This is code that is directly responsible for running a single test. - This will eventually run in a separate process as part of the parallel - testing project. +- example/hsts-preload: show one way to HSTS preload - Ref: #10818 + Closes #11337 -- runtests: skip unneeded work if test won't be running +- examples/http-options: show how to send "OPTIONS *" - This speeds up tests by avoiding unnecessary processing. + With CURLOPT_REQUEST_TARGET. - Ref: #10818 + Also add use of CURLOPT_QUICK_EXIT to show. -- runtests: factor out singletest_postcheck + Closes #11333 - This will eventually need to be part of the test runner. +- examples: make use of CURLOPT_(REDIR_|)PROTOCOLS_STR - Ref: #10818 + To show how to use them -- test303: kill server after test + Closes #11334 - Otherwise, an HTTP test closely following this one with a tight time - constraint (e.g. 672) could fail because the test server stays sitting - with the wait command for a while. +- examples/smtp-mime: use CURLOPT_MAIL_RCPT_ALLOWFAILS -Patrick Monnerat (18 Apr 2023) + For show -- OS400: provide ILE/RPG usage examples + Closes #11335 - Closes https://github.com/curl/curl/pull/10994 +- http: rectify the outgoing Cookie: header field size check -- OS400: improve vararg emulation + Previously it would count the size of the entire outgoing request and + not just the size of only the Cookie: header field - which was the + intention. - - Use V7R4 RPG procedure overloading to improve vararg emulation. + This could make the check be off by several hundred bytes in some cases. - From OS400 V7R4 and above, ILE/RPG implements a limited procedure - overloading feature that can be used to improve curl's typed - implementation of varargs procedures. This commit applies it to - curl_easy_setopt(), curl_multi_setopt(), curl_share_setopt() and - curl_easy_getinfo(). + Closes #11331 - Closes https://github.com/curl/curl/pull/10994 +Jay Satiro (17 Jun 2023) -- OS400: fix and complete ILE/RPG binding +- lib: fix some format specifiers - - Fix wrong definitions of CURL_ZERO_TERNINATED, curl_mime_data() and - curl_mime_data_ccsid(). + - Use CURL_FORMAT_CURL_OFF_T where %zd was erroneously used for some + curl_off_t variables. - - Add recent definitions, in particular blob, header API and WebSockets - API. + - Use %zu where %zd was erroneously used for some size_t variables. - - Support for CURLVERSION_ELEVENTH. + Prior to this change some of the Windows CI tests were failing because + in Windows 32-bit targets have a 32-bit size_t and a 64-bit curl_off_t. + When %zd was used for some curl_off_t variables then only the lower + 32-bits was read and the upper 32-bits would be read for part or all of + the next specifier. - - New functions for EBCDIC support. + Fixes https://github.com/curl/curl/issues/11327 + Closes https://github.com/curl/curl/pull/11321 - Reflect these changes in README.OS400. +Marcel Raad (16 Jun 2023) - Closes https://github.com/curl/curl/pull/10994 +- test427: add `cookies` feature and keyword -- OS400: implement EBCDIC support for recent features + This test doesn't work with `--disable-cookies`. - - Support CURLVERSION_ELEVENTH. + Closes https://github.com/curl/curl/pull/11320 - - New function curl_url_strerror_ccsid(). +Chris Talbot (15 Jun 2023) - - curl_easy_setopt_ccsid() supports blobs and 3 recent string options. +- imap: Provide method to disable SASL if it is advertised - - New function curl_easy_header_ccsid(). + - Implement AUTH=+LOGIN for CURLOPT_LOGIN_OPTIONS to prefer plaintext + LOGIN over SASL auth. - - New generic latin1<-->ccsid conversion functions curl_from_ccsid() and - curl_to_ccsid() for user convenience. + Prior to this change there was no method to be able to fall back to + LOGIN if an IMAP server advertises SASL capabilities. However, this may + be desirable for e.g. a misconfigured server. - - README.OS400 updated accordingly. + Per: https://www.ietf.org/rfc/rfc5092.html#section-3.2 - - Removed a leftover QsoSSL support identifier. + ";AUTH=" looks to be the correct way to specify what + authenication method to use, regardless of SASL or not. - Closes https://github.com/curl/curl/pull/10994 + Closes https://github.com/curl/curl/pull/10041 -- OS400: rework build scripts +Daniel Stenberg (15 Jun 2023) - - Rename shell function "system" to "CLcommand" to avoid confusion with - built-in command. +- RELEASE-NOTES: synced - - Reformat scripts. Fix some indentations. Avoid lines > 80 characters - where possible. +- examples/multi-debugcallback.c: avoid the bool typedef - - Support ASCII runtime development files in a user-defined directory - path. + Apparently this cannot be done in c23 - - FIX SONAME detection. + Reported-by: Cristian Rodríguez + Fixes #11299 + Closes #11319 - - Drop form API test program compilation (does not exist anymore). +- docs/libcurl/libcurl.3: cleanups and improvements - Closes https://github.com/curl/curl/pull/10994 + Closes #11317 -Sevan Janiyan (18 Apr 2023) +- libcurl-ws.3: fix typo -- tests/sshserver.pl: Define AddressFamily earlier +- curl_ws_*.3: enhance - As the comment states "Address family must be specified before ListenAddress" - , otherwise the tests fail to run - `"failed starting SSH server" 52 times (582, 583, 600, 601, 602, 603, 604, 60 - 5, 606 and 43 more)` + - all: SEE ALSO the libcurl-ws man page + - send: add example and return value information + - meta: mention that the returned data is read-only - Closes #10983 + Closes #11318 -Stefan Eissing (18 Apr 2023) +- docs/libcurl/libcurl-ws.3: see also CURLOPT_WS_OPTIONS -- quiche: Enable IDLE egress handling +- docs/libcurl/libcurl-ws.3: minor polish - Follow-up to 544abeea which added the handling but wrongly left it - commented out. +- libcurl-ws.3. WebSocket API overview - Closes https://github.com/curl/curl/pull/11000 + Closes #11314 -Daniel Stenberg (18 Apr 2023) +- libcurl-url.3: also mention CURLUPART_ZONEID -- docs/examples/protofeats.c: Outputs all protocols and features + ... and sort the two part-using lists alphabetically - Showing off one way to get to char pointer arrays of info returned by - curl_version_info() +Marcel Raad (14 Jun 2023) - Closes #10991 +- fopen: fix conversion warning on 32-bit Android -- tests/keywords.pl: remove + When building for 32-bit ARM or x86 Android, `st_mode` is defined as + `unsigned int` instead of `mode_t`, resulting in a + -Wimplicit-int-conversion clang warning because `mode_t` is + `unsigned short`. Add a cast to silence the warning. - This script does not work since the introduction of the test - preprocessing. If we need this functionality, it probably needs to be - moved into the runtests tool or similar. + Ref: https://android.googlesource.com/platform/bionic/+/refs/tags/ndk-r25c/li + bc/include/sys/stat.h#86 + Closes https://github.com/curl/curl/pull/11313 - Reported-by: Dan Fandrich - Fixes #10895 - Closes #10987 +- http2: fix variable type -Stefan Eissing (17 Apr 2023) + `max_recv_speed` is `curl_off_t`, so using `size_t` might result in + -Wconversion GCC warnings for 32-bit `size_t`. Visible in the NetBSD + ARM autobuilds. -- http2: support HTTP/2 to forward proxies, non-tunneling + Closes https://github.com/curl/curl/pull/11312 - - with `--proxy-http2` allow h2 ALPN negotiation to - forward proxies - - applies to http: requests against a https: proxy only, - as https: requests will auto-tunnel - - adding a HTTP/1 request parser in http1.c - - removed h2h3.c - - using new request parser in nghttp2 and all h3 backends - - adding test 2603 for request parser - - adding h2 proxy test cases to test_10_* +Daniel Stenberg (13 Jun 2023) - scorecard.py: request scoring accidentally always run curl - with '-v'. Removed that, expect double numbers. +- vtls: fix potentially uninitialized local variable warnings - labeller: added http1.* and h2-proxy sources to detection + Follow-up from a4a5e438ae533c - Closes #10967 + Closes #11310 -Daniel Stenberg (17 Apr 2023) +- timeval: use CLOCK_MONOTONIC_RAW if available -- curl_easy_unescape.3: rename the argument + Reported-by: Harry Sintonen + Ref: #11288 + Closes #11291 - and highlight it appropriately in the text. +Stefan Eissing (12 Jun 2023) - Closes #10979 +- tool: add curl command line option `--trace-ids` -Viktor Szakats (17 Apr 2023) + - added and documented --trace-ids to prepend (after the timestamp) + the transfer and connection identifiers to each verbose log line + - format is [n-m] with `n` being the transfer id and `m` being the + connection id. In case there is not valid connection id, print 'x'. + - Log calls with a handle that has no transfer id yet, are written + without any ids. -- autotools: sync up clang picky warnings with cmake + Closes #11185 - Bringing missing options over from CMake. +- lib: add CURLINFO_CONN_ID and CURLINFO_XFER_ID - Move around existing `-Wno-pointer-bool-conversion` option to come - _after_ `-Wconversion`. + - add an `id` long to Curl_easy, -1 on init + - once added to a multi (or its own multi), it gets + a non-negative number assigned by the connection cache + - `id` is unique among all transfers using the same + cache until reaching LONG_MAX where it will wrap + around. So, not unique eternally. + - CURLINFO_CONN_ID returns the connection id attached to + data or, if none present, data->state.lastconnect_id + - variables and type declared in tool for write out - Reviewed-by: Marcel Raad - Closes #10974 + Closes #11185 -Daniel Stenberg (17 Apr 2023) +Daniel Stenberg (12 Jun 2023) -- tests/libtest/lib1900.c: remove +- CURLOPT_INFILESIZE.3: mention -1 triggers chunked - This file was left behind when the rest of the test was previously removed. + Ref: #11300 + Closes #11304 - Follow-up to e50a877df74f +Philip Heiduck (12 Jun 2023) -- src/tool_operhlp.c: fix value stored to 'uerr' is never read +- CI: openssl-3.0.9+quic - Ref: https://github.com/curl/curl/pull/10974#issuecomment-1510461343 - Reported-by: Viktor Szakats - Closes #10982 + Closes #11296 -Viktor Szakats (16 Apr 2023) +Karthikdasari0423 (12 Jun 2023) -- cmake: speed up and extend picky clang/gcc options +- HTTP3.md: update openssl version - Extend existing picky compiler options with ones missing compared to - autotools builds. Also sync options between clang and gcc. + Closes #11297 - Redesign the way we enable these options to avoid the slow option - detection almost completely. +Daniel Stenberg (12 Jun 2023) - This reduces the number of detections from 35 to zero for clang and - 3 for gcc, even after adding a bunch of new options. +- vtls: avoid memory leak if sha256 call fails - clang 3.0 (2011-11-29) and gcc 2.95 (1999-07-31) now required. + ... in the pinned public key handling function. - Also show enabled picky options. + Reported-by: lizhuang0630 on github + Fixes #11306 + Closes #11307 - Ref: https://github.com/libssh2/libssh2/pull/952 +- examples/ipv6: disable on win32 - Reviewed-by: Daniel Stenberg - Closes #10973 + I can't make if_nametoindex() work there -Andreas Falkenhahn (16 Apr 2023) + Follow-up to c23dc42f3997acf23 -- nbtlm: use semicolons instead of commas for (void) args + Closes #11305 - Closes #10978 +- tool_operate: allow cookie lines up to 8200 bytes -Daniel Stenberg (15 Apr 2023) + Since this option might set multiple cookies in the same line, it does + not make total sense to cap this at 4096 bytes, which is the limit for a + single cookie name or value. -- multi: free up more data earleier in DONE + Closes #11303 - Before checking for more users of the connection and possibly bailing - out. +- test427: verify sending more cookies than fit in a 8190 bytes line - Fixes #10971 - Reported-by: Paweł Wegner - Closes #10972 + curl will then only populate the header with cookies that fit, dropping + ones that otherwise would have been sent -- RELEASE-NOTES: synced + Ref: https://curl.se/mail/lib-2023-06/0020.html -- curl: do NOT append file name to path for upload when there's a query + Closes #11303 - Added test 425 to verify. +- testutil: allow multiple %-operators on the same line - Reported-by: Dirk Rosenkranz - Bug: https://curl.se/mail/archive-2023-04/0008.html - Closes #10969 + Closes #11303 -- libcurl-thread.3: improved name resolver wording +Oleg Jukovec (12 Jun 2023) - And make better .SH sections +- docs: update CURLOPT_UPLOAD.3 - Closes #10966 + The behavior of CURLOPT_UPLOAD differs from what is described in the + documentation. The option automatically adds the 'Transfer-Encoding: + chunked' header if the upload size is unknown. -Colman Mbuya (14 Apr 2023) + Closes #11300 -- CURLOPT_PROXY_SSL_VERIFYPEER.3: fix minor grammar mistake +Daniel Stenberg (12 Jun 2023) - Closes #10968 +- RELEASE-NOTES: synced -Daniel Stenberg (14 Apr 2023) +- CURLOPT_AWS_SIGV4.3: remove unused variable from example -- curl: add --proxy-http2 + Closes #11302 - For trying HTTP/2 with an HTTPS proxy. +- examples/https.c: use CURLOPT_CA_CACHE_TIMEOUT - Closes #10926 + for demonstration purposes -- KNOWN_BUGS: remove fixed or outdated issues, move non-bugs + Closes #11290 - - remove h3 issues believed to be fixed +- example/ipv6: feature CURLOPT_ADDRESS_SCOPE in use - - make the flaky CI issue be generic and not Windows specific + Closes #11282 - - "TLS session cache does not work with TFO" now documented +Karthikdasari0423 (10 Jun 2023) - This is now a documented restriction and not a bug. TFO in general is - rarely used and has other problems, making it a low-priotity thing to - work on. +- docs: Update HTTP3.md for newer ngtcp2 and nghttp3 - - remove "Renegotiate from server may cause hang for OpenSSL backend" + Follow-up to fb9b9b58 - This is an OpenSSL issue, not a curl one. Even if it taints curl. + Ref: #11184 + Closes #11295 - - rm "make distclean loops forever" +Dan Fandrich (10 Jun 2023) - - rm "configure finding libs in wrong directory" +- docs: update the supported ngtcp2 and nghttp3 versions - Added a section to docs/INSTALL.md about it. + Follow-up to cae9d10b - - "A shared connection cache is not thread-safe" + Ref: #11184 + Closes #11294 - Moved over to TODO and expanded for other sharing improvements we - could do +- tests: fix error messages & handling around sockets - - rm "CURLOPT_OPENSOCKETPAIRFUNCTION is missing" + The wrong error code was checked on Windows on UNIX socket failures, + which could have caused all UNIX sockets to be reported as having + errored and the tests therefore skipped. Also, a useless error message + was displayed on socket errors in many test servers on Windows because + strerror() doesn't work on WinSock error codes; perror() is overridden + there to work on all errors and is used instead. - - rm "Blocking socket operations in non-blocking API" + Ref #11258 + Closes #11265 - Already listed as a TODO +Daniel Stenberg (9 Jun 2023) - - rm "curl compiled on OSX 10.13 failed to run on OSX 10.10" +- CURLOPT_SSH_PRIVATE_KEYFILE.3: expand on the file search - Water under the bridge. No one cares about this anymore. + Reported-by: atjg on github + Ref: #11287 + Closes #11289 - - rm "build on Linux links libcurl to libdl" +Stefan Eissing (9 Jun 2023) - Verified to not be true (anymore). +- ngtcp2: use ever increasing timestamp in io - - rm "libpsl is not supported" + - ngtcp2 v0.16.0 asserts that timestamps passed to its function + will only ever increase. + - Use a context shared between ingress/egress operations that + uses a shared timestamp, regularly updated during calls. - The cmake build supports it since cafb356e19cda22 + Closes #11288 - Closes #10963 +Daniel Stenberg (9 Jun 2023) -- url: fix PVS nits +- GHA: use nghttp2 1.54.0 for the ngtcp2 jobs - - expression 'hostptr' is always true - - a part of conditional expression is always true: proxypasswd - - expression 'proxyuser' is always true - - avoid multiple Curl_now() calls in allocate_conn +Philip Heiduck (9 Jun 2023) - Ref: #10929 - Closes #10959 +- GHA: ngtcp2: use 0.16.0 and nghttp3 0.12.0 -- bufq: simplify since expression is always true +Daniel Stenberg (9 Jun 2023) - The check for 'len' is already done so it will remain true until - updated. Pointed out by PVS. +- ngtcp2: build with 0.16.0 and nghttp3 0.12.0 - Ref: #10929 - Closes #10958 + - moved to qlog_write + - crypto => encryption + - CRYPTO => ENCRYPTION + - removed "_is_" + - ngtcp2_conn_shutdown_stream_read and + ngtcp2_conn_shutdown_stream_write got flag arguments + - the nghttp3_callbacks struct got a recv_settings callback -- hash: fix assigning same value + Closes #11184 - Pointed out by PVS +- example/http2-download: set CURLOPT_BUFFERSIZE - Ref: #10929 - Closes #10956 + Primarily because no other example sets it, and remove the disabling of + the certificate check because we should not recommend that. -- cookie: address PVS nits + Closes #11284 - - avoid assigning the same value again - - remove superfluous check of co->domain - - reduce variable scope for namep/valuep +- example/crawler: also set CURLOPT_AUTOREFERER - Ref: #10929 - Closes #10954 + Could make sense, and it was not used in any example before. -Stefan Eissing (14 Apr 2023) + Closes #11283 -- cf-socket: Disable socket receive buffer by default +Wyatt OʼDay (9 Jun 2023) - - Disable socket receive buffer unless USE_RECV_BEFORE_SEND_WORKAROUND - is in place. +- tls13-ciphers.d: include Schannel - While we would like to use the receive buffer, we have stalls in - parallel transfers where not all buffered data is consumed and no socket - events happen. + Closes #11271 - Note USE_RECV_BEFORE_SEND_WORKAROUND is a Windows sockets workaround - that has been disabled by default since b4b6e4f1, due to other bugs. +Daniel Stenberg (9 Jun 2023) - Closes https://github.com/curl/curl/pull/10961 +- curl_pushheader_byname/bynum.3: document in their own man pages -- cf-h2-proxy: fix processing ingress to stop too early + These two functions were added in 7.44.0 when CURLMOPT_PUSHFUNCTION was + introduced but always lived a life in the shadows, embedded in the + CURLMOPT_PUSHFUNCTION man page. Until now. - - progress ingress stopped too early, causing data - from the underlying filters to not be processed and - report that no tunnel data was available - - this lead to "hangers" where no socket activity was - seen but data rested in buffers + It makes better sense and gives more visibility to document them in + their own stand-alone man pages. - Closes #10952 + Closes #11286 -- http3: check stream_ctx more thoroughly in all backends +- curl_mprintf.3: minor fix of the example - - callbacks and filter methods might be invoked at unexpected - times, e.g. when the transfer's stream_ctx has not been initialized - yet or, more likely, has already been taken down. - - check for existance of stream_ctx in such places and return - an error or silently succeed the call. +- curl_url_set: enforce the max string length check for all parts - Closes #10951 + Update the docs and test 1559 accordingly -Daniel Stenberg (13 Apr 2023) + Closes #11273 -- ftp: fix 'portsock' variable was assigned the same value +- examples/ftpuploadresume.c: add use of CURLOPT_ACCEPTTIMEOUT_MS - Pointed out by PVS + For show - Ref: #10929 - Closes #10955 + Closes #11277 -- ftp: remove dead code +- examples/unixsocket.c: example using CURLOPT_UNIX_SOCKET_PATH - This condition can never be true here since it is handled already 28 - lines above. + and alternatively CURLOPT_ABSTRACT_UNIX_SOCKET - Pointed out by PVS. + Closes #11276 - Ref: #10929 - Closes #10957 +Anssi Kolehmainen (8 Jun 2023) -- cf-h1-proxy: skip an extra NULL assign +- docs: fix missing parameter names in examples - and use Curl_safefree() once to save another NULL assign. Found by PVS. + Closes #11278 - Ref. #10929 - Closes #10953 +Daniel Stenberg (8 Jun 2023) -Philip Heiduck (13 Apr 2023) +- urlapi: have *set(PATH) prepend a slash if one is missing -- GHA: suppress git clone output + Previously the code would just do that for the path when extracting the + full URL, which made a subsequent curl_url_get() of the path to + (unexpectedly) still return it without the leading path. - Follow-up: https://github.com/curl/curl/commit/8203aa6ed405ec832d2c62f18dfda2 - 93f89a23f9 + Amend lib1560 to verify this. Clarify the curl_url_set() docs about it. - Closes #10949 + Bug: https://curl.se/mail/lib-2023-06/0015.html + Closes #11272 + Reported-by: Pedro Henrique -Stefan Eissing (13 Apr 2023) +Dan Fandrich (7 Jun 2023) -- cf-socket: remove dead code discovered by PVS +- runtests; give each server a unique log lock file - Closes #10960 + Logs are written by several servers and all of them must be finished + writing before the test results can be determined. This means each + server must have its own lock file rather than sharing a single one, + which is how it was done up to now. Previously, the first server to + complete a test would clear the lock before the other server was done, + which caused flaky tests. -Daniel Stenberg (13 Apr 2023) + Lock files are now all found in their own directory, so counting locks + equals counting the files in that directory. The result is that the + proxy logs are now reliably written which actually changes the expected + output for two tests. -- http: skip a double NULL assign + Fixes #11231 + Closes #11259 - and also use a local variable to shorten the long names and increase - readability in the function. Pointed out by PVS. +- runtests: make test file directories in log/N - Ref: #10929 - Closes #10950 + Test files in subdirectories were not created after parallel test log + directories were moved down a level due to a now-bad comparison. -- mime: skip NULL assigns after Curl_safefree() + Follow-up to 92d7dd39 - Pointed out by PVS. + Ref #11264 + Closes #11267 - Ref: #10929 - Closes #10947 +Daniel Stenberg (7 Jun 2023) -- rtsp: skip NULL assigns after Curl_safefree() +- ws: make the curl_ws_meta() return pointer a const - ... since this is a macro that assigns NULL itself. Pointed out by PVS. + The returned info is read-only for the user. - Ref: #10929 - Closes #10946 + Closes #11261 -- smb: remove double assign +- RELEASE-NOTES: synced - The same value is assigned the same value already a few lines above. - Pointed out by PVS. +- runtests: move parallel log dirs from logN to log/N - Ref: #10929 - Closes #10945 + Having several hundreds of them in there gets annoying. -- transfer: skip extra assign + Closes #11264 - The 'result' variable already contains CURLE_OK at this point, no use in - setting it again. Pointed out by PVS. +Dan Fandrich (7 Jun 2023) - Ref: #10929 - Closes #10944 +- test447: move the test file into %LOGDIR -- urlapi: skip a pointless assign +Viktor Szakats (7 Jun 2023) - It stores a null byte after already having confirmed there is a null - byte there. Detected by PVS. +- cmake: add support for "unity" builds - Ref: #10929 - Closes #10943 + Aka "jumbo" or "amalgamation" builds. It means to compile all sources + per target as a single C source. This is experimental. -Philip Heiduck (13 Apr 2023) + You can enable it by passing `-DCMAKE_UNITY_BUILD=ON` to cmake. + It requires CMake 3.16 or newer. -- GHA: suppress git clone output + It makes builds (much) faster, allows for better optimizations and tends + to promote less ambiguous code. - Closes #10939 + Also add a new AppVeyor CI job and convert an existing one to use + "unity" mode (one MSVC, one MinGW), and enable it for one macOS CI job. -Stefan Eissing (13 Apr 2023) + Fix related issues: + - add missing include guard to `easy_lock.h`. + - rename static variables and functions (and a macro) with names reused + across sources, or shadowed by local variables. + - add an `#undef` after use. + - add a missing `#undef` before use. + - move internal definitions from `ftp.h` to `ftp.c`. + - `curl_memory.h` fixes to make it work when included repeatedly. + - stop building/linking curlx bits twice for a static-mode curl tool. + These caused doubly defined symbols in unity builds. + - silence missing extern declarations compiler warning for ` _CRT_glob`. + - fix extern declarations for `tool_freq` and `tool_isVistaOrGreater`. + - fix colliding static symbols in debug mode: `debugtime()` and + `statename`. + - rename `ssl_backend_data` structure to unique names for each + TLS-backend, along with the `ssl_connect_data` struct member + referencing them. This required adding casts for each access. + - add workaround for missing `[P]UNICODE_STRING` types in certain Windows + builds when compiling `lib/ldap.c`. To support "unity" builds, we had + to enable `SCHANNEL_USE_BLACKLISTS` for Schannel (a Windows + `schannel.h` option) _globally_. This caused an indirect inclusion of + Windows `schannel.h` from `ldap.c` via `winldap.h` to have it enabled + as well. This requires `[P]UNICODE_STRING` types, which is apperantly + not defined automatically (as seen with both MSVS and mingw-w64). + This patch includes `` to fix it. + Ref: https://github.com/curl/curl/runs/13987772013 + Ref: https://dev.azure.com/daniel0244/curl/_build/results?buildId=15827&vie + w=logs&jobId=2c9f582d-e278-56b6-4354-f38a4d851906&j=2c9f582d-e278-56b6-4354-f + 38a4d851906&t=90509b00-34fa-5a81-35d7-5ed9569d331c + - tweak unity builds to compile `lib/memdebug.c` separately in memory + trace builds to avoid PP confusion. + - force-disable unity for test programs. + - do not compile and link libcurl sources to libtests _twice_ when libcurl + is built in static mode. -- tests: make test_12_01 a bit more forgiving on connection counts + KNOWN ISSUES: + - running tests with unity builds may fail in cases. + - some build configurations/env may not compile in unity mode. E.g.: + https://ci.appveyor.com/project/curlorg/curl/builds/47230972/job/51wfesgnfu + auwl8q#L250 -- cf-socket: add socket recv buffering for most tcp cases + Ref: https://github.com/libssh2/libssh2/issues/1034 + Ref: https://cmake.org/cmake/help/latest/prop_tgt/UNITY_BUILD.html + Ref: https://en.wikipedia.org/wiki/Unity_build - - use bufq as recv buffer, also for Windows pre-receive handling - - catch small reads followed by larger ones in a single socket - call. A common pattern on TLS connections. + Closes #11095 - Closes #10787 +Daniel Stenberg (7 Jun 2023) -Daniel Stenberg (13 Apr 2023) +- examples/websocket.c: websocket example using CONNECT_ONLY -- urlapi: cleanups + Closes #11262 - - move host checks together - - simplify the scheme parser loop and the end of host name parser - - avoid itermediate buffer storing in multiple places - - reduce scope for several variables - - skip the Curl_dyn_tail() call for speed - - detect IPv6 earlier and skip extra checks for such hosts - - normalize directly in dynbuf instead of itermediate buffer - - split out the IPv6 parser into its own funciton - - call the IPv6 parser directly for ipv6 addresses - - remove (unused) special treatment of % in host names - - junkscan() once in the beginning instead of scattered - - make junkscan return error code - - remove unused query management from dedotdotify() - - make Curl_parse_login_details use memchr - - more use of memchr() instead of strchr() and less strlen() calls - - make junkscan check and return the URL length +- websocket-cb: example doing WebSocket download using callback - An optimized build runs one of my benchmark URL parsing programs ~41% - faster using this branch. (compared against the shipped 7.88.1 library - in Debian) + Very basic - Closes #10935 + Closes #11260 -Josh McCullough (13 Apr 2023) +- test/.gitignore: ignore log* -- http2: fix typo in infof() call +Dan Fandrich (5 Jun 2023) - Closes #10940 +- runtests: document the -j parallel testing option -Daniel Stenberg (12 Apr 2023) + Reported-by: Daniel Stenberg + Ref: #10818 + Closes #11255 -- noproxy: pointer to local array 'hostip' is stored outside scope +- runtests: create multiple test runners when requested - Ref: #10929 - Closes #10933 + Parallel testing is enabled by using a nonzero value for the -j option + to runtests.pl. Performant values seem to be about 7*num CPU cores, or + 1.3*num CPU cores if Valgrind is in use. -Stefan Eissing (12 Apr 2023) + Flaky tests due to improper log locking (bug #11231) are exacerbated + while parallel testing, so it is not enabled by default yet. -- connect: fix https connection setup to treat ssl_mode correctly + Fixes #10818 + Closes #11246 - - for HTTPS protocol, a disabled ssl should never be acceptables. +- runtests: handle repeating tests in multiprocess mode - Closes #10934 + Such as what happens with the --repeat option. Some functions are + changed to pass the runner ID instead of relying on the non-unique test + number. -Douglas R. Reno (12 Apr 2023) + Ref: #10818 -- CMakeLists.txt: fix typo for Haiku detection +- runtests: buffer logmsg while running singletest() - Closes #10937 + This allows all messages relating to a single test case to be displayed + together at the end of the test. -Dan Fandrich (11 Apr 2023) + Ref: #10818 -- pathhelp: use the cached $use_cygpath when available +- runtests: call initserverconfig() in the runner -- runtests: eliminate unneeded variable + This must be done so variables pick up the runner's unique $LOGDIR. -- runtests: make the # of server start attempts a constant + Ref: #10818 -- runtests: on startup failure call displaylogs only in serverfortest +- runtests: use a per-runner random seed - This reduces the number of calls spread throughout the code. + Each runner needs a unique random seed to reduce the chance of port + number collisions. The new scheme uses a consistent per-runner source of + randomness which results in deterministic behaviour, as it did before. Ref: #10818 - Closes #10919 -- runtests: return an error code with startservers() +- runtests: complete main test loop refactor for multiple runners - The code indicates the kind of failure encountered in starting a server, - which can be used by the caller to tailor the user experience. + The main test loop is now able to handle multiple runners, or no + additional runner processes at all. At most one process is still + created, however. Ref: #10818 -- runtests: abort early if runpingpongserver is given a bad server type +- runtests: prepare main test loop for multiple runners -- runtests: don't use the SMB server verification time as reference + Some variables are expanded to arrays and hashes so that multiple + runners can be used for running tests. - %FTPTIME2 and %FTPTIME3 should be set by the FTP server only, for - consistency. + Ref: #10818 -- tests: factor out the test server management code +Stefan Eissing (5 Jun 2023) - This now lives in servers.pm with some configuration variables moved to - globalconfig.pm +- bufq: make write/pass methods more robust - Ref: #10818 + - related to #11242 where curl enters busy loop when + sending http2 data to the server -- runtests: remove an inappropriate use of runclientoutput + Closes #11247 - This function is intended for running client code, not servers. +Boris Verkhovskiy (5 Jun 2023) -- runtests: only add $LIBDIR to the path for checktestcmd +- tool_getparam: fix comment - Since checkcmd is for finding servers, there will never be anything in - this directory of interest to them. + Closes #11253 - Ref: #10818 +Raito Bezarius (5 Jun 2023) -- tests: log sshserver.pl messages to a file +- haproxy: add --haproxy-clientip flag to spoof client IPs - The logmsg messages were thrown away before, so they are now available - for debugging. + CURLOPT_HAPROXY_CLIENT_IP in the library -- runtests: also show DISABLED tests with -l + Closes #10779 - Other reasons for skipping tests are ignored for -l, so being explicitly - disabled should be too. +Daniel Stenberg (5 Jun 2023) -- runtests: move the UNIX sockets into $PIDDIR +- curl: add --ca-native and --proxy-ca-native - These were missed when the other server files were moved there. + These are two boolean options to ask curl to use the native OS's CA + store when verifying TLS servers. For peers and for proxies + respectively. - Follow-up to 70d2fca2 + They currently only have an effect for curl on Windows when built to use + OpenSSL for TLS. - Ref: #10818 + Closes #11049 -- tests: tighten up perl exports +Viktor Szakats (5 Jun 2023) - This reduces namespace pollution a little. +- build: drop unused/redundant `HAVE_WINLDAP_H` - Ref: #10818 + Sources did not use it. Autotools used it when checking for the + `winldap` library, which is redundant. -- tests: turn perl modules into full packages + With CMake, detection was broken: + ``` + Run Build Command(s):/usr/local/Cellar/cmake/3.26.3/bin/cmake -E env VERBOSE= + 1 /usr/bin/make -f Makefile cmTC_2d8fe/fast && /Library/Developer/CommandLine + Tools/usr/bin/make -f CMakeFiles/cmTC_2d8fe.dir/build.make CMakeFiles/cmTC_2 + d8fe.dir/build + Building C object CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj + /usr/local/opt/llvm/bin/clang --target=x86_64-w64-mingw32 --sysroot=/usr/loca + l/opt/mingw-w64/toolchain-x86_64 -D_WINSOCKAPI_="" -I/my/quictls/x64-ucrt/usr + /include -I/my/zlib/x64-ucrt/usr/include -I/my/brotli/x64-ucrt/usr/include -W + no-unused-command-line-argument -D_UCRT -DCURL_HIDDEN_SYMBOLS -DHAVE_SSL_SE + T0_WBIO -DHAS_ALPN -DNGHTTP2_STATICLIB -DNGHTTP3_STATICLIB -DNGTCP2_STATICLIB + -DUSE_MANUAL=1 -fuse-ld=lld -Wl,-s -static-libgcc -lucrt -Wextra -Wall -p + edantic -Wbad-function-cast -Wconversion -Winline -Wmissing-declarations -Wmi + ssing-prototypes -Wnested-externs -Wno-long-long -Wno-multichar -Wpointer-ari + th -Wshadow -Wsign-compare -Wundef -Wunused -Wwrite-strings -Wcast-align -Wde + claration-after-statement -Wempty-body -Wendif-labels -Wfloat-equal -Wignored + -qualifiers -Wno-format-nonliteral -Wno-sign-conversion -Wno-system-headers - + Wstrict-prototypes -Wtype-limits -Wvla -Wshift-sign-overflow -Wshorten-64-to- + 32 -Wdouble-promotion -Wenum-conversion -Wunused-const-variable -Wcomma -Wmis + sing-variable-declarations -Wassign-enum -Wextra-semi-stmt -MD -MT CMakeFile + s/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj -MF CMakeFiles/cmTC_2d8fe.dir/HAVE_WINL + DAP_H.c.obj.d -o CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj -c /my/curl/b + ld-cmake-llvm-x64-shared/CMakeFiles/CMakeScratch/TryCompile-3JP6dR/HAVE_WINLD + AP_H.c + In file included from /my/curl/bld-cmake-llvm-x64-shared/CMakeFiles/CMakeScra + tch/TryCompile-3JP6dR/HAVE_WINLDAP_H.c:2: + In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi + ngw32/include/winldap.h:17: + In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi + ngw32/include/schnlsp.h:9: + In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi + ngw32/include/schannel.h:10: + /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mingw32/include/wincrypt + .h:5041:254: error: unknown type name 'PSYSTEMTIME' + WINIMPM PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate (HCRYPTPROV_OR_ + NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey, PCERT_NAME_BLOB pSubjectIssuerBlob, + DWORD dwFlags, PCRYPT_KEY_PROV_INFO pKeyProvInfo, PCRYPT_ALGORITHM_IDENTIFIER + pSignatureAlgorithm, PSYSTEMTIME pStartTime, PSYSTEMTIME pEndTime, PCERT_EXT + ENSIONS pExtensions); + + + + ^ + /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mingw32/include/wincrypt + .h:5041:278: error: unknown type name 'PSYSTEMTIME' + WINIMPM PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate (HCRYPTPROV_OR_ + NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey, PCERT_NAME_BLOB pSubjectIssuerBlob, + DWORD dwFlags, PCRYPT_KEY_PROV_INFO pKeyProvInfo, PCRYPT_ALGORITHM_IDENTIFIER + pSignatureAlgorithm, PSYSTEMTIME pStartTime, PSYSTEMTIME pEndTime, PCERT_EXT + ENSIONS pExtensions); + + + + ^ + 2 errors generated. + make[1]: *** [CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj] Error 1 + make: *** [cmTC_2d8fe/fast] Error 2 + exitCode: 2 + ``` - This helps enforce more modularization and encapsulation. Enable and fix - warnings on a few packages. Also, rename ftp.pm to processhelp.pm since - there's really nothing ftp-specific in it. + Cherry-picked from #11095 88e4a21ff70ccef391cf99c8165281ff81374503 + Reviewed-by: Daniel Stenberg + Closes #11245 - Ref: #10818 +Daniel Stenberg (5 Jun 2023) -Daniel Stenberg (11 Apr 2023) +- urlapi: scheme starts with alpha -- multi: remove a few superfluous assigns + Add multiple tests to lib1560 to verify - PVS found these "The 'rc' variable was assigned the same value." cases. + Fixes #11249 + Reported-by: ad0p on github + Closes #11250 - Ref: #10929 - Closes #10932 +- RELEASE-NOTES: synced -- schannel: add clarifying comment +- CURLOPT_MAIL_RCPT_ALLOWFAILS: replace CURLOPT_MAIL_RCPT_ALLLOWFAILS - Explaining how the PVS warning in #10929 is wrong: Dereferencing of the - null pointer 'backend->cred' might take place. + Deprecate the name using three Ls and prefer the name with two. - Closes #10931 + Replaces #10047 + Closes #11218 -- cookie: clarify that init with data set to NULL reads no file +- tests/servers: generate temp names in /tmp for unix domain sockets - ... and make Curl_cookie_add() require 'data' being set proper with an - assert. + ... instead of putting them in the regular pid directories because + systems generally have strict length requirements for the path name to + be shorter than 107 bytes and we easily hit that boundary otherwise. - The function has not worked with a NULL data for quite some time so this - just corrects the code and comment. + The new concept generates two random names: one for the socks daemon and + one for http. - This is a different take than the proposed fixed in #10927 + Reported-by: Andy Fiddaman + Fixes #11152 + Closes #11166 - Reported-by: Kvarec Lezki - Ref: #10929 - Closes #10930 +Stefan Eissing (2 Jun 2023) -Kvarec Lezki (11 Apr 2023) +- http2: better support for --limit-rate -- vtls: remove int typecast for sizeof() + - leave transfer loop when --limit-rate is in effect and has + been received + - adjust stream window size to --limit-rate plus some slack + to make the server observe the pacing we want + - add test case to confirm behaviour - V220 Suspicious sequence of types castings: memsize -> 32-bit integer -> - memsize. The value being cast: 'sizeof - (buf->data)'. curl\lib\vtls\vtls.c 2025 + Closes #11115 - https://pvs-studio.com/en/docs/warnings/v220/ +- curl_log: evaluate log statement only when transfer is verbose - Closes #10928 + Closes #11238 -Stefan Eissing (11 Apr 2023) +Daniel Stenberg (2 Jun 2023) -- http2: fix copynpaste error reported by coverity +- libssh2: provide error message when setting host key type fails - - move all code handling HTTP/2 frames for a particular - stream into a separate function to keep from confusing - the call `data` with the stream `data`. + Ref: https://curl.se/mail/archive-2023-06/0001.html - Closes #10924 + Closes #11240 -Dan Fandrich (11 Apr 2023) +Igor Todorovski (2 Jun 2023) -- tests: log a too-long Unix socket path in sws and socksd +- system.h: remove __IBMC__/__IBMCPP__ guards and apply to all z/OS compiles - Ref: #10919 + Closes #11241 -Daniel Stenberg (11 Apr 2023) +Daniel Stenberg (2 Jun 2023) -- gen.pl: error on duplicated See-Also fields +- docs/SECURITY-PROCESS.md: link to example of previous critical flaw - Updated http2.d accordingly. +Mark Seuffert (2 Jun 2023) - Closes #10925 +- README.md: updated link to opencollective -- http2: avoid possible null pointer dereference + Closes #11232 - Reported-by: Dan Fandrich - Fixes #10920 - Closes #10923 +Daniel Stenberg (1 Jun 2023) -- lib1560: verify that more bad host names are rejected +- libssh2: use custom memory functions - when setting the hostname component of a URL + Because of how libssh2_userauth_keyboard_interactive_ex() works: the + libcurl callback allocates memory that is later free()d by libssh2, we + must set the custom memory functions. - Closes #10922 + Reverts 8b5f100db388ee60118c08aa28 -- curl_url_set.3: mention that users can set content rather freely + Ref: https://github.com/libssh2/libssh2/issues/1078 + Closes #11235 - ... which then might render bad URLs if you extract a URL later. +- test447: test PUTting a file that grows - Closes #10921 + ... and have curl trim the end when it reaches the expected total amount + of bytes instead of over-sending. -Dan Fandrich (10 Apr 2023) + Reported-by: JustAnotherArchivist on github + Closes #11223 -- CI: retry failed downloads of aws-lc +- curl: count uploaded data to stop at the originally given size - Don't fail the build in case of a temporary server problem. + Closes #11223 + Fixes #11222 + Reported-by: JustAnotherArchivist on github -- test1169: fix so it works properly everywhere +- tool: remove exclamation marks from error/warning messages - - Use an absolute path for the -L option since the module isn't in the - perl path - - Create the needed test file in a section; isn't - intended for this - - Fix the test number in the file name, which was wrong +- tool: use errorf() for error output - Follow-up to f754990a + Convert a number of fprintf() calls. - Ref: #10818 - Fixes #10889 - Closes #10917 +- tool: remove newlines from all helpf/notef/warnf/errorf calls -- tests: stop using strndup(), which isn't portable + Make voutf() always add one. - It's not available on Solaris 10, for example. Since this is just test - code that doesn't need to use an optimized system version, replace it - with the implementation copied from tool_cb_hdr.c. + Closes #11226 -- runtests: fix an incorrect comment about the ld_preload feature +- tests/servers.pm: pick unused port number with a server socket - Follow-up to 1f631864 + This change replaces the previous method of picking a port number at + random to try to start servers on, then retrying up to ten times with + new random numbers each time, with a function that creates a server + socket on port zero, thereby getting a suitable random port set by the + kernel. That server socket is then closed and that port number is used + to setup the actual test server on. - Ref: #10818 + There is a risk that *another* server can be started on the machine in + the time gap, but the server verification feature will detect that. -Daniel Stenberg (9 Apr 2023) + Closes #11220 -- urlapi: prevent setting invalid schemes with *url_set() +- RELEASE-NOTES: synced - A typical mistake would be to try to set "https://" - including the - separator - this is now rejected as that would then lead to - url_get(... URL...) would get an invalid URL extracted. + bump to 8.2.0 - Extended test 1560 to verify. +Alejandro R. Sedeño (31 May 2023) - Closes #10911 +- configure: fix run-compiler for old /bin/sh -Biswapriyo Nath (9 Apr 2023) + If you try to assign and export on the same line on some older /bin/sh + implementations, it complains: -- http2: remove unused Curl_http2_strerror function declaration + ``` + $ export "NAME=value" + NAME=value: is not an identifier + ``` - Curl_http2_strerror was renamed to http2_strerror in - 05b100aee247bb9bec8e9a1b0 and then http2_strerror was removed in - 5808a0d0f5ea0399d4a2a2 + This commit rewrites run-compiler's assignments and exports to work with + old /bin/sh, splitting assignment and export into two separate + statements, and only quote the value. So now we have: - This also fixes the following compiler error + ``` + NAME="value" + export NAME + ``` - lib/http2.h:41:33: error: unknown type name 'uint32_t' - lib/http2.h:1:1: note: 'uint32_t' is defined in header '' + While we're here, make the same change to the two supporting + assign+export lines preceeding the script to be consistent with how + exports work throughout the rest of configure.ac. - Closes #10912 + Closes #11228 -Daniel Stenberg (8 Apr 2023) +Philip Heiduck (31 May 2023) -- RELEASE-NOTES: synced +- circleci: install impacket & wolfssl 5.6.0 -SuperIlu on github (8 Apr 2023) + Closes #11221 -- config-dos.h: fix SIZEOF_CURL_OFF_T for MS-DOS/DJGPP +Daniel Stenberg (31 May 2023) - Fixes #10905 - Closes #10910 +- tool_urlglob: use curl_off_t instead of longs -Daniel Stenberg (8 Apr 2023) + To handle more globs better (especially on Windows) -- lib: remove CURLX_NO_MEMORY_CALLBACKS + Closes #11224 - The only user of this define was 'chkdecimalpoint' - a special purpose - test tool that was built but not used anymore (since 17c18fbc3 - Apr - 2020). +Dan Fandrich (30 May 2023) - Closes #10908 +- scripts: Fix GHA matrix job detection in cijobs.pl -- CURLPROXY_HTTPS2: for HTTPS proxy that may speak HTTP/2 + The parsing is pretty brittle and it broke detecting some jobs at some + point. Also, detect if Windows is used in GHA. - Setting this proxy type allows curl to negotiate and use HTTP/2 with - HTTPS proxies. +- runtests: abort test run after failure without -a - Closes #10900 + This was broken in a recent refactor and test runs would not stop. -Ali Khodkar (8 Apr 2023) + Follow-up to d4a1b5b6 -- write-out.d: add missing periods + Reported-by: Daniel Stenberg + Fixes #11225 + Closes #11227 - Closes #10897 +Version 8.1.2 (30 May 2023) -Daniel Stenberg (7 Apr 2023) +Daniel Stenberg (30 May 2023) -- http2: remove check for !data after it was already dereferenced +- RELEASE-NOTES: synced - Pointed out by Coverity + 8.1.2 release - Closes #10906 +- THANKS: contributors from 8.1.2 diff --git a/libs/libcurl/docs/THANKS b/libs/libcurl/docs/THANKS index b8e754e4ac..d7e05f07ef 100644 --- a/libs/libcurl/docs/THANKS +++ b/libs/libcurl/docs/THANKS @@ -71,6 +71,7 @@ Alessandro Vesely Alex aka WindEagle Alex Baines Alex Bligh +Alex Bozarth Alex Chan Alex Crichton Alex Fishman @@ -78,6 +79,7 @@ Alex Gaynor Alex Grebenschikov Alex Gruz Alex Kiernan +Alex Klyubin Alex Konev Alex Malinovich Alex Mayorga @@ -111,6 +113,7 @@ Alexandre Ferrieux Alexandre Pion Alexey Borzov Alexey Eremikhin +Alexey Larikov Alexey Melnichuk Alexey Pesternikov Alexey Savchuk @@ -130,6 +133,7 @@ Alona Rossen Amaury Denoyelle amishmm on github Amit Katyal +Ammar Faizi Amol Pattekar Amr Shahin Anatol Belski @@ -227,6 +231,7 @@ Antoni Villalonga Antonio Larrosa Antony74 on github Antti Hätälä +Anubhav Rai apparentorder on github April King arainchik on github @@ -349,6 +354,7 @@ Bob Schader bobmitchell1956 on github Bodo Bergmann Bogdan Nicula +boilingoden Boris Kuschel Boris Okunskiy Boris Rasin @@ -422,6 +428,7 @@ Carlo Cannas Carlo Marcelo Arenas Belón Carlo Teubner Carlo Wood +Carlos Henrique Lima Melara Carlos ORyan Carsten Lange Casey Bodley @@ -437,6 +444,7 @@ Chandrakant Bagul Charles Cazabon Charles Kerr Charles Romestant +Charlie C Chen Prog Cherish98 on github Chester Liu @@ -649,6 +657,7 @@ David Sanderson David Schweikert David Shaw David Strauss +David Suter David Tarendash David Thiel David Walser @@ -780,6 +789,7 @@ Edward Sheldrake Edward Thomson Eelco Dolstra Eetu Ojanen +eeverettrbx on github Egon Eckert Egor Pugin Ehren Bendler @@ -806,8 +816,10 @@ Emiliano Ida Emilio Cobos Álvarez Emilio López Emmanuel Tychon +Enno Boland Enrico Scholz Enrik Berkhan +enWILLYado on github eppesuig Eramoto Masaya Eric Cooper @@ -868,6 +880,7 @@ Fabrice Fontaine Fabrizio Ammollo Fahim Chandurwala Faizur Rahman +Faraz Fallahi Farzin on github Fata Nugraha Fawad Mirza @@ -1048,6 +1061,7 @@ Hao Wu Hardeep Singh Haris Okanovic Harold Stuart +Harry Mallon Harry Sarson Harry Sintonen Harshal Pradhan @@ -1103,6 +1117,8 @@ Ian Lynagh Ian Spence Ian Turner Ian Wilkes +iconoclasthero +icy17 on github Ignacio Vazquez-Abrams Igor Franchuk Igor Khristophorov @@ -1279,6 +1295,7 @@ Jesse Tan jethrogb on github jhoyla on github Jie He +Jiehong on github Jilayne Lovejoy Jim Beveridge Jim Drash @@ -1467,10 +1484,12 @@ Kane York Kang Lin Kang-Jin Lee Kantanat Wannapaka +Kareem Kari Pahula Karl Chen Karl Moerder Karol Pietrzak +Kartatz on Github Karthikdasari0423 Karthikdasari0423 on github Kartik Mahajan @@ -1512,6 +1531,7 @@ Kim Minjoong Kim Rinnewitz Kim Vandry Kimmo Kinnunen +kirbyn17 on hackerone Kirill Efimov Kirill Marchuk Kjell Ericson @@ -1570,6 +1590,7 @@ Lars J. Aas Lars Johannesen Lars Nilsson Lars Torben Wilson +Lau Laurent Bonnans Laurent Dufresne Laurent Rabret @@ -1615,15 +1636,18 @@ Litter White Liviu Chircu Liza Alenchery lizhuang0630 on github +lkordos on github lllaffer on github Lloyd Fournier Lluís Batlle i Rossell locpyl-tidnyd on github Loganaden Velvindron Loic Dachary +LoRd_MuldeR Loren Kirkby Lorenzo Miniero Loïc Yhuel +lRoccoon on github Luan Cestari Luca Altea Luca Boccassi @@ -1667,6 +1691,7 @@ Maksim Arhipov Maksim Kuzevanov Maksim Sciepanienka Maksim Stsepanenka +Maksymilian Arciemowicz Malik Idrees Hasan Khan Mamoru Tasaka Mamta Upadhyay @@ -1693,6 +1718,7 @@ Marcelo Juchem Marcin Adamski Marcin Gryszkalis Marcin Konicki +Marcin Rataj Marco Deckel Marco G. Salvagno Marco Kamner @@ -1756,6 +1782,7 @@ Martin Jansen Martin Kammerhofer Martin Kepplinger Martin Lemke +Martin Schmatz Martin Skinner Martin Staael Martin Storsjö @@ -1995,6 +2022,7 @@ Nick Zitzmann nick-telia on github Nicklas Avén Nico Baggus +Nico Rieck nico-abram on github Nicolas Berloquin Nicolas Croiset @@ -2018,6 +2046,7 @@ nimaje on github niner on github Ning Dong Nir Soffer +Niracler Li Niranjan Hasabnis Nis Jorgensen nk @@ -2037,6 +2066,7 @@ Nuru on github Octavio Schroeder odek86 on github Ofer +ohyeaah on github Okhin Vasilij Ola Mork Olaf Flebbe @@ -2063,6 +2093,7 @@ omau on github Ondřej Koláček opensignature on github opensslonzos-github on github +Ophir Lojkine Orange Tsai Oren Souroujon Oren Tirosh @@ -2346,6 +2377,7 @@ Ricky-Tigg on github Rider Linden RiderALT on github Rikard Falkeborn +rilysh rl1987 on github Rob Boeckermann Rob Cotrone @@ -2373,6 +2405,7 @@ Robert Prag Robert Ronto Robert Schumann Robert Simpson +Robert Southee Robert Weaver Robert Wruck Robin A. Meade @@ -2448,6 +2481,7 @@ Salvador Dávila Salvatore Sorrentino Sam Deane Sam Hurst +Sam James Sam Roth Sam Schanken Samanta Navarro @@ -2482,6 +2516,7 @@ Scott Barrett Scott Cantor Scott Davis Scott McCreary +sd0 on hackerone Sean Boudreau Sean Burford Sean MacLennan @@ -2559,10 +2594,12 @@ Simon Warta simplerobot on github Siva Sivaraman SLDiggie on github +Smackd0wn Smackd0wn on github smuellerDD on github sn on hackerone sofaboss on github +Sohom Datta Somnath Kundu Song Ma Sonia Subramanian @@ -2629,6 +2666,7 @@ Steve Marx Steve Oliphant Steve Roskowski Steve Walch +Steven Allen Steven Bazyl Steven G. Johnson Steven Gu @@ -2714,6 +2752,7 @@ Tim Chen Tim Costello Tim Harder Tim Heckman +Tim Hill Tim Mcdonough Tim Newsome Tim Rühsen @@ -2793,6 +2832,7 @@ tonystz on Github Toon Verwaest Tor Arntsen Torben Dannhauer +Torben Dury Torsten Foertsch Toshio Kuratomi Toshiyuki Maezawa @@ -2809,6 +2849,7 @@ Tseng Jun Tuomas Siipola Tuomo Rinne Tupone Alfredo +Turiiya Tyler Hall Török Edwin u20221022 on github @@ -2976,6 +3017,7 @@ Zhang Xiuhua zhanghu on xiaomi Zhao Yisha Zhaoyang Wu +zhengqwe on github Zhibiao Wu zhihaoy on github Zhouyihai Ding diff --git a/libs/libcurl/include/curl/curl.h b/libs/libcurl/include/curl/curl.h index 05c90b7ce3..1f6c5764c6 100644 --- a/libs/libcurl/include/curl/curl.h +++ b/libs/libcurl/include/curl/curl.h @@ -53,28 +53,19 @@ #include "curlver.h" /* libcurl version defines */ #include "system.h" /* determine things run-time */ -/* - * Define CURL_WIN32 when build target is Win32 API - */ - -#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && \ - !defined(__SYMBIAN32__) -#define CURL_WIN32 -#endif - #include #include -#if (defined(__FreeBSD__) && (__FreeBSD__ >= 2)) || defined(__MidnightBSD__) +#if defined(__FreeBSD__) || defined(__MidnightBSD__) /* Needed for __FreeBSD_version or __MidnightBSD_version symbol definition */ -#include +#include #endif /* The include stuff here below is mainly for time_t! */ #include #include -#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) #if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) /* The check above prevents the winsock2 inclusion if winsock.h already was @@ -88,7 +79,7 @@ libc5-based Linux systems. Only include it on systems that are known to require it! */ #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ - defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(__minix) || defined(__INTEGRITY) || \ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \ (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \ @@ -97,11 +88,11 @@ #include #endif -#if !defined(CURL_WIN32) && !defined(_WIN32_WCE) +#if !defined(_WIN32) && !defined(_WIN32_WCE) #include #endif -#if !defined(CURL_WIN32) +#if !defined(_WIN32) #include #endif @@ -128,7 +119,7 @@ typedef void CURLSH; #ifdef CURL_STATICLIB # define CURL_EXTERN -#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \ +#elif defined(_WIN32) || \ (__has_declspec_attribute(dllexport) && \ __has_declspec_attribute(dllimport)) # if defined(BUILDING_LIBCURL) @@ -144,7 +135,7 @@ typedef void CURLSH; #ifndef curl_socket_typedef /* socket typedef */ -#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +#if defined(_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) typedef SOCKET curl_socket_t; #define CURL_SOCKET_BAD INVALID_SOCKET #else @@ -3220,6 +3211,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); #include "options.h" #include "header.h" #include "websockets.h" +#include "mprintf.h" /* the typechecker doesn't work in C++ (yet) */ #if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ diff --git a/libs/libcurl/include/curl/curlver.h b/libs/libcurl/include/curl/curlver.h index 7d64b35c92..e54a5e6138 100644 --- a/libs/libcurl/include/curl/curlver.h +++ b/libs/libcurl/include/curl/curlver.h @@ -32,12 +32,12 @@ /* This is the version number of the libcurl package from which this header file origins: */ -#define LIBCURL_VERSION "8.4.0" +#define LIBCURL_VERSION "8.5.0" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 8 -#define LIBCURL_VERSION_MINOR 4 +#define LIBCURL_VERSION_MINOR 5 #define LIBCURL_VERSION_PATCH 0 /* This is the numeric version of the libcurl version number, meant for easier @@ -59,7 +59,7 @@ CURL_VERSION_BITS() macro since curl's own configure script greps for it and needs it to contain the full number. */ -#define LIBCURL_VERSION_NUM 0x080400 +#define LIBCURL_VERSION_NUM 0x080500 /* * This is the date and time when the full source package was created. The @@ -70,7 +70,7 @@ * * "2007-11-23" */ -#define LIBCURL_TIMESTAMP "2023-10-11" +#define LIBCURL_TIMESTAMP "2023-12-06" #define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z)) #define CURL_AT_LEAST_VERSION(x,y,z) \ diff --git a/libs/libcurl/include/curl/system.h b/libs/libcurl/include/curl/system.h index 9a32e26d63..40044a4ee3 100644 --- a/libs/libcurl/include/curl/system.h +++ b/libs/libcurl/include/curl/system.h @@ -141,29 +141,6 @@ # define CURL_TYPEOF_CURL_SOCKLEN_T int # endif -#elif defined(__SYMBIAN32__) -# if defined(__EABI__) /* Treat all ARM compilers equally */ -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# elif defined(__CW32__) -# pragma longlong on -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# elif defined(__VC32__) -# define CURL_TYPEOF_CURL_OFF_T __int64 -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int - #elif defined(macintosh) # include # if TYPE_LONGLONG @@ -201,9 +178,10 @@ # define CURL_TYPEOF_CURL_SOCKLEN_T int #elif defined(__MINGW32__) +# include # define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "I64d" -# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_FORMAT_CURL_OFF_T PRId64 +# define CURL_FORMAT_CURL_OFF_TU PRIu64 # define CURL_SUFFIX_CURL_OFF_T LL # define CURL_SUFFIX_CURL_OFF_TU ULL # define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t @@ -370,7 +348,14 @@ /* ===================================== */ #elif defined(_MSC_VER) -# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# if (_MSC_VER >= 1800) +# include +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T PRId64 +# define CURL_FORMAT_CURL_OFF_TU PRIu64 +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# elif (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) # define CURL_TYPEOF_CURL_OFF_T __int64 # define CURL_FORMAT_CURL_OFF_T "I64d" # define CURL_FORMAT_CURL_OFF_TU "I64u" diff --git a/libs/libcurl/src/CMakeLists.txt b/libs/libcurl/src/CMakeLists.txt index 283488e935..dd0e8dfe1a 100644 --- a/libs/libcurl/src/CMakeLists.txt +++ b/libs/libcurl/src/CMakeLists.txt @@ -47,20 +47,25 @@ if(USE_ARES) include_directories(${CARES_INCLUDE_DIR}) endif() -add_library( - curlu # special libcurlu library just for unittests - STATIC - EXCLUDE_FROM_ALL - ${HHEADERS} ${CSOURCES} -) -target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB) +if(BUILD_TESTING) + add_library( + curlu # special libcurlu library just for unittests + STATIC + EXCLUDE_FROM_ALL + ${HHEADERS} ${CSOURCES} + ) + target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB) +endif() if(ENABLE_CURLDEBUG) # We must compile these sources separately to avoid memdebug.h redefinitions # applying to them. set_source_files_properties(memdebug.c curl_multibyte.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) endif() -target_link_libraries(curlu PRIVATE ${CURL_LIBS}) + +if(BUILD_TESTING) + target_link_libraries(curlu PRIVATE ${CURL_LIBS}) +endif() transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake") include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake) diff --git a/libs/libcurl/src/Makefile.am b/libs/libcurl/src/Makefile.am index cbc3487e80..5cab1cc00f 100644 --- a/libs/libcurl/src/Makefile.am +++ b/libs/libcurl/src/Makefile.am @@ -110,7 +110,7 @@ libcurl_la_CFLAGS_EXTRA += $(CFLAG_CURL_SYMBOL_HIDING) endif libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA) -libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS) +libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(CURL_LDFLAGS_LIB) $(LIBCURL_LIBS) libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA) libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in index 4d75b419c9..3beb50dc1f 100644 --- a/libs/libcurl/src/Makefile.in +++ b/libs/libcurl/src/Makefile.in @@ -1486,7 +1486,7 @@ libcurl_la_LDFLAGS_EXTRA = $(am__append_1) $(am__append_2) \ $(am__append_3) $(am__append_4) $(am__append_5) libcurl_la_CFLAGS_EXTRA = $(am__append_9) libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA) -libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS) +libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(CURL_LDFLAGS_LIB) $(LIBCURL_LIBS) libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA) libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS) diff --git a/libs/libcurl/src/altsvc.c b/libs/libcurl/src/altsvc.c index ce2324a3d0..13d4f11b71 100644 --- a/libs/libcurl/src/altsvc.c +++ b/libs/libcurl/src/altsvc.c @@ -97,7 +97,7 @@ static struct altsvc *altsvc_createid(const char *srchost, unsigned int srcport, unsigned int dstport) { - struct altsvc *as = calloc(sizeof(struct altsvc), 1); + struct altsvc *as = calloc(1, sizeof(struct altsvc)); size_t hlen; size_t dlen; if(!as) @@ -123,15 +123,13 @@ static struct altsvc *altsvc_createid(const char *srchost, dlen -= 2; } - as->src.host = Curl_memdup(srchost, hlen + 1); + as->src.host = Curl_strndup(srchost, hlen); if(!as->src.host) goto error; - as->src.host[hlen] = 0; - as->dst.host = Curl_memdup(dsthost, dlen + 1); + as->dst.host = Curl_strndup(dsthost, dlen); if(!as->dst.host) goto error; - as->dst.host[dlen] = 0; as->src.alpnid = srcalpnid; as->dst.alpnid = dstalpnid; @@ -301,7 +299,7 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp) */ struct altsvcinfo *Curl_altsvc_init(void) { - struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1); + struct altsvcinfo *asi = calloc(1, sizeof(struct altsvcinfo)); if(!asi) return NULL; Curl_llist_init(&asi->list, NULL); diff --git a/libs/libcurl/src/arpa_telnet.h b/libs/libcurl/src/arpa_telnet.h index b1348a2447..85f739f414 100644 --- a/libs/libcurl/src/arpa_telnet.h +++ b/libs/libcurl/src/arpa_telnet.h @@ -56,12 +56,14 @@ static const char * const telnetoptions[]= "TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON" }; +#define CURL_TELOPT(x) telnetoptions[x] +#else +#define CURL_TELOPT(x) "" #endif #define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON #define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM) -#define CURL_TELOPT(x) telnetoptions[x] #define CURL_NTELOPTS 40 @@ -103,7 +105,12 @@ static const char * const telnetcmds[]= #define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \ ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) ) + +#ifndef CURL_DISABLE_VERBOSE_STRINGS #define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM] +#else +#define CURL_TELCMD(x) "" +#endif #endif /* CURL_DISABLE_TELNET */ diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c index ffb4ecd367..f13ccb36cb 100644 --- a/libs/libcurl/src/asyn-ares.c +++ b/libs/libcurl/src/asyn-ares.c @@ -60,13 +60,13 @@ #include "progress.h" #include "timediff.h" -# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ - defined(WIN32) -# define CARES_STATICLIB -# endif -# include -# include /* really old c-ares didn't include this by - itself */ +#if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ + defined(_WIN32) +# define CARES_STATICLIB +#endif +#include +#include /* really old c-ares didn't include this by + itself */ #if ARES_VERSION >= 0x010500 /* c-ares 1.5.0 or later, the callback proto is modified */ @@ -228,9 +228,9 @@ static void destroy_async_data(struct Curl_async *async); void Curl_resolver_cancel(struct Curl_easy *data) { DEBUGASSERT(data); - if(data->state.async.resolver) - ares_cancel((ares_channel)data->state.async.resolver); - destroy_async_data(&data->state.async); + if(data->conn->resolve_async.resolver) + ares_cancel((ares_channel)data->conn->resolve_async.resolver); + destroy_async_data(&data->conn->resolve_async); } /* @@ -278,14 +278,14 @@ int Curl_resolver_getsock(struct Curl_easy *data, struct timeval timebuf; struct timeval *timeout; long milli; - int max = ares_getsock((ares_channel)data->state.async.resolver, + int max = ares_getsock((ares_channel)data->conn->resolve_async.resolver, (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE); maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; maxtime.tv_usec = 0; - timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime, - &timebuf); + timeout = ares_timeout((ares_channel)data->conn->resolve_async.resolver, + &maxtime, &timebuf); milli = (long)curlx_tvtoms(timeout); if(milli == 0) milli += 10; @@ -313,8 +313,8 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) int i; int num = 0; - bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks, - ARES_GETSOCK_MAXNUM); + bitmask = ares_getsock((ares_channel)data->conn->resolve_async.resolver, + socks, ARES_GETSOCK_MAXNUM); for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) { pfd[i].events = 0; @@ -344,12 +344,12 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) if(!nfds) /* Call ares_process() unconditionally here, even if we simply timed out above, as otherwise the ares name resolve won't timeout! */ - ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD, - ARES_SOCKET_BAD); + ares_process_fd((ares_channel)data->conn->resolve_async.resolver, + ARES_SOCKET_BAD, ARES_SOCKET_BAD); else { /* move through the descriptors and ask for processing on them */ for(i = 0; i < num; i++) - ares_process_fd((ares_channel)data->state.async.resolver, + ares_process_fd((ares_channel)data->conn->resolve_async.resolver, (pfd[i].revents & (POLLRDNORM|POLLIN))? pfd[i].fd:ARES_SOCKET_BAD, (pfd[i].revents & (POLLWRNORM|POLLOUT))? @@ -368,7 +368,7 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dns) { - struct thread_data *res = data->state.async.tdata; + struct thread_data *res = data->conn->resolve_async.tdata; CURLcode result = CURLE_OK; DEBUGASSERT(dns); @@ -397,7 +397,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, ARES_ECANCELLED synchronously for all pending responses. This will leave us with res->num_pending == 0, which is perfect for the next block. */ - ares_cancel((ares_channel)data->state.async.resolver); + ares_cancel((ares_channel)data->conn->resolve_async.resolver); DEBUGASSERT(res->num_pending == 0); } #endif @@ -408,12 +408,12 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, them */ res->temp_ai = NULL; - if(!data->state.async.dns) + if(!data->conn->resolve_async.dns) result = Curl_resolver_error(data); else - *dns = data->state.async.dns; + *dns = data->conn->resolve_async.dns; - destroy_async_data(&data->state.async); + destroy_async_data(&data->conn->resolve_async); } return result; @@ -464,7 +464,8 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, store.tv_sec = itimeout/1000; store.tv_usec = (itimeout%1000)*1000; - tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv); + tvp = ares_timeout((ares_channel)data->conn->resolve_async.resolver, + &store, &tv); /* use the timeout period ares returned to us above if less than one second is left, otherwise just use 1000ms to make sure the progress @@ -478,7 +479,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, return CURLE_UNRECOVERABLE_POLL; result = Curl_resolver_is_resolved(data, entry); - if(result || data->state.async.done) + if(result || data->conn->resolve_async.done) break; if(Curl_pgrsUpdate(data)) @@ -499,12 +500,12 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, } if(result) /* failure, so we cancel the ares operation */ - ares_cancel((ares_channel)data->state.async.resolver); + ares_cancel((ares_channel)data->conn->resolve_async.resolver); /* Operation complete, if the lookup was successful we now have the entry in the cache. */ if(entry) - *entry = data->state.async.dns; + *entry = data->conn->resolve_async.dns; if(result) /* close the connection, since we can't return failure here without @@ -571,12 +572,13 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ be valid so only defer it when we know the 'status' says its fine! */ return; - res = data->state.async.tdata; + res = data->conn->resolve_async.tdata; if(res) { res->num_pending--; if(CURL_ASYNC_SUCCESS == status) { - struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port); + struct Curl_addrinfo *ai = Curl_he2ai(hostent, + data->conn->resolve_async.port); if(ai) { compound_results(res, ai); } @@ -727,14 +729,16 @@ static void addrinfo_cb(void *arg, int status, int timeouts, struct ares_addrinfo *result) { struct Curl_easy *data = (struct Curl_easy *)arg; - struct thread_data *res = data->state.async.tdata; - (void)timeouts; - if(ARES_SUCCESS == status) { - res->temp_ai = ares2addr(result->nodes); - res->last_status = CURL_ASYNC_SUCCESS; - ares_freeaddrinfo(result); + if(data->conn) { + struct thread_data *res = data->conn->resolve_async.tdata; + (void)timeouts; + if(ARES_SUCCESS == status) { + res->temp_ai = ares2addr(result->nodes); + res->last_status = CURL_ASYNC_SUCCESS; + ares_freeaddrinfo(result); + } + res->num_pending--; } - res->num_pending--; } #endif @@ -755,15 +759,15 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, size_t namelen = strlen(hostname); *waitp = 0; /* default to synchronous response */ - res = calloc(sizeof(struct thread_data) + namelen, 1); + res = calloc(1, sizeof(struct thread_data) + namelen); if(res) { strcpy(res->hostname, hostname); - data->state.async.hostname = res->hostname; - data->state.async.port = port; - data->state.async.done = FALSE; /* not done */ - data->state.async.status = 0; /* clear */ - data->state.async.dns = NULL; /* clear */ - data->state.async.tdata = res; + data->conn->resolve_async.hostname = res->hostname; + data->conn->resolve_async.port = port; + data->conn->resolve_async.done = FALSE; /* not done */ + data->conn->resolve_async.status = 0; /* clear */ + data->conn->resolve_async.dns = NULL; /* clear */ + data->conn->resolve_async.tdata = res; /* initial status - failed */ res->last_status = ARES_ENOTFOUND; @@ -793,8 +797,8 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, hints.ai_flags = ARES_AI_NUMERICSERV; msnprintf(service, sizeof(service), "%d", port); res->num_pending = 1; - ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname, - service, &hints, addrinfo_cb, data); + ares_getaddrinfo((ares_channel)data->conn->resolve_async.resolver, + hostname, service, &hints, addrinfo_cb, data); } #else @@ -804,10 +808,10 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, res->num_pending = 2; /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, - PF_INET, query_completed_cb, data); - ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, - PF_INET6, query_completed_cb, data); + ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver, + hostname, PF_INET, query_completed_cb, data); + ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver, + hostname, PF_INET6, query_completed_cb, data); } else #endif @@ -815,7 +819,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, res->num_pending = 1; /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.async.resolver, + ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver, hostname, PF_INET, query_completed_cb, data); } @@ -829,6 +833,7 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers) { CURLcode result = CURLE_NOT_BUILT_IN; + ares_channel channel, lchannel = NULL; int ares_result; /* If server is NULL or empty, this would purge all DNS servers @@ -841,11 +846,23 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, return CURLE_OK; #ifdef HAVE_CARES_SERVERS_CSV + if(data->conn) + channel = data->conn->resolve_async.resolver; + else { + /* we are called by setopt on a data without a connection (yet). In that + * case we set the value on a local instance for checking. + * The configured data options are set when the connection for this + * transfer is created. */ + result = Curl_resolver_init(data, (void **)&lchannel); + if(result) + goto out; + channel = lchannel; + } + #ifdef HAVE_CARES_PORTS_CSV - ares_result = ares_set_servers_ports_csv(data->state.async.resolver, - servers); + ares_result = ares_set_servers_ports_csv(channel, servers); #else - ares_result = ares_set_servers_csv(data->state.async.resolver, servers); + ares_result = ares_set_servers_csv(channel, servers); #endif switch(ares_result) { case ARES_SUCCESS: @@ -861,6 +878,9 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, result = CURLE_BAD_FUNCTION_ARGUMENT; break; } +out: + if(lchannel) + Curl_resolver_cleanup(lchannel); #else /* too old c-ares version! */ (void)data; (void)(ares_result); @@ -872,11 +892,14 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data, const char *interf) { #ifdef HAVE_CARES_LOCAL_DEV - if(!interf) - interf = ""; - - ares_set_local_dev((ares_channel)data->state.async.resolver, interf); + if(data->conn) { + /* not a setopt test run, set the value */ + if(!interf) + interf = ""; + ares_set_local_dev((ares_channel)data->conn->resolve_async.resolver, + interf); + } return CURLE_OK; #else /* c-ares version too old! */ (void)data; @@ -900,8 +923,11 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, } } - ares_set_local_ip4((ares_channel)data->state.async.resolver, - ntohl(a4.s_addr)); + if(data->conn) { + /* not a setopt test run, set the value */ + ares_set_local_ip4((ares_channel)data->conn->resolve_async.resolver, + ntohl(a4.s_addr)); + } return CURLE_OK; #else /* c-ares version too old! */ @@ -927,7 +953,10 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, } } - ares_set_local_ip6((ares_channel)data->state.async.resolver, a6); + if(data->conn) { + /* not a setopt test run, set the value */ + ares_set_local_ip6((ares_channel)data->conn->resolve_async.resolver, a6); + } return CURLE_OK; #else /* c-ares version too old! */ diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c index 5019fa44d9..493f009e34 100644 --- a/libs/libcurl/src/asyn-thread.c +++ b/libs/libcurl/src/asyn-thread.c @@ -136,7 +136,7 @@ static void destroy_async_data(struct Curl_async *); */ void Curl_resolver_cancel(struct Curl_easy *data) { - destroy_async_data(&data->state.async); + destroy_async_data(&data->conn->resolve_async); } /* This function is used to init a threaded resolve */ @@ -173,7 +173,7 @@ struct thread_data { static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data) { - return &(data->state.async.tdata->tsd); + return &(data->conn->resolve_async.tdata->tsd); } /* Destroy resolver thread synchronization data */ @@ -196,7 +196,7 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd) * the other end (for reading) is always closed in the parent thread. */ if(tsd->sock_pair[1] != CURL_SOCKET_BAD) { - sclose(tsd->sock_pair[1]); + wakeup_close(tsd->sock_pair[1]); } #endif memset(tsd, 0, sizeof(*tsd)); @@ -233,8 +233,8 @@ int init_thread_sync_data(struct thread_data *td, Curl_mutex_init(tsd->mtx); #ifndef CURL_DISABLE_SOCKETPAIR - /* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */ - if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) { + /* create socket pair or pipe */ + if(wakeup_create(&tsd->sock_pair[0]) < 0) { tsd->sock_pair[0] = CURL_SOCKET_BAD; tsd->sock_pair[1] = CURL_SOCKET_BAD; goto err_exit; @@ -254,7 +254,7 @@ int init_thread_sync_data(struct thread_data *td, err_exit: #ifndef CURL_DISABLE_SOCKETPAIR if(tsd->sock_pair[0] != CURL_SOCKET_BAD) { - sclose(tsd->sock_pair[0]); + wakeup_close(tsd->sock_pair[0]); tsd->sock_pair[0] = CURL_SOCKET_BAD; } #endif @@ -320,7 +320,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) if(tsd->sock_pair[1] != CURL_SOCKET_BAD) { /* DNS has been resolved, signal client task */ buf[0] = 1; - if(swrite(tsd->sock_pair[1], buf, sizeof(buf)) < 0) { + if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) { /* update sock_erro to errno */ tsd->sock_error = SOCKERRNO; } @@ -428,9 +428,9 @@ static bool init_resolve_thread(struct Curl_easy *data, { struct thread_data *td = calloc(1, sizeof(struct thread_data)); int err = ENOMEM; - struct Curl_async *asp = &data->state.async; + struct Curl_async *asp = &data->conn->resolve_async; - data->state.async.tdata = td; + data->conn->resolve_async.tdata = td; if(!td) goto errno_exit; @@ -488,7 +488,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data, CURLcode result = CURLE_OK; DEBUGASSERT(data); - td = data->state.async.tdata; + td = data->conn->resolve_async.tdata; DEBUGASSERT(td); DEBUGASSERT(td->thread_hnd != curl_thread_t_null); @@ -500,18 +500,18 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data, else DEBUGASSERT(0); - data->state.async.done = TRUE; + data->conn->resolve_async.done = TRUE; if(entry) - *entry = data->state.async.dns; + *entry = data->conn->resolve_async.dns; - if(!data->state.async.dns && report) + if(!data->conn->resolve_async.dns && report) /* a name was not resolved, report error */ result = Curl_resolver_error(data); - destroy_async_data(&data->state.async); + destroy_async_data(&data->conn->resolve_async); - if(!data->state.async.dns && report) + if(!data->conn->resolve_async.dns && report) connclose(data->conn, "asynch resolve failed"); return result; @@ -524,7 +524,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data, */ void Curl_resolver_kill(struct Curl_easy *data) { - struct thread_data *td = data->state.async.tdata; + struct thread_data *td = data->conn->resolve_async.tdata; /* If we're still resolving, we must wait for the threads to fully clean up, unfortunately. Otherwise, we can simply cancel to clean up any resolver @@ -563,7 +563,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **entry) { - struct thread_data *td = data->state.async.tdata; + struct thread_data *td = data->conn->resolve_async.tdata; int done = 0; DEBUGASSERT(entry); @@ -581,13 +581,13 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, if(done) { getaddrinfo_complete(data); - if(!data->state.async.dns) { + if(!data->conn->resolve_async.dns) { CURLcode result = Curl_resolver_error(data); - destroy_async_data(&data->state.async); + destroy_async_data(&data->conn->resolve_async); return result; } - destroy_async_data(&data->state.async); - *entry = data->state.async.dns; + destroy_async_data(&data->conn->resolve_async); + *entry = data->conn->resolve_async.dns; } else { /* poll for name lookup done with exponential backoff up to 250ms */ @@ -619,9 +619,9 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks) int ret_val = 0; timediff_t milli; timediff_t ms; - struct resdata *reslv = (struct resdata *)data->state.async.resolver; + struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver; #ifndef CURL_DISABLE_SOCKETPAIR - struct thread_data *td = data->state.async.tdata; + struct thread_data *td = data->conn->resolve_async.tdata; #else (void)socks; #endif @@ -662,7 +662,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, int port, int *waitp) { - struct resdata *reslv = (struct resdata *)data->state.async.resolver; + struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver; *waitp = 0; /* default to synchronous response */ @@ -691,7 +691,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, { struct addrinfo hints; int pf = PF_INET; - struct resdata *reslv = (struct resdata *)data->state.async.resolver; + struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver; *waitp = 0; /* default to synchronous response */ diff --git a/libs/libcurl/src/base64.c b/libs/libcurl/src/base64.c index 1244677cb0..739c26f24b 100644 --- a/libs/libcurl/src/base64.c +++ b/libs/libcurl/src/base64.c @@ -31,6 +31,7 @@ !defined(CURL_DISABLE_SMTP) || \ !defined(CURL_DISABLE_POP3) || \ !defined(CURL_DISABLE_IMAP) || \ + !defined(CURL_DISABLE_DIGEST_AUTH) || \ !defined(CURL_DISABLE_DOH) || defined(USE_SSL) || defined(BUILDING_CURL) #include "curl/curl.h" #include "warnless.h" diff --git a/libs/libcurl/src/c-hyper.c b/libs/libcurl/src/c-hyper.c index 74adf4e44b..efb534ccad 100644 --- a/libs/libcurl/src/c-hyper.c +++ b/libs/libcurl/src/c-hyper.c @@ -22,6 +22,10 @@ * ***************************************************************************/ +/* Curl's integration with Hyper. This replaces certain functions in http.c, + * based on configuration #defines. This implementation supports HTTP/1.1 but + * not HTTP/2. + */ #include "curl_setup.h" #if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) @@ -172,17 +176,15 @@ static int hyper_each_header(void *userdata, Curl_debug(data, CURLINFO_HEADER_IN, headp, len); - if(!data->state.hconnect || !data->set.suppress_connect_headers) { - writetype = CLIENTWRITE_HEADER; - if(data->state.hconnect) - writetype |= CLIENTWRITE_CONNECT; - if(data->req.httpcode/100 == 1) - writetype |= CLIENTWRITE_1XX; - result = Curl_client_write(data, writetype, headp, len); - if(result) { - data->state.hresult = CURLE_ABORTED_BY_CALLBACK; - return HYPER_ITER_BREAK; - } + writetype = CLIENTWRITE_HEADER; + if(data->state.hconnect) + writetype |= CLIENTWRITE_CONNECT; + if(data->req.httpcode/100 == 1) + writetype |= CLIENTWRITE_1XX; + result = Curl_client_write(data, writetype, headp, len); + if(result) { + data->state.hresult = CURLE_ABORTED_BY_CALLBACK; + return HYPER_ITER_BREAK; } result = Curl_bump_headersize(data, len, FALSE); @@ -201,7 +203,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) struct SingleRequest *k = &data->req; CURLcode result = CURLE_OK; - if(0 == k->bodywrites++) { + if(0 == k->bodywrites) { bool done = FALSE; #if defined(USE_NTLM) struct connectdata *conn = data->conn; @@ -241,11 +243,6 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) return HYPER_ITER_BREAK; } } - if(k->ignorebody) - return HYPER_ITER_CONTINUE; - if(0 == len) - return HYPER_ITER_CONTINUE; - Curl_debug(data, CURLINFO_DATA_IN, buf, len); result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len); if(result) { @@ -253,12 +250,6 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) return HYPER_ITER_BREAK; } - data->req.bytecount += len; - result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount); - if(result) { - data->state.hresult = result; - return HYPER_ITER_BREAK; - } return HYPER_ITER_CONTINUE; } @@ -310,13 +301,14 @@ static CURLcode status_line(struct Curl_easy *data, Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb), len); - if(!data->state.hconnect || !data->set.suppress_connect_headers) { - writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS; - result = Curl_client_write(data, writetype, - Curl_dyn_ptr(&data->state.headerb), len); - if(result) - return result; - } + writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS; + if(data->state.hconnect) + writetype |= CLIENTWRITE_CONNECT; + result = Curl_client_write(data, writetype, + Curl_dyn_ptr(&data->state.headerb), len); + if(result) + return result; + result = Curl_bump_headersize(data, len, FALSE); return result; } @@ -551,11 +543,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, static CURLcode debug_request(struct Curl_easy *data, const char *method, - const char *path, - bool h2) + const char *path) { - char *req = aprintf("%s %s HTTP/%s\r\n", method, path, - h2?"2":"1.1"); + char *req = aprintf("%s %s HTTP/1.1\r\n", method, path); if(!req) return CURLE_OUT_OF_MEMORY; Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req)); @@ -637,7 +627,6 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers, static CURLcode request_target(struct Curl_easy *data, struct connectdata *conn, const char *method, - bool h2, hyper_request *req) { CURLcode result; @@ -649,26 +638,13 @@ static CURLcode request_target(struct Curl_easy *data, if(result) return result; - if(h2 && hyper_request_set_uri_parts(req, - /* scheme */ - (uint8_t *)data->state.up.scheme, - strlen(data->state.up.scheme), - /* authority */ - (uint8_t *)conn->host.name, - strlen(conn->host.name), - /* path_and_query */ - (uint8_t *)Curl_dyn_uptr(&r), - Curl_dyn_len(&r))) { - failf(data, "error setting uri parts to hyper"); - result = CURLE_OUT_OF_MEMORY; - } - else if(!h2 && hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r), + if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r), Curl_dyn_len(&r))) { failf(data, "error setting uri to hyper"); result = CURLE_OUT_OF_MEMORY; } else - result = debug_request(data, method, Curl_dyn_ptr(&r), h2); + result = debug_request(data, method, Curl_dyn_ptr(&r)); Curl_dyn_free(&r); @@ -899,7 +875,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) const char *p_accept; /* Accept: string */ const char *method; Curl_HttpReq httpreq; - bool h2 = FALSE; const char *te = NULL; /* transfer-encoding */ hyper_code rc; @@ -907,6 +882,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) may be parts of the request that is not yet sent, since we can deal with the rest of the request in the PERFORM phase. */ *done = TRUE; + Curl_client_cleanup(data); infof(data, "Time for the Hyper dance"); memset(h, 0, sizeof(struct hyptransfer)); @@ -917,6 +893,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) Curl_http_method(data, conn, &method, &httpreq); + DEBUGASSERT(data->req.bytecount == 0); + /* setup the authentication headers */ { char *pq = NULL; @@ -972,8 +950,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) goto error; } if(conn->alpn == CURL_HTTP_VERSION_2) { - hyper_clientconn_options_http2(options, 1); - h2 = TRUE; + failf(data, "ALPN protocol h2 not supported with Hyper"); + result = CURLE_UNSUPPORTED_PROTOCOL; + goto error; } hyper_clientconn_options_set_preserve_header_case(options, 1); hyper_clientconn_options_set_preserve_header_order(options, 1); @@ -1024,7 +1003,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) } } else { - if(!h2 && !data->state.disableexpect) { + if(!data->state.disableexpect) { data->state.expect100header = TRUE; } } @@ -1035,7 +1014,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) goto error; } - result = request_target(data, conn, method, h2, req); + result = request_target(data, conn, method, req); if(result) goto error; @@ -1056,19 +1035,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(result) goto error; - if(!h2) { - if(data->state.aptr.host) { - result = Curl_hyper_header(data, headers, data->state.aptr.host); - if(result) - goto error; - } - } - else { - /* For HTTP/2, we show the Host: header as if we sent it, to make it look - like for HTTP/1 but it isn't actually sent since :authority is then - used. */ - Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host, - strlen(data->state.aptr.host)); + if(data->state.aptr.host) { + result = Curl_hyper_header(data, headers, data->state.aptr.host); + if(result) + goto error; } if(data->state.aptr.proxyuserpwd) { diff --git a/libs/libcurl/src/cf-h1-proxy.c b/libs/libcurl/src/cf-h1-proxy.c index bec2d1dea4..a49d6869a6 100644 --- a/libs/libcurl/src/cf-h1-proxy.c +++ b/libs/libcurl/src/cf-h1-proxy.c @@ -374,7 +374,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data); char *linep; size_t perline; - int error; + int error, writetype; #define SELECT_OK 0 #define SELECT_ERROR 1 @@ -386,12 +386,12 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, return CURLE_OK; while(ts->keepon) { - ssize_t gotbytes; + ssize_t nread; char byte; /* Read one byte at a time to avoid a race condition. Wait at most one second before looping to ensure continuous pgrsUpdates. */ - result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes); + result = Curl_read(data, tunnelsocket, &byte, 1, &nread); if(result == CURLE_AGAIN) /* socket buffer drained, return */ return CURLE_OK; @@ -404,7 +404,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, break; } - if(gotbytes <= 0) { + if(nread <= 0) { if(data->set.proxyauth && data->state.authproxy.avail && data->state.aptr.proxyuserpwd) { /* proxy auth was requested and there was proxy auth available, @@ -437,11 +437,11 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, properly to know when the end of the body is reached */ CHUNKcode r; CURLcode extra; - ssize_t tookcareof = 0; + size_t consumed = 0; /* now parse the chunked piece of data so that we can properly tell when the stream ends */ - r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra); + r = Curl_httpchunk_read(data, &byte, 1, &consumed, &extra); if(r == CHUNKE_STOP) { /* we're done reading chunks! */ infof(data, "chunk reading DONE"); @@ -467,15 +467,12 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, /* output debug if that is requested */ Curl_debug(data, CURLINFO_HEADER_IN, linep, perline); - if(!data->set.suppress_connect_headers) { - /* send the header to the callback */ - int writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT | - (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0); - - result = Curl_client_write(data, writetype, linep, perline); - if(result) - return result; - } + /* send the header to the callback */ + writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT | + (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0); + result = Curl_client_write(data, writetype, linep, perline); + if(result) + return result; result = Curl_bump_headersize(data, perline, TRUE); if(result) @@ -502,6 +499,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, else if(ts->chunked_encoding) { CHUNKcode r; CURLcode extra; + size_t consumed = 0; infof(data, "Ignore chunked response-body"); @@ -516,8 +514,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, /* now parse the chunked piece of data so that we can properly tell when the stream ends */ - r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes, - &extra); + r = Curl_httpchunk_read(data, linep + 1, 1, &consumed, &extra); if(r == CHUNKE_STOP) { /* we're done reading chunks! */ infof(data, "chunk reading DONE"); @@ -1038,31 +1035,29 @@ out: return result; } -static int cf_h1_proxy_get_select_socks(struct Curl_cfilter *cf, +static void cf_h1_proxy_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) + struct easy_pollset *ps) { struct h1_tunnel_state *ts = cf->ctx; - int fds; - fds = cf->next->cft->get_select_socks(cf->next, data, socks); - if(!fds && cf->next->connected && !cf->connected) { + if(!cf->connected) { /* If we are not connected, but the filter "below" is * and not waiting on something, we are tunneling. */ - socks[0] = Curl_conn_cf_get_socket(cf, data); + curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); if(ts) { /* when we've sent a CONNECT to a proxy, we should rather either wait for the socket to become readable to be able to get the response headers or if we're still sending the request, wait for write. */ - if(ts->CONNECT.sending == HTTPSEND_REQUEST) { - return GETSOCK_WRITESOCK(0); - } - return GETSOCK_READSOCK(0); + if(ts->CONNECT.sending == HTTPSEND_REQUEST) + Curl_pollset_set_out_only(data, ps, sock); + else + Curl_pollset_set_in_only(data, ps, sock); } - return GETSOCK_WRITESOCK(0); + else + Curl_pollset_set_out_only(data, ps, sock); } - return fds; } static void cf_h1_proxy_destroy(struct Curl_cfilter *cf, @@ -1093,7 +1088,7 @@ struct Curl_cftype Curl_cft_h1_proxy = { cf_h1_proxy_connect, cf_h1_proxy_close, Curl_cf_http_proxy_get_host, - cf_h1_proxy_get_select_socks, + cf_h1_proxy_adjust_pollset, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, diff --git a/libs/libcurl/src/cf-h2-proxy.c b/libs/libcurl/src/cf-h2-proxy.c index aab4f4661b..f69098b704 100644 --- a/libs/libcurl/src/cf-h2-proxy.c +++ b/libs/libcurl/src/cf-h2-proxy.c @@ -688,12 +688,8 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session, * window and *assume* that we treat this like a WINDOW_UPDATE. Some * servers send an explicit WINDOW_UPDATE, but not all seem to do that. * To be safe, we UNHOLD a stream in order not to stall. */ - if((data->req.keepon & KEEP_SEND_HOLD) && - (data->req.keepon & KEEP_SEND)) { - data->req.keepon &= ~KEEP_SEND_HOLD; + if(CURL_WANT_SEND(data)) { drain_tunnel(cf, data, &ctx->tunnel); - CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS", - stream_id); } break; case NGHTTP2_GOAWAY: @@ -727,12 +723,8 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session, } break; case NGHTTP2_WINDOW_UPDATE: - if((data->req.keepon & KEEP_SEND_HOLD) && - (data->req.keepon & KEEP_SEND)) { - data->req.keepon &= ~KEEP_SEND_HOLD; - Curl_expire(data, 0, EXPIRE_RUN_NOW); - CURL_TRC_CF(data, cf, "[%d] unpausing after win update", - stream_id); + if(CURL_WANT_SEND(data)) { + drain_tunnel(cf, data, &ctx->tunnel); } break; default: @@ -909,7 +901,6 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id, { struct dynhds h2_headers; nghttp2_nv *nva = NULL; - unsigned int i; int32_t stream_id = -1; size_t nheader; CURLcode result; @@ -920,22 +911,12 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id, if(result) goto out; - nheader = Curl_dynhds_count(&h2_headers); - nva = malloc(sizeof(nghttp2_nv) * nheader); + nva = Curl_dynhds_to_nva(&h2_headers, &nheader); if(!nva) { result = CURLE_OUT_OF_MEMORY; goto out; } - for(i = 0; i < nheader; ++i) { - struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i); - nva[i].name = (unsigned char *)e->name; - nva[i].namelen = e->namelen; - nva[i].value = (unsigned char *)e->value; - nva[i].valuelen = e->valuelen; - nva[i].flags = NGHTTP2_NV_FLAG_NONE; - } - if(read_callback) { nghttp2_data_provider data_prd; @@ -1187,25 +1168,31 @@ static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf, return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE; } -static int cf_h2_proxy_get_select_socks(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t *sock) +static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps) { struct cf_h2_proxy_ctx *ctx = cf->ctx; - int bitmap = GETSOCK_BLANK; - struct cf_call_data save; - - CF_DATA_SAVE(save, cf, data); - sock[0] = Curl_conn_cf_get_socket(cf, data); - bitmap |= GETSOCK_READSOCK(0); + curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); + bool want_recv, want_send; - /* HTTP/2 layer wants to send data) AND there's a window to send data in */ - if(nghttp2_session_want_write(ctx->h2) && - nghttp2_session_get_remote_window_size(ctx->h2)) - bitmap |= GETSOCK_WRITESOCK(0); + Curl_pollset_check(data, ps, sock, &want_recv, &want_send); + if(ctx->h2 && (want_recv || want_send)) { + struct cf_call_data save; + bool c_exhaust, s_exhaust; - CF_DATA_RESTORE(cf, save); - return bitmap; + CF_DATA_SAVE(save, cf, data); + c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2); + s_exhaust = ctx->tunnel.stream_id >= 0 && + !nghttp2_session_get_stream_remote_window_size( + ctx->h2, ctx->tunnel.stream_id); + want_recv = (want_recv || c_exhaust || s_exhaust); + want_send = (!s_exhaust && want_send) || + (!c_exhaust && nghttp2_session_want_write(ctx->h2)); + + Curl_pollset_set(data, ps, sock, want_recv, want_send); + CF_DATA_RESTORE(cf, save); + } } static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf, @@ -1542,7 +1529,7 @@ struct Curl_cftype Curl_cft_h2_proxy = { cf_h2_proxy_connect, cf_h2_proxy_close, Curl_cf_http_proxy_get_host, - cf_h2_proxy_get_select_socks, + cf_h2_proxy_adjust_pollset, cf_h2_proxy_data_pending, cf_h2_proxy_send, cf_h2_proxy_recv, @@ -1560,7 +1547,7 @@ CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf, CURLcode result = CURLE_OUT_OF_MEMORY; (void)data; - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) goto out; diff --git a/libs/libcurl/src/cf-haproxy.c b/libs/libcurl/src/cf-haproxy.c index 8ca38823c6..6036e028a5 100644 --- a/libs/libcurl/src/cf-haproxy.c +++ b/libs/libcurl/src/cf-haproxy.c @@ -171,23 +171,17 @@ static void cf_haproxy_close(struct Curl_cfilter *cf, cf->next->cft->do_close(cf->next, data); } -static int cf_haproxy_get_select_socks(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t *socks) +static void cf_haproxy_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps) { - int fds; - - fds = cf->next->cft->get_select_socks(cf->next, data, socks); - if(!fds && cf->next->connected && !cf->connected) { + if(cf->next->connected && !cf->connected) { /* If we are not connected, but the filter "below" is * and not waiting on something, we are sending. */ - socks[0] = Curl_conn_cf_get_socket(cf, data); - return GETSOCK_WRITESOCK(0); + Curl_pollset_set_out_only(data, ps, Curl_conn_cf_get_socket(cf, data)); } - return fds; } - struct Curl_cftype Curl_cft_haproxy = { "HAPROXY", 0, @@ -196,7 +190,7 @@ struct Curl_cftype Curl_cft_haproxy = { cf_haproxy_connect, cf_haproxy_close, Curl_cf_def_get_host, - cf_haproxy_get_select_socks, + cf_haproxy_adjust_pollset, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, @@ -214,7 +208,7 @@ static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf, CURLcode result; (void)data; - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/libs/libcurl/src/cf-https-connect.c b/libs/libcurl/src/cf-https-connect.c index 5fe93e9c31..f2ae2cbee6 100644 --- a/libs/libcurl/src/cf-https-connect.c +++ b/libs/libcurl/src/cf-https-connect.c @@ -188,9 +188,6 @@ static CURLcode baller_connected(struct Curl_cfilter *cf, #endif infof(data, "using HTTP/2"); break; - case CURL_HTTP_VERSION_1_1: - infof(data, "using HTTP/1.1"); - break; default: infof(data, "using HTTP/1.x"); break; @@ -325,42 +322,25 @@ out: return result; } -static int cf_hc_get_select_socks(struct Curl_cfilter *cf, +static void cf_hc_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) + struct easy_pollset *ps) { - struct cf_hc_ctx *ctx = cf->ctx; - size_t i, j, s; - int brc, rc = GETSOCK_BLANK; - curl_socket_t bsocks[MAX_SOCKSPEREASYHANDLE]; - struct cf_hc_baller *ballers[2]; - - if(cf->connected) - return cf->next->cft->get_select_socks(cf->next, data, socks); - - ballers[0] = &ctx->h3_baller; - ballers[1] = &ctx->h21_baller; - for(i = s = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) { - struct cf_hc_baller *b = ballers[i]; - if(!cf_hc_baller_is_active(b)) - continue; - brc = Curl_conn_cf_get_select_socks(b->cf, data, bsocks); - CURL_TRC_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc); - if(!brc) - continue; - for(j = 0; j < MAX_SOCKSPEREASYHANDLE && s < MAX_SOCKSPEREASYHANDLE; ++j) { - if((brc & GETSOCK_WRITESOCK(j)) || (brc & GETSOCK_READSOCK(j))) { - socks[s] = bsocks[j]; - if(brc & GETSOCK_WRITESOCK(j)) - rc |= GETSOCK_WRITESOCK(s); - if(brc & GETSOCK_READSOCK(j)) - rc |= GETSOCK_READSOCK(s); - s++; - } + if(!cf->connected) { + struct cf_hc_ctx *ctx = cf->ctx; + struct cf_hc_baller *ballers[2]; + size_t i; + + ballers[0] = &ctx->h3_baller; + ballers[1] = &ctx->h21_baller; + for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) { + struct cf_hc_baller *b = ballers[i]; + if(!cf_hc_baller_is_active(b)) + continue; + Curl_conn_cf_adjust_pollset(b->cf, data, ps); } + CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num); } - CURL_TRC_CF(data, cf, "get_selected_socks -> %x", rc); - return rc; } static bool cf_hc_data_pending(struct Curl_cfilter *cf, @@ -455,7 +435,7 @@ struct Curl_cftype Curl_cft_http_connect = { cf_hc_connect, cf_hc_close, Curl_cf_def_get_host, - cf_hc_get_select_socks, + cf_hc_adjust_pollset, cf_hc_data_pending, Curl_cf_def_send, Curl_cf_def_recv, @@ -475,7 +455,7 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf, CURLcode result = CURLE_OK; (void)data; - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/libs/libcurl/src/cf-socket.c b/libs/libcurl/src/cf-socket.c index d815752089..8582fdff64 100644 --- a/libs/libcurl/src/cf-socket.c +++ b/libs/libcurl/src/cf-socket.c @@ -81,7 +81,7 @@ #include "memdebug.h" -#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(WIN32) +#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(_WIN32) /* It makes support for IPv4-mapped IPv6 addresses. * Linux kernel, NetBSD, FreeBSD and Darwin: default is off; * Windows Vista and later: default is on; @@ -102,11 +102,7 @@ static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd) #if defined(TCP_NODELAY) curl_socklen_t onoff = (curl_socklen_t) 1; int level = IPPROTO_TCP; -#if !defined(CURL_DISABLE_VERBOSE_STRINGS) char buffer[STRERROR_LEN]; -#else - (void) data; -#endif if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) @@ -127,6 +123,7 @@ static void nosigpipe(struct Curl_easy *data, curl_socket_t sockfd) { int onoff = 1; + (void)data; if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, sizeof(onoff)) < 0) { #if !defined(CURL_DISABLE_VERBOSE_STRINGS) @@ -662,7 +659,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) int err = 0; curl_socklen_t errSize = sizeof(err); -#ifdef WIN32 +#ifdef _WIN32 /* * In October 2003 we effectively nullified this function on Windows due to * problems with it using all CPU in multi-threaded cases. @@ -883,34 +880,14 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data) struct cf_socket_ctx *ctx = cf->ctx; if(ctx && CURL_SOCKET_BAD != ctx->sock) { - if(ctx->active) { - /* We share our socket at cf->conn->sock[cf->sockindex] when active. - * If it is no longer there, someone has stolen (and hopefully - * closed it) and we just forget about it. - */ - if(ctx->sock == cf->conn->sock[cf->sockindex]) { - CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T - ", active)", ctx->sock); - socket_close(data, cf->conn, !ctx->accepted, ctx->sock); - cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD; - } - else { - CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T - ") no longer at conn->sock[], discarding", ctx->sock); - /* TODO: we do not want this to happen. Need to check which - * code is messing with conn->sock[cf->sockindex] */ - } - ctx->sock = CURL_SOCKET_BAD; - if(cf->sockindex == FIRSTSOCKET) - cf->conn->remote_addr = NULL; - } - else { - /* this is our local socket, we did never publish it */ - CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T - ", not active)", ctx->sock); - socket_close(data, cf->conn, !ctx->accepted, ctx->sock); - ctx->sock = CURL_SOCKET_BAD; - } + CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T + ")", ctx->sock); + if(ctx->sock == cf->conn->sock[cf->sockindex]) + cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD; + socket_close(data, cf->conn, !ctx->accepted, ctx->sock); + ctx->sock = CURL_SOCKET_BAD; + if(ctx->active && cf->sockindex == FIRSTSOCKET) + cf->conn->remote_addr = NULL; Curl_bufq_reset(&ctx->recvbuf); ctx->active = FALSE; ctx->buffer_recv = FALSE; @@ -1169,6 +1146,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, *done = FALSE; /* a very negative world view is best */ if(ctx->sock == CURL_SOCKET_BAD) { + int error; result = cf_socket_open(cf, data); if(result) @@ -1181,8 +1159,12 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, /* Connect TCP socket */ rc = do_connect(cf, data, cf->conn->bits.tcp_fastopen); + error = SOCKERRNO; + set_local_ip(cf, data); + CURL_TRC_CF(data, cf, "local address %s port %d...", + ctx->l_ip, ctx->l_port); if(-1 == rc) { - result = socket_connect_result(data, ctx->r_ip, SOCKERRNO); + result = socket_connect_result(data, ctx->r_ip, error); goto out; } } @@ -1220,13 +1202,14 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, out: if(result) { if(ctx->error) { + set_local_ip(cf, data); data->state.os_errno = ctx->error; SET_SOCKERRNO(ctx->error); #ifndef CURL_DISABLE_VERBOSE_STRINGS { char buffer[STRERROR_LEN]; - infof(data, "connect to %s port %u failed: %s", - ctx->r_ip, ctx->r_port, + infof(data, "connect to %s port %u from %s port %d failed: %s", + ctx->r_ip, ctx->r_port, ctx->l_ip, ctx->l_port, Curl_strerror(ctx->error, buffer, sizeof(buffer))); } #endif @@ -1252,20 +1235,19 @@ static void cf_socket_get_host(struct Curl_cfilter *cf, *pport = cf->conn->port; } -static int cf_socket_get_select_socks(struct Curl_cfilter *cf, +static void cf_socket_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) + struct easy_pollset *ps) { struct cf_socket_ctx *ctx = cf->ctx; - int rc = GETSOCK_BLANK; - (void)data; - if(!cf->connected && ctx->sock != CURL_SOCKET_BAD) { - socks[0] = ctx->sock; - rc |= GETSOCK_WRITESOCK(0); + if(ctx->sock != CURL_SOCKET_BAD) { + if(!cf->connected) + Curl_pollset_set_out_only(data, ps, ctx->sock); + else + Curl_pollset_add_in(data, ps, ctx->sock); + CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num); } - - return rc; } static bool cf_socket_data_pending(struct Curl_cfilter *cf, @@ -1518,6 +1500,9 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf, case CF_CTRL_DATA_SETUP: Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port); break; + case CF_CTRL_FORGET_SOCKET: + ctx->sock = CURL_SOCKET_BAD; + break; } return CURLE_OK; } @@ -1612,7 +1597,7 @@ struct Curl_cftype Curl_cft_tcp = { cf_tcp_connect, cf_socket_close, cf_socket_get_host, - cf_socket_get_select_socks, + cf_socket_adjust_pollset, cf_socket_data_pending, cf_socket_send, cf_socket_recv, @@ -1635,7 +1620,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf, (void)data; (void)conn; DEBUGASSERT(transport == TRNSPRT_TCP); - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1742,7 +1727,7 @@ struct Curl_cftype Curl_cft_udp = { cf_udp_connect, cf_socket_close, cf_socket_get_host, - cf_socket_get_select_socks, + cf_socket_adjust_pollset, cf_socket_data_pending, cf_socket_send, cf_socket_recv, @@ -1765,7 +1750,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf, (void)data; (void)conn; DEBUGASSERT(transport == TRNSPRT_UDP || transport == TRNSPRT_QUIC); - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1793,7 +1778,7 @@ struct Curl_cftype Curl_cft_unix = { cf_tcp_connect, cf_socket_close, cf_socket_get_host, - cf_socket_get_select_socks, + cf_socket_adjust_pollset, cf_socket_data_pending, cf_socket_send, cf_socket_recv, @@ -1816,7 +1801,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf, (void)data; (void)conn; DEBUGASSERT(transport == TRNSPRT_UNIX); - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1857,7 +1842,7 @@ struct Curl_cftype Curl_cft_tcp_accept = { cf_tcp_accept_connect, cf_socket_close, cf_socket_get_host, /* TODO: not accurate */ - cf_socket_get_select_socks, + cf_socket_adjust_pollset, cf_socket_data_pending, cf_socket_send, cf_socket_recv, @@ -1879,7 +1864,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data, Curl_conn_cf_discard_all(data, conn, sockindex); DEBUGASSERT(conn->sock[sockindex] == CURL_SOCKET_BAD); - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/libs/libcurl/src/cfilters.c b/libs/libcurl/src/cfilters.c index 3121673ed1..72783eb53d 100644 --- a/libs/libcurl/src/cfilters.c +++ b/libs/libcurl/src/cfilters.c @@ -33,6 +33,7 @@ #include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "multiif.h" #include "progress.h" +#include "select.h" #include "warnless.h" /* The last 3 #include files should be in this order */ @@ -70,12 +71,14 @@ void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data, } } -int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf, +void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) + struct easy_pollset *ps) { - return cf->next? - cf->next->cft->get_select_socks(cf->next, data, socks) : 0; + /* NOP */ + (void)cf; + (void)data; + (void)ps; } bool Curl_cf_def_data_pending(struct Curl_cfilter *cf, @@ -212,7 +215,7 @@ CURLcode Curl_cf_create(struct Curl_cfilter **pcf, CURLcode result = CURLE_OUT_OF_MEMORY; DEBUGASSERT(cft); - cf = calloc(sizeof(*cf), 1); + cf = calloc(1, sizeof(*cf)); if(!cf) goto out; @@ -303,15 +306,6 @@ void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) cf->cft->do_close(cf, data); } -int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t *socks) -{ - if(cf) - return cf->cft->get_select_socks(cf, data, socks); - return 0; -} - ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, const void *buf, size_t len, CURLcode *err) { @@ -433,22 +427,31 @@ bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex) return FALSE; } -int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex, - curl_socket_t *socks) +void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps) +{ + /* Get the lowest not-connected filter, if there are any */ + while(cf && !cf->connected && cf->next && !cf->next->connected) + cf = cf->next; + /* From there on, give all filters a chance to adjust the pollset. + * Lower filters are called later, so they may override */ + while(cf) { + cf->cft->adjust_pollset(cf, data, ps); + cf = cf->next; + } +} + +void Curl_conn_adjust_pollset(struct Curl_easy *data, + struct easy_pollset *ps) { - struct Curl_cfilter *cf; + int i; DEBUGASSERT(data); DEBUGASSERT(data->conn); - cf = data->conn->cfilter[sockindex]; - - /* if the next one is not yet connected, that's the one we want */ - while(cf && cf->next && !cf->next->connected) - cf = cf->next; - if(cf) { - return cf->cft->get_select_socks(cf, data, socks); + for(i = 0; i < 2; ++i) { + Curl_conn_cf_adjust_pollset(data->conn->cfilter[i], data, ps); } - return GETSOCK_BLANK; } void Curl_conn_get_host(struct Curl_easy *data, int sockindex, @@ -524,6 +527,18 @@ curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex) return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD; } +void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex) +{ + if(data->conn) { + struct Curl_cfilter *cf = data->conn->cfilter[sockindex]; + if(cf) + (void)Curl_conn_cf_cntrl(cf, data, TRUE, + CF_CTRL_FORGET_SOCKET, 0, NULL); + fake_sclose(data->conn->sock[sockindex]); + data->conn->sock[sockindex] = CURL_SOCKET_BAD; + } +} + static CURLcode cf_cntrl_all(struct connectdata *conn, struct Curl_easy *data, bool ignore_result, @@ -646,3 +661,142 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data, &n, NULL) : CURLE_UNKNOWN_OPTION; return (result || n <= 0)? 1 : (size_t)n; } + + +void Curl_pollset_reset(struct Curl_easy *data, + struct easy_pollset *ps) +{ + size_t i; + (void)data; + memset(ps, 0, sizeof(*ps)); + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) + ps->sockets[i] = CURL_SOCKET_BAD; +} + +/** + * + */ +void Curl_pollset_change(struct Curl_easy *data, + struct easy_pollset *ps, curl_socket_t sock, + int add_flags, int remove_flags) +{ + unsigned int i; + + (void)data; + DEBUGASSERT(VALID_SOCK(sock)); + if(!VALID_SOCK(sock)) + return; + + DEBUGASSERT(add_flags <= (CURL_POLL_IN|CURL_POLL_OUT)); + DEBUGASSERT(remove_flags <= (CURL_POLL_IN|CURL_POLL_OUT)); + DEBUGASSERT((add_flags&remove_flags) == 0); /* no overlap */ + for(i = 0; i < ps->num; ++i) { + if(ps->sockets[i] == sock) { + ps->actions[i] &= (unsigned char)(~remove_flags); + ps->actions[i] |= (unsigned char)add_flags; + /* all gone? remove socket */ + if(!ps->actions[i]) { + if((i + 1) < ps->num) { + memmove(&ps->sockets[i], &ps->sockets[i + 1], + (ps->num - (i + 1)) * sizeof(ps->sockets[0])); + memmove(&ps->actions[i], &ps->actions[i + 1], + (ps->num - (i + 1)) * sizeof(ps->actions[0])); + } + --ps->num; + } + return; + } + } + /* not present */ + if(add_flags) { + /* Having more SOCKETS per easy handle than what is defined + * is a programming error. This indicates that we need + * to raise this limit, making easy_pollset larger. + * Since we use this in tight loops, we do not want to make + * the pollset dynamic unnecessarily. + * The current maximum in practise is HTTP/3 eyeballing where + * we have up to 4 sockets involved in connection setup. + */ + DEBUGASSERT(i < MAX_SOCKSPEREASYHANDLE); + if(i < MAX_SOCKSPEREASYHANDLE) { + ps->sockets[i] = sock; + ps->actions[i] = (unsigned char)add_flags; + ps->num = i + 1; + } + } +} + +void Curl_pollset_set(struct Curl_easy *data, + struct easy_pollset *ps, curl_socket_t sock, + bool do_in, bool do_out) +{ + Curl_pollset_change(data, ps, sock, + (do_in?CURL_POLL_IN:0)|(do_out?CURL_POLL_OUT:0), + (!do_in?CURL_POLL_IN:0)|(!do_out?CURL_POLL_OUT:0)); +} + +static void ps_add(struct Curl_easy *data, struct easy_pollset *ps, + int bitmap, curl_socket_t *socks) +{ + if(bitmap) { + int i; + for(i = 0; i < MAX_SOCKSPEREASYHANDLE; ++i) { + if(!(bitmap & GETSOCK_MASK_RW(i)) || !VALID_SOCK((socks[i]))) { + break; + } + if(bitmap & GETSOCK_READSOCK(i)) { + if(bitmap & GETSOCK_WRITESOCK(i)) + Curl_pollset_add_inout(data, ps, socks[i]); + else + /* is READ, since we checked MASK_RW above */ + Curl_pollset_add_in(data, ps, socks[i]); + } + else + Curl_pollset_add_out(data, ps, socks[i]); + } + } +} + +void Curl_pollset_add_socks(struct Curl_easy *data, + struct easy_pollset *ps, + int (*get_socks_cb)(struct Curl_easy *data, + struct connectdata *conn, + curl_socket_t *socks)) +{ + curl_socket_t socks[MAX_SOCKSPEREASYHANDLE]; + int bitmap; + + DEBUGASSERT(data->conn); + bitmap = get_socks_cb(data, data->conn, socks); + ps_add(data, ps, bitmap, socks); +} + +void Curl_pollset_add_socks2(struct Curl_easy *data, + struct easy_pollset *ps, + int (*get_socks_cb)(struct Curl_easy *data, + curl_socket_t *socks)) +{ + curl_socket_t socks[MAX_SOCKSPEREASYHANDLE]; + int bitmap; + + bitmap = get_socks_cb(data, socks); + ps_add(data, ps, bitmap, socks); +} + +void Curl_pollset_check(struct Curl_easy *data, + struct easy_pollset *ps, curl_socket_t sock, + bool *pwant_read, bool *pwant_write) +{ + unsigned int i; + + (void)data; + DEBUGASSERT(VALID_SOCK(sock)); + for(i = 0; i < ps->num; ++i) { + if(ps->sockets[i] == sock) { + *pwant_read = !!(ps->actions[i] & CURL_POLL_IN); + *pwant_write = !!(ps->actions[i] & CURL_POLL_OUT); + return; + } + } + *pwant_read = *pwant_write = FALSE; +} diff --git a/libs/libcurl/src/cfilters.h b/libs/libcurl/src/cfilters.h index 829340a2af..a343ea5fb6 100644 --- a/libs/libcurl/src/cfilters.h +++ b/libs/libcurl/src/cfilters.h @@ -60,14 +60,34 @@ typedef void Curl_cft_get_host(struct Curl_cfilter *cf, const char **pdisplay_host, int *pport); -/* Filters may return sockets and fdset flags they are waiting for. - * The passes array has room for up to MAX_SOCKSPEREASYHANDLE sockets. - * @return read/write fdset for index in socks - * or GETSOCK_BLANK when nothing to wait on +struct easy_pollset; + +/* Passing in an easy_pollset for monitoring of sockets, let + * filters add or remove sockets actions (CURL_POLL_OUT, CURL_POLL_IN). + * This may add a socket or, in case no actions remain, remove + * a socket from the set. + * + * Filter implementations need to call filters "below" *after* they have + * made their adjustments. This allows lower filters to override "upper" + * actions. If a "lower" filter is unable to write, it needs to be able + * to disallow POLL_OUT. + * + * A filter without own restrictions/preferences should not modify + * the pollset. Filters, whose filter "below" is not connected, should + * also do no adjustments. + * + * Examples: a TLS handshake, while ongoing, might remove POLL_IN + * when it needs to write, or vice versa. A HTTP/2 filter might remove + * POLL_OUT when a stream window is exhausted and a WINDOW_UPDATE needs + * to be received first and add instead POLL_IN. + * + * @param cf the filter to ask + * @param data the easy handle the pollset is about + * @param ps the pollset (inout) for the easy handle */ -typedef int Curl_cft_get_select_socks(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t *socks); +typedef void Curl_cft_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps); typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data); @@ -110,6 +130,7 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf, #define CF_CTRL_DATA_DONE_SEND 8 /* 0 NULL ignored */ /* update conn info at connection and data */ #define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0 NULL ignored */ +#define CF_CTRL_FORGET_SOCKET (256+1) /* 0 NULL ignored */ /** * Handle event/control for the filter. @@ -171,7 +192,7 @@ struct Curl_cftype { Curl_cft_connect *do_connect; /* establish connection */ Curl_cft_close *do_close; /* close conn */ Curl_cft_get_host *get_host; /* host filter talks to */ - Curl_cft_get_select_socks *get_select_socks;/* sockets to select on */ + Curl_cft_adjust_pollset *adjust_pollset; /* adjust transfer poll set */ Curl_cft_data_pending *has_data_pending;/* conn has data pending */ Curl_cft_send *do_send; /* send data */ Curl_cft_recv *do_recv; /* receive data */ @@ -200,9 +221,9 @@ void Curl_cf_def_destroy_this(struct Curl_cfilter *cf, void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data, const char **phost, const char **pdisplay_host, int *pport); -int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t *socks); +void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps); bool Curl_cf_def_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data); ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -279,9 +300,6 @@ CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf, struct Curl_easy *data, bool blocking, bool *done); void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data); -int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t *socks); ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, const void *buf, size_t len, CURLcode *err); ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -364,11 +382,22 @@ bool Curl_conn_data_pending(struct Curl_easy *data, curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex); /** - * Get any select fd flags and the socket filters at chain `sockindex` - * at connection `conn` might be waiting for. + * Tell filters to forget about the socket at sockindex. */ -int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex, - curl_socket_t *socks); +void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex); + +/** + * Adjust the pollset for the filter chain startgin at `cf`. + */ +void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps); + +/** + * Adjust pollset from filters installed at transfer's connection. + */ +void Curl_conn_adjust_pollset(struct Curl_easy *data, + struct easy_pollset *ps); /** * Receive data through the filter chain at `sockindex` for connection @@ -468,6 +497,54 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data, int sockindex); +void Curl_pollset_reset(struct Curl_easy *data, + struct easy_pollset *ps); + +/* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for + * socket `sock`. If the socket is not already part of the poll set, it + * will be added. + * If the socket is present and all poll flags are cleared, it will be removed. + */ +void Curl_pollset_change(struct Curl_easy *data, + struct easy_pollset *ps, curl_socket_t sock, + int add_flags, int remove_flags); + +void Curl_pollset_set(struct Curl_easy *data, + struct easy_pollset *ps, curl_socket_t sock, + bool do_in, bool do_out); + +#define Curl_pollset_add_in(data, ps, sock) \ + Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0) +#define Curl_pollset_add_out(data, ps, sock) \ + Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0) +#define Curl_pollset_add_inout(data, ps, sock) \ + Curl_pollset_change((data), (ps), (sock), \ + CURL_POLL_IN|CURL_POLL_OUT, 0) +#define Curl_pollset_set_in_only(data, ps, sock) \ + Curl_pollset_change((data), (ps), (sock), \ + CURL_POLL_IN, CURL_POLL_OUT) +#define Curl_pollset_set_out_only(data, ps, sock) \ + Curl_pollset_change((data), (ps), (sock), \ + CURL_POLL_OUT, CURL_POLL_IN) + +void Curl_pollset_add_socks(struct Curl_easy *data, + struct easy_pollset *ps, + int (*get_socks_cb)(struct Curl_easy *data, + struct connectdata *conn, + curl_socket_t *socks)); +void Curl_pollset_add_socks2(struct Curl_easy *data, + struct easy_pollset *ps, + int (*get_socks_cb)(struct Curl_easy *data, + curl_socket_t *socks)); + +/** + * Check if the pollset, as is, wants to read and/or write regarding + * the given socket. + */ +void Curl_pollset_check(struct Curl_easy *data, + struct easy_pollset *ps, curl_socket_t sock, + bool *pwant_read, bool *pwant_write); + /** * Types and macros used to keep the current easy handle in filter calls, * allowing for nested invocations. See #10336. diff --git a/libs/libcurl/src/config-amigaos.h b/libs/libcurl/src/config-amigaos.h index 26bd2a6b5f..ebb53eac06 100644 --- a/libs/libcurl/src/config-amigaos.h +++ b/libs/libcurl/src/config-amigaos.h @@ -32,7 +32,6 @@ #define HAVE_ARPA_INET_H 1 #define HAVE_CLOSESOCKET_CAMEL 1 -#define HAVE_INTTYPES_H 1 #define HAVE_IOCTLSOCKET_CAMEL 1 #define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1 #define HAVE_LONGLONG 1 diff --git a/libs/libcurl/src/config-dos.h b/libs/libcurl/src/config-dos.h index 92bb083e04..1e0368b98a 100644 --- a/libs/libcurl/src/config-dos.h +++ b/libs/libcurl/src/config-dos.h @@ -122,7 +122,6 @@ #define HAVE_SIGSETJMP 1 #define HAVE_SYS_TIME_H 1 #define HAVE_TERMIOS_H 1 - #define HAVE_VARIADIC_MACROS_GCC 1 #elif defined(__HIGHC__) #define HAVE_SYS_TIME_H 1 diff --git a/libs/libcurl/src/config-os400.h b/libs/libcurl/src/config-os400.h index ff7b8afaa5..355399a1bc 100644 --- a/libs/libcurl/src/config-os400.h +++ b/libs/libcurl/src/config-os400.h @@ -104,9 +104,6 @@ /* Define if you have the `timeval' struct. */ #define HAVE_STRUCT_TIMEVAL -/* Define if you have the header file. */ -#define HAVE_INTTYPES_H - /* Define if you have the header file. */ #undef HAVE_IO_H @@ -152,9 +149,6 @@ /* Define if you have the `socket' function. */ #define HAVE_SOCKET -/* Define if you have the header file. */ -#undef HAVE_STDINT_H - /* The following define is needed on OS400 to enable strcmpi(), stricmp() and strdup(). */ diff --git a/libs/libcurl/src/config-plan9.h b/libs/libcurl/src/config-plan9.h index e667cbd378..be30f883c6 100644 --- a/libs/libcurl/src/config-plan9.h +++ b/libs/libcurl/src/config-plan9.h @@ -91,7 +91,6 @@ #define HAVE_GMTIME_R 1 #define HAVE_INET_NTOP 1 #define HAVE_INET_PTON 1 -#define HAVE_INTTYPES_H 1 #define HAVE_LIBGEN_H 1 #define HAVE_LIBZ 1 #define HAVE_LOCALE_H 1 @@ -117,7 +116,6 @@ #define HAVE_SOCKET 1 #define HAVE_SSL_GET_SHUTDOWN 1 #define HAVE_STDBOOL_H 1 -#define HAVE_STDINT_H 1 #define HAVE_STRCASECMP 1 #define HAVE_STRDUP 1 #define HAVE_STRTOK_R 1 diff --git a/libs/libcurl/src/config-riscos.h b/libs/libcurl/src/config-riscos.h index cab2472e32..7add4d42d5 100644 --- a/libs/libcurl/src/config-riscos.h +++ b/libs/libcurl/src/config-riscos.h @@ -108,9 +108,6 @@ /* Define if you have the `timeval' struct. */ #define HAVE_STRUCT_TIMEVAL -/* Define if you have the header file. */ -#define HAVE_INTTYPES_H - /* Define if you have the header file. */ #undef HAVE_IO_H @@ -144,9 +141,6 @@ /* Define if you have the `socket' function. */ #define HAVE_SOCKET -/* Define if you have the header file. */ -#undef HAVE_STDINT_H - /* Define if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h index 486d5ccab1..d7856dd4b7 100644 --- a/libs/libcurl/src/config-win32.h +++ b/libs/libcurl/src/config-win32.h @@ -38,17 +38,6 @@ /* Define if you have the header file. */ #define HAVE_FCNTL_H 1 -/* Define to 1 if you have the header file. */ -#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__) -#define HAVE_INTTYPES_H 1 -#endif - -/* Define to 1 if you have the header file. */ -#if (defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(__MINGW32__) || \ - (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0582)) || defined(__POCC__) -#define HAVE_STDINT_H 1 -#endif - /* Define if you have the header file. */ #define HAVE_IO_H 1 @@ -56,9 +45,7 @@ #define HAVE_LOCALE_H 1 /* Define if you need header even with header file. */ -#if !defined(__SALFORDC__) && !defined(__POCC__) #define NEED_MALLOC_H 1 -#endif /* Define if you have the header file. */ /* #define HAVE_NETDB_H 1 */ @@ -72,7 +59,9 @@ #endif /* Define if you have the header file. */ -/* #define HAVE_SYS_PARAM_H 1 */ +#if defined(__MINGW32__) +#define HAVE_SYS_PARAM_H 1 +#endif /* Define if you have the header file. */ /* #define HAVE_SYS_SELECT_H 1 */ @@ -87,15 +76,15 @@ #define HAVE_SYS_STAT_H 1 /* Define if you have the header file. */ -/* #define HAVE_SYS_TIME_H 1 */ +#if defined(__MINGW32__) +#define HAVE_SYS_TIME_H 1 +#endif /* Define if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define if you have the header file. */ -#ifndef __BORLANDC__ #define HAVE_SYS_UTIME_H 1 -#endif /* Define if you have the header file. */ /* #define HAVE_TERMIO_H 1 */ @@ -104,7 +93,7 @@ /* #define HAVE_TERMIOS_H 1 */ /* Define if you have the header file. */ -#if defined(__MINGW32__) || defined(__LCC__) || defined(__POCC__) +#if defined(__MINGW32__) #define HAVE_UNISTD_H 1 #endif @@ -112,14 +101,10 @@ #define HAVE_WINDOWS_H 1 /* Define if you have the header file. */ -#ifndef __SALFORDC__ #define HAVE_WINSOCK2_H 1 -#endif /* Define if you have the header file. */ -#ifndef __SALFORDC__ #define HAVE_WS2TCPIP_H 1 -#endif /* Define to 1 if you have the header file. */ #if defined(__MINGW32__) @@ -160,7 +145,9 @@ #define HAVE_GETHOSTNAME 1 /* Define if you have the gettimeofday function. */ -/* #define HAVE_GETTIMEOFDAY 1 */ +#if defined(__MINGW32__) +#define HAVE_GETTIMEOFDAY 1 +#endif /* Define if you have the ioctlsocket function. */ #define HAVE_IOCTLSOCKET 1 @@ -180,10 +167,6 @@ /* Define if you have the socket function. */ #define HAVE_SOCKET 1 -/* Define if libSSH2 is in use */ -#define USE_LIBSSH2 1 -#define HAVE_LIBSSH2_H 1 - /* Define if you have the strcasecmp function. */ #if defined(__MINGW32__) #define HAVE_STRCASECMP 1 @@ -196,15 +179,12 @@ #define HAVE_STRICMP 1 /* Define if you have the strtoll function. */ -#if defined(__MINGW32__) || defined(__POCC__) || \ - (defined(_MSC_VER) && (_MSC_VER >= 1800)) +#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__) #define HAVE_STRTOLL 1 #endif /* Define if you have the utime function. */ -#ifndef __BORLANDC__ #define HAVE_UTIME 1 -#endif /* Define if you have the recv function. */ #define HAVE_RECV 1 @@ -246,7 +226,7 @@ #define SEND_TYPE_RETV int /* Define to 1 if you have the snprintf function. */ -#if defined(_MSC_VER) && (_MSC_VER >= 1900) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || defined(__MINGW32__) #define HAVE_SNPRINTF 1 #endif @@ -279,7 +259,7 @@ /* Define if ssize_t is not an available 'typedefed' type. */ #ifndef _SSIZE_T_DEFINED -# if defined(__POCC__) || defined(__MINGW32__) +# if defined(__MINGW32__) # elif defined(_WIN64) # define _SSIZE_T_DEFINED # define ssize_t __int64 @@ -329,8 +309,6 @@ # undef RECV_TYPE_ARG3 # undef SEND_TYPE_ARG1 # undef SEND_TYPE_ARG3 -# define HAVE_FREEADDRINFO -# define HAVE_GETADDRINFO # define HAVE_GETHOSTBYNAME_R # define HAVE_GETHOSTBYNAME_R_6 # define LWIP_POSIX_SOCKETS_IO_NAMES 0 @@ -351,13 +329,11 @@ #undef USE_WINSOCK #undef HAVE_WINSOCK2_H #undef HAVE_WS2TCPIP_H - #define HAVE_GETADDRINFO #define HAVE_SYS_IOCTL_H #define HAVE_SYS_SOCKET_H #define HAVE_NETINET_IN_H #define HAVE_NETDB_H #define HAVE_ARPA_INET_H - #define HAVE_FREEADDRINFO #define SOCKET int #endif @@ -375,15 +351,8 @@ /* Windows should not have HAVE_GMTIME_R defined */ /* #undef HAVE_GMTIME_R */ -/* Define if the compiler supports C99 variadic macro style. */ -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#define HAVE_VARIADIC_MACROS_C99 1 -#endif - /* Define if the compiler supports the 'long long' data type. */ -#if defined(__MINGW32__) || \ - (defined(_MSC_VER) && (_MSC_VER >= 1310)) || \ - (defined(__BORLANDC__) && (__BORLANDC__ >= 0x561)) +#if (defined(_MSC_VER) && (_MSC_VER >= 1310)) || defined(__MINGW32__) #define HAVE_LONGLONG 1 #endif @@ -465,53 +434,17 @@ Vista # endif #endif -/* When no build target is specified Pelles C 5.00 and later default build - target is Windows Vista. We override default target to be Windows 2000. */ -#if defined(__POCC__) && (__POCC__ >= 500) -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0500 -# endif -# ifndef WINVER -# define WINVER 0x0500 -# endif -#endif - -/* Availability of freeaddrinfo, getaddrinfo, and if_nametoindex - functions is quite convoluted, compiler dependent and even build target - dependent. */ -#if defined(HAVE_WS2TCPIP_H) -# if defined(__POCC__) -# define HAVE_FREEADDRINFO 1 -# define HAVE_GETADDRINFO 1 -# define HAVE_GETADDRINFO_THREADSAFE 1 -# elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) -# define HAVE_FREEADDRINFO 1 -# define HAVE_GETADDRINFO 1 -# define HAVE_GETADDRINFO_THREADSAFE 1 -# elif defined(_MSC_VER) && (_MSC_VER >= 1200) -# define HAVE_FREEADDRINFO 1 -# define HAVE_GETADDRINFO 1 -# define HAVE_GETADDRINFO_THREADSAFE 1 -# endif -#endif - -#if defined(__POCC__) -# ifndef _MSC_VER -# error Microsoft extensions /Ze compiler option is required -# endif -# ifndef __POCC__OLDNAMES -# error Compatibility names /Go compiler option is required -# endif -#endif +/* Windows XP is required for freeaddrinfo, getaddrinfo */ +#define HAVE_FREEADDRINFO 1 +#define HAVE_GETADDRINFO 1 +#define HAVE_GETADDRINFO_THREADSAFE 1 /* ---------------------------------------------------------------- */ /* STRUCT RELATED */ /* ---------------------------------------------------------------- */ /* Define if you have struct sockaddr_storage. */ -#if !defined(__SALFORDC__) && !defined(__BORLANDC__) #define HAVE_STRUCT_SOCKADDR_STORAGE 1 -#endif /* Define if you have struct timeval. */ #define HAVE_STRUCT_TIMEVAL 1 @@ -535,10 +468,6 @@ Vista # define USE_WIN32_LARGE_FILES #endif -#if defined(__POCC__) -# undef USE_WIN32_LARGE_FILES -#endif - #if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES) # define USE_WIN32_SMALL_FILES #endif @@ -600,13 +529,6 @@ Vista #define USE_WIN32_LDAP 1 #endif -#if defined(__POCC__) && defined(USE_WIN32_LDAP) -# define CURL_DISABLE_LDAP 1 -#endif - -/* if SSL is enabled */ -#define USE_OPENSSL 1 - /* Define to use the Windows crypto library. */ #if !defined(CURL_WINDOWS_APP) #define USE_WIN32_CRYPTO @@ -642,7 +564,7 @@ Vista /* If you want to build curl with the built-in manual */ #define USE_MANUAL 1 -#if defined(__POCC__) || defined(USE_IPV6) +#if defined(USE_IPV6) # define ENABLE_IPV6 1 #endif diff --git a/libs/libcurl/src/config-win32ce.h b/libs/libcurl/src/config-win32ce.h index 6898be9575..70a95d0411 100644 --- a/libs/libcurl/src/config-win32ce.h +++ b/libs/libcurl/src/config-win32ce.h @@ -81,7 +81,7 @@ /* #define HAVE_TERMIOS_H 1 */ /* Define if you have the header file. */ -#if defined(__MINGW32__) || defined(__LCC__) +#if defined(__MINGW32__) #define HAVE_UNISTD_H 1 #endif @@ -190,8 +190,7 @@ #define in_addr_t unsigned long /* Define ssize_t if it is not an available 'typedefed' type */ -#if defined(__POCC__) -#elif defined(_WIN64) +#if defined(_WIN64) #define ssize_t __int64 #else #define ssize_t int diff --git a/libs/libcurl/src/conncache.c b/libs/libcurl/src/conncache.c index fae7c0b057..de05e7494f 100644 --- a/libs/libcurl/src/conncache.c +++ b/libs/libcurl/src/conncache.c @@ -107,7 +107,7 @@ int Curl_conncache_init(struct conncache *connc, int size) connc->closure_handle = curl_easy_init(); if(!connc->closure_handle) return 1; /* bad */ - connc->closure_handle->internal = true; + connc->closure_handle->state.internal = true; Curl_hash_init(&connc->hash, size, Curl_hash_str, Curl_str_key_compare, free_bundle_hash_entry); @@ -243,7 +243,7 @@ CURLcode Curl_conncache_add_conn(struct Curl_easy *data) conn->connection_id = connc->next_connection_id++; connc->num_conn++; - DEBUGF(infof(data, "Added connection %ld. " + DEBUGF(infof(data, "Added connection %" CURL_FORMAT_CURL_OFF_T ". " "The cache now contains %zu members", conn->connection_id, connc->num_conn)); @@ -379,21 +379,26 @@ conncache_find_first_connection(struct conncache *connc) bool Curl_conncache_return_conn(struct Curl_easy *data, struct connectdata *conn) { - /* data->multi->maxconnects can be negative, deal with it. */ - size_t maxconnects = - (data->multi->maxconnects < 0) ? data->multi->num_easy * 4: - data->multi->maxconnects; + unsigned int maxconnects = !data->multi->maxconnects ? + data->multi->num_easy * 4: data->multi->maxconnects; struct connectdata *conn_candidate = NULL; conn->lastused = Curl_now(); /* it was used up until now */ - if(maxconnects > 0 && - Curl_conncache_size(data) > maxconnects) { + if(maxconnects && Curl_conncache_size(data) > maxconnects) { infof(data, "Connection cache is full, closing the oldest one"); conn_candidate = Curl_conncache_extract_oldest(data); if(conn_candidate) { - /* the winner gets the honour of being disconnected */ - Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE); + /* Use the closure handle for this disconnect so that anything that + happens during the disconnect is not stored and associated with the + 'data' handle which already just finished a transfer and it is + important that details from this (unrelated) disconnect does not + taint meta-data in the data handle. */ + struct conncache *connc = data->state.conn_cache; + connc->closure_handle->state.buffer = data->state.buffer; + connc->closure_handle->set.buffer_size = data->set.buffer_size; + Curl_disconnect(connc->closure_handle, conn_candidate, + /* dead_connection */ FALSE); } } diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c index ccc7bcda96..4e77d275e5 100644 --- a/libs/libcurl/src/connect.c +++ b/libs/libcurl/src/connect.c @@ -84,6 +84,9 @@ #include "curl_memory.h" #include "memdebug.h" +#ifndef ARRAYSIZE +#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif /* * Curl_timeleft() returns the amount of milliseconds left allowed for the @@ -348,6 +351,7 @@ void Curl_conncontrol(struct connectdata *conn, */ struct eyeballer { const char *name; + const struct Curl_addrinfo *first; /* complete address list, not owned */ const struct Curl_addrinfo *addr; /* List of addresses to try, not owned */ int ai_family; /* matching address family only */ cf_ip_connect_create *cf_create; /* for creating cf */ @@ -359,9 +363,12 @@ struct eyeballer { expire_id timeout_id; /* ID for Curl_expire() */ CURLcode result; int error; + BIT(rewinded); /* if we rewinded the addr list */ BIT(has_started); /* attempts have started */ BIT(is_done); /* out of addresses/time */ BIT(connected); /* cf has connected */ + BIT(inconclusive); /* connect was not a hard failure, we + * might talk to a restarting server */ }; @@ -408,7 +415,7 @@ static CURLcode eyeballer_new(struct eyeballer **pballer, #endif "ip")); baller->cf_create = cf_create; - baller->addr = addr; + baller->first = baller->addr = addr; baller->ai_family = ai_family; baller->primary = primary; baller->delay_ms = delay_ms; @@ -438,6 +445,13 @@ static void baller_free(struct eyeballer *baller, } } +static void baller_rewind(struct eyeballer *baller) +{ + baller->rewinded = TRUE; + baller->addr = baller->first; + baller->inconclusive = FALSE; +} + static void baller_next_addr(struct eyeballer *baller) { baller->addr = addr_next_match(baller->addr, baller->ai_family); @@ -528,6 +542,10 @@ static CURLcode baller_start_next(struct Curl_cfilter *cf, { if(cf->sockindex == FIRSTSOCKET) { baller_next_addr(baller); + /* If we get inconclusive answers from the server(s), we make + * a second iteration over the address list */ + if(!baller->addr && baller->inconclusive && !baller->rewinded) + baller_rewind(baller); baller_start(cf, data, baller, timeoutms); } else { @@ -566,6 +584,8 @@ static CURLcode baller_connect(struct Curl_cfilter *cf, baller->result = CURLE_OPERATION_TIMEDOUT; } } + else if(baller->result == CURLE_WEIRD_SERVER_REPLY) + baller->inconclusive = TRUE; } return baller->result; } @@ -595,7 +615,7 @@ evaluate: *connected = FALSE; /* a very negative world view is best */ now = Curl_now(); ongoing = not_started = 0; - for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { + for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { struct eyeballer *baller = ctx->baller[i]; if(!baller || baller->is_done) @@ -656,7 +676,7 @@ evaluate: if(not_started > 0) { int added = 0; - for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { + for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { struct eyeballer *baller = ctx->baller[i]; if(!baller || baller->has_started) @@ -691,13 +711,13 @@ evaluate: /* all ballers have failed to connect. */ CURL_TRC_CF(data, cf, "all eyeballers failed"); result = CURLE_COULDNT_CONNECT; - for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { + for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { struct eyeballer *baller = ctx->baller[i]; + if(!baller) + continue; CURL_TRC_CF(data, cf, "%s assess started=%d, result=%d", - baller?baller->name:NULL, - baller?baller->has_started:0, - baller?baller->result:0); - if(baller && baller->has_started && baller->result) { + baller->name, baller->has_started, baller->result); + if(baller->has_started && baller->result) { result = baller->result; break; } @@ -838,7 +858,7 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data) DEBUGASSERT(ctx); DEBUGASSERT(data); - for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { + for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { baller_free(ctx->baller[i], data); ctx->baller[i] = NULL; } @@ -846,35 +866,22 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data) ctx->winner = NULL; } -static int cf_he_get_select_socks(struct Curl_cfilter *cf, +static void cf_he_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) + struct easy_pollset *ps) { struct cf_he_ctx *ctx = cf->ctx; - size_t i, s; - int wrc, rc = GETSOCK_BLANK; - curl_socket_t wsocks[MAX_SOCKSPEREASYHANDLE]; - - if(cf->connected) - return cf->next->cft->get_select_socks(cf->next, data, socks); - - for(i = s = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { - struct eyeballer *baller = ctx->baller[i]; - if(!baller || !baller->cf) - continue; + size_t i; - wrc = Curl_conn_cf_get_select_socks(baller->cf, data, wsocks); - if(wrc) { - /* TODO: we assume we get at most one socket back */ - socks[s] = wsocks[0]; - if(wrc & GETSOCK_WRITESOCK(0)) - rc |= GETSOCK_WRITESOCK(s); - if(wrc & GETSOCK_READSOCK(0)) - rc |= GETSOCK_READSOCK(s); - s++; + if(!cf->connected) { + for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { + struct eyeballer *baller = ctx->baller[i]; + if(!baller || !baller->cf) + continue; + Curl_conn_cf_adjust_pollset(baller->cf, data, ps); } + CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num); } - return rc; } static CURLcode cf_he_connect(struct Curl_cfilter *cf, @@ -956,7 +963,7 @@ static bool cf_he_data_pending(struct Curl_cfilter *cf, if(cf->connected) return cf->next->cft->has_data_pending(cf->next, data); - for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { + for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { struct eyeballer *baller = ctx->baller[i]; if(!baller || !baller->cf) continue; @@ -975,7 +982,7 @@ static struct curltime get_max_baller_time(struct Curl_cfilter *cf, size_t i; memset(&tmax, 0, sizeof(tmax)); - for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { + for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { struct eyeballer *baller = ctx->baller[i]; memset(&t, 0, sizeof(t)); @@ -1000,7 +1007,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf, int reply_ms = -1; size_t i; - for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { + for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { struct eyeballer *baller = ctx->baller[i]; int breply_ms; @@ -1055,7 +1062,7 @@ struct Curl_cftype Curl_cft_happy_eyeballs = { cf_he_connect, cf_he_close, Curl_cf_def_get_host, - cf_he_get_select_socks, + cf_he_adjust_pollset, cf_he_data_pending, Curl_cf_def_send, Curl_cf_def_recv, @@ -1089,7 +1096,7 @@ cf_happy_eyeballs_create(struct Curl_cfilter **pcf, (void)data; (void)conn; *pcf = NULL; - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1122,13 +1129,13 @@ struct transport_provider transport_providers[] = { #ifdef ENABLE_QUIC { TRNSPRT_QUIC, Curl_cf_quic_create }, #endif +#ifndef CURL_DISABLE_TFTP { TRNSPRT_UDP, Curl_cf_udp_create }, +#endif +#ifdef USE_UNIX_SOCKETS { TRNSPRT_UNIX, Curl_cf_unix_create }, -}; - -#ifndef ARRAYSIZE -#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) #endif +}; static cf_ip_connect_create *get_cf_create(int transport) { @@ -1319,7 +1326,7 @@ struct Curl_cftype Curl_cft_setup = { cf_setup_connect, cf_setup_close, Curl_cf_def_get_host, - Curl_cf_def_get_select_socks, + Curl_cf_def_adjust_pollset, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, @@ -1340,7 +1347,7 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf, CURLcode result = CURLE_OK; (void)data; - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/libs/libcurl/src/content_encoding.c b/libs/libcurl/src/content_encoding.c index b1a64ebd52..2ea5e140be 100644 --- a/libs/libcurl/src/content_encoding.c +++ b/libs/libcurl/src/content_encoding.c @@ -63,6 +63,9 @@ #ifndef CURL_DISABLE_HTTP +/* allow no more than 5 "chained" compression steps */ +#define MAX_ENCODE_STACK 5 + #define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */ @@ -95,7 +98,7 @@ typedef enum { /* Deflate and gzip writer. */ struct zlib_writer { - struct contenc_writer super; + struct Curl_cwriter super; zlibInitState zlib_init; /* zlib init state */ uInt trailerlen; /* Remaining trailer byte count. */ z_stream z; /* State structure for zlib. */ @@ -171,7 +174,7 @@ static CURLcode process_trailer(struct Curl_easy *data, } static CURLcode inflate_stream(struct Curl_easy *data, - struct contenc_writer *writer, + struct Curl_cwriter *writer, int type, zlibInitState started) { struct zlib_writer *zp = (struct zlib_writer *) writer; @@ -196,7 +199,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); /* because the buffer size is fixed, iteratively decompress and transfer to - the client via downstream_write function. */ + the client via next_write function. */ while(!done) { int status; /* zlib status */ done = TRUE; @@ -217,7 +220,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, if(z->avail_out != DSIZ) { if(status == Z_OK || status == Z_STREAM_END) { zp->zlib_init = started; /* Data started. */ - result = Curl_unencode_write(data, writer->downstream, decomp, + result = Curl_cwriter_write(data, writer->next, type, decomp, DSIZ - z->avail_out); if(result) { exit_zlib(data, z, &zp->zlib_init, result); @@ -274,8 +277,8 @@ static CURLcode inflate_stream(struct Curl_easy *data, /* Deflate handler. */ -static CURLcode deflate_init_writer(struct Curl_easy *data, - struct contenc_writer *writer) +static CURLcode deflate_do_init(struct Curl_easy *data, + struct Curl_cwriter *writer) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ @@ -290,13 +293,16 @@ static CURLcode deflate_init_writer(struct Curl_easy *data, return CURLE_OK; } -static CURLcode deflate_unencode_write(struct Curl_easy *data, - struct contenc_writer *writer, +static CURLcode deflate_do_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, const char *buf, size_t nbytes) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ + if(!(type & CLIENTWRITE_BODY)) + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + /* Set the compressed input when this function is called */ z->next_in = (Bytef *) buf; z->avail_in = (uInt) nbytes; @@ -305,11 +311,11 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data, return process_trailer(data, zp); /* Now uncompress the data */ - return inflate_stream(data, writer, ZLIB_INFLATING); + return inflate_stream(data, writer, type, ZLIB_INFLATING); } -static void deflate_close_writer(struct Curl_easy *data, - struct contenc_writer *writer) +static void deflate_do_close(struct Curl_easy *data, + struct Curl_cwriter *writer) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ @@ -317,19 +323,19 @@ static void deflate_close_writer(struct Curl_easy *data, exit_zlib(data, z, &zp->zlib_init, CURLE_OK); } -static const struct content_encoding deflate_encoding = { +static const struct Curl_cwtype deflate_encoding = { "deflate", NULL, - deflate_init_writer, - deflate_unencode_write, - deflate_close_writer, + deflate_do_init, + deflate_do_write, + deflate_do_close, sizeof(struct zlib_writer) }; /* Gzip handler. */ -static CURLcode gzip_init_writer(struct Curl_easy *data, - struct contenc_writer *writer) +static CURLcode gzip_do_init(struct Curl_easy *data, + struct Curl_cwriter *writer) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ @@ -441,19 +447,22 @@ static enum { } #endif -static CURLcode gzip_unencode_write(struct Curl_easy *data, - struct contenc_writer *writer, +static CURLcode gzip_do_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, const char *buf, size_t nbytes) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ + if(!(type & CLIENTWRITE_BODY)) + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + if(zp->zlib_init == ZLIB_INIT_GZIP) { /* Let zlib handle the gzip decompression entirely */ z->next_in = (Bytef *) buf; z->avail_in = (uInt) nbytes; /* Now uncompress the data */ - return inflate_stream(data, writer, ZLIB_INIT_GZIP); + return inflate_stream(data, writer, type, ZLIB_INIT_GZIP); } #ifndef OLD_ZLIB_SUPPORT @@ -565,12 +574,12 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data, } /* We've parsed the header, now uncompress the data */ - return inflate_stream(data, writer, ZLIB_GZIP_INFLATING); + return inflate_stream(data, writer, type, ZLIB_GZIP_INFLATING); #endif } -static void gzip_close_writer(struct Curl_easy *data, - struct contenc_writer *writer) +static void gzip_do_close(struct Curl_easy *data, + struct Curl_cwriter *writer) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ @@ -578,12 +587,12 @@ static void gzip_close_writer(struct Curl_easy *data, exit_zlib(data, z, &zp->zlib_init, CURLE_OK); } -static const struct content_encoding gzip_encoding = { +static const struct Curl_cwtype gzip_encoding = { "gzip", "x-gzip", - gzip_init_writer, - gzip_unencode_write, - gzip_close_writer, + gzip_do_init, + gzip_do_write, + gzip_do_close, sizeof(struct zlib_writer) }; @@ -593,7 +602,7 @@ static const struct content_encoding gzip_encoding = { #ifdef HAVE_BROTLI /* Brotli writer. */ struct brotli_writer { - struct contenc_writer super; + struct Curl_cwriter super; BrotliDecoderState *br; /* State structure for brotli. */ }; @@ -635,8 +644,8 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be) return CURLE_WRITE_ERROR; } -static CURLcode brotli_init_writer(struct Curl_easy *data, - struct contenc_writer *writer) +static CURLcode brotli_do_init(struct Curl_easy *data, + struct Curl_cwriter *writer) { struct brotli_writer *bp = (struct brotli_writer *) writer; (void) data; @@ -645,8 +654,8 @@ static CURLcode brotli_init_writer(struct Curl_easy *data, return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY; } -static CURLcode brotli_unencode_write(struct Curl_easy *data, - struct contenc_writer *writer, +static CURLcode brotli_do_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, const char *buf, size_t nbytes) { struct brotli_writer *bp = (struct brotli_writer *) writer; @@ -657,6 +666,9 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data, CURLcode result = CURLE_OK; BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; + if(!(type & CLIENTWRITE_BODY)) + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + if(!bp->br) return CURLE_WRITE_ERROR; /* Stream already ended. */ @@ -670,7 +682,7 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data, dstleft = DSIZ; r = BrotliDecoderDecompressStream(bp->br, &nbytes, &src, &dstleft, &dst, NULL); - result = Curl_unencode_write(data, writer->downstream, + result = Curl_cwriter_write(data, writer->next, type, decomp, DSIZ - dstleft); if(result) break; @@ -693,8 +705,8 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data, return result; } -static void brotli_close_writer(struct Curl_easy *data, - struct contenc_writer *writer) +static void brotli_do_close(struct Curl_easy *data, + struct Curl_cwriter *writer) { struct brotli_writer *bp = (struct brotli_writer *) writer; @@ -706,12 +718,12 @@ static void brotli_close_writer(struct Curl_easy *data, } } -static const struct content_encoding brotli_encoding = { +static const struct Curl_cwtype brotli_encoding = { "br", NULL, - brotli_init_writer, - brotli_unencode_write, - brotli_close_writer, + brotli_do_init, + brotli_do_write, + brotli_do_close, sizeof(struct brotli_writer) }; #endif @@ -720,13 +732,13 @@ static const struct content_encoding brotli_encoding = { #ifdef HAVE_ZSTD /* Zstd writer. */ struct zstd_writer { - struct contenc_writer super; + struct Curl_cwriter super; ZSTD_DStream *zds; /* State structure for zstd. */ void *decomp; }; -static CURLcode zstd_init_writer(struct Curl_easy *data, - struct contenc_writer *writer) +static CURLcode zstd_do_init(struct Curl_easy *data, + struct Curl_cwriter *writer) { struct zstd_writer *zp = (struct zstd_writer *) writer; @@ -737,8 +749,8 @@ static CURLcode zstd_init_writer(struct Curl_easy *data, return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY; } -static CURLcode zstd_unencode_write(struct Curl_easy *data, - struct contenc_writer *writer, +static CURLcode zstd_do_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, const char *buf, size_t nbytes) { CURLcode result = CURLE_OK; @@ -747,6 +759,9 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data, ZSTD_outBuffer out; size_t errorCode; + if(!(type & CLIENTWRITE_BODY)) + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + if(!zp->decomp) { zp->decomp = malloc(DSIZ); if(!zp->decomp) @@ -766,7 +781,7 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data, return CURLE_BAD_CONTENT_ENCODING; } if(out.pos > 0) { - result = Curl_unencode_write(data, writer->downstream, + result = Curl_cwriter_write(data, writer->next, type, zp->decomp, out.pos); if(result) break; @@ -778,8 +793,8 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data, return result; } -static void zstd_close_writer(struct Curl_easy *data, - struct contenc_writer *writer) +static void zstd_do_close(struct Curl_easy *data, + struct Curl_cwriter *writer) { struct zstd_writer *zp = (struct zstd_writer *) writer; @@ -795,52 +810,30 @@ static void zstd_close_writer(struct Curl_easy *data, } } -static const struct content_encoding zstd_encoding = { +static const struct Curl_cwtype zstd_encoding = { "zstd", NULL, - zstd_init_writer, - zstd_unencode_write, - zstd_close_writer, + zstd_do_init, + zstd_do_write, + zstd_do_close, sizeof(struct zstd_writer) }; #endif /* Identity handler. */ -static CURLcode identity_init_writer(struct Curl_easy *data, - struct contenc_writer *writer) -{ - (void)data; - (void)writer; - return CURLE_OK; -} - -static CURLcode identity_unencode_write(struct Curl_easy *data, - struct contenc_writer *writer, - const char *buf, size_t nbytes) -{ - return Curl_unencode_write(data, writer->downstream, buf, nbytes); -} - -static void identity_close_writer(struct Curl_easy *data, - struct contenc_writer *writer) -{ - (void) data; - (void) writer; -} - -static const struct content_encoding identity_encoding = { +static const struct Curl_cwtype identity_encoding = { "identity", "none", - identity_init_writer, - identity_unencode_write, - identity_close_writer, - sizeof(struct contenc_writer) + Curl_cwriter_def_init, + Curl_cwriter_def_write, + Curl_cwriter_def_close, + sizeof(struct Curl_cwriter) }; /* supported content encodings table. */ -static const struct content_encoding * const encodings[] = { +static const struct Curl_cwtype * const encodings[] = { &identity_encoding, #ifdef HAVE_LIBZ &deflate_encoding, @@ -856,13 +849,17 @@ static const struct content_encoding * const encodings[] = { }; -/* Return a list of comma-separated names of supported encodings. */ -char *Curl_all_content_encodings(void) +/* Provide a list of comma-separated names of supported encodings. +*/ +void Curl_all_content_encodings(char *buf, size_t blen) { size_t len = 0; - const struct content_encoding * const *cep; - const struct content_encoding *ce; - char *ace; + const struct Curl_cwtype * const *cep; + const struct Curl_cwtype *ce; + + DEBUGASSERT(buf); + DEBUGASSERT(blen); + buf[0] = 0; for(cep = encodings; *cep; cep++) { ce = *cep; @@ -870,12 +867,12 @@ char *Curl_all_content_encodings(void) len += strlen(ce->name) + 2; } - if(!len) - return strdup(CONTENT_ENCODING_DEFAULT); - - ace = malloc(len); - if(ace) { - char *p = ace; + if(!len) { + if(blen >= sizeof(CONTENT_ENCODING_DEFAULT)) + strcpy(buf, CONTENT_ENCODING_DEFAULT); + } + else if(blen > len) { + char *p = buf; for(cep = encodings; *cep; cep++) { ce = *cep; if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) { @@ -887,75 +884,60 @@ char *Curl_all_content_encodings(void) } p[-2] = '\0'; } - - return ace; } - /* Deferred error dummy writer. */ -static CURLcode error_init_writer(struct Curl_easy *data, - struct contenc_writer *writer) +static CURLcode error_do_init(struct Curl_easy *data, + struct Curl_cwriter *writer) { (void)data; (void)writer; return CURLE_OK; } -static CURLcode error_unencode_write(struct Curl_easy *data, - struct contenc_writer *writer, +static CURLcode error_do_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, const char *buf, size_t nbytes) { - char *all = Curl_all_content_encodings(); + char all[256]; + (void)Curl_all_content_encodings(all, sizeof(all)); (void) writer; (void) buf; (void) nbytes; - if(!all) - return CURLE_OUT_OF_MEMORY; + if(!(type & CLIENTWRITE_BODY)) + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + failf(data, "Unrecognized content encoding type. " "libcurl understands %s content encodings.", all); - free(all); return CURLE_BAD_CONTENT_ENCODING; } -static void error_close_writer(struct Curl_easy *data, - struct contenc_writer *writer) +static void error_do_close(struct Curl_easy *data, + struct Curl_cwriter *writer) { (void) data; (void) writer; } -static const struct content_encoding error_encoding = { - NULL, +static const struct Curl_cwtype error_writer = { + "ce-error", NULL, - error_init_writer, - error_unencode_write, - error_close_writer, - sizeof(struct contenc_writer) + error_do_init, + error_do_write, + error_do_close, + sizeof(struct Curl_cwriter) }; -/* Write data using an unencoding writer stack. "nbytes" is not - allowed to be 0. */ -CURLcode Curl_unencode_write(struct Curl_easy *data, - struct contenc_writer *writer, - const char *buf, size_t nbytes) -{ - if(!nbytes) - return CURLE_OK; - if(!writer) - return CURLE_WRITE_ERROR; - return writer->handler->unencode_write(data, writer, buf, nbytes); -} - /* Find the content encoding by name. */ -static const struct content_encoding *find_encoding(const char *name, +static const struct Curl_cwtype *find_encoding(const char *name, size_t len) { - const struct content_encoding * const *cep; + const struct Curl_cwtype * const *cep; for(cep = encodings; *cep; cep++) { - const struct content_encoding *ce = *cep; + const struct Curl_cwtype *ce = *cep; if((strncasecompare(name, ce->name, len) && !ce->name[len]) || (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len])) return ce; @@ -969,7 +951,8 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, const char *enclist, int is_transfer) { struct SingleRequest *k = &data->req; - unsigned int order = is_transfer? 2: 1; + Curl_cwriter_phase phase = is_transfer? + CURL_CW_TRANSFER_DECODE:CURL_CW_CONTENT_DECODE; CURLcode result; do { @@ -992,23 +975,32 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, Curl_httpchunk_init(data); /* init our chunky engine. */ } else if(namelen) { - const struct content_encoding *encoding; - struct contenc_writer *writer; - if(is_transfer && !data->set.http_transfer_encoding) + const struct Curl_cwtype *cwt; + struct Curl_cwriter *writer; + + if((is_transfer && !data->set.http_transfer_encoding) || + (!is_transfer && data->set.http_ce_skip)) { /* not requested, ignore */ return CURLE_OK; + } - encoding = find_encoding(name, namelen); - if(!encoding) - encoding = &error_encoding; /* Defer error at stack use. */ + if(Curl_cwriter_count(data, phase) + 1 >= MAX_ENCODE_STACK) { + failf(data, "Reject response due to more than %u content encodings", + MAX_ENCODE_STACK); + return CURLE_BAD_CONTENT_ENCODING; + } + + cwt = find_encoding(name, namelen); + if(!cwt) + cwt = &error_writer; /* Defer error at use. */ - result = Curl_client_create_writer(&writer, data, encoding, order); + result = Curl_cwriter_create(&writer, data, cwt, phase); if(result) return result; - result = Curl_client_add_writer(data, writer); + result = Curl_cwriter_add(data, writer); if(result) { - Curl_client_free_writer(data, writer); + Curl_cwriter_free(data, writer); return result; } } @@ -1028,20 +1020,15 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, return CURLE_NOT_BUILT_IN; } -CURLcode Curl_unencode_write(struct Curl_easy *data, - struct contenc_writer *writer, - const char *buf, size_t nbytes) +void Curl_all_content_encodings(char *buf, size_t blen) { - (void) data; - (void) writer; - (void) buf; - (void) nbytes; - return CURLE_NOT_BUILT_IN; + DEBUGASSERT(buf); + DEBUGASSERT(blen); + if(blen < sizeof(CONTENT_ENCODING_DEFAULT)) + buf[0] = 0; + else + strcpy(buf, CONTENT_ENCODING_DEFAULT); } -char *Curl_all_content_encodings(void) -{ - return strdup(CONTENT_ENCODING_DEFAULT); /* Satisfy caller. */ -} #endif /* CURL_DISABLE_HTTP */ diff --git a/libs/libcurl/src/content_encoding.h b/libs/libcurl/src/content_encoding.h index 4b50e9b8da..4ca176abb6 100644 --- a/libs/libcurl/src/content_encoding.h +++ b/libs/libcurl/src/content_encoding.h @@ -25,15 +25,10 @@ ***************************************************************************/ #include "curl_setup.h" -struct contenc_writer; +struct Curl_cwriter; -char *Curl_all_content_encodings(void); +void Curl_all_content_encodings(char *buf, size_t blen); CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, const char *enclist, int is_transfer); -CURLcode Curl_unencode_write(struct Curl_easy *data, - struct contenc_writer *writer, - const char *buf, size_t nbytes); -void Curl_unencode_cleanup(struct Curl_easy *data); - #endif /* HEADER_CURL_CONTENT_ENCODING_H */ diff --git a/libs/libcurl/src/cookie.c b/libs/libcurl/src/cookie.c index cc698af53b..03f9699bd4 100644 --- a/libs/libcurl/src/cookie.c +++ b/libs/libcurl/src/cookie.c @@ -330,7 +330,7 @@ static char *sanitize_cookie_path(const char *cookie_path) */ void Curl_cookie_loadfiles(struct Curl_easy *data) { - struct curl_slist *list = data->set.cookielist; + struct curl_slist *list = data->state.cookielist; if(list) { Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); while(list) { @@ -365,9 +365,7 @@ static void strstore(char **str, const char *newstr, size_t len) DEBUGASSERT(newstr); DEBUGASSERT(str); free(*str); - *str = Curl_memdup(newstr, len + 1); - if(*str) - (*str)[len] = 0; + *str = Curl_strndup(newstr, len); } /* @@ -1029,15 +1027,23 @@ Curl_cookie_add(struct Curl_easy *data, * dereference it. */ if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) { - const psl_ctx_t *psl = Curl_psl_use(data); - int acceptable; - - if(psl) { - acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain); - Curl_psl_release(data); + bool acceptable = FALSE; + char lcase[256]; + char lcookie[256]; + size_t dlen = strlen(domain); + size_t clen = strlen(co->domain); + if((dlen < sizeof(lcase)) && (clen < sizeof(lcookie))) { + const psl_ctx_t *psl = Curl_psl_use(data); + if(psl) { + /* the PSL check requires lowercase domain name and pattern */ + Curl_strntolower(lcase, domain, dlen + 1); + Curl_strntolower(lcookie, co->domain, clen + 1); + acceptable = psl_is_cookie_domain_acceptable(psl, lcase, lcookie); + Curl_psl_release(data); + } + else + acceptable = !bad_domain(domain, strlen(domain)); } - else - acceptable = !bad_domain(domain, strlen(domain)); if(!acceptable) { infof(data, "cookie '%s' dropped, domain '%s' must not " @@ -1347,7 +1353,7 @@ static int cookie_sort_ct(const void *p1, const void *p2) static struct Cookie *dup_cookie(struct Cookie *src) { - struct Cookie *d = calloc(sizeof(struct Cookie), 1); + struct Cookie *d = calloc(1, sizeof(struct Cookie)); if(d) { CLONE(domain); CLONE(path); diff --git a/libs/libcurl/src/curl_config.h.cmake b/libs/libcurl/src/curl_config.h.cmake index a3774a05c1..11fa806dd1 100644 --- a/libs/libcurl/src/curl_config.h.cmake +++ b/libs/libcurl/src/curl_config.h.cmake @@ -74,9 +74,15 @@ /* disables FTP */ #cmakedefine CURL_DISABLE_FTP 1 +/* disables curl_easy_options API for existing options to curl_easy_setopt */ +#cmakedefine CURL_DISABLE_GETOPTIONS 1 + /* disables GOPHER */ #cmakedefine CURL_DISABLE_GOPHER 1 +/* disables headers-api support */ +#cmakedefine CURL_DISABLE_HEADERS_API 1 + /* disables HSTS support */ #cmakedefine CURL_DISABLE_HSTS 1 @@ -98,6 +104,9 @@ /* disables MIME support */ #cmakedefine CURL_DISABLE_MIME 1 +/* disables local binding support */ +#cmakedefine CURL_DISABLE_BINDLOCAL 1 + /* disables MQTT */ #cmakedefine CURL_DISABLE_MQTT 1 @@ -168,9 +177,6 @@ /* Define to 1 if you have _Atomic support. */ #cmakedefine HAVE_ATOMIC 1 -/* Define to 1 if you have the `fchmod' function. */ -#cmakedefine HAVE_FCHMOD 1 - /* Define to 1 if you have the `fnmatch' function. */ #cmakedefine HAVE_FNMATCH 1 @@ -208,6 +214,9 @@ /* Define to 1 if you have the fseeko function. */ #cmakedefine HAVE_FSEEKO 1 +/* Define to 1 if you have the fseeko declaration. */ +#cmakedefine HAVE_DECL_FSEEKO 1 + /* Define to 1 if you have the _fseeki64 function. */ #cmakedefine HAVE__FSEEKI64 1 @@ -313,9 +322,6 @@ /* Define to 1 if symbol `ADDRESS_FAMILY' exists */ #cmakedefine HAVE_ADDRESS_FAMILY 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_INTTYPES_H 1 - /* Define to 1 if you have the ioctlsocket function. */ #cmakedefine HAVE_IOCTLSOCKET 1 @@ -497,9 +503,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDBOOL_H 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STDINT_H 1 - /* Define to 1 if you have the strcasecmp function. */ #cmakedefine HAVE_STRCASECMP 1 @@ -596,12 +599,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UTIME_H 1 -/* Define to 1 if compiler supports C99 variadic macro style. */ -#cmakedefine HAVE_VARIADIC_MACROS_C99 1 - -/* Define to 1 if compiler supports old gcc variadic macro style. */ -#cmakedefine HAVE_VARIADIC_MACROS_GCC 1 - /* Define to 1 if you have the windows.h header file. */ #cmakedefine HAVE_WINDOWS_H 1 diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in index 8aa193abb6..ee2c680f6d 100644 --- a/libs/libcurl/src/curl_config.h.in +++ b/libs/libcurl/src/curl_config.h.in @@ -199,6 +199,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_CRYPTO_H +/* Define to 1 if you have the fseeko declaration */ +#undef HAVE_DECL_FSEEKO + /* Define to 1 if you have the declaration of `getpwuid_r', and to 0 if you don't. */ #undef HAVE_DECL_GETPWUID_R @@ -212,9 +215,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ERR_H -/* Define to 1 if you have the `fchmod' function. */ -#undef HAVE_FCHMOD - /* Define to 1 if you have the fcntl function. */ #undef HAVE_FCNTL @@ -722,12 +722,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UTIME_H -/* Define to 1 if compiler supports C99 variadic macro style. */ -#undef HAVE_VARIADIC_MACROS_C99 - -/* Define to 1 if compiler supports old gcc variadic macro style. */ -#undef HAVE_VARIADIC_MACROS_GCC - /* Define to 1 if you have the windows.h header file. */ #undef HAVE_WINDOWS_H diff --git a/libs/libcurl/src/curl_hmac.h b/libs/libcurl/src/curl_hmac.h index 50b3052de8..7d7a83711f 100644 --- a/libs/libcurl/src/curl_hmac.h +++ b/libs/libcurl/src/curl_hmac.h @@ -25,7 +25,8 @@ ***************************************************************************/ #if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \ - || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) + || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \ + || defined(USE_LIBSSH2) #include diff --git a/libs/libcurl/src/curl_memory.h b/libs/libcurl/src/curl_memory.h index 0340c142db..57e719e770 100644 --- a/libs/libcurl/src/curl_memory.h +++ b/libs/libcurl/src/curl_memory.h @@ -68,7 +68,7 @@ #undef send #undef recv -#ifdef WIN32 +#ifdef _WIN32 # ifdef UNICODE # undef wcsdup # undef _wcsdup @@ -134,7 +134,7 @@ extern curl_free_callback Curl_cfree; extern curl_realloc_callback Curl_crealloc; extern curl_strdup_callback Curl_cstrdup; extern curl_calloc_callback Curl_ccalloc; -#if defined(WIN32) && defined(UNICODE) +#if defined(_WIN32) && defined(UNICODE) extern curl_wcsdup_callback Curl_cwcsdup; #endif @@ -160,7 +160,7 @@ extern curl_wcsdup_callback Curl_cwcsdup; #undef free #define free(ptr) Curl_cfree(ptr) -#ifdef WIN32 +#ifdef _WIN32 # ifdef UNICODE # undef wcsdup # define wcsdup(ptr) Curl_cwcsdup(ptr) diff --git a/libs/libcurl/src/curl_multibyte.c b/libs/libcurl/src/curl_multibyte.c index 6180cb4e33..7448f51f3a 100644 --- a/libs/libcurl/src/curl_multibyte.c +++ b/libs/libcurl/src/curl_multibyte.c @@ -32,7 +32,7 @@ #include "curl_setup.h" -#if defined(WIN32) +#if defined(_WIN32) #include "curl_multibyte.h" @@ -84,7 +84,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w) return str_utf8; } -#endif /* WIN32 */ +#endif /* _WIN32 */ #if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES) diff --git a/libs/libcurl/src/curl_multibyte.h b/libs/libcurl/src/curl_multibyte.h index f0748b8ecd..e1f6a81451 100644 --- a/libs/libcurl/src/curl_multibyte.h +++ b/libs/libcurl/src/curl_multibyte.h @@ -25,7 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" -#if defined(WIN32) +#if defined(_WIN32) /* * MultiByte conversions using Windows kernel32 library. @@ -33,7 +33,7 @@ wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8); char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w); -#endif /* WIN32 */ +#endif /* _WIN32 */ /* * Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8() @@ -54,7 +54,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w); * ensure that the curl memdebug override macros do not replace them. */ -#if defined(UNICODE) && defined(WIN32) +#if defined(UNICODE) && defined(_WIN32) #define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr)) #define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr)) @@ -78,7 +78,7 @@ typedef union { const unsigned char *const_tbyte_ptr; } xcharp_u; -#endif /* UNICODE && WIN32 */ +#endif /* UNICODE && _WIN32 */ #define curlx_unicodefree(ptr) \ do { \ diff --git a/libs/libcurl/src/curl_ntlm_core.c b/libs/libcurl/src/curl_ntlm_core.c index d9c3acb7d8..c11b4b8a11 100644 --- a/libs/libcurl/src/curl_ntlm_core.c +++ b/libs/libcurl/src/curl_ntlm_core.c @@ -111,6 +111,7 @@ # include #else # error "Can't compile NTLM support without a crypto library with DES." +# define CURL_NTLM_NOT_SUPPORTED #endif #include "urldata.h" @@ -130,6 +131,7 @@ #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" #define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) +#if !defined(CURL_NTLM_NOT_SUPPORTED) /* * Turns a 56-bit key into being 64-bit wide. */ @@ -144,6 +146,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key) key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); } +#endif #if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL) /* @@ -337,6 +340,10 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, encrypt_des(plaintext, results, keys); encrypt_des(plaintext, results + 8, keys + 7); encrypt_des(plaintext, results + 16, keys + 14); +#else + (void)keys; + (void)plaintext; + (void)results; #endif } @@ -347,9 +354,11 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password, unsigned char *lmbuffer /* 21 bytes */) { unsigned char pw[14]; +#if !defined(CURL_NTLM_NOT_SUPPORTED) static const unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ }; +#endif size_t len = CURLMIN(strlen(password), 14); Curl_strntoupper((char *)pw, password, len); diff --git a/libs/libcurl/src/curl_ntlm_wb.c b/libs/libcurl/src/curl_ntlm_wb.c index 93a1d5b3b0..3103b9e3f4 100644 --- a/libs/libcurl/src/curl_ntlm_wb.c +++ b/libs/libcurl/src/curl_ntlm_wb.c @@ -68,7 +68,9 @@ /* Portable 'sclose_nolog' used only in child process instead of 'sclose' to avoid fooling the socket leak detector */ -#if defined(HAVE_CLOSESOCKET) +#ifdef HAVE_PIPE +# define sclose_nolog(x) close((x)) +#elif defined(HAVE_CLOSESOCKET) # define sclose_nolog(x) closesocket((x)) #elif defined(HAVE_CLOSESOCKET_CAMEL) # define sclose_nolog(x) CloseSocket((x)) @@ -189,7 +191,7 @@ static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm, goto done; } - if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) { + if(wakeup_create(sockfds)) { failf(data, "Could not open socket pair. errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; @@ -197,8 +199,8 @@ static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm, child_pid = fork(); if(child_pid == -1) { - sclose(sockfds[0]); - sclose(sockfds[1]); + wakeup_close(sockfds[0]); + wakeup_close(sockfds[1]); failf(data, "Could not fork. errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; @@ -268,7 +270,7 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm, Curl_dyn_init(&b, MAX_NTLM_WB_RESPONSE); while(len_in > 0) { - ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in); + ssize_t written = wakeup_write(ntlm->ntlm_auth_hlpr_socket, input, len_in); if(written == -1) { /* Interrupted by a signal, retry it */ if(errno == EINTR) @@ -282,7 +284,7 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm, /* Read one line */ while(1) { ssize_t size = - sread(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size); + wakeup_read(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size); if(size == -1) { if(errno == EINTR) continue; diff --git a/libs/libcurl/src/curl_path.h b/libs/libcurl/src/curl_path.h index 039348c2ff..3c0d0b7480 100644 --- a/libs/libcurl/src/curl_path.h +++ b/libs/libcurl/src/curl_path.h @@ -28,7 +28,7 @@ #include #include "urldata.h" -#ifdef WIN32 +#ifdef _WIN32 # undef PATH_MAX # define PATH_MAX MAX_PATH # ifndef R_OK diff --git a/libs/libcurl/src/curl_rtmp.c b/libs/libcurl/src/curl_rtmp.c index 4b675d6f82..0af8cdeb1a 100644 --- a/libs/libcurl/src/curl_rtmp.c +++ b/libs/libcurl/src/curl_rtmp.c @@ -39,7 +39,7 @@ /* The last #include file should be: */ #include "memdebug.h" -#if defined(WIN32) && !defined(USE_LWIPSOCK) +#if defined(_WIN32) && !defined(USE_LWIPSOCK) #define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e) #define SET_RCVTIMEO(tv,s) int tv = s*1000 #elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) diff --git a/libs/libcurl/src/curl_sasl.c b/libs/libcurl/src/curl_sasl.c index 42de215900..8d78d49129 100644 --- a/libs/libcurl/src/curl_sasl.c +++ b/libs/libcurl/src/curl_sasl.c @@ -262,6 +262,8 @@ static void sasl_state(struct SASL *sasl, struct Curl_easy *data, sasl->state = newstate; } +#if defined(USE_NTLM) || defined(USE_GSASL) || defined(USE_KERBEROS5) || \ + !defined(CURL_DISABLE_DIGEST_AUTH) /* Get the SASL server message and convert it to binary. */ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data, struct bufref *out) @@ -284,6 +286,7 @@ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data, } return result; } +#endif /* Encode the outgoing SASL message. */ static CURLcode build_message(struct SASL *sasl, struct bufref *msg) diff --git a/libs/libcurl/src/curl_setup.h b/libs/libcurl/src/curl_setup.h index b3995b87c6..2505a6e47c 100644 --- a/libs/libcurl/src/curl_setup.h +++ b/libs/libcurl/src/curl_setup.h @@ -28,6 +28,11 @@ #define CURL_NO_OLDIES #endif +/* Set default _WIN32_WINNT */ +#ifdef __MINGW32__ +#include <_mingw.h> +#endif + /* * Disable Visual Studio warnings: * 4127 "conditional expression is constant" @@ -36,15 +41,7 @@ #pragma warning(disable:4127) #endif -/* - * Define WIN32 when build target is Win32 API - */ - -#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -#define WIN32 -#endif - -#ifdef WIN32 +#ifdef _WIN32 /* * Don't include unneeded stuff in Windows headers to avoid compiler * warnings and macro clashes. @@ -56,6 +53,16 @@ # ifndef NOGDI # define NOGDI # endif +/* Detect Windows App environment which has a restricted access + * to the Win32 APIs. */ +# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \ + defined(WINAPI_FAMILY) +# include +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \ + !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define CURL_WINDOWS_APP +# endif +# endif #endif /* @@ -72,7 +79,7 @@ #ifdef _WIN32_WCE # include "config-win32ce.h" #else -# ifdef WIN32 +# ifdef _WIN32 # include "config-win32.h" # endif #endif @@ -204,6 +211,23 @@ # define CURL_DISABLE_RTSP #endif +/* + * When HTTP is disabled, disable HTTP-only features + */ + +#if defined(CURL_DISABLE_HTTP) +# define CURL_DISABLE_ALTSVC 1 +# define CURL_DISABLE_COOKIES 1 +# define CURL_DISABLE_BASIC_AUTH 1 +# define CURL_DISABLE_BEARER_AUTH 1 +# define CURL_DISABLE_AWS 1 +# define CURL_DISABLE_DOH 1 +# define CURL_DISABLE_FORM_API 1 +# define CURL_DISABLE_HEADERS_API 1 +# define CURL_DISABLE_HSTS 1 +# define CURL_DISABLE_HTTP_AUTH 1 +#endif + /* ================================================================ */ /* No system header file shall be included in this file before this */ /* point. */ @@ -321,23 +345,6 @@ #include #endif -#ifdef __POCC__ -# include -# include -# define sys_nerr EILSEQ -#endif - -/* - * Salford-C kludge section (mostly borrowed from wxWidgets). - */ -#ifdef __SALFORDC__ - #pragma suppress 353 /* Possible nested comments */ - #pragma suppress 593 /* Define not used */ - #pragma suppress 61 /* enum has no name */ - #pragma suppress 106 /* unnamed, unused parameter */ - #include -#endif - /* * Large file (>2Gb) support using WIN32 functions. */ @@ -490,11 +497,11 @@ 5. set dir/file naming defines */ -#ifdef WIN32 +#ifdef _WIN32 # define DIR_CHAR "\\" -#else /* WIN32 */ +#else /* _WIN32 */ # ifdef MSDOS /* Watt-32 */ @@ -519,48 +526,19 @@ # define DIR_CHAR "/" -# ifndef fileno /* sunos 4 have this as a macro! */ - int fileno(FILE *stream); -# endif - -#endif /* WIN32 */ - -/* - * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN - * defined in ws2tcpip.h as well as to provide IPv6 support. - * Does not apply if lwIP is used. - */ - -#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK) -# if !defined(HAVE_WS2TCPIP_H) || \ - ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN)) -# undef HAVE_GETADDRINFO_THREADSAFE -# undef HAVE_FREEADDRINFO -# undef HAVE_GETADDRINFO -# undef ENABLE_IPV6 -# endif -#endif +#endif /* _WIN32 */ /* ---------------------------------------------------------------- */ /* resolver specialty compile-time defines */ /* CURLRES_* defines to use in the host*.c sources */ /* ---------------------------------------------------------------- */ -/* - * lcc-win32 doesn't have _beginthreadex(), lacks threads support. - */ - -#if defined(__LCC__) && defined(WIN32) -# undef USE_THREADS_POSIX -# undef USE_THREADS_WIN32 -#endif - /* * MSVC threads support requires a multi-threaded runtime library. * _beginthreadex() is not available in single-threaded ones. */ -#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT) +#if defined(_MSC_VER) && !defined(_MT) # undef USE_THREADS_POSIX # undef USE_THREADS_WIN32 #endif @@ -571,6 +549,9 @@ #if defined(ENABLE_IPV6) && defined(HAVE_GETADDRINFO) # define CURLRES_IPV6 +#elif defined(ENABLE_IPV6) && (defined(_WIN32) || defined(__CYGWIN__)) +/* assume on Windows that IPv6 without getaddrinfo is a broken build */ +# error "Unexpected build: IPv6 is enabled but getaddrinfo was not found." #else # define CURLRES_IPV4 #endif @@ -590,35 +571,6 @@ /* ---------------------------------------------------------------- */ -/* - * msvc 6.0 does not have struct sockaddr_storage and - * does not define IPPROTO_ESP in winsock2.h. But both - * are available if PSDK is properly installed. - */ - -#if defined(_MSC_VER) && !defined(__POCC__) -# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP)) -# undef HAVE_STRUCT_SOCKADDR_STORAGE -# endif -#endif - -/* - * Intentionally fail to build when using msvc 6.0 without PSDK installed. - * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK - * in lib/config-win32.h although absolutely discouraged and unsupported. - */ - -#if defined(_MSC_VER) && !defined(__POCC__) -# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_)) -# if !defined(ALLOW_MSVC6_WITHOUT_PSDK) -# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \ - "Windows Server 2003 PSDK" -# else -# define CURL_DISABLE_LDAP 1 -# endif -# endif -#endif - #if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN) /* The lib and header are present */ #define USE_LIBIDN2 @@ -684,6 +636,18 @@ # define WARN_UNUSED_RESULT #endif +/* noreturn attribute */ + +#if !defined(CURL_NORETURN) +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) +# define CURL_NORETURN __attribute__((__noreturn__)) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) +# define CURL_NORETURN __declspec(noreturn) +#else +# define CURL_NORETURN +#endif +#endif + /* * Include macros and defines that should only be processed once. */ @@ -742,7 +706,7 @@ /* In Windows the default file mode is text but an application can override it. Therefore we specify it explicitly. https://github.com/curl/curl/pull/258 */ -#if defined(WIN32) || defined(MSDOS) +#if defined(_WIN32) || defined(MSDOS) #define FOPEN_READTEXT "rt" #define FOPEN_WRITETEXT "wt" #define FOPEN_APPENDTEXT "at" @@ -797,7 +761,8 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, #define UNITTEST static #endif -#if defined(USE_NGHTTP2) || defined(USE_HYPER) +/* Hyper supports HTTP2 also, but Curl's integration with Hyper does not */ +#if defined(USE_NGHTTP2) #define USE_HTTP2 #endif @@ -810,11 +775,11 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, /* Certain Windows implementations are not aligned with what curl expects, so always use the local one on this platform. E.g. the mingw-w64 implementation can return wrong results for non-ASCII inputs. */ -#if defined(HAVE_BASENAME) && defined(WIN32) +#if defined(HAVE_BASENAME) && defined(_WIN32) #undef HAVE_BASENAME #endif -#if defined(USE_UNIX_SOCKETS) && defined(WIN32) +#if defined(USE_UNIX_SOCKETS) && defined(_WIN32) # if !defined(UNIX_PATH_MAX) /* Replicating logic present in afunix.h (distributed with newer Windows 10 SDK versions only) */ diff --git a/libs/libcurl/src/curl_setup_once.h b/libs/libcurl/src/curl_setup_once.h index df1d35e961..2d92332eed 100644 --- a/libs/libcurl/src/curl_setup_once.h +++ b/libs/libcurl/src/curl_setup_once.h @@ -56,7 +56,7 @@ #include #endif -#ifdef WIN32 +#ifdef _WIN32 #include #include #endif @@ -70,11 +70,7 @@ #endif #ifdef USE_WOLFSSL -# if defined(HAVE_STDINT_H) -# include -# elif defined(HAVE_INTTYPES_H) -# include -# endif +#include #endif #ifdef USE_SCHANNEL diff --git a/libs/libcurl/src/curl_sspi.h b/libs/libcurl/src/curl_sspi.h index 33b0129c36..d1f89720dd 100644 --- a/libs/libcurl/src/curl_sspi.h +++ b/libs/libcurl/src/curl_sspi.h @@ -88,6 +88,22 @@ extern PSecurityFunctionTable s_pSecFn; # define CRYPT_E_REVOKED ((HRESULT)0x80092010L) #endif +#ifndef CRYPT_E_NO_REVOCATION_DLL +# define CRYPT_E_NO_REVOCATION_DLL ((HRESULT)0x80092011L) +#endif + +#ifndef CRYPT_E_NO_REVOCATION_CHECK +# define CRYPT_E_NO_REVOCATION_CHECK ((HRESULT)0x80092012L) +#endif + +#ifndef CRYPT_E_REVOCATION_OFFLINE +# define CRYPT_E_REVOCATION_OFFLINE ((HRESULT)0x80092013L) +#endif + +#ifndef CRYPT_E_NOT_IN_REVOCATION_DATABASE +# define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L) +#endif + #ifdef UNICODE # define SECFLAG_WINNT_AUTH_IDENTITY \ (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE diff --git a/libs/libcurl/src/curl_trc.c b/libs/libcurl/src/curl_trc.c index f4946ed337..9913ceaf9a 100644 --- a/libs/libcurl/src/curl_trc.c +++ b/libs/libcurl/src/curl_trc.c @@ -61,10 +61,6 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type, "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; if(data->set.fdebug) { bool inCallback = Curl_is_in_callback(data); - /* CURLOPT_DEBUGFUNCTION doc says the user may set CURLOPT_PRIVATE to - distinguish their handle from internal handles. */ - if(data->internal) - DEBUGASSERT(!data->set.private_data); Curl_set_in_callback(data, true); (void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata); Curl_set_in_callback(data, inCallback); @@ -109,6 +105,8 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...) } } +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* Curl_infof() is for info message along the way */ #define MAXINFO 2048 @@ -128,13 +126,11 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...) } } -#if !defined(CURL_DISABLE_VERBOSE_STRINGS) - void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, const char *fmt, ...) { DEBUGASSERT(cf); - if(data && Curl_trc_cf_is_verbose(cf, data)) { + if(Curl_trc_cf_is_verbose(cf, data)) { va_list ap; int len; char buffer[MAXINFO + 2]; @@ -232,24 +228,14 @@ CURLcode Curl_trc_init(void) if(config) { return Curl_trc_opt(config); } -#endif +#endif /* DEBUGBUILD */ return CURLE_OK; } -#else /* !CURL_DISABLE_VERBOSE_STRINGS) */ +#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */ CURLcode Curl_trc_init(void) { return CURLE_OK; } -#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) -void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, - const char *fmt, ...) -{ - (void)data; - (void)cf; - (void)fmt; -} -#endif - -#endif /* !DEBUGBUILD */ +#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */ diff --git a/libs/libcurl/src/curl_trc.h b/libs/libcurl/src/curl_trc.h index f9288a6a64..27fc8fc769 100644 --- a/libs/libcurl/src/curl_trc.h +++ b/libs/libcurl/src/curl_trc.h @@ -54,19 +54,6 @@ CURLcode Curl_trc_opt(const char *config); void Curl_debug(struct Curl_easy *data, curl_infotype type, char *ptr, size_t size); -/** - * Output an informational message when transfer's verbose logging is enabled. - */ -void Curl_infof(struct Curl_easy *data, -#if defined(__GNUC__) && !defined(printf) && \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !defined(__MINGW32__) - const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#else - const char *fmt, ...); -#endif - /** * Output a failure message on registered callbacks for transfer. */ @@ -82,39 +69,15 @@ void Curl_failf(struct Curl_easy *data, #define failf Curl_failf -/** - * Output an informational message when both transfer's verbose logging - * and connection filters verbose logging are enabled. - */ -void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, -#if defined(__GNUC__) && !defined(printf) && \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !defined(__MINGW32__) - const char *fmt, ...) - __attribute__((format(printf, 3, 4))); -#else - const char *fmt, ...); -#endif - #define CURL_LOG_LVL_NONE 0 #define CURL_LOG_LVL_INFO 1 -#if !defined(CURL_DISABLE_VERBOSE_STRINGS) -/* informational messages enabled */ - -#define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose) -#define Curl_trc_cf_is_verbose(cf, data) \ - ((data) && (data)->set.verbose && \ - (cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO) - -/* explainer: we have some mix configuration and werror settings - * that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced - * on gnuc and some other compiler. Need to treat carefully. - */ -#if defined(HAVE_VARIADIC_MACROS_C99) && \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define CURL_HAVE_C99 +#endif +#ifdef CURL_HAVE_C99 #define infof(data, ...) \ do { if(Curl_trc_is_verbose(data)) \ Curl_infof(data, __VA_ARGS__); } while(0) @@ -122,29 +85,62 @@ void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, do { if(Curl_trc_cf_is_verbose(cf, data)) \ Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0) -#else /* no variadic macro args */ +#else #define infof Curl_infof #define CURL_TRC_CF Curl_trc_cf_infof -#endif /* variadic macro args */ +#endif + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* informational messages enabled */ -#else /* !CURL_DISABLE_VERBOSE_STRINGS */ +#define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose) +#define Curl_trc_cf_is_verbose(cf, data) \ + ((data) && (data)->set.verbose && \ + (cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO) + +/** + * Output an informational message when transfer's verbose logging is enabled. + */ +void Curl_infof(struct Curl_easy *data, +#if defined(__GNUC__) && !defined(printf) && defined(CURL_HAVE_C99) && \ + !defined(__MINGW32__) + const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +#else + const char *fmt, ...); +#endif + +/** + * Output an informational message when both transfer's verbose logging + * and connection filters verbose logging are enabled. + */ +void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, +#if defined(__GNUC__) && !defined(printf) && defined(CURL_HAVE_C99) && \ + !defined(__MINGW32__) + const char *fmt, ...) + __attribute__((format(printf, 3, 4))); +#else + const char *fmt, ...); +#endif + +#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */ /* All informational messages are not compiled in for size savings */ #define Curl_trc_is_verbose(d) ((void)(d), FALSE) #define Curl_trc_cf_is_verbose(x,y) ((void)(x), (void)(y), FALSE) -#if defined(HAVE_VARIADIC_MACROS_C99) -#define infof(...) Curl_nop_stmt -#define CURL_TRC_CF(...) Curl_nop_stmt -#define Curl_trc_cf_infof(...) Curl_nop_stmt -#elif defined(HAVE_VARIADIC_MACROS_GCC) -#define infof(x...) Curl_nop_stmt -#define CURL_TRC_CF(x...) Curl_nop_stmt -#define Curl_trc_cf_infof(x...) Curl_nop_stmt -#else -#error "missing VARIADIC macro define, fix and rebuild!" -#endif +static void Curl_infof(struct Curl_easy *data, const char *fmt, ...) +{ + (void)data; (void)fmt; +} + +static void Curl_trc_cf_infof(struct Curl_easy *data, + struct Curl_cfilter *cf, + const char *fmt, ...) +{ + (void)data; (void)cf; (void)fmt; +} -#endif /* CURL_DISABLE_VERBOSE_STRINGS */ +#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */ #endif /* HEADER_CURL_TRC_H */ diff --git a/libs/libcurl/src/doh.c b/libs/libcurl/src/doh.c index 06c9eb17e3..0abeb965cd 100644 --- a/libs/libcurl/src/doh.c +++ b/libs/libcurl/src/doh.c @@ -242,7 +242,7 @@ static CURLcode dohprobe(struct Curl_easy *data, /* pass in the struct pointer via a local variable to please coverity and the gcc typecheck helpers */ struct dynbuf *resp = &p->serverdoh; - doh->internal = true; + doh->state.internal = true; ERROR_CHECK_SETOPT(CURLOPT_URL, url); ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https"); ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb); @@ -252,6 +252,7 @@ static CURLcode dohprobe(struct Curl_easy *data, ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers); #ifdef USE_HTTP2 ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); + ERROR_CHECK_SETOPT(CURLOPT_PIPEWAIT, 1L); #endif #ifndef CURLDEBUG /* enforce HTTPS if not debug */ @@ -339,9 +340,10 @@ static CURLcode dohprobe(struct Curl_easy *data, doh->set.dohfor = data; /* identify for which transfer this is done */ p->easy = doh; - /* DoH private_data must be null because the user must have a way to - distinguish their transfer's handle from DoH handles in user - callbacks (ie SSL CTX callback). */ + /* DoH handles must not inherit private_data. The handles may be passed to + the user via callbacks and the user will be able to identify them as + internal handles because private data is not set. The user can then set + private_data via CURLOPT_PRIVATE if they so choose. */ DEBUGASSERT(!doh->set.private_data); if(curl_multi_add_handle(multi, doh)) @@ -372,7 +374,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, int slot; struct dohdata *dohp; struct connectdata *conn = data->conn; - *waitp = TRUE; /* this never returns synchronously */ + *waitp = FALSE; (void)hostname; (void)port; @@ -380,7 +382,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, DEBUGASSERT(conn); /* start clean, consider allocating this struct on demand */ - dohp = data->req.doh = calloc(sizeof(struct dohdata), 1); + dohp = data->req.doh = calloc(1, sizeof(struct dohdata)); if(!dohp) return NULL; @@ -412,12 +414,14 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, dohp->pending++; } #endif + *waitp = TRUE; /* this never returns synchronously */ return NULL; error: curl_slist_free_all(dohp->headers); data->req.doh->headers = NULL; for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { + (void)curl_multi_remove_handle(data->multi, dohp->probe[slot].easy); Curl_close(&dohp->probe[slot].easy); } Curl_safefree(data->req.doh); @@ -787,8 +791,8 @@ static void showdoh(struct Curl_easy *data, * must be an associated call later to Curl_freeaddrinfo(). */ -static struct Curl_addrinfo * -doh2ai(const struct dohentry *de, const char *hostname, int port) +static CURLcode doh2ai(const struct dohentry *de, const char *hostname, + int port, struct Curl_addrinfo **aip) { struct Curl_addrinfo *ai; struct Curl_addrinfo *prevai = NULL; @@ -801,9 +805,10 @@ doh2ai(const struct dohentry *de, const char *hostname, int port) int i; size_t hostlen = strlen(hostname) + 1; /* include null-terminator */ - if(!de) - /* no input == no output! */ - return NULL; + DEBUGASSERT(de); + + if(!de->numaddr) + return CURLE_COULDNT_RESOLVE_HOST; for(i = 0; i < de->numaddr; i++) { size_t ss_size; @@ -876,8 +881,9 @@ doh2ai(const struct dohentry *de, const char *hostname, int port) Curl_freeaddrinfo(firstai); firstai = NULL; } + *aip = firstai; - return firstai; + return result; } #ifndef CURL_DISABLE_VERBOSE_STRINGS @@ -898,6 +904,7 @@ UNITTEST void de_cleanup(struct dohentry *d) CURLcode Curl_doh_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dnsp) { + struct connectdata *conn = data->conn; CURLcode result; struct dohdata *dohp = data->req.doh; *dnsp = NULL; /* defaults to no response */ @@ -906,7 +913,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy && !dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) { - failf(data, "Could not DoH-resolve: %s", data->state.async.hostname); + failf(data, "Could not DoH-resolve: %s", conn->resolve_async.hostname); return CONN_IS_PROXIED(data->conn)?CURLE_COULDNT_RESOLVE_PROXY: CURLE_COULDNT_RESOLVE_HOST; } @@ -932,10 +939,12 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, p->dnstype, &de); Curl_dyn_free(&p->serverdoh); +#ifndef CURL_DISABLE_VERBOSE_STRINGS if(rc[slot]) { infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]), type2name(p->dnstype), dohp->host); } +#endif } /* next slot */ result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */ @@ -947,10 +956,10 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, infof(data, "DoH Host name: %s", dohp->host); showdoh(data, &de); - ai = doh2ai(&de, dohp->host, dohp->port); - if(!ai) { + result = doh2ai(&de, dohp->host, dohp->port, &ai); + if(result) { de_cleanup(&de); - return CURLE_OUT_OF_MEMORY; + return result; } if(data->share) @@ -967,7 +976,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, Curl_freeaddrinfo(ai); } else { - data->state.async.dns = dns; + conn->resolve_async.dns = dns; *dnsp = dns; result = CURLE_OK; /* address resolution OK */ } diff --git a/libs/libcurl/src/dynbuf.c b/libs/libcurl/src/dynbuf.c index fc376a4e4b..dcf3da23ac 100644 --- a/libs/libcurl/src/dynbuf.c +++ b/libs/libcurl/src/dynbuf.c @@ -77,6 +77,7 @@ static CURLcode dyn_nappend(struct dynbuf *s, DEBUGASSERT(indx < s->toobig); DEBUGASSERT(!s->leng || s->bufr); DEBUGASSERT(a <= s->toobig); + DEBUGASSERT(!len || mem); if(fit > s->toobig) { Curl_dyn_free(s); @@ -174,10 +175,12 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len) */ CURLcode Curl_dyn_add(struct dynbuf *s, const char *str) { - size_t n = strlen(str); + size_t n; + DEBUGASSERT(str); DEBUGASSERT(s); DEBUGASSERT(s->init == DYNINIT); DEBUGASSERT(!s->leng || s->bufr); + n = strlen(str); return dyn_nappend(s, (unsigned char *)str, n); } @@ -191,6 +194,7 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap) DEBUGASSERT(s); DEBUGASSERT(s->init == DYNINIT); DEBUGASSERT(!s->leng || s->bufr); + DEBUGASSERT(fmt); rc = Curl_dyn_vprintf(s, fmt, ap); if(!rc) diff --git a/libs/libcurl/src/dynhds.c b/libs/libcurl/src/dynhds.c index 95e0b32227..465c09baca 100644 --- a/libs/libcurl/src/dynhds.c +++ b/libs/libcurl/src/dynhds.c @@ -27,6 +27,10 @@ #include "strcase.h" /* The last 3 #include files should be in this order */ +#ifdef USE_NGHTTP2 +#include +#include +#endif /* USE_NGHTTP2 */ #include "curl_printf.h" #include "curl_memory.h" #include "memdebug.h" @@ -365,3 +369,28 @@ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf) return result; } +#ifdef USE_NGHTTP2 + +nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount) +{ + nghttp2_nv *nva = calloc(1, sizeof(nghttp2_nv) * dynhds->hds_len); + size_t i; + + *pcount = 0; + if(!nva) + return NULL; + + for(i = 0; i < dynhds->hds_len; ++i) { + struct dynhds_entry *e = dynhds->hds[i]; + DEBUGASSERT(e); + nva[i].name = (unsigned char *)e->name; + nva[i].namelen = e->namelen; + nva[i].value = (unsigned char *)e->value; + nva[i].valuelen = e->valuelen; + nva[i].flags = NGHTTP2_NV_FLAG_NONE; + } + *pcount = dynhds->hds_len; + return nva; +} + +#endif /* USE_NGHTTP2 */ diff --git a/libs/libcurl/src/dynhds.h b/libs/libcurl/src/dynhds.h index 8cb5e6bc56..215087c6f4 100644 --- a/libs/libcurl/src/dynhds.h +++ b/libs/libcurl/src/dynhds.h @@ -171,4 +171,13 @@ CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds, */ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf); +#ifdef USE_NGHTTP2 + +#include +#include + +nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount); + +#endif /* USE_NGHTTP2 */ + #endif /* HEADER_CURL_DYNHDS_H */ diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c index 807b6391d3..f5ffe259de 100644 --- a/libs/libcurl/src/easy.c +++ b/libs/libcurl/src/easy.c @@ -112,7 +112,7 @@ static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT; #define system_strdup strdup #endif -#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +#if defined(_MSC_VER) && defined(_DLL) # pragma warning(disable:4232) /* MSVC extension, dllimport identity */ #endif @@ -125,11 +125,11 @@ curl_free_callback Curl_cfree = (curl_free_callback)free; curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; -#if defined(WIN32) && defined(UNICODE) +#if defined(_WIN32) && defined(UNICODE) curl_wcsdup_callback Curl_cwcsdup = Curl_wcsdup; #endif -#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +#if defined(_MSC_VER) && defined(_DLL) # pragma warning(default:4232) /* MSVC extension, dllimport identity */ #endif @@ -153,7 +153,7 @@ static CURLcode global_init(long flags, bool memoryfuncs) Curl_crealloc = (curl_realloc_callback)realloc; Curl_cstrdup = (curl_strdup_callback)system_strdup; Curl_ccalloc = (curl_calloc_callback)calloc; -#if defined(WIN32) && defined(UNICODE) +#if defined(_WIN32) && defined(UNICODE) Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; #endif } @@ -188,18 +188,10 @@ static CURLcode global_init(long flags, bool memoryfuncs) goto fail; } -#if defined(USE_SSH) if(Curl_ssh_init()) { + DEBUGF(fprintf(stderr, "Error: Curl_ssh_init failed\n")); goto fail; } -#endif - -#ifdef USE_WOLFSSH - if(WS_SUCCESS != wolfSSH_Init()) { - DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n")); - return CURLE_FAILED_INIT; - } -#endif easy_init_flags = flags; @@ -295,7 +287,7 @@ void curl_global_cleanup(void) Curl_ssl_cleanup(); Curl_resolver_global_cleanup(); -#ifdef WIN32 +#ifdef _WIN32 Curl_win32_cleanup(easy_init_flags); #endif @@ -752,7 +744,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events) return CURLE_RECURSIVE_API_CALL; /* Copy the MAXCONNECTS option to the multi handle */ - curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects); + curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, (long)data->set.maxconnects); mcode = curl_multi_add_handle(multi, data); if(mcode) { @@ -845,8 +837,10 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) dst->set = src->set; Curl_mime_initpart(&dst->set.mimepost); - /* clear all string pointers first */ + /* clear all dest string and blob pointers first, in case we error out + mid-function */ memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); + memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *)); /* duplicate all strings */ for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { @@ -855,8 +849,6 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) return result; } - /* clear all blob pointers first */ - memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *)); /* duplicate all blobs */ for(j = (enum dupblob)0; j < BLOB_LAST; j++) { result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]); @@ -866,10 +858,13 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) /* duplicate memory areas pointed to */ i = STRING_COPYPOSTFIELDS; - if(src->set.postfieldsize && src->set.str[i]) { - /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ - dst->set.str[i] = Curl_memdup(src->set.str[i], - curlx_sotouz(src->set.postfieldsize)); + if(src->set.str[i]) { + if(src->set.postfieldsize == -1) + dst->set.str[i] = strdup(src->set.str[i]); + else + /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ + dst->set.str[i] = Curl_memdup(src->set.str[i], + curlx_sotouz(src->set.postfieldsize)); if(!dst->set.str[i]) return CURLE_OUT_OF_MEMORY; /* point to the new copy */ @@ -919,18 +914,19 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) outcurl->progress.callback = data->progress.callback; #ifndef CURL_DISABLE_COOKIES - if(data->cookies) { + outcurl->state.cookielist = NULL; + if(data->cookies && data->state.cookie_engine) { /* If cookies are enabled in the parent handle, we enable them in the clone as well! */ - outcurl->cookies = Curl_cookie_init(data, NULL, outcurl->cookies, + outcurl->cookies = Curl_cookie_init(outcurl, NULL, outcurl->cookies, data->set.cookiesession); if(!outcurl->cookies) goto fail; } - if(data->set.cookielist) { - outcurl->set.cookielist = Curl_slist_duplicate(data->set.cookielist); - if(!outcurl->set.cookielist) + if(data->state.cookielist) { + outcurl->state.cookielist = Curl_slist_duplicate(data->state.cookielist); + if(!outcurl->state.cookielist) goto fail; } #endif @@ -976,33 +972,6 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) (void)Curl_hsts_loadcb(outcurl, outcurl->hsts); } #endif - /* Clone the resolver handle, if present, for the new handle */ - if(Curl_resolver_duphandle(outcurl, - &outcurl->state.async.resolver, - data->state.async.resolver)) - goto fail; - -#ifdef USE_ARES - { - CURLcode rc; - - rc = Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]); - if(rc && rc != CURLE_NOT_BUILT_IN) - goto fail; - - rc = Curl_set_dns_interface(outcurl, data->set.str[STRING_DNS_INTERFACE]); - if(rc && rc != CURLE_NOT_BUILT_IN) - goto fail; - - rc = Curl_set_dns_local_ip4(outcurl, data->set.str[STRING_DNS_LOCAL_IP4]); - if(rc && rc != CURLE_NOT_BUILT_IN) - goto fail; - - rc = Curl_set_dns_local_ip6(outcurl, data->set.str[STRING_DNS_LOCAL_IP6]); - if(rc && rc != CURLE_NOT_BUILT_IN) - goto fail; - } -#endif /* USE_ARES */ Curl_initinfo(outcurl); @@ -1016,13 +985,10 @@ fail: if(outcurl) { #ifndef CURL_DISABLE_COOKIES - curl_slist_free_all(outcurl->set.cookielist); - outcurl->set.cookielist = NULL; + free(outcurl->cookies); #endif - Curl_safefree(outcurl->state.buffer); + free(outcurl->state.buffer); Curl_dyn_free(&outcurl->state.headerb); - Curl_safefree(outcurl->state.url); - Curl_safefree(outcurl->state.referer); Curl_altsvc_cleanup(&outcurl->asi); Curl_hsts_cleanup(&outcurl->hsts); Curl_freeset(outcurl); diff --git a/libs/libcurl/src/easy_lock.h b/libs/libcurl/src/easy_lock.h index 49c5e58c86..52f63dd874 100644 --- a/libs/libcurl/src/easy_lock.h +++ b/libs/libcurl/src/easy_lock.h @@ -93,6 +93,15 @@ static inline void curl_simple_lock_unlock(curl_simple_lock *lock) atomic_store_explicit(lock, false, memory_order_release); } +#elif defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + +#include + +#define curl_simple_lock pthread_mutex_t +#define CURL_SIMPLE_LOCK_INIT PTHREAD_MUTEX_INITIALIZER +#define curl_simple_lock_lock(m) pthread_mutex_lock(m) +#define curl_simple_lock_unlock(m) pthread_mutex_unlock(m) + #else #undef GLOBAL_INIT_IS_THREADSAFE diff --git a/libs/libcurl/src/file.c b/libs/libcurl/src/file.c index 925372cf3f..7e0570d9f9 100644 --- a/libs/libcurl/src/file.c +++ b/libs/libcurl/src/file.c @@ -69,7 +69,7 @@ #include "curl_memory.h" #include "memdebug.h" -#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) +#if defined(_WIN32) || defined(MSDOS) || defined(__EMX__) #define DOS_FILESYSTEM 1 #elif defined(__amigaos4__) #define AMIGA_FILESYSTEM 1 @@ -414,7 +414,6 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) bool size_known; bool fstated = FALSE; char *buf = data->state.buffer; - curl_off_t bytecount = 0; int fd; struct FILEPROTO *file; @@ -563,7 +562,6 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) if(nread <= 0 || (size_known && (expected_size == 0))) break; - bytecount += nread; if(size_known) expected_size -= nread; @@ -571,10 +569,6 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) if(result) return result; - result = Curl_pgrsSetDownloadCounter(data, bytecount); - if(result) - return result; - if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; else diff --git a/libs/libcurl/src/fopen.c b/libs/libcurl/src/fopen.c index d1b2c57e31..444ebd090c 100644 --- a/libs/libcurl/src/fopen.c +++ b/libs/libcurl/src/fopen.c @@ -39,6 +39,51 @@ #include "curl_memory.h" #include "memdebug.h" +/* + The dirslash() function breaks a null-terminated pathname string into + directory and filename components then returns the directory component up + to, *AND INCLUDING*, a final '/'. If there is no directory in the path, + this instead returns a "" string. + + This function returns a pointer to malloc'ed memory. + + The input path to this function is expected to have a file name part. +*/ + +#ifdef _WIN32 +#define PATHSEP "\\" +#define IS_SEP(x) (((x) == '/') || ((x) == '\\')) +#elif defined(MSDOS) || defined(__EMX__) || defined(OS2) +#define PATHSEP "\\" +#define IS_SEP(x) ((x) == '\\') +#else +#define PATHSEP "/" +#define IS_SEP(x) ((x) == '/') +#endif + +static char *dirslash(const char *path) +{ + size_t n; + struct dynbuf out; + DEBUGASSERT(path); + Curl_dyn_init(&out, CURL_MAX_INPUT_LENGTH); + n = strlen(path); + if(n) { + /* find the rightmost path separator, if any */ + while(n && !IS_SEP(path[n-1])) + --n; + /* skip over all the path separators, if any */ + while(n && IS_SEP(path[n-1])) + --n; + } + if(Curl_dyn_addn(&out, path, n)) + return NULL; + /* if there was a directory, append a single trailing slash */ + if(n && Curl_dyn_addn(&out, PATHSEP, 1)) + return NULL; + return Curl_dyn_ptr(&out); +} + /* * Curl_fopen() opens a file for writing with a temp name, to be renamed * to the final name when completed. If there is an existing file using this @@ -50,47 +95,44 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, FILE **fh, char **tempname) { CURLcode result = CURLE_WRITE_ERROR; - unsigned char randsuffix[9]; + unsigned char randbuf[41]; char *tempstore = NULL; struct_stat sb; int fd = -1; + char *dir = NULL; *tempname = NULL; *fh = fopen(filename, FOPEN_WRITETEXT); if(!*fh) goto fail; - if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) + if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) { return CURLE_OK; + } fclose(*fh); *fh = NULL; - result = Curl_rand_alnum(data, randsuffix, sizeof(randsuffix)); + result = Curl_rand_alnum(data, randbuf, sizeof(randbuf)); if(result) goto fail; - tempstore = aprintf("%s.%s.tmp", filename, randsuffix); + dir = dirslash(filename); + if(dir) { + /* The temp file name should not end up too long for the target file + system */ + tempstore = aprintf("%s%s.tmp", dir, randbuf); + free(dir); + } + if(!tempstore) { result = CURLE_OUT_OF_MEMORY; goto fail; } result = CURLE_WRITE_ERROR; - fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600|sb.st_mode); if(fd == -1) goto fail; -#ifdef HAVE_FCHMOD - { - struct_stat nsb; - if((fstat(fd, &nsb) != -1) && - (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) { - /* if the user and group are the same, clone the original mode */ - if(fchmod(fd, (mode_t)sb.st_mode) == -1) - goto fail; - } - } -#endif - *fh = fdopen(fd, FOPEN_WRITETEXT); if(!*fh) goto fail; @@ -105,7 +147,6 @@ fail: } free(tempstore); - return result; } diff --git a/libs/libcurl/src/formdata.c b/libs/libcurl/src/formdata.c index 337cd3b2c5..88901c6bdd 100644 --- a/libs/libcurl/src/formdata.c +++ b/libs/libcurl/src/formdata.c @@ -603,9 +603,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, app passed in a bad combo, so we better check for that first. */ if(form->name) { /* copy name (without strdup; possibly not null-terminated) */ - form->name = Curl_memdup(form->name, form->namelength? - form->namelength: - strlen(form->name) + 1); + form->name = Curl_strndup(form->name, form->namelength? + form->namelength: + strlen(form->name)); } if(!form->name) { return_value = CURL_FORMADD_MEMORY; @@ -792,7 +792,7 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len) /* wrap call to fseeko so it matches the calling convention of callback */ static int fseeko_wrapper(void *stream, curl_off_t offset, int whence) { -#if defined(HAVE_FSEEKO) +#if defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO) return fseeko(stream, (off_t)offset, whence); #elif defined(HAVE__FSEEKI64) return _fseeki64(stream, (__int64)offset, whence); diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c index a4e0045122..cee0d97c59 100644 --- a/libs/libcurl/src/ftp.c +++ b/libs/libcurl/src/ftp.c @@ -819,7 +819,7 @@ static int ftp_domore_getsock(struct Curl_easy *data, DEBUGF(infof(data, "ftp_domore_getsock()")); if(conn->cfilter[SECONDARYSOCKET] && !Curl_conn_is_connected(conn, SECONDARYSOCKET)) - return Curl_conn_get_select_socks(data, SECONDARYSOCKET, socks); + return 0; if(FTP_STOP == ftpc->state) { int bits = GETSOCK_READSOCK(0); @@ -947,7 +947,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, char *port_start = NULL; char *port_sep = NULL; - addr = calloc(addrlen + 1, 1); + addr = calloc(1, addrlen + 1); if(!addr) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -4379,7 +4379,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, CURLcode result = CURLE_OK; struct ftp_conn *ftpc = &conn->proto.ftpc; - ftp = calloc(sizeof(struct FTP), 1); + ftp = calloc(1, sizeof(struct FTP)); if(!ftp) return CURLE_OUT_OF_MEMORY; diff --git a/libs/libcurl/src/ftplistparser.c b/libs/libcurl/src/ftplistparser.c index 4d54379acc..403a019b21 100644 --- a/libs/libcurl/src/ftplistparser.c +++ b/libs/libcurl/src/ftplistparser.c @@ -55,9 +55,6 @@ /* The last #include file should be: */ #include "memdebug.h" -/* allocs buffer which will contain one line of LIST command response */ -#define FTP_BUFFER_ALLOCSIZE 160 - typedef enum { PL_UNIX_TOTALSIZE = 0, PL_UNIX_FILETYPE, diff --git a/libs/libcurl/src/functypes.h b/libs/libcurl/src/functypes.h index 9cfbd8a63f..2ee699f7a5 100644 --- a/libs/libcurl/src/functypes.h +++ b/libs/libcurl/src/functypes.h @@ -38,7 +38,7 @@ 2. For systems with config-*.h files, define them there. */ -#ifdef WIN32 +#ifdef _WIN32 /* int recv(SOCKET, char *, int, int) */ #define RECV_TYPE_ARG1 SOCKET #define RECV_TYPE_ARG2 char * diff --git a/libs/libcurl/src/getenv.c b/libs/libcurl/src/getenv.c index 79aed96fb3..51faaad73b 100644 --- a/libs/libcurl/src/getenv.c +++ b/libs/libcurl/src/getenv.c @@ -31,10 +31,11 @@ static char *GetEnv(const char *variable) { -#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) +#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) || \ + defined(__ORBIS__) || defined(__PROSPERO__) /* PlayStation 4 and 5 */ (void)variable; return NULL; -#elif defined(WIN32) +#elif defined(_WIN32) /* This uses Windows API instead of C runtime getenv() to get the environment variable since some changes aren't always visible to the latter. #4774 */ char *buf = NULL; diff --git a/libs/libcurl/src/hostasyn.c b/libs/libcurl/src/hostasyn.c index 59a009ce33..326aa29983 100644 --- a/libs/libcurl/src/hostasyn.c +++ b/libs/libcurl/src/hostasyn.c @@ -67,10 +67,11 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data, int status, struct Curl_addrinfo *ai) { + struct connectdata *conn = data->conn; struct Curl_dns_entry *dns = NULL; CURLcode result = CURLE_OK; - data->state.async.status = status; + conn->resolve_async.status = status; if(CURL_ASYNC_SUCCESS == status) { if(ai) { @@ -78,8 +79,8 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data, Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); dns = Curl_cache_addr(data, ai, - data->state.async.hostname, 0, - data->state.async.port); + conn->resolve_async.hostname, 0, + conn->resolve_async.port); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); @@ -94,12 +95,12 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data, } } - data->state.async.dns = dns; + conn->resolve_async.dns = dns; /* Set async.done TRUE last in this function since it may be used multi- threaded and once this is TRUE the other thread may read fields from the async struct */ - data->state.async.done = TRUE; + conn->resolve_async.done = TRUE; /* IPv4: The input hostent struct will be freed by ares when we return from this function */ diff --git a/libs/libcurl/src/hostip.c b/libs/libcurl/src/hostip.c index 5490650ee9..8d84708a26 100644 --- a/libs/libcurl/src/hostip.c +++ b/libs/libcurl/src/hostip.c @@ -117,6 +117,13 @@ static void freednsentry(void *freethis); +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void show_resolve_info(struct Curl_easy *data, + struct Curl_dns_entry *dns); +#else +#define show_resolve_info(x,y) Curl_nop_stmt +#endif + /* * Curl_printable_address() stores a printable version of the 1st address * given in the 'ai' argument. The result will be stored in the buf that is @@ -481,9 +488,11 @@ Curl_cache_addr(struct Curl_easy *data, return NULL; } #endif + if(!hostlen) + hostlen = strlen(hostname); /* Create a new cache entry */ - dns = calloc(1, sizeof(struct Curl_dns_entry)); + dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen); if(!dns) { return NULL; } @@ -497,6 +506,9 @@ Curl_cache_addr(struct Curl_easy *data, time(&dns->timestamp); if(dns->timestamp == 0) dns->timestamp = 1; /* zero indicates permanent CURLOPT_RESOLVE entry */ + dns->hostport = port; + if(hostlen) + memcpy(dns->hostname, hostname, hostlen); /* Store the resolved data in our DNS cache. */ dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1, @@ -521,7 +533,7 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name) struct sockaddr_in6 sa6; unsigned char ipv6[16]; unsigned short port16 = (unsigned short)(port & 0xffff); - ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1); + ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1); if(!ca) return NULL; @@ -568,7 +580,7 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name) return NULL; memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4)); - ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1); + ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1); if(!ca) return NULL; ca->ai_flags = 0; @@ -729,7 +741,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, Curl_set_in_callback(data, true); st = data->set.resolver_start( #ifdef USE_CURL_ASYNC - data->state.async.resolver, + conn->resolve_async.resolver, #else NULL, #endif @@ -823,8 +835,10 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, if(!dns) /* returned failure, bail out nicely */ Curl_freeaddrinfo(addr); - else + else { rc = CURLRESOLV_RESOLVED; + show_resolve_info(data, dns); + } } } @@ -839,7 +853,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, * execution. This effectively causes the remainder of the application to run * within a signal handler which is nonportable and could lead to problems. */ -static +CURL_NORETURN static void alarmfunc(int sig) { (void)sig; @@ -1269,9 +1283,11 @@ err: Curl_freeaddrinfo(head); return CURLE_OUT_OF_MEMORY; } +#ifndef CURL_DISABLE_VERBOSE_STRINGS infof(data, "Added %.*s:%d:%s to DNS cache%s", (int)hlen, host_begin, port, addresses, permanent ? "" : " (non-permanent)"); +#endif /* Wildcard hostname */ if((hlen == 1) && (host_begin[0] == '*')) { @@ -1285,18 +1301,89 @@ err: return CURLE_OK; } +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void show_resolve_info(struct Curl_easy *data, + struct Curl_dns_entry *dns) +{ + struct Curl_addrinfo *a; + CURLcode result = CURLE_OK; +#ifdef CURLRES_IPV6 + struct dynbuf out[2]; +#else + struct dynbuf out[1]; +#endif + DEBUGASSERT(data); + DEBUGASSERT(dns); + + if(!data->set.verbose || + /* ignore no name or numerical IP addresses */ + !dns->hostname[0] || Curl_host_is_ipnum(dns->hostname)) + return; + + a = dns->addr; + + infof(data, "Host %s:%d was resolved.", + (dns->hostname[0] ? dns->hostname : "(none)"), dns->hostport); + + Curl_dyn_init(&out[0], 1024); +#ifdef CURLRES_IPV6 + Curl_dyn_init(&out[1], 1024); +#endif + + while(a) { + if( +#ifdef CURLRES_IPV6 + a->ai_family == PF_INET6 || +#endif + a->ai_family == PF_INET) { + char buf[MAX_IPADR_LEN]; + struct dynbuf *d = &out[(a->ai_family != PF_INET)]; + Curl_printable_address(a, buf, sizeof(buf)); + if(Curl_dyn_len(d)) + result = Curl_dyn_addn(d, ", ", 2); + if(!result) + result = Curl_dyn_add(d, buf); + if(result) { + infof(data, "too many IP, can't show"); + goto fail; + } + } + a = a->ai_next; + } + +#ifdef CURLRES_IPV6 + infof(data, "IPv6: %s", + (Curl_dyn_len(&out[1]) ? Curl_dyn_ptr(&out[1]) : "(none)")); +#endif + infof(data, "IPv4: %s", + (Curl_dyn_len(&out[0]) ? Curl_dyn_ptr(&out[0]) : "(none)")); + +fail: + Curl_dyn_free(&out[0]); +#ifdef CURLRES_IPV6 + Curl_dyn_free(&out[1]); +#endif +} +#endif + CURLcode Curl_resolv_check(struct Curl_easy *data, struct Curl_dns_entry **dns) { + CURLcode result; #if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH) (void)data; (void)dns; #endif #ifndef CURL_DISABLE_DOH - if(data->conn->bits.doh) - return Curl_doh_is_resolved(data, dns); + if(data->conn->bits.doh) { + result = Curl_doh_is_resolved(data, dns); + } + else #endif - return Curl_resolver_is_resolved(data, dns); + result = Curl_resolver_is_resolved(data, dns); + if(*dns) + show_resolve_info(data, *dns); + return result; } int Curl_resolv_getsock(struct Curl_easy *data, @@ -1328,9 +1415,9 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done) struct connectdata *conn = data->conn; #ifdef USE_CURL_ASYNC - if(data->state.async.dns) { - conn->dns_entry = data->state.async.dns; - data->state.async.dns = NULL; + if(conn->resolve_async.dns) { + conn->dns_entry = conn->resolve_async.dns; + conn->resolve_async.dns = NULL; } #endif @@ -1352,11 +1439,11 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done) #ifdef USE_CURL_ASYNC CURLcode Curl_resolver_error(struct Curl_easy *data) { + struct connectdata *conn = data->conn; const char *host_or_proxy; CURLcode result; #ifndef CURL_DISABLE_PROXY - struct connectdata *conn = data->conn; if(conn->bits.httpproxy) { host_or_proxy = "proxy"; result = CURLE_COULDNT_RESOLVE_PROXY; @@ -1369,7 +1456,7 @@ CURLcode Curl_resolver_error(struct Curl_easy *data) } failf(data, "Could not resolve %s: %s", host_or_proxy, - data->state.async.hostname); + conn->resolve_async.hostname); return result; } diff --git a/libs/libcurl/src/hostip.h b/libs/libcurl/src/hostip.h index 756d55c1d3..f47e3abaf9 100644 --- a/libs/libcurl/src/hostip.h +++ b/libs/libcurl/src/hostip.h @@ -64,6 +64,10 @@ struct Curl_dns_entry { time_t timestamp; /* use-counter, use Curl_resolv_unlock to release reference */ long inuse; + /* hostname port number that resolved to addr. */ + int hostport; + /* hostname that resolved to addr. may be NULL (unix domain sockets). */ + char hostname[1]; }; bool Curl_host_is_ipnum(const char *hostname); diff --git a/libs/libcurl/src/hostip6.c b/libs/libcurl/src/hostip6.c index 4b33e3e8e4..5e8c3abbda 100644 --- a/libs/libcurl/src/hostip6.c +++ b/libs/libcurl/src/hostip6.c @@ -71,8 +71,7 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn) #if defined(CURLRES_SYNCH) #ifdef DEBUG_ADDRINFO -static void dump_addrinfo(struct connectdata *conn, - const struct Curl_addrinfo *ai) +static void dump_addrinfo(const struct Curl_addrinfo *ai) { printf("dump_addrinfo:\n"); for(; ai; ai = ai->ai_next) { @@ -84,7 +83,7 @@ static void dump_addrinfo(struct connectdata *conn, } } #else -#define dump_addrinfo(x,y) Curl_nop_stmt +#define dump_addrinfo(x) Curl_nop_stmt #endif /* @@ -149,7 +148,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, Curl_addrinfo_set_port(res, port); } - dump_addrinfo(conn, res); + dump_addrinfo(res); return res; } diff --git a/libs/libcurl/src/hsts.c b/libs/libcurl/src/hsts.c index baf308874a..9ccfa14905 100644 --- a/libs/libcurl/src/hsts.c +++ b/libs/libcurl/src/hsts.c @@ -40,6 +40,7 @@ #include "fopen.h" #include "rename.h" #include "share.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -76,7 +77,7 @@ static time_t hsts_debugtime(void *unused) struct hsts *Curl_hsts_init(void) { - struct hsts *h = calloc(sizeof(struct hsts), 1); + struct hsts *h = calloc(1, sizeof(struct hsts)); if(h) { Curl_llist_init(&h->list, NULL); } @@ -108,7 +109,7 @@ void Curl_hsts_cleanup(struct hsts **hp) static struct stsentry *hsts_entry(void) { - return calloc(sizeof(struct stsentry), 1); + return calloc(1, sizeof(struct stsentry)); } static CURLcode hsts_create(struct hsts *h, @@ -116,23 +117,30 @@ static CURLcode hsts_create(struct hsts *h, bool subdomains, curl_off_t expires) { - struct stsentry *sts = hsts_entry(); + struct stsentry *sts; char *duphost; size_t hlen; + DEBUGASSERT(h); + DEBUGASSERT(hostname); + + hlen = strlen(hostname); + if(hlen && (hostname[hlen - 1] == '.')) + /* strip off any trailing dot */ + --hlen; + if(!hlen) + /* no host name left */ + return CURLE_BAD_FUNCTION_ARGUMENT; + + sts = hsts_entry(); if(!sts) return CURLE_OUT_OF_MEMORY; - duphost = strdup(hostname); + duphost = Curl_strndup(hostname, hlen); if(!duphost) { free(sts); return CURLE_OUT_OF_MEMORY; } - hlen = strlen(duphost); - if(duphost[hlen - 1] == '.') - /* strip off trailing any dot */ - duphost[--hlen] = 0; - sts->host = duphost; sts->expires = expires; sts->includeSubDomains = subdomains; @@ -564,7 +572,7 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h) void Curl_hsts_loadfiles(struct Curl_easy *data) { - struct curl_slist *l = data->set.hstslist; + struct curl_slist *l = data->state.hstslist; if(l) { Curl_share_lock(data, CURL_LOCK_DATA_HSTS, CURL_LOCK_ACCESS_SINGLE); diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c index 9b935d88e1..d27c300bd3 100644 --- a/libs/libcurl/src/http.c +++ b/libs/libcurl/src/http.c @@ -836,6 +836,7 @@ output_auth_headers(struct Curl_easy *data, (data->state.aptr.user ? data->state.aptr.user : "")); #else + (void)proxy; infof(data, "Server auth using %s with user '%s'", auth, data->state.aptr.user ? data->state.aptr.user : ""); @@ -845,7 +846,7 @@ output_auth_headers(struct Curl_easy *data, else authstatus->multipass = FALSE; - return CURLE_OK; + return result; } /** @@ -970,17 +971,21 @@ Curl_http_output_auth(struct Curl_easy *data, } #endif -/* - * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate: - * headers. They are dealt with both in the transfer.c main loop and in the - * proxy CONNECT loop. - */ - +#if defined(USE_SPNEGO) || defined(USE_NTLM) || \ + !defined(CURL_DISABLE_DIGEST_AUTH) || \ + !defined(CURL_DISABLE_BASIC_AUTH) || \ + !defined(CURL_DISABLE_BEARER_AUTH) static int is_valid_auth_separator(char ch) { return ch == '\0' || ch == ',' || ISSPACE(ch); } +#endif +/* + * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate: + * headers. They are dealt with both in the transfer.c main loop and in the + * proxy CONNECT loop. + */ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, const char *auth) /* the first non-space */ { @@ -992,11 +997,15 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state : &conn->http_negotiate_state; #endif +#if defined(USE_SPNEGO) || \ + defined(USE_NTLM) || \ + !defined(CURL_DISABLE_DIGEST_AUTH) || \ + !defined(CURL_DISABLE_BASIC_AUTH) || \ + !defined(CURL_DISABLE_BEARER_AUTH) + unsigned long *availp; struct auth *authp; - (void) conn; /* In case conditionals make it unused. */ - if(proxy) { availp = &data->info.proxyauthavail; authp = &data->state.authproxy; @@ -1005,6 +1014,11 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, availp = &data->info.httpauthavail; authp = &data->state.authhost; } +#else + (void) proxy; +#endif + + (void) conn; /* In case conditionals make it unused. */ /* * Here we check if we want the specific single authentication (using ==) and @@ -1140,7 +1154,14 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, } } #else - ; + { + /* + * Empty block to terminate the if-else chain correctly. + * + * A semicolon would yield the same result here, but can cause a + * compiler warning when -Wextra is enabled. + */ + } #endif /* there may be multiple methods on one line, so keep reading */ @@ -1403,7 +1424,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in, * and install our own `data->state.fread_func` that * on subsequent calls reads `in` empty. * - when the whisked away `in` is empty, the `fread_func` - * is restored ot its original state. + * is restored to its original state. * The problem is that `fread_func` can only return * `upload_buffer_size` lengths. If the send we do here * is larger and blocks, we do re-sending with smaller @@ -1678,8 +1699,6 @@ static CURLcode expect100(struct Curl_easy *data, struct dynbuf *req) { CURLcode result = CURLE_OK; - data->state.expect100header = FALSE; /* default to false unless it is set - to TRUE below */ if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) && (conn->httpversion < 20)) { /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an @@ -2414,14 +2433,16 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, /* Convert the form structure into a mime structure, then keep the conversion */ if(!data->state.formp) { - data->state.formp = calloc(sizeof(curl_mimepart), 1); + data->state.formp = calloc(1, sizeof(curl_mimepart)); if(!data->state.formp) return CURLE_OUT_OF_MEMORY; Curl_mime_cleanpart(data->state.formp); result = Curl_getformdata(data, data->state.formp, data->set.httppost, data->state.fread_func); - if(result) + if(result) { + Curl_safefree(data->state.formp); return result; + } data->state.mimepost = data->state.formp; } break; @@ -2494,6 +2515,29 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, return result; } +static CURLcode addexpect(struct Curl_easy *data, struct connectdata *conn, + struct dynbuf *r) +{ + data->state.expect100header = FALSE; + /* Avoid Expect: 100-continue if Upgrade: is used */ + if(data->req.upgr101 == UPGR101_INIT) { + struct HTTP *http = data->req.p.http; + /* For really small puts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + char *ptr = Curl_checkheaders(data, STRCONST("Expect")); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, STRCONST("Expect:"), + STRCONST("100-continue")); + } + else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) + return expect100(data, conn, r); + } + return CURLE_OK; +} + CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, struct dynbuf *r, Curl_HttpReq httpreq) { @@ -2506,14 +2550,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, #endif CURLcode result = CURLE_OK; struct HTTP *http = data->req.p.http; - const char *ptr; - - /* If 'authdone' is FALSE, we must not set the write socket index to the - Curl_transfer() call below, as we're not ready to actually upload any - data yet. */ switch(httpreq) { - case HTTPREQ_PUT: /* Let's PUT the data to the server! */ if(conn->bits.authneg) @@ -2531,20 +2569,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, return result; } - /* For really small puts we don't use Expect: headers at all, and for - the somewhat bigger ones we allow the app to disable it. Just make - sure that the expect100header is always set to the preferred value - here. */ - ptr = Curl_checkheaders(data, STRCONST("Expect")); - if(ptr) { - data->state.expect100header = - Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue")); - } - else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) { - result = expect100(data, conn, r); - if(result) - return result; - } + result = addexpect(data, conn, r); + if(result) + return result; /* end of headers */ result = Curl_dyn_addn(r, STRCONST("\r\n")); @@ -2617,22 +2644,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, } #endif - /* For really small posts we don't use Expect: headers at all, and for - the somewhat bigger ones we allow the app to disable it. Just make - sure that the expect100header is always set to the preferred value - here. */ - ptr = Curl_checkheaders(data, STRCONST("Expect")); - if(ptr) { - data->state.expect100header = - Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue")); - } - else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) { - result = expect100(data, conn, r); - if(result) - return result; - } - else - data->state.expect100header = FALSE; + result = addexpect(data, conn, r); + if(result) + return result; /* make the request end in a true CRLF */ result = Curl_dyn_addn(r, STRCONST("\r\n")); @@ -2692,22 +2706,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, return result; } - /* For really small posts we don't use Expect: headers at all, and for - the somewhat bigger ones we allow the app to disable it. Just make - sure that the expect100header is always set to the preferred value - here. */ - ptr = Curl_checkheaders(data, STRCONST("Expect")); - if(ptr) { - data->state.expect100header = - Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue")); - } - else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) { - result = expect100(data, conn, r); - if(result) - return result; - } - else - data->state.expect100header = FALSE; + result = addexpect(data, conn, r); + if(result) + return result; #ifndef USE_HYPER /* With Hyper the body is always passed on separately */ @@ -3193,7 +3194,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) DEBUGASSERT(Curl_conn_is_http2(data, conn, FIRSTSOCKET)); break; case CURL_HTTP_VERSION_1_1: - /* continue with HTTP/1.1 when explicitly requested */ + /* continue with HTTP/1.x when explicitly requested */ break; default: /* Check if user wants to use HTTP/2 with clear TCP */ @@ -3685,7 +3686,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, k->content_range = TRUE; } } - else + else if(k->httpcode < 300) data->state.resume_from = 0; /* get everything */ } #if !defined(CURL_DISABLE_COOKIES) @@ -3996,35 +3997,30 @@ CURLcode Curl_bump_headersize(struct Curl_easy *data, */ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, struct connectdata *conn, - ssize_t *nread, - bool *stop_reading) + const char *buf, size_t blen, + size_t *pconsumed) { CURLcode result; struct SingleRequest *k = &data->req; - ssize_t onread = *nread; - char *ostr = k->str; char *headp; - char *str_start; char *end_ptr; /* header line within buffer loop */ + *pconsumed = 0; do { - size_t rest_length; - size_t full_length; + size_t line_length; int writetype; - /* str_start is start of line within buf */ - str_start = k->str; - /* data is in network encoding so use 0x0a instead of '\n' */ - end_ptr = memchr(str_start, 0x0a, *nread); + end_ptr = memchr(buf, 0x0a, blen); if(!end_ptr) { /* Not a complete header line within buffer, append the data to the end of the headerbuff. */ - result = Curl_dyn_addn(&data->state.headerb, str_start, *nread); + result = Curl_dyn_addn(&data->state.headerb, buf, blen); if(result) return result; + *pconsumed += blen; if(!k->headerline) { /* check if this looks like a protocol header */ @@ -4036,31 +4032,28 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if(st == STATUS_BAD) { /* this is not the beginning of a protocol first header line */ k->header = FALSE; - k->badheader = HEADER_ALLBAD; + k->badheader = TRUE; streamclose(conn, "bad HTTP: No end-of-message indicator"); if(!data->set.http09_allowed) { failf(data, "Received HTTP/0.9 when not allowed"); return CURLE_UNSUPPORTED_PROTOCOL; } - break; + goto out; } } - - break; /* read more and try again */ + goto out; /* read more and try again */ } /* decrease the size of the remaining (supposed) header line */ - rest_length = (end_ptr - k->str) + 1; - *nread -= (ssize_t)rest_length; - - k->str = end_ptr + 1; /* move past new line */ - - full_length = k->str - str_start; - - result = Curl_dyn_addn(&data->state.headerb, str_start, full_length); + line_length = (end_ptr - buf) + 1; + result = Curl_dyn_addn(&data->state.headerb, buf, line_length); if(result) return result; + blen -= line_length; + buf += line_length; + *pconsumed += line_length; + /**** * We now have a FULL header line in 'headerb'. *****/ @@ -4078,14 +4071,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, return CURLE_UNSUPPORTED_PROTOCOL; } k->header = FALSE; - if(*nread) + if(blen) /* since there's more, this is a partial bad header */ - k->badheader = HEADER_PARTHEADER; + k->badheader = TRUE; else { /* this was all we read so it's all a bad header */ - k->badheader = HEADER_ALLBAD; - *nread = onread; - k->str = ostr; + k->badheader = TRUE; return CURLE_OK; } break; @@ -4139,22 +4130,23 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, /* switch to http2 now. The bytes after response headers are also processed here, otherwise they are lost. */ - result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, - k->str, *nread); + result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen); if(result) return result; - *nread = 0; + *pconsumed += blen; + blen = 0; } #ifdef USE_WEBSOCKETS else if(k->upgr101 == UPGR101_WS) { /* verify the response */ - result = Curl_ws_accept(data, k->str, *nread); + result = Curl_ws_accept(data, buf, blen); if(result) return result; k->header = FALSE; /* no more header to parse! */ if(data->set.connect_only) { k->keepon &= ~KEEP_RECV; /* read no more content */ - *nread = 0; + *pconsumed += blen; + blen = 0; } } #endif @@ -4366,7 +4358,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * out and return home. */ if(data->req.no_body) - *stop_reading = TRUE; + k->download_done = TRUE; #ifndef CURL_DISABLE_RTSP else if((conn->handler->protocol & CURLPROTO_RTSP) && (data->set.rtspreq == RTSPREQ_DESCRIBE) && @@ -4375,7 +4367,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, absent, a length 0 must be assumed. It will prevent libcurl from hanging on DESCRIBE request that got refused for whatever reason */ - *stop_reading = TRUE; + k->download_done = TRUE; #endif /* If max download size is *zero* (nothing) we already have @@ -4386,15 +4378,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if(0 == k->maxdownload && !Curl_conn_is_http2(data, conn, FIRSTSOCKET) && !Curl_conn_is_http3(data, conn, FIRSTSOCKET)) - *stop_reading = TRUE; + k->download_done = TRUE; - if(*stop_reading) { - /* we make sure that this socket isn't read more now */ - k->keepon &= ~KEEP_RECV; - } - - Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen); - break; /* exit header line loop */ + Curl_debug(data, CURLINFO_HEADER_IN, + Curl_dyn_ptr(&data->state.headerb), + Curl_dyn_len(&data->state.headerb)); + goto out; /* exit header line loop */ } /* We continue reading headers, reset the line-based header */ @@ -4583,12 +4572,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, Curl_dyn_reset(&data->state.headerb); } - while(*k->str); /* header line within buffer */ + while(blen); /* We might have reached the end of the header part here, but there might be a non-header part left in the end of the read buffer. */ - +out: return CURLE_OK; } @@ -4618,17 +4607,6 @@ out: return result; } -/* simple implementation of strndup(), which isn't portable */ -static char *my_strndup(const char *ptr, size_t len) -{ - char *copy = malloc(len + 1); - if(!copy) - return NULL; - memcpy(copy, ptr, len); - copy[len] = '\0'; - return copy; -} - CURLcode Curl_http_req_make(struct httpreq **preq, const char *method, size_t m_len, const char *scheme, size_t s_len, @@ -4647,17 +4625,17 @@ CURLcode Curl_http_req_make(struct httpreq **preq, goto out; memcpy(req->method, method, m_len); if(scheme) { - req->scheme = my_strndup(scheme, s_len); + req->scheme = Curl_strndup(scheme, s_len); if(!req->scheme) goto out; } if(authority) { - req->authority = my_strndup(authority, a_len); + req->authority = Curl_strndup(authority, a_len); if(!req->authority) goto out; } if(path) { - req->path = my_strndup(path, p_len); + req->path = Curl_strndup(path, p_len); if(!req->path) goto out; } diff --git a/libs/libcurl/src/http.h b/libs/libcurl/src/http.h index fc4f518530..f7571ebdb0 100644 --- a/libs/libcurl/src/http.h +++ b/libs/libcurl/src/http.h @@ -227,8 +227,8 @@ CURLcode Curl_http_size(struct Curl_easy *data); CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, struct connectdata *conn, - ssize_t *nread, - bool *stop_reading); + const char *buf, size_t blen, + size_t *pconsumed); /** * Curl_http_output_auth() setups the authentication headers for the @@ -263,7 +263,7 @@ CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len); * All about a core HTTP request, excluding body and trailers */ struct httpreq { - char method[12]; + char method[24]; char *scheme; char *authority; char *path; diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c index ba3bfef61c..6a7d18379d 100644 --- a/libs/libcurl/src/http2.c +++ b/libs/libcurl/src/http2.c @@ -107,14 +107,14 @@ static int populate_settings(nghttp2_settings_entry *iv, return 3; } -static size_t populate_binsettings(uint8_t *binsettings, - struct Curl_easy *data) +static ssize_t populate_binsettings(uint8_t *binsettings, + struct Curl_easy *data) { nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN]; int ivlen; ivlen = populate_settings(iv, data); - /* this returns number of bytes it wrote */ + /* this returns number of bytes it wrote or a negative number on error. */ return nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, iv, ivlen); } @@ -369,12 +369,15 @@ static ssize_t nw_out_writer(void *writer_ctx, { struct Curl_cfilter *cf = writer_ctx; struct Curl_easy *data = CF_DATA_CURRENT(cf); - ssize_t nwritten; - nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err); - if(nwritten > 0) - CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten); - return nwritten; + if(data) { + ssize_t nwritten = Curl_conn_cf_send(cf->next, data, + (const char *)buf, buflen, err); + if(nwritten > 0) + CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten); + return nwritten; + } + return 0; } static ssize_t send_callback(nghttp2_session *h2, @@ -452,9 +455,14 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf, * in the H1 request and we upgrade from there. This stream * is opened implicitly as #1. */ uint8_t binsettings[H2_BINSETTINGS_LEN]; - size_t binlen; /* length of the binsettings data */ + ssize_t binlen; /* length of the binsettings data */ binlen = populate_binsettings(binsettings, data); + if(binlen <= 0) { + failf(data, "nghttp2 unexpectedly failed on pack_settings_payload"); + result = CURLE_FAILED_INIT; + goto out; + } result = http2_data_setup(cf, data, &stream); if(result) @@ -1076,16 +1084,11 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf, stream->reset = TRUE; } stream->send_closed = TRUE; - data->req.keepon &= ~KEEP_SEND_HOLD; drain_stream(cf, data, stream); break; case NGHTTP2_WINDOW_UPDATE: - if((data->req.keepon & KEEP_SEND_HOLD) && - (data->req.keepon & KEEP_SEND)) { - data->req.keepon &= ~KEEP_SEND_HOLD; + if(CURL_WANT_SEND(data)) { drain_stream(cf, data, stream); - CURL_TRC_CF(data, cf, "[%d] un-holding after win update", - stream_id); } break; default: @@ -1230,15 +1233,10 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, * window and *assume* that we treat this like a WINDOW_UPDATE. Some * servers send an explicit WINDOW_UPDATE, but not all seem to do that. * To be safe, we UNHOLD a stream in order not to stall. */ - if((data->req.keepon & KEEP_SEND_HOLD) && - (data->req.keepon & KEEP_SEND)) { + if(CURL_WANT_SEND(data)) { struct stream_ctx *stream = H2_STREAM_CTX(data); - data->req.keepon &= ~KEEP_SEND_HOLD; - if(stream) { + if(stream) drain_stream(cf, data, stream); - CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS", - stream_id); - } } } break; @@ -1338,7 +1336,6 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, stream->error = error_code; if(stream->error) stream->reset = TRUE; - data_s->req.keepon &= ~KEEP_SEND_HOLD; if(stream->error) CURL_TRC_CF(data_s, cf, "[%d] RESET: %s (err %d)", @@ -1602,10 +1599,10 @@ static int error_callback(nghttp2_session *session, size_t len, void *userp) { + struct Curl_cfilter *cf = userp; + struct Curl_easy *data = CF_DATA_CURRENT(cf); (void)session; - (void)msg; - (void)len; - (void)userp; + failf(data, "%.*s", (int)len, msg); return 0; } #endif @@ -1621,7 +1618,7 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req, size_t blen; struct SingleRequest *k = &data->req; uint8_t binsettings[H2_BINSETTINGS_LEN]; - size_t binlen; /* length of the binsettings data */ + ssize_t binlen; /* length of the binsettings data */ binlen = populate_binsettings(binsettings, data); if(binlen <= 0) { @@ -2052,23 +2049,13 @@ static ssize_t h2_submit(struct stream_ctx **pstream, /* no longer needed */ Curl_h1_req_parse_free(&stream->h1); - nheader = Curl_dynhds_count(&h2_headers); - nva = malloc(sizeof(nghttp2_nv) * nheader); + nva = Curl_dynhds_to_nva(&h2_headers, &nheader); if(!nva) { *err = CURLE_OUT_OF_MEMORY; nwritten = -1; goto out; } - for(i = 0; i < nheader; ++i) { - struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i); - nva[i].name = (unsigned char *)e->name; - nva[i].namelen = e->namelen; - nva[i].value = (unsigned char *)e->value; - nva[i].valuelen = e->valuelen; - nva[i].flags = NGHTTP2_NV_FLAG_NONE; - } - h2_pri_spec(data, &pri_spec); if(!nghttp2_session_check_request_allowed(ctx->h2)) CURL_TRC_CF(data, cf, "send request NOT allowed (via nghttp2)"); @@ -2272,14 +2259,6 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data, * frame buffer or our network out buffer. */ size_t rwin = nghttp2_session_get_stream_remote_window_size(ctx->h2, stream->id); - if(rwin == 0) { - /* H2 flow window exhaustion. We need to HOLD upload until we get - * a WINDOW_UPDATE from the server. */ - data->req.keepon |= KEEP_SEND_HOLD; - CURL_TRC_CF(data, cf, "[%d] holding send as remote flow " - "window is exhausted", stream->id); - } - /* Whatever the cause, we need to return CURL_EAGAIN for this call. * We have unwritten state that needs us being invoked again and EAGAIN * is the only way to ensure that. */ @@ -2331,38 +2310,34 @@ out: return nwritten; } -static int cf_h2_get_select_socks(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t *sock) +static void cf_h2_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps) { struct cf_h2_ctx *ctx = cf->ctx; - struct SingleRequest *k = &data->req; - struct stream_ctx *stream = H2_STREAM_CTX(data); - int bitmap = GETSOCK_BLANK; - struct cf_call_data save; + bool want_recv = CURL_WANT_RECV(data); + bool want_send = CURL_WANT_SEND(data); - CF_DATA_SAVE(save, cf, data); - sock[0] = Curl_conn_cf_get_socket(cf, data); - - if(!(k->keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD))) - /* Unless paused - in an HTTP/2 connection we can basically always get a - frame so we should always be ready for one */ - bitmap |= GETSOCK_READSOCK(0); - - /* we're (still uploading OR the HTTP/2 layer wants to send data) AND - there's a window to send data in */ - if((((k->keepon & KEEP_SENDBITS) == KEEP_SEND) || - nghttp2_session_want_write(ctx->h2)) && - (nghttp2_session_get_remote_window_size(ctx->h2) && - nghttp2_session_get_stream_remote_window_size(ctx->h2, - stream->id))) - bitmap |= GETSOCK_WRITESOCK(0); + if(ctx->h2 && (want_recv || want_send)) { + struct stream_ctx *stream = H2_STREAM_CTX(data); + curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); + struct cf_call_data save; + bool c_exhaust, s_exhaust; - CF_DATA_RESTORE(cf, save); - return bitmap; + CF_DATA_SAVE(save, cf, data); + c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2); + s_exhaust = stream && stream->id >= 0 && + !nghttp2_session_get_stream_remote_window_size(ctx->h2, + stream->id); + want_recv = (want_recv || c_exhaust || s_exhaust); + want_send = (!s_exhaust && want_send) || + (!c_exhaust && nghttp2_session_want_write(ctx->h2)); + + Curl_pollset_set(data, ps, sock, want_recv, want_send); + CF_DATA_RESTORE(cf, save); + } } - static CURLcode cf_h2_connect(struct Curl_cfilter *cf, struct Curl_easy *data, bool blocking, bool *done) @@ -2511,14 +2486,15 @@ static CURLcode cf_h2_cntrl(struct Curl_cfilter *cf, case CF_CTRL_DATA_PAUSE: result = http2_data_pause(cf, data, (arg1 != 0)); break; - case CF_CTRL_DATA_DONE_SEND: { + case CF_CTRL_DATA_DONE_SEND: result = http2_data_done_send(cf, data); break; - } - case CF_CTRL_DATA_DONE: { + case CF_CTRL_DATA_DETACH: + http2_data_done(cf, data, TRUE); + break; + case CF_CTRL_DATA_DONE: http2_data_done(cf, data, arg1 != 0); break; - } default: break; } @@ -2606,7 +2582,7 @@ struct Curl_cftype Curl_cft_nghttp2 = { cf_h2_connect, cf_h2_close, Curl_cf_def_get_host, - cf_h2_get_select_socks, + cf_h2_adjust_pollset, cf_h2_data_pending, cf_h2_send, cf_h2_recv, @@ -2626,7 +2602,7 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf, CURLcode result = CURLE_OUT_OF_MEMORY; DEBUGASSERT(data->conn); - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) goto out; @@ -2652,7 +2628,7 @@ static CURLcode http2_cfilter_insert_after(struct Curl_cfilter *cf, CURLcode result = CURLE_OUT_OF_MEMORY; (void)data; - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) goto out; diff --git a/libs/libcurl/src/http_aws_sigv4.c b/libs/libcurl/src/http_aws_sigv4.c index 8bbc022511..0313026562 100644 --- a/libs/libcurl/src/http_aws_sigv4.c +++ b/libs/libcurl/src/http_aws_sigv4.c @@ -456,6 +456,7 @@ static CURLcode canon_query(struct Curl_easy *data, for(i = 0; !result && (i < entry); i++, ap++) { size_t len; const char *q = ap->p; + bool found_equals = false; if(!ap->len) continue; for(len = ap->len; len && !result; q++, len--) { @@ -467,9 +468,13 @@ static CURLcode canon_query(struct Curl_easy *data, case '.': case '_': case '~': + /* allowed as-is */ + result = Curl_dyn_addn(dq, q, 1); + break; case '=': /* allowed as-is */ result = Curl_dyn_addn(dq, q, 1); + found_equals = true; break; case '%': /* uppercase the following if hexadecimal */ @@ -497,7 +502,11 @@ static CURLcode canon_query(struct Curl_easy *data, } } } - if(i < entry - 1) { + if(!result && !found_equals) { + /* queries without value still need an equals */ + result = Curl_dyn_addn(dq, "=", 1); + } + if(!result && i < entry - 1) { /* insert ampersands between query pairs */ result = Curl_dyn_addn(dq, "&", 1); } diff --git a/libs/libcurl/src/http_chunks.c b/libs/libcurl/src/http_chunks.c index 5541dd5b1b..0d6d6302a4 100644 --- a/libs/libcurl/src/http_chunks.c +++ b/libs/libcurl/src/http_chunks.c @@ -75,8 +75,6 @@ */ -#define isxdigit_ascii(x) Curl_isxdigit(x) - void Curl_httpchunk_init(struct Curl_easy *data) { struct connectdata *conn = data->conn; @@ -98,9 +96,9 @@ void Curl_httpchunk_init(struct Curl_easy *data) * For example, 0x0d and 0x0a are used instead of '\r' and '\n'. */ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, - char *datap, - ssize_t datalen, - ssize_t *wrote, + char *buf, + size_t blen, + size_t *pconsumed, CURLcode *extrap) { CURLcode result = CURLE_OK; @@ -108,28 +106,27 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, struct Curl_chunker *ch = &conn->chunk; struct SingleRequest *k = &data->req; size_t piece; - curl_off_t length = (curl_off_t)datalen; - *wrote = 0; /* nothing's written yet */ + *pconsumed = 0; /* nothing's written yet */ /* the original data is written to the client, but we go on with the chunk read process, to properly calculate the content length */ if(data->set.http_te_skip && !k->ignorebody) { - result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen); + result = Curl_client_write(data, CLIENTWRITE_BODY, buf, blen); if(result) { *extrap = result; return CHUNKE_PASSTHRU_ERROR; } } - while(length) { + while(blen) { switch(ch->state) { case CHUNK_HEX: - if(ISXDIGIT(*datap)) { + if(ISXDIGIT(*buf)) { if(ch->hexindex < CHUNK_MAXNUM_LEN) { - ch->hexbuffer[ch->hexindex] = *datap; - datap++; - length--; + ch->hexbuffer[ch->hexindex] = *buf; + buf++; + blen--; ch->hexindex++; } else { @@ -143,7 +140,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, a hexadecimal digit. */ return CHUNKE_ILLEGAL_HEX; - /* length and datap are unmodified */ + /* blen and buf are unmodified */ ch->hexbuffer[ch->hexindex] = 0; if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize)) @@ -154,7 +151,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, case CHUNK_LF: /* waiting for the LF after a chunk size */ - if(*datap == 0x0a) { + if(*buf == 0x0a) { /* we're now expecting data to come, unless size was zero! */ if(0 == ch->datasize) { ch->state = CHUNK_TRAILER; /* now check for trailers */ @@ -163,19 +160,21 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, ch->state = CHUNK_DATA; } - datap++; - length--; + buf++; + blen--; break; case CHUNK_DATA: - /* We expect 'datasize' of data. We have 'length' right now, it can be + /* We expect 'datasize' of data. We have 'blen' right now, it can be more or less than 'datasize'. Get the smallest piece. */ - piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize); + piece = blen; + if(ch->datasize < (curl_off_t)blen) + piece = curlx_sotouz(ch->datasize); /* Write the data portion available */ if(!data->set.http_te_skip && !k->ignorebody) { - result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece); + result = Curl_client_write(data, CLIENTWRITE_BODY, buf, piece); if(result) { *extrap = result; @@ -183,10 +182,10 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, } } - *wrote += piece; + *pconsumed += piece; ch->datasize -= piece; /* decrease amount left to expect */ - datap += piece; /* move read pointer forward */ - length -= piece; /* decrease space left in this round */ + buf += piece; /* move read pointer forward */ + blen -= piece; /* decrease space left in this round */ if(0 == ch->datasize) /* end of data this round, we now expect a trailing CRLF */ @@ -194,18 +193,18 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, break; case CHUNK_POSTLF: - if(*datap == 0x0a) { + if(*buf == 0x0a) { /* The last one before we go back to hex state and start all over. */ Curl_httpchunk_init(data); /* sets state back to CHUNK_HEX */ } - else if(*datap != 0x0d) + else if(*buf != 0x0d) return CHUNKE_BAD_CHUNK; - datap++; - length--; + buf++; + blen--; break; case CHUNK_TRAILER: - if((*datap == 0x0d) || (*datap == 0x0a)) { + if((*buf == 0x0d) || (*buf == 0x0a)) { char *tr = Curl_dyn_ptr(&conn->trailer); /* this is the end of a trailer, but if the trailer was zero bytes there was no trailer and we move on */ @@ -229,7 +228,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, } Curl_dyn_reset(&conn->trailer); ch->state = CHUNK_TRAILER_CR; - if(*datap == 0x0a) + if(*buf == 0x0a) /* already on the LF */ break; } @@ -240,19 +239,19 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, } } else { - result = Curl_dyn_addn(&conn->trailer, datap, 1); + result = Curl_dyn_addn(&conn->trailer, buf, 1); if(result) return CHUNKE_OUT_OF_MEMORY; } - datap++; - length--; + buf++; + blen--; break; case CHUNK_TRAILER_CR: - if(*datap == 0x0a) { + if(*buf == 0x0a) { ch->state = CHUNK_TRAILER_POSTCR; - datap++; - length--; + buf++; + blen--; } else return CHUNKE_BAD_CHUNK; @@ -261,27 +260,27 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, case CHUNK_TRAILER_POSTCR: /* We enter this state when a CR should arrive so we expect to have to first pass a CR before we wait for LF */ - if((*datap != 0x0d) && (*datap != 0x0a)) { + if((*buf != 0x0d) && (*buf != 0x0a)) { /* not a CR then it must be another header in the trailer */ ch->state = CHUNK_TRAILER; break; } - if(*datap == 0x0d) { + if(*buf == 0x0d) { /* skip if CR */ - datap++; - length--; + buf++; + blen--; } /* now wait for the final LF */ ch->state = CHUNK_STOP; break; case CHUNK_STOP: - if(*datap == 0x0a) { - length--; + if(*buf == 0x0a) { + blen--; /* Record the length of any data left in the end of the buffer even if there's no more chunks to read */ - ch->datasize = curlx_sotouz(length); + ch->datasize = blen; return CHUNKE_STOP; /* return stop */ } diff --git a/libs/libcurl/src/http_chunks.h b/libs/libcurl/src/http_chunks.h index 5a84b92695..3c228f84eb 100644 --- a/libs/libcurl/src/http_chunks.h +++ b/libs/libcurl/src/http_chunks.h @@ -93,8 +93,8 @@ struct Curl_chunker { /* The following functions are defined in http_chunks.c */ void Curl_httpchunk_init(struct Curl_easy *data); -CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap, - ssize_t length, ssize_t *wrote, +CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *buf, + size_t blen, size_t *pconsumed, CURLcode *passthru); #endif /* HEADER_CURL_HTTP_CHUNKS_H */ diff --git a/libs/libcurl/src/http_proxy.c b/libs/libcurl/src/http_proxy.c index 4c247cc96e..56bf385e70 100644 --- a/libs/libcurl/src/http_proxy.c +++ b/libs/libcurl/src/http_proxy.c @@ -299,7 +299,7 @@ struct Curl_cftype Curl_cft_http_proxy = { http_proxy_cf_connect, http_proxy_cf_close, Curl_cf_http_proxy_get_host, - Curl_cf_def_get_select_socks, + Curl_cf_def_adjust_pollset, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, diff --git a/libs/libcurl/src/idn.c b/libs/libcurl/src/idn.c index b409039ade..493cc59c1c 100644 --- a/libs/libcurl/src/idn.c +++ b/libs/libcurl/src/idn.c @@ -36,7 +36,7 @@ #ifdef USE_LIBIDN2 #include -#if defined(WIN32) && defined(UNICODE) +#if defined(_WIN32) && defined(UNICODE) #define IDN2_LOOKUP(name, host, flags) \ idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags) #else diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c index e444457442..d4abe3568c 100644 --- a/libs/libcurl/src/imap.c +++ b/libs/libcurl/src/imap.c @@ -1194,8 +1194,6 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data, if(result) return result; - data->req.bytecount += chunk; - infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU " bytes are left for transfer", chunk, size - chunk); @@ -1430,7 +1428,7 @@ static CURLcode imap_init(struct Curl_easy *data) CURLcode result = CURLE_OK; struct IMAP *imap; - imap = data->req.p.imap = calloc(sizeof(struct IMAP), 1); + imap = data->req.p.imap = calloc(1, sizeof(struct IMAP)); if(!imap) result = CURLE_OUT_OF_MEMORY; diff --git a/libs/libcurl/src/ldap.c b/libs/libcurl/src/ldap.c index a67a487a89..16e851dcec 100644 --- a/libs/libcurl/src/ldap.c +++ b/libs/libcurl/src/ldap.c @@ -313,7 +313,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) int ldap_ssl = 0; char *val_b64 = NULL; size_t val_b64_sz = 0; - curl_off_t dlsize = 0; #ifdef LDAP_OPT_NETWORK_TIMEOUT struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */ #endif @@ -327,7 +326,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) *done = TRUE; /* unconditionally */ infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d", - LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); + LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); infof(data, "LDAP local: %s", data->state.url); #ifdef HAVE_LDAP_URL_PARSE @@ -345,7 +344,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) if(conn->given->flags & PROTOPT_SSL) ldap_ssl = 1; infof(data, "LDAP local: trying to establish %s connection", - ldap_ssl ? "encrypted" : "cleartext"); + ldap_ssl ? "encrypted" : "cleartext"); #if defined(USE_WIN32_LDAP) host = curlx_convert_UTF8_to_tchar(conn->host.name); @@ -535,6 +534,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } + Curl_pgrsSetDownloadCounter(data, 0); rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg); @@ -596,8 +596,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } - dlsize += name_len + 5; - FREE_ON_WINLDAP(name); ldap_memfree(dn); } @@ -659,8 +657,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } - dlsize += attr_len + 3; - if((attr_len > 7) && (strcmp(";binary", attr + (attr_len - 7)) == 0)) { /* Binary attribute, encode to base64. */ @@ -689,8 +685,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } - - dlsize += val_b64_sz; } } else { @@ -705,8 +699,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } - - dlsize += vals[i]->bv_len; } result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); @@ -719,8 +711,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } - - dlsize++; } /* Free memory used to store values */ @@ -734,10 +724,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(result) goto quit; - dlsize++; - result = Curl_pgrsSetDownloadCounter(data, dlsize); - if(result) - goto quit; } if(ber) diff --git a/libs/libcurl/src/libcurl.plist b/libs/libcurl/src/libcurl.plist index 216f07a612..7c4364f8d8 100644 --- a/libs/libcurl/src/libcurl.plist +++ b/libs/libcurl/src/libcurl.plist @@ -15,7 +15,7 @@ se.curl.libcurl CFBundleVersion - 8.4.0 + 8.5.0 CFBundleName libcurl @@ -27,9 +27,9 @@ ???? CFBundleShortVersionString - libcurl 8.4.0 + libcurl 8.5.0 CFBundleGetInfoString - libcurl.plist 8.4.0 + libcurl.plist 8.5.0 diff --git a/libs/libcurl/src/md4.c b/libs/libcurl/src/md4.c index c7ce9e6d80..7aae719266 100644 --- a/libs/libcurl/src/md4.c +++ b/libs/libcurl/src/md4.c @@ -32,9 +32,8 @@ #include "warnless.h" #ifdef USE_OPENSSL -#include -#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \ - !defined(USE_AMISSL) +#include +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) && !defined(USE_AMISSL) /* OpenSSL 3.0.0 marks the MD4 functions as deprecated */ #define OPENSSL_NO_MD4 #endif diff --git a/libs/libcurl/src/memdebug.c b/libs/libcurl/src/memdebug.c index 88f0ee81b2..869d9ca54d 100644 --- a/libs/libcurl/src/memdebug.c +++ b/libs/libcurl/src/memdebug.c @@ -208,7 +208,7 @@ ALLOC_FUNC char *curl_dbg_strdup(const char *str, return mem; } -#if defined(WIN32) && defined(UNICODE) +#if defined(_WIN32) && defined(UNICODE) ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source) { diff --git a/libs/libcurl/src/memdebug.h b/libs/libcurl/src/memdebug.h index 412744fba5..a3a701011e 100644 --- a/libs/libcurl/src/memdebug.h +++ b/libs/libcurl/src/memdebug.h @@ -64,7 +64,7 @@ CURL_EXTERN ALLOC_SIZE(2) void *curl_dbg_realloc(void *ptr, CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source); CURL_EXTERN ALLOC_FUNC char *curl_dbg_strdup(const char *str, int line, const char *src); -#if defined(WIN32) && defined(UNICODE) +#if defined(_WIN32) && defined(UNICODE) CURL_EXTERN ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source); @@ -121,7 +121,7 @@ CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source); #define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__) #define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__) -#ifdef WIN32 +#ifdef _WIN32 # ifdef UNICODE # undef wcsdup # define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c index 19ac72c49f..007a187bf5 100644 --- a/libs/libcurl/src/mime.c +++ b/libs/libcurl/src/mime.c @@ -48,7 +48,7 @@ #include "curl_memory.h" #include "memdebug.h" -#ifdef WIN32 +#ifdef _WIN32 # ifndef R_OK # define R_OK 4 # endif @@ -311,8 +311,7 @@ static char *escape_string(struct Curl_easy *data, table = formtable; /* data can be NULL when this function is called indirectly from curl_formget(). */ - if(strategy == MIMESTRATEGY_MAIL || - (data && (data->set.mime_options & CURLMIMEOPT_FORMESCAPE))) + if(strategy == MIMESTRATEGY_MAIL || (data && (data->set.mime_formescape))) table = mimetable; Curl_dyn_init(&db, CURL_MAX_INPUT_LENGTH); diff --git a/libs/libcurl/src/mprintf.c b/libs/libcurl/src/mprintf.c index c4eeb8c836..cb91b6429a 100644 --- a/libs/libcurl/src/mprintf.c +++ b/libs/libcurl/src/mprintf.c @@ -66,9 +66,7 @@ * Non-ANSI integer extensions */ -#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \ - (defined(__POCC__) && defined(_MSC_VER)) || \ - (defined(_WIN32_WCE)) || \ +#if (defined(_WIN32_WCE)) || \ (defined(__MINGW32__)) || \ (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)) # define MP_HAVE_INT_EXTENSIONS @@ -1071,9 +1069,6 @@ static int alloc_addbyter(int output, FILE *data) return outc; /* fputc() returns like this on success */ } -extern int Curl_dyn_vprintf(struct dynbuf *dyn, - const char *format, va_list ap_save); - /* appends the formatted string, returns 0 on success, 1 on error */ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save) { diff --git a/libs/libcurl/src/mqtt.c b/libs/libcurl/src/mqtt.c index 712b736250..530d929e5e 100644 --- a/libs/libcurl/src/mqtt.c +++ b/libs/libcurl/src/mqtt.c @@ -616,9 +616,6 @@ static void mqstate(struct Curl_easy *data, } -/* for the publish packet */ -#define MQTT_HEADER_LEN 5 /* max 5 bytes */ - static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; @@ -677,7 +674,6 @@ MQTT_SUBACK_COMING: /* FALLTHROUGH */ case MQTT_PUB_REMAIN: { /* read rest of packet, but no more. Cap to buffer size */ - struct SingleRequest *k = &data->req; size_t rest = mq->npacket; if(rest > (size_t)data->set.buffer_size) rest = (size_t)data->set.buffer_size; @@ -693,13 +689,8 @@ MQTT_SUBACK_COMING: result = CURLE_PARTIAL_FILE; goto end; } - Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread); mq->npacket -= nread; - k->bytecount += nread; - result = Curl_pgrsSetDownloadCounter(data, k->bytecount); - if(result) - goto end; /* if QoS is set, message contains packet id */ diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c index c655e3ae48..8e6f2c739d 100644 --- a/libs/libcurl/src/multi.c +++ b/libs/libcurl/src/multi.c @@ -55,22 +55,6 @@ #include "curl_memory.h" #include "memdebug.h" -#ifdef __APPLE__ - -#define wakeup_write write -#define wakeup_read read -#define wakeup_close close -#define wakeup_create pipe - -#else /* __APPLE__ */ - -#define wakeup_write swrite -#define wakeup_read sread -#define wakeup_close sclose -#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p) - -#endif /* __APPLE__ */ - /* CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every @@ -231,10 +215,6 @@ struct Curl_sh_entry { unsigned int readers; /* this many transfers want to read */ unsigned int writers; /* this many transfers want to write */ }; -/* bits for 'action' having no bits means this socket is not expecting any - action */ -#define SH_READ 1 -#define SH_WRITE 2 /* look up a given socket in the socket hash, skip invalid sockets */ static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh, @@ -416,9 +396,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ Curl_llist_init(&multi->msgsent, NULL); multi->multiplexing = TRUE; - - /* -1 means it not set by user, use the default value */ - multi->maxconnects = -1; multi->max_concurrent_streams = 100; #ifdef USE_WINSOCK @@ -1040,49 +1017,61 @@ static int protocol_getsock(struct Curl_easy *data, { if(conn->handler->proto_getsock) return conn->handler->proto_getsock(data, conn, socks); - return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks); + return GETSOCK_BLANK; } -/* returns bitmapped flags for this handle and its sockets. The 'socks[]' - array contains MAX_SOCKSPEREASYHANDLE entries. */ -static int multi_getsock(struct Curl_easy *data, - curl_socket_t *socks) +/* Initializes `poll_set` with the current socket poll actions needed + * for transfer `data`. */ +static void multi_getsock(struct Curl_easy *data, + struct easy_pollset *ps) { - struct connectdata *conn = data->conn; /* The no connection case can happen when this is called from curl_multi_remove_handle() => singlesocket() => multi_getsock(). */ - if(!conn) - return 0; + Curl_pollset_reset(data, ps); + if(!data->conn) + return; switch(data->mstate) { default: - return 0; + break; case MSTATE_RESOLVING: - return Curl_resolv_getsock(data, socks); + Curl_pollset_add_socks2(data, ps, Curl_resolv_getsock); + /* connection filters are not involved in this phase */ + return; case MSTATE_PROTOCONNECTING: case MSTATE_PROTOCONNECT: - return protocol_getsock(data, conn, socks); + Curl_pollset_add_socks(data, ps, protocol_getsock); + break; case MSTATE_DO: case MSTATE_DOING: - return doing_getsock(data, conn, socks); + Curl_pollset_add_socks(data, ps, doing_getsock); + break; case MSTATE_TUNNELING: case MSTATE_CONNECTING: - return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks); + break; case MSTATE_DOING_MORE: - return domore_getsock(data, conn, socks); + Curl_pollset_add_socks(data, ps, domore_getsock); + break; case MSTATE_DID: /* since is set after DO is completed, we switch to waiting for the same as the PERFORMING state */ case MSTATE_PERFORMING: - return Curl_single_getsock(data, conn, socks); + Curl_pollset_add_socks(data, ps, Curl_single_getsock); + break; + + case MSTATE_RATELIMITING: + /* nothing to wait for */ + return; } + /* Let connection filters add/remove as needed */ + Curl_conn_adjust_pollset(data, ps); } CURLMcode curl_multi_fdset(struct Curl_multi *multi, @@ -1094,8 +1083,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, and then we must make sure that is done. */ struct Curl_easy *data; int this_max_fd = -1; - curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; - int i; + struct easy_pollset ps; + unsigned int i; (void)exc_fd_set; /* not used */ if(!GOOD_MULTI_HANDLE(multi)) @@ -1104,29 +1093,20 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, if(multi->in_callback) return CURLM_RECURSIVE_API_CALL; + memset(&ps, 0, sizeof(ps)); for(data = multi->easyp; data; data = data->next) { - int bitmap; -#ifdef __clang_analyzer_ - /* to prevent "The left operand of '>=' is a garbage value" warnings */ - memset(sockbunch, 0, sizeof(sockbunch)); -#endif - bitmap = multi_getsock(data, sockbunch); - - for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { - if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) { - if(!FDSET_SOCK(sockbunch[i])) - /* pretend it doesn't exist */ - continue; - if(bitmap & GETSOCK_READSOCK(i)) - FD_SET(sockbunch[i], read_fd_set); - if(bitmap & GETSOCK_WRITESOCK(i)) - FD_SET(sockbunch[i], write_fd_set); - if((int)sockbunch[i] > this_max_fd) - this_max_fd = (int)sockbunch[i]; - } - else { - break; - } + multi_getsock(data, &ps); + + for(i = 0; i < ps.num; i++) { + if(!FDSET_SOCK(ps.sockets[i])) + /* pretend it doesn't exist */ + continue; + if(ps.actions[i] & CURL_POLL_IN) + FD_SET(ps.sockets[i], read_fd_set); + if(ps.actions[i] & CURL_POLL_OUT) + FD_SET(ps.sockets[i], write_fd_set); + if((int)ps.sockets[i] > this_max_fd) + this_max_fd = (int)ps.sockets[i]; } } @@ -1162,9 +1142,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi, bool use_wakeup) { struct Curl_easy *data; - curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; - int bitmap; - unsigned int i; + struct easy_pollset ps; + size_t i; unsigned int nfds = 0; unsigned int curlfds; long timeout_internal; @@ -1190,17 +1169,10 @@ static CURLMcode multi_wait(struct Curl_multi *multi, return CURLM_BAD_FUNCTION_ARGUMENT; /* Count up how many fds we have from the multi handle */ + memset(&ps, 0, sizeof(ps)); for(data = multi->easyp; data; data = data->next) { - bitmap = multi_getsock(data, sockbunch); - - for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) { - if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) { - ++nfds; - } - else { - break; - } - } + multi_getsock(data, &ps); + nfds += ps.num; } /* If the internally desired timeout is actually shorter than requested from @@ -1241,40 +1213,35 @@ static CURLMcode multi_wait(struct Curl_multi *multi, if(curlfds) { /* Add the curl handles to our pollfds first */ for(data = multi->easyp; data; data = data->next) { - bitmap = multi_getsock(data, sockbunch); + multi_getsock(data, &ps); - for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) { - if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) { - struct pollfd *ufd = &ufds[nfds++]; -#ifdef USE_WINSOCK - long mask = 0; -#endif - ufd->fd = sockbunch[i]; - ufd->events = 0; - if(bitmap & GETSOCK_READSOCK(i)) { + for(i = 0; i < ps.num; i++) { + struct pollfd *ufd = &ufds[nfds++]; #ifdef USE_WINSOCK - mask |= FD_READ|FD_ACCEPT|FD_CLOSE; + long mask = 0; #endif - ufd->events |= POLLIN; - } - if(bitmap & GETSOCK_WRITESOCK(i)) { + ufd->fd = ps.sockets[i]; + ufd->events = 0; + if(ps.actions[i] & CURL_POLL_IN) { #ifdef USE_WINSOCK - mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; - reset_socket_fdwrite(sockbunch[i]); + mask |= FD_READ|FD_ACCEPT|FD_CLOSE; #endif - ufd->events |= POLLOUT; - } + ufd->events |= POLLIN; + } + if(ps.actions[i] & CURL_POLL_OUT) { #ifdef USE_WINSOCK - if(WSAEventSelect(sockbunch[i], multi->wsa_event, mask) != 0) { - if(ufds_malloc) - free(ufds); - return CURLM_INTERNAL_ERROR; - } + mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; + reset_socket_fdwrite(ps.sockets[i]); #endif + ufd->events |= POLLOUT; } - else { - break; +#ifdef USE_WINSOCK + if(WSAEventSelect(ps.sockets[i], multi->wsa_event, mask) != 0) { + if(ufds_malloc) + free(ufds); + return CURLM_INTERNAL_ERROR; } +#endif } } } @@ -1386,21 +1353,16 @@ static CURLMcode multi_wait(struct Curl_multi *multi, if(curlfds) { for(data = multi->easyp; data; data = data->next) { - bitmap = multi_getsock(data, sockbunch); - - for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) { - if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) { - wsa_events.lNetworkEvents = 0; - if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) { - if(ret && !pollrc && wsa_events.lNetworkEvents) - retcode++; - } - WSAEventSelect(sockbunch[i], multi->wsa_event, 0); - } - else { - /* break on entry not checked for being readable or writable */ - break; + multi_getsock(data, &ps); + + for(i = 0; i < ps.num; i++) { + wsa_events.lNetworkEvents = 0; + if(WSAEnumNetworkEvents(ps.sockets[i], NULL, + &wsa_events) == 0) { + if(ret && !pollrc && wsa_events.lNetworkEvents) + retcode++; } + WSAEventSelect(ps.sockets[i], multi->wsa_event, 0); } } } @@ -2021,8 +1983,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(dns) { #ifdef CURLRES_ASYNCH - data->state.async.dns = dns; - data->state.async.done = TRUE; + conn->resolve_async.dns = dns; + conn->resolve_async.done = TRUE; #endif result = CURLE_OK; infof(data, "Hostname '%s' was found in DNS cache", hostname); @@ -2895,53 +2857,36 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue) static CURLMcode singlesocket(struct Curl_multi *multi, struct Curl_easy *data) { - curl_socket_t socks[MAX_SOCKSPEREASYHANDLE]; - int i; + struct easy_pollset cur_poll; + unsigned int i; struct Curl_sh_entry *entry; curl_socket_t s; - int num; - unsigned int curraction; - unsigned char actions[MAX_SOCKSPEREASYHANDLE]; int rc; - for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) - socks[i] = CURL_SOCKET_BAD; - /* Fill in the 'current' struct with the state as it is now: what sockets to supervise and for what actions */ - curraction = multi_getsock(data, socks); + multi_getsock(data, &cur_poll); /* We have 0 .. N sockets already and we get to know about the 0 .. M sockets we should have from now on. Detect the differences, remove no longer supervised ones and add new ones */ /* walk over the sockets we got right now */ - for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) && - (curraction & GETSOCK_MASK_RW(i)); - i++) { - unsigned char action = CURL_POLL_NONE; - unsigned char prevaction = 0; + for(i = 0; i < cur_poll.num; i++) { + unsigned char cur_action = cur_poll.actions[i]; + unsigned char last_action = 0; int comboaction; - bool sincebefore = FALSE; - s = socks[i]; + s = cur_poll.sockets[i]; /* get it from the hash */ entry = sh_getentry(&multi->sockhash, s); - - if(curraction & GETSOCK_READSOCK(i)) - action |= CURL_POLL_IN; - if(curraction & GETSOCK_WRITESOCK(i)) - action |= CURL_POLL_OUT; - - actions[i] = action; if(entry) { /* check if new for this transfer */ - int j; - for(j = 0; j< data->numsocks; j++) { - if(s == data->sockets[j]) { - prevaction = data->actions[j]; - sincebefore = TRUE; + unsigned int j; + for(j = 0; j< data->last_poll.num; j++) { + if(s == data->last_poll.sockets[j]) { + last_action = data->last_poll.actions[j]; break; } } @@ -2953,23 +2898,23 @@ static CURLMcode singlesocket(struct Curl_multi *multi, /* fatal */ return CURLM_OUT_OF_MEMORY; } - if(sincebefore && (prevaction != action)) { + if(last_action && (last_action != cur_action)) { /* Socket was used already, but different action now */ - if(prevaction & CURL_POLL_IN) + if(last_action & CURL_POLL_IN) entry->readers--; - if(prevaction & CURL_POLL_OUT) + if(last_action & CURL_POLL_OUT) entry->writers--; - if(action & CURL_POLL_IN) + if(cur_action & CURL_POLL_IN) entry->readers++; - if(action & CURL_POLL_OUT) + if(cur_action & CURL_POLL_OUT) entry->writers++; } - else if(!sincebefore) { - /* a new user */ + else if(!last_action) { + /* a new transfer using this socket */ entry->users++; - if(action & CURL_POLL_IN) + if(cur_action & CURL_POLL_IN) entry->readers++; - if(action & CURL_POLL_OUT) + if(cur_action & CURL_POLL_OUT) entry->writers++; /* add 'data' to the transfer hash on this socket! */ @@ -2980,11 +2925,11 @@ static CURLMcode singlesocket(struct Curl_multi *multi, } } - comboaction = (entry->writers? CURL_POLL_OUT : 0) | + comboaction = (entry->writers ? CURL_POLL_OUT : 0) | (entry->readers ? CURL_POLL_IN : 0); /* socket existed before and has the same action set as before */ - if(sincebefore && ((int)entry->action == comboaction)) + if(last_action && ((int)entry->action == comboaction)) /* same, continue */ continue; @@ -2992,6 +2937,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi, set_in_callback(multi, TRUE); rc = multi->socket_cb(data, s, comboaction, multi->socket_userp, entry->socketp); + set_in_callback(multi, FALSE); if(rc == -1) { multi->dead = TRUE; @@ -3002,16 +2948,15 @@ static CURLMcode singlesocket(struct Curl_multi *multi, entry->action = comboaction; /* store the current action state */ } - num = i; /* number of sockets */ - - /* when we've walked over all the sockets we should have right now, we must - make sure to detect sockets that are removed */ - for(i = 0; i< data->numsocks; i++) { - int j; + /* Check for last_poll.sockets that no longer appear in cur_poll.sockets. + * Need to remove the easy handle from the multi->sockhash->transfers and + * remove multi->sockhash entry when this was the last transfer */ + for(i = 0; i< data->last_poll.num; i++) { + unsigned int j; bool stillused = FALSE; - s = data->sockets[i]; - for(j = 0; j < num; j++) { - if(s == socks[j]) { + s = data->last_poll.sockets[i]; + for(j = 0; j < cur_poll.num; j++) { + if(s == cur_poll.sockets[j]) { /* this is still supervised */ stillused = TRUE; break; @@ -3024,7 +2969,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi, /* if this is NULL here, the socket has been closed and notified so already by Curl_multi_closed() */ if(entry) { - unsigned char oldactions = data->actions[i]; + unsigned char oldactions = data->last_poll.actions[i]; /* this socket has been removed. Decrease user count */ entry->users--; if(oldactions & CURL_POLL_OUT) @@ -3052,11 +2997,10 @@ static CURLMcode singlesocket(struct Curl_multi *multi, } } } - } /* for loop over numsocks */ + } /* for loop over num */ - memcpy(data->sockets, socks, num*sizeof(curl_socket_t)); - memcpy(data->actions, actions, num*sizeof(char)); - data->numsocks = num; + /* Remember for next time */ + memcpy(&data->last_poll, &cur_poll, sizeof(data->last_poll)); return CURLM_OK; } @@ -3296,6 +3240,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi, { CURLMcode res = CURLM_OK; va_list param; + unsigned long uarg; if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -3328,7 +3273,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi, multi->timer_userp = va_arg(param, void *); break; case CURLMOPT_MAXCONNECTS: - multi->maxconnects = va_arg(param, long); + uarg = va_arg(param, unsigned long); + if(uarg <= UINT_MAX) + multi->maxconnects = (unsigned int)uarg; break; case CURLMOPT_MAX_HOST_CONNECTIONS: multi->max_host_connections = va_arg(param, long); @@ -3350,9 +3297,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi, case CURLMOPT_MAX_CONCURRENT_STREAMS: { long streams = va_arg(param, long); - if(streams < 1) + if((streams < 1) || (streams > INT_MAX)) streams = 100; - multi->max_concurrent_streams = curlx_sltoui(streams); + multi->max_concurrent_streams = (unsigned int)streams; } break; default: @@ -3782,11 +3729,11 @@ struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi) struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) * (multi->num_easy + 1)); if(a) { - int i = 0; + unsigned int i = 0; struct Curl_easy *e = multi->easyp; while(e) { DEBUGASSERT(i < multi->num_easy); - if(!e->internal) + if(!e->state.internal) a[i++] = e; e = e->next; } diff --git a/libs/libcurl/src/multihandle.h b/libs/libcurl/src/multihandle.h index 771c04d226..ec57304a38 100644 --- a/libs/libcurl/src/multihandle.h +++ b/libs/libcurl/src/multihandle.h @@ -93,9 +93,9 @@ struct Curl_multi { struct Curl_easy *easyp; struct Curl_easy *easylp; /* last node */ - int num_easy; /* amount of entries in the linked list above. */ - int num_alive; /* amount of easy handles that are added but have not yet - reached COMPLETE state */ + unsigned int num_easy; /* amount of entries in the linked list above. */ + unsigned int num_alive; /* amount of easy handles that are added but have + not yet reached COMPLETE state */ struct Curl_llist msglist; /* a list of messages from completed transfers */ @@ -136,9 +136,6 @@ struct Curl_multi { /* Shared connection cache (bundles)*/ struct conncache conn_cache; - long maxconnects; /* if >0, a fixed limit of the maximum number of entries - we're allowed to grow the connection cache to */ - long max_host_connections; /* if >0, a fixed limit of the maximum number of connections per host */ @@ -150,8 +147,6 @@ struct Curl_multi { void *timer_userp; struct curltime timer_lastcall; /* the fixed time for the timeout for the previous callback */ - unsigned int max_concurrent_streams; - #ifdef USE_WINSOCK WSAEVENT wsa_event; /* winsock event used for waits */ #else @@ -160,6 +155,10 @@ struct Curl_multi { 0 is used for read, 1 is used for write */ #endif #endif + unsigned int max_concurrent_streams; + unsigned int maxconnects; /* if >0, a fixed limit of the maximum number of + entries we're allowed to grow the connection + cache to */ #define IPV6_UNKNOWN 0 #define IPV6_DEAD 1 #define IPV6_WORKS 2 diff --git a/libs/libcurl/src/netrc.c b/libs/libcurl/src/netrc.c index 3163a60a1f..72680af665 100644 --- a/libs/libcurl/src/netrc.c +++ b/libs/libcurl/src/netrc.c @@ -327,7 +327,7 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp, } retcode = parsenetrc(host, loginp, passwordp, filealloc); free(filealloc); -#ifdef WIN32 +#ifdef _WIN32 if(retcode == NETRC_FILE_MISSING) { /* fallback to the old-style "_netrc" file */ filealloc = curl_maprintf("%s%s_netrc", home, DIR_CHAR); diff --git a/libs/libcurl/src/openldap.c b/libs/libcurl/src/openldap.c index fb612660da..bd5a5f88c8 100644 --- a/libs/libcurl/src/openldap.c +++ b/libs/libcurl/src/openldap.c @@ -319,31 +319,12 @@ static CURLcode oldap_setup_connection(struct Curl_easy *data, { CURLcode result; LDAPURLDesc *lud; - struct ldapconninfo *li; + (void)conn; /* Early URL syntax check. */ result = oldap_url_parse(data, &lud); ldap_free_urldesc(lud); - if(!result) { - li = calloc(1, sizeof(struct ldapconninfo)); - if(!li) - result = CURLE_OUT_OF_MEMORY; - else { - li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme); - conn->proto.ldapc = li; - connkeep(conn, "OpenLDAP default"); - - /* Initialize the SASL storage */ - Curl_sasl_init(&li->sasl, data, &saslldap); - - /* Clear the TLS upgraded flag */ - conn->bits.tls_upgraded = FALSE; - - result = oldap_parse_login_options(conn); - } - } - return result; } @@ -537,7 +518,7 @@ static CURLcode oldap_perform_starttls(struct Curl_easy *data) static CURLcode oldap_connect(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; - struct ldapconninfo *li = conn->proto.ldapc; + struct ldapconninfo *li; static const int version = LDAP_VERSION3; int rc; char *hosturl; @@ -547,6 +528,26 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) (void)done; + DEBUGASSERT(!conn->proto.ldapc); + li = calloc(1, sizeof(struct ldapconninfo)); + if(!li) + return CURLE_OUT_OF_MEMORY; + else { + CURLcode result; + li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme); + conn->proto.ldapc = li; + + /* Initialize the SASL storage */ + Curl_sasl_init(&li->sasl, data, &saslldap); + + /* Clear the TLS upgraded flag */ + conn->bits.tls_upgraded = FALSE; + + result = oldap_parse_login_options(conn); + if(result) + return result; + } + hosturl = aprintf("ldap%s://%s:%d", conn->handler->flags & PROTOPT_SSL? "s": "", conn->host.name, conn->remote_port); @@ -886,6 +887,11 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done) result = oldap_url_parse(data, &lud); if(!result) { + Sockbuf *sb; + /* re-install the libcurl SSL handlers into the sockbuf. */ + ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); + ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data); + rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope, lud->lud_filter, lud->lud_attrs, 0, NULL, NULL, NULL, 0, &msgid); @@ -947,18 +953,12 @@ static CURLcode client_write(struct Curl_easy *data, if(!len && plen && prefix[plen - 1] == ' ') plen--; result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) prefix, plen); - if(!result) - data->req.bytecount += plen; } if(!result && value) { result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) value, len); - if(!result) - data->req.bytecount += len; } if(!result && suffix) { result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) suffix, slen); - if(!result) - data->req.bytecount += slen; } return result; } diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c index 32e410f79f..b6ad724c10 100644 --- a/libs/libcurl/src/pop3.c +++ b/libs/libcurl/src/pop3.c @@ -1088,7 +1088,7 @@ static CURLcode pop3_init(struct Curl_easy *data) CURLcode result = CURLE_OK; struct POP3 *pop3; - pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1); + pop3 = data->req.p.pop3 = calloc(1, sizeof(struct POP3)); if(!pop3) result = CURLE_OUT_OF_MEMORY; diff --git a/libs/libcurl/src/progress.c b/libs/libcurl/src/progress.c index 86d8a4dc6e..a151cd2889 100644 --- a/libs/libcurl/src/progress.c +++ b/libs/libcurl/src/progress.c @@ -304,7 +304,7 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize, * 'actual' is the time in milliseconds it took to actually download the * last 'size' bytes. */ - actual = Curl_timediff(now, start); + actual = Curl_timediff_ceil(now, start); if(actual < minimum) { /* if it downloaded the data faster than the limit, make it wait the difference */ @@ -319,12 +319,6 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize, */ CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size) { - if(data->set.max_filesize && (size > data->set.max_filesize)) { - failf(data, "Exceeded the maximum allowed file size " - "(%" CURL_FORMAT_CURL_OFF_T ")", - data->set.max_filesize); - return CURLE_FILESIZE_EXCEEDED; - } data->progress.downloaded = size; return CURLE_OK; } diff --git a/libs/libcurl/src/rand.c b/libs/libcurl/src/rand.c index 22bb0e6ade..025f8bdf4f 100644 --- a/libs/libcurl/src/rand.c +++ b/libs/libcurl/src/rand.c @@ -32,10 +32,6 @@ #ifdef HAVE_ARPA_INET_H #include #endif -#ifdef HAVE_ARC4RANDOM -/* Some platforms might have the prototype missing (ubuntu + libressl) */ -uint32_t arc4random(void); -#endif #include #include "urldata.h" @@ -50,7 +46,7 @@ uint32_t arc4random(void); #include "curl_memory.h" #include "memdebug.h" -#ifdef WIN32 +#ifdef _WIN32 #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 # define HAVE_WIN_BCRYPTGENRANDOM @@ -105,7 +101,6 @@ CURLcode Curl_win32_random(unsigned char *entropy, size_t length) static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) { - unsigned int r; CURLcode result = CURLE_OK; static unsigned int randseed; static bool seeded = FALSE; @@ -138,7 +133,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) /* ---- non-cryptographic version following ---- */ -#ifdef WIN32 +#ifdef _WIN32 if(!seeded) { result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd)); if(result != CURLE_NOT_BUILT_IN) @@ -146,12 +141,14 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) } #endif -#ifdef HAVE_ARC4RANDOM - *rnd = (unsigned int)arc4random(); - return CURLE_OK; +#if defined(HAVE_ARC4RANDOM) && !defined(USE_OPENSSL) + if(!seeded) { + *rnd = (unsigned int)arc4random(); + return CURLE_OK; + } #endif -#if defined(RANDOM_FILE) && !defined(WIN32) +#if defined(RANDOM_FILE) && !defined(_WIN32) if(!seeded) { /* if there's a random file to read a seed from, use it */ int fd = open(RANDOM_FILE, O_RDONLY); @@ -175,9 +172,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) seeded = TRUE; } - /* Return an unsigned 32-bit pseudo-random number. */ - r = randseed = randseed * 1103515245 + 12345; - *rnd = (r << 16) | ((r >> 16) & 0xFFFF); + { + unsigned int r; + /* Return an unsigned 32-bit pseudo-random number. */ + r = randseed = randseed * 1103515245 + 12345; + *rnd = (r << 16) | ((r >> 16) & 0xFFFF); + } return CURLE_OK; } diff --git a/libs/libcurl/src/rand.h b/libs/libcurl/src/rand.h index bb3d0addd7..5984de9b38 100644 --- a/libs/libcurl/src/rand.h +++ b/libs/libcurl/src/rand.h @@ -41,7 +41,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd, size_t num); -#ifdef WIN32 +#ifdef _WIN32 /* Random generator shared between the Schannel vtls and Curl_rand*() functions */ CURLcode Curl_win32_random(unsigned char *entropy, size_t length); diff --git a/libs/libcurl/src/rename.c b/libs/libcurl/src/rename.c index 8f9b0731c7..9eb7b41076 100644 --- a/libs/libcurl/src/rename.c +++ b/libs/libcurl/src/rename.c @@ -40,7 +40,7 @@ /* return 0 on success, 1 on error */ int Curl_rename(const char *oldpath, const char *newpath) { -#ifdef WIN32 +#ifdef _WIN32 /* rename() on Windows doesn't overwrite, so we can't use it here. MoveFileEx() will overwrite and is usually atomic, however it fails when there are open handles to the file. */ diff --git a/libs/libcurl/src/rtsp.c b/libs/libcurl/src/rtsp.c index bb9708f11b..3ad2efb690 100644 --- a/libs/libcurl/src/rtsp.c +++ b/libs/libcurl/src/rtsp.c @@ -45,8 +45,8 @@ #include "curl_memory.h" #include "memdebug.h" -#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \ - ((int)((unsigned char)((p)[3])))) +#define RTP_PKT_LENGTH(p) ((((unsigned int)((unsigned char)((p)[2]))) << 8) | \ + ((unsigned int)((unsigned char)((p)[3])))) /* protocol-specific functions set up to be called by the main engine */ static CURLcode rtsp_do(struct Curl_easy *data, bool *done); @@ -59,14 +59,19 @@ static int rtsp_getsock_do(struct Curl_easy *data, /* * Parse and write out any available RTP data. - * - * nread: amount of data left after k->str. will be modified if RTP - * data is parsed and k->str is moved up - * readmore: whether or not the RTP parser needs more data right away + * @param data the transfer + * @param conn the connection + * @param buf data read from connection + * @param blen amount of data in buf + * @param consumed out, number of blen consumed + * @param readmore out, TRUE iff complete buf was consumed and more data + * is needed */ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, struct connectdata *conn, - ssize_t *nread, + const char *buf, + size_t blen, + size_t *pconsumed, bool *readmore); static CURLcode rtsp_setup_connection(struct Curl_easy *data, @@ -88,7 +93,7 @@ static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn, } static -CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len); +CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len); static CURLcode rtsp_parse_transport(struct Curl_easy *data, char *transport); @@ -585,153 +590,249 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) return result; } - -static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, - struct connectdata *conn, - ssize_t *nread, - bool *readmore) { - struct SingleRequest *k = &data->req; +static CURLcode rtsp_filter_rtp(struct Curl_easy *data, + struct connectdata *conn, + const char *buf, + size_t blen, + bool in_body, + size_t *pconsumed) +{ struct rtsp_conn *rtspc = &(conn->proto.rtspc); - unsigned char *rtp_channel_mask = data->state.rtp_channel_mask; + CURLcode result = CURLE_OK; - char *rtp; /* moving pointer to rtp data */ - ssize_t rtp_dataleft; /* how much data left to parse in this round */ - CURLcode result; - bool interleaved = false; - size_t skip_size = 0; + *pconsumed = 0; + while(blen) { + switch(rtspc->state) { - if(Curl_dyn_len(&rtspc->buf)) { - /* There was some leftover data the last time. Append new buffers */ - if(Curl_dyn_addn(&rtspc->buf, k->str, *nread)) - return CURLE_OUT_OF_MEMORY; - rtp = Curl_dyn_ptr(&rtspc->buf); - rtp_dataleft = Curl_dyn_len(&rtspc->buf); - } - else { - /* Just parse the request buffer directly */ - rtp = k->str; - rtp_dataleft = *nread; - } - - while(rtp_dataleft > 0) { - if(rtp[0] == '$') { - if(rtp_dataleft > 4) { - unsigned char rtp_channel; - int rtp_length; - int idx; - int off; - - /* Parse the header */ - /* The channel identifier immediately follows and is 1 byte */ - rtp_channel = (unsigned char)rtp[1]; - idx = rtp_channel / 8; - off = rtp_channel % 8; - if(!(rtp_channel_mask[idx] & (1 << off))) { - /* invalid channel number, maybe not an RTP packet */ - rtp++; - rtp_dataleft--; - skip_size++; - continue; + case RTP_PARSE_SKIP: { + DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 0); + if(in_body && buf[0] != '$') { + /* in BODY and no valid start, do not consume and return */ + goto out; + } + while(blen && buf[0] != '$') { + if(!in_body && buf[0] == 'R' && + data->set.rtspreq != RTSPREQ_RECEIVE) { + if(strncmp(buf, "RTSP/", (blen < 5) ? blen : 5) == 0) { + /* This could be the next response, no consume and return */ + if(*pconsumed) { + DEBUGF(infof(data, "RTP rtsp_filter_rtp[SKIP] RTSP/ prefix, " + "skipping %zd bytes of junk", *pconsumed)); + } + rtspc->state = RTP_PARSE_SKIP; + rtspc->in_header = TRUE; + goto out; + } } - if(skip_size > 0) { - DEBUGF(infof(data, "Skip the malformed interleaved data %lu " - "bytes", skip_size)); + /* junk, consume without buffering */ + *pconsumed += 1; + ++buf; + --blen; + } + if(blen && buf[0] == '$') { + /* possible start of an RTP message, buffer */ + if(Curl_dyn_addn(&rtspc->buf, buf, 1)) { + result = CURLE_OUT_OF_MEMORY; + goto out; } - skip_size = 0; - rtspc->rtp_channel = rtp_channel; - - /* The length is two bytes */ - rtp_length = RTP_PKT_LENGTH(rtp); + *pconsumed += 1; + ++buf; + --blen; + rtspc->state = RTP_PARSE_CHANNEL; + } + break; + } - if(rtp_dataleft < rtp_length + 4) { - /* Need more - incomplete payload */ - *readmore = TRUE; - break; + case RTP_PARSE_CHANNEL: { + int idx = ((unsigned char)buf[0]) / 8; + int off = ((unsigned char)buf[0]) % 8; + DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 1); + if(!(data->state.rtp_channel_mask[idx] & (1 << off))) { + /* invalid channel number, junk or BODY data */ + rtspc->state = RTP_PARSE_SKIP; + if(in_body) { + /* we do not consume this byte, it is BODY data */ + DEBUGF(infof(data, "RTSP: invalid RTP channel %d in BODY, " + "treating as BODY data", idx)); + if(*pconsumed == 0) { + /* We did not consume the initial '$' in our buffer, but had + * it from an earlier call. We cannot un-consume it and have + * to write it directly as BODY data */ + result = Curl_client_write(data, CLIENTWRITE_BODY, + Curl_dyn_ptr(&rtspc->buf), 1); + Curl_dyn_free(&rtspc->buf); + if(result) + goto out; + } + else { + /* un-consume the '$' and leave */ + Curl_dyn_free(&rtspc->buf); + *pconsumed -= 1; + --buf; + ++blen; + goto out; + } } - interleaved = true; - /* We have the full RTP interleaved packet - * Write out the header including the leading '$' */ - DEBUGF(infof(data, "RTP write channel %d rtp_length %d", - rtspc->rtp_channel, rtp_length)); - result = rtp_client_write(data, &rtp[0], rtp_length + 4); - if(result) { - *readmore = FALSE; - return result; + else { + /* not BODY, forget the junk '$'. Do not consume this byte, + * it might be a start */ + infof(data, "RTSP: invalid RTP channel %d, skipping", idx); + Curl_dyn_free(&rtspc->buf); } + break; + } + /* a valid channel, so we expect this to be a real RTP message */ + rtspc->rtp_channel = (unsigned char)buf[0]; + if(Curl_dyn_addn(&rtspc->buf, buf, 1)) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + *pconsumed += 1; + ++buf; + --blen; + rtspc->state = RTP_PARSE_LEN; + break; + } - /* Move forward in the buffer */ - rtp_dataleft -= rtp_length + 4; - rtp += rtp_length + 4; + case RTP_PARSE_LEN: { + size_t rtp_len = Curl_dyn_len(&rtspc->buf); + const char *rtp_buf; + DEBUGASSERT(rtp_len >= 2 && rtp_len < 4); + if(Curl_dyn_addn(&rtspc->buf, buf, 1)) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + *pconsumed += 1; + ++buf; + --blen; + if(rtp_len == 2) + break; + rtp_buf = Curl_dyn_ptr(&rtspc->buf); + rtspc->rtp_len = RTP_PKT_LENGTH(rtp_buf) + 4; + rtspc->state = RTP_PARSE_DATA; + break; + } - if(data->set.rtspreq == RTSPREQ_RECEIVE) { - /* If we are in a passive receive, give control back - * to the app as often as we can. - */ - k->keepon &= ~KEEP_RECV; + case RTP_PARSE_DATA: { + size_t rtp_len = Curl_dyn_len(&rtspc->buf); + size_t needed; + DEBUGASSERT(rtp_len < rtspc->rtp_len); + needed = rtspc->rtp_len - rtp_len; + if(needed <= blen) { + if(Curl_dyn_addn(&rtspc->buf, buf, needed)) { + result = CURLE_OUT_OF_MEMORY; + goto out; } + *pconsumed += needed; + buf += needed; + blen -= needed; + /* complete RTP message in buffer */ + DEBUGF(infof(data, "RTP write channel %d rtp_len %zu", + rtspc->rtp_channel, rtspc->rtp_len)); + result = rtp_client_write(data, Curl_dyn_ptr(&rtspc->buf), + rtspc->rtp_len); + Curl_dyn_free(&rtspc->buf); + rtspc->state = RTP_PARSE_SKIP; + if(result) + goto out; } else { - /* Need more - incomplete header */ - *readmore = TRUE; - break; - } - } - else { - /* If the following data begins with 'RTSP/', which might be an RTSP - message, we should stop skipping the data. */ - /* If `k-> headerline> 0 && !interleaved` is true, we are maybe in the - middle of an RTSP message. It is difficult to determine this, so we - stop skipping. */ - size_t prefix_len = (rtp_dataleft < 5) ? rtp_dataleft : 5; - if((k->headerline > 0 && !interleaved) || - strncmp(rtp, "RTSP/", prefix_len) == 0) { - if(skip_size > 0) { - DEBUGF(infof(data, "Skip the malformed interleaved data %lu " - "bytes", skip_size)); + if(Curl_dyn_addn(&rtspc->buf, buf, blen)) { + result = CURLE_OUT_OF_MEMORY; + goto out; } - break; /* maybe is an RTSP message */ + *pconsumed += blen; + buf += blen; + blen = 0; } - /* Skip incorrect data util the next RTP packet or RTSP message */ - do { - rtp++; - rtp_dataleft--; - skip_size++; - } while(rtp_dataleft > 0 && rtp[0] != '$' && rtp[0] != 'R'); + break; + } + + default: + DEBUGASSERT(0); + return CURLE_RECV_ERROR; } } +out: + return result; +} + +static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, + struct connectdata *conn, + const char *buf, + size_t blen, + size_t *pconsumed, + bool *readmore) +{ + struct rtsp_conn *rtspc = &(conn->proto.rtspc); + CURLcode result = CURLE_OK; + size_t consumed = 0; + bool in_body; - if(rtp_dataleft && rtp[0] == '$') { - DEBUGF(infof(data, "RTP Rewinding %zd %s", rtp_dataleft, - *readmore ? "(READMORE)" : "")); + if(!data->req.header) + rtspc->in_header = FALSE; + in_body = (data->req.headerline && !rtspc->in_header) && + (data->req.size >= 0) && + (data->req.bytecount < data->req.size); - /* Store the incomplete RTP packet for a "rewind" */ - if(!Curl_dyn_len(&rtspc->buf)) { - /* nothing was stored, add this data */ - if(Curl_dyn_addn(&rtspc->buf, rtp, rtp_dataleft)) - return CURLE_OUT_OF_MEMORY; - } - else { - /* keep the remainder */ - Curl_dyn_tail(&rtspc->buf, rtp_dataleft); - } + *readmore = FALSE; + *pconsumed = 0; + if(!blen) { + goto out; + } - /* As far as the transfer is concerned, this data is consumed */ - *nread = 0; - return CURLE_OK; + /* If header parsing is not onging, extract RTP messages */ + if(!rtspc->in_header) { + result = rtsp_filter_rtp(data, conn, buf, blen, in_body, &consumed); + if(result) + goto out; + *pconsumed += consumed; + buf += consumed; + blen -= consumed; } - /* Fix up k->str to point just after the last RTP packet */ - k->str += *nread - rtp_dataleft; - *nread = rtp_dataleft; + /* we want to parse headers, do so */ + if(data->req.header && blen) { + rtspc->in_header = TRUE; + result = Curl_http_readwrite_headers(data, conn, buf, blen, + &consumed); + if(result) + goto out; + + *pconsumed += consumed; + buf += consumed; + blen -= consumed; + + if(!data->req.header) + rtspc->in_header = FALSE; + + if(!rtspc->in_header) { + /* If header parsing is done and data left, extract RTP messages */ + in_body = (data->req.headerline && !rtspc->in_header) && + (data->req.size >= 0) && + (data->req.bytecount < data->req.size); + result = rtsp_filter_rtp(data, conn, buf, blen, in_body, &consumed); + if(result) + goto out; + *pconsumed += consumed; + } + } - /* If we get here, we have finished with the leftover/merge buffer */ - Curl_dyn_free(&rtspc->buf); + if(rtspc->state != RTP_PARSE_SKIP) + *readmore = TRUE; - return CURLE_OK; +out: + if(!*readmore && data->set.rtspreq == RTSPREQ_RECEIVE) { + /* In special mode RECEIVE, we just process one chunk of network + * data, so we stop the transfer here, if we have no incomplete + * RTP message pending. */ + data->req.keepon &= ~KEEP_RECV; + } + return result; } static -CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len) +CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len) { size_t wrote; curl_write_callback writeit; @@ -756,7 +857,7 @@ CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len) } Curl_set_in_callback(data, true); - wrote = writeit(ptr, 1, len, user_ptr); + wrote = writeit((char *)ptr, 1, len, user_ptr); Curl_set_in_callback(data, false); if(CURL_WRITEFUNC_PAUSE == wrote) { diff --git a/libs/libcurl/src/rtsp.h b/libs/libcurl/src/rtsp.h index e084cdaa35..15419e7f9f 100644 --- a/libs/libcurl/src/rtsp.h +++ b/libs/libcurl/src/rtsp.h @@ -39,6 +39,12 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header); #endif /* CURL_DISABLE_RTSP */ +typedef enum { + RTP_PARSE_SKIP, + RTP_PARSE_CHANNEL, + RTP_PARSE_LEN, + RTP_PARSE_DATA +} rtp_parse_st; /* * RTSP Connection data * @@ -47,6 +53,9 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header); struct rtsp_conn { struct dynbuf buf; int rtp_channel; + size_t rtp_len; + rtp_parse_st state; + BIT(in_header); }; /**************************************************************************** diff --git a/libs/libcurl/src/select.c b/libs/libcurl/src/select.c index d0aa2a764b..64ff9c2eed 100644 --- a/libs/libcurl/src/select.c +++ b/libs/libcurl/src/select.c @@ -76,7 +76,7 @@ int Curl_wait_ms(timediff_t timeout_ms) } #if defined(MSDOS) delay(timeout_ms); -#elif defined(WIN32) +#elif defined(_WIN32) /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */ #if TIMEDIFF_T_MAX >= ULONG_MAX if(timeout_ms >= ULONG_MAX) diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c index 90f7e86e16..efd1723f17 100644 --- a/libs/libcurl/src/sendf.c +++ b/libs/libcurl/src/sendf.c @@ -50,6 +50,7 @@ #include "strdup.h" #include "http2.h" #include "headers.h" +#include "progress.h" #include "ws.h" /* The last 3 #include files should be in this order */ @@ -57,6 +58,9 @@ #include "curl_memory.h" #include "memdebug.h" + +static CURLcode do_init_stack(struct Curl_easy *data); + #if defined(CURL_DO_LINEEND_CONV) && !defined(CURL_DISABLE_FTP) /* * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF @@ -385,17 +389,17 @@ static CURLcode chop_write(struct Curl_easy *data, the future to leave the original data alone. */ CURLcode Curl_client_write(struct Curl_easy *data, - int type, - char *ptr, - size_t len) + int type, char *buf, size_t blen) { + CURLcode result; + #if !defined(CURL_DISABLE_FTP) && defined(CURL_DO_LINEEND_CONV) /* FTP data may need conversion. */ if((type & CLIENTWRITE_BODY) && (data->conn->handler->protocol & PROTO_FAMILY_FTP) && data->conn->proto.ftpc.transfertype == 'A') { /* convert end-of-line markers */ - len = convert_lineends(data, ptr, len); + blen = convert_lineends(data, buf, blen); } #endif /* it is one of those, at least */ @@ -405,14 +409,14 @@ CURLcode Curl_client_write(struct Curl_easy *data, /* INFO is only INFO */ DEBUGASSERT(!(type & CLIENTWRITE_INFO) || (type == CLIENTWRITE_INFO)); - if(type == CLIENTWRITE_BODY) { - if(data->req.ignorebody) - return CURLE_OK; - - if(data->req.writer_stack && !data->set.http_ce_skip) - return Curl_unencode_write(data, data->req.writer_stack, ptr, len); + if(!data->req.writer_stack) { + result = do_init_stack(data); + if(result) + return result; + DEBUGASSERT(data->req.writer_stack); } - return chop_write(data, type, FALSE, ptr, len); + + return Curl_cwriter_write(data, data->req.writer_stack, type, buf, blen); } CURLcode Curl_client_unpause(struct Curl_easy *data) @@ -449,12 +453,12 @@ CURLcode Curl_client_unpause(struct Curl_easy *data) void Curl_client_cleanup(struct Curl_easy *data) { - struct contenc_writer *writer = data->req.writer_stack; + struct Curl_cwriter *writer = data->req.writer_stack; size_t i; while(writer) { - data->req.writer_stack = writer->downstream; - writer->handler->close_writer(data, writer); + data->req.writer_stack = writer->next; + writer->cwt->do_close(data, writer); free(writer); writer = data->req.writer_stack; } @@ -463,61 +467,222 @@ void Curl_client_cleanup(struct Curl_easy *data) Curl_dyn_free(&data->state.tempwrite[i].b); } data->state.tempcount = 0; + data->req.bytecount = 0; + data->req.headerline = 0; +} +/* Write data using an unencoding writer stack. "nbytes" is not + allowed to be 0. */ +CURLcode Curl_cwriter_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, + const char *buf, size_t nbytes) +{ + if(!nbytes) + return CURLE_OK; + if(!writer) + return CURLE_WRITE_ERROR; + return writer->cwt->do_write(data, writer, type, buf, nbytes); } -/* Real client writer: no downstream. */ -static CURLcode client_cew_init(struct Curl_easy *data, - struct contenc_writer *writer) +CURLcode Curl_cwriter_def_init(struct Curl_easy *data, + struct Curl_cwriter *writer) { - (void) data; + (void)data; (void)writer; return CURLE_OK; } -static CURLcode client_cew_write(struct Curl_easy *data, - struct contenc_writer *writer, - const char *buf, size_t nbytes) +CURLcode Curl_cwriter_def_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, + const char *buf, size_t nbytes) { - (void)writer; - if(!nbytes || data->req.ignorebody) - return CURLE_OK; - return chop_write(data, CLIENTWRITE_BODY, FALSE, (char *)buf, nbytes); + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); } -static void client_cew_close(struct Curl_easy *data, - struct contenc_writer *writer) +void Curl_cwriter_def_close(struct Curl_easy *data, + struct Curl_cwriter *writer) { (void) data; (void) writer; } -static const struct content_encoding client_cew = { +/* Real client writer to installed callbacks. */ +static CURLcode cw_client_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, + const char *buf, size_t nbytes) +{ + (void)writer; + if(!nbytes) + return CURLE_OK; + return chop_write(data, type, FALSE, (char *)buf, nbytes); +} + +static const struct Curl_cwtype cw_client = { + "client", NULL, + Curl_cwriter_def_init, + cw_client_write, + Curl_cwriter_def_close, + sizeof(struct Curl_cwriter) +}; + +static size_t get_max_body_write_len(struct Curl_easy *data, curl_off_t limit) +{ + if(limit != -1) { + /* How much more are we allowed to write? */ + curl_off_t remain_diff; + remain_diff = limit - data->req.bytecount; + if(remain_diff < 0) { + /* already written too much! */ + return 0; + } +#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T + else if(remain_diff > SSIZE_T_MAX) { + return SIZE_T_MAX; + } +#endif + else { + return (size_t)remain_diff; + } + } + return SIZE_T_MAX; +} + +/* Download client writer in phase CURL_CW_PROTOCOL that + * sees the "real" download body data. */ +static CURLcode cw_download_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, + const char *buf, size_t nbytes) +{ + CURLcode result; + size_t nwrite, excess_len = 0; + const char *excess_data = NULL; + + if(!(type & CLIENTWRITE_BODY)) { + if((type & CLIENTWRITE_CONNECT) && data->set.suppress_connect_headers) + return CURLE_OK; + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + } + + nwrite = nbytes; + if(-1 != data->req.maxdownload) { + size_t wmax = get_max_body_write_len(data, data->req.maxdownload); + if(nwrite > wmax) { + excess_len = nbytes - wmax; + nwrite = wmax; + excess_data = buf + nwrite; + } + + if(nwrite == wmax) { + data->req.download_done = TRUE; + } + } + + if(data->set.max_filesize) { + size_t wmax = get_max_body_write_len(data, data->set.max_filesize); + if(nwrite > wmax) { + nwrite = wmax; + } + } + + data->req.bytecount += nwrite; + ++data->req.bodywrites; + if(!data->req.ignorebody && nwrite) { + result = Curl_cwriter_write(data, writer->next, type, buf, nwrite); + if(result) + return result; + } + result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount); + if(result) + return result; + + if(excess_len) { + if(data->conn->handler->readwrite) { + /* RTSP hack moved from transfer loop to here */ + bool readmore = FALSE; /* indicates data is incomplete, need more */ + size_t consumed = 0; + result = data->conn->handler->readwrite(data, data->conn, + excess_data, excess_len, + &consumed, &readmore); + if(result) + return result; + DEBUGASSERT(consumed <= excess_len); + excess_len -= consumed; + if(readmore) { + data->req.download_done = FALSE; + data->req.keepon |= KEEP_RECV; /* we're not done reading */ + } + } + if(excess_len && !data->req.ignorebody) { + infof(data, + "Excess found writing body:" + " excess = %zu" + ", size = %" CURL_FORMAT_CURL_OFF_T + ", maxdownload = %" CURL_FORMAT_CURL_OFF_T + ", bytecount = %" CURL_FORMAT_CURL_OFF_T, + excess_len, data->req.size, data->req.maxdownload, + data->req.bytecount); + connclose(data->conn, "excess found in a read"); + } + } + else if(nwrite < nbytes) { + failf(data, "Exceeded the maximum allowed file size " + "(%" CURL_FORMAT_CURL_OFF_T ") with %" + CURL_FORMAT_CURL_OFF_T " bytes", + data->set.max_filesize, data->req.bytecount); + return CURLE_FILESIZE_EXCEEDED; + } + + return CURLE_OK; +} + +static const struct Curl_cwtype cw_download = { + "download", NULL, - client_cew_init, - client_cew_write, - client_cew_close, - sizeof(struct contenc_writer) + Curl_cwriter_def_init, + cw_download_write, + Curl_cwriter_def_close, + sizeof(struct Curl_cwriter) +}; + +/* RAW client writer in phase CURL_CW_RAW that + * enabled tracing of raw data. */ +static CURLcode cw_raw_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, + const char *buf, size_t nbytes) +{ + if(type & CLIENTWRITE_BODY && data->set.verbose && !data->req.ignorebody) { + Curl_debug(data, CURLINFO_DATA_IN, (char *)buf, nbytes); + } + return Curl_cwriter_write(data, writer->next, type, buf, nbytes); +} + +static const struct Curl_cwtype cw_raw = { + "raw", + NULL, + Curl_cwriter_def_init, + cw_raw_write, + Curl_cwriter_def_close, + sizeof(struct Curl_cwriter) }; /* Create an unencoding writer stage using the given handler. */ -CURLcode Curl_client_create_writer(struct contenc_writer **pwriter, +CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter, struct Curl_easy *data, - const struct content_encoding *ce_handler, - int order) + const struct Curl_cwtype *cwt, + Curl_cwriter_phase phase) { - struct contenc_writer *writer; + struct Curl_cwriter *writer; CURLcode result = CURLE_OUT_OF_MEMORY; - DEBUGASSERT(ce_handler->writersize >= sizeof(struct contenc_writer)); - writer = (struct contenc_writer *) calloc(1, ce_handler->writersize); + DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter)); + writer = (struct Curl_cwriter *) calloc(1, cwt->cwriter_size); if(!writer) goto out; - writer->handler = ce_handler; - writer->order = order; - result = ce_handler->init_writer(data, writer); + writer->cwt = cwt; + writer->phase = phase; + result = cwt->do_init(data, writer); out: *pwriter = result? NULL : writer; @@ -526,55 +691,74 @@ out: return result; } -void Curl_client_free_writer(struct Curl_easy *data, - struct contenc_writer *writer) +void Curl_cwriter_free(struct Curl_easy *data, + struct Curl_cwriter *writer) { if(writer) { - writer->handler->close_writer(data, writer); + writer->cwt->do_close(data, writer); free(writer); } } -/* allow no more than 5 "chained" compression steps */ -#define MAX_ENCODE_STACK 5 +size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase) +{ + struct Curl_cwriter *w; + size_t n = 0; + for(w = data->req.writer_stack; w; w = w->next) { + if(w->phase == phase) + ++n; + } + return n; +} -static CURLcode init_writer_stack(struct Curl_easy *data) +static CURLcode do_init_stack(struct Curl_easy *data) { + struct Curl_cwriter *writer; + CURLcode result; + DEBUGASSERT(!data->req.writer_stack); - return Curl_client_create_writer(&data->req.writer_stack, - data, &client_cew, 0); + result = Curl_cwriter_create(&data->req.writer_stack, + data, &cw_client, CURL_CW_CLIENT); + if(result) + return result; + + result = Curl_cwriter_create(&writer, data, &cw_download, CURL_CW_PROTOCOL); + if(result) + return result; + result = Curl_cwriter_add(data, writer); + if(result) { + Curl_cwriter_free(data, writer); + } + + result = Curl_cwriter_create(&writer, data, &cw_raw, CURL_CW_RAW); + if(result) + return result; + result = Curl_cwriter_add(data, writer); + if(result) { + Curl_cwriter_free(data, writer); + } + return result; } -CURLcode Curl_client_add_writer(struct Curl_easy *data, - struct contenc_writer *writer) +CURLcode Curl_cwriter_add(struct Curl_easy *data, + struct Curl_cwriter *writer) { CURLcode result; + struct Curl_cwriter **anchor = &data->req.writer_stack; - if(!data->req.writer_stack) { - result = init_writer_stack(data); + if(!*anchor) { + result = do_init_stack(data); if(result) return result; } - if(data->req.writer_stack_depth++ >= MAX_ENCODE_STACK) { - failf(data, "Reject response due to more than %u content encodings", - MAX_ENCODE_STACK); - return CURLE_BAD_CONTENT_ENCODING; - } - - /* Stack the unencoding stage. */ - if(writer->order >= data->req.writer_stack->order) { - writer->downstream = data->req.writer_stack; - data->req.writer_stack = writer; - } - else { - struct contenc_writer *w = data->req.writer_stack; - while(w->downstream && writer->order < w->downstream->order) - w = w->downstream; - writer->downstream = w->downstream; - w->downstream = writer; - } + /* Insert the writer as first in its phase. + * Skip existing writers of lower phases. */ + while(*anchor && (*anchor)->phase < writer->phase) + anchor = &((*anchor)->next); + writer->next = *anchor; + *anchor = writer; return CURLE_OK; } diff --git a/libs/libcurl/src/sendf.h b/libs/libcurl/src/sendf.h index 90efb61ace..a871b8d098 100644 --- a/libs/libcurl/src/sendf.h +++ b/libs/libcurl/src/sendf.h @@ -50,43 +50,122 @@ #define CLIENTWRITE_1XX (1<<5) /* a 1xx response related HEADER */ #define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */ +/** + * Write `len` bytes at `prt` to the client. `type` indicates what + * kind of data is being written. + */ CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr, size_t len) WARN_UNUSED_RESULT; +/** + * For a paused transfer, there might be buffered data held back. + * Attempt to flush this data to the client. This *may* trigger + * another pause of the transfer. + */ CURLcode Curl_client_unpause(struct Curl_easy *data); + +/** + * Free all resources related to client writing. + */ void Curl_client_cleanup(struct Curl_easy *data); -struct contenc_writer { - const struct content_encoding *handler; /* Encoding handler. */ - struct contenc_writer *downstream; /* Downstream writer. */ - unsigned int order; /* Ordering within writer stack. */ +/** + * Client Writers - a chain passing transfer BODY data to the client. + * Main application: HTTP and related protocols + * Other uses: monitoring of download progress + * + * Writers in the chain are order by their `phase`. First come all + * writers in CURL_CW_RAW, followed by any in CURL_CW_TRANSFER_DECODE, + * followed by any in CURL_CW_PROTOCOL, etc. + * + * When adding a writer, it is inserted as first in its phase. This means + * the order of adding writers of the same phase matters, but writers for + * different phases may be added in any order. + * + * Writers which do modify the BODY data written are expected to be of + * phases TRANSFER_DECODE or CONTENT_DECODE. The other phases are intended + * for monitoring writers. Which do *not* modify the data but gather + * statistics or update progress reporting. + */ + +/* Phase a writer operates at. */ +typedef enum { + CURL_CW_RAW, /* raw data written, before any decoding */ + CURL_CW_TRANSFER_DECODE, /* remove transfer-encodings */ + CURL_CW_PROTOCOL, /* after transfer, but before content decoding */ + CURL_CW_CONTENT_DECODE, /* remove content-encodings */ + CURL_CW_CLIENT /* data written to client */ +} Curl_cwriter_phase; + +/* Client Writer Type, provides the implementation */ +struct Curl_cwtype { + const char *name; /* writer name. */ + const char *alias; /* writer name alias, maybe NULL. */ + CURLcode (*do_init)(struct Curl_easy *data, + struct Curl_cwriter *writer); + CURLcode (*do_write)(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, + const char *buf, size_t nbytes); + void (*do_close)(struct Curl_easy *data, + struct Curl_cwriter *writer); + size_t cwriter_size; /* sizeof() allocated struct Curl_cwriter */ }; -/* Content encoding writer. */ -struct content_encoding { - const char *name; /* Encoding name. */ - const char *alias; /* Encoding name alias. */ - CURLcode (*init_writer)(struct Curl_easy *data, - struct contenc_writer *writer); - CURLcode (*unencode_write)(struct Curl_easy *data, - struct contenc_writer *writer, - const char *buf, size_t nbytes); - void (*close_writer)(struct Curl_easy *data, - struct contenc_writer *writer); - size_t writersize; +/* Client writer instance */ +struct Curl_cwriter { + const struct Curl_cwtype *cwt; /* type implementation */ + struct Curl_cwriter *next; /* Downstream writer. */ + Curl_cwriter_phase phase; /* phase at which it operates */ }; +/** + * Create a new cwriter instance with given type and phase. Is not + * inserted into the writer chain by this call. + * Invokes `writer->do_init()`. + */ +CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter, + struct Curl_easy *data, + const struct Curl_cwtype *ce_handler, + Curl_cwriter_phase phase); -CURLcode Curl_client_create_writer(struct contenc_writer **pwriter, - struct Curl_easy *data, - const struct content_encoding *ce_handler, - int order); +/** + * Free a cwriter instance. + * Invokes `writer->do_close()`. + */ +void Curl_cwriter_free(struct Curl_easy *data, + struct Curl_cwriter *writer); -void Curl_client_free_writer(struct Curl_easy *data, - struct contenc_writer *writer); +/** + * Count the number of writers installed of the given phase. + */ +size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase); -CURLcode Curl_client_add_writer(struct Curl_easy *data, - struct contenc_writer *writer); +/** + * Adds a writer to the transfer's writer chain. + * The writers `phase` determines where in the chain it is inserted. + */ +CURLcode Curl_cwriter_add(struct Curl_easy *data, + struct Curl_cwriter *writer); + +/** + * Convenience method for calling `writer->do_write()` that + * checks for NULL writer. + */ +CURLcode Curl_cwriter_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, + const char *buf, size_t nbytes); + +/** + * Default implementations for do_init, do_write, do_close that + * do nothing and pass the data through. + */ +CURLcode Curl_cwriter_def_init(struct Curl_easy *data, + struct Curl_cwriter *writer); +CURLcode Curl_cwriter_def_write(struct Curl_easy *data, + struct Curl_cwriter *writer, int type, + const char *buf, size_t nbytes); +void Curl_cwriter_def_close(struct Curl_easy *data, + struct Curl_cwriter *writer); /* internal read-function, does plain socket, SSL and krb4 */ diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c index 01219c7c39..5ad3c9456b 100644 --- a/libs/libcurl/src/setopt.c +++ b/libs/libcurl/src/setopt.c @@ -50,6 +50,7 @@ #include "multiif.h" #include "altsvc.h" #include "hsts.h" +#include "tftp.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -171,7 +172,7 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val) str = strchr(str, ','); tlen = str? (size_t) (str - token): strlen(token); if(tlen) { - const struct Curl_handler *h = Curl_builtin_scheme(token, tlen); + const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen); if(!h) return CURLE_UNSUPPORTED_PROTOCOL; @@ -261,43 +262,43 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Set the absolute number of maximum simultaneous alive connection that * libcurl is allowed to have. */ - arg = va_arg(param, long); - if(arg < 0) + uarg = va_arg(param, unsigned long); + if(uarg > UINT_MAX) return CURLE_BAD_FUNCTION_ARGUMENT; - data->set.maxconnects = arg; + data->set.maxconnects = (unsigned int)uarg; break; case CURLOPT_FORBID_REUSE: /* * When this transfer is done, it must not be left to be reused by a * subsequent transfer but shall be closed immediately. */ - data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.reuse_forbid = (0 != va_arg(param, long)); break; case CURLOPT_FRESH_CONNECT: /* * This transfer shall not use a previously cached connection but * should be made with a fresh new connect! */ - data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.reuse_fresh = (0 != va_arg(param, long)); break; case CURLOPT_VERBOSE: /* * Verbose means infof() calls that give a lot of information about * the connection and transfer procedures as well as internal choices. */ - data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.verbose = (0 != va_arg(param, long)); break; case CURLOPT_HEADER: /* * Set to include the header in the general data output stream. */ - data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.include_header = (0 != va_arg(param, long)); break; case CURLOPT_NOPROGRESS: /* * Shut off the internal supported progress meter */ - data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.hide_progress = (0 != va_arg(param, long)); if(data->set.hide_progress) data->progress.flags |= PGRS_HIDE; else @@ -307,7 +308,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Do not include the body part in the output data stream. */ - data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.opt_no_body = (0 != va_arg(param, long)); #ifndef CURL_DISABLE_HTTP if(data->set.opt_no_body) /* in HTTP lingo, no body means using the HEAD request... */ @@ -321,11 +322,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Don't output the >=400 error code HTML-page, but instead only * return error. */ - data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.http_fail_on_error = (0 != va_arg(param, long)); break; case CURLOPT_KEEP_SENDING_ON_ERROR: - data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ? - TRUE : FALSE; + data->set.http_keep_sending_on_error = (0 != va_arg(param, long)); break; case CURLOPT_UPLOAD: case CURLOPT_PUT: @@ -353,7 +353,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Try to get the file time of the remote document. The time will * later (possibly) become available using curl_easy_getinfo(). */ - data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.get_filetime = (0 != va_arg(param, long)); break; case CURLOPT_SERVER_RESPONSE_TIMEOUT: /* @@ -379,7 +379,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * TFTP option that specifies the block size to use for data transmission. */ arg = va_arg(param, long); - if(arg < 0) + if(arg > TFTP_BLKSIZE_MAX || arg < TFTP_BLKSIZE_MIN) return CURLE_BAD_FUNCTION_ARGUMENT; data->set.tftp_blksize = arg; break; @@ -409,7 +409,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * * Transfer using ASCII (instead of BINARY). */ - data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.prefer_ascii = (0 != va_arg(param, long)); break; case CURLOPT_TIMECONDITION: /* @@ -577,7 +577,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Switch on automatic referer that gets set if curl follows locations. */ - data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.http_auto_referer = (0 != va_arg(param, long)); break; case CURLOPT_ACCEPT_ENCODING: @@ -592,28 +592,23 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) */ argptr = va_arg(param, char *); if(argptr && !*argptr) { - argptr = Curl_all_content_encodings(); - if(!argptr) - result = CURLE_OUT_OF_MEMORY; - else { - result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); - free(argptr); - } + char all[256]; + Curl_all_content_encodings(all, sizeof(all)); + result = Curl_setstropt(&data->set.str[STRING_ENCODING], all); } else result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); break; case CURLOPT_TRANSFER_ENCODING: - data->set.http_transfer_encoding = (0 != va_arg(param, long)) ? - TRUE : FALSE; + data->set.http_transfer_encoding = (0 != va_arg(param, long)); break; case CURLOPT_FOLLOWLOCATION: /* * Follow Location: header hints on an HTTP-server. */ - data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.http_follow_location = (0 != va_arg(param, long)); break; case CURLOPT_UNRESTRICTED_AUTH: @@ -621,8 +616,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Send authentication (user+password) when following locations, even when * hostname changed. */ - data->set.allow_auth_to_other_hosts = - (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.allow_auth_to_other_hosts = (0 != va_arg(param, long)); break; case CURLOPT_MAXREDIRS: @@ -736,7 +730,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Set header option. */ arg = va_arg(param, long); - data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE); + data->set.sep_headers = !!(arg & CURLHEADER_SEPARATE); break; #if !defined(CURL_DISABLE_COOKIES) @@ -760,18 +754,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) return CURLE_BAD_FUNCTION_ARGUMENT; /* append the cookie file name to the list of file names, and deal with them later */ - cl = curl_slist_append(data->set.cookielist, argptr); + cl = curl_slist_append(data->state.cookielist, argptr); if(!cl) { - curl_slist_free_all(data->set.cookielist); - data->set.cookielist = NULL; + curl_slist_free_all(data->state.cookielist); + data->state.cookielist = NULL; return CURLE_OUT_OF_MEMORY; } - data->set.cookielist = cl; /* store the list for later use */ + data->state.cookielist = cl; /* store the list for later use */ } else { /* clear the list of cookie files */ - curl_slist_free_all(data->set.cookielist); - data->set.cookielist = NULL; + curl_slist_free_all(data->state.cookielist); + data->state.cookielist = NULL; if(!data->share || !data->share->cookies) { /* throw away all existing cookies if this isn't a shared cookie @@ -811,17 +805,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * prevent the forthcoming read-cookies-from-file actions to accept * cookies that are marked as being session cookies, as they belong to a * previous session. - * - * In the original Netscape cookie spec, "session cookies" are cookies - * with no expire date set. RFC2109 describes the same action if no - * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds - * a 'Discard' action that can enforce the discard even for cookies that - * have a Max-Age. - * - * We run mostly with the original cookie spec, as hardly anyone implements - * anything else. */ - data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.cookiesession = (0 != va_arg(param, long)); break; case CURLOPT_COOKIELIST: @@ -956,7 +941,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) if(arg) return CURLE_BAD_FUNCTION_ARGUMENT; #else - data->set.http09_allowed = arg ? TRUE : FALSE; + data->set.http09_allowed = !!arg; #endif break; @@ -997,8 +982,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_MIME_OPTIONS: - data->set.mime_options = (unsigned int)va_arg(param, long); - break; + arg = va_arg(param, long); + data->set.mime_formescape = !!(arg & CURLMIMEOPT_FORMESCAPE); + break; # endif #endif @@ -1018,8 +1004,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* the DIGEST_IE bit is only used to set a special marker, for all the rest we need to handle it as normal DIGEST */ - data->state.authhost.iestyle = - (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); + data->state.authhost.iestyle = !!(auth & CURLAUTH_DIGEST_IE); if(auth & CURLAUTH_DIGEST_IE) { auth |= CURLAUTH_DIGEST; /* set standard digest bit */ @@ -1072,8 +1057,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Tunnel operations through the proxy instead of normal proxy use */ - data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ? - TRUE : FALSE; + data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)); break; case CURLOPT_PROXYPORT: @@ -1102,8 +1086,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* the DIGEST_IE bit is only used to set a special marker, for all the rest we need to handle it as normal DIGEST */ - data->state.authproxy.iestyle = - (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); + data->state.authproxy.iestyle = !!(auth & CURLAUTH_DIGEST_IE); if(auth & CURLAUTH_DIGEST_IE) { auth |= CURLAUTH_DIGEST; /* set standard digest bit */ @@ -1203,7 +1186,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Set flag for NEC SOCK5 support */ - data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.socks5_gssapi_nec = (0 != va_arg(param, long)); break; #endif #ifndef CURL_DISABLE_PROXY @@ -1251,7 +1234,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * An option that changes the command to one that asks for a list only, no * file info details. Used for FTP, POP3 and SFTP. */ - data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.list_only = (0 != va_arg(param, long)); break; #endif case CURLOPT_APPEND: @@ -1259,7 +1242,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * We want to upload and append to an existing file. Used for FTP and * SFTP. */ - data->set.remote_append = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.remote_append = (0 != va_arg(param, long)); break; #ifndef CURL_DISABLE_FTP @@ -1270,7 +1253,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) arg = va_arg(param, long); if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST)) return CURLE_BAD_FUNCTION_ARGUMENT; - data->set.ftp_filemethod = (unsigned char)(curl_ftpfile)arg; + data->set.ftp_filemethod = (unsigned char)arg; break; case CURLOPT_FTPPORT: /* @@ -1278,26 +1261,26 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) */ result = Curl_setstropt(&data->set.str[STRING_FTPPORT], va_arg(param, char *)); - data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE; + data->set.ftp_use_port = !!(data->set.str[STRING_FTPPORT]); break; case CURLOPT_FTP_USE_EPRT: - data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ftp_use_eprt = (0 != va_arg(param, long)); break; case CURLOPT_FTP_USE_EPSV: - data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ftp_use_epsv = (0 != va_arg(param, long)); break; case CURLOPT_FTP_USE_PRET: - data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ftp_use_pret = (0 != va_arg(param, long)); break; case CURLOPT_FTP_SSL_CCC: arg = va_arg(param, long); if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST)) return CURLE_BAD_FUNCTION_ARGUMENT; - data->set.ftp_ccc = (unsigned char)(curl_ftpccc)arg; + data->set.ftp_ccc = (unsigned char)arg; break; case CURLOPT_FTP_SKIP_PASV_IP: @@ -1305,7 +1288,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the * bypass of the IP address in PASV responses. */ - data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ftp_skip_ip = (0 != va_arg(param, long)); break; case CURLOPT_FTP_ACCOUNT: @@ -1333,7 +1316,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) */ result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL], va_arg(param, char *)); - data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE; + data->set.krb = !!(data->set.str[STRING_KRB_LEVEL]); break; #endif #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) @@ -1867,14 +1850,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Kludgy option to enable CRLF conversions. Subject for removal. */ - data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.crlf = (0 != va_arg(param, long)); break; #ifndef CURL_DISABLE_PROXY case CURLOPT_HAPROXYPROTOCOL: /* * Set to send the HAProxy Proxy Protocol header */ - data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.haproxyprotocol = (0 != va_arg(param, long)); break; case CURLOPT_HAPROXY_CLIENT_IP: /* @@ -1926,22 +1909,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Enable peer SSL verifying. */ - data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ? - TRUE : FALSE; + data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)); /* Update the current connection ssl_config. */ - if(data->conn) { - data->conn->ssl_config.verifypeer = - data->set.ssl.primary.verifypeer; - } + Curl_ssl_conn_config_update(data, FALSE); break; #ifndef CURL_DISABLE_DOH case CURLOPT_DOH_SSL_VERIFYPEER: /* * Enable peer SSL verifying for DoH. */ - data->set.doh_verifypeer = (0 != va_arg(param, long)) ? - TRUE : FALSE; + data->set.doh_verifypeer = (0 != va_arg(param, long)); break; #endif #ifndef CURL_DISABLE_PROXY @@ -1953,10 +1931,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) (0 != va_arg(param, long))?TRUE:FALSE; /* Update the current connection proxy_ssl_config. */ - if(data->conn) { - data->conn->proxy_ssl_config.verifypeer = - data->set.proxy_ssl.primary.verifypeer; - } + Curl_ssl_conn_config_update(data, TRUE); break; #endif case CURLOPT_SSL_VERIFYHOST: @@ -1968,13 +1943,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* Obviously people are not reading documentation and too many thought this argument took a boolean when it wasn't and misused it. Treat 1 and 2 the same */ - data->set.ssl.primary.verifyhost = (bool)((arg & 3) ? TRUE : FALSE); + data->set.ssl.primary.verifyhost = !!(arg & 3); /* Update the current connection ssl_config. */ - if(data->conn) { - data->conn->ssl_config.verifyhost = - data->set.ssl.primary.verifyhost; - } + Curl_ssl_conn_config_update(data, FALSE); break; #ifndef CURL_DISABLE_DOH case CURLOPT_DOH_SSL_VERIFYHOST: @@ -1984,7 +1956,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) arg = va_arg(param, long); /* Treat both 1 and 2 as TRUE */ - data->set.doh_verifyhost = (bool)((arg & 3) ? TRUE : FALSE); + data->set.doh_verifyhost = !!(arg & 3); break; #endif #ifndef CURL_DISABLE_PROXY @@ -1996,12 +1968,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* Treat both 1 and 2 as TRUE */ data->set.proxy_ssl.primary.verifyhost = (bool)((arg & 3)?TRUE:FALSE); - /* Update the current connection proxy_ssl_config. */ - if(data->conn) { - data->conn->proxy_ssl_config.verifyhost = - data->set.proxy_ssl.primary.verifyhost; - } + Curl_ssl_conn_config_update(data, TRUE); break; #endif case CURLOPT_SSL_VERIFYSTATUS: @@ -2013,14 +1981,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; } - data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ? - TRUE : FALSE; + data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)); /* Update the current connection ssl_config. */ - if(data->conn) { - data->conn->ssl_config.verifystatus = - data->set.ssl.primary.verifystatus; - } + Curl_ssl_conn_config_update(data, FALSE); break; #ifndef CURL_DISABLE_DOH case CURLOPT_DOH_SSL_VERIFYSTATUS: @@ -2032,8 +1996,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; } - data->set.doh_verifystatus = (0 != va_arg(param, long)) ? - TRUE : FALSE; + data->set.doh_verifystatus = (0 != va_arg(param, long)); break; #endif case CURLOPT_SSL_CTX_FUNCTION: @@ -2067,12 +2030,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; } - data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ssl.falsestart = (0 != va_arg(param, long)); break; case CURLOPT_CERTINFO: #ifdef USE_SSL if(Curl_ssl_supports(data, SSLSUPP_CERTINFO)) - data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ssl.certinfo = (0 != va_arg(param, long)); else #endif result = CURLE_NOT_BUILT_IN; @@ -2118,14 +2081,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Specify entire PEM of the CA certificate */ #ifdef USE_SSL - if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) + if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) { result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO], va_arg(param, struct curl_blob *)); + break; + } else #endif return CURLE_NOT_BUILT_IN; - - break; #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXY_CAINFO: /* @@ -2141,13 +2104,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Specify entire PEM of the CA certificate */ #ifdef USE_SSL - if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) + if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) { result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY], va_arg(param, struct curl_blob *)); + break; + } else #endif return CURLE_NOT_BUILT_IN; - break; #endif case CURLOPT_CAPATH: /* @@ -2278,7 +2242,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * The application asks not to set any signal() or alarm() handlers, * even when using a timeout. */ - data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.no_signal = (0 != va_arg(param, long)); break; case CURLOPT_SHARE: @@ -2453,11 +2417,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Enable or disable TCP_NODELAY, which will disable/enable the Nagle * algorithm */ - data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.tcp_nodelay = (0 != va_arg(param, long)); break; case CURLOPT_IGNORE_CONTENT_LENGTH: - data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ignorecl = (0 != va_arg(param, long)); break; case CURLOPT_CONNECT_ONLY: @@ -2532,8 +2496,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_SSL_SESSIONID_CACHE: - data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ? - TRUE : FALSE; + data->set.ssl.primary.sessionid = (0 != va_arg(param, long)); #ifndef CURL_DISABLE_PROXY data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid; #endif @@ -2622,7 +2585,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * disable libcurl transfer encoding is used */ #ifndef USE_HYPER - data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE; + data->set.http_te_skip = (0 == va_arg(param, long)); break; #else return CURLE_NOT_BUILT_IN; /* hyper doesn't support */ @@ -2632,7 +2595,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * raw data passed to the application when content encoding is used */ - data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE; + data->set.http_ce_skip = (0 == va_arg(param, long)); break; #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) @@ -2733,7 +2696,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_MAIL_RCPT_ALLOWFAILS: /* allow RCPT TO command to fail for some recipients */ - data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)); break; #endif @@ -2745,7 +2708,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_SASL_IR: /* Enable/disable SASL initial response */ - data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.sasl_ir = (0 != va_arg(param, long)); break; #ifndef CURL_DISABLE_RTSP case CURLOPT_RTSP_REQUEST: @@ -2859,7 +2822,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) #endif #ifndef CURL_DISABLE_FTP case CURLOPT_WILDCARDMATCH: - data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.wildcard_enabled = (0 != va_arg(param, long)); break; case CURLOPT_CHUNK_BGN_FUNCTION: data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback); @@ -2942,7 +2905,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; #endif case CURLOPT_TCP_KEEPALIVE: - data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.tcp_keepalive = (0 != va_arg(param, long)); break; case CURLOPT_TCP_KEEPIDLE: arg = va_arg(param, long); @@ -2971,7 +2934,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_SSL_ENABLE_NPN: break; case CURLOPT_SSL_ENABLE_ALPN: - data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ssl_enable_alpn = (0 != va_arg(param, long)); break; #ifdef USE_UNIX_SOCKETS case CURLOPT_UNIX_SOCKET_PATH: @@ -2987,10 +2950,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) #endif case CURLOPT_PATH_AS_IS: - data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.path_as_is = (0 != va_arg(param, long)); break; case CURLOPT_PIPEWAIT: - data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.pipewait = (0 != va_arg(param, long)); break; case CURLOPT_STREAM_WEIGHT: #if defined(USE_HTTP2) || defined(USE_HTTP3) @@ -3025,12 +2988,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; #ifndef CURL_DISABLE_SHUFFLE_DNS case CURLOPT_DNS_SHUFFLE_ADDRESSES: - data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE; + data->set.dns_shuffle_addresses = (0 != va_arg(param, long)); break; #endif case CURLOPT_DISALLOW_USERNAME_IN_URL: - data->set.disallow_username_in_url = - (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.disallow_username_in_url = (0 != va_arg(param, long)); break; #ifndef CURL_DISABLE_DOH case CURLOPT_DOH_URL: @@ -3095,18 +3057,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* this needs to build a list of file names to read from, so that it can read them later, as we might get a shared HSTS handle to load them into */ - h = curl_slist_append(data->set.hstslist, argptr); + h = curl_slist_append(data->state.hstslist, argptr); if(!h) { - curl_slist_free_all(data->set.hstslist); - data->set.hstslist = NULL; + curl_slist_free_all(data->state.hstslist); + data->state.hstslist = NULL; return CURLE_OUT_OF_MEMORY; } - data->set.hstslist = h; /* store the list for later use */ + data->state.hstslist = h; /* store the list for later use */ } else { /* clear the list of HSTS files */ - curl_slist_free_all(data->set.hstslist); - data->set.hstslist = NULL; + curl_slist_free_all(data->state.hstslist); + data->state.hstslist = NULL; if(!data->share || !data->share->hsts) /* throw away the HSTS cache unless shared */ Curl_hsts_cleanup(&data->hsts); diff --git a/libs/libcurl/src/setup-win32.h b/libs/libcurl/src/setup-win32.h index 43701e20bf..2203c46a55 100644 --- a/libs/libcurl/src/setup-win32.h +++ b/libs/libcurl/src/setup-win32.h @@ -53,14 +53,14 @@ # ifndef NOGDI # define NOGDI # endif -# include -# include # ifdef HAVE_WINSOCK2_H # include # ifdef HAVE_WS2TCPIP_H # include # endif # endif +# include +# include # include # ifdef UNICODE typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str); @@ -96,18 +96,12 @@ #ifndef _WIN32_WINNT_WS03 #define _WIN32_WINNT_WS03 0x0502 /* Windows Server 2003 */ #endif -#ifndef _WIN32_WINNT_WIN6 -#define _WIN32_WINNT_WIN6 0x0600 /* Windows Vista */ -#endif #ifndef _WIN32_WINNT_VISTA #define _WIN32_WINNT_VISTA 0x0600 /* Windows Vista */ #endif #ifndef _WIN32_WINNT_WS08 #define _WIN32_WINNT_WS08 0x0600 /* Windows Server 2008 */ #endif -#ifndef _WIN32_WINNT_LONGHORN -#define _WIN32_WINNT_LONGHORN 0x0600 /* Windows Vista */ -#endif #ifndef _WIN32_WINNT_WIN7 #define _WIN32_WINNT_WIN7 0x0601 /* Windows 7 */ #endif @@ -117,9 +111,6 @@ #ifndef _WIN32_WINNT_WINBLUE #define _WIN32_WINNT_WINBLUE 0x0603 /* Windows 8.1 */ #endif -#ifndef _WIN32_WINNT_WINTHRESHOLD -#define _WIN32_WINNT_WINTHRESHOLD 0x0A00 /* Windows 10 */ -#endif #ifndef _WIN32_WINNT_WIN10 #define _WIN32_WINNT_WIN10 0x0A00 /* Windows 10 */ #endif diff --git a/libs/libcurl/src/share.h b/libs/libcurl/src/share.h index 0f4d6a31b3..e3e130daed 100644 --- a/libs/libcurl/src/share.h +++ b/libs/libcurl/src/share.h @@ -31,14 +31,6 @@ #include "urldata.h" #include "conncache.h" -/* SalfordC says "A structure member may not be volatile". Hence: - */ -#ifdef __SALFORDC__ -#define CURL_VOLATILE -#else -#define CURL_VOLATILE volatile -#endif - #define CURL_GOOD_SHARE 0x7e117a1e #define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE) @@ -46,7 +38,7 @@ struct Curl_share { unsigned int magic; /* CURL_GOOD_SHARE */ unsigned int specifier; - CURL_VOLATILE unsigned int dirty; + volatile unsigned int dirty; curl_lock_function lockfunc; curl_unlock_function unlockfunc; diff --git a/libs/libcurl/src/smb.c b/libs/libcurl/src/smb.c index f708ded3ca..130382c740 100644 --- a/libs/libcurl/src/smb.c +++ b/libs/libcurl/src/smb.c @@ -27,7 +27,7 @@ #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) -#ifdef WIN32 +#ifdef _WIN32 #define getpid GetCurrentProcessId #endif @@ -1047,14 +1047,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done) break; } } - data->req.bytecount += len; data->req.offset += len; - result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount); - if(result) { - req->result = result; - next_state = SMB_CLOSE; - break; - } next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD; break; diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c index 10a4b9c038..b6da9ba679 100644 --- a/libs/libcurl/src/smtp.c +++ b/libs/libcurl/src/smtp.c @@ -1320,7 +1320,7 @@ static CURLcode smtp_init(struct Curl_easy *data) CURLcode result = CURLE_OK; struct SMTP *smtp; - smtp = data->req.p.smtp = calloc(sizeof(struct SMTP), 1); + smtp = data->req.p.smtp = calloc(1, sizeof(struct SMTP)); if(!smtp) result = CURLE_OUT_OF_MEMORY; diff --git a/libs/libcurl/src/socketpair.c b/libs/libcurl/src/socketpair.c index 7733ab3322..9d4020426f 100644 --- a/libs/libcurl/src/socketpair.c +++ b/libs/libcurl/src/socketpair.c @@ -28,7 +28,7 @@ #include "rand.h" #if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR) -#ifdef WIN32 +#ifdef _WIN32 /* * This is a socketpair() implementation for Windows. */ @@ -50,7 +50,7 @@ #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK 0x7f000001 #endif /* !INADDR_LOOPBACK */ -#endif /* !WIN32 */ +#endif /* !_WIN32 */ #include "nonblock.h" /* for curlx_nonblock */ #include "timeval.h" /* needed before select.h */ @@ -87,7 +87,7 @@ int Curl_socketpair(int domain, int type, int protocol, socks[0] = socks[1] = CURL_SOCKET_BAD; -#if defined(WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) || defined(__CYGWIN__) /* don't set SO_REUSEADDR on Windows */ (void)reuse; #ifdef SO_EXCLUSIVEADDRUSE diff --git a/libs/libcurl/src/socketpair.h b/libs/libcurl/src/socketpair.h index cd6faf788a..08f076d916 100644 --- a/libs/libcurl/src/socketpair.h +++ b/libs/libcurl/src/socketpair.h @@ -25,6 +25,23 @@ ***************************************************************************/ #include "curl_setup.h" + +#ifdef HAVE_PIPE + +#define wakeup_write write +#define wakeup_read read +#define wakeup_close close +#define wakeup_create pipe + +#else /* HAVE_PIPE */ + +#define wakeup_write swrite +#define wakeup_read sread +#define wakeup_close sclose +#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p) + +#endif /* HAVE_PIPE */ + #ifndef HAVE_SOCKETPAIR #include diff --git a/libs/libcurl/src/socks.c b/libs/libcurl/src/socks.c index 487f26d2c4..2a8f106510 100644 --- a/libs/libcurl/src/socks.c +++ b/libs/libcurl/src/socks.c @@ -339,8 +339,8 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf, if(dns) { #ifdef CURLRES_ASYNCH - data->state.async.dns = dns; - data->state.async.done = TRUE; + conn->resolve_async.dns = dns; + conn->resolve_async.done = TRUE; #endif infof(data, "Hostname '%s' was found", sx->hostname); sxstate(sx, data, CONNECT_RESOLVED); @@ -402,8 +402,11 @@ CONNECT_REQ_INIT: socksreq[8] = 0; /* ensure empty userid is NUL-terminated */ if(sx->proxy_user) { size_t plen = strlen(sx->proxy_user); - if(plen >= (size_t)data->set.buffer_size - 8) { - failf(data, "Too long SOCKS proxy user name, can't use"); + if(plen > 255) { + /* there is no real size limit to this field in the protocol, but + SOCKS5 limits the proxy user field to 255 bytes and it seems likely + that a longer field is either a mistake or malicious input */ + failf(data, "Too long SOCKS proxy user name"); return CURLPX_LONG_USER; } /* copy the proxy name WITH trailing zero */ @@ -426,7 +429,8 @@ CONNECT_REQ_INIT: socksreq[7] = 1; /* append hostname */ hostnamelen = strlen(sx->hostname) + 1; /* length including NUL */ - if(hostnamelen <= 255) + if((hostnamelen <= 255) && + (packetsize + hostnamelen < data->set.buffer_size)) strcpy((char *)socksreq + packetsize, sx->hostname); else { failf(data, "SOCKS4: too long host name"); @@ -802,8 +806,8 @@ CONNECT_REQ_INIT: if(dns) { #ifdef CURLRES_ASYNCH - data->state.async.dns = dns; - data->state.async.done = TRUE; + conn->resolve_async.dns = dns; + conn->resolve_async.done = TRUE; #endif infof(data, "SOCKS5: hostname '%s' found", sx->hostname); } @@ -819,10 +823,19 @@ CONNECT_REQ_INIT: /* FALLTHROUGH */ CONNECT_RESOLVED: case CONNECT_RESOLVED: { - char dest[MAX_IPADR_LEN] = "unknown"; /* printable address */ + char dest[MAX_IPADR_LEN]; /* printable address */ struct Curl_addrinfo *hp = NULL; if(dns) hp = dns->addr; +#ifdef ENABLE_IPV6 + if(data->set.ipver != CURL_IPRESOLVE_WHATEVER) { + int wanted_family = data->set.ipver == CURL_IPRESOLVE_V4 ? + AF_INET : AF_INET6; + /* scan for the first proper address */ + while(hp && (hp->ai_family != wanted_family)) + hp = hp->ai_next; + } +#endif if(!hp) { failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", sx->hostname); @@ -1119,7 +1132,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf, return result; if(!sx) { - sx = calloc(sizeof(*sx), 1); + sx = calloc(1, sizeof(*sx)); if(!sx) return CURLE_OUT_OF_MEMORY; cf->ctx = sx; @@ -1157,32 +1170,29 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf, return result; } -static int socks_cf_get_select_socks(struct Curl_cfilter *cf, +static void socks_cf_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) + struct easy_pollset *ps) { struct socks_state *sx = cf->ctx; - int fds; - fds = cf->next->cft->get_select_socks(cf->next, data, socks); - if(!fds && cf->next->connected && !cf->connected && sx) { + if(!cf->connected && sx) { /* If we are not connected, the filter below is and has nothing * to wait on, we determine what to wait for. */ - socks[0] = Curl_conn_cf_get_socket(cf, data); + curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); switch(sx->state) { case CONNECT_RESOLVING: case CONNECT_SOCKS_READ: case CONNECT_AUTH_READ: case CONNECT_REQ_READ: case CONNECT_REQ_READ_MORE: - fds = GETSOCK_READSOCK(0); + Curl_pollset_set_in_only(data, ps, sock); break; default: - fds = GETSOCK_WRITESOCK(0); + Curl_pollset_set_out_only(data, ps, sock); break; } } - return fds; } static void socks_proxy_cf_close(struct Curl_cfilter *cf, @@ -1227,7 +1237,7 @@ struct Curl_cftype Curl_cft_socks_proxy = { socks_proxy_cf_connect, socks_proxy_cf_close, socks_cf_get_host, - socks_cf_get_select_socks, + socks_cf_adjust_pollset, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, diff --git a/libs/libcurl/src/strdup.c b/libs/libcurl/src/strdup.c index 1008d94fe5..ee341ef27e 100644 --- a/libs/libcurl/src/strdup.c +++ b/libs/libcurl/src/strdup.c @@ -26,7 +26,7 @@ #include -#ifdef WIN32 +#ifdef _WIN32 #include #endif @@ -56,7 +56,7 @@ char *Curl_strdup(const char *str) } #endif -#ifdef WIN32 +#ifdef _WIN32 /*************************************************************************** * * Curl_wcsdup(source) @@ -99,6 +99,30 @@ void *Curl_memdup(const void *src, size_t length) return buffer; } +/*************************************************************************** + * + * Curl_strndup(source, length) + * + * Copies the 'source' string to a newly allocated buffer (that is returned). + * Copies not more than 'length' bytes (up to a null terminator) then adds a + * null terminator. + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +void *Curl_strndup(const char *src, size_t length) +{ + char *buf = memchr(src, '\0', length); + if(buf) + length = buf - src; + buf = malloc(length + 1); + if(!buf) + return NULL; + memcpy(buf, src, length); + buf[length] = 0; + return buf; +} + /*************************************************************************** * * Curl_saferealloc(ptr, size) diff --git a/libs/libcurl/src/strdup.h b/libs/libcurl/src/strdup.h index 8bf1c9a8d3..7c7862db45 100644 --- a/libs/libcurl/src/strdup.h +++ b/libs/libcurl/src/strdup.h @@ -28,10 +28,11 @@ #ifndef HAVE_STRDUP char *Curl_strdup(const char *str); #endif -#ifdef WIN32 +#ifdef _WIN32 wchar_t* Curl_wcsdup(const wchar_t* src); #endif void *Curl_memdup(const void *src, size_t buffer_length); void *Curl_saferealloc(void *ptr, size_t size); +void *Curl_strndup(const char *src, size_t length); #endif /* HEADER_CURL_STRDUP_H */ diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c index 2d64a277eb..57105759d2 100644 --- a/libs/libcurl/src/strerror.c +++ b/libs/libcurl/src/strerror.c @@ -48,7 +48,7 @@ #include "curl_memory.h" #include "memdebug.h" -#if defined(WIN32) || defined(_WIN32_WCE) +#if defined(_WIN32) || defined(_WIN32_WCE) #define PRESERVE_WINDOWS_ERROR_CODE #endif @@ -762,7 +762,7 @@ get_winsock_error (int err, char *buf, size_t len) } #endif /* USE_WINSOCK */ -#if defined(WIN32) || defined(_WIN32_WCE) +#if defined(_WIN32) || defined(_WIN32_WCE) /* This is a helper function for Curl_strerror that converts Windows API error * codes (GetLastError) to error messages. * Returns NULL if no error message was found for error code. @@ -804,7 +804,7 @@ get_winapi_error(int err, char *buf, size_t buflen) return (*buf ? buf : NULL); } -#endif /* WIN32 || _WIN32_WCE */ +#endif /* _WIN32 || _WIN32_WCE */ /* * Our thread-safe and smart strerror() replacement. @@ -837,15 +837,15 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) if(!buflen) return NULL; -#ifndef WIN32 +#ifndef _WIN32 DEBUGASSERT(err >= 0); #endif max = buflen - 1; *buf = '\0'; -#if defined(WIN32) || defined(_WIN32_WCE) -#if defined(WIN32) +#if defined(_WIN32) || defined(_WIN32_WCE) +#if defined(_WIN32) /* 'sys_nerr' is the maximum errno number, it is not widely portable */ if(err >= 0 && err < sys_nerr) strncpy(buf, sys_errlist[err], max); @@ -923,7 +923,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) * Curl_winapi_strerror: * Variant of Curl_strerror if the error code is definitely Windows API. */ -#if defined(WIN32) || defined(_WIN32_WCE) +#if defined(_WIN32) || defined(_WIN32_WCE) const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen) { #ifdef PRESERVE_WINDOWS_ERROR_CODE @@ -958,7 +958,7 @@ const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen) return buf; } -#endif /* WIN32 || _WIN32_WCE */ +#endif /* _WIN32 || _WIN32_WCE */ #ifdef USE_WINDOWS_SSPI /* @@ -986,6 +986,10 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen) break; #define SEC2TXT(sec) case sec: txt = #sec; break SEC2TXT(CRYPT_E_REVOKED); + SEC2TXT(CRYPT_E_NO_REVOCATION_DLL); + SEC2TXT(CRYPT_E_NO_REVOCATION_CHECK); + SEC2TXT(CRYPT_E_REVOCATION_OFFLINE); + SEC2TXT(CRYPT_E_NOT_IN_REVOCATION_DATABASE); SEC2TXT(SEC_E_ALGORITHM_MISMATCH); SEC2TXT(SEC_E_BAD_BINDINGS); SEC2TXT(SEC_E_BAD_PKGID); diff --git a/libs/libcurl/src/strerror.h b/libs/libcurl/src/strerror.h index e0fd369d47..1fd423fc17 100644 --- a/libs/libcurl/src/strerror.h +++ b/libs/libcurl/src/strerror.h @@ -29,7 +29,7 @@ #define STRERROR_LEN 256 /* a suitable length */ const char *Curl_strerror(int err, char *buf, size_t buflen); -#if defined(WIN32) || defined(_WIN32_WCE) +#if defined(_WIN32) || defined(_WIN32_WCE) const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen); #endif #ifdef USE_WINDOWS_SSPI diff --git a/libs/libcurl/src/system_win32.c b/libs/libcurl/src/system_win32.c index f4a03cfea4..10d7fa9c27 100644 --- a/libs/libcurl/src/system_win32.c +++ b/libs/libcurl/src/system_win32.c @@ -24,7 +24,7 @@ #include "curl_setup.h" -#if defined(WIN32) +#if defined(_WIN32) #include #include "system_win32.h" @@ -238,4 +238,4 @@ HMODULE Curl_load_library(LPCTSTR filename) #endif } -#endif /* WIN32 */ +#endif /* _WIN32 */ diff --git a/libs/libcurl/src/system_win32.h b/libs/libcurl/src/system_win32.h index 33169a129d..f14ae8e4e5 100644 --- a/libs/libcurl/src/system_win32.h +++ b/libs/libcurl/src/system_win32.h @@ -26,7 +26,7 @@ #include "curl_setup.h" -#if defined(WIN32) +#if defined(_WIN32) extern LARGE_INTEGER Curl_freq; extern bool Curl_isVistaOrGreater; @@ -42,8 +42,8 @@ extern IF_NAMETOINDEX_FN Curl_if_nametoindex; /* This is used to dynamically load DLLs */ HMODULE Curl_load_library(LPCTSTR filename); -#else /* WIN32 */ +#else /* _WIN32 */ #define Curl_win32_init(x) CURLE_OK -#endif /* !WIN32 */ +#endif /* !_WIN32 */ #endif /* HEADER_CURL_SYSTEM_WIN32_H */ diff --git a/libs/libcurl/src/tftp.c b/libs/libcurl/src/tftp.c index 028fc2af6d..9f0877cbf2 100644 --- a/libs/libcurl/src/tftp.c +++ b/libs/libcurl/src/tftp.c @@ -70,8 +70,6 @@ /* RFC2348 allows the block size to be negotiated */ #define TFTP_BLKSIZE_DEFAULT 512 -#define TFTP_BLKSIZE_MIN 8 -#define TFTP_BLKSIZE_MAX 65464 #define TFTP_OPTION_BLKSIZE "blksize" /* from RFC2349: */ @@ -978,11 +976,9 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done) return CURLE_OUT_OF_MEMORY; /* alloc pkt buffers based on specified blksize */ - if(data->set.tftp_blksize) { + if(data->set.tftp_blksize) + /* range checked when set */ blksize = (int)data->set.tftp_blksize; - if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN) - return CURLE_TFTP_ILLEGAL; - } need_blksize = blksize; /* default size is the fallback when no OACK is received */ @@ -1107,7 +1103,6 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data) CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; struct tftp_state_data *state = conn->proto.tftpc; - struct SingleRequest *k = &data->req; /* Receive the packet */ fromlen = sizeof(fromaddr); @@ -1141,11 +1136,6 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data) result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)state->rpacket.data + 4, state->rbytes-4); - if(!result) { - k->bytecount += state->rbytes-4; - result = Curl_pgrsSetDownloadCounter(data, - (curl_off_t) k->bytecount); - } if(result) { tftp_state_machine(state, TFTP_EVENT_ERROR); return result; diff --git a/libs/libcurl/src/tftp.h b/libs/libcurl/src/tftp.h index acdde26a68..47d0db76b6 100644 --- a/libs/libcurl/src/tftp.h +++ b/libs/libcurl/src/tftp.h @@ -25,6 +25,9 @@ ***************************************************************************/ #ifndef CURL_DISABLE_TFTP extern const struct Curl_handler Curl_handler_tftp; + +#define TFTP_BLKSIZE_MIN 8 +#define TFTP_BLKSIZE_MAX 65464 #endif #endif /* HEADER_CURL_TFTP_H */ diff --git a/libs/libcurl/src/timediff.c b/libs/libcurl/src/timediff.c index c044b96680..a98d5782c1 100644 --- a/libs/libcurl/src/timediff.c +++ b/libs/libcurl/src/timediff.c @@ -53,7 +53,7 @@ struct timeval *curlx_mstotv(struct timeval *tv, timediff_t ms) #endif tv->tv_sec = (time_t)tv_sec; tv->tv_usec = (suseconds_t)tv_usec; -#elif defined(WIN32) /* maybe also others in the future */ +#elif defined(_WIN32) /* maybe also others in the future */ #if TIMEDIFF_T_MAX > LONG_MAX /* tv_sec overflow check on Windows there we know it is long */ if(tv_sec > LONG_MAX) diff --git a/libs/libcurl/src/timeval.c b/libs/libcurl/src/timeval.c index 8989c5b8b9..a15e138e25 100644 --- a/libs/libcurl/src/timeval.c +++ b/libs/libcurl/src/timeval.c @@ -24,11 +24,10 @@ #include "timeval.h" -#if defined(WIN32) && !defined(MSDOS) +#if defined(_WIN32) -/* set in win32_init() */ -extern LARGE_INTEGER Curl_freq; -extern bool Curl_isVistaOrGreater; +#include +#include "system_win32.h" /* In case of bug fix this function has a counterpart in tool_util.c */ struct curltime Curl_now(void) diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c index 44e5f03cea..1fe0bbae06 100644 --- a/libs/libcurl/src/transfer.c +++ b/libs/libcurl/src/transfer.c @@ -163,9 +163,9 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, { size_t buffersize = bytes; size_t nread; - curl_read_callback readfunc = NULL; void *extra_data = NULL; + int eof_index = 0; #ifndef CURL_DISABLE_HTTP if(data->state.trailers_state == TRAILERS_INITIALIZED) { @@ -223,6 +223,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, */ readfunc = trailers_read; extra_data = (void *)data; + eof_index = 1; } else #endif @@ -231,10 +232,15 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, extra_data = data->state.in; } - Curl_set_in_callback(data, true); - nread = readfunc(data->req.upload_fromhere, 1, - buffersize, extra_data); - Curl_set_in_callback(data, false); + if(!data->req.fread_eof[eof_index]) { + Curl_set_in_callback(data, true); + nread = readfunc(data->req.upload_fromhere, 1, buffersize, extra_data); + Curl_set_in_callback(data, false); + /* make sure the callback is not called again after EOF */ + data->req.fread_eof[eof_index] = !nread; + } + else + nread = 0; if(nread == CURL_READFUNC_ABORT) { failf(data, "operation aborted by callback"); @@ -422,16 +428,15 @@ static CURLcode readwrite_data(struct Curl_easy *data, bool *comeback) { CURLcode result = CURLE_OK; - ssize_t nread; /* number of bytes read */ - size_t excess = 0; /* excess bytes read */ - bool readmore = FALSE; /* used by RTP to signal for more data */ + char *buf; + size_t blen; + size_t consumed; int maxloops = 100; curl_off_t max_recv = data->set.max_recv_speed? data->set.max_recv_speed : CURL_OFF_T_MAX; - char *buf = data->state.buffer; bool data_eof_handled = FALSE; - DEBUGASSERT(buf); + DEBUGASSERT(data->state.buffer); *done = FALSE; *comeback = FALSE; @@ -439,8 +444,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, read or we get a CURLE_AGAIN */ do { bool is_empty_data = FALSE; - size_t buffersize = data->set.buffer_size; - size_t bytestoread = buffersize; + size_t bytestoread = data->set.buffer_size; /* For HTTP/2 and HTTP/3, read data without caring about the content length. This is safe because body in HTTP/2 is always segmented thanks to its framing layer. Meanwhile, we have to call Curl_read @@ -449,31 +453,38 @@ static CURLcode readwrite_data(struct Curl_easy *data, bool is_http3 = Curl_conn_is_http3(data, conn, FIRSTSOCKET); data_eof_handled = is_http3 || Curl_conn_is_http2(data, conn, FIRSTSOCKET); - if(!data_eof_handled && k->size != -1 && !k->header) { - /* make sure we don't read too much */ + /* Each loop iteration starts with a fresh buffer and handles + * all data read into it. */ + buf = data->state.buffer; + blen = 0; + + /* If we are reading BODY data and the connection does NOT handle EOF + * and we know the size of the BODY data, limit the read amount */ + if(!k->header && !data_eof_handled && k->size != -1) { curl_off_t totalleft = k->size - k->bytecount; - if(totalleft < (curl_off_t)bytestoread) + if(totalleft <= 0) + bytestoread = 0; + else if(totalleft < (curl_off_t)bytestoread) bytestoread = (size_t)totalleft; } if(bytestoread) { /* receive data from the network! */ + ssize_t nread; /* number of bytes read */ result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread); - - /* read would've blocked */ if(CURLE_AGAIN == result) { result = CURLE_OK; break; /* get out of loop */ } - - if(result>0) + else if(result) goto out; + DEBUGASSERT(nread >= 0); + blen = (size_t)nread; } else { /* read nothing but since we wanted nothing we consider this an OK situation to proceed from */ DEBUGF(infof(data, "readwrite_data: we're done")); - nread = 0; } if(!k->bytecount) { @@ -485,12 +496,17 @@ static CURLcode readwrite_data(struct Curl_easy *data, *didwhat |= KEEP_RECV; /* indicates data of zero size, i.e. empty file */ - is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE; - - if(0 < nread || is_empty_data) { - buf[nread] = 0; + is_empty_data = ((blen == 0) && (k->bodywrites == 0)) ? TRUE : FALSE; + + if(0 < blen || is_empty_data) { + /* data->state.buffer is allocated 1 byte larger than + * data->set.buffer_size admits. *wink* */ + /* TODO: we should really not rely on this being 0-terminated, since + * the actual data read might contain 0s. */ + buf[blen] = 0; } - if(!nread) { + + if(!blen) { /* if we receive 0 or less here, either the data transfer is done or the server closed the connection and we bail out from this! */ if(data_eof_handled) @@ -502,48 +518,70 @@ static CURLcode readwrite_data(struct Curl_easy *data, break; } - /* Default buffer to use when we write the buffer, it may be changed - in the flow below before the actual storing is done. */ - k->str = buf; - if(conn->handler->readwrite) { - result = conn->handler->readwrite(data, conn, &nread, &readmore); + bool readmore = FALSE; /* indicates data is incomplete, need more */ + consumed = 0; + result = conn->handler->readwrite(data, conn, buf, blen, + &consumed, &readmore); if(result) goto out; if(readmore) break; + buf += consumed; + blen -= consumed; + if(k->download_done) { + /* We've stopped dealing with input, get out of the do-while loop */ + if(blen > 0) { + infof(data, + "Excess found:" + " excess = %zu" + " url = %s (zero-length body)", + blen, data->state.up.path); + } + + /* we make sure that this socket isn't read more now */ + k->keepon &= ~KEEP_RECV; + break; + } } #ifndef CURL_DISABLE_HTTP /* Since this is a two-state thing, we check if we are parsing headers at the moment or not. */ if(k->header) { - /* we are in parse-the-header-mode */ - bool stop_reading = FALSE; - result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading); + consumed = 0; + result = Curl_http_readwrite_headers(data, conn, buf, blen, &consumed); if(result) goto out; + buf += consumed; + blen -= consumed; if(conn->handler->readwrite && - (k->maxdownload <= 0 && nread > 0)) { - result = conn->handler->readwrite(data, conn, &nread, &readmore); + (k->maxdownload <= 0 && blen > 0)) { + bool readmore = FALSE; /* indicates data is incomplete, need more */ + consumed = 0; + result = conn->handler->readwrite(data, conn, buf, blen, + &consumed, &readmore); if(result) goto out; if(readmore) break; + buf += consumed; + blen -= consumed; } - if(stop_reading) { + if(k->download_done) { /* We've stopped dealing with input, get out of the do-while loop */ - - if(nread > 0) { + if(blen > 0) { infof(data, "Excess found:" - " excess = %zd" + " excess = %zu" " url = %s (zero-length body)", - nread, data->state.up.path); + blen, data->state.up.path); } + /* we make sure that this socket isn't read more now */ + k->keepon &= ~KEEP_RECV; break; } } @@ -553,11 +591,13 @@ static CURLcode readwrite_data(struct Curl_easy *data, /* This is not an 'else if' since it may be a rest from the header parsing, where the beginning of the buffer is headers and the end is non-headers. */ - if(!k->header && (nread > 0 || is_empty_data)) { + if(!k->header && (blen > 0 || is_empty_data)) { - if(data->req.no_body) { + if(data->req.no_body && blen > 0) { /* data arrives although we want none, bail out */ streamclose(conn, "ignoring body"); + DEBUGF(infof(data, "did not want a BODY, but seeing %zu bytes", + blen)); *done = TRUE; result = CURLE_WEIRD_SERVER_REPLY; goto out; @@ -576,34 +616,18 @@ static CURLcode readwrite_data(struct Curl_easy *data, } /* this is the first time we write a body part */ #endif /* CURL_DISABLE_HTTP */ - k->bodywrites++; - - /* pass data to the debug function before it gets "dechunked" */ - if(data->set.verbose) { - if(k->badheader) { - Curl_debug(data, CURLINFO_DATA_IN, - Curl_dyn_ptr(&data->state.headerb), - Curl_dyn_len(&data->state.headerb)); - if(k->badheader == HEADER_PARTHEADER) - Curl_debug(data, CURLINFO_DATA_IN, - k->str, (size_t)nread); - } - else - Curl_debug(data, CURLINFO_DATA_IN, - k->str, (size_t)nread); - } - #ifndef CURL_DISABLE_HTTP if(k->chunk) { /* * Here comes a chunked transfer flying and we need to decode this * properly. While the name says read, this function both reads - * and writes away the data. The returned 'nread' holds the number - * of actual data it wrote to the client. + * and writes away the data. */ CURLcode extra; - CHUNKcode res = - Curl_httpchunk_read(data, k->str, nread, &nread, &extra); + CHUNKcode res; + + consumed = 0; + res = Curl_httpchunk_read(data, buf, blen, &consumed, &extra); if(CHUNKE_OK < res) { if(CHUNKE_PASSTHRU_ERROR == res) { @@ -615,9 +639,14 @@ static CURLcode readwrite_data(struct Curl_easy *data, result = CURLE_RECV_ERROR; goto out; } - if(CHUNKE_STOP == res) { + + buf += consumed; + blen -= consumed; + if(CHUNKE_STOP == res) { /* we're done reading chunks! */ k->keepon &= ~KEEP_RECV; /* read no more */ + /* chunks read successfully, download is complete */ + k->download_done = TRUE; /* N number of bytes at the end of the str buffer that weren't written to the client. */ @@ -631,117 +660,57 @@ static CURLcode readwrite_data(struct Curl_easy *data, } #endif /* CURL_DISABLE_HTTP */ - /* Account for body content stored in the header buffer */ - if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) { - size_t headlen = Curl_dyn_len(&data->state.headerb); - DEBUGF(infof(data, "Increasing bytecount by %zu", headlen)); - k->bytecount += headlen; - } - - if((-1 != k->maxdownload) && - (k->bytecount + nread >= k->maxdownload)) { + max_recv -= blen; - excess = (size_t)(k->bytecount + nread - k->maxdownload); - if(excess > 0 && !k->ignorebody) { - infof(data, - "Excess found in a read:" - " excess = %zu" - ", size = %" CURL_FORMAT_CURL_OFF_T - ", maxdownload = %" CURL_FORMAT_CURL_OFF_T - ", bytecount = %" CURL_FORMAT_CURL_OFF_T, - excess, k->size, k->maxdownload, k->bytecount); - connclose(conn, "excess found in a read"); - } - - nread = (ssize_t) (k->maxdownload - k->bytecount); - if(nread < 0) /* this should be unusual */ - nread = 0; - - /* HTTP/3 over QUIC should keep reading until QUIC connection - is closed. In contrast to HTTP/2 which can stop reading - from TCP connection, HTTP/3 over QUIC needs ACK from server - to ensure stream closure. It should keep reading. */ - if(!is_http3) { - k->keepon &= ~KEEP_RECV; /* we're done reading */ - } - } - - k->bytecount += nread; - max_recv -= nread; - - result = Curl_pgrsSetDownloadCounter(data, k->bytecount); - if(result) - goto out; - - if(!k->chunk && (nread || k->badheader || is_empty_data)) { + if(!k->chunk && (blen || k->badheader || is_empty_data)) { /* If this is chunky transfer, it was already written */ - if(k->badheader && !k->ignorebody) { + if(k->badheader) { /* we parsed a piece of data wrongly assuming it was a header and now we output it as body instead */ size_t headlen = Curl_dyn_len(&data->state.headerb); /* Don't let excess data pollute body writes */ - if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload) - result = Curl_client_write(data, CLIENTWRITE_BODY, - Curl_dyn_ptr(&data->state.headerb), - headlen); - else - result = Curl_client_write(data, CLIENTWRITE_BODY, - Curl_dyn_ptr(&data->state.headerb), - (size_t)k->maxdownload); + if(k->maxdownload != -1 && (curl_off_t)headlen > k->maxdownload) + headlen = (size_t)k->maxdownload; + result = Curl_client_write(data, CLIENTWRITE_BODY, + Curl_dyn_ptr(&data->state.headerb), + headlen); if(result) goto out; } - if(k->badheader < HEADER_ALLBAD) { - /* This switch handles various content encodings. If there's an - error here, be sure to check over the almost identical code - in http_chunks.c. - Make sure that ALL_CONTENT_ENCODINGS contains all the - encodings handled here. */ - if(!k->ignorebody && nread) { + + if(blen) { #ifndef CURL_DISABLE_POP3 - if(conn->handler->protocol & PROTO_FAMILY_POP3) - result = Curl_pop3_write(data, k->str, nread); - else -#endif /* CURL_DISABLE_POP3 */ - result = Curl_client_write(data, CLIENTWRITE_BODY, k->str, - nread); + if(conn->handler->protocol & PROTO_FAMILY_POP3) { + result = k->ignorebody? CURLE_OK : + Curl_pop3_write(data, buf, blen); } + else +#endif /* CURL_DISABLE_POP3 */ + result = Curl_client_write(data, CLIENTWRITE_BODY, buf, blen); } - k->badheader = HEADER_NORMAL; /* taken care of now */ + k->badheader = FALSE; /* taken care of now */ if(result) goto out; } - } /* if(!header and data to read) */ - - if(conn->handler->readwrite && excess) { - /* Parse the excess data */ - k->str += nread; - - if(&k->str[excess] > &buf[data->set.buffer_size]) { - /* the excess amount was too excessive(!), make sure - it doesn't read out of buffer */ - excess = &buf[data->set.buffer_size] - k->str; + if(k->download_done && !is_http3) { + /* HTTP/3 over QUIC should keep reading until QUIC connection + is closed. In contrast to HTTP/2 which can stop reading + from TCP connection, HTTP/3 over QUIC needs ACK from server + to ensure stream closure. It should keep reading. */ + k->keepon &= ~KEEP_RECV; /* we're done reading */ } - nread = (ssize_t)excess; - - result = conn->handler->readwrite(data, conn, &nread, &readmore); - if(result) - goto out; - - if(readmore) - k->keepon |= KEEP_RECV; /* we're not done reading */ - break; - } + } /* if(!header and data to read) */ if(is_empty_data) { /* if we received nothing, the server closed the connection and we are done */ k->keepon &= ~KEEP_RECV; + k->download_done = TRUE; } if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV)) { @@ -764,6 +733,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, on from our side, we need to stop that immediately. */ infof(data, "we are done reading and this is set to close, stop send"); k->keepon &= ~KEEP_SEND; /* no writing anymore either */ + k->keepon &= ~KEEP_SEND_PAUSE; /* no pausing anymore either */ } out: @@ -783,7 +753,7 @@ CURLcode Curl_done_sending(struct Curl_easy *data, return CURLE_OK; } -#if defined(WIN32) && defined(USE_WINSOCK) +#if defined(_WIN32) && defined(USE_WINSOCK) #ifndef SIO_IDEAL_SEND_BACKLOG_QUERY #define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B #endif @@ -977,7 +947,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, if(result) return result; -#if defined(WIN32) && defined(USE_WINSOCK) +#if defined(_WIN32) && defined(USE_WINSOCK) { struct curltime n = Curl_now(); if(Curl_timediff(n, k->last_sndbuf_update) > 1000) { @@ -1430,8 +1400,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) return CURLE_OUT_OF_MEMORY; } wc = data->wildcard; - if((wc->state < CURLWC_INIT) || - (wc->state >= CURLWC_CLEAN)) { + if(wc->state < CURLWC_INIT) { if(wc->ftpwc) wc->dtor(wc->ftpwc); Curl_safefree(wc->pattern); @@ -1635,7 +1604,7 @@ CURLcode Curl_follow(struct Curl_easy *data, return Curl_uc_to_curlcode(uc); } - p = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED); + p = Curl_get_scheme_handler(scheme); if(p && (p->protocol != data->info.conn_protocol)) { infof(data, "Clear auth, redirects scheme from %s to %s", data->info.conn_scheme, scheme); diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c index 1746a51ca9..243a603c8b 100644 --- a/libs/libcurl/src/url.c +++ b/libs/libcurl/src/url.c @@ -168,130 +168,6 @@ static curl_prot_t get_protocol_family(const struct Curl_handler *h) return h->family; } - -/* - * Protocol table. Schemes (roughly) in 2019 popularity order: - * - * HTTPS, HTTP, FTP, FTPS, SFTP, FILE, SCP, SMTP, LDAP, IMAPS, TELNET, IMAP, - * LDAPS, SMTPS, TFTP, SMB, POP3, GOPHER POP3S, RTSP, RTMP, SMBS, DICT - */ -static const struct Curl_handler * const protocols[] = { - -#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_https, -#endif - -#ifndef CURL_DISABLE_HTTP - &Curl_handler_http, -#endif - -#ifdef USE_WEBSOCKETS -#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_wss, -#endif - -#ifndef CURL_DISABLE_HTTP - &Curl_handler_ws, -#endif -#endif - -#ifndef CURL_DISABLE_FTP - &Curl_handler_ftp, -#endif - -#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) - &Curl_handler_ftps, -#endif - -#if defined(USE_SSH) - &Curl_handler_sftp, -#endif - -#ifndef CURL_DISABLE_FILE - &Curl_handler_file, -#endif - -#if defined(USE_SSH) && !defined(USE_WOLFSSH) - &Curl_handler_scp, -#endif - -#ifndef CURL_DISABLE_SMTP - &Curl_handler_smtp, -#ifdef USE_SSL - &Curl_handler_smtps, -#endif -#endif - -#ifndef CURL_DISABLE_LDAP - &Curl_handler_ldap, -#if !defined(CURL_DISABLE_LDAPS) && \ - ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ - (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) - &Curl_handler_ldaps, -#endif -#endif - -#ifndef CURL_DISABLE_IMAP - &Curl_handler_imap, -#ifdef USE_SSL - &Curl_handler_imaps, -#endif -#endif - -#ifndef CURL_DISABLE_TELNET - &Curl_handler_telnet, -#endif - -#ifndef CURL_DISABLE_TFTP - &Curl_handler_tftp, -#endif - -#ifndef CURL_DISABLE_POP3 - &Curl_handler_pop3, -#ifdef USE_SSL - &Curl_handler_pop3s, -#endif -#endif - -#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ - (SIZEOF_CURL_OFF_T > 4) - &Curl_handler_smb, -#ifdef USE_SSL - &Curl_handler_smbs, -#endif -#endif - -#ifndef CURL_DISABLE_RTSP - &Curl_handler_rtsp, -#endif - -#ifndef CURL_DISABLE_MQTT - &Curl_handler_mqtt, -#endif - -#ifndef CURL_DISABLE_GOPHER - &Curl_handler_gopher, -#ifdef USE_SSL - &Curl_handler_gophers, -#endif -#endif - -#ifdef USE_LIBRTMP - &Curl_handler_rtmp, - &Curl_handler_rtmpt, - &Curl_handler_rtmpe, - &Curl_handler_rtmpte, - &Curl_handler_rtmps, - &Curl_handler_rtmpts, -#endif - -#ifndef CURL_DISABLE_DICT - &Curl_handler_dict, -#endif - - (struct Curl_handler *) NULL -}; - void Curl_freeset(struct Curl_easy *data) { /* Free all dynamic strings stored in the data->set substructure. */ @@ -320,8 +196,8 @@ void Curl_freeset(struct Curl_easy *data) Curl_mime_cleanpart(&data->set.mimepost); #ifndef CURL_DISABLE_COOKIES - curl_slist_free_all(data->set.cookielist); - data->set.cookielist = NULL; + curl_slist_free_all(data->state.cookielist); + data->state.cookielist = NULL; #endif } @@ -363,16 +239,18 @@ CURLcode Curl_close(struct Curl_easy **datap) /* Detach connection if any is left. This should not be normal, but can be the case for example with CONNECT_ONLY + recv/send (test 556) */ Curl_detach_connection(data); - if(data->multi) - /* This handle is still part of a multi handle, take care of this first - and detach this handle from there. */ - curl_multi_remove_handle(data->multi, data); + if(!data->state.internal) { + if(data->multi) + /* This handle is still part of a multi handle, take care of this first + and detach this handle from there. */ + curl_multi_remove_handle(data->multi, data); - if(data->multi_easy) { - /* when curl_easy_perform() is used, it creates its own multi handle to - use and this is the one */ - curl_multi_cleanup(data->multi_easy); - data->multi_easy = NULL; + if(data->multi_easy) { + /* when curl_easy_perform() is used, it creates its own multi handle to + use and this is the one */ + curl_multi_cleanup(data->multi_easy); + data->multi_easy = NULL; + } } data->magic = 0; /* force a clear AFTER the possibly enforced removal from @@ -412,7 +290,7 @@ CURLcode Curl_close(struct Curl_easy **datap) #ifndef CURL_DISABLE_HSTS if(!data->share || !data->share->hsts) Curl_hsts_cleanup(&data->hsts); - curl_slist_free_all(data->set.hstslist); /* clean up list */ + curl_slist_free_all(data->state.hstslist); /* clean up list */ #endif #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH) Curl_http_auth_cleanup_digest(data); @@ -420,10 +298,6 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->info.contenttype); Curl_safefree(data->info.wouldredirect); - /* this destroys the channel and we cannot use it anymore after this */ - Curl_resolver_cancel(data); - Curl_resolver_cleanup(data->state.async.resolver); - data_priority_cleanup(data); /* No longer a dirty share, if it exists */ @@ -457,8 +331,8 @@ CURLcode Curl_close(struct Curl_easy **datap) } #endif - Curl_mime_cleanpart(data->state.formp); #ifndef CURL_DISABLE_HTTP + Curl_mime_cleanpart(data->state.formp); Curl_safefree(data->state.formp); #endif @@ -530,26 +404,16 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) Curl_mime_initpart(&set->mimepost); - /* - * libcurl 7.10 introduced SSL verification *by default*! This needs to be - * switched off unless wanted. - */ + Curl_ssl_easy_config_init(data); #ifndef CURL_DISABLE_DOH set->doh_verifyhost = TRUE; set->doh_verifypeer = TRUE; #endif - set->ssl.primary.verifypeer = TRUE; - set->ssl.primary.verifyhost = TRUE; #ifdef USE_SSH /* defaults to any auth type */ set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; set->new_directory_perms = 0755; /* Default permissions */ #endif - set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by - default */ -#ifndef CURL_DISABLE_PROXY - set->proxy_ssl = set->ssl; -#endif set->new_file_perms = 0644; /* Default permissions */ set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL; @@ -650,13 +514,6 @@ CURLcode Curl_open(struct Curl_easy **curl) data->magic = CURLEASY_MAGIC_NUMBER; - result = Curl_resolver_init(data, &data->state.async.resolver); - if(result) { - DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); - free(data); - return result; - } - result = Curl_init_userdefined(data); if(!result) { Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER); @@ -673,7 +530,6 @@ CURLcode Curl_open(struct Curl_easy **curl) } if(result) { - Curl_resolver_cleanup(data->state.async.resolver); Curl_dyn_free(&data->state.headerb); Curl_freeset(data); free(data); @@ -707,6 +563,7 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_conn_cf_discard_all(data, conn, (int)i); } + Curl_resolver_cleanup(conn->resolve_async.resolver); Curl_free_idnconverted_hostname(&conn->host); Curl_free_idnconverted_hostname(&conn->conn_to_host); #ifndef CURL_DISABLE_PROXY @@ -718,7 +575,6 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_safefree(conn->socks_proxy.passwd); Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */ Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */ - Curl_free_primary_ssl_config(&conn->proxy_ssl_config); #endif Curl_safefree(conn->user); Curl_safefree(conn->passwd); @@ -733,7 +589,7 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_safefree(conn->hostname_resolve); Curl_safefree(conn->secondaryhostname); Curl_safefree(conn->localdev); - Curl_free_primary_ssl_config(&conn->ssl_config); + Curl_ssl_conn_config_cleanup(conn); #ifdef USE_UNIX_SOCKETS Curl_safefree(conn->unix_domain_socket); @@ -807,6 +663,7 @@ void Curl_disconnect(struct Curl_easy *data, conn->handler->disconnect(data, conn, dead_connection); conn_shutdown(data); + Curl_resolver_cancel(data); /* detach it again */ Curl_detach_connection(data); @@ -1059,11 +916,11 @@ ConnectionExists(struct Curl_easy *data, bool *force_reuse, bool *waitpipe) { - struct connectdata *check; - struct connectdata *chosen = 0; + struct connectdata *chosen = NULL; bool foundPendingCandidate = FALSE; - bool canmultiplex = IsMultiplexingPossible(data, needle); + bool canmultiplex = FALSE; struct connectbundle *bundle; + struct Curl_llist_element *curr; #ifdef USE_NTLM bool wantNTLMhttp = ((data->state.authhost.want & @@ -1082,395 +939,368 @@ ConnectionExists(struct Curl_easy *data, bool h2upgrade = (data->state.httpwant == CURL_HTTP_VERSION_2_0) && (needle->handler->protocol & CURLPROTO_HTTP); + *usethis = NULL; *force_reuse = FALSE; *waitpipe = FALSE; /* Look up the bundle with all the connections to this particular host. Locks the connection cache, beware of early returns! */ bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache); - if(bundle) { - /* Max pipe length is zero (unlimited) for multiplexed connections */ - struct Curl_llist_element *curr; - - infof(data, "Found bundle for host: %p [%s]", - (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ? - "can multiplex" : "serially")); - - /* We can't multiplex if we don't know anything about the server */ - if(canmultiplex) { - if(bundle->multiuse == BUNDLE_UNKNOWN) { - if(data->set.pipewait) { - infof(data, "Server doesn't support multiplex yet, wait"); - *waitpipe = TRUE; - CONNCACHE_UNLOCK(data); - return FALSE; /* no reuse */ - } - - infof(data, "Server doesn't support multiplex (yet)"); - canmultiplex = FALSE; + if(!bundle) { + CONNCACHE_UNLOCK(data); + return FALSE; + } + infof(data, "Found bundle for host: %p [%s]", + (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ? + "can multiplex" : "serially")); + + /* We can only multiplex iff the transfer allows it AND we know + * that the server we want to talk to supports it as well. */ + canmultiplex = FALSE; + if(IsMultiplexingPossible(data, needle)) { + if(bundle->multiuse == BUNDLE_UNKNOWN) { + if(data->set.pipewait) { + infof(data, "Server doesn't support multiplex yet, wait"); + *waitpipe = TRUE; + CONNCACHE_UNLOCK(data); + return FALSE; /* no reuse */ } - if((bundle->multiuse == BUNDLE_MULTIPLEX) && - !Curl_multiplex_wanted(data->multi)) { + infof(data, "Server doesn't support multiplex (yet)"); + } + else if(bundle->multiuse == BUNDLE_MULTIPLEX) { + if(Curl_multiplex_wanted(data->multi)) + canmultiplex = TRUE; + else infof(data, "Could multiplex, but not asked to"); - canmultiplex = FALSE; - } - if(bundle->multiuse == BUNDLE_NO_MULTIUSE) { - infof(data, "Can not multiplex, even if we wanted to"); - canmultiplex = FALSE; - } } + else if(bundle->multiuse == BUNDLE_NO_MULTIUSE) { + infof(data, "Can not multiplex, even if we wanted to"); + } + } - curr = bundle->conn_list.head; - while(curr) { - bool match = FALSE; - size_t multiplexed = 0; + curr = bundle->conn_list.head; + while(curr) { + struct connectdata *check = curr->ptr; + /* Get next node now. We might remove a dead `check` connection which + * would invalidate `curr` as well. */ + curr = curr->next; - /* - * Note that if we use an HTTP proxy in normal mode (no tunneling), we - * check connections to that proxy and not to the actual remote server. - */ - check = curr->ptr; - curr = curr->next; + /* Note that if we use an HTTP proxy in normal mode (no tunneling), we + * check connections to that proxy and not to the actual remote server. + */ + if(check->connect_only || check->bits.close) + /* connect-only or to-be-closed connections will not be reused */ + continue; - if(check->connect_only || check->bits.close) - /* connect-only or to-be-closed connections will not be reused */ - continue; + if(data->set.ipver != CURL_IPRESOLVE_WHATEVER + && data->set.ipver != check->ip_version) { + /* skip because the connection is not via the requested IP version */ + continue; + } - if(extract_if_dead(check, data)) { - /* disconnect it */ - Curl_disconnect(data, check, TRUE); + if(!canmultiplex) { + if(Curl_resolver_asynch() && + /* primary_ip[0] is NUL only if the resolving of the name hasn't + completed yet and until then we don't reuse this connection */ + !check->primary_ip[0]) continue; - } + } - if(data->set.ipver != CURL_IPRESOLVE_WHATEVER - && data->set.ipver != check->ip_version) { - /* skip because the connection is not via the requested IP version */ + if(CONN_INUSE(check)) { + if(!canmultiplex) { + /* transfer can't be multiplexed and check is in use */ continue; } - - if(bundle->multiuse == BUNDLE_MULTIPLEX) - multiplexed = CONN_INUSE(check); - - if(!canmultiplex) { - if(multiplexed) { - /* can only happen within multi handles, and means that another easy - handle is using this connection */ - continue; - } - - if(Curl_resolver_asynch() && - /* primary_ip[0] is NUL only if the resolving of the name hasn't - completed yet and until then we don't reuse this connection */ - !check->primary_ip[0]) + else { + /* Could multiplex, but not when check belongs to another multi */ + struct Curl_llist_element *e = check->easyq.head; + struct Curl_easy *entry = e->ptr; + if(entry->multi != data->multi) continue; } + } - if(!Curl_conn_is_connected(check, FIRSTSOCKET)) { - foundPendingCandidate = TRUE; - /* Don't pick a connection that hasn't connected yet */ - infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T - " isn't open enough, can't reuse", check->connection_id); - continue; - } + if(!Curl_conn_is_connected(check, FIRSTSOCKET)) { + foundPendingCandidate = TRUE; + /* Don't pick a connection that hasn't connected yet */ + infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T + " isn't open enough, can't reuse", check->connection_id); + continue; + } + + /* `check` is connected. if it is in use and does not support multiplex, + * we cannot use it. */ + if(!check->bits.multiplex && CONN_INUSE(check)) + continue; #ifdef USE_UNIX_SOCKETS - if(needle->unix_domain_socket) { - if(!check->unix_domain_socket) - continue; - if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) - continue; - if(needle->bits.abstract_unix_socket != - check->bits.abstract_unix_socket) - continue; - } - else if(check->unix_domain_socket) + if(needle->unix_domain_socket) { + if(!check->unix_domain_socket) continue; -#endif - - if((needle->handler->flags&PROTOPT_SSL) != - (check->handler->flags&PROTOPT_SSL)) - /* don't do mixed SSL and non-SSL connections */ - if(get_protocol_family(check->handler) != - needle->handler->protocol || !check->bits.tls_upgraded) - /* except protocols that have been upgraded via TLS */ - continue; - -#ifndef CURL_DISABLE_PROXY - if(needle->bits.httpproxy != check->bits.httpproxy || - needle->bits.socksproxy != check->bits.socksproxy) + if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) continue; - - if(needle->bits.socksproxy && - !socks_proxy_info_matches(&needle->socks_proxy, - &check->socks_proxy)) + if(needle->bits.abstract_unix_socket != + check->bits.abstract_unix_socket) continue; + } + else if(check->unix_domain_socket) + continue; #endif - if(needle->bits.conn_to_host != check->bits.conn_to_host) - /* don't mix connections that use the "connect to host" feature and - * connections that don't use this feature */ - continue; - if(needle->bits.conn_to_port != check->bits.conn_to_port) - /* don't mix connections that use the "connect to port" feature and - * connections that don't use this feature */ + if((needle->handler->flags&PROTOPT_SSL) != + (check->handler->flags&PROTOPT_SSL)) + /* don't do mixed SSL and non-SSL connections */ + if(get_protocol_family(check->handler) != + needle->handler->protocol || !check->bits.tls_upgraded) + /* except protocols that have been upgraded via TLS */ continue; -#ifndef CURL_DISABLE_PROXY - if(needle->bits.httpproxy) { - if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) - continue; + if(needle->bits.conn_to_host != check->bits.conn_to_host) + /* don't mix connections that use the "connect to host" feature and + * connections that don't use this feature */ + continue; - if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) - continue; + if(needle->bits.conn_to_port != check->bits.conn_to_port) + /* don't mix connections that use the "connect to port" feature and + * connections that don't use this feature */ + continue; - if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) { - /* use https proxy */ - if(needle->http_proxy.proxytype != - check->http_proxy.proxytype) - continue; - else if(needle->handler->flags&PROTOPT_SSL) { - /* use double layer ssl */ - if(!Curl_ssl_config_matches(&needle->proxy_ssl_config, - &check->proxy_ssl_config)) - continue; - } - else if(!Curl_ssl_config_matches(&needle->ssl_config, - &check->ssl_config)) - continue; - } - } -#endif +#ifndef CURL_DISABLE_PROXY + if(needle->bits.httpproxy != check->bits.httpproxy || + needle->bits.socksproxy != check->bits.socksproxy) + continue; - if(h2upgrade && !check->httpversion && canmultiplex) { - if(data->set.pipewait) { - infof(data, "Server upgrade doesn't support multiplex yet, wait"); - *waitpipe = TRUE; - CONNCACHE_UNLOCK(data); - return FALSE; /* no reuse */ - } - infof(data, "Server upgrade cannot be used"); - continue; /* can't be used atm */ - } + if(needle->bits.socksproxy && + !socks_proxy_info_matches(&needle->socks_proxy, + &check->socks_proxy)) + continue; - if(!canmultiplex && CONN_INUSE(check)) - /* this request can't be multiplexed but the checked connection is - already in use so we skip it */ + if(needle->bits.httpproxy) { + if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) continue; - if(CONN_INUSE(check)) { - /* Subject for multiplex use if 'checks' belongs to the same multi - handle as 'data' is. */ - struct Curl_llist_element *e = check->easyq.head; - struct Curl_easy *entry = e->ptr; - if(entry->multi != data->multi) - continue; - } + if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) + continue; - if(needle->localdev || needle->localport) { - /* If we are bound to a specific local end (IP+port), we must not - reuse a random other one, although if we didn't ask for a - particular one we can reuse one that was bound. - - This comparison is a bit rough and too strict. Since the input - parameters can be specified in numerous ways and still end up the - same it would take a lot of processing to make it really accurate. - Instead, this matching will assume that reuses of bound connections - will most likely also reuse the exact same binding parameters and - missing out a few edge cases shouldn't hurt anyone very much. - */ - if((check->localport != needle->localport) || - (check->localportrange != needle->localportrange) || - (needle->localdev && - (!check->localdev || strcmp(check->localdev, needle->localdev)))) + if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) { + /* https proxies come in different types, http/1.1, h2, ... */ + if(needle->http_proxy.proxytype != check->http_proxy.proxytype) continue; - } - - if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { - /* This protocol requires credentials per connection, - so verify that we're using the same name and password as well */ - if(Curl_timestrcmp(needle->user, check->user) || - Curl_timestrcmp(needle->passwd, check->passwd) || - Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) || - Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) { - /* one of them was different */ + /* match SSL config to proxy */ + if(!Curl_ssl_conn_config_match(data, check, TRUE)) { + DEBUGF(infof(data, + "Connection #%" CURL_FORMAT_CURL_OFF_T + " has different SSL proxy parameters, can't reuse", + check->connection_id)); continue; } + /* the SSL config to the server, which may apply here is checked + * further below */ } + } +#endif - /* GSS delegation differences do not actually affect every connection - and auth method, but this check takes precaution before efficiency */ - if(needle->gssapi_delegation != check->gssapi_delegation) + if(h2upgrade && !check->httpversion && canmultiplex) { + if(data->set.pipewait) { + infof(data, "Server upgrade doesn't support multiplex yet, wait"); + *waitpipe = TRUE; + CONNCACHE_UNLOCK(data); + return FALSE; /* no reuse */ + } + infof(data, "Server upgrade cannot be used"); + continue; /* can't be used atm */ + } + + if(needle->localdev || needle->localport) { + /* If we are bound to a specific local end (IP+port), we must not + reuse a random other one, although if we didn't ask for a + particular one we can reuse one that was bound. + + This comparison is a bit rough and too strict. Since the input + parameters can be specified in numerous ways and still end up the + same it would take a lot of processing to make it really accurate. + Instead, this matching will assume that reuses of bound connections + will most likely also reuse the exact same binding parameters and + missing out a few edge cases shouldn't hurt anyone very much. + */ + if((check->localport != needle->localport) || + (check->localportrange != needle->localportrange) || + (needle->localdev && + (!check->localdev || strcmp(check->localdev, needle->localdev)))) continue; + } - /* If multiplexing isn't enabled on the h2 connection and h1 is - explicitly requested, handle it: */ - if((needle->handler->protocol & PROTO_FAMILY_HTTP) && - (((check->httpversion >= 20) && - (data->state.httpwant < CURL_HTTP_VERSION_2_0)) - || ((check->httpversion >= 30) && - (data->state.httpwant < CURL_HTTP_VERSION_3)))) + if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { + /* This protocol requires credentials per connection, + so verify that we're using the same name and password as well */ + if(Curl_timestrcmp(needle->user, check->user) || + Curl_timestrcmp(needle->passwd, check->passwd) || + Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) || + Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) { + /* one of them was different */ continue; -#ifdef USE_SSH - else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) { - if(!ssh_config_matches(needle, check)) - continue; } + } + + /* GSS delegation differences do not actually affect every connection + and auth method, but this check takes precaution before efficiency */ + if(needle->gssapi_delegation != check->gssapi_delegation) + continue; + + /* If looking for HTTP and the HTTP version we want is less + * than the HTTP version of the check connection, continue looking */ + if((needle->handler->protocol & PROTO_FAMILY_HTTP) && + (((check->httpversion >= 20) && + (data->state.httpwant < CURL_HTTP_VERSION_2_0)) + || ((check->httpversion >= 30) && + (data->state.httpwant < CURL_HTTP_VERSION_3)))) + continue; +#ifdef USE_SSH + else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) { + if(!ssh_config_matches(needle, check)) + continue; + } #endif #ifndef CURL_DISABLE_FTP - else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) { - /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */ - if(Curl_timestrcmp(needle->proto.ftpc.account, - check->proto.ftpc.account) || - Curl_timestrcmp(needle->proto.ftpc.alternative_to_user, - check->proto.ftpc.alternative_to_user) || - (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) || - (needle->proto.ftpc.ccc != check->proto.ftpc.ccc)) - continue; - } + else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) { + /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */ + if(Curl_timestrcmp(needle->proto.ftpc.account, + check->proto.ftpc.account) || + Curl_timestrcmp(needle->proto.ftpc.alternative_to_user, + check->proto.ftpc.alternative_to_user) || + (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) || + (needle->proto.ftpc.ccc != check->proto.ftpc.ccc)) + continue; + } #endif - if((needle->handler->flags&PROTOPT_SSL) + /* Additional match requirements if talking TLS OR + * not talking to a HTTP proxy OR using a tunnel through a proxy */ + if((needle->handler->flags&PROTOPT_SSL) #ifndef CURL_DISABLE_PROXY - || !needle->bits.httpproxy || needle->bits.tunnel_proxy -#endif - ) { - /* The requested connection does not use an HTTP proxy or it uses SSL - or it is a non-SSL protocol tunneled or it is a non-SSL protocol - which is allowed to be upgraded via TLS */ - - if((strcasecompare(needle->handler->scheme, check->handler->scheme) || - (get_protocol_family(check->handler) == - needle->handler->protocol && check->bits.tls_upgraded)) && - (!needle->bits.conn_to_host || strcasecompare( - needle->conn_to_host.name, check->conn_to_host.name)) && - (!needle->bits.conn_to_port || - needle->conn_to_port == check->conn_to_port) && - strcasecompare(needle->host.name, check->host.name) && - needle->remote_port == check->remote_port) { - /* The schemes match or the protocol family is the same and the - previous connection was TLS upgraded, and the hostname and host - port match */ - if(needle->handler->flags & PROTOPT_SSL) { - /* This is a SSL connection so verify that we're using the same - SSL options as well */ - if(!Curl_ssl_config_matches(&needle->ssl_config, - &check->ssl_config)) { - DEBUGF(infof(data, - "Connection #%" CURL_FORMAT_CURL_OFF_T - " has different SSL parameters, can't reuse", - check->connection_id)); - continue; - } - } - match = TRUE; - } - } - else { - /* The requested connection is using the same HTTP proxy in normal - mode (no tunneling) */ - match = TRUE; + || !needle->bits.httpproxy || needle->bits.tunnel_proxy +#endif + ) { + /* Talking the same protocol scheme or a TLS upgraded protocol in the + * same protocol family? */ + if(!strcasecompare(needle->handler->scheme, check->handler->scheme) && + (get_protocol_family(check->handler) != + needle->handler->protocol || !check->bits.tls_upgraded)) + continue; + + /* If needle has "conn_to_*" set, check must match this */ + if((needle->bits.conn_to_host && !strcasecompare( + needle->conn_to_host.name, check->conn_to_host.name)) || + (needle->bits.conn_to_port && + needle->conn_to_port != check->conn_to_port)) + continue; + + /* hostname and port must match */ + if(!strcasecompare(needle->host.name, check->host.name) || + needle->remote_port != check->remote_port) + continue; + + /* If talking TLS, check needs to use the same SSL options. */ + if((needle->handler->flags & PROTOPT_SSL) && + !Curl_ssl_conn_config_match(data, check, FALSE)) { + DEBUGF(infof(data, + "Connection #%" CURL_FORMAT_CURL_OFF_T + " has different SSL parameters, can't reuse", + check->connection_id)); + continue; } + } - if(match) { #if defined(USE_NTLM) - /* If we are looking for an HTTP+NTLM connection, check if this is - already authenticating with the right credentials. If not, keep - looking so that we can reuse NTLM connections if - possible. (Especially we must not reuse the same connection if - partway through a handshake!) */ - if(wantNTLMhttp) { - if(Curl_timestrcmp(needle->user, check->user) || - Curl_timestrcmp(needle->passwd, check->passwd)) { - - /* we prefer a credential match, but this is at least a connection - that can be reused and "upgraded" to NTLM */ - if(check->http_ntlm_state == NTLMSTATE_NONE) - chosen = check; - continue; - } - } - else if(check->http_ntlm_state != NTLMSTATE_NONE) { - /* Connection is using NTLM auth but we don't want NTLM */ - continue; - } - -#ifndef CURL_DISABLE_PROXY - /* Same for Proxy NTLM authentication */ - if(wantProxyNTLMhttp) { - /* Both check->http_proxy.user and check->http_proxy.passwd can be - * NULL */ - if(!check->http_proxy.user || !check->http_proxy.passwd) - continue; - - if(Curl_timestrcmp(needle->http_proxy.user, - check->http_proxy.user) || - Curl_timestrcmp(needle->http_proxy.passwd, - check->http_proxy.passwd)) - continue; - } - else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { - /* Proxy connection is using NTLM auth but we don't want NTLM */ - continue; - } -#endif - if(wantNTLMhttp || wantProxyNTLMhttp) { - /* Credentials are already checked, we can use this connection */ + /* If we are looking for an HTTP+NTLM connection, check if this is + already authenticating with the right credentials. If not, keep + looking so that we can reuse NTLM connections if + possible. (Especially we must not reuse the same connection if + partway through a handshake!) */ + if(wantNTLMhttp) { + if(Curl_timestrcmp(needle->user, check->user) || + Curl_timestrcmp(needle->passwd, check->passwd)) { + + /* we prefer a credential match, but this is at least a connection + that can be reused and "upgraded" to NTLM */ + if(check->http_ntlm_state == NTLMSTATE_NONE) chosen = check; + continue; + } + } + else if(check->http_ntlm_state != NTLMSTATE_NONE) { + /* Connection is using NTLM auth but we don't want NTLM */ + continue; + } - if((wantNTLMhttp && - (check->http_ntlm_state != NTLMSTATE_NONE)) || - (wantProxyNTLMhttp && - (check->proxy_ntlm_state != NTLMSTATE_NONE))) { - /* We must use this connection, no other */ - *force_reuse = TRUE; - break; - } +#ifndef CURL_DISABLE_PROXY + /* Same for Proxy NTLM authentication */ + if(wantProxyNTLMhttp) { + /* Both check->http_proxy.user and check->http_proxy.passwd can be + * NULL */ + if(!check->http_proxy.user || !check->http_proxy.passwd) + continue; - /* Continue look up for a better connection */ - continue; - } + if(Curl_timestrcmp(needle->http_proxy.user, + check->http_proxy.user) || + Curl_timestrcmp(needle->http_proxy.passwd, + check->http_proxy.passwd)) + continue; + } + else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { + /* Proxy connection is using NTLM auth but we don't want NTLM */ + continue; + } +#endif + if(wantNTLMhttp || wantProxyNTLMhttp) { + /* Credentials are already checked, we may use this connection. + * With NTLM being weird as it is, we MUST use a + * connection where it has already been fully negotiated. + * If it has not, we keep on looking for a better one. */ + chosen = check; + + if((wantNTLMhttp && + (check->http_ntlm_state != NTLMSTATE_NONE)) || + (wantProxyNTLMhttp && + (check->proxy_ntlm_state != NTLMSTATE_NONE))) { + /* We must use this connection, no other */ + *force_reuse = TRUE; + break; + } + /* Continue look up for a better connection */ + continue; + } #endif - if(canmultiplex) { - /* We can multiplex if we want to. Let's continue looking for - the optimal connection to use. */ - - if(!multiplexed) { - /* We have the optimal connection. Let's stop looking. */ - chosen = check; - break; - } -#ifdef USE_NGHTTP2 - /* If multiplexed, make sure we don't go over concurrency limit */ - if(check->bits.multiplex) { - if(multiplexed >= Curl_conn_get_max_concurrent(data, check, - FIRSTSOCKET)) { - infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)", - multiplexed); - continue; - } - else if(multiplexed >= - Curl_multi_max_concurrent_streams(data->multi)) { - infof(data, "client side MAX_CONCURRENT_STREAMS reached" - ", skip (%zu)", - multiplexed); - continue; - } - } -#endif - /* When not multiplexed, we have a match here! */ - chosen = check; - infof(data, "Multiplexed connection found"); - break; - } - else { - /* We have found a connection. Let's stop searching. */ - chosen = check; - break; - } + if(CONN_INUSE(check)) { + DEBUGASSERT(canmultiplex); + DEBUGASSERT(check->bits.multiplex); + /* If multiplexed, make sure we don't go over concurrency limit */ + if(CONN_INUSE(check) >= + Curl_multi_max_concurrent_streams(data->multi)) { + infof(data, "client side MAX_CONCURRENT_STREAMS reached" + ", skip (%zu)", CONN_INUSE(check)); + continue; } + if(CONN_INUSE(check) >= + Curl_conn_get_max_concurrent(data, check, FIRSTSOCKET)) { + infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)", + CONN_INUSE(check)); + continue; + } + /* When not multiplexed, we have a match here! */ + infof(data, "Multiplexed connection found"); + } + else if(extract_if_dead(check, data)) { + /* disconnect it */ + Curl_disconnect(data, check, TRUE); + continue; } - } + + /* We have found a connection. Let's stop searching. */ + chosen = check; + break; + } /* loop over connection bundle */ if(chosen) { /* mark it as used before releasing the lock */ @@ -1560,17 +1390,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) #ifndef CURL_DISABLE_FTP conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; -#endif - conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus; - conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer; - conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost; - conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options; -#ifndef CURL_DISABLE_PROXY - conn->proxy_ssl_config.verifystatus = - data->set.proxy_ssl.primary.verifystatus; - conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer; - conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost; - conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options; #endif conn->ip_version = data->set.ipver; conn->connect_only = data->set.connect_only; @@ -1615,30 +1434,231 @@ error: return NULL; } -/* returns the handler if the given scheme is built-in */ -const struct Curl_handler *Curl_builtin_scheme(const char *scheme, - size_t schemelen) +const struct Curl_handler *Curl_get_scheme_handler(const char *scheme) { - const struct Curl_handler * const *pp; - const struct Curl_handler *p; - /* Scan protocol handler table and match against 'scheme'. The handler may - be changed later when the protocol specific setup function is called. */ - if(schemelen == CURL_ZERO_TERMINATED) - schemelen = strlen(scheme); - for(pp = protocols; (p = *pp) != NULL; pp++) - if(strncasecompare(p->scheme, scheme, schemelen) && !p->scheme[schemelen]) - /* Protocol found in table. */ - return p; - return NULL; /* not found */ + return Curl_getn_scheme_handler(scheme, strlen(scheme)); } +/* returns the handler if the given scheme is built-in */ +const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, + size_t len) +{ + /* table generated by schemetable.c: + 1. gcc schemetable.c && ./a.out + 2. check how small the table gets + 3. tweak the hash algorithm, then rerun from 1 + 4. when the table is good enough + 5. copy the table into this source code + 6. make sure this function uses the same hash function that worked for + schemetable.c + 7. if needed, adjust the #ifdefs in schemetable.c and rerun + */ + static const struct Curl_handler * const protocols[67] = { +#ifndef CURL_DISABLE_FILE + &Curl_handler_file, +#else + NULL, +#endif + NULL, NULL, +#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER) + &Curl_handler_gophers, +#else + NULL, +#endif + NULL, +#ifdef USE_LIBRTMP + &Curl_handler_rtmpe, +#else + NULL, +#endif +#ifndef CURL_DISABLE_SMTP + &Curl_handler_smtp, +#else + NULL, +#endif +#if defined(USE_SSH) + &Curl_handler_sftp, +#else + NULL, +#endif +#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ + (SIZEOF_CURL_OFF_T > 4) + &Curl_handler_smb, +#else + NULL, +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP) + &Curl_handler_smtps, +#else + NULL, +#endif +#ifndef CURL_DISABLE_TELNET + &Curl_handler_telnet, +#else + NULL, +#endif +#ifndef CURL_DISABLE_GOPHER + &Curl_handler_gopher, +#else + NULL, +#endif +#ifndef CURL_DISABLE_TFTP + &Curl_handler_tftp, +#else + NULL, +#endif + NULL, NULL, NULL, +#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) + &Curl_handler_ftps, +#else + NULL, +#endif +#ifndef CURL_DISABLE_HTTP + &Curl_handler_http, +#else + NULL, +#endif +#ifndef CURL_DISABLE_IMAP + &Curl_handler_imap, +#else + NULL, +#endif +#ifdef USE_LIBRTMP + &Curl_handler_rtmps, +#else + NULL, +#endif +#ifdef USE_LIBRTMP + &Curl_handler_rtmpt, +#else + NULL, +#endif + NULL, NULL, NULL, +#if !defined(CURL_DISABLE_LDAP) && \ + !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + &Curl_handler_ldaps, +#else + NULL, +#endif +#if defined(USE_WEBSOCKETS) && \ + defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_wss, +#else + NULL, +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_https, +#else + NULL, +#endif + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +#ifndef CURL_DISABLE_RTSP + &Curl_handler_rtsp, +#else + NULL, +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \ + defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4) + &Curl_handler_smbs, +#else + NULL, +#endif +#if defined(USE_SSH) && !defined(USE_WOLFSSH) + &Curl_handler_scp, +#else + NULL, +#endif + NULL, NULL, NULL, +#ifndef CURL_DISABLE_POP3 + &Curl_handler_pop3, +#else + NULL, +#endif + NULL, NULL, +#ifdef USE_LIBRTMP + &Curl_handler_rtmp, +#else + NULL, +#endif + NULL, NULL, NULL, +#ifdef USE_LIBRTMP + &Curl_handler_rtmpte, +#else + NULL, +#endif + NULL, NULL, NULL, +#ifndef CURL_DISABLE_DICT + &Curl_handler_dict, +#else + NULL, +#endif + NULL, NULL, NULL, +#ifndef CURL_DISABLE_MQTT + &Curl_handler_mqtt, +#else + NULL, +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3) + &Curl_handler_pop3s, +#else + NULL, +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP) + &Curl_handler_imaps, +#else + NULL, +#endif + NULL, +#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_ws, +#else + NULL, +#endif + NULL, +#ifdef USE_LIBRTMP + &Curl_handler_rtmpts, +#else + NULL, +#endif +#ifndef CURL_DISABLE_LDAP + &Curl_handler_ldap, +#else + NULL, +#endif + NULL, NULL, +#ifndef CURL_DISABLE_FTP + &Curl_handler_ftp, +#else + NULL, +#endif + }; + + if(len && (len <= 7)) { + const char *s = scheme; + size_t l = len; + const struct Curl_handler *h; + unsigned int c = 978; + while(l) { + c <<= 5; + c += Curl_raw_tolower(*s); + s++; + l--; + } + + h = protocols[c % 67]; + if(h && strncasecompare(scheme, h->scheme, len) && !h->scheme[len]) + return h; + } + return NULL; +} static CURLcode findprotocol(struct Curl_easy *data, struct connectdata *conn, const char *protostr) { - const struct Curl_handler *p = Curl_builtin_scheme(protostr, - CURL_ZERO_TERMINATED); + const struct Curl_handler *p = Curl_get_scheme_handler(protostr); if(p && /* Protocol found in table. Check if allowed */ (data->set.allowed_protocols & p->protocol)) { @@ -1652,7 +1672,6 @@ static CURLcode findprotocol(struct Curl_easy *data, else { /* Perform setup complement if some. */ conn->handler = conn->given = p; - /* 'port' and 'remote_port' are set in setup_connection_internals() */ return CURLE_OK; } @@ -1705,14 +1724,14 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, conn->scope_id = (unsigned int)scope; #if defined(HAVE_IF_NAMETOINDEX) else { -#elif defined(WIN32) +#elif defined(_WIN32) else if(Curl_if_nametoindex) { #endif -#if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32) +#if defined(HAVE_IF_NAMETOINDEX) || defined(_WIN32) /* Zone identifier is not numeric */ unsigned int scopeidx = 0; -#if defined(WIN32) +#if defined(_WIN32) scopeidx = Curl_if_nametoindex(zoneid); #else scopeidx = if_nametoindex(zoneid); @@ -1727,7 +1746,7 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, else conn->scope_id = scopeidx; } -#endif /* HAVE_IF_NAMETOINDEX || WIN32 */ +#endif /* HAVE_IF_NAMETOINDEX || _WIN32 */ free(zoneid); } @@ -3596,85 +3615,10 @@ static CURLcode create_conn(struct Curl_easy *data, conn->send[SECONDARYSOCKET] = Curl_conn_send; conn->bits.tcp_fastopen = data->set.tcp_fastopen; - /* Get a cloned copy of the SSL config situation stored in the - connection struct. But to get this going nicely, we must first make - sure that the strings in the master copy are pointing to the correct - strings in the session handle strings array! - - Keep in mind that the pointers in the master copy are pointing to strings - that will be freed as part of the Curl_easy struct, but all cloned - copies will be separately allocated. - */ - data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH]; - data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE]; - data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; - data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT]; - data->set.ssl.primary.cipher_list = - data->set.str[STRING_SSL_CIPHER_LIST]; - data->set.ssl.primary.cipher_list13 = - data->set.str[STRING_SSL_CIPHER13_LIST]; - data->set.ssl.primary.pinned_key = - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; - data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT]; - data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO]; - data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES]; - -#ifndef CURL_DISABLE_PROXY - data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; - data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; - data->set.proxy_ssl.primary.cipher_list = - data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; - data->set.proxy_ssl.primary.cipher_list13 = - data->set.str[STRING_SSL_CIPHER13_LIST_PROXY]; - data->set.proxy_ssl.primary.pinned_key = - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]; - data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY]; - data->set.proxy_ssl.primary.ca_info_blob = - data->set.blobs[BLOB_CAINFO_PROXY]; - data->set.proxy_ssl.primary.issuercert = - data->set.str[STRING_SSL_ISSUERCERT_PROXY]; - data->set.proxy_ssl.primary.issuercert_blob = - data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY]; - data->set.proxy_ssl.primary.CRLfile = - data->set.str[STRING_SSL_CRLFILE_PROXY]; - data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; - data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; - data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; - data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY]; - data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; - data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY]; -#endif - data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE]; - data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE]; - data->set.ssl.key = data->set.str[STRING_KEY]; - data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE]; - data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD]; - data->set.ssl.primary.clientcert = data->set.str[STRING_CERT]; -#ifdef USE_TLS_SRP - data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME]; - data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD]; -#ifndef CURL_DISABLE_PROXY - data->set.proxy_ssl.primary.username = - data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; - data->set.proxy_ssl.primary.password = - data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; -#endif -#endif - data->set.ssl.key_blob = data->set.blobs[BLOB_KEY]; - - if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, - &conn->ssl_config)) { - result = CURLE_OUT_OF_MEMORY; - goto out; - } - -#ifndef CURL_DISABLE_PROXY - if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary, - &conn->proxy_ssl_config)) { - result = CURLE_OUT_OF_MEMORY; + /* Complete the easy's SSL configuration for connection cache matching */ + result = Curl_ssl_easy_config_complete(data); + if(result) goto out; - } -#endif prune_dead_connections(data); @@ -3789,7 +3733,41 @@ static CURLcode create_conn(struct Curl_easy *data, * This is a brand new connection, so let's store it in the connection * cache of ours! */ + result = Curl_ssl_conn_config_init(data, conn); + if(result) { + DEBUGF(fprintf(stderr, "Error: init connection ssl config\n")); + goto out; + } + + result = Curl_resolver_init(data, &conn->resolve_async.resolver); + if(result) { + DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); + goto out; + } + Curl_attach_connection(data, conn); + +#ifdef USE_ARES + result = Curl_set_dns_servers(data, data->set.str[STRING_DNS_SERVERS]); + if(result && result != CURLE_NOT_BUILT_IN) + goto out; + + result = Curl_set_dns_interface(data, + data->set.str[STRING_DNS_INTERFACE]); + if(result && result != CURLE_NOT_BUILT_IN) + goto out; + + result = Curl_set_dns_local_ip4(data, + data->set.str[STRING_DNS_LOCAL_IP4]); + if(result && result != CURLE_NOT_BUILT_IN) + goto out; + + result = Curl_set_dns_local_ip6(data, + data->set.str[STRING_DNS_LOCAL_IP6]); + if(result && result != CURLE_NOT_BUILT_IN) + goto out; +#endif /* USE_ARES */ + result = Curl_conncache_add_conn(data); if(result) goto out; @@ -3976,6 +3954,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) k->bytecount = 0; k->ignorebody = FALSE; + Curl_client_cleanup(data); Curl_speedinit(data); Curl_pgrsSetUploadCounter(data, 0); Curl_pgrsSetDownloadCounter(data, 0); diff --git a/libs/libcurl/src/url.h b/libs/libcurl/src/url.h index 8603d3ff02..65b04db079 100644 --- a/libs/libcurl/src/url.h +++ b/libs/libcurl/src/url.h @@ -46,8 +46,13 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len, char **userptr, char **passwdptr, char **optionsptr); -const struct Curl_handler *Curl_builtin_scheme(const char *scheme, - size_t schemelen); +/* Get protocol handler for a URI scheme + * @param scheme URI scheme, case-insensitive + * @return NULL of handler not found + */ +const struct Curl_handler *Curl_get_scheme_handler(const char *scheme); +const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, + size_t len); #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ #define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c index 37dabba3e0..1a94e7f4cf 100644 --- a/libs/libcurl/src/urlapi.c +++ b/libs/libcurl/src/urlapi.c @@ -206,7 +206,7 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen, (void)buflen; /* only used in debug-builds */ if(buf) buf[0] = 0; /* always leave a defined value in buf */ -#ifdef WIN32 +#ifdef _WIN32 if(guess_scheme && STARTS_WITH_DRIVE_PREFIX(url)) return 0; #endif @@ -446,7 +446,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, /* if this is a known scheme, get some details */ if(u->scheme) - h = Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED); + h = Curl_get_scheme_handler(u->scheme); /* We could use the login information in the URL so extract it. Only parse options if the handler says we should. Note that 'h' might be NULL! */ @@ -1056,7 +1056,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) ptr += 9; /* now points to the slash after the host */ } else { -#if defined(WIN32) +#if defined(_WIN32) size_t len; /* the host name, NetBIOS computer name, can not contain disallowed @@ -1095,7 +1095,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) /* no host for file: URLs by default */ Curl_dyn_reset(&host); -#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__) +#if !defined(_WIN32) && !defined(MSDOS) && !defined(__CYGWIN__) /* Don't allow Windows drive letters when not in Windows. * This catches both "file:/c:" and "file:c:" */ if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) || @@ -1129,7 +1129,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) } schemep = schemebuf; - if(!Curl_builtin_scheme(schemep, CURL_ZERO_TERMINATED) && + if(!Curl_get_scheme_handler(schemep) && !(flags & CURLU_NON_SUPPORT_SCHEME)) { result = CURLUE_UNSUPPORTED_SCHEME; goto fail; @@ -1224,14 +1224,14 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) if(flags & CURLU_URLENCODE) { struct dynbuf enc; Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH); - if(urlencode_str(&enc, fragment + 1, fraglen, TRUE, FALSE)) { + if(urlencode_str(&enc, fragment + 1, fraglen - 1, TRUE, FALSE)) { result = CURLUE_OUT_OF_MEMORY; goto fail; } u->fragment = Curl_dyn_ptr(&enc); } else { - u->fragment = Curl_memdup(fragment + 1, fraglen); + u->fragment = Curl_strndup(fragment + 1, fraglen - 1); if(!u->fragment) { result = CURLUE_OUT_OF_MEMORY; goto fail; @@ -1260,12 +1260,11 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) u->query = Curl_dyn_ptr(&enc); } else { - u->query = Curl_memdup(query + 1, qlen); + u->query = Curl_strndup(query + 1, qlen - 1); if(!u->query) { result = CURLUE_OUT_OF_MEMORY; goto fail; } - u->query[qlen - 1] = 0; } } else { @@ -1295,12 +1294,11 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) } else { if(!u->path) { - u->path = Curl_memdup(path, pathlen + 1); + u->path = Curl_strndup(path, pathlen); if(!u->path) { result = CURLUE_OUT_OF_MEMORY; goto fail; } - u->path[pathlen] = 0; path = u->path; } else if(flags & CURLU_URLENCODE) @@ -1352,7 +1350,7 @@ static CURLUcode parseurl_and_replace(const char *url, CURLU *u, */ CURLU *curl_url(void) { - return calloc(sizeof(struct Curl_URL), 1); + return calloc(1, sizeof(struct Curl_URL)); } void curl_url_cleanup(CURLU *u) @@ -1374,7 +1372,7 @@ void curl_url_cleanup(CURLU *u) CURLU *curl_url_dup(const CURLU *in) { - struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1); + struct Curl_URL *u = calloc(1, sizeof(struct Curl_URL)); if(u) { DUP(u, in, scheme); DUP(u, in, user); @@ -1447,8 +1445,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what, if(!ptr && (flags & CURLU_DEFAULT_PORT) && u->scheme) { /* there's no stored port number, but asked to deliver a default one for the scheme */ - const struct Curl_handler *h = - Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED); + const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme); if(h) { msnprintf(portbuf, sizeof(portbuf), "%u", h->defport); ptr = portbuf; @@ -1457,8 +1454,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what, else if(ptr && u->scheme) { /* there is a stored port number, but ask to inhibit if it matches the default one for the scheme */ - const struct Curl_handler *h = - Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED); + const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme); if(h && (h->defport == u->portnum) && (flags & CURLU_NO_DEFAULT_PORT)) ptr = NULL; @@ -1503,7 +1499,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what, else return CURLUE_NO_SCHEME; - h = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED); + h = Curl_get_scheme_handler(scheme); if(!port && (flags & CURLU_DEFAULT_PORT)) { /* there's no stored port number, but asked to deliver a default one for the scheme */ @@ -1596,7 +1592,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what, if(ptr) { size_t partlen = strlen(ptr); size_t i = 0; - *part = Curl_memdup(ptr, partlen + 1); + *part = Curl_strndup(ptr, partlen); if(!*part) return CURLUE_OUT_OF_MEMORY; if(plusdecode) { @@ -1743,9 +1739,8 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, if((plen > MAX_SCHEME_LEN) || (plen < 1)) /* too long or too short */ return CURLUE_BAD_SCHEME; - if(!(flags & CURLU_NON_SUPPORT_SCHEME) && - /* verify that it is a fine scheme */ - !Curl_builtin_scheme(part, CURL_ZERO_TERMINATED)) + /* verify that it is a fine scheme */ + if(!(flags & CURLU_NON_SUPPORT_SCHEME) && !Curl_get_scheme_handler(part)) return CURLUE_UNSUPPORTED_SCHEME; storep = &u->scheme; urlencode = FALSE; /* never */ @@ -1905,7 +1900,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, } newp = Curl_dyn_ptr(&enc); - if(appendquery) { + if(appendquery && newp) { /* Append the 'newp' string onto the old query. Add a '&' separator if none is present at the end of the existing query already */ @@ -1934,8 +1929,8 @@ nomem: } } - if(what == CURLUPART_HOST) { - size_t n = strlen(newp); + else if(what == CURLUPART_HOST) { + size_t n = Curl_dyn_len(&enc); if(!n && (flags & CURLU_NO_AUTHORITY)) { /* Skip hostname check, it's allowed to be empty. */ } diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h index 6710314c55..b5b6bf866b 100644 --- a/libs/libcurl/src/urldata.h +++ b/libs/libcurl/src/urldata.h @@ -266,6 +266,13 @@ typedef enum { /* SSL backend-specific data; declared differently by each SSL backend */ struct ssl_backend_data; +struct ssl_peer { + char *hostname; /* hostname for verification */ + char *dispname; /* display version of hostname */ + char *sni; /* SNI version of hostname or NULL if not usable */ + BIT(is_ip_address); /* if hostname is an IPv4|6 address */ +}; + struct ssl_primary_config { char *CApath; /* certificate dir (doesn't work on windows) */ char *CAfile; /* certificate to verify peer against */ @@ -571,6 +578,13 @@ struct hostname { #define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) #define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) +/* transfer wants to send is not PAUSE or HOLD */ +#define CURL_WANT_SEND(data) \ + (((data)->req.keepon & KEEP_SENDBITS) == KEEP_SEND) +/* transfer receive is not on PAUSE or HOLD */ +#define CURL_WANT_RECV(data) \ + (!((data)->req.keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD))) + #if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH) #define USE_CURL_ASYNC struct Curl_async { @@ -589,6 +603,15 @@ struct Curl_async { #define FIRSTSOCKET 0 #define SECONDARYSOCKET 1 +/* Polling requested by an easy handle. + * `action` is CURL_POLL_IN, CURL_POLL_OUT or CURL_POLL_INOUT. + */ +struct easy_pollset { + curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE]; + unsigned int num; + unsigned char actions[MAX_SOCKSPEREASYHANDLE]; +}; + enum expect100 { EXP100_SEND_DATA, /* enough waiting, just send the body now */ EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */ @@ -649,16 +672,8 @@ struct SingleRequest { counter to make only a 100 reply (without a following second response code) result in a CURLE_GOT_NOTHING error code */ - enum { - HEADER_NORMAL, /* no bad header at all */ - HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest - is normal data */ - HEADER_ALLBAD /* all was believed to be header */ - } badheader; /* the header was deemed bad and will be - written as body */ int headerline; /* counts header lines to better track the first one */ - char *str; /* within buf */ curl_off_t offset; /* possible resume offset read from the Content-Range: header */ int httpcode; /* error code from the 'HTTP/1.? XXX' or @@ -669,7 +684,7 @@ struct SingleRequest { enum upgrade101 upgr101; /* 101 upgrade state */ /* Content unencoding stack. See sec 3.5, RFC2616. */ - struct contenc_writer *writer_stack; + struct Curl_cwriter *writer_stack; time_t timeofdoc; long bodywrites; char *location; /* This points to an allocated version of the Location: @@ -706,16 +721,20 @@ struct SingleRequest { #ifndef CURL_DISABLE_DOH struct dohdata *doh; /* DoH specific data for this request */ #endif -#if defined(WIN32) && defined(USE_WINSOCK) +#if defined(_WIN32) && defined(USE_WINSOCK) struct curltime last_sndbuf_update; /* last time readwrite_upload called win_update_buffer_size */ #endif + char fread_eof[2]; /* the body read callback (index 0) returned EOF or + the trailer read callback (index 1) returned EOF */ #ifndef CURL_DISABLE_COOKIES unsigned char setcookies; #endif unsigned char writer_stack_depth; /* Unencoding stack depth. */ BIT(header); /* incoming data has HTTP header */ + BIT(badheader); /* header parsing found sth not a header */ BIT(content_range); /* set TRUE if Content-Range: was found */ + BIT(download_done); /* set to TRUE when download is complete */ BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding upload and we're uploading the last chunk */ BIT(ignorebody); /* we read a response-body but we ignore it! */ @@ -799,7 +818,8 @@ struct Curl_handler { /* If used, this function gets called from transfer.c:readwrite_data() to allow the protocol to do extra reads/writes */ CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn, - ssize_t *nread, bool *readmore); + const char *buf, size_t blen, + size_t *pconsumed, bool *readmore); /* This function can perform various checks on the connection. See CONNCHECK_* for more information about the checks that can be performed, @@ -901,6 +921,9 @@ struct connectdata { multi_done(). This entry will be NULL if the connection is reused as then there is no name resolve done. */ struct Curl_dns_entry *dns_entry; +#ifdef USE_CURL_ASYNC + struct Curl_async resolve_async; /* asynchronous name resolver data */ +#endif /* 'remote_addr' is the particular IP we connected to. it is owned, set * and NULLed by the connected socket filter (if there is one). */ @@ -1325,7 +1348,8 @@ struct UrlState { curl_off_t recent_conn_id; /* The most recent connection used, might no * longer exist */ struct dynbuf headerb; /* buffer to store headers in */ - + struct curl_slist *hstslist; /* list of HSTS files set by + curl_easy_setopt(HSTS) calls */ char *buffer; /* download buffer */ char *ulbuf; /* allocated upload buffer or NULL */ curl_off_t current_speed; /* the ProgressShow() function sets this, @@ -1358,9 +1382,6 @@ struct UrlState { #endif struct auth authhost; /* auth details for host */ struct auth authproxy; /* auth details for proxy */ -#ifdef USE_CURL_ASYNC - struct Curl_async async; /* asynchronous name resolver data */ -#endif #if defined(USE_OPENSSL) /* void instead of ENGINE to avoid bleeding OpenSSL into this header */ @@ -1373,7 +1394,7 @@ struct UrlState { /* a place to store the most recently set (S)FTP entrypath */ char *most_recent_ftp_entrypath; -#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) +#if !defined(_WIN32) && !defined(MSDOS) && !defined(__EMX__) /* do FTP line-end conversions on most platforms */ #define CURL_DO_LINEEND_CONV /* for FTP downloads: track CRLF sequences that span blocks */ @@ -1411,7 +1432,7 @@ struct UrlState { this should be dealt with in pretransfer */ #ifndef CURL_DISABLE_HTTP curl_mimepart *mimepost; - curl_mimepart *formp; /* storage for old API form-posting, alloced on + curl_mimepart *formp; /* storage for old API form-posting, allocated on demand */ size_t trailers_bytes_sent; struct dynbuf trailers_buf; /* a buffer containing the compiled trailing @@ -1422,6 +1443,10 @@ struct UrlState { trailers_state trailers_state; /* whether we are sending trailers and what stage are we at */ #endif +#ifndef CURL_DISABLE_COOKIES + struct curl_slist *cookielist; /* list of cookie files set by + curl_easy_setopt(COOKIEFILE) calls */ +#endif #ifdef USE_HYPER bool hconnect; /* set if a CONNECT request */ CURLcode hresult; /* used to pass return codes back from hyper callbacks */ @@ -1498,6 +1523,9 @@ struct UrlState { though it will be discarded. We must call the data rewind callback before trying to send again. */ BIT(upload); /* upload request */ + BIT(internal); /* internal: true if this easy handle was created for + internal use and the user does not have ownership of the + handle. */ }; /* @@ -1674,13 +1702,7 @@ struct UserDefined { void *prereq_userp; /* pre-initial request user data */ void *seek_client; /* pointer to pass to the seek callback */ -#ifndef CURL_DISABLE_COOKIES - struct curl_slist *cookielist; /* list of cookie files set by - curl_easy_setopt(COOKIEFILE) calls */ -#endif #ifndef CURL_DISABLE_HSTS - struct curl_slist *hstslist; /* list of HSTS files set by - curl_easy_setopt(HSTS) calls */ curl_hstsread_callback hsts_read; void *hsts_read_userp; curl_hstswrite_callback hsts_write; @@ -1780,9 +1802,6 @@ struct UserDefined { #endif curl_prot_t allowed_protocols; curl_prot_t redir_protocols; -#ifndef CURL_DISABLE_MIME - unsigned int mime_options; /* Mime option flags. */ -#endif #ifndef CURL_DISABLE_RTSP void *rtp_out; /* write RTP to this if non-NULL */ /* Common RTSP header options */ @@ -1805,8 +1824,6 @@ struct UserDefined { int tcp_keepidle; /* seconds in idle before sending keepalive probe */ int tcp_keepintvl; /* seconds between TCP keepalive probes */ - size_t maxconnects; /* Max idle connections in the connection cache */ - long expect_100_timeout; /* in milliseconds */ #if defined(USE_HTTP2) || defined(USE_HTTP3) struct Curl_data_priority priority; @@ -1831,10 +1848,14 @@ struct UserDefined { BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some recipients */ #endif + unsigned int maxconnects; /* Max idle connections in the connection cache */ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or IMAP or POP3 or others! (type: curl_usessl)*/ unsigned char connect_only; /* make connection/request, then let application use the socket */ +#ifndef CURL_DISABLE_MIME + BIT(mime_formescape); +#endif BIT(is_fread_set); /* has read callback been set to non-NULL? */ #ifndef CURL_DISABLE_TFTP BIT(tftp_no_options); /* do not send TFTP options requests */ @@ -1971,10 +1992,7 @@ struct Curl_easy { particular order. Note that all sockets are added to the sockhash, where the state etc are also kept. This array is mostly used to detect when a socket is to be removed from the hash. See singlesocket(). */ - curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE]; - unsigned char actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in - sockets[] */ - int numsocks; + struct easy_pollset last_poll; struct Names dns; struct Curl_multi *multi; /* if non-NULL, points to the multi handle @@ -2013,10 +2031,6 @@ struct Curl_easy { #ifdef USE_HYPER struct hyptransfer hyp; #endif - - /* internal: true if this easy handle was created for internal use and the - user does not have ownership of the handle. */ - bool internal; }; #define LIBCURL_NAME "libcurl" diff --git a/libs/libcurl/src/vauth/digest.c b/libs/libcurl/src/vauth/digest.c index e73302ff6a..166b66e0fb 100644 --- a/libs/libcurl/src/vauth/digest.c +++ b/libs/libcurl/src/vauth/digest.c @@ -125,7 +125,6 @@ bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, } else return FALSE; - break; } } diff --git a/libs/libcurl/src/version.c b/libs/libcurl/src/version.c index 97de3340c4..86c8aff13b 100644 --- a/libs/libcurl/src/version.c +++ b/libs/libcurl/src/version.c @@ -39,7 +39,7 @@ #ifdef USE_ARES # if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ - defined(WIN32) + defined(_WIN32) # define CARES_STATICLIB # endif # include @@ -409,7 +409,8 @@ static int idn_present(curl_version_info_data *info) #define idn_present NULL #endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) +#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \ + !defined(CURL_DISABLE_HTTP) static int https_proxy_present(curl_version_info_data *info) { (void) info; @@ -454,13 +455,14 @@ static const struct feat features_table[] = { #ifndef CURL_DISABLE_HSTS FEATURE("HSTS", NULL, CURL_VERSION_HSTS), #endif -#if defined(USE_NGHTTP2) || defined(USE_HYPER) +#if defined(USE_NGHTTP2) FEATURE("HTTP2", NULL, CURL_VERSION_HTTP2), #endif #if defined(ENABLE_QUIC) FEATURE("HTTP3", NULL, CURL_VERSION_HTTP3), #endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) +#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \ + !defined(CURL_DISABLE_HTTP) FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY), #endif #if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) @@ -510,7 +512,7 @@ static const struct feat features_table[] = { #ifdef CURLDEBUG FEATURE("TrackMemory", NULL, CURL_VERSION_CURLDEBUG), #endif -#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE) +#if defined(_WIN32) && defined(UNICODE) && defined(_UNICODE) FEATURE("Unicode", NULL, CURL_VERSION_UNICODE), #endif #ifdef USE_UNIX_SOCKETS diff --git a/libs/libcurl/src/version_win32.c b/libs/libcurl/src/version_win32.c index 042c1ba13f..8759dcc325 100644 --- a/libs/libcurl/src/version_win32.c +++ b/libs/libcurl/src/version_win32.c @@ -24,7 +24,7 @@ #include "curl_setup.h" -#if defined(WIN32) +#if defined(_WIN32) #include #include "version_win32.h" @@ -316,4 +316,4 @@ bool curlx_verify_windows_version(const unsigned int majorVersion, return matched; } -#endif /* WIN32 */ +#endif /* _WIN32 */ diff --git a/libs/libcurl/src/version_win32.h b/libs/libcurl/src/version_win32.h index 9a8c317fb3..f45270c8f4 100644 --- a/libs/libcurl/src/version_win32.h +++ b/libs/libcurl/src/version_win32.h @@ -26,7 +26,7 @@ #include "curl_setup.h" -#if defined(WIN32) +#if defined(_WIN32) /* Version condition */ typedef enum { @@ -51,6 +51,6 @@ bool curlx_verify_windows_version(const unsigned int majorVersion, const PlatformIdentifier platform, const VersionCondition condition); -#endif /* WIN32 */ +#endif /* _WIN32 */ #endif /* HEADER_CURL_VERSION_WIN32_H */ diff --git a/libs/libcurl/src/vquic/curl_msh3.c b/libs/libcurl/src/vquic/curl_msh3.c index 5d31e234d8..bf8220470c 100644 --- a/libs/libcurl/src/vquic/curl_msh3.c +++ b/libs/libcurl/src/vquic/curl_msh3.c @@ -38,6 +38,7 @@ #include "http1.h" #include "curl_msh3.h" #include "socketpair.h" +#include "vtls/vtls.h" #include "vquic/vquic.h" /* The last 3 #include files should be in this order */ @@ -45,6 +46,10 @@ #include "curl_memory.h" #include "memdebug.h" +#ifdef CURL_DISABLE_SOCKETPAIR +#error "MSH3 cannot be build with CURL_DISABLE_SOCKETPAIR set" +#endif + #define H3_STREAM_WINDOW_SIZE (128 * 1024) #define H3_STREAM_CHUNK_SIZE (16 * 1024) #define H3_STREAM_RECV_CHUNKS \ @@ -672,31 +677,25 @@ out: return nwritten; } -static int cf_msh3_get_select_socks(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t *socks) +static void cf_msh3_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps) { struct cf_msh3_ctx *ctx = cf->ctx; struct stream_ctx *stream = H3_STREAM_CTX(data); - int bitmap = GETSOCK_BLANK; struct cf_call_data save; CF_DATA_SAVE(save, cf, data); if(stream && ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD) { - socks[0] = ctx->sock[SP_LOCAL]; - if(stream->recv_error) { - bitmap |= GETSOCK_READSOCK(0); + Curl_pollset_add_in(data, ps, ctx->sock[SP_LOCAL]); drain_stream(cf, data); } else if(stream->req) { - bitmap |= GETSOCK_READSOCK(0); + Curl_pollset_add_out(data, ps, ctx->sock[SP_LOCAL]); drain_stream(cf, data); } } - CURL_TRC_CF(data, cf, "select_sock -> %d", bitmap); - CF_DATA_RESTORE(cf, save); - return bitmap; } static bool cf_msh3_data_pending(struct Curl_cfilter *cf, @@ -802,14 +801,20 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_msh3_ctx *ctx = cf->ctx; - bool verify = !!cf->conn->ssl_config.verifypeer; + struct ssl_primary_config *conn_config; MSH3_ADDR addr = {0}; CURLcode result; + bool verify; + + conn_config = Curl_ssl_cf_get_primary_config(cf); + if(!conn_config) + return CURLE_FAILED_INIT; + verify = !!conn_config->verifypeer; memcpy(&addr, &ctx->addr.sa_addr, ctx->addr.addrlen); MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port); - if(verify && (cf->conn->ssl_config.CAfile || cf->conn->ssl_config.CApath)) { + if(verify && (conn_config->CAfile || conn_config->CApath)) { /* TODO: need a way to provide trust anchors to MSH3 */ #ifdef DEBUGBUILD /* we need this for our test cases to run */ @@ -1025,7 +1030,7 @@ struct Curl_cftype Curl_cft_http3 = { cf_msh3_connect, cf_msh3_close, Curl_cf_def_get_host, - cf_msh3_get_select_socks, + cf_msh3_adjust_pollset, cf_msh3_data_pending, cf_msh3_send, cf_msh3_recv, @@ -1047,7 +1052,7 @@ CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf, (void)data; (void)conn; (void)ai; /* TODO: msh3 resolves itself? */ - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/libs/libcurl/src/vquic/curl_ngtcp2.c b/libs/libcurl/src/vquic/curl_ngtcp2.c index 1be49f389b..9584065f5a 100644 --- a/libs/libcurl/src/vquic/curl_ngtcp2.c +++ b/libs/libcurl/src/vquic/curl_ngtcp2.c @@ -78,7 +78,6 @@ #define QUIC_MAX_STREAMS (256*1024) #define QUIC_MAX_DATA (1*1024*1024) -#define QUIC_IDLE_TIMEOUT (60*NGTCP2_SECONDS) #define QUIC_HANDSHAKE_TIMEOUT (10*NGTCP2_SECONDS) /* A stream window is the maximum amount we need to buffer for @@ -134,6 +133,7 @@ void Curl_ngtcp2_ver(char *p, size_t len) struct cf_ngtcp2_ctx { struct cf_quic_ctx q; + struct ssl_peer peer; ngtcp2_path connected_path; ngtcp2_conn *qconn; ngtcp2_cid dcid; @@ -161,6 +161,7 @@ struct cf_ngtcp2_ctx { struct curltime reconnect_at; /* time the next attempt should start */ struct bufc_pool stream_bufcp; /* chunk pool for streams */ size_t max_stream_window; /* max flow window for one stream */ + uint64_t max_idle_ms; /* max idle time for QUIC connection */ int qlogfd; BIT(got_first_byte); /* if first byte was received */ #ifdef USE_OPENSSL @@ -191,6 +192,7 @@ struct h3_stream_ctx { bool closed; /* TRUE on stream close */ bool reset; /* TRUE on stream reset */ bool send_closed; /* stream is local closed */ + BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */ }; #define H3_STREAM_CTX(d) ((struct h3_stream_ctx *)(((d) && (d)->req.p.http)? \ @@ -236,11 +238,21 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) { + struct cf_ngtcp2_ctx *ctx = cf->ctx; struct h3_stream_ctx *stream = H3_STREAM_CTX(data); (void)cf; if(stream) { CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id); + if(ctx->h3conn && !stream->closed) { + nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream->id); + nghttp3_conn_close_stream(ctx->h3conn, stream->id, + NGHTTP3_H3_REQUEST_CANCELLED); + nghttp3_conn_set_stream_user_data(ctx->h3conn, stream->id, NULL); + ngtcp2_conn_set_stream_user_data(ctx->qconn, stream->id, NULL); + stream->closed = TRUE; + } + Curl_bufq_free(&stream->sendbuf); Curl_bufq_free(&stream->recvbuf); Curl_h1_req_parse_free(&stream->h1); @@ -249,6 +261,43 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) } } +static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf, + struct Curl_easy *data, + int64_t stream_id) +{ + struct Curl_easy *sdata; + + (void)cf; + if(H3_STREAM_ID(data) == stream_id) { + return data; + } + else { + DEBUGASSERT(data->multi); + for(sdata = data->multi->easyp; sdata; sdata = sdata->next) { + if((sdata->conn == data->conn) && H3_STREAM_ID(sdata) == stream_id) { + return sdata; + } + } + } + return NULL; +} + +static void h3_drain_stream(struct Curl_cfilter *cf, + struct Curl_easy *data) +{ + struct h3_stream_ctx *stream = H3_STREAM_CTX(data); + unsigned char bits; + + (void)cf; + bits = CURL_CSELECT_IN; + if(stream && stream->upload_left && !stream->send_closed) + bits |= CURL_CSELECT_OUT; + if(data->state.dselect_bits != bits) { + data->state.dselect_bits = bits; + Curl_expire(data, 0, EXPIRE_RUN_NOW); + } +} + /* ngtcp2 default congestion controller does not perform pacing. Limit the maximum packet burst to MAX_PKT_BURST packets. */ #define MAX_PKT_BURST 10 @@ -261,10 +310,14 @@ struct pkt_io_ctx { ngtcp2_path_storage ps; }; -static ngtcp2_tstamp timestamp(void) +static void pktx_update_time(struct pkt_io_ctx *pktx, + struct Curl_cfilter *cf) { - struct curltime ct = Curl_now(); - return ct.tv_sec * NGTCP2_SECONDS + ct.tv_usec * NGTCP2_MICROSECONDS; + struct cf_ngtcp2_ctx *ctx = cf->ctx; + + vquic_ctx_update_time(&ctx->q); + pktx->ts = ctx->q.last_op.tv_sec * NGTCP2_SECONDS + + ctx->q.last_op.tv_usec * NGTCP2_MICROSECONDS; } static void pktx_init(struct pkt_io_ctx *pktx, @@ -273,9 +326,9 @@ static void pktx_init(struct pkt_io_ctx *pktx, { pktx->cf = cf; pktx->data = data; - pktx->ts = timestamp(); pktx->pkt_count = 0; ngtcp2_path_storage_zero(&pktx->ps); + pktx_update_time(pktx, cf); } static CURLcode cf_progress_ingress(struct Curl_cfilter *cf, @@ -354,7 +407,7 @@ static void quic_settings(struct cf_ngtcp2_ctx *ctx, t->initial_max_stream_data_uni = ctx->max_stream_window; t->initial_max_streams_bidi = QUIC_MAX_STREAMS; t->initial_max_streams_uni = QUIC_MAX_STREAMS; - t->max_idle_timeout = QUIC_IDLE_TIMEOUT; + t->max_idle_timeout = (ctx->max_idle_ms * NGTCP2_MILLISECONDS); if(ctx->qlogfd != -1) { s->qlog_write = qlog_callback; } @@ -398,14 +451,19 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx, struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_ngtcp2_ctx *ctx = cf->ctx; - struct connectdata *conn = cf->conn; + struct ssl_primary_config *conn_config; CURLcode result = CURLE_FAILED_INIT; - SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method()); + SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method()); if(!ssl_ctx) { result = CURLE_OUT_OF_MEMORY; goto out; } + conn_config = Curl_ssl_cf_get_primary_config(cf); + if(!conn_config) { + result = CURLE_FAILED_INIT; + goto out; + } #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) { @@ -422,8 +480,8 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx, SSL_CTX_set_default_verify_paths(ssl_ctx); { - const char *curves = conn->ssl_config.curves ? - conn->ssl_config.curves : QUIC_GROUPS; + const char *curves = conn_config->curves ? + conn_config->curves : QUIC_GROUPS; if(!SSL_CTX_set1_curves_list(ssl_ctx, curves)) { failf(data, "failed setting curves list for QUIC: '%s'", curves); return CURLE_SSL_CIPHER; @@ -432,8 +490,8 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx, #ifndef OPENSSL_IS_BORINGSSL { - const char *ciphers13 = conn->ssl_config.cipher_list13 ? - conn->ssl_config.cipher_list13 : QUIC_CIPHERS; + const char *ciphers13 = conn_config->cipher_list13 ? + conn_config->cipher_list13 : QUIC_CIPHERS; if(SSL_CTX_set_ciphersuites(ssl_ctx, ciphers13) != 1) { failf(data, "failed setting QUIC cipher suite: %s", ciphers13); return CURLE_SSL_CIPHER; @@ -452,7 +510,7 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx, * 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 * SSL_get_verify_result() below. */ - SSL_CTX_set_verify(ssl_ctx, conn->ssl_config.verifypeer ? + SSL_CTX_set_verify(ssl_ctx, conn_config->verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); /* give application a chance to interfere with SSL set up. */ @@ -491,7 +549,7 @@ static CURLcode quic_set_client_cert(struct Curl_cfilter *cf, SSL_CTX *ssl_ctx = ctx->sslctx; const struct ssl_config_data *ssl_config; - ssl_config = Curl_ssl_get_config(data, FIRSTSOCKET); + ssl_config = Curl_ssl_cf_get_config(cf, data); DEBUGASSERT(ssl_config); if(ssl_config->primary.clientcert || ssl_config->primary.cert_blob @@ -514,7 +572,6 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf, struct cf_ngtcp2_ctx *ctx = cf->ctx; const uint8_t *alpn = NULL; size_t alpnlen = 0; - unsigned char checkip[16]; DEBUGASSERT(!ctx->ssl); ctx->ssl = SSL_new(ctx->sslctx); @@ -529,13 +586,8 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf, SSL_set_alpn_protos(ctx->ssl, alpn, (int)alpnlen); /* set SNI */ - if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip)) -#ifdef ENABLE_IPV6 - && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip)) -#endif - ) { - char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL); - if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) { + if(ctx->peer.sni) { + if(!SSL_set_tlsext_host_name(ctx->ssl, ctx->peer.sni)) { failf(data, "Failed set SNI"); SSL_free(ctx->ssl); ctx->ssl = NULL; @@ -549,20 +601,24 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_ngtcp2_ctx *ctx = cf->ctx; + struct ssl_primary_config *conn_config; CURLcode result; gnutls_datum_t alpn[2]; /* this will need some attention when HTTPS proxy over QUIC get fixed */ - const char * const hostname = cf->conn->host.name; long * const pverifyresult = &data->set.ssl.certverifyresult; int rc; + conn_config = Curl_ssl_cf_get_primary_config(cf); + if(!conn_config) + return CURLE_FAILED_INIT; + DEBUGASSERT(ctx->gtls == NULL); ctx->gtls = calloc(1, sizeof(*(ctx->gtls))); if(!ctx->gtls) return CURLE_OUT_OF_MEMORY; - result = gtls_client_init(data, &cf->conn->ssl_config, &data->set.ssl, - hostname, ctx->gtls, pverifyresult); + result = gtls_client_init(data, conn_config, &data->set.ssl, + &ctx->peer, ctx->gtls, pverifyresult); if(result) return result; @@ -602,10 +658,17 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf, static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx, struct Curl_cfilter *cf, struct Curl_easy *data) { - struct connectdata *conn = cf->conn; CURLcode result = CURLE_FAILED_INIT; - WOLFSSL_CTX *ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + struct ssl_primary_config *conn_config; + WOLFSSL_CTX *ssl_ctx = NULL; + conn_config = Curl_ssl_cf_get_primary_config(cf); + if(!conn_config) { + result = CURLE_FAILED_INIT; + goto out; + } + + ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); if(!ssl_ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -613,13 +676,14 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx, if(ngtcp2_crypto_wolfssl_configure_client_context(ssl_ctx) != 0) { failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed"); + result = CURLE_FAILED_INIT; goto out; } wolfSSL_CTX_set_default_verify_paths(ssl_ctx); - if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn->ssl_config.cipher_list13 ? - conn->ssl_config.cipher_list13 : + if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn_config->cipher_list13 ? + conn_config->cipher_list13 : QUIC_CIPHERS) != 1) { char error_buffer[256]; ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer)); @@ -627,8 +691,8 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx, goto out; } - if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn->ssl_config.curves ? - conn->ssl_config.curves : + if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn_config->curves ? + conn_config->curves : (char *)QUIC_GROUPS) != 1) { failf(data, "wolfSSL failed to set curves"); goto out; @@ -645,9 +709,9 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx, #endif } - if(conn->ssl_config.verifypeer) { - const char * const ssl_cafile = conn->ssl_config.CAfile; - const char * const ssl_capath = conn->ssl_config.CApath; + if(conn_config->verifypeer) { + const char * const ssl_cafile = conn_config->CAfile; + const char * const ssl_capath = conn_config->CApath; wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); if(ssl_cafile || ssl_capath) { @@ -786,6 +850,12 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags, CURL_TRC_CF(data, cf, "[%" PRId64 "] read_stream(len=%zu) -> %zd", stream_id, buflen, nconsumed); if(nconsumed < 0) { + if(!data) { + struct Curl_easy *cdata = CF_DATA_CURRENT(cf); + CURL_TRC_CF(cdata, cf, "[%" PRId64 "] nghttp3 error on stream not " + "used by us, ignored", stream_id); + return 0; + } ngtcp2_ccerr_set_application_error( &ctx->last_error, nghttp3_err_infer_quic_app_error_code((int)nconsumed), NULL, 0); @@ -816,7 +886,7 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; rv = nghttp3_conn_add_ack_offset(ctx->h3conn, stream_id, datalen); - if(rv) { + if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -844,7 +914,7 @@ static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags, app_error_code); CURL_TRC_CF(data, cf, "[%" PRId64 "] quic close(err=%" PRIu64 ") -> %d", stream3_id, app_error_code, rv); - if(rv) { + if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { ngtcp2_ccerr_set_application_error( &ctx->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0); return NGTCP2_ERR_CALLBACK_FAILURE; @@ -868,7 +938,7 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id, rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id); CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv); - if(rv) { + if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -887,7 +957,7 @@ static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id); - if(rv) { + if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -911,16 +981,25 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id, { struct Curl_cfilter *cf = user_data; struct cf_ngtcp2_ctx *ctx = cf->ctx; + struct Curl_easy *data = CF_DATA_CURRENT(cf); + struct Curl_easy *s_data; + struct h3_stream_ctx *stream; int rv; (void)tconn; (void)max_data; (void)stream_user_data; rv = nghttp3_conn_unblock_stream(ctx->h3conn, stream_id); - if(rv) { + if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { return NGTCP2_ERR_CALLBACK_FAILURE; } - + s_data = get_stream_easy(cf, data, stream_id); + stream = H3_STREAM_CTX(s_data); + if(stream && stream->quic_flow_blocked) { + CURL_TRC_CF(data, cf, "[%" PRId64 "] unblock quic flow", stream_id); + stream->quic_flow_blocked = FALSE; + h3_drain_stream(cf, data); + } return 0; } @@ -1038,7 +1117,7 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf, pktx = &local_pktx; } else { - pktx->ts = timestamp(); + pktx_update_time(pktx, cf); } expiry = ngtcp2_conn_get_expiry(ctx->qconn); @@ -1073,46 +1152,29 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf, return CURLE_OK; } -static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf, +static void cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) + struct easy_pollset *ps) { struct cf_ngtcp2_ctx *ctx = cf->ctx; - struct SingleRequest *k = &data->req; - int rv = GETSOCK_BLANK; - struct h3_stream_ctx *stream = H3_STREAM_CTX(data); - struct cf_call_data save; - - CF_DATA_SAVE(save, cf, data); - socks[0] = ctx->q.sockfd; + bool want_recv = CURL_WANT_RECV(data); + bool want_send = CURL_WANT_SEND(data); - /* in HTTP/3 we can always get a frame, so check read */ - rv |= GETSOCK_READSOCK(0); - - /* we're still uploading or the HTTP/2 layer wants to send data */ - if((k->keepon & KEEP_SENDBITS) == KEEP_SEND && - ngtcp2_conn_get_cwnd_left(ctx->qconn) && - ngtcp2_conn_get_max_data_left(ctx->qconn) && - stream && nghttp3_conn_is_stream_writable(ctx->h3conn, stream->id)) - rv |= GETSOCK_WRITESOCK(0); - - CF_DATA_RESTORE(cf, save); - return rv; -} - -static void h3_drain_stream(struct Curl_cfilter *cf, - struct Curl_easy *data) -{ - struct h3_stream_ctx *stream = H3_STREAM_CTX(data); - unsigned char bits; + if(ctx->qconn && (want_recv || want_send)) { + struct h3_stream_ctx *stream = H3_STREAM_CTX(data); + struct cf_call_data save; + bool c_exhaust, s_exhaust; - (void)cf; - bits = CURL_CSELECT_IN; - if(stream && stream->upload_left && !stream->send_closed) - bits |= CURL_CSELECT_OUT; - if(data->state.dselect_bits != bits) { - data->state.dselect_bits = bits; - Curl_expire(data, 0, EXPIRE_RUN_NOW); + CF_DATA_SAVE(save, cf, data); + c_exhaust = !ngtcp2_conn_get_cwnd_left(ctx->qconn) || + !ngtcp2_conn_get_max_data_left(ctx->qconn); + s_exhaust = stream && stream->id >= 0 && stream->quic_flow_blocked; + want_recv = (want_recv || c_exhaust || s_exhaust); + want_send = (!s_exhaust && want_send) || + !Curl_bufq_is_empty(&ctx->q.sendbuf); + + Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send); + CF_DATA_RESTORE(cf, save); } } @@ -1141,7 +1203,6 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id, else { CURL_TRC_CF(data, cf, "[%" PRId64 "] CLOSED", stream->id); } - data->req.keepon &= ~KEEP_SEND_HOLD; h3_drain_stream(cf, data); return 0; } @@ -1570,15 +1631,9 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id, /* Everything ACKed, we resume upload processing */ if(!stream->sendbuf_len_in_flight) { int rv = nghttp3_conn_resume_stream(conn, stream_id); - if(rv) { + if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { return NGTCP2_ERR_CALLBACK_FAILURE; } - if((data->req.keepon & KEEP_SEND_HOLD) && - (data->req.keepon & KEEP_SEND)) { - data->req.keepon &= ~KEEP_SEND_HOLD; - h3_drain_stream(cf, data); - CURL_TRC_CF(data, cf, "[%" PRId64 "] unpausing acks", stream_id); - } } return 0; } @@ -1676,6 +1731,10 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf, goto out; stream = H3_STREAM_CTX(data); DEBUGASSERT(stream); + if(!stream) { + *err = CURLE_FAILED_INIT; + goto out; + } nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err); if(nwritten < 0) @@ -1711,7 +1770,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf, nva[i].flags = NGHTTP3_NV_FLAG_NONE; } - rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, NULL); + rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, data); if(rc) { failf(data, "can get bidi streams"); *err = CURLE_SEND_ERROR; @@ -1860,15 +1919,13 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, if(stream && sent > 0 && stream->sendbuf_len_in_flight) { /* We have unacknowledged DATA and cannot report success to our * caller. Instead we EAGAIN and remember how much we have already - * "written" into our various internal connection buffers. - * We put the stream upload on HOLD, until this gets ACKed. */ + * "written" into our various internal connection buffers. */ stream->upload_blocked_len = sent; CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu), " "%zu bytes in flight -> EGAIN", stream->id, len, stream->sendbuf_len_in_flight); *err = CURLE_AGAIN; sent = -1; - data->req.keepon |= KEEP_SEND_HOLD; } out: @@ -1887,40 +1944,37 @@ static CURLcode qng_verify_peer(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_ngtcp2_ctx *ctx = cf->ctx; + struct ssl_primary_config *conn_config; CURLcode result = CURLE_OK; - const char *hostname, *disp_hostname; - int port; - char *snihost; - Curl_conn_get_host(data, cf->sockindex, &hostname, &disp_hostname, &port); - snihost = Curl_ssl_snihost(data, hostname, NULL); - if(!snihost) - return CURLE_PEER_FAILED_VERIFICATION; + conn_config = Curl_ssl_cf_get_primary_config(cf); + if(!conn_config) + return CURLE_FAILED_INIT; cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ cf->conn->httpversion = 30; cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX; - if(cf->conn->ssl_config.verifyhost) { + if(conn_config->verifyhost) { #ifdef USE_OPENSSL X509 *server_cert; - server_cert = SSL_get_peer_certificate(ctx->ssl); + server_cert = SSL_get1_peer_certificate(ctx->ssl); if(!server_cert) { return CURLE_PEER_FAILED_VERIFICATION; } - result = Curl_ossl_verifyhost(data, cf->conn, server_cert); + result = Curl_ossl_verifyhost(data, cf->conn, &ctx->peer, server_cert); X509_free(server_cert); if(result) return result; #elif defined(USE_GNUTLS) result = Curl_gtls_verifyserver(data, ctx->gtls->session, - &cf->conn->ssl_config, &data->set.ssl, - hostname, disp_hostname, + conn_config, &data->set.ssl, &ctx->peer, data->set.str[STRING_SSL_PINNEDPUBLICKEY]); if(result) return result; #elif defined(USE_WOLFSSL) - if(wolfSSL_check_domain_name(ctx->ssl, snihost) == SSL_FAILURE) + if(!ctx->peer.sni || + wolfSSL_check_domain_name(ctx->ssl, ctx->peer.sni) == SSL_FAILURE) return CURLE_PEER_FAILED_VERIFICATION; #endif infof(data, "Verified certificate just fine"); @@ -1955,8 +2009,8 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen, rv = ngtcp2_conn_read_pkt(ctx->qconn, &path, &pi, pkt, pktlen, pktx->ts); if(rv) { - CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s", - ngtcp2_strerror(rv)); + CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s (%d)", + ngtcp2_strerror(rv), rv); if(!ctx->last_error.error_code) { if(rv == NGTCP2_ERR_CRYPTO) { ngtcp2_ccerr_set_tls_alert(&ctx->last_error, @@ -1993,7 +2047,7 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf, pktx = &local_pktx; } else { - pktx->ts = timestamp(); + pktx_update_time(pktx, cf); } #ifdef USE_OPENSSL @@ -2081,11 +2135,18 @@ static ssize_t read_pkt_to_send(void *userp, } else if(n < 0) { switch(n) { - case NGTCP2_ERR_STREAM_DATA_BLOCKED: + case NGTCP2_ERR_STREAM_DATA_BLOCKED: { + struct h3_stream_ctx *stream = H3_STREAM_CTX(x->data); DEBUGASSERT(ndatalen == -1); nghttp3_conn_block_stream(ctx->h3conn, stream_id); + CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] block quic flow", + stream_id); + DEBUGASSERT(stream); + if(stream) + stream->quic_flow_blocked = TRUE; n = 0; break; + } case NGTCP2_ERR_STREAM_SHUT_WR: DEBUGASSERT(ndatalen == -1); nghttp3_conn_shutdown_stream_write(ctx->h3conn, stream_id); @@ -2145,7 +2206,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf, pktx = &local_pktx; } else { - pktx->ts = timestamp(); + pktx_update_time(pktx, cf); ngtcp2_path_storage_zero(&pktx->ps); } @@ -2282,10 +2343,12 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf, case CF_CTRL_DATA_PAUSE: result = h3_data_pause(cf, data, (arg1 != 0)); break; - case CF_CTRL_DATA_DONE: { + case CF_CTRL_DATA_DETACH: + h3_data_done(cf, data); + break; + case CF_CTRL_DATA_DONE: h3_data_done(cf, data); break; - } case CF_CTRL_DATA_DONE_SEND: { struct h3_stream_ctx *stream = H3_STREAM_CTX(data); if(stream && !stream->send_closed) { @@ -2344,6 +2407,7 @@ static void cf_ngtcp2_ctx_clear(struct cf_ngtcp2_ctx *ctx) if(ctx->qconn) ngtcp2_conn_del(ctx->qconn); Curl_bufcp_free(&ctx->stream_bufcp); + Curl_ssl_peer_cleanup(&ctx->peer); memset(ctx, 0, sizeof(*ctx)); ctx->qlogfd = -1; @@ -2358,15 +2422,15 @@ static void cf_ngtcp2_close(struct Curl_cfilter *cf, struct Curl_easy *data) CF_DATA_SAVE(save, cf, data); if(ctx && ctx->qconn) { char buffer[NGTCP2_MAX_UDP_PAYLOAD_SIZE]; - ngtcp2_tstamp ts; + struct pkt_io_ctx pktx; ngtcp2_ssize rc; CURL_TRC_CF(data, cf, "close"); - ts = timestamp(); + pktx_init(&pktx, cf, data); rc = ngtcp2_conn_write_connection_close(ctx->qconn, NULL, /* path */ NULL, /* pkt_info */ (uint8_t *)buffer, sizeof(buffer), - &ctx->last_error, ts); + &ctx->last_error, pktx.ts); if(rc > 0) { while((send(ctx->q.sockfd, buffer, (SEND_TYPE_ARG3)rc, 0) == -1) && SOCKERRNO == EINTR); @@ -2411,9 +2475,14 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, ctx->version = NGTCP2_PROTO_VER_MAX; ctx->max_stream_window = H3_STREAM_WINDOW_SIZE; + ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS; Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE, H3_STREAM_POOL_SPARES); + result = Curl_ssl_peer_init(&ctx->peer, cf); + if(result) + return result; + #ifdef USE_OPENSSL result = quic_ssl_ctx(&ctx->sslctx, cf, data); if(result) @@ -2559,27 +2628,9 @@ out: ngtcp2_conn_in_draining_period(ctx->qconn)) { /* When a QUIC server instance is shutting down, it may send us a * CONNECTION_CLOSE right away. Our connection then enters the DRAINING - * state. - * This may be a stopping of the service or it may be that the server - * is reloading and a new instance will start serving soon. - * In any case, we tear down our socket and start over with a new one. - * We re-open the underlying UDP cf right now, but do not start - * connecting until called again. - */ - int reconn_delay_ms = 200; - - CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms", - reconn_delay_ms); - Curl_conn_cf_close(cf->next, data); - cf_ngtcp2_ctx_clear(ctx); - result = Curl_conn_cf_connect(cf->next, data, FALSE, done); - if(!result && *done) { - *done = FALSE; - ctx->reconnect_at = now; - ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000; - Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC); - result = CURLE_OK; - } + * state. The CONNECT may work in the near future again. Indicate + * that as a "weird" reply. */ + result = CURLE_WEIRD_SERVER_REPLY; } #ifndef CURL_DISABLE_VERBOSE_STRINGS @@ -2657,24 +2708,51 @@ static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data, bool *input_pending) { - bool alive = TRUE; + struct cf_ngtcp2_ctx *ctx = cf->ctx; + bool alive = FALSE; + const ngtcp2_transport_params *rp; + struct cf_call_data save; + CF_DATA_SAVE(save, cf, data); *input_pending = FALSE; + if(!ctx->qconn) + goto out; + + /* Both sides of the QUIC connection announce they max idle times in + * the transport parameters. Look at the minimum of both and if + * we exceed this, regard the connection as dead. The other side + * may have completely purged it and will no longer respond + * to any packets from us. */ + rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn); + if(rp) { + timediff_t idletime; + uint64_t idle_ms = ctx->max_idle_ms; + + if(rp->max_idle_timeout && + (rp->max_idle_timeout / NGTCP2_MILLISECONDS) < idle_ms) + idle_ms = (rp->max_idle_timeout / NGTCP2_MILLISECONDS); + idletime = Curl_timediff(Curl_now(), ctx->q.last_io); + if(idletime > 0 && (uint64_t)idletime > idle_ms) + goto out; + } + if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending)) - return FALSE; + goto out; + alive = TRUE; if(*input_pending) { + CURLcode result; /* This happens before we've sent off a request and the connection is not in use by any other transfer, there shouldn't be any data here, only "protocol frames" */ *input_pending = FALSE; - if(cf_progress_ingress(cf, data, NULL)) - alive = FALSE; - else { - alive = TRUE; - } + result = cf_progress_ingress(cf, data, NULL); + CURL_TRC_CF(data, cf, "is_alive, progress ingress -> %d", result); + alive = result? FALSE : TRUE; } +out: + CF_DATA_RESTORE(cf, save); return alive; } @@ -2686,7 +2764,7 @@ struct Curl_cftype Curl_cft_http3 = { cf_ngtcp2_connect, cf_ngtcp2_close, Curl_cf_def_get_host, - cf_ngtcp2_get_select_socks, + cf_ngtcp2_adjust_pollset, cf_ngtcp2_data_pending, cf_ngtcp2_send, cf_ngtcp2_recv, @@ -2706,7 +2784,7 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf, CURLcode result; (void)data; - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/libs/libcurl/src/vquic/curl_quiche.c b/libs/libcurl/src/vquic/curl_quiche.c index d15b3983e9..9cf0617f11 100644 --- a/libs/libcurl/src/vquic/curl_quiche.c +++ b/libs/libcurl/src/vquic/curl_quiche.c @@ -55,10 +55,10 @@ #include "curl_memory.h" #include "memdebug.h" -/* #define DEBUG_QUICHE */ +/* HTTP/3 error values defined in RFC 9114, ch. 8.1 */ +#define CURL_H3_NO_ERROR (0x0100) #define QUIC_MAX_STREAMS (100) -#define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */ #define H3_STREAM_WINDOW_SIZE (128 * 1024) #define H3_STREAM_CHUNK_SIZE (16 * 1024) @@ -92,6 +92,7 @@ static void keylog_callback(const SSL *ssl, const char *line) struct cf_quiche_ctx { struct cf_quic_ctx q; + struct ssl_peer peer; quiche_conn *qconn; quiche_config *cfg; quiche_h3_conn *h3c; @@ -105,7 +106,7 @@ struct cf_quiche_ctx { struct curltime reconnect_at; /* time the next attempt should start */ struct bufc_pool stream_bufcp; /* chunk pool for streams */ curl_off_t data_recvd; - size_t sends_on_hold; /* # of streams with SEND_HOLD set */ + uint64_t max_idle_ms; /* max idle time for QUIC conn */ BIT(goaway); /* got GOAWAY from server */ BIT(got_first_byte); /* if first byte was received */ BIT(x509_store_setup); /* if x509 store has been set up */ @@ -132,6 +133,8 @@ static void cf_quiche_ctx_clear(struct cf_quiche_ctx *ctx) if(ctx->cfg) quiche_config_free(ctx->cfg); Curl_bufcp_free(&ctx->stream_bufcp); + Curl_ssl_peer_cleanup(&ctx->peer); + memset(ctx, 0, sizeof(*ctx)); } } @@ -140,11 +143,16 @@ static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_quiche_ctx *ctx = cf->ctx; + struct ssl_primary_config *conn_config; + + conn_config = Curl_ssl_cf_get_primary_config(cf); + if(!conn_config) + return CURLE_FAILED_INIT; if(!ctx->x509_store_setup) { - if(cf->conn->ssl_config.verifypeer) { - const char * const ssl_cafile = cf->conn->ssl_config.CAfile; - const char * const ssl_capath = cf->conn->ssl_config.CApath; + if(conn_config->verifypeer) { + const char * const ssl_cafile = conn_config->CAfile; + const char * const ssl_capath = conn_config->CApath; if(ssl_cafile || ssl_capath) { SSL_CTX_set_verify(ctx->sslctx, SSL_VERIFY_PEER, NULL); /* tell OpenSSL where to find CA certificates that are used to verify @@ -177,9 +185,16 @@ static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf, static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_quiche_ctx *ctx = cf->ctx; - unsigned char checkip[16]; - struct connectdata *conn = data->conn; - const char *curves = conn->ssl_config.curves; + struct ssl_primary_config *conn_config; + CURLcode result; + + conn_config = Curl_ssl_cf_get_primary_config(cf); + if(!conn_config) + return CURLE_FAILED_INIT; + + result = Curl_ssl_peer_init(&ctx->peer, cf); + if(result) + return result; DEBUGASSERT(!ctx->sslctx); ctx->sslctx = SSL_CTX_new(TLS_method()); @@ -198,8 +213,10 @@ static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data) SSL_CTX_set_keylog_callback(ctx->sslctx, keylog_callback); } - if(curves && !SSL_CTX_set1_curves_list(ctx->sslctx, curves)) { - failf(data, "failed setting curves list for QUIC: '%s'", curves); + if(conn_config->curves && + !SSL_CTX_set1_curves_list(ctx->sslctx, conn_config->curves)) { + failf(data, "failed setting curves list for QUIC: '%s'", + conn_config->curves); return CURLE_SSL_CIPHER; } @@ -209,13 +226,8 @@ static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data) SSL_set_app_data(ctx->ssl, cf); - if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip)) -#ifdef ENABLE_IPV6 - && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip)) -#endif - ) { - char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL); - if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) { + if(ctx->peer.sni) { + if(!SSL_set_tlsext_host_name(ctx->ssl, ctx->peer.sni)) { failf(data, "Failed set SNI"); SSL_free(ctx->ssl); ctx->ssl = NULL; @@ -240,6 +252,7 @@ struct stream_ctx { bool send_closed; /* stream is locally closed */ bool resp_hds_complete; /* complete, final response has been received */ bool resp_got_header; /* TRUE when h3 stream has recvd some HEADER */ + BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */ }; #define H3_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \ @@ -249,56 +262,20 @@ struct stream_ctx { #define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \ H3_STREAM_CTX(d)->id : -2) -static bool stream_send_is_suspended(struct Curl_easy *data) -{ - return (data->req.keepon & KEEP_SEND_HOLD); -} - -static void stream_send_suspend(struct Curl_cfilter *cf, - struct Curl_easy *data) -{ - struct cf_quiche_ctx *ctx = cf->ctx; - - if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) { - data->req.keepon |= KEEP_SEND_HOLD; - ++ctx->sends_on_hold; - if(H3_STREAM_ID(data) >= 0) - CURL_TRC_CF(data, cf, "[%"PRId64"] suspend sending", - H3_STREAM_ID(data)); - else - CURL_TRC_CF(data, cf, "[%s] suspend sending", data->state.url); - } -} - -static void stream_send_resume(struct Curl_cfilter *cf, - struct Curl_easy *data) -{ - struct cf_quiche_ctx *ctx = cf->ctx; - - if(stream_send_is_suspended(data)) { - data->req.keepon &= ~KEEP_SEND_HOLD; - --ctx->sends_on_hold; - if(H3_STREAM_ID(data) >= 0) - CURL_TRC_CF(data, cf, "[%"PRId64"] resume sending", - H3_STREAM_ID(data)); - else - CURL_TRC_CF(data, cf, "[%s] resume sending", data->state.url); - Curl_expire(data, 0, EXPIRE_RUN_NOW); - } -} - static void check_resumes(struct Curl_cfilter *cf, struct Curl_easy *data) { - struct cf_quiche_ctx *ctx = cf->ctx; struct Curl_easy *sdata; - - if(ctx->sends_on_hold) { - DEBUGASSERT(data->multi); - for(sdata = data->multi->easyp; - sdata && ctx->sends_on_hold; sdata = sdata->next) { - if(stream_send_is_suspended(sdata)) { - stream_send_resume(cf, sdata); + struct stream_ctx *stream; + + DEBUGASSERT(data->multi); + for(sdata = data->multi->easyp; sdata; sdata = sdata->next) { + if(sdata->conn == data->conn) { + stream = H3_STREAM_CTX(sdata); + if(stream && stream->quic_flow_blocked) { + stream->quic_flow_blocked = FALSE; + Curl_expire(data, 0, EXPIRE_RUN_NOW); + CURL_TRC_CF(data, cf, "[%"PRId64"] unblock", stream->id); } } } @@ -333,9 +310,15 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) (void)cf; if(stream) { CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id); - if(stream_send_is_suspended(data)) { - data->req.keepon &= ~KEEP_SEND_HOLD; - --ctx->sends_on_hold; + if(ctx->qconn && !stream->closed) { + quiche_conn_stream_shutdown(ctx->qconn, stream->id, + QUICHE_SHUTDOWN_READ, CURL_H3_NO_ERROR); + if(!stream->send_closed) { + quiche_conn_stream_shutdown(ctx->qconn, stream->id, + QUICHE_SHUTDOWN_WRITE, CURL_H3_NO_ERROR); + stream->send_closed = TRUE; + } + stream->closed = TRUE; } Curl_bufq_free(&stream->recvbuf); Curl_h1_req_parse_free(&stream->h1); @@ -590,7 +573,6 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf, } stream->closed = TRUE; streamclose(cf->conn, "End of stream"); - data->req.keepon &= ~KEEP_SEND_HOLD; break; case QUICHE_H3_EVENT_GOAWAY: @@ -883,6 +865,8 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data, ssize_t nread = -1; CURLcode result; + vquic_ctx_update_time(&ctx->q); + if(!stream) { *err = CURLE_RECV_ERROR; return -1; @@ -1035,9 +1019,8 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf, if(QUICHE_H3_ERR_STREAM_BLOCKED == stream3_id) { /* quiche seems to report this error if the connection window is * exhausted. Which happens frequently and intermittent. */ - CURL_TRC_CF(data, cf, "send_request(%s) rejected with BLOCKED", - data->state.url); - stream_send_suspend(cf, data); + CURL_TRC_CF(data, cf, "[%"PRId64"] blocked", stream->id); + stream->quic_flow_blocked = TRUE; *err = CURLE_AGAIN; nwritten = -1; goto out; @@ -1081,6 +1064,8 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, CURLcode result; ssize_t nwritten; + vquic_ctx_update_time(&ctx->q); + *err = cf_process_ingress(cf, data); if(*err) { nwritten = -1; @@ -1104,7 +1089,7 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) { CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) " "-> window exhausted", stream->id, len); - stream_send_suspend(cf, data); + stream->quic_flow_blocked = TRUE; } *err = CURLE_AGAIN; nwritten = -1; @@ -1173,30 +1158,32 @@ static bool stream_is_writeable(struct Curl_cfilter *cf, struct cf_quiche_ctx *ctx = cf->ctx; struct stream_ctx *stream = H3_STREAM_CTX(data); - return stream && - quiche_conn_stream_writable(ctx->qconn, (uint64_t)stream->id, 1); + return stream && (quiche_conn_stream_writable(ctx->qconn, + (uint64_t)stream->id, 1) > 0); } -static int cf_quiche_get_select_socks(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t *socks) +static void cf_quiche_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps) { struct cf_quiche_ctx *ctx = cf->ctx; - struct SingleRequest *k = &data->req; - int rv = GETSOCK_BLANK; - - socks[0] = ctx->q.sockfd; + bool want_recv = CURL_WANT_RECV(data); + bool want_send = CURL_WANT_SEND(data); - /* in an HTTP/3 connection we can basically always get a frame so we should - always be ready for one */ - rv |= GETSOCK_READSOCK(0); + if(ctx->qconn && (want_recv || want_send)) { + struct stream_ctx *stream = H3_STREAM_CTX(data); + bool c_exhaust, s_exhaust; - /* we're still uploading or the HTTP/3 layer wants to send data */ - if(((k->keepon & KEEP_SENDBITS) == KEEP_SEND) - && stream_is_writeable(cf, data)) - rv |= GETSOCK_WRITESOCK(0); + c_exhaust = FALSE; /* Have not found any call in quiche that tells + us if the connection itself is blocked */ + s_exhaust = stream && stream->id >= 0 && + (stream->quic_flow_blocked || !stream_is_writeable(cf, data)); + want_recv = (want_recv || c_exhaust || s_exhaust); + want_send = (!s_exhaust && want_send) || + !Curl_bufq_is_empty(&ctx->q.sendbuf); - return rv; + Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send); + } } /* @@ -1238,10 +1225,12 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf, case CF_CTRL_DATA_PAUSE: result = h3_data_pause(cf, data, (arg1 != 0)); break; - case CF_CTRL_DATA_DONE: { + case CF_CTRL_DATA_DETACH: + h3_data_done(cf, data); + break; + case CF_CTRL_DATA_DONE: h3_data_done(cf, data); break; - } case CF_CTRL_DATA_DONE_SEND: { struct stream_ctx *stream = H3_STREAM_CTX(data); if(stream && !stream->send_closed) { @@ -1276,20 +1265,25 @@ static CURLcode cf_verify_peer(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_quiche_ctx *ctx = cf->ctx; + struct ssl_primary_config *conn_config; CURLcode result = CURLE_OK; + conn_config = Curl_ssl_cf_get_primary_config(cf); + if(!conn_config) + return CURLE_FAILED_INIT; + cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ cf->conn->httpversion = 30; cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX; - if(cf->conn->ssl_config.verifyhost) { + if(conn_config->verifyhost) { X509 *server_cert; server_cert = SSL_get_peer_certificate(ctx->ssl); if(!server_cert) { result = CURLE_PEER_FAILED_VERIFICATION; goto out; } - result = Curl_ossl_verifyhost(data, cf->conn, server_cert); + result = Curl_ossl_verifyhost(data, cf->conn, &ctx->peer, server_cert); X509_free(server_cert); if(result) goto out; @@ -1345,6 +1339,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, debug_log_init = 1; } #endif + ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS; Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE, H3_STREAM_POOL_SPARES); ctx->data_recvd = 0; @@ -1359,7 +1354,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, return CURLE_FAILED_INIT; } quiche_config_enable_pacing(ctx->cfg, false); - quiche_config_set_max_idle_timeout(ctx->cfg, QUIC_IDLE_TIMEOUT); + quiche_config_set_max_idle_timeout(ctx->cfg, ctx->max_idle_ms * 1000); quiche_config_set_initial_max_data(ctx->cfg, (1 * 1024 * 1024) /* (QUIC_MAX_STREAMS/2) * H3_STREAM_WINDOW_SIZE */); quiche_config_set_initial_max_streams_bidi(ctx->cfg, QUIC_MAX_STREAMS); @@ -1411,7 +1406,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, } /* Known to not work on Windows */ -#if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD) +#if !defined(_WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD) { int qfd; (void)Curl_qlogdir(data, ctx->scid, sizeof(ctx->scid), &qfd); @@ -1449,7 +1444,6 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, { struct cf_quiche_ctx *ctx = cf->ctx; CURLcode result = CURLE_OK; - struct curltime now; if(cf->connected) { *done = TRUE; @@ -1464,9 +1458,10 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, } *done = FALSE; - now = Curl_now(); + vquic_ctx_update_time(&ctx->q); - if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) { + if(ctx->reconnect_at.tv_sec && + Curl_timediff(ctx->q.last_op, ctx->reconnect_at) < 0) { /* Not time yet to attempt the next connect */ CURL_TRC_CF(data, cf, "waiting for reconnect time"); goto out; @@ -1476,7 +1471,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, result = cf_connect_start(cf, data); if(result) goto out; - ctx->started_at = now; + ctx->started_at = ctx->q.last_op; result = cf_flush_egress(cf, data); /* we do not expect to be able to recv anything yet */ goto out; @@ -1491,9 +1486,9 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, goto out; if(quiche_conn_is_established(ctx->qconn)) { + ctx->handshake_at = ctx->q.last_op; CURL_TRC_CF(data, cf, "handshake complete after %dms", - (int)Curl_timediff(now, ctx->started_at)); - ctx->handshake_at = now; + (int)Curl_timediff(ctx->handshake_at, ctx->started_at)); result = cf_verify_peer(cf, data); if(!result) { CURL_TRC_CF(data, cf, "peer verified"); @@ -1506,27 +1501,9 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, else if(quiche_conn_is_draining(ctx->qconn)) { /* When a QUIC server instance is shutting down, it may send us a * CONNECTION_CLOSE right away. Our connection then enters the DRAINING - * state. - * This may be a stopping of the service or it may be that the server - * is reloading and a new instance will start serving soon. - * In any case, we tear down our socket and start over with a new one. - * We re-open the underlying UDP cf right now, but do not start - * connecting until called again. - */ - int reconn_delay_ms = 200; - - CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms", - reconn_delay_ms); - Curl_conn_cf_close(cf->next, data); - cf_quiche_ctx_clear(ctx); - result = Curl_conn_cf_connect(cf->next, data, FALSE, done); - if(!result && *done) { - *done = FALSE; - ctx->reconnect_at = Curl_now(); - ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000; - Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC); - result = CURLE_OK; - } + * state. The CONNECT may work in the near future again. Indicate + * that as a "weird" reply. */ + result = CURLE_WEIRD_SERVER_REPLY; } out: @@ -1550,6 +1527,7 @@ static void cf_quiche_close(struct Curl_cfilter *cf, struct Curl_easy *data) if(ctx) { if(ctx->qconn) { + vquic_ctx_update_time(&ctx->q); (void)quiche_conn_close(ctx->qconn, TRUE, 0, NULL, 0); /* flushing the egress is not a failsafe way to deliver all the outstanding packets, but we also don't want to get stuck here... */ @@ -1617,9 +1595,32 @@ static bool cf_quiche_conn_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data, bool *input_pending) { + struct cf_quiche_ctx *ctx = cf->ctx; bool alive = TRUE; *input_pending = FALSE; + if(!ctx->qconn) + return FALSE; + + /* Both sides of the QUIC connection announce they max idle times in + * the transport parameters. Look at the minimum of both and if + * we exceed this, regard the connection as dead. The other side + * may have completely purged it and will no longer respond + * to any packets from us. */ + { + quiche_transport_params qpeerparams; + timediff_t idletime; + uint64_t idle_ms = ctx->max_idle_ms; + + if(quiche_conn_peer_transport_params(ctx->qconn, &qpeerparams) && + qpeerparams.peer_max_idle_timeout && + qpeerparams.peer_max_idle_timeout < idle_ms) + idle_ms = qpeerparams.peer_max_idle_timeout; + idletime = Curl_timediff(Curl_now(), cf->conn->lastused); + if(idletime > 0 && (uint64_t)idletime > idle_ms) + return FALSE; + } + if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending)) return FALSE; @@ -1646,7 +1647,7 @@ struct Curl_cftype Curl_cft_http3 = { cf_quiche_connect, cf_quiche_close, Curl_cf_def_get_host, - cf_quiche_get_select_socks, + cf_quiche_adjust_pollset, cf_quiche_data_pending, cf_quiche_send, cf_quiche_recv, @@ -1667,7 +1668,7 @@ CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf, (void)data; (void)conn; - ctx = calloc(sizeof(*ctx), 1); + ctx = calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/libs/libcurl/src/vquic/vquic.c b/libs/libcurl/src/vquic/vquic.c index e49b6567ad..8b9c1ae223 100644 --- a/libs/libcurl/src/vquic/vquic.c +++ b/libs/libcurl/src/vquic/vquic.c @@ -100,6 +100,7 @@ CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx) } } #endif + vquic_ctx_update_time(qctx); return CURLE_OK; } @@ -109,6 +110,11 @@ void vquic_ctx_free(struct cf_quic_ctx *qctx) Curl_bufq_free(&qctx->sendbuf); } +void vquic_ctx_update_time(struct cf_quic_ctx *qctx) +{ + qctx->last_op = Curl_now(); +} + static CURLcode send_packet_no_gso(struct Curl_cfilter *cf, struct Curl_easy *data, struct cf_quic_ctx *qctx, @@ -242,6 +248,7 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf, const uint8_t *pkt, size_t pktlen, size_t gsolen, size_t *psent) { + CURLcode result; #ifdef DEBUGBUILD /* simulate network blocking/partial writes */ if(qctx->wblock_percent > 0) { @@ -254,10 +261,14 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf, } #endif if(qctx->no_gso && pktlen > gsolen) { - return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent); + result = send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent); } - - return do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent); + else { + result = do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent); + } + if(!result) + qctx->last_io = qctx->last_op; + return result; } CURLcode vquic_flush(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -524,13 +535,17 @@ CURLcode vquic_recv_packets(struct Curl_cfilter *cf, size_t max_pkts, vquic_recv_pkt_cb *recv_cb, void *userp) { + CURLcode result; #if defined(HAVE_SENDMMSG) - return recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp); + result = recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp); #elif defined(HAVE_SENDMSG) - return recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp); + result = recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp); #else - return recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp); + result = recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp); #endif + if(!result) + qctx->last_io = qctx->last_op; + return result; } /* diff --git a/libs/libcurl/src/vquic/vquic_int.h b/libs/libcurl/src/vquic/vquic_int.h index 3fe06fb9c9..dc50593cd9 100644 --- a/libs/libcurl/src/vquic/vquic_int.h +++ b/libs/libcurl/src/vquic/vquic_int.h @@ -31,6 +31,8 @@ #define MAX_PKT_BURST 10 #define MAX_UDP_PAYLOAD_SIZE 1452 +/* Default QUIC connection timeout we announce from our side */ +#define CURL_QUIC_MAX_IDLE_MS (120 * 1000) struct cf_quic_ctx { curl_socket_t sockfd; /* connected UDP socket */ @@ -38,6 +40,8 @@ struct cf_quic_ctx { socklen_t local_addrlen; /* length of local address */ struct bufq sendbuf; /* buffer for sending one or more packets */ + struct curltime last_op; /* last (attempted) send/recv operation */ + struct curltime last_io; /* last successful socket IO */ size_t gsolen; /* length of individual packets in send buf */ size_t split_len; /* if != 0, buffer length after which GSO differs */ size_t split_gsolen; /* length of individual packets after split_len */ @@ -50,6 +54,8 @@ struct cf_quic_ctx { CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx); void vquic_ctx_free(struct cf_quic_ctx *qctx); +void vquic_ctx_update_time(struct cf_quic_ctx *qctx); + void vquic_push_blocked_pkt(struct Curl_cfilter *cf, struct cf_quic_ctx *qctx, const uint8_t *pkt, size_t pktlen, size_t gsolen); diff --git a/libs/libcurl/src/vssh/libssh.c b/libs/libcurl/src/vssh/libssh.c index 93e87e9c63..71a64cd5e8 100644 --- a/libs/libcurl/src/vssh/libssh.c +++ b/libs/libcurl/src/vssh/libssh.c @@ -93,6 +93,7 @@ #if defined(__GNUC__) && \ (LIBSSH_VERSION_MINOR >= 10) || \ (LIBSSH_VERSION_MAJOR > 0) +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif @@ -1159,13 +1160,23 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) break; } else if(statvfs) { + #ifdef _MSC_VER + #define LIBSSH_VFS_SIZE_MASK "I64u" + #else + #define LIBSSH_VFS_SIZE_MASK PRIu64 + #endif char *tmp = aprintf("statvfs:\n" - "f_bsize: %llu\n" "f_frsize: %llu\n" - "f_blocks: %llu\n" "f_bfree: %llu\n" - "f_bavail: %llu\n" "f_files: %llu\n" - "f_ffree: %llu\n" "f_favail: %llu\n" - "f_fsid: %llu\n" "f_flag: %llu\n" - "f_namemax: %llu\n", + "f_bsize: %" LIBSSH_VFS_SIZE_MASK "\n" + "f_frsize: %" LIBSSH_VFS_SIZE_MASK "\n" + "f_blocks: %" LIBSSH_VFS_SIZE_MASK "\n" + "f_bfree: %" LIBSSH_VFS_SIZE_MASK "\n" + "f_bavail: %" LIBSSH_VFS_SIZE_MASK "\n" + "f_files: %" LIBSSH_VFS_SIZE_MASK "\n" + "f_ffree: %" LIBSSH_VFS_SIZE_MASK "\n" + "f_favail: %" LIBSSH_VFS_SIZE_MASK "\n" + "f_fsid: %" LIBSSH_VFS_SIZE_MASK "\n" + "f_flag: %" LIBSSH_VFS_SIZE_MASK "\n" + "f_namemax: %" LIBSSH_VFS_SIZE_MASK "\n", statvfs->f_bsize, statvfs->f_frsize, statvfs->f_blocks, statvfs->f_bfree, statvfs->f_bavail, statvfs->f_files, @@ -1466,13 +1477,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) state(data, SSH_STOP); break; } - /* since this counts what we send to the client, we include the - newline in this counter */ - data->req.bytecount += sshc->readdir_len + 1; - /* output debug output if that is requested */ - Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename, - sshc->readdir_len); } else { if(Curl_dyn_add(&sshc->readdir_buf, sshc->readdir_longentry)) { @@ -1564,12 +1569,6 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) Curl_dyn_ptr(&sshc->readdir_buf), Curl_dyn_len(&sshc->readdir_buf)); - if(!result) { - /* output debug output if that is requested */ - Curl_debug(data, CURLINFO_DATA_OUT, Curl_dyn_ptr(&sshc->readdir_buf), - Curl_dyn_len(&sshc->readdir_buf)); - data->req.bytecount += Curl_dyn_len(&sshc->readdir_buf); - } ssh_string_free_char(sshc->readdir_tmp); sshc->readdir_tmp = NULL; @@ -1963,10 +1962,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) ssh_disconnect(sshc->ssh_session); if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) { /* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back, - explicitly mark it as closed with the memdebug macro. This libssh + tell the connection to forget about it. This libssh bug is fixed in 0.10.0. */ - fake_sclose(conn->sock[FIRSTSOCKET]); - conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; + Curl_conn_forget_socket(data, FIRSTSOCKET); } SSH_STRING_FREE_CHAR(sshc->homedir); @@ -2959,4 +2957,10 @@ void Curl_ssh_version(char *buffer, size_t buflen) (void)msnprintf(buffer, buflen, "libssh/%s", ssh_version(0)); } +#if defined(__GNUC__) && \ + (LIBSSH_VERSION_MINOR >= 10) || \ + (LIBSSH_VERSION_MAJOR > 0) +#pragma GCC diagnostic pop +#endif + #endif /* USE_LIBSSH */ diff --git a/libs/libcurl/src/vssh/libssh2.c b/libs/libcurl/src/vssh/libssh2.c index 056041db38..430f4e2ef3 100644 --- a/libs/libcurl/src/vssh/libssh2.c +++ b/libs/libcurl/src/vssh/libssh2.c @@ -1537,139 +1537,137 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) state(data, SSH_SFTP_NEXT_QUOTE); break; } - { - /* - * the arguments following the command must be separated from the - * command with a space so we can check for it unconditionally - */ - cp = strchr(cmd, ' '); - if(!cp) { - failf(data, "Syntax error command '%s', missing parameter", - cmd); + + /* + * the arguments following the command must be separated from the + * command with a space so we can check for it unconditionally + */ + cp = strchr(cmd, ' '); + if(!cp) { + failf(data, "Syntax error command '%s', missing parameter", + cmd); + state(data, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + + /* + * also, every command takes at least one argument so we get that + * first argument right now + */ + result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error: Bad first parameter to '%s'", cmd); + state(data, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + + /* + * SFTP is a binary protocol, so we don't send text commands + * to the server. Instead, we scan for commands used by + * OpenSSH's sftp program and call the appropriate libssh2 + * functions. + */ + if(strncasecompare(cmd, "chgrp ", 6) || + strncasecompare(cmd, "chmod ", 6) || + strncasecompare(cmd, "chown ", 6) || + strncasecompare(cmd, "atime ", 6) || + strncasecompare(cmd, "mtime ", 6)) { + /* attribute change */ + + /* sshc->quote_path1 contains the mode to set */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in %s: Bad second parameter", cmd); + Curl_safefree(sshc->quote_path1); state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; + sshc->actualcode = result; break; } - - /* - * also, every command takes at least one argument so we get that - * first argument right now - */ - result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir); + memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); + state(data, SSH_SFTP_QUOTE_STAT); + break; + } + if(strncasecompare(cmd, "ln ", 3) || + strncasecompare(cmd, "symlink ", 8)) { + /* symbolic linking */ + /* sshc->quote_path1 is the source */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); if(result) { if(result == CURLE_OUT_OF_MEMORY) failf(data, "Out of memory"); else - failf(data, "Syntax error: Bad first parameter to '%s'", cmd); + failf(data, + "Syntax error in ln/symlink: Bad second parameter"); + Curl_safefree(sshc->quote_path1); state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; break; } - - /* - * SFTP is a binary protocol, so we don't send text commands - * to the server. Instead, we scan for commands used by - * OpenSSH's sftp program and call the appropriate libssh2 - * functions. - */ - if(strncasecompare(cmd, "chgrp ", 6) || - strncasecompare(cmd, "chmod ", 6) || - strncasecompare(cmd, "chown ", 6) || - strncasecompare(cmd, "atime ", 6) || - strncasecompare(cmd, "mtime ", 6)) { - /* attribute change */ - - /* sshc->quote_path1 contains the mode to set */ - /* get the destination */ - result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, "Syntax error in %s: Bad second parameter", cmd); - Curl_safefree(sshc->quote_path1); - state(data, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - state(data, SSH_SFTP_QUOTE_STAT); - break; - } - if(strncasecompare(cmd, "ln ", 3) || - strncasecompare(cmd, "symlink ", 8)) { - /* symbolic linking */ - /* sshc->quote_path1 is the source */ - /* get the destination */ - result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, - "Syntax error in ln/symlink: Bad second parameter"); - Curl_safefree(sshc->quote_path1); - state(data, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - state(data, SSH_SFTP_QUOTE_SYMLINK); - break; - } - else if(strncasecompare(cmd, "mkdir ", 6)) { - /* create dir */ - state(data, SSH_SFTP_QUOTE_MKDIR); - break; - } - else if(strncasecompare(cmd, "rename ", 7)) { - /* rename file */ - /* first param is the source path */ - /* second param is the dest. path */ - result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, "Syntax error in rename: Bad second parameter"); - Curl_safefree(sshc->quote_path1); - state(data, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - state(data, SSH_SFTP_QUOTE_RENAME); - break; - } - else if(strncasecompare(cmd, "rmdir ", 6)) { - /* delete dir */ - state(data, SSH_SFTP_QUOTE_RMDIR); - break; - } - else if(strncasecompare(cmd, "rm ", 3)) { - state(data, SSH_SFTP_QUOTE_UNLINK); + state(data, SSH_SFTP_QUOTE_SYMLINK); + break; + } + else if(strncasecompare(cmd, "mkdir ", 6)) { + /* create dir */ + state(data, SSH_SFTP_QUOTE_MKDIR); + break; + } + else if(strncasecompare(cmd, "rename ", 7)) { + /* rename file */ + /* first param is the source path */ + /* second param is the dest. path */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in rename: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(data, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; break; } + state(data, SSH_SFTP_QUOTE_RENAME); + break; + } + else if(strncasecompare(cmd, "rmdir ", 6)) { + /* delete dir */ + state(data, SSH_SFTP_QUOTE_RMDIR); + break; + } + else if(strncasecompare(cmd, "rm ", 3)) { + state(data, SSH_SFTP_QUOTE_UNLINK); + break; + } #ifdef HAS_STATVFS_SUPPORT - else if(strncasecompare(cmd, "statvfs ", 8)) { - state(data, SSH_SFTP_QUOTE_STATVFS); - break; - } -#endif - - failf(data, "Unknown SFTP command"); - Curl_safefree(sshc->quote_path1); - Curl_safefree(sshc->quote_path2); - state(data, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; + else if(strncasecompare(cmd, "statvfs ", 8)) { + state(data, SSH_SFTP_QUOTE_STATVFS); break; } +#endif + + failf(data, "Unknown SFTP command"); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + state(data, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; } - break; case SSH_SFTP_NEXT_QUOTE: Curl_safefree(sshc->quote_path1); @@ -1962,13 +1960,23 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) break; } else if(rc == 0) { + #ifdef _MSC_VER + #define LIBSSH2_VFS_SIZE_MASK "I64u" + #else + #define LIBSSH2_VFS_SIZE_MASK "llu" + #endif char *tmp = aprintf("statvfs:\n" - "f_bsize: %llu\n" "f_frsize: %llu\n" - "f_blocks: %llu\n" "f_bfree: %llu\n" - "f_bavail: %llu\n" "f_files: %llu\n" - "f_ffree: %llu\n" "f_favail: %llu\n" - "f_fsid: %llu\n" "f_flag: %llu\n" - "f_namemax: %llu\n", + "f_bsize: %" LIBSSH2_VFS_SIZE_MASK "\n" + "f_frsize: %" LIBSSH2_VFS_SIZE_MASK "\n" + "f_blocks: %" LIBSSH2_VFS_SIZE_MASK "\n" + "f_bfree: %" LIBSSH2_VFS_SIZE_MASK "\n" + "f_bavail: %" LIBSSH2_VFS_SIZE_MASK "\n" + "f_files: %" LIBSSH2_VFS_SIZE_MASK "\n" + "f_ffree: %" LIBSSH2_VFS_SIZE_MASK "\n" + "f_favail: %" LIBSSH2_VFS_SIZE_MASK "\n" + "f_fsid: %" LIBSSH2_VFS_SIZE_MASK "\n" + "f_flag: %" LIBSSH2_VFS_SIZE_MASK "\n" + "f_namemax: %" LIBSSH2_VFS_SIZE_MASK "\n", statvfs.f_bsize, statvfs.f_frsize, statvfs.f_blocks, statvfs.f_bfree, statvfs.f_bavail, statvfs.f_files, @@ -2341,14 +2349,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) state(data, SSH_STOP); break; } - /* since this counts what we send to the client, we include the - newline in this counter */ - data->req.bytecount += readdir_len + 1; - /* output debug output if that is requested */ - Curl_debug(data, CURLINFO_DATA_IN, sshp->readdir_filename, - readdir_len); - Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1); } else { result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry); @@ -2427,13 +2428,6 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) Curl_dyn_ptr(&sshp->readdir), Curl_dyn_len(&sshp->readdir)); - if(!result) { - /* output debug output if that is requested */ - Curl_debug(data, CURLINFO_DATA_IN, - Curl_dyn_ptr(&sshp->readdir), - Curl_dyn_len(&sshp->readdir)); - data->req.bytecount += Curl_dyn_len(&sshp->readdir); - } if(result) { Curl_dyn_free(&sshp->readdir); state(data, SSH_STOP); diff --git a/libs/libcurl/src/vssh/ssh.h b/libs/libcurl/src/vssh/ssh.h index d310066369..ab9ac759d5 100644 --- a/libs/libcurl/src/vssh/ssh.h +++ b/libs/libcurl/src/vssh/ssh.h @@ -267,6 +267,7 @@ void Curl_ssh_attach(struct Curl_easy *data, /* for non-SSH builds */ #define Curl_ssh_cleanup() #define Curl_ssh_attach(x,y) +#define Curl_ssh_init() 0 #endif #endif /* HEADER_CURL_SSH_H */ diff --git a/libs/libcurl/src/vssh/wolfssh.c b/libs/libcurl/src/vssh/wolfssh.c index b806845cb0..346d1875b0 100644 --- a/libs/libcurl/src/vssh/wolfssh.c +++ b/libs/libcurl/src/vssh/wolfssh.c @@ -343,9 +343,6 @@ static CURLcode wssh_setup_connection(struct Curl_easy *data, return CURLE_OK; } -static Curl_recv wscp_recv, wsftp_recv; -static Curl_send wscp_send, wsftp_send; - static int userauth(byte authtype, WS_UserAuthData* authdata, void *ctx) diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c index 33f566931c..3bda30328c 100644 --- a/libs/libcurl/src/vtls/bearssl.c +++ b/libs/libcurl/src/vtls/bearssl.c @@ -582,17 +582,12 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf, const char * const ssl_cafile = /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ (ca_info_blob ? NULL : conn_config->CAfile); - const char *hostname = connssl->hostname; + const char *hostname = connssl->peer.hostname; const bool verifypeer = conn_config->verifypeer; const bool verifyhost = conn_config->verifyhost; CURLcode ret; unsigned version_min, version_max; int session_set = 0; -#ifdef ENABLE_IPV6 - struct in6_addr addr; -#else - struct in_addr addr; -#endif DEBUGASSERT(backend); CURL_TRC_CF(data, cf, "connect_step1"); @@ -706,11 +701,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf, infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); } - if((1 == Curl_inet_pton(AF_INET, hostname, &addr)) -#ifdef ENABLE_IPV6 - || (1 == Curl_inet_pton(AF_INET6, hostname, &addr)) -#endif - ) { + if(connssl->peer.is_ip_address) { if(verifyhost) { failf(data, "BearSSL: " "host verification of IP address is not supported"); @@ -719,12 +710,11 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf, hostname = NULL; } else { - char *snihost = Curl_ssl_snihost(data, hostname, NULL); - if(!snihost) { + if(!connssl->peer.sni) { failf(data, "Failed to set SNI"); return CURLE_SSL_CONNECT_ERROR; } - hostname = snihost; + hostname = connssl->peer.sni; CURL_TRC_CF(data, cf, "connect_step1, SNI set"); } @@ -749,26 +739,26 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf, return CURLE_OK; } -static int bearssl_get_select_socks(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t *socks) +static void bearssl_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps) { - struct ssl_connect_data *connssl = cf->ctx; - curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data); - - if(sock == CURL_SOCKET_BAD) - return GETSOCK_BLANK; - else { - struct bearssl_ssl_backend_data *backend = - (struct bearssl_ssl_backend_data *)connssl->backend; - unsigned state = br_ssl_engine_current_state(&backend->ctx.eng); - if(state & BR_SSL_SENDREC) { - socks[0] = sock; - return GETSOCK_WRITESOCK(0); + if(!cf->connected) { + curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data); + if(sock != CURL_SOCKET_BAD) { + struct ssl_connect_data *connssl = cf->ctx; + struct bearssl_ssl_backend_data *backend = + (struct bearssl_ssl_backend_data *)connssl->backend; + unsigned state = br_ssl_engine_current_state(&backend->ctx.eng); + + if(state & BR_SSL_SENDREC) { + Curl_pollset_set_out_only(data, ps, sock); + } + else { + Curl_pollset_set_in_only(data, ps, sock); + } } } - socks[0] = sock; - return GETSOCK_READSOCK(0); } static CURLcode bearssl_run_until(struct Curl_cfilter *cf, @@ -1210,7 +1200,7 @@ const struct Curl_ssl Curl_ssl_bearssl = { Curl_none_cert_status_request, /* cert_status_request */ bearssl_connect, /* connect */ bearssl_connect_nonblocking, /* connect_nonblocking */ - bearssl_get_select_socks, /* getsock */ + bearssl_adjust_pollset, /* adjust_pollset */ bearssl_get_internals, /* get_internals */ bearssl_close, /* close_one */ Curl_none_close_all, /* close_all */ diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c index cc30cb0f55..bd78eb5030 100644 --- a/libs/libcurl/src/vtls/gtls.c +++ b/libs/libcurl/src/vtls/gtls.c @@ -402,18 +402,13 @@ set_ssl_version_min_max(struct Curl_easy *data, CURLcode gtls_client_init(struct Curl_easy *data, struct ssl_primary_config *config, struct ssl_config_data *ssl_config, - const char *hostname, + struct ssl_peer *peer, struct gtls_instance *gtls, long *pverifyresult) { unsigned int init_flags; int rc; bool sni = TRUE; /* default is SNI enabled */ -#ifdef ENABLE_IPV6 - struct in6_addr addr; -#else - struct in_addr addr; -#endif const char *prioritylist; const char *err = NULL; const char *tls13support; @@ -460,50 +455,60 @@ CURLcode gtls_client_init(struct Curl_easy *data, } #endif - if(config->CAfile) { - /* set the trusted CA cert bundle file */ - gnutls_certificate_set_verify_flags(gtls->cred, - GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); + if(config->verifypeer) { + bool imported_native_ca = false; - rc = gnutls_certificate_set_x509_trust_file(gtls->cred, - config->CAfile, - GNUTLS_X509_FMT_PEM); - if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)", - config->CAfile, gnutls_strerror(rc)); - if(config->verifypeer) { - *pverifyresult = rc; - return CURLE_SSL_CACERT_BADFILE; + if(ssl_config->native_ca_store) { + rc = gnutls_certificate_set_x509_system_trust(gtls->cred); + if(rc < 0) + infof(data, "error reading native ca store (%s), continuing anyway", + gnutls_strerror(rc)); + else { + infof(data, "found %d certificates in native ca store", rc); + if(rc > 0) + imported_native_ca = true; } } - else - infof(data, "found %d certificates in %s", rc, config->CAfile); - } - if(config->CApath) { - /* set the trusted CA cert directory */ - rc = gnutls_certificate_set_x509_trust_dir(gtls->cred, - config->CApath, - GNUTLS_X509_FMT_PEM); - if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)", - config->CApath, gnutls_strerror(rc)); - if(config->verifypeer) { - *pverifyresult = rc; - return CURLE_SSL_CACERT_BADFILE; + if(config->CAfile) { + /* set the trusted CA cert bundle file */ + gnutls_certificate_set_verify_flags(gtls->cred, + GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); + + rc = gnutls_certificate_set_x509_trust_file(gtls->cred, + config->CAfile, + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)%s", + config->CAfile, gnutls_strerror(rc), + (imported_native_ca ? ", continuing anyway" : "")); + if(!imported_native_ca) { + *pverifyresult = rc; + return CURLE_SSL_CACERT_BADFILE; + } } + else + infof(data, "found %d certificates in %s", rc, config->CAfile); } - else - infof(data, "found %d certificates in %s", rc, config->CApath); - } -#ifdef CURL_CA_FALLBACK - /* use system ca certificate store as fallback */ - if(config->verifypeer && !(config->CAfile || config->CApath)) { - /* this ignores errors on purpose */ - gnutls_certificate_set_x509_system_trust(gtls->cred); + if(config->CApath) { + /* set the trusted CA cert directory */ + rc = gnutls_certificate_set_x509_trust_dir(gtls->cred, + config->CApath, + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)%s", + config->CApath, gnutls_strerror(rc), + (imported_native_ca ? ", continuing anyway" : "")); + if(!imported_native_ca) { + *pverifyresult = rc; + return CURLE_SSL_CACERT_BADFILE; + } + } + else + infof(data, "found %d certificates in %s", rc, config->CApath); + } } -#endif if(config->CRLfile) { /* set the CRL list file */ @@ -537,15 +542,9 @@ CURLcode gtls_client_init(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } - if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && -#ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && -#endif - sni) { - size_t snilen; - char *snihost = Curl_ssl_snihost(data, hostname, &snilen); - if(!snihost || gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS, - snihost, snilen) < 0) { + if(sni && peer->sni) { + if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS, + peer->sni, strlen(peer->sni)) < 0) { failf(data, "Failed to set SNI"); return CURLE_SSL_CONNECT_ERROR; } @@ -699,7 +698,7 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OK; result = gtls_client_init(data, conn_config, ssl_config, - connssl->hostname, + &connssl->peer, &backend->gtls, pverifyresult); if(result) return result; @@ -811,8 +810,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data, gnutls_session_t session, struct ssl_primary_config *config, struct ssl_config_data *ssl_config, - const char *hostname, - const char *dispname, + struct ssl_peer *peer, const char *pinned_key) { unsigned int cert_list_size; @@ -1068,7 +1066,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data, in RFC2818 (HTTPS), which takes into account wildcards, and the subject alternative name PKIX extension. Returns non zero on success, and zero on failure. */ - rc = gnutls_x509_crt_check_hostname(x509_cert, hostname); + rc = gnutls_x509_crt_check_hostname(x509_cert, peer->hostname); #if GNUTLS_VERSION_NUMBER < 0x030306 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP addresses. */ @@ -1081,10 +1079,10 @@ Curl_gtls_verifyserver(struct Curl_easy *data, unsigned char addrbuf[sizeof(struct use_addr)]; size_t addrlen = 0; - if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0) + if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0) addrlen = 4; #ifdef ENABLE_IPV6 - else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0) + else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0) addrlen = 16; #endif @@ -1114,13 +1112,13 @@ Curl_gtls_verifyserver(struct Curl_easy *data, if(!rc) { if(config->verifyhost) { failf(data, "SSL: certificate subject name (%s) does not match " - "target host name '%s'", certname, dispname); + "target host name '%s'", certname, peer->dispname); gnutls_x509_crt_deinit(x509_cert); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, " common name: %s (does not match '%s')", - certname, dispname); + certname, peer->dispname); } else infof(data, " common name: %s (matched)", certname); @@ -1253,8 +1251,7 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf, CURLcode result; result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config, - connssl->hostname, connssl->dispname, - pinned_key); + &connssl->peer, pinned_key); if(result) goto out; @@ -1662,7 +1659,7 @@ const struct Curl_ssl Curl_ssl_gnutls = { gtls_cert_status_request, /* cert_status_request */ gtls_connect, /* connect */ gtls_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_get_select_socks, /* getsock */ + Curl_ssl_adjust_pollset, /* adjust_pollset */ gtls_get_internals, /* get_internals */ gtls_close, /* close_one */ Curl_none_close_all, /* close_all */ diff --git a/libs/libcurl/src/vtls/gtls.h b/libs/libcurl/src/vtls/gtls.h index 64f13b3b2a..998957e689 100644 --- a/libs/libcurl/src/vtls/gtls.h +++ b/libs/libcurl/src/vtls/gtls.h @@ -43,6 +43,7 @@ struct Curl_easy; struct Curl_cfilter; struct ssl_primary_config; struct ssl_config_data; +struct ssl_peer; struct gtls_instance { gnutls_session_t session; @@ -56,7 +57,7 @@ CURLcode gtls_client_init(struct Curl_easy *data, struct ssl_primary_config *config, struct ssl_config_data *ssl_config, - const char *hostname, + struct ssl_peer *peer, struct gtls_instance *gtls, long *pverifyresult); @@ -65,8 +66,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data, gnutls_session_t session, struct ssl_primary_config *config, struct ssl_config_data *ssl_config, - const char *hostname, - const char *dispname, + struct ssl_peer *peer, const char *pinned_key); extern const struct Curl_ssl Curl_ssl_gnutls; diff --git a/libs/libcurl/src/vtls/keylog.c b/libs/libcurl/src/vtls/keylog.c index dfa033d154..4a1f8ce74b 100644 --- a/libs/libcurl/src/vtls/keylog.c +++ b/libs/libcurl/src/vtls/keylog.c @@ -23,6 +23,11 @@ ***************************************************************************/ #include "curl_setup.h" +#if defined(USE_OPENSSL) || \ + defined(USE_WOLFSSL) || \ + (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \ + defined(USE_QUICHE) + #include "keylog.h" #include @@ -55,7 +60,7 @@ Curl_tls_keylog_open(void) if(keylog_file_name) { keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT); if(keylog_file_fp) { -#ifdef WIN32 +#ifdef _WIN32 if(setvbuf(keylog_file_fp, NULL, _IONBF, 0)) #else if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096)) @@ -157,3 +162,5 @@ Curl_tls_keylog_write(const char *label, fputs(line, keylog_file_fp); return true; } + +#endif /* TLS or QUIC backend */ diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c index 496cac0ab4..292c933291 100644 --- a/libs/libcurl/src/vtls/mbedtls.c +++ b/libs/libcurl/src/vtls/mbedtls.c @@ -322,7 +322,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) char * const ssl_cert = ssl_config->primary.clientcert; const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; const char * const ssl_crlfile = ssl_config->primary.CRLfile; - const char *hostname = connssl->hostname; + const char *hostname = connssl->peer.hostname; int ret = -1; char errorbuf[128]; @@ -639,9 +639,9 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) mbedtls_ssl_conf_own_cert(&backend->config, &backend->clicert, &backend->pk); } - { - char *snihost = Curl_ssl_snihost(data, hostname, NULL); - if(!snihost || mbedtls_ssl_set_hostname(&backend->ssl, snihost)) { + + if(connssl->peer.sni) { + if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni)) { /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ @@ -1274,7 +1274,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = { Curl_none_cert_status_request, /* cert_status_request */ mbedtls_connect, /* connect */ mbedtls_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_get_select_socks, /* getsock */ + Curl_ssl_adjust_pollset, /* adjust_pollset */ mbedtls_get_internals, /* get_internals */ mbedtls_close, /* close_one */ mbedtls_close_all, /* close_all */ diff --git a/libs/libcurl/src/vtls/mbedtls_threadlock.c b/libs/libcurl/src/vtls/mbedtls_threadlock.c index 935d0e1d66..757d19f003 100644 --- a/libs/libcurl/src/vtls/mbedtls_threadlock.c +++ b/libs/libcurl/src/vtls/mbedtls_threadlock.c @@ -51,7 +51,7 @@ int Curl_mbedtlsthreadlock_thread_setup(void) { int i; - mutex_buf = calloc(NUMT * sizeof(MBEDTLS_MUTEX_T), 1); + mutex_buf = calloc(1, NUMT * sizeof(MBEDTLS_MUTEX_T)); if(!mutex_buf) return 0; /* error, no number of threads defined */ diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c index b2f201ef13..fcc4e4eb0b 100644 --- a/libs/libcurl/src/vtls/openssl.c +++ b/libs/libcurl/src/vtls/openssl.c @@ -79,6 +79,8 @@ #include #include #include +#include +#include #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP) #include @@ -96,6 +98,9 @@ #include "curl_memory.h" #include "memdebug.h" +#ifndef ARRAYSIZE +#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif /* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS renegotiations when built with BoringSSL. Renegotiating is non-compliant @@ -173,8 +178,6 @@ #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) #define HAVE_EVP_PKEY_GET_PARAMS 1 -#else -#define SSL_get1_peer_certificate SSL_get_peer_certificate #endif #ifdef HAVE_EVP_PKEY_GET_PARAMS @@ -235,7 +238,11 @@ #elif defined(OPENSSL_IS_AWSLC) #define OSSL_PACKAGE "AWS-LC" #else -#define OSSL_PACKAGE "OpenSSL" +# if defined(USE_NGTCP2) && defined(USE_NGHTTP3) +# define OSSL_PACKAGE "quictls" +# else +# define OSSL_PACKAGE "OpenSSL" +#endif #endif #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) @@ -538,9 +545,9 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl) #else RSA_get0_key(rsa, &n, &e, NULL); #endif /* HAVE_EVP_PKEY_GET_PARAMS */ - BIO_printf(mem, "%d", BN_num_bits(n)); + BIO_printf(mem, "%d", n ? BN_num_bits(n) : 0); #else - BIO_printf(mem, "%d", BN_num_bits(rsa->n)); + BIO_printf(mem, "%d", rsa->n ? BN_num_bits(rsa->n) : 0); #endif /* HAVE_OPAQUE_RSA_DSA_DH */ push_certinfo("RSA Public Key", i); print_pubkey_BN(rsa, n, i); @@ -2098,22 +2105,6 @@ static bool subj_alt_hostcheck(struct Curl_easy *data, return FALSE; } -static CURLcode -ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, - X509 *server_cert, const char *hostname, - const char *dispname); - -CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, - X509 *server_cert) -{ - const char *hostname, *dispname; - int port; - - (void)conn; - Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &dispname, &port); - return ossl_verifyhost(data, conn, server_cert, hostname, dispname); -} - /* Quote from RFC2818 section 3.1 "Server Identity" If a subjectAltName extension of type dNSName is present, that MUST @@ -2136,10 +2127,8 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, This function is now used from ngtcp2 (QUIC) as well. */ -static CURLcode -ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, - X509 *server_cert, const char *hostname, - const char *dispname) +CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, + struct ssl_peer *peer, X509 *server_cert) { bool matched = FALSE; int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */ @@ -2156,25 +2145,21 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, size_t hostlen; (void)conn; - hostlen = strlen(hostname); - -#ifndef ENABLE_IPV6 - /* Silence compiler warnings for unused params */ - (void) conn; -#endif - + hostlen = strlen(peer->hostname); + if(peer->is_ip_address) { #ifdef ENABLE_IPV6 - if(conn->bits.ipv6_ip && - Curl_inet_pton(AF_INET6, hostname, &addr)) { - target = GEN_IPADD; - addrlen = sizeof(struct in6_addr); - } - else -#endif - if(Curl_inet_pton(AF_INET, hostname, &addr)) { + if(conn->bits.ipv6_ip && + Curl_inet_pton(AF_INET6, peer->hostname, &addr)) { target = GEN_IPADD; - addrlen = sizeof(struct in_addr); + addrlen = sizeof(struct in6_addr); } + else +#endif + if(Curl_inet_pton(AF_INET, peer->hostname, &addr)) { + target = GEN_IPADD; + addrlen = sizeof(struct in_addr); + } + } /* get a "list" of alternative names */ altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL); @@ -2224,9 +2209,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, if((altlen == strlen(altptr)) && /* if this isn't true, there was an embedded zero in the name string and we cannot match it. */ - subj_alt_hostcheck(data, - altptr, - altlen, hostname, hostlen, dispname)) { + subj_alt_hostcheck(data, altptr, altlen, + peer->hostname, hostlen, + peer->dispname)) { dnsmatched = TRUE; } break; @@ -2238,7 +2223,7 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, ipmatched = TRUE; infof(data, " subjectAltName: host \"%s\" matched cert's IP address!", - dispname); + peer->dispname); } break; } @@ -2254,9 +2239,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, /* an alternative name matched */ ; else if(dNSName || iPAddress) { - infof(data, " subjectAltName does not match %s", dispname); + infof(data, " subjectAltName does not match %s", peer->dispname); failf(data, "SSL: no alternative certificate subject name matches " - "target host name '%s'", dispname); + "target host name '%s'", peer->dispname); result = CURLE_PEER_FAILED_VERIFICATION; } else { @@ -2320,9 +2305,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, result = CURLE_PEER_FAILED_VERIFICATION; } else if(!Curl_cert_hostcheck((const char *)peer_CN, - peerlen, hostname, hostlen)) { + peerlen, peer->hostname, hostlen)) { failf(data, "SSL: certificate subject name '%s' does not match " - "target host name '%s'", peer_CN, dispname); + "target host name '%s'", peer_CN, peer->dispname); result = CURLE_PEER_FAILED_VERIFICATION; } else { @@ -2731,12 +2716,6 @@ static void ossl_trace(int direction, int ssl_ver, int content_type, #ifdef USE_OPENSSL /* ====================================================== */ -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -# define use_sni(x) sni = (x) -#else -# define use_sni(x) Curl_nop_stmt -#endif - /* Check for OpenSSL 1.0.2 which has ALPN support. */ #undef HAS_ALPN #if OPENSSL_VERSION_NUMBER >= 0x10002000L \ @@ -3032,6 +3011,151 @@ static CURLcode load_cacert_from_memory(X509_STORE *store, return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE; } +#if defined(USE_WIN32_CRYPTO) +static CURLcode import_windows_cert_store(struct Curl_easy *data, + const char *name, + X509_STORE *store, + bool *imported) +{ + CURLcode result = CURLE_OK; + HCERTSTORE hStore; + + *imported = false; + + hStore = CertOpenSystemStoreA(0, name); + if(hStore) { + PCCERT_CONTEXT pContext = NULL; + /* The array of enhanced key usage OIDs will vary per certificate and + is declared outside of the loop so that rather than malloc/free each + iteration we can grow it with realloc, when necessary. */ + CERT_ENHKEY_USAGE *enhkey_usage = NULL; + DWORD enhkey_usage_size = 0; + + /* This loop makes a best effort to import all valid certificates from + the MS root store. If a certificate cannot be imported it is + skipped. 'result' is used to store only hard-fail conditions (such + as out of memory) that cause an early break. */ + result = CURLE_OK; + for(;;) { + X509 *x509; + FILETIME now; + BYTE key_usage[2]; + DWORD req_size; + const unsigned char *encoded_cert; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + char cert_name[256]; +#endif + + pContext = CertEnumCertificatesInStore(hStore, pContext); + if(!pContext) + break; + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, + NULL, cert_name, sizeof(cert_name))) { + strcpy(cert_name, "Unknown"); + } + infof(data, "SSL: Checking cert \"%s\"", cert_name); +#endif + encoded_cert = (const unsigned char *)pContext->pbCertEncoded; + if(!encoded_cert) + continue; + + GetSystemTimeAsFileTime(&now); + if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 || + CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0) + continue; + + /* If key usage exists check for signing attribute */ + if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType, + pContext->pCertInfo, + key_usage, sizeof(key_usage))) { + if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE)) + continue; + } + else if(GetLastError()) + continue; + + /* If enhanced key usage exists check for server auth attribute. + * + * Note "In a Microsoft environment, a certificate might also have + * EKU extended properties that specify valid uses for the + * certificate." The call below checks both, and behavior varies + * depending on what is found. For more details see + * CertGetEnhancedKeyUsage doc. + */ + if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) { + if(req_size && req_size > enhkey_usage_size) { + void *tmp = realloc(enhkey_usage, req_size); + + if(!tmp) { + failf(data, "SSL: Out of memory allocating for OID list"); + result = CURLE_OUT_OF_MEMORY; + break; + } + + enhkey_usage = (CERT_ENHKEY_USAGE *)tmp; + enhkey_usage_size = req_size; + } + + if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) { + if(!enhkey_usage->cUsageIdentifier) { + /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate + is good for all uses. If it returns zero, the certificate + has no valid uses." */ + if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND) + continue; + } + else { + DWORD i; + bool found = false; + + for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) { + if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */, + enhkey_usage->rgpszUsageIdentifier[i])) { + found = true; + break; + } + } + + if(!found) + continue; + } + } + else + continue; + } + else + continue; + + x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded); + if(!x509) + continue; + + /* Try to import the certificate. This may fail for legitimate + reasons such as duplicate certificate, which is allowed by MS but + not OpenSSL. */ + if(X509_STORE_add_cert(store, x509) == 1) { +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + infof(data, "SSL: Imported cert \"%s\"", cert_name); +#endif + *imported = true; + } + X509_free(x509); + } + + free(enhkey_usage); + CertFreeCertificateContext(pContext); + CertCloseStore(hStore, 0); + + if(result) + return result; + } + + return result; +} +#endif + static CURLcode populate_x509_store(struct Curl_cfilter *cf, struct Curl_easy *data, X509_STORE *store) @@ -3061,140 +3185,25 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037 https://datatracker.ietf.org/doc/html/rfc5280 */ if(ssl_config->native_ca_store) { - HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT")); - - if(hStore) { - PCCERT_CONTEXT pContext = NULL; - /* The array of enhanced key usage OIDs will vary per certificate and - is declared outside of the loop so that rather than malloc/free each - iteration we can grow it with realloc, when necessary. */ - CERT_ENHKEY_USAGE *enhkey_usage = NULL; - DWORD enhkey_usage_size = 0; - - /* This loop makes a best effort to import all valid certificates from - the MS root store. If a certificate cannot be imported it is - skipped. 'result' is used to store only hard-fail conditions (such - as out of memory) that cause an early break. */ - result = CURLE_OK; - for(;;) { - X509 *x509; - FILETIME now; - BYTE key_usage[2]; - DWORD req_size; - const unsigned char *encoded_cert; -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - char cert_name[256]; -#endif - - pContext = CertEnumCertificatesInStore(hStore, pContext); - if(!pContext) - break; - -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, - NULL, cert_name, sizeof(cert_name))) { - strcpy(cert_name, "Unknown"); - } - infof(data, "SSL: Checking cert \"%s\"", cert_name); -#endif - encoded_cert = (const unsigned char *)pContext->pbCertEncoded; - if(!encoded_cert) - continue; - - GetSystemTimeAsFileTime(&now); - if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 || - CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0) - continue; - - /* If key usage exists check for signing attribute */ - if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType, - pContext->pCertInfo, - key_usage, sizeof(key_usage))) { - if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE)) - continue; - } - else if(GetLastError()) - continue; - - /* If enhanced key usage exists check for server auth attribute. - * - * Note "In a Microsoft environment, a certificate might also have - * EKU extended properties that specify valid uses for the - * certificate." The call below checks both, and behavior varies - * depending on what is found. For more details see - * CertGetEnhancedKeyUsage doc. - */ - if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) { - if(req_size && req_size > enhkey_usage_size) { - void *tmp = realloc(enhkey_usage, req_size); - - if(!tmp) { - failf(data, "SSL: Out of memory allocating for OID list"); - result = CURLE_OUT_OF_MEMORY; - break; - } - - enhkey_usage = (CERT_ENHKEY_USAGE *)tmp; - enhkey_usage_size = req_size; - } - - if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) { - if(!enhkey_usage->cUsageIdentifier) { - /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate - is good for all uses. If it returns zero, the certificate - has no valid uses." */ - if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND) - continue; - } - else { - DWORD i; - bool found = false; - - for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) { - if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */, - enhkey_usage->rgpszUsageIdentifier[i])) { - found = true; - break; - } - } - - if(!found) - continue; - } - } - else - continue; - } - else - continue; - - x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded); - if(!x509) - continue; - - /* Try to import the certificate. This may fail for legitimate - reasons such as duplicate certificate, which is allowed by MS but - not OpenSSL. */ - if(X509_STORE_add_cert(store, x509) == 1) { -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - infof(data, "SSL: Imported cert \"%s\"", cert_name); -#endif - imported_native_ca = true; - } - X509_free(x509); - } - - free(enhkey_usage); - CertFreeCertificateContext(pContext); - CertCloseStore(hStore, 0); - + const char *storeNames[] = { + "ROOT", /* Trusted Root Certification Authorities */ + "CA" /* Intermediate Certification Authorities */ + }; + size_t i; + for(i = 0; i < ARRAYSIZE(storeNames); ++i) { + bool imported = false; + result = import_windows_cert_store(data, storeNames[i], store, + &imported); if(result) return result; + if(imported) { + infof(data, "successfully imported Windows %s store", storeNames[i]); + imported_native_ca = true; + } + else + infof(data, "error importing Windows %s store, continuing anyway", + storeNames[i]); } - if(imported_native_ca) - infof(data, "successfully imported Windows CA store"); - else - infof(data, "error importing Windows CA store, continuing anyway"); } #endif if(ca_info_blob) { @@ -3210,7 +3219,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, } if(ssl_cafile || ssl_capath) { -#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */ if(ssl_cafile && !X509_STORE_load_file(store, ssl_cafile)) { if(!imported_native_ca && !imported_ca_info_blob) { @@ -3339,6 +3348,7 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi; X509_STORE *store = NULL; + DEBUGASSERT(multi); if(multi && multi->ssl_backend_data && multi->ssl_backend_data->store && @@ -3358,6 +3368,7 @@ static void set_cached_x509_store(struct Curl_cfilter *cf, struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi; struct multi_ssl_backend_data *mbackend; + DEBUGASSERT(multi); if(!multi) return; @@ -3449,17 +3460,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); BIO *bio; - -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - bool sni; - const char *hostname = connssl->hostname; - -#ifdef ENABLE_IPV6 - struct in6_addr addr; -#else - struct in_addr addr; -#endif -#endif const long int ssl_version = conn_config->version; char * const ssl_cert = ssl_config->primary.clientcert; const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; @@ -3494,7 +3494,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, #else req_method = SSLv23_client_method(); #endif - use_sni(TRUE); break; case CURL_SSLVERSION_SSLv2: failf(data, "No SSLv2 support"); @@ -3787,13 +3786,8 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, backend->server_cert = 0x0; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && -#ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && -#endif - sni) { - char *snihost = Curl_ssl_snihost(data, hostname, NULL); - if(!snihost || !SSL_set_tlsext_host_name(backend->handle, snihost)) { + if(connssl->peer.sni) { + if(!SSL_set_tlsext_host_name(backend->handle, connssl->peer.sni)) { failf(data, "Failed set SNI"); return CURLE_SSL_CONNECT_ERROR; } @@ -3802,6 +3796,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, SSL_set_app_data(backend->handle, cf); + connssl->reused_session = FALSE; if(ssl_config->primary.sessionid) { Curl_ssl_sessionid_lock(data); if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) { @@ -3815,6 +3810,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, } /* Informational message */ infof(data, "SSL reusing session ID"); + connssl->reused_session = TRUE; } Curl_ssl_sessionid_unlock(data); } @@ -3975,7 +3971,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, Curl_strerror(sockerr, extramsg, sizeof(extramsg)); failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%d ", extramsg[0] ? extramsg : SSL_ERROR_to_str(detail), - connssl->hostname, connssl->port); + connssl->peer.hostname, connssl->port); return result; } @@ -3986,13 +3982,28 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, } } else { + int psigtype_nid = NID_undef; + const char *negotiated_group_name = NULL; + /* we connected fine, we're not waiting for anything else. */ connssl->connecting_state = ssl_connect_3; +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + SSL_get_peer_signature_type_nid(backend->handle, &psigtype_nid); +#if (OPENSSL_VERSION_NUMBER >= 0x30200000L) + negotiated_group_name = SSL_get0_group_name(backend->handle); +#else + negotiated_group_name = + OBJ_nid2sn(SSL_get_negotiated_group(backend->handle) & 0x0000FFFF); +#endif +#endif + /* Informational message */ - infof(data, "SSL connection using %s / %s", + infof(data, "SSL connection using %s / %s / %s / %s", SSL_get_version(backend->handle), - SSL_get_cipher(backend->handle)); + SSL_get_cipher(backend->handle), + negotiated_group_name? negotiated_group_name : "[blank]", + OBJ_nid2sn(psigtype_nid)); #ifdef HAS_ALPN /* Sets data and len to negotiated protocol, len is 0 if no protocol was @@ -4069,6 +4080,75 @@ static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, return result; } +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ + !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x3060000fL) && \ + !defined(OPENSSL_IS_BORINGSSL) && \ + !defined(OPENSSL_IS_AWSLC) && \ + !defined(CURL_DISABLE_VERBOSE_STRINGS) +static void infof_certstack(struct Curl_easy *data, const SSL *ssl) +{ + STACK_OF(X509) *certstack; + long verify_result; + int num_cert_levels; + int cert_level; + + verify_result = SSL_get_verify_result(ssl); + if(verify_result != X509_V_OK) + certstack = SSL_get_peer_cert_chain(ssl); + else + certstack = SSL_get0_verified_chain(ssl); + num_cert_levels = sk_X509_num(certstack); + + for(cert_level = 0; cert_level < num_cert_levels; cert_level++) { + char cert_algorithm[80] = ""; + char group_name_final[80] = ""; + const X509_ALGOR *palg_cert = NULL; + const ASN1_OBJECT *paobj_cert = NULL; + X509 *current_cert; + EVP_PKEY *current_pkey; + int key_bits; + int key_sec_bits; + int get_group_name; + const char *type_name; + + current_cert = sk_X509_value(certstack, cert_level); + + X509_get0_signature(NULL, &palg_cert, current_cert); + X509_ALGOR_get0(&paobj_cert, NULL, NULL, palg_cert); + OBJ_obj2txt(cert_algorithm, sizeof(cert_algorithm), paobj_cert, 0); + + current_pkey = X509_get0_pubkey(current_cert); + key_bits = EVP_PKEY_bits(current_pkey); +#if (OPENSSL_VERSION_NUMBER < 0x30000000L) +#define EVP_PKEY_get_security_bits EVP_PKEY_security_bits +#endif + key_sec_bits = EVP_PKEY_get_security_bits(current_pkey); +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + { + char group_name[80] = ""; + get_group_name = EVP_PKEY_get_group_name(current_pkey, group_name, + sizeof(group_name), NULL); + msnprintf(group_name_final, sizeof(group_name_final), "/%s", group_name); + } + type_name = EVP_PKEY_get0_type_name(current_pkey); +#else + get_group_name = 0; + type_name = NULL; +#endif + + infof(data, + " Certificate level %d: " + "Public key type %s%s (%d/%d Bits/secBits), signed using %s", + cert_level, type_name ? type_name : "?", + get_group_name == 0 ? "" : group_name_final, + key_bits, key_sec_bits, cert_algorithm); + } +} +#else +#define infof_certstack(data, ssl) +#endif + /* * Get the server cert, verify it and show it, etc., only call failf() if the * 'strict' argument is TRUE as otherwise all this is for informational @@ -4147,8 +4227,8 @@ static CURLcode servercert(struct Curl_cfilter *cf, BIO_free(mem); if(conn_config->verifyhost) { - result = ossl_verifyhost(data, conn, backend->server_cert, - connssl->hostname, connssl->dispname); + result = Curl_ossl_verifyhost(data, conn, &connssl->peer, + backend->server_cert); if(result) { X509_free(backend->server_cert); backend->server_cert = NULL; @@ -4258,9 +4338,12 @@ static CURLcode servercert(struct Curl_cfilter *cf, infof(data, " SSL certificate verify ok."); } + infof_certstack(data, backend->handle); + #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) - if(conn_config->verifystatus) { + if(conn_config->verifystatus && !connssl->reused_session) { + /* don't do this after Session ID reuse */ result = verifystatus(cf, data); if(result) { X509_free(backend->server_cert); @@ -4522,22 +4605,9 @@ static ssize_t ossl_send(struct Curl_cfilter *cf, case SSL_ERROR_SSL: { /* A failure in the SSL library occurred, usually a protocol error. The OpenSSL error queue contains more information on the error. */ - struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next); - struct ssl_connect_data *connssl_next = cf_ssl_next? - cf_ssl_next->ctx : NULL; sslerror = ERR_get_error(); - if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL && - ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET && - connssl->state == ssl_connection_complete && - (connssl_next && connssl_next->state == ssl_connection_complete) - ) { - char ver[120]; - (void)ossl_version(ver, sizeof(ver)); - failf(data, "Error: %s does not support double SSL tunneling.", ver); - } - else - failf(data, "SSL_write() error: %s", - ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); + failf(data, "SSL_write() error: %s", + ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); *curlcode = CURLE_SEND_ERROR; rc = -1; goto out; @@ -4842,7 +4912,7 @@ const struct Curl_ssl Curl_ssl_openssl = { ossl_cert_status_request, /* cert_status_request */ ossl_connect, /* connect */ ossl_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_get_select_socks,/* getsock */ + Curl_ssl_adjust_pollset, /* adjust_pollset */ ossl_get_internals, /* get_internals */ ossl_close, /* close_one */ ossl_close_all, /* close_all */ diff --git a/libs/libcurl/src/vtls/openssl.h b/libs/libcurl/src/vtls/openssl.h index b88b83febe..df36a831b1 100644 --- a/libs/libcurl/src/vtls/openssl.h +++ b/libs/libcurl/src/vtls/openssl.h @@ -31,24 +31,21 @@ * This header should only be needed to get included by vtls.c, openssl.c * and ngtcp2.c */ +#include #include #include "urldata.h" -/* - * In an effort to avoid using 'X509 *' here, we instead use the struct - * x509_st version of the type so that we can forward-declare it here without - * having to include . Including that header causes name - * conflicts when libcurl is built with both Schannel and OpenSSL support. - */ -struct x509_st; +#if (OPENSSL_VERSION_NUMBER < 0x30000000L) +#define SSL_get1_peer_certificate SSL_get_peer_certificate +#endif + CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, - struct x509_st *server_cert); + struct ssl_peer *peer, X509 *server_cert); extern const struct Curl_ssl Curl_ssl_openssl; -struct ssl_ctx_st; CURLcode Curl_ossl_set_client_cert(struct Curl_easy *data, - struct ssl_ctx_st *ctx, char *cert_file, + SSL_CTX *ctx, char *cert_file, const struct curl_blob *cert_blob, const char *cert_type, char *key_file, const struct curl_blob *key_blob, @@ -65,5 +62,9 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf, struct Curl_easy *data, SSL_CTX *ssl_ctx); +CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf, + struct Curl_easy *data, + SSL_CTX *ssl_ctx); + #endif /* USE_OPENSSL */ #endif /* HEADER_CURL_SSLUSE_H */ diff --git a/libs/libcurl/src/vtls/rustls.c b/libs/libcurl/src/vtls/rustls.c index 989954bf46..d30325d098 100644 --- a/libs/libcurl/src/vtls/rustls.c +++ b/libs/libcurl/src/vtls/rustls.c @@ -39,6 +39,7 @@ #include "select.h" #include "strerror.h" #include "multiif.h" +#include "connect.h" /* for the connect timeout */ struct rustls_ssl_backend_data { @@ -75,14 +76,6 @@ cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data) return backend->data_pending; } -static CURLcode -cr_connect(struct Curl_cfilter *cf UNUSED_PARAM, - struct Curl_easy *data UNUSED_PARAM) -{ - infof(data, "rustls_connect: unimplemented"); - return CURLE_SSL_CONNECT_ERROR; -} - struct io_ctx { struct Curl_cfilter *cf; struct Curl_easy *data; @@ -386,7 +379,7 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ (ca_info_blob ? NULL : conn_config->CAfile); const bool verifypeer = conn_config->verifypeer; - const char *hostname = connssl->hostname; + const char *hostname = connssl->peer.hostname; char errorbuf[256]; size_t errorlen; int result; @@ -458,12 +451,11 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, backend->config = rustls_client_config_builder_build(config_builder); DEBUGASSERT(rconn == NULL); { - char *snihost = Curl_ssl_snihost(data, hostname, NULL); - if(!snihost) { - failf(data, "rustls: failed to get SNI"); - return CURLE_SSL_CONNECT_ERROR; - } - result = rustls_client_connection_new(backend->config, snihost, &rconn); + /* rustls claims to manage ip address hostnames as well here. So, + * if we have an SNI, we use it, otherwise we pass the hostname */ + char *server = connssl->peer.sni? + connssl->peer.sni : connssl->peer.hostname; + result = rustls_client_connection_new(backend->config, server, &rconn); } if(result != RUSTLS_RESULT_OK) { rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen); @@ -486,9 +478,20 @@ cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data, Curl_alpn_set_negotiated(cf, data, protocol, len); } +/* Given an established network connection, do a TLS handshake. + * + * If `blocking` is true, this function will block until the handshake is + * complete. Otherwise it will return as soon as I/O would block. + * + * For the non-blocking I/O case, this function will set `*done` to true + * once the handshake is complete. This function never reads the value of + * `*done*`. + */ static CURLcode -cr_connect_nonblocking(struct Curl_cfilter *cf, - struct Curl_easy *data, bool *done) +cr_connect_common(struct Curl_cfilter *cf, + struct Curl_easy *data, + bool blocking, + bool *done) { struct ssl_connect_data *const connssl = cf->ctx; curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); @@ -502,6 +505,8 @@ cr_connect_nonblocking(struct Curl_cfilter *cf, bool wants_write; curl_socket_t writefd; curl_socket_t readfd; + timediff_t timeout_ms; + timediff_t socket_check_timeout; DEBUGASSERT(backend); @@ -539,12 +544,29 @@ cr_connect_nonblocking(struct Curl_cfilter *cf, writefd = wants_write?sockfd:CURL_SOCKET_BAD; readfd = wants_read?sockfd:CURL_SOCKET_BAD; - what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 0); + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "rustls: operation timed out before socket check"); + return CURLE_OPERATION_TIMEDOUT; + } + + socket_check_timeout = blocking?timeout_ms:0; + + what = Curl_socket_check( + readfd, CURL_SOCKET_BAD, writefd, socket_check_timeout); if(what < 0) { /* fatal error */ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); return CURLE_SSL_CONNECT_ERROR; } + if(blocking && 0 == what) { + failf(data, "rustls connection timeout after %d ms", + socket_check_timeout); + return CURLE_OPERATION_TIMEDOUT; + } if(0 == what) { infof(data, "Curl_socket_check: %s would block", wants_read&&wants_write ? "writing and reading" : @@ -589,32 +611,43 @@ cr_connect_nonblocking(struct Curl_cfilter *cf, DEBUGASSERT(false); } -/* returns a bitmap of flags for this connection's first socket indicating - whether we want to read or write */ -static int -cr_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) +static CURLcode +cr_connect_nonblocking(struct Curl_cfilter *cf, + struct Curl_easy *data, bool *done) { - struct ssl_connect_data *const connssl = cf->ctx; - curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); - struct rustls_ssl_backend_data *const backend = - (struct rustls_ssl_backend_data *)connssl->backend; - struct rustls_connection *rconn = NULL; + return cr_connect_common(cf, data, false, done); +} - (void)data; - DEBUGASSERT(backend); - rconn = backend->conn; +static CURLcode +cr_connect_blocking(struct Curl_cfilter *cf UNUSED_PARAM, + struct Curl_easy *data UNUSED_PARAM) +{ + bool done; /* unused */ + return cr_connect_common(cf, data, true, &done); +} - if(rustls_connection_wants_write(rconn)) { - socks[0] = sockfd; - return GETSOCK_WRITESOCK(0); - } - if(rustls_connection_wants_read(rconn)) { - socks[0] = sockfd; - return GETSOCK_READSOCK(0); +static void cr_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps) +{ + if(!cf->connected) { + curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data); + struct ssl_connect_data *const connssl = cf->ctx; + struct rustls_ssl_backend_data *const backend = + (struct rustls_ssl_backend_data *)connssl->backend; + struct rustls_connection *rconn = NULL; + + (void)data; + DEBUGASSERT(backend); + rconn = backend->conn; + + if(rustls_connection_wants_write(rconn)) { + Curl_pollset_add_out(data, ps, sock); + } + if(rustls_connection_wants_read(rconn)) { + Curl_pollset_add_in(data, ps, sock); + } } - - return GETSOCK_BLANK; } static void * @@ -675,9 +708,9 @@ const struct Curl_ssl Curl_ssl_rustls = { cr_data_pending, /* data_pending */ Curl_none_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ - cr_connect, /* connect */ + cr_connect_blocking, /* connect */ cr_connect_nonblocking, /* connect_nonblocking */ - cr_get_select_socks, /* get_select_socks */ + cr_adjust_pollset, /* adjust_pollset */ cr_get_internals, /* get_internals */ cr_close, /* close_one */ Curl_none_close_all, /* close_all */ diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c index 77ab43a9bf..c04f968f29 100644 --- a/libs/libcurl/src/vtls/schannel.c +++ b/libs/libcurl/src/vtls/schannel.c @@ -1063,17 +1063,12 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) #endif SECURITY_STATUS sspi_status = SEC_E_OK; struct Curl_schannel_cred *old_cred = NULL; - struct in_addr addr; -#ifdef ENABLE_IPV6 - struct in6_addr addr6; -#endif CURLcode result; - const char *hostname = connssl->hostname; DEBUGASSERT(backend); DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %d (step 1/3)", - hostname, connssl->port)); + connssl->peer.hostname, connssl->port)); if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT, VERSION_LESS_THAN_EQUAL)) { @@ -1154,22 +1149,14 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* A hostname associated with the credential is needed by InitializeSecurityContext for SNI and other reasons. */ - snihost = Curl_ssl_snihost(data, hostname, NULL); - if(!snihost) { - failf(data, "Failed to set SNI"); - return CURLE_SSL_CONNECT_ERROR; - } + snihost = connssl->peer.sni? connssl->peer.sni : connssl->peer.hostname; backend->cred->sni_hostname = curlx_convert_UTF8_to_tchar(snihost); if(!backend->cred->sni_hostname) return CURLE_OUT_OF_MEMORY; } /* Warn if SNI is disabled due to use of an IP address */ - if(Curl_inet_pton(AF_INET, hostname, &addr) -#ifdef ENABLE_IPV6 - || Curl_inet_pton(AF_INET6, hostname, &addr6) -#endif - ) { + if(connssl->peer.is_ip_address) { infof(data, "schannel: using IP address, SNI is not supported by OS."); } @@ -1346,7 +1333,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %d (step 2/3)", - connssl->hostname, connssl->port)); + connssl->peer.hostname, connssl->port)); if(!backend->cred || !backend->ctxt) return CURLE_SSL_CONNECT_ERROR; @@ -1700,7 +1687,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %d (step 3/3)", - connssl->hostname, connssl->port)); + connssl->peer.hostname, connssl->port)); if(!backend->cred) return CURLE_SSL_CONNECT_ERROR; @@ -2498,7 +2485,7 @@ static int schannel_shutdown(struct Curl_cfilter *cf, if(backend->ctxt) { infof(data, "schannel: shutting down SSL/TLS connection with %s port %d", - connssl->hostname, connssl->port); + connssl->peer.hostname, connssl->port); } if(backend->cred && backend->ctxt) { @@ -2754,6 +2741,151 @@ static void *schannel_get_internals(struct ssl_connect_data *connssl, return &backend->ctxt->ctxt_handle; } +HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, + const struct Curl_easy *data) +{ + struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); + struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi; + const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; + struct schannel_multi_ssl_backend_data *mbackend; + const struct ssl_general_config *cfg = &data->set.general_ssl; + timediff_t timeout_ms; + timediff_t elapsed_ms; + struct curltime now; + unsigned char info_blob_digest[CURL_SHA256_DIGEST_LENGTH]; + + DEBUGASSERT(multi); + + if(!multi || !multi->ssl_backend_data) { + return NULL; + } + + mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data; + if(!mbackend->cert_store) { + return NULL; + } + + /* zero ca_cache_timeout completely disables caching */ + if(!cfg->ca_cache_timeout) { + return NULL; + } + + /* check for cache timeout by using the cached_x509_store_expired timediff + calculation pattern from openssl.c. + negative timeout means retain forever. */ + timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; + if(timeout_ms >= 0) { + now = Curl_now(); + elapsed_ms = Curl_timediff(now, mbackend->time); + if(elapsed_ms >= timeout_ms) { + return NULL; + } + } + + if(ca_info_blob) { + if(!mbackend->CAinfo_blob_digest) { + return NULL; + } + if(mbackend->CAinfo_blob_size != ca_info_blob->len) { + return NULL; + } + schannel_sha256sum((const unsigned char *)ca_info_blob->data, + ca_info_blob->len, + info_blob_digest, + CURL_SHA256_DIGEST_LENGTH); + if(memcmp(mbackend->CAinfo_blob_digest, + info_blob_digest, + CURL_SHA256_DIGEST_LENGTH)) { + return NULL; + } + } + else { + if(!conn_config->CAfile || !mbackend->CAfile || + strcmp(mbackend->CAfile, conn_config->CAfile)) { + return NULL; + } + } + + return mbackend->cert_store; +} + +bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, + const struct Curl_easy *data, + HCERTSTORE cert_store) +{ + struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); + struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi; + const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; + struct schannel_multi_ssl_backend_data *mbackend; + unsigned char *CAinfo_blob_digest = NULL; + size_t CAinfo_blob_size = 0; + char *CAfile = NULL; + + DEBUGASSERT(multi); + + if(!multi) { + return false; + } + + if(!multi->ssl_backend_data) { + multi->ssl_backend_data = + calloc(1, sizeof(struct schannel_multi_ssl_backend_data)); + if(!multi->ssl_backend_data) { + return false; + } + } + + mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data; + + + if(ca_info_blob) { + CAinfo_blob_digest = malloc(CURL_SHA256_DIGEST_LENGTH); + if(!CAinfo_blob_digest) { + return false; + } + schannel_sha256sum((const unsigned char *)ca_info_blob->data, + ca_info_blob->len, + CAinfo_blob_digest, + CURL_SHA256_DIGEST_LENGTH); + CAinfo_blob_size = ca_info_blob->len; + } + else { + if(conn_config->CAfile) { + CAfile = strdup(conn_config->CAfile); + if(!CAfile) { + return false; + } + } + } + + /* free old cache data */ + if(mbackend->cert_store) { + CertCloseStore(mbackend->cert_store, 0); + } + free(mbackend->CAinfo_blob_digest); + free(mbackend->CAfile); + + mbackend->time = Curl_now(); + mbackend->cert_store = cert_store; + mbackend->CAinfo_blob_digest = CAinfo_blob_digest; + mbackend->CAinfo_blob_size = CAinfo_blob_size; + mbackend->CAfile = CAfile; + return true; +} + +static void schannel_free_multi_ssl_backend_data( + struct multi_ssl_backend_data *msbd) +{ + struct schannel_multi_ssl_backend_data *mbackend = + (struct schannel_multi_ssl_backend_data*)msbd; + if(mbackend->cert_store) { + CertCloseStore(mbackend->cert_store, 0); + } + free(mbackend->CAinfo_blob_digest); + free(mbackend->CAfile); + free(mbackend); +} + const struct Curl_ssl Curl_ssl_schannel = { { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ @@ -2777,7 +2909,7 @@ const struct Curl_ssl Curl_ssl_schannel = { Curl_none_cert_status_request, /* cert_status_request */ schannel_connect, /* connect */ schannel_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_get_select_socks, /* getsock */ + Curl_ssl_adjust_pollset, /* adjust_pollset */ schannel_get_internals, /* get_internals */ schannel_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -2789,7 +2921,7 @@ const struct Curl_ssl Curl_ssl_schannel = { schannel_sha256sum, /* sha256sum */ NULL, /* associate_connection */ NULL, /* disassociate_connection */ - NULL, /* free_multi_ssl_backend_data */ + schannel_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */ schannel_recv, /* recv decrypted data */ schannel_send, /* send data to encrypt */ }; diff --git a/libs/libcurl/src/vtls/schannel_int.h b/libs/libcurl/src/vtls/schannel_int.h index 17a94d6e85..c460be63aa 100644 --- a/libs/libcurl/src/vtls/schannel_int.h +++ b/libs/libcurl/src/vtls/schannel_int.h @@ -149,5 +149,22 @@ struct schannel_ssl_backend_data { #endif }; +struct schannel_multi_ssl_backend_data { + unsigned char *CAinfo_blob_digest; /* CA info blob digest */ + size_t CAinfo_blob_size; /* CA info blob size */ + char *CAfile; /* CAfile path used to generate + certificate store */ + HCERTSTORE cert_store; /* cached certificate store or + NULL if none */ + struct curltime time; /* when the cached store was created */ +}; + +HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, + const struct Curl_easy *data); + +bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, + const struct Curl_easy *data, + HCERTSTORE cert_store); + #endif /* USE_SCHANNEL */ #endif /* HEADER_CURL_SCHANNEL_INT_H */ diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c index 35ce35b789..0c9c00c16a 100644 --- a/libs/libcurl/src/vtls/schannel_verify.c +++ b/libs/libcurl/src/vtls/schannel_verify.c @@ -470,7 +470,7 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf, CERT_CONTEXT *pCertContextServer = NULL; TCHAR *cert_hostname_buff = NULL; size_t cert_hostname_buff_index = 0; - const char *conn_hostname = connssl->hostname; + const char *conn_hostname = connssl->peer.hostname; size_t hostlen = strlen(conn_hostname); DWORD len = 0; DWORD actual_len = 0; @@ -600,6 +600,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, const CERT_CHAIN_CONTEXT *pChainContext = NULL; HCERTCHAINENGINE cert_chain_engine = NULL; HCERTSTORE trust_store = NULL; + HCERTSTORE own_trust_store = NULL; DEBUGASSERT(BACKEND); @@ -630,31 +631,46 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, result = CURLE_SSL_CACERT_BADFILE; } else { - /* Open the certificate store */ - trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY, - 0, - (HCRYPTPROV)NULL, - CERT_STORE_CREATE_NEW_FLAG, - NULL); - if(!trust_store) { - char buffer[STRERROR_LEN]; - failf(data, "schannel: failed to create certificate store: %s", - Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); - result = CURLE_SSL_CACERT_BADFILE; + /* try cache */ + trust_store = Curl_schannel_get_cached_cert_store(cf, data); + + if(trust_store) { + infof(data, "schannel: reusing certificate store from cache"); } else { - const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; - if(ca_info_blob) { - result = add_certs_data_to_store(trust_store, - (const char *)ca_info_blob->data, - ca_info_blob->len, - "(memory blob)", - data); + /* Open the certificate store */ + trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY, + 0, + (HCRYPTPROV)NULL, + CERT_STORE_CREATE_NEW_FLAG, + NULL); + if(!trust_store) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: failed to create certificate store: %s", + Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; } else { - result = add_certs_file_to_store(trust_store, - conn_config->CAfile, - data); + const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; + own_trust_store = trust_store; + + if(ca_info_blob) { + result = add_certs_data_to_store(trust_store, + (const char *)ca_info_blob->data, + ca_info_blob->len, + "(memory blob)", + data); + } + else { + result = add_certs_file_to_store(trust_store, + conn_config->CAfile, + data); + } + if(result == CURLE_OK) { + if(Curl_schannel_set_cached_cert_store(cf, data, trust_store)) { + own_trust_store = NULL; + } + } } } } @@ -754,8 +770,8 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, CertFreeCertificateChainEngine(cert_chain_engine); } - if(trust_store) { - CertCloseStore(trust_store, 0); + if(own_trust_store) { + CertCloseStore(own_trust_store, 0); } if(pChainContext) diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c index d941119de9..26b673016e 100644 --- a/libs/libcurl/src/vtls/sectransp.c +++ b/libs/libcurl/src/vtls/sectransp.c @@ -46,8 +46,10 @@ #endif /* __clang__ */ #ifdef __GNUC__ +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Waddress" #pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wunreachable-code" #endif #include @@ -1013,7 +1015,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data, } else { size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1; - cbuf = calloc(cbuf_size, 1); + cbuf = calloc(1, cbuf_size); if(cbuf) { if(!CFStringGetCString(c, cbuf, cbuf_size, kCFStringEncodingUTF8)) { @@ -1651,11 +1653,6 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf, const bool verifypeer = conn_config->verifypeer; char * const ssl_cert = ssl_config->primary.clientcert; const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; -#ifdef ENABLE_IPV6 - struct in6_addr addr; -#else - struct in_addr addr; -#endif /* ENABLE_IPV6 */ char *ciphers; OSStatus err = noErr; #if CURL_BUILD_MAC @@ -2003,13 +2000,9 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf, * Both hostname check and SNI require SSLSetPeerDomainName(). * Also: the verifyhost setting influences SNI usage */ if(conn_config->verifyhost) { - size_t snilen; - char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen); - if(!snihost) { - failf(data, "Failed to set SNI"); - return CURLE_SSL_CONNECT_ERROR; - } - err = SSLSetPeerDomainName(backend->ssl_ctx, snihost, snilen); + char *server = connssl->peer.sni? + connssl->peer.sni : connssl->peer.hostname; + err = SSLSetPeerDomainName(backend->ssl_ctx, server, strlen(server)); if(err != noErr) { failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d", @@ -2017,11 +2010,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf, return CURLE_SSL_CONNECT_ERROR; } - if((Curl_inet_pton(AF_INET, connssl->hostname, &addr)) - #ifdef ENABLE_IPV6 - || (Curl_inet_pton(AF_INET6, connssl->hostname, &addr)) - #endif - ) { + if(connssl->peer.is_ip_address) { infof(data, "WARNING: using IP address, SNI is being disabled by " "the OS."); } @@ -2079,7 +2068,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf, ssl_sessionid = aprintf("%s:%d:%d:%s:%d", ssl_cafile ? ssl_cafile : "(blob memory)", - verifypeer, conn_config->verifyhost, connssl->hostname, + verifypeer, conn_config->verifyhost, connssl->peer.hostname, connssl->port); ssl_sessionid_len = strlen(ssl_sessionid); @@ -2665,7 +2654,7 @@ check_handshake: host name: */ case errSSLHostNameMismatch: failf(data, "SSL certificate peer verification failed, the " - "certificate did not match \"%s\"\n", connssl->dispname); + "certificate did not match \"%s\"\n", connssl->peer.dispname); return CURLE_PEER_FAILED_VERIFICATION; /* Problem with SSL / TLS negotiation */ @@ -2757,7 +2746,7 @@ check_handshake: default: /* May also return codes listed in Security Framework Result Codes */ failf(data, "Unknown SSL protocol error in connection to %s:%d", - connssl->hostname, err); + connssl->peer.hostname, err); break; } return CURLE_SSL_CONNECT_ERROR; @@ -3415,7 +3404,6 @@ again: } *curlcode = CURLE_AGAIN; return -1L; - break; /* errSSLClosedGraceful - server gracefully shut down the SSL session errSSLClosedNoNotify - server hung up on us instead of sending a @@ -3425,7 +3413,6 @@ again: case errSSLClosedNoNotify: *curlcode = CURLE_OK; return 0; - break; /* The below is errSSLPeerAuthCompleted; it's not defined in Leopard's headers */ @@ -3445,7 +3432,6 @@ again: failf(data, "SSLRead() return error %d", err); *curlcode = CURLE_RECV_ERROR; return -1L; - break; } } return (ssize_t)processed; @@ -3483,7 +3469,7 @@ const struct Curl_ssl Curl_ssl_sectransp = { Curl_none_cert_status_request, /* cert_status_request */ sectransp_connect, /* connect */ sectransp_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_get_select_socks, /* getsock */ + Curl_ssl_adjust_pollset, /* adjust_pollset */ sectransp_get_internals, /* get_internals */ sectransp_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -3500,6 +3486,10 @@ const struct Curl_ssl Curl_ssl_sectransp = { sectransp_send, /* send data to encrypt */ }; +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #ifdef __clang__ #pragma clang diagnostic pop #endif diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c index 6a45ccb6d8..f37907c494 100644 --- a/libs/libcurl/src/vtls/vtls.c +++ b/libs/libcurl/src/vtls/vtls.c @@ -67,6 +67,7 @@ #include "warnless.h" #include "curl_base64.h" #include "curl_printf.h" +#include "inet_pton.h" #include "strdup.h" /* The last #include files should be: */ @@ -131,9 +132,6 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second) } #ifdef USE_SSL -static const struct alpn_spec ALPN_SPEC_H10 = { - { ALPN_HTTP_1_0 }, 1 -}; static const struct alpn_spec ALPN_SPEC_H11 = { { ALPN_HTTP_1_1 }, 1 }; @@ -147,51 +145,83 @@ static const struct alpn_spec *alpn_get_spec(int httpwant, bool use_alpn) { if(!use_alpn) return NULL; - if(httpwant == CURL_HTTP_VERSION_1_0) - return &ALPN_SPEC_H10; #ifdef USE_HTTP2 if(httpwant >= CURL_HTTP_VERSION_2) return &ALPN_SPEC_H2_H11; +#else + (void)httpwant; #endif + /* Use the ALPN protocol "http/1.1" for HTTP/1.x. + Avoid "http/1.0" because some servers don't support it. */ return &ALPN_SPEC_H11; } #endif /* USE_SSL */ -bool -Curl_ssl_config_matches(struct ssl_primary_config *data, - struct ssl_primary_config *needle) -{ - if((data->version == needle->version) && - (data->version_max == needle->version_max) && - (data->ssl_options == needle->ssl_options) && - (data->verifypeer == needle->verifypeer) && - (data->verifyhost == needle->verifyhost) && - (data->verifystatus == needle->verifystatus) && - blobcmp(data->cert_blob, needle->cert_blob) && - blobcmp(data->ca_info_blob, needle->ca_info_blob) && - blobcmp(data->issuercert_blob, needle->issuercert_blob) && - Curl_safecmp(data->CApath, needle->CApath) && - Curl_safecmp(data->CAfile, needle->CAfile) && - Curl_safecmp(data->issuercert, needle->issuercert) && - Curl_safecmp(data->clientcert, needle->clientcert) && +void Curl_ssl_easy_config_init(struct Curl_easy *data) +{ + /* + * libcurl 7.10 introduced SSL verification *by default*! This needs to be + * switched off unless wanted. + */ + data->set.ssl.primary.verifypeer = TRUE; + data->set.ssl.primary.verifyhost = TRUE; + data->set.ssl.primary.sessionid = TRUE; /* session ID caching by default */ +#ifndef CURL_DISABLE_PROXY + data->set.proxy_ssl = data->set.ssl; +#endif +} + +static bool +match_ssl_primary_config(struct Curl_easy *data, + struct ssl_primary_config *c1, + struct ssl_primary_config *c2) +{ + (void)data; + if((c1->version == c2->version) && + (c1->version_max == c2->version_max) && + (c1->ssl_options == c2->ssl_options) && + (c1->verifypeer == c2->verifypeer) && + (c1->verifyhost == c2->verifyhost) && + (c1->verifystatus == c2->verifystatus) && + blobcmp(c1->cert_blob, c2->cert_blob) && + blobcmp(c1->ca_info_blob, c2->ca_info_blob) && + blobcmp(c1->issuercert_blob, c2->issuercert_blob) && + Curl_safecmp(c1->CApath, c2->CApath) && + Curl_safecmp(c1->CAfile, c2->CAfile) && + Curl_safecmp(c1->issuercert, c2->issuercert) && + Curl_safecmp(c1->clientcert, c2->clientcert) && #ifdef USE_TLS_SRP - !Curl_timestrcmp(data->username, needle->username) && - !Curl_timestrcmp(data->password, needle->password) && + !Curl_timestrcmp(c1->username, c2->username) && + !Curl_timestrcmp(c1->password, c2->password) && #endif - strcasecompare(data->cipher_list, needle->cipher_list) && - strcasecompare(data->cipher_list13, needle->cipher_list13) && - strcasecompare(data->curves, needle->curves) && - strcasecompare(data->CRLfile, needle->CRLfile) && - strcasecompare(data->pinned_key, needle->pinned_key)) + strcasecompare(c1->cipher_list, c2->cipher_list) && + strcasecompare(c1->cipher_list13, c2->cipher_list13) && + strcasecompare(c1->curves, c2->curves) && + strcasecompare(c1->CRLfile, c2->CRLfile) && + strcasecompare(c1->pinned_key, c2->pinned_key)) return TRUE; return FALSE; } -bool -Curl_clone_primary_ssl_config(struct ssl_primary_config *source, - struct ssl_primary_config *dest) +bool Curl_ssl_conn_config_match(struct Curl_easy *data, + struct connectdata *candidate, + bool proxy) +{ +#ifndef CURL_DISABLE_PROXY + if(proxy) + return match_ssl_primary_config(data, &data->set.proxy_ssl.primary, + &candidate->proxy_ssl_config); +#else + (void)proxy; +#endif + return match_ssl_primary_config(data, &data->set.ssl.primary, + &candidate->ssl_config); +} + +static bool clone_ssl_primary_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest) { dest->version = source->version; dest->version_max = source->version_max; @@ -221,7 +251,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source, return TRUE; } -void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) +static void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) { Curl_safefree(sslc->CApath); Curl_safefree(sslc->CAfile); @@ -241,6 +271,111 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) #endif } +CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data) +{ + data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH]; + data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE]; + data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE]; + data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; + data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT]; + data->set.ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST]; + data->set.ssl.primary.cipher_list13 = + data->set.str[STRING_SSL_CIPHER13_LIST]; + data->set.ssl.primary.pinned_key = + data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT]; + data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO]; + data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES]; +#ifdef USE_TLS_SRP + data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME]; + data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD]; +#endif + data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE]; + data->set.ssl.key = data->set.str[STRING_KEY]; + data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE]; + data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD]; + data->set.ssl.primary.clientcert = data->set.str[STRING_CERT]; + data->set.ssl.key_blob = data->set.blobs[BLOB_KEY]; + +#ifndef CURL_DISABLE_PROXY + data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; + data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; + data->set.proxy_ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; + data->set.proxy_ssl.primary.cipher_list13 = + data->set.str[STRING_SSL_CIPHER13_LIST_PROXY]; + data->set.proxy_ssl.primary.pinned_key = + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]; + data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY]; + data->set.proxy_ssl.primary.ca_info_blob = + data->set.blobs[BLOB_CAINFO_PROXY]; + data->set.proxy_ssl.primary.issuercert = + data->set.str[STRING_SSL_ISSUERCERT_PROXY]; + data->set.proxy_ssl.primary.issuercert_blob = + data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY]; + data->set.proxy_ssl.primary.CRLfile = + data->set.str[STRING_SSL_CRLFILE_PROXY]; + data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; + data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; + data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; + data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY]; + data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; + data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY]; +#ifdef USE_TLS_SRP + data->set.proxy_ssl.primary.username = + data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; + data->set.proxy_ssl.primary.password = + data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; +#endif +#endif /* CURL_DISABLE_PROXY */ + + return CURLE_OK; +} + +CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data, + struct connectdata *conn) +{ + /* Clone "primary" SSL configurations from the esay handle to + * the connection. They are used for connection cache matching and + * probably outlive the easy handle */ + if(!clone_ssl_primary_config(&data->set.ssl.primary, &conn->ssl_config)) + return CURLE_OUT_OF_MEMORY; +#ifndef CURL_DISABLE_PROXY + if(!clone_ssl_primary_config(&data->set.proxy_ssl.primary, + &conn->proxy_ssl_config)) + return CURLE_OUT_OF_MEMORY; +#endif + return CURLE_OK; +} + +void Curl_ssl_conn_config_cleanup(struct connectdata *conn) +{ + Curl_free_primary_ssl_config(&conn->ssl_config); +#ifndef CURL_DISABLE_PROXY + Curl_free_primary_ssl_config(&conn->proxy_ssl_config); +#endif +} + +void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy) +{ + /* May be called on an easy that has no connection yet */ + if(data->conn) { + struct ssl_primary_config *src, *dest; +#ifndef CURL_DISABLE_PROXY + src = for_proxy? &data->set.proxy_ssl.primary : &data->set.ssl.primary; + dest = for_proxy? &data->conn->proxy_ssl_config : &data->conn->ssl_config; +#else + (void)for_proxy; + src = &data->set.ssl.primary; + dest = &data->conn->ssl_config; +#endif + dest->verifyhost = src->verifyhost; + dest->verifypeer = src->verifypeer; + dest->verifystatus = src->verifystatus; + } +} + #ifdef USE_SSL static int multissl_setup(const struct Curl_ssl *backend); #endif @@ -432,7 +567,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf, if(!check->sessionid) /* not session ID means blank entry */ continue; - if(strcasecompare(connssl->hostname, check->name) && + if(strcasecompare(connssl->peer.hostname, check->name) && ((!cf->conn->bits.conn_to_host && !check->conn_to_host) || (cf->conn->bits.conn_to_host && check->conn_to_host && strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) && @@ -441,7 +576,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf, cf->conn->conn_to_port == check->conn_to_port)) && (connssl->port == check->remote_port) && strcasecompare(cf->conn->handler->scheme, check->scheme) && - Curl_ssl_config_matches(conn_config, &check->ssl_config)) { + match_ssl_primary_config(data, conn_config, &check->ssl_config)) { /* yes, we have a session ID! */ (*general_age)++; /* increase general age */ check->age = *general_age; /* set this as used in this age */ @@ -456,7 +591,8 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf, DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d", no_match? "Didn't find": "Found", Curl_ssl_cf_is_proxy(cf) ? "proxy" : "host", - cf->conn->handler->scheme, connssl->hostname, connssl->port)); + cf->conn->handler->scheme, connssl->peer.hostname, + connssl->port)); return no_match; } @@ -532,7 +668,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf, (void)ssl_config; DEBUGASSERT(ssl_config->primary.sessionid); - clone_host = strdup(connssl->hostname); + clone_host = strdup(connssl->peer.hostname); if(!clone_host) return CURLE_OUT_OF_MEMORY; /* bail out */ @@ -590,7 +726,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf, store->remote_port = connssl->port; store->scheme = cf->conn->handler->scheme; - if(!Curl_clone_primary_ssl_config(conn_config, &store->ssl_config)) { + if(!clone_ssl_primary_config(conn_config, &store->ssl_config)) { Curl_free_primary_ssl_config(&store->ssl_config); store->sessionid = NULL; /* let caller free sessionid */ free(clone_host); @@ -629,22 +765,21 @@ void Curl_ssl_close_all(struct Curl_easy *data) Curl_ssl->close_all(data); } -int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) +void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, + struct easy_pollset *ps) { - struct ssl_connect_data *connssl = cf->ctx; - curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data); - - if(sock == CURL_SOCKET_BAD) - return GETSOCK_BLANK; - - if(connssl->connecting_state == ssl_connect_2_writing) { - /* we are only interested in writing */ - socks[0] = sock; - return GETSOCK_WRITESOCK(0); + if(!cf->connected) { + struct ssl_connect_data *connssl = cf->ctx; + curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data); + if(sock != CURL_SOCKET_BAD) { + if(connssl->connecting_state == ssl_connect_2_writing) { + Curl_pollset_set_out_only(data, ps, sock); + } + else { + Curl_pollset_set_in_only(data, ps, sock); + } + } } - socks[0] = sock; - return GETSOCK_READSOCK(0); } /* Selects an SSL crypto engine @@ -785,32 +920,6 @@ CURLcode Curl_ssl_random(struct Curl_easy *data, return Curl_ssl->random(data, entropy, length); } -/* - * Curl_ssl_snihost() converts the input host name to a suitable SNI name put - * in data->state.buffer. Returns a pointer to the name (or NULL if a problem) - * and stores the new length in 'olen'. - * - * SNI fields must not have any trailing dot and while RFC 6066 section 3 says - * the SNI field is case insensitive, browsers always send the data lowercase - * and subsequently there are numerous servers out there that don't work - * unless the name is lowercased. - */ - -char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen) -{ - size_t len = strlen(host); - if(len && (host[len-1] == '.')) - len--; - if(len >= data->set.buffer_size) - return NULL; - - Curl_strntolower(data->state.buffer, host, len); - data->state.buffer[len] = 0; - if(olen) - *olen = len; - return data->state.buffer; -} - /* * Public key pem to der conversion */ @@ -1156,13 +1265,13 @@ static CURLcode multissl_connect_nonblocking(struct Curl_cfilter *cf, return Curl_ssl->connect_nonblocking(cf, data, done); } -static int multissl_get_select_socks(struct Curl_cfilter *cf, +static void multissl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) + struct easy_pollset *ps) { if(multissl_setup(NULL)) - return 0; - return Curl_ssl->get_select_socks(cf, data, socks); + return; + Curl_ssl->adjust_pollset(cf, data, ps); } static void *multissl_get_internals(struct ssl_connect_data *connssl, @@ -1214,7 +1323,7 @@ static const struct Curl_ssl Curl_ssl_multi = { Curl_none_cert_status_request, /* cert_status_request */ multissl_connect, /* connect */ multissl_connect_nonblocking, /* connect_nonblocking */ - multissl_get_select_socks, /* getsock */ + multissl_adjust_pollset, /* adjust_pollset */ multissl_get_internals, /* get_internals */ multissl_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -1409,12 +1518,14 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name, #ifdef USE_SSL -static void free_hostname(struct ssl_connect_data *connssl) +void Curl_ssl_peer_cleanup(struct ssl_peer *peer) { - if(connssl->dispname != connssl->hostname) - free(connssl->dispname); - free(connssl->hostname); - connssl->hostname = connssl->dispname = NULL; + if(peer->dispname != peer->hostname) + free(peer->dispname); + free(peer->sni); + free(peer->hostname); + peer->hostname = peer->sni = peer->dispname = NULL; + peer->is_ip_address = FALSE; } static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) @@ -1423,12 +1534,26 @@ static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) if(connssl) { Curl_ssl->close(cf, data); connssl->state = ssl_connection_none; - free_hostname(connssl); + Curl_ssl_peer_cleanup(&connssl->peer); } cf->connected = FALSE; } -static CURLcode reinit_hostname(struct Curl_cfilter *cf) +static int is_ip_address(const char *hostname) +{ +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif + return (hostname && hostname[0] && (Curl_inet_pton(AF_INET, hostname, &addr) +#ifdef ENABLE_IPV6 + || Curl_inet_pton(AF_INET6, hostname, &addr) +#endif + )); +} + +CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf) { struct ssl_connect_data *connssl = cf->ctx; const char *ehostname, *edispname; @@ -1454,23 +1579,43 @@ static CURLcode reinit_hostname(struct Curl_cfilter *cf) } /* change if ehostname changed */ - if(ehostname && (!connssl->hostname - || strcmp(ehostname, connssl->hostname))) { - free_hostname(connssl); - connssl->hostname = strdup(ehostname); - if(!connssl->hostname) { - free_hostname(connssl); + if(ehostname && (!peer->hostname + || strcmp(ehostname, peer->hostname))) { + Curl_ssl_peer_cleanup(peer); + peer->hostname = strdup(ehostname); + if(!peer->hostname) { + Curl_ssl_peer_cleanup(peer); return CURLE_OUT_OF_MEMORY; } if(!edispname || !strcmp(ehostname, edispname)) - connssl->dispname = connssl->hostname; + peer->dispname = peer->hostname; else { - connssl->dispname = strdup(edispname); - if(!connssl->dispname) { - free_hostname(connssl); + peer->dispname = strdup(edispname); + if(!peer->dispname) { + Curl_ssl_peer_cleanup(peer); return CURLE_OUT_OF_MEMORY; } } + + peer->sni = NULL; + peer->is_ip_address = is_ip_address(peer->hostname)? TRUE : FALSE; + if(peer->hostname[0] && !peer->is_ip_address) { + /* not an IP address, normalize according to RCC 6066 ch. 3, + * max len of SNI is 2^16-1, no trailing dot */ + size_t len = strlen(peer->hostname); + if(len && (peer->hostname[len-1] == '.')) + len--; + if(len < USHRT_MAX) { + peer->sni = calloc(1, len + 1); + if(!peer->sni) { + Curl_ssl_peer_cleanup(peer); + return CURLE_OUT_OF_MEMORY; + } + Curl_strntolower(peer->sni, peer->hostname, len); + peer->sni[len] = 0; + } + } + } connssl->port = eport; return CURLE_OK; @@ -1525,7 +1670,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf, goto out; *done = FALSE; - result = reinit_hostname(cf); + result = Curl_ssl_peer_init(&connssl->peer, cf); if(result) goto out; @@ -1599,22 +1744,17 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf, return nread; } -static int ssl_cf_get_select_socks(struct Curl_cfilter *cf, +static void ssl_cf_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks) + struct easy_pollset *ps) { struct cf_call_data save; - int fds = GETSOCK_BLANK; - if(!cf->next->connected) { - fds = cf->next->cft->get_select_socks(cf->next, data, socks); - } - else if(!cf->connected) { + if(!cf->connected) { CF_DATA_SAVE(save, cf, data); - fds = Curl_ssl->get_select_socks(cf, data, socks); + Curl_ssl->adjust_pollset(cf, data, ps); CF_DATA_RESTORE(cf, save); } - return fds; } static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf, @@ -1705,7 +1845,7 @@ struct Curl_cftype Curl_cft_ssl = { ssl_cf_connect, ssl_cf_close, Curl_cf_def_get_host, - ssl_cf_get_select_socks, + ssl_cf_adjust_pollset, ssl_cf_data_pending, ssl_cf_send, ssl_cf_recv, @@ -1723,7 +1863,7 @@ struct Curl_cftype Curl_cft_ssl_proxy = { ssl_cf_connect, ssl_cf_close, Curl_cf_def_get_host, - ssl_cf_get_select_socks, + ssl_cf_adjust_pollset, ssl_cf_data_pending, ssl_cf_send, ssl_cf_recv, @@ -1837,6 +1977,16 @@ bool Curl_ssl_supports(struct Curl_easy *data, int option) return (Curl_ssl->supports & option)? TRUE : FALSE; } +static struct Curl_cfilter *get_ssl_filter(struct Curl_cfilter *cf) +{ + for(; cf; cf = cf->next) { + if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) + return cf; + } + return NULL; +} + + void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex, CURLINFO info, int n) { @@ -1844,8 +1994,8 @@ void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex, (void)n; if(data->conn) { struct Curl_cfilter *cf; - /* get first filter in chain, if any is present */ - cf = Curl_ssl_cf_get_ssl(data->conn->cfilter[sockindex]); + /* get first SSL filter in chain, if any is present */ + cf = get_ssl_filter(data->conn->cfilter[sockindex]); if(cf) { struct cf_call_data save; CF_DATA_SAVE(save, cf, data); @@ -1875,23 +2025,6 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data, return result; } -static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn, - int sockindex) -{ - struct Curl_cfilter *cf, *lowest_ssl_cf = NULL; - - for(cf = conn->cfilter[sockindex]; cf; cf = cf->next) { - if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) { - lowest_ssl_cf = cf; - if(cf->connected || (cf->next && cf->next->connected)) { - /* connected or about to start */ - return cf; - } - } - } - return lowest_ssl_cf; -} - bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf) { return (cf->cft == &Curl_cft_ssl_proxy); @@ -1908,17 +2041,6 @@ Curl_ssl_cf_get_config(struct Curl_cfilter *cf, struct Curl_easy *data) #endif } -struct ssl_config_data * -Curl_ssl_get_config(struct Curl_easy *data, int sockindex) -{ - struct Curl_cfilter *cf; - - (void)data; - DEBUGASSERT(data->conn); - cf = get_ssl_cf_engaged(data->conn, sockindex); - return cf? Curl_ssl_cf_get_config(cf, data) : &data->set.ssl; -} - struct ssl_primary_config * Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf) { @@ -1930,15 +2052,6 @@ Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf) #endif } -struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf) -{ - for(; cf; cf = cf->next) { - if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) - return cf; - } - return NULL; -} - CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf, const struct alpn_spec *spec) { @@ -2005,10 +2118,6 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, !memcmp(ALPN_HTTP_1_1, proto, ALPN_HTTP_1_1_LENGTH)) { *palpn = CURL_HTTP_VERSION_1_1; } - else if(proto_len == ALPN_HTTP_1_0_LENGTH && - !memcmp(ALPN_HTTP_1_0, proto, ALPN_HTTP_1_0_LENGTH)) { - *palpn = CURL_HTTP_VERSION_1_0; - } #ifdef USE_HTTP2 else if(proto_len == ALPN_H2_LENGTH && !memcmp(ALPN_H2, proto, ALPN_H2_LENGTH)) { diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h index 2ec6162296..111d17f32c 100644 --- a/libs/libcurl/src/vtls/vtls.h +++ b/libs/libcurl/src/vtls/vtls.h @@ -65,15 +65,54 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name, #define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */ #endif -char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen); -bool Curl_ssl_config_matches(struct ssl_primary_config *data, - struct ssl_primary_config *needle); -bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source, - struct ssl_primary_config *dest); -void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc); - curl_sslbackend Curl_ssl_backend(void); +/** + * Init ssl config for a new easy handle. + */ +void Curl_ssl_easy_config_init(struct Curl_easy *data); + +/** + * Init the `data->set.ssl` and `data->set.proxy_ssl` for + * connection matching use. + */ +CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data); + +/** + * Init SSL configs (main + proxy) for a new connection from the easy handle. + */ +CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data, + struct connectdata *conn); + +/** + * Free allocated resources in SSL configs (main + proxy) for + * the given connection. + */ +void Curl_ssl_conn_config_cleanup(struct connectdata *conn); + +/** + * Return TRUE iff SSL configuration from `conn` is functionally the + * same as the one on `candidate`. + * @param proxy match the proxy SSL config or the main one + */ +bool Curl_ssl_conn_config_match(struct Curl_easy *data, + struct connectdata *candidate, + bool proxy); + +/* Update certain connection SSL config flags after they have + * been changed on the easy handle. Will work for `verifypeer`, + * `verifyhost` and `verifystatus`. */ +void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy); + +/** + * Init SSL peer information for filter. Can be called repeatedly. + */ +CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf); +/** + * Free all allocated data and reset peer information. + */ +void Curl_ssl_peer_cleanup(struct ssl_peer *peer); + #ifdef USE_SSL int Curl_ssl_init(void); void Curl_ssl_cleanup(void); @@ -159,18 +198,6 @@ CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at, struct Curl_easy *data); #endif /* !CURL_DISABLE_PROXY */ -/** - * Get the SSL configuration that is used on the connection. - * This returns NULL if no SSL is configured. - * Otherwise it returns the config of the first (highest) one that is - * either connected, in handshake or about to start - * (e.g. all filters below it are connected). If SSL filters are present, - * but neither can start operating, return the config of the lowest one - * that will first come into effect when connecting. - */ -struct ssl_config_data *Curl_ssl_get_config(struct Curl_easy *data, - int sockindex); - /** * True iff the underlying SSL implementation supports the option. * Option is one of the defined SSLSUPP_* values. @@ -188,6 +215,18 @@ bool Curl_ssl_supports(struct Curl_easy *data, int ssl_option); void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex, CURLINFO info, int n); +/** + * Get the ssl_config_data in `data` that is relevant for cfilter `cf`. + */ +struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf, + struct Curl_easy *data); + +/** + * Get the primary config relevant for the filter from its connection. + */ +struct ssl_primary_config * + Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf); + extern struct Curl_cftype Curl_cft_ssl; extern struct Curl_cftype Curl_cft_ssl_proxy; @@ -209,8 +248,9 @@ extern struct Curl_cftype Curl_cft_ssl_proxy; #define Curl_ssl_get_internals(a,b,c,d) NULL #define Curl_ssl_supports(a,b) FALSE #define Curl_ssl_cfilter_add(a,b,c) CURLE_NOT_BUILT_IN -#define Curl_ssl_get_config(a,b) NULL #define Curl_ssl_cfilter_remove(a,b) CURLE_OK +#define Curl_ssl_cf_get_config(a,b) NULL +#define Curl_ssl_cf_get_primary_config(a) NULL #endif #endif /* HEADER_CURL_VTLS_H */ diff --git a/libs/libcurl/src/vtls/vtls_int.h b/libs/libcurl/src/vtls/vtls_int.h index 7a78a56cc7..858a0de8e7 100644 --- a/libs/libcurl/src/vtls/vtls_int.h +++ b/libs/libcurl/src/vtls/vtls_int.h @@ -32,8 +32,6 @@ /* see https://www.iana.org/assignments/tls-extensiontype-values/ */ #define ALPN_HTTP_1_1_LENGTH 8 #define ALPN_HTTP_1_1 "http/1.1" -#define ALPN_HTTP_1_0_LENGTH 8 -#define ALPN_HTTP_1_0 "http/1.0" #define ALPN_H2_LENGTH 2 #define ALPN_H2 "h2" #define ALPN_H3_LENGTH 2 @@ -70,14 +68,14 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, struct ssl_connect_data { ssl_connection_state state; ssl_connect_state connecting_state; - char *hostname; /* hostname for verification */ - char *dispname; /* display version of hostname */ + struct ssl_peer peer; const struct alpn_spec *alpn; /* ALPN to use or NULL for none */ void *backend; /* vtls backend specific props */ struct cf_call_data call_data; /* data handle used in current call */ struct curltime handshake_done; /* time when handshake finished */ int port; /* remote port at origin */ BIT(use_alpn); /* if ALPN shall be used in handshake */ + BIT(reused_session); /* session-ID was reused for this */ }; @@ -118,14 +116,11 @@ struct Curl_ssl { struct Curl_easy *data, bool *done); - /* If the SSL backend wants to read or write on this connection during a - handshake, set socks[0] to the connection's FIRSTSOCKET, and return - a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or - GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK. - Mandatory. */ - int (*get_select_socks)(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks); - + /* During handshake, adjust the pollset to include the socket + * for POLLOUT or POLLIN as needed. + * Mandatory. */ + void (*adjust_pollset)(struct Curl_cfilter *cf, struct Curl_easy *data, + struct easy_pollset *ps); void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); void (*close)(struct Curl_cfilter *cf, struct Curl_easy *data); void (*close_all)(struct Curl_easy *data); @@ -169,25 +164,8 @@ CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine); CURLcode Curl_none_set_engine_default(struct Curl_easy *data); struct curl_slist *Curl_none_engines_list(struct Curl_easy *data); bool Curl_none_false_start(void); -int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - curl_socket_t *socks); - -/** - * Get the ssl_config_data in `data` that is relevant for cfilter `cf`. - */ -struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf, - struct Curl_easy *data); - -/** - * Get the primary config relevant for the filter from its connection. - */ -struct ssl_primary_config * - Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf); - -/** - * Get the first SSL filter in the chain starting with `cf`, or NULL. - */ -struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf); +void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, + struct easy_pollset *ps); /** * Get the SSL filter below the given one or NULL if there is none. diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index fad1f7a88e..32681520a0 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -480,6 +480,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_SSL_CONNECT_ERROR; } #endif + default: break; } @@ -513,7 +514,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) } } -#ifndef NO_FILESYSTEM +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS) /* load native CA certificates */ if(ssl_config->native_ca_store) { if(wolfSSL_CTX_load_system_CA_certs(backend->ctx) != WOLFSSL_SUCCESS) { @@ -608,24 +609,12 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) SSL_VERIFY_NONE, NULL); #ifdef HAVE_SNI - if(sni) { - struct in_addr addr4; -#ifdef ENABLE_IPV6 - struct in6_addr addr6; -#endif - size_t hostname_len = strlen(connssl->hostname); - - if((hostname_len < USHRT_MAX) && - !Curl_inet_pton(AF_INET, connssl->hostname, &addr4) -#ifdef ENABLE_IPV6 - && !Curl_inet_pton(AF_INET6, connssl->hostname, &addr6) -#endif - ) { - size_t snilen; - char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen); - if(!snihost || - wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, snihost, - (unsigned short)snilen) != 1) { + if(sni && connssl->peer.sni) { + size_t sni_len = strlen(connssl->peer.sni); + if((sni_len < USHRT_MAX)) { + if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, + connssl->peer.sni, + (unsigned short)sni_len) != 1) { failf(data, "Failed to set SNI"); return CURLE_SSL_CONNECT_ERROR; } @@ -763,9 +752,9 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) /* Enable RFC2818 checks */ if(conn_config->verifyhost) { - char *snihost = Curl_ssl_snihost(data, connssl->hostname, NULL); - if(!snihost || - (wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE)) + char *snihost = connssl->peer.sni? + connssl->peer.sni : connssl->peer.hostname; + if(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE) return CURLE_SSL_CONNECT_ERROR; } @@ -813,7 +802,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) else if(DOMAIN_NAME_MISMATCH == detail) { #if 1 failf(data, " subject alt name(s) or common name do not match \"%s\"", - connssl->dispname); + connssl->peer.dispname); return CURLE_PEER_FAILED_VERIFICATION; #else /* When the wolfssl_check_domain_name() is used and you desire to @@ -1398,7 +1387,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = { Curl_none_cert_status_request, /* cert_status_request */ wolfssl_connect, /* connect */ wolfssl_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_get_select_socks, /* getsock */ + Curl_ssl_adjust_pollset, /* adjust_pollset */ wolfssl_get_internals, /* get_internals */ wolfssl_close, /* close_one */ Curl_none_close_all, /* close_all */ diff --git a/libs/libcurl/src/vtls/x509asn1.c b/libs/libcurl/src/vtls/x509asn1.c index a695922816..0ce971c7ba 100644 --- a/libs/libcurl/src/vtls/x509asn1.c +++ b/libs/libcurl/src/vtls/x509asn1.c @@ -1317,16 +1317,16 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, if(Curl_parseX509(&cert, beg, end)) return CURLE_PEER_FAILED_VERIFICATION; - hostlen = strlen(connssl->hostname); + hostlen = strlen(connssl->peer.hostname); /* Get the server IP address. */ #ifdef ENABLE_IPV6 if(cf->conn->bits.ipv6_ip && - Curl_inet_pton(AF_INET6, connssl->hostname, &addr)) + Curl_inet_pton(AF_INET6, connssl->peer.hostname, &addr)) addrlen = sizeof(struct in6_addr); else #endif - if(Curl_inet_pton(AF_INET, connssl->hostname, &addr)) + if(Curl_inet_pton(AF_INET, connssl->peer.hostname, &addr)) addrlen = sizeof(struct in_addr); /* Process extensions. */ @@ -1361,7 +1361,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, name.beg, name.end); if(len > 0 && (size_t)len == strlen(dnsname)) matched = Curl_cert_hostcheck(dnsname, (size_t)len, - connssl->hostname, hostlen); + connssl->peer.hostname, hostlen); else matched = 0; free(dnsname); @@ -1421,7 +1421,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */ failf(data, "SSL: illegal cert name field"); else if(Curl_cert_hostcheck((const char *) dnsname, - len, connssl->hostname, hostlen)) { + len, connssl->peer.hostname, hostlen)) { infof(data, " common name: %s (matched)", dnsname); free(dnsname); return CURLE_OK; diff --git a/libs/libcurl/src/warnless.c b/libs/libcurl/src/warnless.c index b28197d6cf..0fc4c268b2 100644 --- a/libs/libcurl/src/warnless.c +++ b/libs/libcurl/src/warnless.c @@ -37,7 +37,7 @@ #include "warnless.h" -#ifdef WIN32 +#ifdef _WIN32 #undef read #undef write #endif @@ -367,7 +367,7 @@ curl_socket_t curlx_sitosk(int i) #endif /* USE_WINSOCK */ -#if defined(WIN32) +#if defined(_WIN32) ssize_t curlx_read(int fd, void *buf, size_t count) { @@ -379,8 +379,8 @@ ssize_t curlx_write(int fd, const void *buf, size_t count) return (ssize_t)write(fd, buf, curlx_uztoui(count)); } -/* Ensure that warnless.h continues to have an effect in "unity" builds. */ -#undef HEADER_CURL_WARNLESS_H - -#endif /* WIN32 */ +#endif /* _WIN32 */ +/* Ensure that warnless.h redefinitions continue to have an effect + in "unity" builds. */ +#undef HEADER_CURL_WARNLESS_H_REDEFS diff --git a/libs/libcurl/src/warnless.h b/libs/libcurl/src/warnless.h index 02301db792..7fa00af36c 100644 --- a/libs/libcurl/src/warnless.h +++ b/libs/libcurl/src/warnless.h @@ -69,18 +69,13 @@ curl_socket_t curlx_sitosk(int i); #endif /* USE_WINSOCK */ -#if defined(WIN32) +#if defined(_WIN32) ssize_t curlx_read(int fd, void *buf, size_t count); ssize_t curlx_write(int fd, const void *buf, size_t count); -#undef read -#define read(fd, buf, count) curlx_read(fd, buf, count) -#undef write -#define write(fd, buf, count) curlx_write(fd, buf, count) - -#endif /* WIN32 */ +#endif /* _WIN32 */ #if defined(__INTEL_COMPILER) && defined(__unix__) @@ -97,3 +92,15 @@ unsigned short curlx_ntohs(unsigned short usnum); #endif /* __INTEL_COMPILER && __unix__ */ #endif /* HEADER_CURL_WARNLESS_H */ + +#ifndef HEADER_CURL_WARNLESS_H_REDEFS +#define HEADER_CURL_WARNLESS_H_REDEFS + +#if defined(_WIN32) +#undef read +#define read(fd, buf, count) curlx_read(fd, buf, count) +#undef write +#define write(fd, buf, count) curlx_write(fd, buf, count) +#endif + +#endif /* HEADER_CURL_WARNLESS_H_REDEFS */ diff --git a/libs/libcurl/src/ws.c b/libs/libcurl/src/ws.c index 41eb5d526d..5c8db777f1 100644 --- a/libs/libcurl/src/ws.c +++ b/libs/libcurl/src/ws.c @@ -274,8 +274,8 @@ static CURLcode ws_dec_pass_payload(struct ws_decoder *dec, dec->payload_offset += (curl_off_t)nwritten; remain = dec->payload_len - dec->payload_offset; /* infof(data, "WS-DEC: passed %zd bytes payload, %" - CURL_FORMAT_CURL_OFF_T " remain", - nwritten, remain); */ + CURL_FORMAT_CURL_OFF_T " remain", + nwritten, remain); */ } return remain? CURLE_AGAIN : CURLE_OK; @@ -925,8 +925,8 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer, *metap = &ws->frame; *nread = ws->frame.len; /* infof(data, "curl_ws_recv(len=%zu) -> %zu bytes (frame at %" - CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)", - buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */ + CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)", + buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */ return CURLE_OK; } -- cgit v1.2.3