diff options
Diffstat (limited to 'libs/libcurl')
116 files changed, 6136 insertions, 4636 deletions
diff --git a/libs/libcurl/docs/CHANGES b/libs/libcurl/docs/CHANGES index 3842d916a4..f77f0a9e13 100644 --- a/libs/libcurl/docs/CHANGES +++ b/libs/libcurl/docs/CHANGES @@ -6,6 +6,3277 @@ Changelog +Version 7.80.0 (10 Nov 2021) + +Daniel Stenberg (10 Nov 2021) +- RELEASE-NOTES: synced + + for curl 7.80.0 + +- THANKS: add contributors from the 7.80.0 cycle + +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: advertise h3 as well as h3-29 + + Advertise h3 as well as h3-29 since some servers out there require h3 + for QUIC v1. + + Closes #7979 + +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: use QUIC v1 consistently + + Since we switched to v1 quic_transport_parameters codepoint in #7960 + with quictls, lets use QUIC v1 consistently. + + Closes #7979 + +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: compile with the latest nghttp3 + + Closes #7978 + +Marc Hoersken (9 Nov 2021) +- tests: add Schannel-specific tests and disable unsupported ones + + Adds Schannel variants of SSLpinning tests that include the option + --ssl-revoke-best-effort to ignore certificate revocation check + failures which is required due to our custom test CA certificate. + + Disable the original variants if the Schannel backend is enabled. + + Also skip all IDN tests which are broken while using an msys shell. + + This is a step to simplify test exclusions for Windows and MinGW. + + Reviewed-by: Jay Satiro + Reviewed-by: Marcel Raad + Reviewed-by: Daniel Stenberg + Closes #7968 + +Daniel Stenberg (8 Nov 2021) +- docs: NAME fixes in easy option man pages + + Closes #7975 + +- [Roger Young brought this change] + + ftp: make the MKD retry to retry once per directory + + Reported-by: Roger Young + Fixes #7967 + Closes #7976 + +- tool_operate: reorder code to avoid compiler warning + + tool_operate.c(889) : warning C4701: potentially uninitialized local + variable 'per' use + + Follow-up to cc71d352651a0d95 + Reported-by: Marc Hörsken + Bug: https://github.com/curl/curl/pull/7922#issuecomment-963042676 + Closes #7971 + +- curl_easy_perform.3: add a para about recv and send data + + Reported-by: Godwin Stewart + Fixes #7973 + Closes #7974 + +- tool_operate: fclose stream only if fopened + + Fixes torture test failures + Follow-up to cc71d352651 + + Closes #7972 + +- libcurl-easy.3: language polish + +- limit-rate.d: this is average over several seconds + + Closes #7970 + +- docs: reduce/avoid English contractions + + You're => You are + Hasn't => Has not + Doesn't => Does not + Don't => Do not + You'll => You will + etc + + Closes #7930 + +- tool_operate: fix torture leaks with etags + + Spotted by torture testing 343 344 345 347. + + Follow-up from cc71d352651a0 + Pointed-out-by: Dan Fandrich + + Closes #7969 + +- [Amaury Denoyelle brought this change] + + ngtcp2: support latest QUIC TLS RFC9001 + + QUIC Transport Parameters Extension has been changed between draft-29 + and latest RFC9001. Most notably, its identifier has been updated from + 0xffa5 to 0x0039. The version is selected through the QUIC TLS library + via the legacy codepoint. + + Disable the usage of legacy codepoint in curl to switch to latest + RFC9001. This is required to be able to keep up with latest QUIC + implementations. + + Acked-by: Tatsuhiro Tsujikawa + Closes #7960 + +- test1173: make manpage-syntax.pl spot \n errors in examples + +- man pages: fix backslash-n in examples + + ... to be proper backslash-backslash-n sequences to render nicely in man + and on website. + + Follow-up to 24155569d8a + Reported-by: Sergey Markelov + + Fixes https://github.com/curl/curl-www/issues/163 + Closes #7962 + +- scripts/release-notes.pl: use out of repo links verbatim in refs + +- tool_operate: a failed etag save now only fails that transfer + + When failing to create the output file for saving an etag, only fail + that particular single transfer and allow others to follow. + + In a serial transfer setup, if no transfer at all is done due to them + all being skipped because of this error, curl will output an error + message and return exit code 26. + + Added test 369 and 370 to verify. + + Reported-by: Earnestly on github + Ref: #7942 + Closes #7945 + +- [Kevin Burke brought this change] + + .github: retry macos "brew install" command on failure + + Previously we saw errors attempting to run "brew install", see + https://github.com/curl/curl/runs/4095721123?check_suite_focus=true for + an example, since this command is idempotent, it is safe to run again. + + Closes #7955 + +- CURLOPT_ALTSVC_CTRL.3: mention conn reuse is preferred + + Ref: https://github.com/curl/curl/discussions/7954 + + Closes #7957 + +- RELEASE-NOTES: synced + +- zuul: pin the quiche build to use an older cmake-rs + + The latest cmake-rs assumes cmake's --parallel works. That was added in + cmake 3.12, but a lot of our CI builds run on Ubuntu Bionic which only + has cmake 3.10. + + Fixes #7927 + Closes #7952 + +- [Marc Hoersken brought this change] + + Revert "src/tool_filetime: disable -Wformat on mingw for this file" + + This reverts commit 7c88fe375b15c44d77bccc9ab733b8069d228e6f. + + Follow up to #6535 as the pragma is obsolete with warnf + + Closes #7941 + +Jay Satiro (2 Nov 2021) +- schannel: fix memory leak due to failed SSL connection + + - Call schannel_shutdown if the SSL connection fails. + + Prior to this change schannel_shutdown (which shuts down the SSL + connection as well as memory cleanup) was not called when the SSL + connection failed (eg due to failed handshake). + + Co-authored-by: Gisle Vanem + + Fixes https://github.com/curl/curl/issues/7877 + Closes https://github.com/curl/curl/pull/7878 + +Daniel Stenberg (2 Nov 2021) +- Curl_updateconninfo: store addresses for QUIC connections too + + So that CURLINFO_PRIMARY_IP etc work for HTTP/3 like for other HTTP + versions. + + Reported-by: Jerome Mao + Fixes #7939 + Closes #7944 + +- [Sergio Durigan Junior brought this change] + + curl.1: fix typos in the manpage + + s/transfering/transferring/ + s/transfered/transferred/ + + Signed-off-by: Sergio Durigan Junior <sergiodj@sergiodj.net> + Closes #7937 + +Marc Hoersken (1 Nov 2021) +- tests/smbserver.py: fix compatibility with impacket 0.9.23+ + + impacket now performs sanity checks if the requested and to + be served file path actually is inside the real share path. + + Ref: https://github.com/SecureAuthCorp/impacket/pull/1066 + + Fixes #7924 + Closes #7935 + +Daniel Stenberg (1 Nov 2021) +- docs: reduce use of "very" + + "Very" should be avoided in most texts. If intensifiers are needed, try + find better words instead. + + Closes #7936 + +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: specify the missing required callback functions + + Closes #7929 + +- CURLOPT_[PROXY]_SSL_CIPHER_LIST.3: bold instead of quote + + Bold the example ciphers instead of using single quotes, which then also + avoids the problem of how to use single quotes when first in a line. + + Also rephrased the pages a little. + + Reported-by: Sergio Durigan Junior + Ref: #7928 + Closes #7934 + +- gen.pl: replace leading single quotes with \(aq + + ... and allow single quotes to be used "normally" in the .d files. + + Makes the output curl.1 use better nroff. + + Reported-by: Sergio Durigan Junior + Ref: #7928 + Closes #7933 + +Marc Hoersken (1 Nov 2021) +- tests: kill some test servers afterwards to avoid locked logfiles + + Reviewed-by: Daniel Stenberg + Closes #7925 + +Daniel Stenberg (1 Nov 2021) +- smooth-gtk-thread.c: enhance the mutex lock use + + Reported-by: ryancaicse on github + Fixes #7926 + Closes #7931 + +Marc Hoersken (31 Oct 2021) +- CI/runtests.pl: restore -u flag, but remove it from CI runs + + This makes it possible to use -u again for local testing, + but removes the flag from CI config files and make targets. + + Reviewed-by: Daniel Stenberg + + Partially reverts #7841 + Closes #7921 + +Daniel Stenberg (29 Oct 2021) +- [Jonathan Cardoso Machado brought this change] + + CURLOPT_HSTSWRITEFUNCTION.3: using CURLOPT_HSTS_CTRL is required + + Closes #7923 + +- [Axel Morawietz brought this change] + + imap: display quota information + + Show response to "GETQUOTAROOT INBOX" command. + + Closes #6973 + +- RELEASE-NOTES: synced + +- [Boris Rasin brought this change] + + cmake: fix error getting LOCATION property on non-imported target + + Closes #7885 + +- [x2018 brought this change] + + url: check the return value of curl_url() + + Closes #7917 + +- [Roy Li brought this change] + + configure.ac: replace krb5-config with pkg-config + + The rationale is that custom *-config tools don't work well when + cross-compiling or using sysroots (such as when using Yocto project) and + require custom fixing for each of them; pkg-config on the other hand + works similarly everywhere. + + Signed-off-by: Roy Li <rongqing.li@windriver.com> + Signed-off-by: Alexander Kanavin <alex@linutronix.de> + + Closes #7916 + +- test1160: edited to work with hyper + + Closes #7912 + +- data/DISABLED: enable tests that now work with hyper + + Closes #7911 + +- test559: add 'HTTP' in keywords + + Makes it run fine with hyper + + Closes #7911 + +- test552: updated to work with hyper + + Closes #7911 + +Marc Hoersken (27 Oct 2021) +- github: fix incomplete permission to label PRs for Hacktoberfest + + Unfortunately the GitHub API requires a token with write permission + for both issues and pull-requests to edit labels on even just PRs. + + Follow up to #7897 + +Daniel Stenberg (27 Oct 2021) +- opt-manpages: use 'Added in' instead of 'Since' + + Closes #7913 + +Marc Hoersken (27 Oct 2021) +- github: fix missing permission to label PRs for Hacktoberfest + + Follow up to #7897 + + Test references to see if permissions are now sufficient: + + Closes #7832 + Closes #7897 + +- CI: more use of test-ci make target and verbose output + + Replace test-nonflaky with test-ci and enable verbose output + in all remaining CIs except Zuul which is customized a lot. + + Reviewed-by: Daniel Stenberg + Reviewed-by: Jay Satiro + + Follow up to #7785 + Closes #7832 + +- github: add support for Hacktoberfest using labels + + Automatically add hacktoberfest-accepted label to PRs opened between + September 30th and November 1st once a commit with a close reference + to it is pushed onto the master branch. + + With this workflow we can participate in Hacktoberfest while not + relying on GitHub to identify PRs as merged due to our rebasing. + + Requires hacktoberfest-accepted labels to exist for PRs on the + participating repository. Also requires hacktoberfest topic on + the participating repository to avoid applying to forked repos. + + Reviewed-by: Daniel Stenberg + + Fixes #7865 + Closes #7897 + +Daniel Stenberg (27 Oct 2021) +- http: reject HTTP response codes < 100 + + ... which then also includes negative ones as test 1430 uses. + + This makes native + hyper backend act identically on this and therefore + test 1430 can now be enabled when building with hyper. Adjust test 1431 + as well. + + Closes #7909 + +- [Kerem Kat brought this change] + + docs: fix typo in CURLOPT_TRAILERFUNCTION example + + Closes #7910 + +- docs/HYPER: remove some remaining issues, add HTTP/0.9 limitation + +- configure: when hyper is selected, deselect nghttp2 + + Closes #7908 + +- [Patrick Monnerat brought this change] + + sendf: accept zero-length data in Curl_client_write() + + Historically, Curl_client_write() used a length value of 0 as a marker + for a null-terminated data string. This feature has been removed in + commit f4b85d2. To detect leftover uses of the feature, a DEBUGASSERT + statement rejecting a length with value 0 was introduced, effectively + precluding use of this function with zero-length data. + + The current commit removes the DEBUGASSERT and makes the function to + return immediately if length is 0. + + A direct effect is to fix trying to output a zero-length distinguished + name in openldap. + + Another DEBUGASSERT statement is also rephrased for better readability. + + Closes #7898 + +- hyper: disable test 1294 since hyper doesn't allow such crazy headers + + Closes #7905 + +- c-hyper: make CURLOPT_SUPPRESS_CONNECT_HEADERS work + + Verified by the enabled test 1288 + + Closes #7905 + +- test1287: make work on hyper + + Closes #7905 + +- test1266/1267: disabled on hyper: no HTTP/0.9 support + + Closes #7905 + +Viktor Szakats (25 Oct 2021) +- Makefile.m32: fix to not require OpenSSL with -libssh2 or -rtmp options + + Previously, -libssh2/-rtmp options assumed that OpenSSL is also enabled + (and then failed with an error when not finding expected OpenSSL headers), + but this isn't necessarly true, e.g. when building both libssh2 and curl + against Schannel. This patch makes sure to only enable the OpenSSL backend + with -libssh2/-rtmp, when there was no SSL option explicitly selected. + + - Re-implement the logic as a single block of script. + - Also fix an indentation while there. + + Assisted-by: Jay Satiro + + Closes #7895 + +Daniel Stenberg (25 Oct 2021) +- docs: consistent use of "Added in" + + Make them all say "Added in [version]" without using 'curl' or 'libcurl' + in that phrase. + +- man pages: require all to use the same section header order + + This is the same order we already enforce among the options' man pages: + consistency is good. Add lots of previously missing examples. + + Adjust the manpage-syntax script for this purpose, used in test 1173. + + Closes #7904 + +- [David Hu brought this change] + + docs/HTTP3: improve build instructions + + 1. If writing to a system path if the command is not prefixed with + `sudo` it will cause a permission denied error + + 2. The patched OpenSSL branch has been updated to `openssl-3.0.0+quic` + to match upstream OpenSSL version. + + 3. We should not disable GnuTLS docs. + + Updated some commands about `make install` + + Closes #7842 + +- [Ricardo Martins brought this change] + + CMake: restore support for SecureTransport on iOS + + Restore support for building curl for iOS with SecureTransport enabled. + + Closes #7501 + +- tests: enable more tests with hyper + + Adjusted 1144, 1164 and 1176. + + Closes #7900 + +- docs: provide "RETURN VALUE" section for more func manpages + + Three were missing, one used a non-standard name for the header. + + Closes #7902 + +Jay Satiro (25 Oct 2021) +- curl_multi_socket_action.3: add a "RETURN VALUE" section + + .. because it may not be immediately clear to the user what + curl_multi_socket_action returns. + + Ref: https://curl.se/mail/lib-2021-10/0035.html + + Closes https://github.com/curl/curl/pull/7901 + +Daniel Stenberg (24 Oct 2021) +- RELEASE-NOTES: synced + +- [Samuel Henrique brought this change] + + tests: use python3 in test 1451 + + This is a continuation of commit ec91b5a69000bea0794bbb3 in which + changing this test was missed. There are no other python2 leftovers + now. + + Based on a Debian patch originally written by Alessandro Ghedini + <ghedo@debian.org> + + Closes #7899 + +- [Eddie Lumpkin brought this change] + + lib: fixing comment spelling typos in lib files + + Closes #7894 + Signed-off-by: ewlumpkin <ewlumpkin@gmail.com> + +- openssl: if verifypeer is not requested, skip the CA loading + + It was previously done mostly to show a match/non-match in the verbose + output even when verification was not asked for. This change skips the + loading of the CA certs unless verifypeer is set to save memory and CPU. + + Closes #7892 + +- curl-confopts.m4: remove --enable/disable-hidden-symbols + + These configure options have been saying "deprecated" since 9e24b9c7af + (April 2012). It was about time we remove them. + + Closes #7891 + +- c-hyper: don't abort CONNECT responses early when auth-in-progress + + ... and make sure to stop ignoring the body once the CONNECT is done. + + This should make test 206 work proper again and not be flaky. + + Closes #7889 + +- hyper: does not support disabling CURLOPT_HTTP_TRANSFER_DECODING + + Simply because hyper doesn't have this ability. Mentioned in docs now. + + Skip test 326 then + + Closes #7889 + +- test262: don't attempt with hyper + + This test verifies that curl works with binary zeroes in HTTP response + headers and hyper refuses such. They're not kosher http. + + Closes #7889 + +- c-hyper: make test 217 run + + Closes #7889 + +- DISABLED: enable test 209+213 for hyper + + Follow-up to 823d3ab855c + + Closes #7889 + +- test207: accept a different error code for hyper + + It returns HYPERE_UNEXPECTED_EOF for this case which we convert to the + somewhat generic CURLE_RECV_ERROR. + + Closes #7889 + +- [Érico Nogueira brought this change] + + INSTALL: update symbol hiding option + + --enable-hidden-symbols was deprecated in + 9e24b9c7afbcb81120af4cf3f6cdee49a06d8224. + + Closes #7890 + +- http_proxy: multiple CONNECT with hyper done better + + Enabled test 206 + + Closes #7888 + +- hyper: pass the CONNECT line to the debug callback + + Closes #7887 + +- mailmap: Malik Idrees Hasan Khan + +Jay Satiro (21 Oct 2021) +- [Malik Idrees Hasan Khan brought this change] + + build: fix typos + + Closes https://github.com/curl/curl/pull/7886 + +- URL-SYNTAX: add IMAP UID SEARCH example + + - Explain the difference between IMAP search via URL (which returns + message sequence numbers) and IMAP search via custom request (which + can return UID numbers if prefixed with UID, eg "UID SEARCH ..."). + + Bug: https://github.com/curl/curl/issues/7626 + Reported-by: orycho@users.noreply.github.com + + Ref: https://github.com/curl/curl/issues/2789 + + Closes https://github.com/curl/curl/pull/7881 + +Daniel Stenberg (20 Oct 2021) +- manpage: adjust the asterisk in some SYNOPSIS sections + + Closes #7884 + +- curl_multi_perform.3: polish wording + + - simplify the example by using curl_multi_poll + + - mention curl_multi_add_handle in the text + + - cut out the description of pre-7.20.0 return code behavior - that version + is now more than eleven years old and is basically no longer out there + + - adjust the "typical usage" to mention curl_multi_poll + + Closes #7883 + +- docs/THANKS: removed on request + +- FAQ: polish the explanation of libcurl + +- curl_easy_perform.3: minor wording tweak + +- [Erik Stenlund brought this change] + + mime: mention CURL_DISABLE_MIME in comment + + CURL_DISABLE_MIME is not mentioned in the comment describing the if else + preprocessor directive. + + Closes #7882 + +- tls: remove newline from three infof() calls + + Follow-up to e7416cf + + Reported-by: billionai on github + Fixes #7879 + Closes #7880 + +- RELEASE-NOTES: synced + +- curl_gssapi: fix build warnings by removing const + + Follow-up to 20e980f85b0ea6 + + In #7875 these inits were modified but I get two warnings that these new + typecasts are necessary for. + + Closes #7876 + +- [Bo Anderson brought this change] + + curl_gssapi: fix link error on macOS Monterey + + Fixes #7657 + Closes #7875 + +- test1185: verify checksrc + + Closes #7866 + +- checksrc: improve the SPACESEMICOLON error message + + and adjust the MULTISPACE one to use plural + + Closes #7866 + +- url: set "k->size" -1 at start of request + + The size of the transfer is unknown at that point. + + Fixes #7871 + Closes #7872 + +Daniel Gustafsson (18 Oct 2021) +- doh: remove experimental code for DoH with GET + + The code for sending DoH requests with GET was never enabled in a way + such that it could be used or tested. As there haven't been requests + for this feature, and since it at this is effectively dead, remove it + and favor reimplementing the feature in case anyone is interested. + + Closes #7870 + Reviewed-by: Daniel Stenberg <daniel@haxx.se> + +Daniel Stenberg (18 Oct 2021) +- cirrus: remove FreeBSD 11.4 from the matrix + + It has reached End-Of-Life and causes some LDAP CI issues. + + Closes #7869 + +- cirrus: switch to openldap24-client + + ... as it seems openldap-client doesn't exist anymore. + + Reported-by: Jay Satiro + Fixes #7868 + Closes #7869 + +- checksrc: ignore preprocessor lines + + In order to check the actual code better, checksrc now ignores + everything that look like preprocessor instructions. It also means + that code in macros are now longer checked. + + Note that some rules then still don't need to be followed when code is + exactly below a cpp instruction. + + Removes two checksrc exceptions we needed previously because of + preprocessor lines being checked. + + Reported-by: Marcel Raad + Fixes #7863 + Closes #7864 + +- urlapi: skip a strlen(), pass in zero + + ... to let curl_easy_escape() itself do the strlen. This avoids a (false + positive) Coverity warning and it avoids us having to store the strlen() + return value in an int variable. + + Reviewed-by: Daniel Gustafsson + Closes #7862 + +- misc: update copyright years + +- examples/htmltidy: correct wrong printf() use + + ... and update the includes to match how current htmltidy wants them + used. + + Reported-by: Stathis Kapnidis + Fixes #7860 + Closes #7861 + +Jay Satiro (15 Oct 2021) +- http: set content length earlier + + - Make content length (ie download size) accessible to the user in the + header callback, but only after all headers have been processed (ie + only in the final call to the header callback). + + Background: + + For a long time the content length could be retrieved in the header + callback via CURLINFO_CONTENT_LENGTH_DOWNLOAD_T as soon as it was parsed + by curl. + + Changes were made in 8a16e54 (precedes 7.79.0) to ignore content length + if any transfer encoding is used. A side effect of that was that + content length was not set by libcurl until after the header callback + was called the final time, because until all headers are processed it + cannot be determined if content length is valid. + + This change keeps the same intention --all headers must be processed-- + but now the content length is available before the final call to the + header function that indicates all headers have been processed (ie + a blank header). + + Bug: https://github.com/curl/curl/commit/8a16e54#r57374914 + Reported-by: sergio-nsk@users.noreply.github.com + + Co-authored-by: Daniel Stenberg + + Fixes https://github.com/curl/curl/issues/7804 + Closes https://github.com/curl/curl/pull/7803 + +Daniel Stenberg (15 Oct 2021) +- [Abhinav Singh brought this change] + + aws-sigv4: make signature work when post data is binary + + User sets the post fields size for binary data. Hence, we should not be + using strlen on it. + + Added test 1937 and 1938 to verify. + + Closes #7844 + +- [a1346054 brought this change] + + MacOSX-Framework: remove redundant ';' + + Closes #7859 + +- RELEASE-NOTES: synced + +- openssl: with OpenSSL 1.1.0+ a failed RAND_status means goaway + + One reason we know it can fail is if a provider is used that doesn't do + a proper job or is wrongly configured. + + Reported-by: Michael Baentsch + Fixes #7840 + Closes #7856 + +Marcel Raad (14 Oct 2021) +- [Ryan Mast brought this change] + + cmake: add CURL_ENABLE_SSL option and make CMAKE_USE_* SSL backend options depend on it + + Closes https://github.com/curl/curl/pull/7822 + +Daniel Stenberg (14 Oct 2021) +- http: remove assert that breaks hyper + + Reported-by: Jay Satiro + Fixes #7852 + Closes #7855 + +- http_proxy: fix one more result assign for hyper + + and remove the bad assert again, since it was run even with no error! + + Closes #7854 + +Jay Satiro (14 Oct 2021) +- sws: fix memory leak on exit + + - Free the allocated http request struct on cleanup. + + Prior to this change if sws was built with leak sanitizer it would + report a memory leak error during testing. + + Closes https://github.com/curl/curl/pull/7849 + +Daniel Stenberg (14 Oct 2021) +- c-hyper: make Curl_http propagate errors better + + Pass on better return codes when errors occur within Curl_http instead + of insisting that CURLE_OUT_OF_MEMORY is the only possible one. + + Pointed-out-by: Jay Satiro + Closes #7851 + +- http_proxy: make hyper CONNECT() return the correct error code + + For every 'goto error', make sure the result variable holds the error + code for what went wrong. + + Reported-by: Rafał Mikrut + Fixes #7825 + Closes #7846 + +- docs/Makefile.am: repair 'make html' + + by removing index.html which isn't around anymore + + Closes #7853 + +- [Борис Верховский brought this change] + + curl: correct grammar in generated libcurl code + + Closes #7802 + +- tests: disable test 2043 + + It uses revoked.badssl.com which now is expired and therefor this now + permafails. We should not use external sites for tests, this test should + be converted to use our own infra. + + Closes #7845 + +- runtests: split out ignored tests + + Report ignore tests separately from the actual fails. + + Don't exit non-zero if test servers couldn't get killed. + + Assisted-by: Jay Satiro + + Fixes #7818 + Closes #7841 + +- http2: make getsock not wait for write if there's no remote window + + While uploading, check for remote window availability in the getsock + function so that we don't wait for a writable socket if no data can be + sent. + + Reported-by: Steini2000 on github + Fixes #7821 + Closes #7839 + +- test368: verify dash is appended for "-r [num]" + + Follow-up to 8758a26f8878 + +- [Борис Верховский brought this change] + + curl: actually append "-" to --range without number only + + Closes #7837 + +- RELEASE-NOTES: synced + +- urlapi: URL decode percent-encoded host names + + The host name is stored decoded and can be encoded when used to extract + the full URL. By default when extracting the URL, the host name will not + be URL encoded to work as similar as possible as before. When not URL + encoding the host name, the '%' character will however still be encoded. + + Getting the URL with the CURLU_URLENCODE flag set will percent encode + the host name part. + + As a bonus, setting the host name part with curl_url_set() no longer + accepts a name that contains space, CR or LF. + + Test 1560 has been extended to verify percent encodings. + + Reported-by: Noam Moshe + Reported-by: Sharon Brizinov + Reported-by: Raul Onitza-Klugman + Reported-by: Kirill Efimov + Fixes #7830 + Closes #7834 + +Marc Hoersken (8 Oct 2021) +- CI/makefiles: introduce dedicated test target + + Make it easy to use the same set of test flags + throughout all current and future CI builds. + + Reviewed-by: Jay Satiro + + Follow up to #7690 + Closes #7785 + +Daniel Stenberg (8 Oct 2021) +- maketgz: redirect updatemanpages.pl output to /dev/null + +- CURLOPT_HTTPHEADER.3: add descripion for specific headers + + Settting Host: or Transfer-Encoding: chunked actually have special + meanings to libcurl. This change tries to document them + + Closes #7829 + +- c-hyper: use hyper_request_set_uri_parts to make h2 better + + and make sure to not send Host: over h2. + + Fixes #7679 + Reported-by: David Cook + Closes #7827 + +- [Michael Afanasiev brought this change] + + curl-openssl.m4: modify library order for openssl linking + + lcrypto may depend on lz, and configure corrently fails with when + statically linking as the order is "-lz -lcrypto". This commit switches + the order to "-lcrypto -lz". + + Closes #7826 + +Marcel Raad (7 Oct 2021) +- sha256: use high-level EVP interface for OpenSSL + + Available since OpenSSL 0.9.7. The low-level SHA256 interface is + deprecated in OpenSSL v3, and its usage was discouraged even before. + + Closes https://github.com/curl/curl/pull/7808 + +- curl_ntlm_core: use OpenSSL only if DES is available + + This selects another SSL backend then if available, or otherwise at + least gives a meaningful error message. + + Closes https://github.com/curl/curl/pull/7808 + +- md5: fix compilation with OpenSSL 3.0 API + + Only use OpenSSL's MD5 code if it's available. + + Also fix wolfSSL build with `NO_MD5`, in which case neither the + wolfSSL/OpenSSL implementation nor the fallback implementation was + used. + + Closes https://github.com/curl/curl/pull/7808 + +Daniel Stenberg (7 Oct 2021) +- print_category: printf %*s needs an int argument + + ... not a size_t! + + Detected by Coverity: CID 1492331. + Closes #7823 + +Jay Satiro (7 Oct 2021) +- version_win32: use actual version instead of manifested version + + - Use RtlVerifyVersionInfo instead of VerifyVersionInfo, when possible. + + Later versions of Windows have normal version functions that compare and + return versions based on the way the application is manifested, instead + of the actual version of Windows the application is running on. We + prefer the actual version of Windows so we'll now call the Rtl variant + of version functions (RtlVerifyVersionInfo) which does a proper + comparison of the actual version. + + Reported-by: Wyatt O'Day + + Ref: https://github.com/curl/curl/pull/7727 + + Fixes https://github.com/curl/curl/issues/7742 + Closes https://github.com/curl/curl/pull/7810 + +Daniel Stenberg (6 Oct 2021) +- RELEASE-NOTES: synced + +- http: fix Basic auth with empty name field in URL + + Add test 367 to verify. + + Reported-by: Rick Lane + Fixes #7819 + Closes #7820 + +- [Jeffrey Tolar brought this change] + + CURLOPT_MAXLIFETIME_CONN: maximum allowed lifetime for conn reuse + + ... and close connections that are too old instead of reusing them. + + By default, this behavior is disabled. + + Bug: https://curl.se/mail/lib-2021-09/0058.html + Closes #7751 + +Daniel Gustafsson (6 Oct 2021) +- docs/examples: add missing binaries to gitignore + + Commit f65d7889b added getreferrer, and commit ae8e11ed5 multi-legacy, + both of which missed adding .gitignore clauses for the built binaries. + + Closes #7817 + Reviewed-by: Daniel Stenberg <daniel@haxx.se> + +Daniel Stenberg (5 Oct 2021) +- [Josip Medved brought this change] + + HTTP3: fix the HTTP/3 Explained book link + + Closes #7813 + +- [Lucas Holt brought this change] + + misc: fix a few issues on MidnightBSD + + Closes #7812 + +Daniel Gustafsson (4 Oct 2021) +- [8U61ife brought this change] + + tool_main: fix typo in comment + + Closes: #7811 + Reviewed-by: Daniel Gustafsson <daniel@yesql.se> + +Daniel Stenberg (4 Oct 2021) +- [Ryan Mast brought this change] + + BINDINGS: URL updates + + For cpr, BBHTTP, Eiffel, Harbour, Haskell, Mono, and Rust + + Closes #7809 + +- scripts/delta: hide a git error message we don't care about + + fatal: path 'src/tool_listhelp.c' exists on disk, but not in [tag] + +- [Patrick Monnerat brought this change] + + sasl: binary messages + + Capabilities of sasl module are extended to exchange messages in binary + as an alternative to base64. + + If http authentication flags have been set, those are used as sasl + default preferred mechanisms. + + Closes #6930 + +- [Hayden Roche brought this change] + + wolfssl: use for SHA256, MD4, MD5, and setting DES odd parity + + Prior to this commit, OpenSSL could be used for all these functions, but + not wolfSSL. This commit makes it so wolfSSL will be used if USE_WOLFSSL + is defined. + + Closes #7806 + +- scripts/delta: count command line options in the new file + + ... which makes the shown delta number wrong until next release. + +- RELEASE-NOTES: synced + +- print_category: print help descriptions aligned + + Adjust the description position to make an aligned column when doing + help listings, which is more pleasing to the eye. + + Suggested-by: Gisle Vanem + Closes #7792 + +- lib/mk-ca-bundle.pl: skip certs passed Not Valid After date + + With this change applied, the now expired 'DST Root CA X3' cert will no + longer be included in the output. + + Details: https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021/ + + Closes #7801 + +- tool_listhelp: easier to generate with gen.pl + + tool_listhelp.c is now a separate file with only the command line --help + output, exactly as generated by gen.pl. This makes it easier to generate + updates according to what's in the docs/cmdline-opts docs. + + cd $srcroot/docs/cmdline-opts + ./gen.pl listhelp *.d > $srcroot/src/tool_listhelp.c + + With a configure build, this also works: + + make -C src listhelp + + Closes #7787 + +- [Anthony Hu brought this change] + + wolfssl: allow setting of groups/curves + + In particular, the quantum safe KEM and hybrid curves if wolfSSL is + built to support them. + + Closes #7728 + +- [Jan Mazur brought this change] + + connnect: use sysaddr_un fron sys/un.h or custom-defined for windows + + Closes #7737 + +Jay Satiro (30 Sep 2021) +- [Rikard Falkeborn brought this change] + + hostip: Move allocation to clarify there is no memleak + + By just glancing at the code, it looks like there is a memleak if the + call to Curl_inet_pton() fails. Looking closer, it is clear that the + call to Curl_inet_pton() can not fail, so the code will never leak + memory. However, we can make this obvious by moving the allocation + after the if-statement. + + Closes https://github.com/curl/curl/pull/7796 + +Daniel Stenberg (30 Sep 2021) +- gen.pl: make the output date format work better + + Follow-up to 15910dfd143dd + + The previous strftime format used didn't work correctly on Windows, so + change to %B %d %Y which today looks like "September 29 2021". + + Reported-by: Gisle Vanem + Bug: #7782 + Closes #7793 + +- typecheck-gcc.h: add CURLOPT_PREREQDATA awareness + + Follow-up to a517378de58358a + + To make test 1912 happy again + + Closes #7799 + +Marcel Raad (29 Sep 2021) +- configure: remove `HAVE_WINSOCK_H` definition + + It's not used anymore. + + Closes https://github.com/curl/curl/pull/7795 + +- CMake: remove `HAVE_WINSOCK_H` definition + + It's not used anymore. + + Closes https://github.com/curl/curl/pull/7795 + +- config: remove `HAVE_WINSOCK_H` definition + + It's not used anymore. + + Closes https://github.com/curl/curl/pull/7795 + +- lib: remove `HAVE_WINSOCK_H` usage + + WinSock v1 is not supported anymore. Exclusively use `HAVE_WINSOCK2_H` + instead. + + Closes https://github.com/curl/curl/pull/7795 + +Daniel Stenberg (29 Sep 2021) +- easyoptions: add the two new PRE* options + + Follow-up to a517378de58358a + + Also fix optiontable.pl to do the correct remainder on the entry. + + Reported-by: Gisle Vanem + Bug: https://github.com/curl/curl/commit/a517378de58358a85b7cfe9efecb56051268f629#commitcomment-57224830 + Closes #7791 + +- Revert "build: remove checks for WinSock 1" + + Due to CI issues + + This reverts commit c2ea04f92b00b6271627cb218647527b5a50f2fc. + + Closes #7790 + +Daniel Gustafsson (29 Sep 2021) +- lib: avoid fallthrough cases in switch statements + + Commit b5a434f7f0ee4d64857f8592eced5b9007d83620 inhibits the warning + on implicit fallthrough cases, since the current coding of indicating + fallthrough with comments is falling out of fashion with new compilers. + This attempts to make the issue smaller by rewriting fallthroughs to no + longer fallthrough, via either breaking the cases or turning switch + statements into if statements. + + lib/content_encoding.c: the fallthrough codepath is simply copied + into the case as it's a single line. + lib/http_ntlm.c: the fallthrough case skips a state in the state- + machine and fast-forwards to NTLMSTATE_LAST. Do this before the + switch statement instead to set up the states that we actually + want. + lib/http_proxy.c: the fallthrough is just falling into exiting the + switch statement which can be done easily enough in the case. + lib/mime.c: switch statement rewritten as if statement. + lib/pop3.c: the fallthrough case skips to the next state in the + statemachine, do this explicitly instead. + lib/urlapi.c: switch statement rewritten as if statement. + lib/vssh/wolfssh.c: the fallthrough cases fast-forwards the state + machine, do this by running another iteration of the switch + statement instead. + lib/vtls/gtls.c: switch statement rewritten as if statement. + lib/vtls/nss.c: the fallthrough codepath is simply copied into the + case as it's a single line. Also twiddle a comment to not be + inside a non-brace if statement. + + Closes: #7322 + See-also: #7295 + Reviewed-by: Daniel Stenberg <daniel@haxx.se> + +Marcel Raad (28 Sep 2021) +- config-win32ce: enable WinSock 2 + + WinSock 2.2 is supported by Windows CE .NET 4.1 (from 2002, out of + support since 2013). + + Ref: https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms899586(v=msdn.10) + + Closes https://github.com/curl/curl/pull/7778 + +- externalsocket: use WinSock 2.2 + + That's the only version we support. + + Closes https://github.com/curl/curl/pull/7778 + +- build: remove checks for WinSock 1 + + It's not supported anymore. + + Closes https://github.com/curl/curl/pull/7778 + +Daniel Stenberg (28 Sep 2021) +- scripts/copyright: .muse is .lift now + + And update 5 files with old copyright year range + +- cmdline-opts: made the 'Added:' field mandatory + + Since "too old" versions are no longer included in the generated man + page, this field is now mandatory so that it won't be forgotten and then + not included in the documentation. + + Closes #7786 + +- curl.1: remove mentions of really old version changes + + To make the man page more readable, this change removes all references + to changes in support/versions etc that happened before 7.30.0 from the + curl.1 output file. 7.30.0 was released on Apr 12 2013. This particular + limit is a bit arbitrary but was fairly easy to grep for. + + It is handled like this: the 'Added' keyword is only used in output if + it refers to 7.30.0 or later. All occurances of "(Added in $VERSION)" in + description will be stripped out if the mentioned $VERSION is from + before 7.30.0. It is therefore important that the "Added in..." + references are always written exactly like that - and on a single line, + not split over two. + + This change removes about 80 version number references from curl.1, down + to 138 from 218. + + Closes #7786 + +- RELEASE-NOTES: synced + +- tool_cb_prg: make resumed upload progress bar show better + + This is a regression that was *probably* injected in the larger progress + bar overhaul in 2018. + + Reported-by: beslick5 on github + Fixes #7760 + Closes #7777 + +- gen.pl: insert the current date and version in generated man page + + Reported-by: Gisle Vanem + Ref: #7780 + Closes #7782 + +- NTLM: use DES_set_key_unchecked with OpenSSL + + ... as the previously used function DES_set_key() will in some cases + reject using a key that it deems "weak" which will cause curl to + continue using the unitialized buffer content as key instead. + + Assisted-by: Harry Sintonen + Fixes #7779 + Closes #7781 + +Marc Hoersken (27 Sep 2021) +- CI: align make and test flags in various config files + + 1. Use Makefile target to run tests in autotools builds on AppVeyor. + 2. Disable testing of SCP protocol on native Windows environments. + 3. Remove redundant parameters -a -p from target test-nonflaky. + 4. Don't use -vc parameter which is reserved for debugging. + + Replaces #7591 + Closes #7690 + +Daniel Stenberg (27 Sep 2021) +- mailmap: unify Max! + +- [Max Dymond brought this change] + + CURLOPT_PREREQFUNCTION: add new callback + + Triggered before a request is made but after a connection is set up + + Changes: + + - callback: Update docs and callback for pre-request callback + - Add documentation for CURLOPT_PREREQDATA and CURLOPT_PREREQFUNCTION, + - Add redirect test and callback failure test + - Note that the function may be called multiple times on a redirection + - Disable new 2086 test due to Windows weirdness + + Closes #7477 + +- KNOWN_BUGS: HTTP/2 connections through HTTPS proxy frequently stall + + Closes #6936 + +- TODO: make configure use --cache-file more and better + + Closes #7753 + +- [Sergey Markelov brought this change] + + urlapi: support UNC paths in file: URLs on Windows + + - file://host.name/path/file.txt is a valid UNC path + \\host.name\path\files.txt to a non-local file transformed into URI + (RFC 8089 Appendix E.3) + + - UNC paths on other OSs must be smb: URLs + + Closes #7366 + +- [Gleb Ivanovsky brought this change] + + urlapi: add curl_url_strerror() + + Add curl_url_strerror() to convert CURLUcode into readable string and + facilitate easier troubleshooting in programs using URL API. + Extend CURLUcode with CURLU_LAST for iteration in unit tests. + Update man pages with a mention of new function. + Update example code and tests with new functionality where it fits. + + Closes #7605 + +- RELEASE-NOTES: synced + +- [Mats Lindestam brought this change] + + libssh2: add SHA256 fingerprint support + + Added support for SHA256 fingerprint in command line curl and in + libcurl. + + Closes #7646 + +- libcurl.rc: switch out the copyright symbol for plain ASCII + + Reported-by: Vitaly Varyvdin + Assisted-by: Viktor Szakats + Fixes #7765 + Closes #7776 + +- [Jun-ya Kato brought this change] + + ngtcp2: fix QUIC transport parameter version + + fix inappropriate version setting for QUIC transport parameters. + this patch keeps curl with ngtcp2 uses QUIC draft version (h3-29). + + Closes #7771 + +- examples/imap-append: fix end-of-data check + + Reported-by: Alexander Chuykov + Fixes #7774 + Closes #7775 + +Michael Kaufmann (24 Sep 2021) +- vtls: Fix a memory leak if an SSL session cannot be added to the cache + + On connection shutdown, a new TLS session ticket may arrive after the + SSL session cache has already been destructed. In this case, the new + SSL session cannot be added to the SSL session cache. + + The callers of Curl_ssl_addsessionid() need to know whether the SSL + session has been added to the cache. If it has not been added, the + reference counter of the SSL session must not be incremented, or memory + used by the SSL session must be freed. This is now possible with the new + output parameter "added" of Curl_ssl_addsessionid(). + + Fixes #7683 + Closes #7752 + +Daniel Stenberg (24 Sep 2021) +- [Momoka Yamamoto brought this change] + + HTTP3.md: use 'autoreconf -fi' instead of buildconf + + buildconf is not used since #5853 + + Closes #7746 + +- GIT-INFO: rephrase to adapt to s/buildconf/autoreconf + +- [h1zzz brought this change] + + llist: remove redundant code, branch will not be executed + + Closes #7770 + +- [tlahn brought this change] + + HTTP-COOKIES.md: remove duplicate 'each' + + Closes #7772 + +Jay Satiro (24 Sep 2021) +- [Joel Depooter brought this change] + + libssh2: Get the version at runtime if possible + + Previously this code used a compile time constant, meaning that libcurl + always reported the libssh2 version that libcurl was built with. This + could differ from the libssh2 version actually being used. The new code + uses the CURL_LIBSSH2_VERSION macro, which is defined in ssh.h. The + macro calls the libssh2_version function if it is available, otherwise + it falls back to the compile time version. + + Closes https://github.com/curl/curl/pull/7768 + +- [Joel Depooter brought this change] + + schannel: fix typo + + Closes https://github.com/curl/curl/pull/7769 + +Daniel Stenberg (23 Sep 2021) +- cmake: with OpenSSL, define OPENSSL_SUPPRESS_DEPRECATED + + To avoid the "... is deprecated" warnings brought by OpenSSL v3. + (We need to address the underlying code at some point of course.) + + Assisted-by: Jakub Zakrzewski + Closes #7767 + +- curl-openssl: pass argument to sed single-quoted + + ... instead of using an escaped double-quote. This is an attempt to make + this work better with ksh that otherwise would insist on a double + escape! + + Reported-by: Randall S. Becker + Fixes #7758 + Closes #7764 + +- RELEASE-NOTES: synced + + Bumped curlver to 7.80.0-dev + +- [a1346054 brought this change] + + misc: fix typos in docs and comments + + No user facing output from curl/libcurl is changed by this, just + comments. + + Closes #7747 + +- [Thomas M. DuBuisson brought this change] + + ci: update Lift config to match requirements of curl build + + Also renamed Muse -> Lift, the new tool name. + + Closes #7761 + +- [Rikard Falkeborn brought this change] + + cleanup: constify unmodified static structs + + Constify a number of static structs that are never modified. Make them + const to show this. + + Closes #7759 + +Version 7.79.1 (22 Sep 2021) + +Daniel Stenberg (22 Sep 2021) +- RELEASE-NOTES: synced + + curl 7.79.1 release + +- THANKS: added names from the 7.79.1 release + +- test897: verify delivery of IMAP post-body header content + + The "content" is delivered as "body" by curl, but the envelope continues + after the body and the rest of it should be delivered as header. + + The IMAP server can now get 'POSTFETCH' set to include more data to + include after the body and test 897 is done to verify that such "extra" + header data is in fact delivered by curl as header. + + Ref: #7284 but fails to reproduce the issue + + Closes #7748 + +- KNOWN_BUGS: connection migration doesn't work + + Closes #7695 + +- RELEASE-NOTES: synced + +- http: fix the broken >3 digit response code detection + + When the "reason phrase" in the HTTP status line starts with a digit, + that was treated as the forth response code digit and curl would claim + the response to be non-compliant. + + Added test 1466 to verify this case. + + Regression brought by 5dc594e44f73b17 + Reported-by: Glenn de boer + Fixes #7738 + Closes #7739 + +Jay Satiro (17 Sep 2021) +- strerror: use sys_errlist instead of strerror on Windows + + - Change Curl_strerror to use sys_errlist[errnum] instead of strerror to + retrieve the error message on Windows. + + Windows' strerror writes to a static buffer and is not thread-safe. + + Follow-up to 2f0bb86 which removed most instances of strerror in favor + of calling Curl_strerror (which calls strerror_r for other platforms). + + Ref: https://github.com/curl/curl/pull/7685 + Ref: https://github.com/curl/curl/commit/2f0bb86 + + Closes https://github.com/curl/curl/pull/7735 + +Daniel Stenberg (16 Sep 2021) +- dist: provide lib/.checksrc in the tarball + + So that debug builds work (checksrc really) + + Reported-by: Marcel Raad + Reported-by: tawmoto on github + Fixes #7733 + Closes #7734 + +- TODO: Improve documentation about fork safety + + Closes #6968 + +- hsts: CURLSTS_FAIL from hsts read callback should fail transfer + + ... and have CURLE_ABORTED_BY_CALLBACK returned. + + Extended test 1915 to verify. + + Reported-by: Jonathan Cardoso + Fixes #7726 + Closes #7729 + +- test1184: disable + + The test should be fine and it works for me repeated when run manually, + but clearly it causes CI failures and it needs more research. + + Reported-by: RiderALT on github + Fixes #7725 + Closes #7732 + +- Curl_http2_setup: don't change connection data on repeat invokes + + Regression from 3cb8a748670ab88c (releasde in 7.79.0). That change moved + transfer oriented inits to before the check but also erroneously moved a + few connection oriented ones, which causes problems. + + Reported-by: Evangelos Foutras + Fixes #7730 + Closes #7731 + +- RELEASE-NOTES: synced + + and bump to 7.79.1 + +Kamil Dudka (16 Sep 2021) +- tests/sshserver.pl: make it work with openssh-8.7p1 + + ... by not using options with no argument where an argument is required: + + === Start of file tests/log/ssh_server.log + curl_sshd_config line 6: no argument after keyword "DenyGroups" + curl_sshd_config line 7: no argument after keyword "AllowGroups" + curl_sshd_config line 10: Deprecated option AuthorizedKeysFile2 + curl_sshd_config line 29: Deprecated option KeyRegenerationInterval + curl_sshd_config line 39: Deprecated option RhostsRSAAuthentication + curl_sshd_config line 40: Deprecated option RSAAuthentication + curl_sshd_config line 41: Deprecated option ServerKeyBits + curl_sshd_config line 45: Deprecated option UseLogin + curl_sshd_config line 56: no argument after keyword "AcceptEnv" + curl_sshd_config: terminating, 3 bad configuration options + === End of file tests/log/ssh_server.log + + === Start of file log/sftp_server.log + curl_sftp_config line 33: Unsupported option "rhostsrsaauthentication" + curl_sftp_config line 34: Unsupported option "rsaauthentication" + curl_sftp_config line 52: no argument after keyword "sendenv" + curl_sftp_config: terminating, 1 bad configuration options + Connection closed. + Connection closed + === End of file log/sftp_server.log + + Closes #7724 + +Daniel Stenberg (15 Sep 2021) +- hsts: handle unlimited expiry + + When setting a blank expire string, meaning unlimited, curl would pass + TIME_T_MAX to getime_r() when creating the output, while on 64 bit + systems such a large value cannot be convetered to a tm struct making + curl to exit the loop with an error instead. It can't be converted + because the year it would represent doesn't fit in the 'int tm_year' + field! + + Starting now, unlimited expiry is instead handled differently by using a + human readable expiry date spelled out as "unlimited" instead of trying + to use a distant actual date. + + Test 1660 and 1915 have been updated to help verify this change. + + Reported-by: Jonathan Cardoso + Fixes #7720 + Closes #7721 + +- curl_multi_fdset: make FD_SET() not operate on sockets out of range + + The VALID_SOCK() macro was made to only check for FD_SETSIZE if curl was + built to use select(), even though the curl_multi_fdset() function + always and unconditionally uses FD_SET and needs the check. + + Reported-by: 0xee on github + Fixes #7718 + Closes #7719 + +- FAQ: add GOPHERS + curl works on data, not files + +Version 7.79.0 (14 Sep 2021) + +Daniel Stenberg (14 Sep 2021) +- RELEASE-NOTES: synced + + For the 7.79.0 release + +- THANKS: add contributors from 7.79.0 release cycle + +- FAQ: add two dev related questions + + 8.1 Why does curl use C89? + 8.2 Will curl be rewritten? + + Spell-checked-by: Paul Johnson + Closes #7715 + +- zuul.d/jobs: disable three tests for *-openssl-disable-proxy + + ... as they mysteriously seem to permfail without being related to + proxy. + + Closes #7714 + +- [Patrick Monnerat brought this change] + + ftp,imap,pop3,smtp: reject STARTTLS server response pipelining + + If a server pipelines future responses within the STARTTLS response, the + former are preserved in the pingpong cache across TLS negotiation and + used as responses to the encrypted commands. + + This fix detects pipelined STARTTLS responses and rejects them with an + error. + + CVE-2021-22947 + + Bug: https://curl.se/docs/CVE-2021-22947.html + +- [Patrick Monnerat brought this change] + + ftp,imap,pop3: do not ignore --ssl-reqd + + In imap and pop3, check if TLS is required even when capabilities + request has failed. + + In ftp, ignore preauthentication (230 status of server greeting) if TLS + is required. + + Bug: https://curl.se/docs/CVE-2021-22946.html + + CVE-2021-22946 + +- [z2_ on hackerone brought this change] + + mqtt: clear the leftovers pointer when sending succeeds + + CVE-2021-22945 + + Bug: https://curl.se/docs/CVE-2021-22945.html + +- zuul: bump the rustls job to use v0.7.2 + + ... and add -lm when using a rust library. + + Closes #7701 + +- RELEASE-PROCEDURE: add release dates from now to 8.0.0 in 2023 + +- SECURITY-PROCESS: tweak a little to match current practices + + Closes #7713 + +- http_proxy: fix the User-Agent inclusion in CONNECT + + It should not refer to the uagent string that is allocated and created + for the end server http request, as that pointer may be cleared on + subsequent CONNECT requests. + + Added test case 1184 to verify. + + Reported-by: T200proX7 on github + Fixes #7705 + Closes #7707 + +- Curl_hsts_loadcb: don't attempt to load if hsts wasn't inited + + Reported-by: Jonathan Cardoso + Fixes #7710 + Closes #7711 + +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: fix build with ngtcp2 and nghttp3 + + ngtcp2_conn_client_new and nghttp3_conn_client_new are now macros. + Check the wrapped functions instead. + + ngtcp2_stream_close callback now takes flags parameter. + + Closes #7709 + +- write-out.d: clarify size_download/upload + + They show the number of "body" bytes transfered. + Fixes #7702 + Closes #7706 + +- http2: Curl_http2_setup needs to init stream data in all invokes + + Thus function was written to avoid doing multiple connection data + initializations, which is fine, but since it also initiates stream + related data it is crucial that it doesn't skip those even if called + again for the same connection. Solved by moving the stream + initializations before the "doing-it-again" check. + + Reported-by: Inho Oh + Fixes #7630 + Closes #7692 + +- url: fix compiler warning in no-verbose builds + + Follow-up from 2f0bb864c12 + + Closes #7700 + +- non-ascii: fix build errors from strerror fix + + Follow-up to 2f0bb864c12 + + Closes #7697 + +- parse_args: redo the warnings for --remote-header-name combos + + ... to avoid the memory leak risk pointed out by scan-build. + + Follow-up from 7a3e981781d6c18a + + Closes #7698 + +- ngtcp2: adapt to new size defintions upstream + + Reviewed-by: Tatsuhiro Tsujikawa + Closes #7699 + +- rustls: add strerror.h include + + Follow-up to 2f0bb864c12 + +- docs: the security list is reached at security at curl.se now + + Also update the FAQ section a bit to encourage users to rather submit + security issues on hackerone than sending email. + + Closes #7689 + +Marc Hoersken (9 Sep 2021) +- runtests: add option -u to error on server unexpectedly alive + + Let's try to actually handle the server unexpectedly alive + case by first making them visible on CI builds as failures. + + This is needed to detect issues with killing of the test + servers completely including nested process chains with + multiple PIDs per test server (including bash and perl). + + On Windows/cygwin platforms this is especially helpful with + debugging PID mixups due to cygwin using its own PID space. + + Reviewed-by: Daniel Stenberg + Closes #7180 + +Daniel Stenberg (9 Sep 2021) +- opts docs: unify phrasing in NAME header + + - avoid writing "set ..." or "enable/disable ..." or "specify ..." + *All* options for curl_easy_setopt() are about setting or enabling + things and most of the existing options didn't use that way of + description. + + - start with lowercase letter, unless abbreviation. For consistency. + + - Some additional touch-ups + + Closes #7688 + +- strerror.h: remove the #include from files not using it + +- lib: don't use strerror() + + We have and provide Curl_strerror() internally for a reason: strerror() + is not necessarily thread-safe so we should always try to avoid it. + + Extended checksrc to warn for this, but feature the check disabled by + default and only enable it in lib/ + + Closes #7685 + +Daniel Gustafsson (8 Sep 2021) +- cirrus: Add FreeBSD 13.0 job and disable sanitizer build + + As alluded to the in the now removed comment, a 13.0 image became + available and is now ready to be used. + + The sanitizer builds were running on the 12.1 image which since has + been removed from the config, leaving the builds not running at all. + When enabled it turns out that they don't actually work due to very + long timeouts in executing the tests, so keep the disabled for now + but a bit more controlled. + + Closes #7592 + +Daniel Stenberg (8 Sep 2021) +- copyrights: update copyright year ranges + +- RELEASE-NOTES: synced + +- INTERNALS: c-ares has a new home: c-ares.org + +- docs: remove experimental mentions from HSTS and MQTT + + Reported-by: Jonathan Cardoso + Bug: https://github.com/curl/curl/pull/6700#issuecomment-913792863 + Closes #7681 + +- [Cao ZhenXiang brought this change] + + curl: add warning for incompatible parameters usage + + --continue-at - and --remote-header-name are known incompatible parameters + + Closes #7674 + +- [git-bruh brought this change] + + examples/*hiperfifo.c: fix calloc arguments to match function proto + + Closes #7678 + +- INTERNALS: bump c-ares requirement to 1.16.0 + + Since ba904db0705c93 we use ares_getaddrinfo, added in c-ares 1.16.0 + +- curl: stop retry if Retry-After: is longer than allowed + + If Retry-After: specifies a period that is longer than what fits within + --retry-max-time, then stop retrying immediately. + + Added test 366 to verify. + + Reported-by: Kari Pahula + Fixes #7675 + Closes #7676 + +- [Michał Antoniak brought this change] + + mbedtls: avoid using a large buffer on the stack + + Use dynamic memory allocation for the buffer used in checking "pinned + public key". The PUB_DER_MAX_BYTES parameter with default settings is + set to a value greater than 2kB. + + Co-authored-by: Daniel Stenberg + Closes #7586 + +- configure: make --disable-hsts work + + The AC_ARG_ENABLE() macro itself uses a variable called + 'enable_[option]', so when our script also used a variable with that + name for the purpose of storing what the user wants, it also + accidentally made it impossible to switch off the feature with + --disable-hsts. Fix this by renaming our variable. + + Reported-by: Michał Antoniak + Fixes #7669 + Closes #7672 + +Jay Satiro (5 Sep 2021) +- config.d: note that curlrc is used even when --config + + Bug: https://github.com/curl/curl/pull/7666#issuecomment-912214751 + Reported-by: Viktor Szakats + + Closes https://github.com/curl/curl/pull/7667 + +Daniel Stenberg (4 Sep 2021) +- RELEASE-NOTES: synced + +- test1173: check references to libcurl options + + ... that they refer to actual existing libcurl options. + + Reviewed-by: Daniel Gustafsson + Closes #7656 + +- CURLOPT_UNIX_SOCKET_PATH.3: remove nginx reference, add see also + + Closes #7656 + +- opt-docs: verify man page sections + order + + In every libcurl option man page there are now 8 mandatory sections that + must use the right name in the correct order and test 1173 verifies + this. Only 14 man pages needed adjustments. + + The sections and the order is as follows: + + - NAME + - SYNOPSIS + - DESCRIPTION + - PROTOCOLS + - EXAMPLE + - AVAILABILITY + - RETURN VALUE + - SEE ALSO + + Reviewed-by: Daniel Gustafsson + Closes #7656 + +- opt-docs: make sure all man pages have examples + + Extended manpage-syntax.pl (run by test 1173) to check that every man + page for a libcurl option has an EXAMPLE section that is more than two + lines. Then fixed all errors it found and added examples. + + Reviewed-by: Daniel Gustafsson + Closes #7656 + +- get.d: provide more useful examples + + Closes #7668 + +- page-header: add GOPHERS, simplify wording in the 1st para + + Closes #7665 + +- connect: get local port + ip also when reusing connections + + Regression. In d6a37c23a3c (7.75.0) we removed the duplicated storage + (connection + easy handle), so this info needs be extracted again even + for re-used connections. + + Add test 435 to verify + + Reported-by: Max Dymond + Fixes #7660 + Closes #7662 + +Marcel Raad (2 Sep 2021) +- multi: fix compiler warning with `CURL_DISABLE_WAKEUP` + + `use_wakeup` is unused in this case. + + Closes https://github.com/curl/curl/pull/7661 + +Daniel Stenberg (1 Sep 2021) +- tests: adjust the tftpd output to work with hyper mode + + By making them look less like http headers, the hyper mode "tweak" + doesn't interfere. + + Enable test 2002 and 2003 in hyper builds (and 1280 which is unrelated + but should be enabled). + + Closes #7658 + +Daniel Gustafsson (1 Sep 2021) +- [Gisle Vanem brought this change] + + openssl: annotate SSL3_MT_SUPPLEMENTAL_DATA + + This adds support for the previously unhandled supplemental data which + in -v output was printed like: + + TLSv1.2 (IN), TLS header, Unknown (23): + + These will now be printed with proper annotation: + + TLSv1.2 (OUT), TLS header, Supplemental data (23): + + Closes #7652 + Reviewed-by: Daniel Stenberg <daniel@haxx.se> + +Daniel Stenberg (1 Sep 2021) +- curl.1: provide examples for each option + + The file format for each option now features a "Example:" header that + can provide one or more examples that get rendered appropriately in the + output. All options MUST have at least one example or gen.pl complains + at build-time. + + This fix also does a few other minor format and consistency cleanups. + + Closes #7654 + +- progress: make trspeed avoid floats + + and compiler warnings for data conversions. + + Reported-by: Michał Antoniak + Fixes #7645 + Closes #7653 + +- test365: verify response with chunked AND Content-Length headers + +- http: ignore content-length if any transfer-encoding is used + + Fixes #7643 + Closes #7649 + +- RELEASE-NOTES: synced + +- Revert "http2: skip immediate parsing of payload following protocol switch" + + This reverts commit 455a63c66f188598275e87d32de2c4e8e26b80cb. + + Reported-by: Tk Xiong + Fixes #7633 + Closes #7648 + +- KNOWN_BUGS: HTTP/3 doesn't support client certs + + Closes #7625 + +- mailing lists: move from cool.haxx.se to lists.haxx.se + +- http_proxy: only wait for writable socket while sending request + + Otherwise it would wait socket writability even after the entire CONNECT + request has sent and make curl basically busy-loop while waiting for a + response to come back. + + The previous fix attempt in #7484 (c27a70a591a4) was inadequate. + + Reported-by: zloi-user on github + Reported-by: Oleguer Llopart + Fixes #7589 + Closes #7647 + +- http: disallow >3-digit response codes + + Make the built-in HTTP parser behave similar to hyper and reject any + HTTP response using more than 3 digits for the response code. + + Updated test 1432 accordingly. + Enabled test 1432 in the hyper builds. + + Closes #7641 + +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: stop buffering crypto data + + Stop buffering crypto data because libngtcp2 now buffers submitted + crypto data. + + Closes #7637 + +- test1280: CRLFify the response to please hyper + + Closes #7639 + +- tests: enable test 1129 for hyper builds + + Closes #7638 + +- curl: better error message when -O fails to get a good name + + Due to how this currently works internally, it needs a working initial + file name to store contents in, so it may still fail even with -J is + used (and thus accepting a name from content-disposition:) if the file + name part of the URL isn't "good enough". + + Fixes #7628 + Closes #7635 + +- curl_easy_setopt: tweak the string copy wording + + Reported-by: Yaobin Wen + Fixes #7632 + Closes #7634 + +- RELEASE-NOTES: synced + +- [Don J Olmstead brought this change] + + cmake: sync CURL_DISABLE options + + Adds the full listing of CURL_DISABLE options to the CMake build. Moves + all option code, except for CURL_DISABLE_OPENSSL_AUTO_LOA_CONFIG which + resides near OpenSSL configuration, to the same block of code. Also + sorts the options here and in the cmake config header. + + Additionally sorted the CURL-DISABLE listing and fixed the + CURL_DISABLE_POP3 option. + + Closes #7624 + +Jay Satiro (25 Aug 2021) +- KNOWN_BUGS: FTPS upload data loss with TLS 1.3 + + Bug: https://github.com/curl/curl/issues/6149 + Reported-by: Bylon2@users.noreply.github.com + + Closes https://github.com/curl/curl/pull/7623 + +Daniel Stenberg (24 Aug 2021) +- cmake: avoid poll() on macOS + + ... like we do in configure builds. Since poll() on macOS is not + reliable enough. + + Reported-by: marc-groundctl + Fixes #7595 + Closes #7619 + +- c-hyper: handle HTTP/1.1 => HTTP/1.0 downgrade on reused connection + + Enable test 1074 + + Closes #7617 + +- c-hyper: deal with Expect: 100-continue combined with POSTFIELDS + + Enable test 1130 and 1131 + + Closes #7616 + +- [a1346054 brought this change] + + tests: be explicit about using 'python3' instead of 'python' + + This fixes running tests in virtualenvs (or on distros) that no longer + have a symlink from python to python2 or python3. + + Closes #7602 + +- [a1346054 brought this change] + + scripts: invoke interpreters through /usr/bin/env + + Closes #7602 + +- DISABLED: enable 11 more tests for hyper builds + + Closes #7612 + +- setopt: enable CURLOPT_IGNORE_CONTENT_LENGTH for hyper + + Since this option is also used for FTP, it needs to work to set for + applications even if hyper doesn't support it for HTTP. Verified by test + 1137. + + Updated docs to specify that the option doesn't work for HTTP when using + the hyper backend. + + Closes #7614 + +- test1138: remove trailing space to make work with hyper + + Closes #7613 + +- libcurl-errors.3: clarify two CURLUcode errors + + CURLUE_BAD_HANDLE and CURLUE_BAD_PARTPOINTER should be for "bad" or + wrong pointers in a generic sense, not just for NULL pointers. + + Reviewed-by: Jay Satiro + + Ref: #7605 + Closes #7611 + +Jay Satiro (23 Aug 2021) +- symbols-in-versions: fix CURLSSLBACKEND_QSOSSL last used version + + ... and also change the 'Removed' column name to 'Last' since that + column is for the last version to contain the symbol. + + Closes https://github.com/curl/curl/pull/7609 + +Daniel Stenberg (23 Aug 2021) +- urlapi.c:seturl: assert URL instead of using if-check + + There's no code flow possible where this can happen. The assert makes + sure it also won't be introduced undetected in the future. + + Closes #7610 + +- curl-openssl.m4: show correct output for OpenSSL v3 + + Using 3.0.0 versions configure should now show this: + + checking for OpenSSL headers version... 3.0.0 - 0x300 + checking for OpenSSL library version... 3.0.0 + checking for OpenSSL headers and library versions matching... yes + + This output doesn't actually change what configure generates but is only + "cosmetic". + + Reported-by: Randall S. Becker + Fixes #7606 + Closes #7608 + +Jay Satiro (22 Aug 2021) +- mksymbolsmanpage.pl: Fix showing symbol's last used version + + Prior to this change the symbol's deprecated version was erroneously + shown as its last used version. + + Bug: https://github.com/curl/curl/commit/4e53b94#commitcomment-55239509 + Reported-by: i-ky@users.noreply.github.com + +Daniel Stenberg (21 Aug 2021) +- mksymbolsmanpage.pl: match symbols case insenitively + + Follow-up to 4e53b9430c750 which made this bug show. + + Reported-by: i-ky + Bug: https://github.com/curl/curl/commit/4e53b9430c7504de8984796e2a2091ec16f27136#commitcomment-55239253 + Closes #7607 + +- asyn-ares: call ares_freeaddrinfo() to clean up addrinfo results + + As this leaks memory otherwise + + Follow-up to ba904db0705c931 + + Closes #7599 + +- [Ehren Bendler brought this change] + + wolfssl: clean up wolfcrypt error queue + + If wolfSSL is built in certain ways (OPENSSL_EXTRA or Debug), the error + queue gets added on to for each session and never freed. Fix it by + calling ERR_clear_error() like in vtls/openssl when needed. This func is + a no-op in wolfcrypt if the error queue is not enabled. + + Closes #7594 + +- man pages: remove trailing whitespaces + + Extended test 1173 (via the manpage-syntax.pl script) to detect and warn + for them. + + Ref: #7602 + Reported-by: a1346054 on github + Closes #7604 + +- mailmap: add Gleb Ivanovsky + +- config.d: escape the backslash properly + + Closes #7603 + +- [Don J Olmstead brought this change] + + curl_setup.h: sync values for HTTP_ONLY + + The values for HTTP_ONLY differed between CMakeLists.txt and + curl_setup.h. Sync them and sort the values in curl_setup.h to make it + easier to spot differences. + + Closes #7601 + +Jay Satiro (21 Aug 2021) +- configure: set classic mingw minimum OS version to XP + + - If the user has not specified a minimum OS version (via WINVER or + _WIN32_WINNT macros) then set it to Windows XP. + + Prior to this change classic MinGW defaulted the minimum OS version + to Windows NT 4.0 which is way too old. At least Windows XP is needed + for getaddrinfo (which resolves hostnames to IPv6 addresses). + + Ref: https://github.com/curl/curl/issues/7483#issuecomment-891597034 + + Closes https://github.com/curl/curl/pull/7581 + +- schannel: Work around typo in classic mingw macro + + - Define ALG_CLASS_DHASH (the typo from the include) to ALG_CLASS_HASH. + + Prior to this change there was an incomplete fix to ignore the + CALG_TLS1PRF macro on those versions of MinGW where it uses the + ALG_CLASS_DHASH typoed macro. + + Ref: 48cf45c + Ref: https://osdn.net/projects/mingw/ticket/38391 + Ref: https://github.com/curl/curl/issues/2924 + + Closes https://github.com/curl/curl/pull/7580 + +Daniel Stenberg (20 Aug 2021) +- RELEASE-NOTES: synced + +- http_proxy: fix user-agent and custom headers for CONNECT with hyper + + Enable test 287 + + Closes #7598 + +- c-hyper: initial support for "dumping" 1xx HTTP responses + + With the use hyper_request_on_informational() + + Enable test 155 and 158 + + Closes #7597 + +Marc Hoersken (18 Aug 2021) +- tests/*server.pl: flush output before executing subprocess + + Also avoid shell processes staying around by using exec. + This is necessary to avoid output data being buffering + inside the process chain of Perl, Bash/Shell and our + test server binaries. On non-Windows systems the exec + will also make the subprocess replace the intermediate + shell, but on Windows it will at least bind the processes + together since there is no real fork or exec available. + + See: https://cygwin.com/cygwin-ug-net/highlights.html + and: https://docs.microsoft.com/cpp/c-runtime-library/exec-wexec-functions + Ref: https://github.com/curl/curl/pull/7530#issuecomment-900949010 + + Reviewed-by: Daniel Stenberg + Reviewed-by: Jay Satiro + Closes #7530 + +- CI: use GitHub Container Registry instead of Docker Hub + + Avoid limits on Docker Hub and improve image pull/download speed. + + Closes #7587 + +Daniel Stenberg (18 Aug 2021) +- openssl: when creating a new context, there cannot be an old one + + Remove the previous handling that would call SSL_CTX_free(), and instead + add an assert that halts a debug build if there ever is a context + already set at this point. + + Closes #7585 + +Jay Satiro (18 Aug 2021) +- KNOWN_BUGS: Renegotiate from server may cause hang for OpenSSL backend + + Closes https://github.com/curl/curl/issues/6785 + +Viktor Szakats (17 Aug 2021) +- docs/BINDINGS: URL update + +Marc Hoersken (17 Aug 2021) +- tests/server/*.c: align handling of portfile argument and file + + 1. Call the internal variable portname (like pidname) everywhere. + 2. Have a variable wroteportfile (like wrotepidfile) everywhere. + 3. Make sure the file is cleaned up on exit (like pidfile). + 4. Add parameter --portfile to usage outputs everywhere. + + Reviewed-by: Daniel Stenberg + + Replaces #7523 + Closes #7574 + +Daniel Gustafsson (17 Aug 2021) +- KNOWN_BUGS: Fix a number of typos in KNOWN_BUGS + + Fixes a set of typos found in section 11.3. + +Daniel Stenberg (17 Aug 2021) +- getparameter: fix the --local-port number parser + + It could previously get tricked into parsing the uninitialized stack + based buffer. + + Reported-by: Brian Carpenter + Closes #7582 + +- KNOWN_BUGS: Can't use Secure Transport with Crypto Token Kit + + Closes #7048 + +- [Jan Verbeek brought this change] + + curl: add warning for ignored data after quoted form parameter + + In an argument like `-F 'x=@/etc/hostname;filename="foo"abc'` the `abc` + is ignored. This adds a warning if the ignored data isn't all + whitespace. + + Closes #7394 + +Jay Satiro (17 Aug 2021) +- codeql: fix error "Resource not accessible by integration" + + - Enable codeql writing security-events. + + GitHub set the default permissions to read, apparently since earlier + this year. + + Ref: https://github.com/github/codeql-action/issues/464 + Ref: https://github.blog/changelog/2021-04-20-github-actions-control-permissions-for-github_token/ + + Fixes https://github.com/curl/curl/issues/7575 + Closes https://github.com/curl/curl/pull/7576 + +- tool_operate: Fix --fail-early with parallel transfers + + - Abort via progress callback to fail early during parallel transfers. + + When a critical error occurs during a transfer (eg --fail-early + constraint) then other running transfers will be aborted via progress + callback and finish with error CURLE_ABORTED_BY_CALLBACK (42). In this + case, the callback error does not become the most recent error and a + custom error message is used for those transfers: + + curld --fail --fail-early --parallel + https://httpbin.org/status/404 https://httpbin.org/delay/10 + + curl: (22) The requested URL returned error: 404 + curl: (42) Transfer aborted due to critical error in another transfer + + > echo %ERRORLEVEL% + 22 + + Fixes https://github.com/curl/curl/issues/6939 + Closes https://github.com/curl/curl/pull/6984 + +Daniel Stenberg (17 Aug 2021) +- [Sergey Markelov brought this change] + + sectransp: support CURLINFO_CERTINFO + + Fixes #4130 + Closes #7372 + +- ngtcp2: remove the acked_crypto_offset struct field init + + ... as it is gone from the API upstream. + + Closes #7578 + +- misc: update incorrect copyright year ranges + + Closes #7577 + +- KNOWN_BUGS: HTTP/3 quiche upload large file fails + + Closes #7532 + +- KNOWN_BUGS: CMake build with MIT Kerberos does not work + + Closes #6904 + +- TODO: add asynch getaddrinfo support + + Closes #6746 + +- RELEASE-NOTES: synced + +- [Artur Sinila brought this change] + + http2: revert call the handle-closed function correctly on closed stream + + Reverts 252790c5335a221 + + Assisted-by: Gergely Nagy + Fixes #7400 + Closes #7525 + +- [Patrick Monnerat brought this change] + + auth: do not append zero-terminator to authorisation id in kerberos + + RFC4752 Section 3.1 states "The authorization identity is not terminated + with a zero-valued (%x00) octet". Although a comment in code said it may + be needed anyway, nothing confirms it. In addition, servers may consider + it as part of the identity, causing a failure. + + Closes #7008 + +- [Patrick Monnerat brought this change] + + auth: use sasl authzid option in kerberos + + ... instead of deriving it from active ticket. + Closes #7008 + +- [Patrick Monnerat brought this change] + + auth: we do not support a security layer after kerberos authentication + + Closes #7008 + +- [Patrick Monnerat brought this change] + + auth: properly handle byte order in kerberos security message + + Closes #7008 + +- [z2_ brought this change] + + x509asn1: fix heap over-read when parsing x509 certificates + + Assisted-by: Patrick Monnerat + Closes #7536 + +- KNOWN_BUGS: Disconnects don't do verbose + + Closes #6995 + +- mailmap: fixup Michał Antoniak + +- [Michał Antoniak brought this change] + + build: fix compiler warnings + + For when CURL_DISABLE_VERBOSE_STRINGS and DEBUGBUILD flags are both + active. + + - socks.c : warning C4100: 'lineno': unreferenced formal parameter + (co-authored by Daniel Stenberg) + + - mbedtls.c: warning C4189: 'port': local variable is initialized but + not referenced + + - schannel.c: warning C4189: 'hostname': local variable is initialized + but not referenced + + Cloes #7528 + +- [Gleb Ivanovsky brought this change] + + CODE_STYLE-md: fix bold font style + + Markdown gets confused with abundance of asterisks, so use underscores + instead. + + Reviewed-by: Daniel Gustafsson + Closes #7569 + +- [Gleb Ivanovsky brought this change] + + CODE_STYLE-md: add missing comma + + Reviewed-by: Daniel Gustafsson + Closes #7570 + +- [Daniel Gustafsson brought this change] + + examples/ephiperfifo.c: simplify signal handler + + The signal handler registered for SIGINT is only handling SIGINT + so there isn't much need for inspecting the signo. While there, + rename the handler to be more specific. + + g_should_exit should really be of sig_atomic_t type, but relying + on autoconf in the examples seems like a bad idea so keep that + for now. + + Reviewed-by: Daniel Stenberg + Closes #7310 + +- c-hyper: initial step for 100-continue support + + Enabled test 154 + + Closes #7568 + +- [Ikko Ashimine brought this change] + + vtls: fix typo in schannel_verify.c + + occurence -> occurrence + + Closes #7566 + +- [Emil Engler brought this change] + + curl_url_get.3: clarify about path and query + + The current man-page lacks some details regarding the obtained path and + query. + + Closes #7563 + +- c-hyper: fix header value passed to debug callback + + Closes #7567 + +Viktor Szakats (12 Aug 2021) +- cleanup: URL updates + + - replace broken URL with the one it was most probably pointing to + when added (lib/tftp.c) + - replace broken URL with archive.org link (lib/curl_ntlm_wb.c) + - delete unnecessary protocol designator from archive.org URL + (docs/BINDINGS.md) + + Closes #7562 + +Daniel Stenberg (12 Aug 2021) +- [April King brought this change] + + DEPRECATE.md: linkify curl-library mailing list + + Closes #7561 + +- [Barry Pollard brought this change] + + output.d: add method to suppress response bodies + + Closes #7560 + +- TODO: remove 'c-ares deviates on http://1346569778' + + Fixed since 56a037cc0ad1b2 (7.77.0) + +- [Colin O'Dell brought this change] + + BINDINGS.md: update links to use https where available + + Closes #7558 + +- asyn-ares.c: move all version number checks to the top + + ... and use #ifdef [feature] in the code as per our guidelines. + +- ares: use ares_getaddrinfo() + + ares_getaddrinfo() is the getaddrinfo() cloned provided by c-ares, introduced + in version 1.16.0. + + With older c-ares versions, curl invokes ares_gethostbyname() twice - once for + IPv4 and once for IPv6 to resolve both addresses, and then combines the + returned results. + + Reported-by: jjandesmet + Fixes #7364 + Closes #7552 + +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: utilize crypto API functions to simplify + + Closes #7551 + +- [megatronking brought this change] + + ngtcp2: reset the oustanding send buffer again when drained + + Closes #7538 + +Michael Kaufmann (10 Aug 2021) +- progress: fix a compile warning on some systems + + lib/progress.c:380:40: warning: conversion to 'long double' from + 'curl_off_t {aka long long int}' may alter its value [-Wconversion] + + Closes #7549 + +Daniel Stenberg (10 Aug 2021) +- RELEASE-NOTES: synced + +- http: consider cookies over localhost to be secure + + Updated test31. + Added test 392 to verify secure cookies used for http://localhost + + Reviewed-by: Daniel Gustafsson + Fixes #6733 + Closes #7263 + +- TODO: erase secrets from heap/stack after use + + Closes #7268 + +Jay Satiro (10 Aug 2021) +- hostip: Make Curl_ipv6works function independent of getaddrinfo + + - Do not assume IPv6 is not working when getaddrinfo is not present. + + The check to see if IPv6 actually works is now independent of whether + there is any resolver that can potentially resolve a hostname to IPv6. + + Prior to this change if getaddrinfo() was not found at compile time then + Curl_ipv6works() would be defined as a macro that returns FALSE. + + When getaddrinfo is not found then libcurl is built with CURLRES_IPV4 + defined instead of CURLRES_IPV6, meaning that it cannot do IPv6 lookups + in the traditional way. With this commit if libcurl is built with IPv6 + support (ENABLE_IPV6) but without getaddrinfo (CURLRES_IPV6), and the + IPv6 stack is actually working, then it is possible for libcurl to + resolve IPv6 addresses by using DoH. + + Ref: https://github.com/curl/curl/issues/7483#issuecomment-890765378 + + Closes https://github.com/curl/curl/pull/7529 + +- test1565: fix windows build errors + + - Use our wait_ms() instead of sleep() since Windows doesn't have the + latter. + + - Use a separate variable to keep track of whether the pthread_t thread + id is valid. + + On Windows pthread_t is not an integer type. pthread offers no macro for + invalid pthread_t thread id, so validity is kept track of separately. + + Closes https://github.com/curl/curl/pull/7527 + +- [Jeremy Falcon brought this change] + + winbuild/README.md: clarify GEN_PDB option + + - Document that GEN_PDB option creates an external database. + + Ref: https://github.com/curl/curl/issues/7502 + +Daniel Stenberg (9 Aug 2021) +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: replace deprecated functions with nghttp3_conn_shutdown_stream_read + + Closes #7546 + +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: rework the return value handling of ngtcp2_conn_writev_stream + + Rework the return value handling of ngtcp2_conn_writev_stream and treat + NGTCP2_ERR_STREAM_SHUT_WR separately. + + Closes #7546 + +- configure: error out if both ngtcp2 and quiche are specified + + Reported-by: Vincent Grande + See #7539 + Closes #7545 + +- [Jeff Mears brought this change] + + easy: use a custom implementation of wcsdup on Windows + + ... so that malloc/free overrides from curl_global_init are used for + wcsdup correctly. + + Closes #7540 + +- zuul: add an mbedtls3 CI job + + Closes #7544 + +- [Benau brought this change] + + mbedTLS: initial 3.0.0 support + + Closes #7428 + +- RELEASE-NOTES: synced + +- configure.ac: revert bad nghttp2 library detection improvements + + This reverts commit b4b34db65f9f8, 673753344c5f and 29c7cf79e8b. + + The logic is now back to assuming that the nghttp2 lib is called nghttp2 and + nothing else. + + Reported-by: Rui Pinheiro + Reported-by: Alex Crichton + Fixes #7514 + Closes #7515 + +- happy-eyeballs-timeout-ms.d: polish the wording + + Reported-by: Josh Soref + Fixes #7433 + Closes #7542 + +- [modbw brought this change] + + mbedtls_threadlock: fix unused variable warning + + Closes #7393 + +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: compile with the latest ngtcp2 and nghttp3 + + Closes #7541 + +Marc Hoersken (31 Jul 2021) +- CI/cirrus: reduce compile time with increased parallism + + Cirrus CI VMs have 2 CPUs, let's use them also for Windows builds. + + Reviewed-by: Daniel Stenberg + Closes #7505 + +Daniel Stenberg (30 Jul 2021) +- [Bin Lan brought this change] + + tool/tests: fix potential year 2038 issues + + The length of 'long' in a 32-bit system is 32 bits, which cannot be used + to save timestamps after 2038. Most operating systems have extended + time_t to 64 bits. + + Remove the castings to long. + + Closes #7466 + +- compressed.d: it's a request, not an order + + Clarified + + Reported-by: Dan Jacobson + Reviewed-by: Daniel Gustafsson + Fixes #7516 + Closes #7517 + +- [Bernhard M. Wiedemann brought this change] + + tests: make three tests pass until 2037 + + after 2038 something in test1915 fails on 32-bit OSes + + Closes #7512 + +Daniel Gustafsson (30 Jul 2021) +- connect: remove superfluous conditional + + Commit dbd16c3e2 cleaned up the logic for traversing the addrinfos, + but the move left a conditional on ai which no longer is needed as + the while loop reevaluation will cover it. + + Closes #7511 + Reviewed-by: Carlo Marcelo Arenas Belón + Reviewed-by: Daniel Stenberg <daniel@haxx.se> + +Daniel Stenberg (29 Jul 2021) +- RELEASE-NOTES: synced + + and bump curlver to 7.79.0 for next release + +Marc Hoersken (29 Jul 2021) +- tests/*server.py: remove pidfile on server termination + + Avoid pidfile leaking/laying around after server already exited. + + Reviewed-by: Daniel Stenberg + Closes #7506 + +Daniel Gustafsson (27 Jul 2021) +- tool_main: fix typo in comment + + The referred to library is NSPR, so fix the switched around characters. + +Daniel Stenberg (28 Jul 2021) +- [Aleksandr Krotov brought this change] + + bearssl: support CURLOPT_CAINFO_BLOB + + Closes #7468 + +- curl.1: mention "global" flags + + Mention options that are "global". A global command line option is one + that doesn't get reset at --next uses and therefore don't need to be + used again. + + Reported-by: Josh Soref + + Fixes #7457 + Closes #7510 + +- CURLOPT_DOH_URL.3: CURLOPT_OPENSOCKETFUNCTION is not inherited + + Reported-by: Daniel Woelfel + Fixes #7441 + Closes #7509 + +- KNOWN_BUGS: add more HTTP/3 problems + + Closes #7351 + Closes #7339 + Closes #7125 + +Marc Hoersken (27 Jul 2021) +- CI/azure: reduce compile time with increased parallism + + Azure Pipelines CI VMs have 2 CPUs, let's use them. + + Closes #7489 + +Jay Satiro (27 Jul 2021) +- [Josh Soref brought this change] + + docs: fix grammar + + Fixes https://github.com/curl/curl/issues/7444 + Fixes https://github.com/curl/curl/issues/7451 + Fixes https://github.com/curl/curl/issues/7465 + Closes https://github.com/curl/curl/pull/7495 + +- mail-rcpt.d: fix grammar + + Remove confusing sentence that says to specify an e-mail address for + mail transfer, since that's implied. + + Reported-by: Josh Soref + + Fixes https://github.com/curl/curl/issues/7452 + Closes https://github.com/curl/curl/pull/7495 + +Daniel Stenberg (27 Jul 2021) +- c-hyper: remove the hyper_executor_poll() loop from Curl_http + + 1. it's superfluous + 2. it didn't work identically to the Curl_hyper_stream one which could + cause problems like #7486 + + Pointed-out-by: David Cook + Closes #7499 + +- curl-openssl.m4: check lib64 for the pkg-config file + + OpenSSL recently started putting the libs in $prefix/lib64 on 'make + install', so we check that directory for pkg-config data if the 'lib' + check fails. + + Closes #7503 + +- CURLOPT_SSL_CTX_*.3: tidy up the example + + Use the proper code style. Don't store return codes that aren't read. + Copy the same example into CURLOPT_SSL_CTX_FUNCTION.3 as well. + + Closes #7500 + +- example/cookie_interface: fix scan-build printf warning + + Follow-up to 4b79c4fb565 + + Fixes #7497 + Closes #7498 + +- [Josh Soref brought this change] + + limit-rate.d: clarify base unit + + Fixes #7439 + Closes #7494 + +- [Carlo Marcelo Arenas Belón brought this change] + + examples/cookie_interface: avoid printfing time_t directly + + time_t representation is undefined and varies on bitsize and signedness, + and as of C11 could be even non integer. + + instead of casting to unsigned long (which would truncate in systems + with a 32bit long after 2106) use difftime to get the elapsed time as a + double and print that (without decimals) instead. + + alternatively a cast to curl_off_t and its corresponding print + formatting could have been used (at least in POSIX) but portability and + curl agnostic code was prioritized. + + Closes #7490 + +Marc Hoersken (25 Jul 2021) +- tests/servers: remove obsolete pid variable + + Variable is not used since pidfile handling moved to util.[ch] + + Reviewed-by: Jay Satiro + Closes #7482 + +- tests/servers: use our platform-aware pid for server verification + + The pid used for server verification is later stored as pid2 in + the hash of running test servers and therefore used for shutdown. + + The pid used for shutdown must be the platform-aware (Win32) pid + to avoid leaking test servers while running them using Cygwin/msys. + + Reviewed-by: Jay Satiro + Closes #7481 + +- tests/runtests.pl: cleanup copy&paste mistakes and unused code + + Reviewed-by: Jay Satiro + Part of #7481 + +Daniel Stenberg (25 Jul 2021) +- RELEASE-NOTES: synced + + bumped to 7.78.1 for next release + +- http_proxy: clear 'sending' when the outgoing request is sent + + ... so that Curl_connect_getsock() will know how to wait for the socket + to become readable and not writable after the entire CONNECT request has + been issued. + + Regression added in 7.77.0 + + Reported-by: zloi-user on github + Assisted-by: Jay Satiro + Fixes #7155 + Closes #7484 + +Jay Satiro (25 Jul 2021) +- [Josh Soref brought this change] + + openssl: fix grammar + + Closes https://github.com/curl/curl/pull/7480 + +- configure.ac: tweak nghttp2 library name fix again + + - Change extraction to handle multiple library names returned by + pkg-config (eg a possible scenario with pkg-config --static). + + Ref: https://github.com/curl/curl/pull/7472 + + Closes https://github.com/curl/curl/pull/7485 + +Dan Fandrich (23 Jul 2021) +- Get rid of the unused HAVE_SIG_ATOMIC_T et. al. + + It was added in 2006 but I see no evidence it was ever used. + +Jay Satiro (23 Jul 2021) +- docs: change max-filesize caveat again + + - Add protocols field to max-filesize.d. + + - Revert wording on unknown file size caveat and do not discuss specific + protocols in that section. + + Partial revert of ecf0225. All max-filesize options now have the list of + protocols and it's clearer just to have that list without discussing + specific protocols in the caveat. + + Reported-by: Josh Soref + + Ref: https://github.com/curl/curl/issues/7453#issuecomment-884128762 + +Daniel Stenberg (22 Jul 2021) +- [Christian Weisgerber brought this change] + + configure: tweak nghttp2 library name fix + + commit 29c7cf79e8b44cf (shipped in 7.78.0) introduced a problem by + assuming that LIB_H2 does not have any leading whitespace. At least + OpenBSD's native pkg-config can produce such whitespace, though: + + $ pkg-config --libs-only-l libnghttp2 + -lnghttp2 + + As a result, the configure check for libnghttp2 will erroneously fail. + + Bug: https://curl.se/mail/lib-2021-07/0050.html + Closes #7472 + +- [Bastian Krause brought this change] + + docs/MQTT: update state of username/password support + + PR #7243 implemented username/password support for MQTT, so let's drop + these items from the caveats. + + Signed-off-by: Bastian Krause <bst@pengutronix.de> + + Closes #7474 + +- [Oleg Pudeyev brought this change] + + CURLMOPT_TIMERFUNCTION.3: remove misplaced "time" + + Closes #7470 + Version 7.78.0 (21 Jul 2021) Daniel Stenberg (21 Jul 2021) @@ -192,7 +3463,7 @@ Daniel Stenberg (18 Jul 2021) Closes #7411 Closes #7412 -- [MAntoniak brought this change] +- [Michał Antoniak brought this change] lib: fix compiler warnings with CURL_DISABLE_NETRC @@ -279,7 +3550,7 @@ Daniel Stenberg (18 Jul 2021) Fixes #7415 Closes #7417 -- [MAntoniak brought this change] +- [Michał Antoniak brought this change] mbedtls: Remove unnecessary include @@ -1789,19 +5060,19 @@ Daniel Stenberg (3 Jun 2021) Add test 3017 and 3018 to verify. Closes #7166 -- [theawless brought this change] +- [Abhinav Singh brought this change] cmake: add CURL_DISABLE_NTLM option Closes #7028 -- [theawless brought this change] +- [Abhinav Singh brought this change] configure: add --disable-ntlm option Closes #7028 -- [theawless brought this change] +- [Abhinav Singh brought this change] define: re-add CURL_DISABLE_NTLM and corresponding ifdefs @@ -3040,7 +6311,7 @@ Daniel Stenberg (4 May 2021) Closes #6960 -- [MAntoniak brought this change] +- [Michał Antoniak brought this change] gskit: fix CURL_DISABLE_PROXY build @@ -3050,7 +6321,7 @@ Daniel Stenberg (4 May 2021) Closes #6981 -- [MAntoniak brought this change] +- [Michał Antoniak brought this change] gskit: fix undefined reference to 'conn' @@ -5027,3065 +8298,3 @@ Daniel Gustafsson (26 Feb 2021) Closes #6665 Reviewed-by: Daniel Gustafsson <daniel@yesql.se> Signed-off-by: Jean-Philippe Menil <jpmenil@gmail.com> - -- gnutls: Fix nettle discovery - - Commit e06fa7462ac258c removed support for libgcrypt leaving only - support for nettle which has been the default crypto library in - GnuTLS for a long time. There were however a few conditionals on - USE_GNUTLS_NETTLE which cause compilation errors in the metalink - code (as it used the gcrypt fallback instead as a result). See the - below autobuild for an example of the error: - - https://curl.se/dev/log.cgi?id=20210225123226-30704#prob1 - - This removes all uses of USE_GNUTLS_NETTLE and also removes the - gcrypt support from the metalink code while at it. - - Closes #6656 - Reviewed-by: Daniel Stenberg <daniel@haxx.se> - -- cookies: Support multiple -b parameters - - Previously only a single -b cookie parameter was supported with the last - one winning. This adds support for supplying multiple -b params to have - them serialized semicolon separated. Both cookiefiles and cookies can be - entered multiple times. - - Closes #6649 - Reviewed-by: Daniel Stenberg <daniel@haxx.se> - -Daniel Stenberg (25 Feb 2021) -- build: remove all traces of USE_BLOCKING_SOCKETS - - libcurl doesn't behave properly with the define set - - Closes #6655 - -- RELEASE-NOTES: synced - -Daniel Gustafsson (25 Feb 2021) -- docs: Fix typos - - Random typos spotted when skimming docs. - -- cookies: Use named parameters in header prototypes - - Align header with project style of using named parameters in the - function prototypes to aid readability and self-documentation. - - Closes #6653 - Reviewed-by: Daniel Stenberg <daniel@haxx.se> - -Daniel Stenberg (24 Feb 2021) -- urldata: make 'actions[]' use unsigned char instead of int - - ... as it only needs a few bits per index anyway. - - Reviewed-by: Daniel Gustafsson - Closes #6648 - -- configure: fail if --with-quiche is used and quiche isn't found - - Closes #6652 - -- [Gregor Jasny brought this change] - - cmake: use CMAKE_INSTALL_INCLUDEDIR indirection - - Reviewed-by: Sergei Nikulov - Closes #6440 - -Viktor Szakats (23 Feb 2021) -- mingw: enable using strcasecmp() - - This makes the 'Features:' list sorted case-insensitively, - bringing output in-line with *nix builds. - - Reviewed-by: Jay Satiro - Closes #6644 - -- build: delete unused feature guards - - - `HAVE_STRNCASECMP` - - `HAVE_TCGETATTR` - - `HAVE_TCSETATTR` - - Reviewed-by: Jay Satiro - Reviewed-by: Daniel Stenberg - Closes #6645 - -Jay Satiro (23 Feb 2021) -- docs: add CURLOPT_CURLU to 'See also' in curl_url_ functions - - Closes https://github.com/curl/curl/pull/6639 - -Daniel Stenberg (23 Feb 2021) -- [Jacob Hoffman-Andrews brought this change] - - configure: make hyper opt-in, and fail if missing - - Previously, configure would look for hyper by default, and use it if - found; otherwise it would not use hyper, and not error. - - Now, configure will not look for hyper unless --with-hyper is passed. If - configure looks for hyper and fails, it will error. - - Also, add -ld -lpthread -lm to Hyper's libs. I think they are required. - - Closes #6598 - -- multi: do once-per-transfer inits in before_perform in DID state - - ... since the state machine might go to RATELIMITING and then back to - PERFORMING doing once-per-transfer inits in that function is wrong and - it caused problems with receiving chunked HTTP and it set the - PRETRANSFER time much too often... - - Regression from b68dc34af341805aeb7b3715 (shipped in 7.75.0) - - Reported-by: Amaury Denoyelle - Fixes #6640 - Closes #6641 - -- RELEASE-NOTES: synced - -- CODE_STYLE.md: fix broken link to INTERNALS - - ... the link would only work if browsed on GitHub, while this link now - takes the user to the website instead and thus should work on either. - - Reported-by: David Demelier - -- curl_url_set.3: mention CURLU_PATH_AS_IS - - ... it has been supported since the URL API was added. - - Bug: https://curl.se/mail/lib-2021-02/0046.html - - Closes #6638 - -Viktor Szakats (21 Feb 2021) -- time: enable 64-bit time_t in supported mingw environments - - (Unless 32-bit `time_t` is selected manually via the `_USE_32BIT_TIME_T` - mingw macro.) - - Previously, 64-bit `time_t` was enabled on VS2005 and newer only, and - 32-bit `time_t` was used on all other Windows builds. - - Assisted-by: Jay Satiro - Closes #6636 - -Jay Satiro (20 Feb 2021) -- test1188: Check for --fail HTTP status - - - Change the test to check for curl error on HTTP 404 Not Found. - - test1188 tests "--write-out with %{onerror} and %{urlnum} to stderr". - Prior to this change it did that by specifying a non-existent host which - would cause an error. ISPs may hijack DNS and resolve non-existent hosts - so the test would not work if that was the case. - - Ref: https://en.wikipedia.org/wiki/DNS_hijacking#Manipulation_by_ISPs - Ref: https://github.com/curl/curl/issues/6621 - Ref: https://github.com/curl/curl/pull/6623 - - Closes https://github.com/curl/curl/pull/6637 - -- memdebug: close debug logfile explicitly on exit - - - Use atexit to register a dbg cleanup function that closes the logfile. - - LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is - detected on exit so the logfile must be closed explicitly or data could - be lost. Though _exit() does not call atexit handlers such as this, - LSAN's call to _exit() comes after the atexit handlers are called. - - Prior to this change the logfile was not explicitly closed so it was - possible that if LSAN detected a leak and called _exit (which does - not flush or close files like exit) then the logfile could be missing - data. That could then cause curl's memanalyze to report false leaks - (eg a malloc was recorded to the logfile but the corresponding free was - discarded from the buffer instead of written to the logfile, then - memanalyze reports that as a leak). - - Ref: https://github.com/google/sanitizers/issues/1374 - - Bug: https://github.com/curl/curl/pull/6591#issuecomment-780396541 - - Closes https://github.com/curl/curl/pull/6620 - -- curl_multibyte: always return a heap-allocated copy of string - - - Change the Windows char <-> UTF-8 conversion functions to return an - allocated copy of the passed in string instead of the original. - - Prior to this change the curlx_convert_ functions would, as what I - assume was an optimization, not make a copy of the passed in string if - no conversion was required. No conversion is required in non-UNICODE - Windows builds since our tchar strings are type char and remain in - whatever the passed in encoding is, which is assumed to be UTF-8 but may - be other encoding. - - In contrast the UNICODE Windows builds require conversion - (wchar <-> char) and do return a copy. That inconsistency could lead to - programming errors where the developer expects a copy, and does not - realize that won't happen in all cases. - - Closes https://github.com/curl/curl/pull/6602 - -Viktor Szakats (19 Feb 2021) -- http: add new files missed from referrer commit - - Ref: 44872aefc2d54f297caf2b0cc887df321bc9d791 - Ref: #6591 - -- http: add support to read and store the referrer header - - - add CURLINFO_REFERER libcurl option - - add --write-out '%{referer}' command-line option - - extend --xattr command-line option to fill user.xdg.referrer.url extended - attribute with the referrer (if there was any) - - Closes #6591 - -Daniel Stenberg (19 Feb 2021) -- urldata: remove the _ORIG suffix from string names - - It doesn't provide any useful info but only makes the names longer. - - Closes #6624 - -- url: fix memory leak if OOM in the HSTS handling - - Reported-by: Viktor Szakats - Bug: https://github.com/curl/curl/pull/6627#issuecomment-781626205 - - Closes #6628 - -- gnutls: assume nettle crypto support - - nettle has been the default crypto library with GnuTLS since 2010. By - dropping support for the previous libcrypto, we simplify code. - - Closes #6625 - -- asyn-ares: use consistent resolve error message - - ... with the help of Curl_resolver_error() which now is moved from - asyn-thead.c and is provided globally for this purpose. - - Follow-up to 35ca04ce1b77636 - - Makes test 1188 work for c-ares builds - - Closes #6626 - -Viktor Szakats (18 Feb 2021) -- ci: stop building on freebsd-12-1 - - An updated freebsd-12-2 image was added a few months ago, and this - older one is consistently failing to go past `pkginstall`: - ``` - Newer FreeBSD version for package py37-mlt: - To ignore this error set IGNORE_OSVERSION=yes - - package: 1202000 - - running kernel: 1201000 - Ignore the mismatch and continue? [Y/n]: pkg: repository FreeBSD contains packages for wrong OS version: FreeBSD:12:amd64 - ``` - - FreeBSD thread suggests that 12.1 is EOL, and best to avoid. - - Ref: https://forums.freebsd.org/threads/78856/ - - Reviewed-by: Daniel Stenberg - Closes #6622 - -Daniel Stenberg (18 Feb 2021) -- test1188: change error from connect to resolve error - - Using the %NOLISTENPORT to trigger a connection failure is somewhat - "risky" (since it isn't guaranteed to not be listened to) and caused - occasional CI problems. This fix changes the infused error to be a more - reliable one but still verifies the --write-out functionality properly - - which is the purpose of this test. - - Reported-by: Jay Satiro - Fixes #6621 - Closes #6623 - -- url.c: use consistent error message for failed resolve - -- BUGS: language polish - -- wolfssl: don't store a NULL sessionid - - This caused a memory leak as the session id cache entry was still - erroneously stored with a NULL sessionid and that would later be treated - as not needed to get freed. - - Reported-by: Gisle Vanem - Fixes #6616 - Closes #6617 - -- parse_proxy: fix a memory leak in the OOM path - - Reported-by: Jay Satiro - Reviewed-by: Jay Satiro - Reviewed-by: Emil Engler - - Closes #6614 - Bug: https://github.com/curl/curl/pull/6591#issuecomment-780396541 - -Jay Satiro (17 Feb 2021) -- url: fix possible use-after-free in default protocol - - Prior to this change if the user specified a default protocol and a - separately allocated non-absolute URL was used then it was freed - prematurely, before it was then used to make the replacement URL. - - Bug: https://github.com/curl/curl/issues/6604#issuecomment-780138219 - Reported-by: arvids-kokins-bidstack@users.noreply.github.com - - Closes https://github.com/curl/curl/pull/6613 - -Daniel Stenberg (16 Feb 2021) -- multi: rename the multi transfer states - - While working on documenting the states it dawned on me that step one is - to use more descriptive names on the states. This also changes prefix on - the states to make them shorter in the source. - - State names NOT ending with *ing are transitional ones. - - Closes #6612 - -Viktor Szakats (16 Feb 2021) -- http: do not add a referrer header with empty value - - Previously an empty 'Referer:' header was added to the HTTP request when - passing `--referer ';auto'` or `--referer ''` on the command-line. This - patch makes `--referer` work like `--header 'Referer:'` and will only add - the header if it has a non-zero length value. - - Reviewed-by: Jay Satiro - Closes #6610 - -Daniel Stenberg (16 Feb 2021) -- lib: remove 'conn->data' completely - - The Curl_easy pointer struct entry in connectdata is now gone. Just - before commit 215db086e0 landed on January 8, 2021 there were 919 - references to conn->data. - - Closes #6608 - -- openldap: pass 'data' to the callbacks instead of 'conn' - -Jay Satiro (15 Feb 2021) -- doh: Fix sharing user's resolve list with DOH handles - - - Share the shared object from the user's easy handle with the DOH - handles. - - Prior to this change if the user had set a shared object with shared - cached DNS (CURL_LOCK_DATA_DNS) for their easy handle then that wasn't - used by any associated DOH handles, since they used the multi's default - hostcache. - - This change means all the handles now use the same hostcache, which is - either the shared hostcache from the user created shared object if it - exists or if not then the multi's default hostcache. - - Reported-by: Manuj Bhatia - - Fixes https://github.com/curl/curl/issues/6589 - Closes https://github.com/curl/curl/pull/6607 - -Daniel Stenberg (15 Feb 2021) -- http2: remove conn->data use - - ... but instead use a private alternative that points to the "driving - transfer" from the connection. We set the "user data" associated with - the connection to be the connectdata struct, but when we drive transfers - the code still needs to know the pointer to the transfer. We can change - the user data to become the Curl_easy handle, but with older nghttp2 - version we cannot dynamically update that pointer properly when - different transfers are used over the same connection. - - Closes #6520 - -- openssl: remove conn->data use - - We still make the trace callback function get the connectdata struct - passed to it, since the callback is anchored on the connection. - - Repeatedly updating the callback pointer to set 'data' with - SSL_CTX_set_msg_callback_arg() doesn't seem to work, probably because - there might already be messages in the queue with the old pointer. - - This code therefore makes sure to set the "logger" handle before using - OpenSSL calls so that the right easy handle gets used for tracing. - - Closes #6522 - -- RELEASE-NOTES: synced - -Jay Satiro (14 Feb 2021) -- doh: add options to disable ssl verification - - - New libcurl options CURLOPT_DOH_SSL_VERIFYHOST, - CURLOPT_DOH_SSL_VERIFYPEER and CURLOPT_DOH_SSL_VERIFYSTATUS do the - same as their respective counterparts. - - - New curl tool options --doh-insecure and --doh-cert-status do the same - as their respective counterparts. - - Prior to this change DOH SSL certificate verification settings for - verifyhost and verifypeer were supposed to be inherited respectively - from CURLOPT_SSL_VERIFYHOST and CURLOPT_SSL_VERIFYPEER, but due to a bug - were not. As a result DOH verification remained at the default, ie - enabled, and it was not possible to disable. This commit changes - behavior so that the DOH verification settings are independent and not - inherited. - - Ref: https://github.com/curl/curl/pull/4579#issuecomment-554723676 - - Fixes https://github.com/curl/curl/issues/4578 - Closes https://github.com/curl/curl/pull/6597 - -- hostip: fix crash in sync resolver builds that use DOH - - - Guard some Curl_async accesses with USE_CURL_ASYNC instead of - !CURLRES_SYNCH. - - This is another follow-up to 8335c64 which moved the async struct from - the connectdata struct into the Curl_easy struct. A previous follow-up - 6cd167a fixed building for sync resolver by guarding some async struct - accesses with !CURLRES_SYNCH. The problem is since DOH (DNS-over-HTTPS) - is available as an asynchronous secondary resolver the async struct may - be used even when libcurl is built for the sync resolver. That means - that CURLRES_SYNCH and USE_CURL_ASYNC may be defined at the same time. - - Closes https://github.com/curl/curl/pull/6603 - -Daniel Stenberg (13 Feb 2021) -- KNOWN_BUGS: cannot enable LDAPS on Windows with cmake - - Reported-by: Jack Boos Yu - Closes #6284 - -- KNOWN_BUGS: Excessive HTTP/2 packets with TCP_NODELAY - - Reported-by: Alex Xu - Closes #6363 - -- http: use credentials from transfer, not connection - - HTTP auth "accidentally" worked before this cleanup since the code would - always overwrite the connection credentials with the credentials from - the most recent transfer and since HTTP auth is typically done first - thing, this has not been an issue. It was still wrong and subject to - possible race conditions or future breakage if the sequence of functions - would change. - - The data.set.str[] strings MUST remain unmodified exactly as set by the - user, and the credentials to use internally are instead set/updated in - state.aptr.* - - Added test 675 to verify different credentials used in two requests done - over a reused HTTP connection, which previously behaved wrongly. - - Fixes #6542 - Closes #6545 - -- test433: clear some home dir env variables - - Follow-up to bd6b54ba1f55b5 - - ... so that XDG_CONFIG_HOME is the only home dir variable set and thus - used correctly in the test! - - Fixes #6599 - Closes #6600 - -- RELEASE-NOTES: synced - - bumped the version to 7.76.0 - -- travis: install libgsasl-dev to add that to the builds - - Closes #6588 - -- urldata: don't touch data->set.httpversion at run-time - - Rename it to 'httpwant' and make a cloned field in the state struct as - well for run-time updates. - - Also: refuse non-supported HTTP versions. Verified with test 129. - - Closes #6585 - -Viktor Szakats (11 Feb 2021) -- tests: disable .curlrc in more environments - - by also setting CURL_HOME and XDG_CONFIG_HOME envvars to the local - directory. - - Reviewed-by: Daniel Stenberg - Fixes #6595 - Closes #6596 - -- docs/Makefile.inc: format to be update-friendly - - - one source file per line - - convert tabs to spaces - - do not align line-continuation backslashes - - sort source files alphabetically - - Reviewed-by: Daniel Stenberg - Closes #6593 - -Daniel Stenberg (11 Feb 2021) -- curl: provide libgsasl version and feature info in -V output - - Closes #6592 - -- gsasl: provide CURL_VERSION_GSASL if built-in - - To let applications know the feature is available. - - Closes #6592 - -- curl: add --fail-with-body - - Prevent both --fail and --fail-with-body on the same command line. - - Verify with test 349, 360 and 361. - - Closes #6449 - -- TODO: remove HSTS - - Provided now since commit 7385610d0c74 - -Jay Satiro (10 Feb 2021) -- tests: Fix tests failing due to change in curl --help - - Follow-up to parent 3183217 which added add missing <mode> argument to - --create-file-mode <mode>. - - Ref: https://github.com/curl/curl/issues/6590 - -- tool_help: add missing argument for --create-file-mode - - Prior to this change the required argument was not shown in curl --help. - - before: - --create-file-mode File mode for created files - - after: - --create-file-mode <mode> File mode (octal) for created files - - Reported-by: ZimCodes@users.noreply.github.com - - Fixes https://github.com/curl/curl/issues/6590 - -- create-file-mode.d: add missing Arg tag - - Prior to this change the required argument was not shown. - - curl.1 before: --create-file-mode - curl.1 after: --create-file-mode <mode> - - Reported-by: ZimCodes@users.noreply.github.com - - Fixes https://github.com/curl/curl/issues/6590 - -Viktor Szakats (10 Feb 2021) -- gsasl: fix errors/warnings building against libgsasl - - - also fix an indentation - - make Curl_auth_gsasl_token() use CURLcode (by Daniel Stenberg) - - Ref: https://github.com/curl/curl/pull/6372#issuecomment-776118711 - Ref: https://github.com/curl/curl/pull/6588 - - Reviewed-by: Jay Satiro - Assisted-by: Daniel Stenberg - Reviewed-by: Simon Josefsson - Closes #6587 - -- Makefile.m32: add support for libgsasl dependency - - Reviewed-by: Marcel Raad - Closes #6586 - -Marcel Raad (10 Feb 2021) -- ngtcp2: clarify calculation precedence - - As suggested by Codacy/cppcheck. - - Closes https://github.com/curl/curl/pull/6576 - -- server: remove redundant condition - - `end` is always non-null here. - - Closes https://github.com/curl/curl/pull/6576 - -- lib: remove redundant code - - Closes https://github.com/curl/curl/pull/6576 - -- mqttd: remove unused variable - - Closes https://github.com/curl/curl/pull/6576 - -- tool_paramhlp: reduce variable scope - - Closes https://github.com/curl/curl/pull/6576 - -- tests: reduce variable scopes - - Closes https://github.com/curl/curl/pull/6576 - -- lib: reduce variable scopes - - Closes https://github.com/curl/curl/pull/6576 - -- ftp: fix Codacy/cppcheck warning about null pointer arithmetic - - Increment `bytes` only if it is non-null. - - Closes https://github.com/curl/curl/pull/6576 - -Daniel Stenberg (9 Feb 2021) -- ngtcp2: adapt to the new recv_datagram callback - -- quiche: fix build error: use 'int' for port number - - Follow-up to cb2dc1ba8 - -- ftp: add 'list_only' to the transfer state struct - - and rename it from 'ftp_list_only' since it is also used for SSH and - POP3. The state is updated internally for 'type=D' FTP URLs. - - Added test case 1570 to verify. - - Closes #6578 - -- ftp: add 'prefer_ascii' to the transfer state struct - - ... and make sure the code never updates 'set.prefer_ascii' as it breaks - handle reuse which should use the setting as the user specified it. - - Added test 1569 to verify: it first makes an FTP transfer with ';type=A' - and then another without type on the same handle and the second should - then use binary. Previously, curl failed this. - - Closes #6578 - -- RELEASE-NOTES: synced - -- [Jacob Hoffman-Andrews brought this change] - - vtls: initial implementation of rustls backend - - This adds a new TLS backend, rustls. It uses the C-to-rustls bindings - from https://github.com/abetterinternet/crustls. - - Rustls is at https://github.com/ctz/rustls/. - - There is still a fair bit to be done, like sending CloseNotify on - connection shutdown, respecting CAPATH, and properly indicating features - like "supports TLS 1.3 ciphersuites." But it works well enough to make - requests and receive responses. - - Blog post for context: - https://www.abetterinternet.org/post/memory-safe-curl/ - - Closes #6350 - -- [Simon Josefsson brought this change] - - sasl: support SCRAM-SHA-1 and SCRAM-SHA-256 via libgsasl - - Closes #6372 - -Jay Satiro (9 Feb 2021) -- lib: use int type for more port variables - - This is a follow-up to 764c6bd. Prior to that change port variables - were usually type long. - - Closes https://github.com/curl/curl/pull/6553 - -- tool_writeout: refactor write-out and write-out json - - - Deduplicate the logic used by write-out and write-out json. - - Rather than have separate writeLong, writeString, etc, logic for - each of write-out and write-out json instead have respective shared - functions that can output either format and a 'use_json' parameter to - indicate whether it is json that is output. - - This will make it easier to maintain. Rather than have to go through - two sets of logic now we only have to go through one. - - - Support write-out %{errormsg} and %{exitcode} in json. - - - Clarify in the doc that %{exitcode} is the exit code of the transfer. - - Prior to this change it just said "The numerical exitcode" which - implies it's the exit code of the tool, and it's not necessarily that. - - Closes https://github.com/curl/curl/pull/6544 - -- lib: drop USE_SOCKETPAIR in favor of CURL_DISABLE_SOCKETPAIR - - .. since the former is undocumented and they both do the same thing. - - Closes https://github.com/curl/curl/pull/6517 - -- curl_multibyte: fall back to local code page stat/access on Windows - - If libcurl is built with Unicode support for Windows then it is assumed - the filename string is Unicode in UTF-8 encoding and it is converted to - UTF-16 to be passed to the wide character version of the respective - function (eg wstat). However the filename string may actually be in the - local encoding so, even if it successfully converted to UTF-16, if it - could not be stat/accessed then try again using the local code page - version of the function (eg wstat fails try stat). - - We already do this with fopen (ie wfopen fails try fopen), so I think it - makes sense to extend it to stat and access functions. - - Closes https://github.com/curl/curl/pull/6514 - -- [Stephan Szabo brought this change] - - file: Support unicode urls on windows - - Closes https://github.com/curl/curl/pull/6501 - -- [Vincent Torri brought this change] - - cmake: fix import library name for non-MS compiler on Windows - - - Use _imp.lib suffix only for Microsoft's compiler (MSVC). - - Prior to this change library suffix _imp.lib was used for the import - library on Windows regardless of compiler. - - With this change the other compilers should now use their default - suffix which should be .dll.a. - - This change is motivated by the usage of pkg-config on MSYS2. - Indeed, when 'pkg-config --libs libcurl' is used, -lcurl is - passed to ld. The documentation of ld on Windows : - - https://sourceware.org/binutils/docs/ld/WIN32.html - - lists, in the 'direct linking to a dll' section, the pattern - of the searched import library, and libcurl_imp.lib is not there. - - Closes https://github.com/curl/curl/pull/6225 - -Daniel Stenberg (9 Feb 2021) -- urldata: move 'followlocation' to UrlState - - As this is a state variable it does not belong in UserDefined which is - used to store values set by the user. - - Closes #6582 - -- [Ikko Ashimine brought this change] - - http_proxy: fix typo in http_proxy.c - - settting -> setting - - Closes #6583 - -- [Fabian Keil brought this change] - - tests/server: Bump MAX_TAG_LEN to 200 - - This is useful for tests containing HTML inside of <data> sections. - For <img> tags it's not uncommon to be longer than the previous - limit of 79 bytes. - - An example of a previously problem-causing tag is: - <img src="http://config.privoxy.org/send-banner?type=auto" border="0" title="Killed-http://www.privoxy.org/images/privoxy.png-by-size" width="88" height="31"> - which is needed for a Privoxy test for the banners-by-size filter. - - Previously it caused server failures like: - 12:29:05.786961 ====> Client connect - 12:29:05.787116 accept_connection 3 returned 4 - 12:29:05.787194 accept_connection 3 returned 0 - 12:29:05.787285 Read 119 bytes - 12:29:05.787345 Process 119 bytes request - 12:29:05.787407 Got request: GET /banners-by-size/9 HTTP/1.1 - 12:29:05.787464 Requested test number 9 part 0 - 12:29:05.787686 getpart() failed with error: -2 - 12:29:05.787744 - request found to be complete (9) - 12:29:05.787912 getpart() failed with error: -2 - 12:29:05.788048 Wrote request (119 bytes) input to log/server.input - 12:29:05.788157 Send response test9 section <data> - 12:29:05.788443 getpart() failed with error: -2 - 12:29:05.788498 instructed to close connection after server-reply - 12:29:05.788550 ====> Client disconnect 0 - 12:29:05.871448 exit_signal_handler: 15 - 12:29:05.871714 signalled to die - 12:29:05.872040 ========> IPv4 sws (port 21108 pid: 51758) exits with signal (15) - -- [Fabian Keil brought this change] - - tests/badsymbols.pl: when opening '$incdir' fails include it in the error message - -- [Fabian Keil brought this change] - - runtests.1: document -o, -P, -L, and -E - -- [Fabian Keil brought this change] - - runtests.pl: add %TESTNUMBER variable to make copying tests more convenient - -- [Fabian Keil brought this change] - - runtests.pl: add an -o option to change internal variables - - runtests.pl has lots of internal variables one might want to - change in certain situations, but adding a dedicated option - for every single one of them isn't practical. - - Usage: - ./runtests.pl -o TESTDIR=$privoxy_curl_test_dir -o HOSTIP=10.0.0.1 ... - -- [Fabian Keil brought this change] - - runtests.pl: cleanups - - - show the summarized test result in the last line of the report - - do not use $_ after mapping it to a named variable - Doing that makes the code harder to follow. - - log the restraints sorted by the number of their occurrences - - fix language when logging restraints that only occured once - - let runhttpserver() use $TESTDIR instead of $srcdir - ... so it works if a non-default $TESTDIR is being used. - -- [Fabian Keil brought this change] - - runtests.pl: add an -E option to specify an exclude file - - It can contain additional restraints for test numbers, - keywords and tools. - - The idea is to let third parties like the Privoxy project - distribute an exclude file with their tarballs that specifies - which curl tests are not expected to work when using Privoxy - as a proxy, without having to fork the whole curl test suite. - - The syntax could be changed to be extendable and maybe - more closely reflect the "curl test" syntax. Currently - it's a bunch of lines like these: - - test:$TESTNUMBER:Reason why this test with number $TESTNUMBER should be skipped - keyword:$KEYWORD:Reason why tests whose keywords contain the $KEYWORD should be skipped - tool:$TOOL:Reason why tests with tools that contain $TOOL should be skipped - - To specify multiple $TESTNUMBERs, $KEYWORDs and $TOOLs - on a single line, split them with commas. - -- [Fabian Keil brought this change] - - runtests.pl: add -L parameter to require additional perl libraries - - This is useful to change the behaviour of the script without - having to modify the file itself, for example to use a custom - compareparts() function that ignores header differences that - are expected to occur when an external proxy is being used. - - Such differences are proxy-specific and thus the modifications - should be maintained together with the proxy. - -- [Fabian Keil brought this change] - - runtests.pl: add a -P option to specify an external proxy - - ... that should be used when executing the tests. - - The assumption is that the proxy is an HTTP proxy. - - This option should be used together with -L to provide - a customized compareparts() version that knows which - proxy-specific header differences should be ignored. - - This option doesn't work for all test types yet. - -- [Fabian Keil brought this change] - - tests: fixup several tests - - missing CRs and modified %hostip - - lib556/test556: use a real HTTP version to make test reuse more convenient - - make sure the weekday in Date headers matches the date - - test61: replace stray "^M" (5e 4d) at the end of a cookie with a '^M' (0d) - - Gets the test working with external proxies like Privoxy again. - - Closes #6463 - -- ftp: never set data->set.ftp_append outside setopt - - Since the set value then risks getting used like that when the easy - handle is reused by the application. - - Also: renamed the struct field from 'ftp_append' to 'remote_append' - since it is also used for SSH protocols. - - Closes #6579 - -- urldata: remove the 'rtspversion' field - - from struct connectdata and the corresponding code in http.c that set - it. It was never used for anything! - - Closes #6581 - -- CURLOPT_QUOTE.3: clarify that libcurl doesn't parse what's sent - - ... so passed in commands may confuse libcurl's knowledge of state. - - Reported-by: Bodo Bergmann - Fixes #6577 - Closes #6580 - -- [Jacob Hoffman-Andrews brought this change] - - vtls: factor out Curl_ssl_getsock to field of Curl_ssl - - Closes #6558 - -- RELEASE-PROCEDURE: remove old release dates, add new - -- docs/SSL-PROBLEMS: enhanced - - Elaborate on the intermediate cert issue, and mention that anything - below TLS 1.2 is generally considered insecure these days. - - Closes #6572 - -- THANKS: remove a Jon Rumsey dupe - -Daniel Gustafsson (5 Feb 2021) -- [nimaje brought this change] - - docs: fix FILE example url in --metalink documentation - - In a url after <scheme>:// follows the possibly empty authority part - till the next /, so that url missed a /. - - Closes #6573 - Reviewed-by: Daniel Stenberg <daniel@haxx.se> - Reviewed-by: Daniel Gustafsson <daniel@yesql.se> - -Daniel Stenberg (5 Feb 2021) -- hostip: fix build with sync resolver - - Reported-by: David Goerger - Follow-up from 8335c6417 - Fixes #6566 - Closes #6568 - -- mailmap: Jon Rumsey - -- [Jon Rumsey brought this change] - - gskit: correct the gskit_send() prototype - - gskit_send() first paramater is a pointer to Curl_easy not connectdata - struct. - - Closes #6570 - Fixes #6569 - -- urldata: fix build without HTTP and MQTT - - Reported-by: Joseph Chen - Fixes #6562 - Closes #6563 - -- ftp: avoid SIZE when asking for a TYPE A file - - ... as we ignore it anyway because servers don't report the correct size - and proftpd even blatantly returns a 550. - - Updates a set of tests accordingly. - - Reported-by: awesomenode on github - Fixes #6564 - Closes #6565 - -- pingpong: rename the curl_pp_transfer enum to use PP prefix - - Using an FTP prefix for PP provided functionality was misleading. - -- RELEASE-NOTES: synced - - ... and bump pending version to 7.75.1 (for now) - -Jay Satiro (4 Feb 2021) -- build: fix --disable-http-auth - - Broken since 215db08 (precedes 7.75.0). - - Reported-by: Benbuck Nason - - Fixes https://github.com/curl/curl/issues/6567 - -- build: fix --disable-dateparse - - Broken since 215db08 (precedes 7.75.0). - - Bug: https://curl.se/mail/lib-2021-02/0008.html - Reported-by: Firefox OS - -Daniel Stenberg (4 Feb 2021) -- [Jon Rumsey brought this change] - - OS400: update for CURLOPT_AWS_SIGV4 - - chkstrings fails because a new string option that could require codepage - conversion has been added. - - Closes #6561 - Fixes #6560 - -- BUG-BOUNTY: removed the cooperation mention - -Version 7.75.0 (3 Feb 2021) - -Daniel Stenberg (3 Feb 2021) -- RELEASE-NOTES: synced - -- THANKS: added contributors from 7.75.0 - -- copyright: fix year ranges in need of updates - -- TODO: remove items for next SONAME bump etc - - We want to avoid that completely, so we don't plan for things after such - an event. - -- [Jay Satiro brought this change] - - ngtcp2: Fix build error due to change in ngtcp2_settings - - - Separate ngtcp2_transport_params. - - ngtcp2/ngtcp2@05d7adc made ngtcp2_transport_params separate from - ngtcp2_settings. - - ngtcp2 master is required to build curl with http3 support. - - Closes #6554 - -- vtls: remove md5sum - - As it is not used anymore. - - Reported-by: Jacob Hoffman-Andrews - Bug: https://curl.se/mail/lib-2021-02/0000.html - - Closes #6557 - -- [Alessandro Ghedini brought this change] - - quiche: don't use primary_ip / primary_port - - Closes #6555 - -Alessandro Ghedini (1 Feb 2021) -- travis: enable quiche's FFI feature - -Daniel Stenberg (30 Jan 2021) -- [Dmitry Wagin brought this change] - - http: improve AWS HTTP v4 Signature auth - - - Add support services without region and service prefixes in - the URL endpoint (ex. Min.IO, GCP, Yandex Cloud, Mail.Ru Cloud Solutions, etc) - by providing region and service parameters via aws-sigv4 option. - - Add [:region[:service]] suffix to aws-sigv4 option; - - Fix memory allocation errors. - - Refactor memory management. - - Use Curl_http_method instead() STRING_CUSTOMREQUEST. - - Refactor canonical headers generating. - - Remove repeated sha256_to_hex() usage. - - Add some docs fixes. - - Add some codestyle fixes. - - Add overloaded strndup() for debug - curl_dbg_strndup(). - - Update tests. - - Closes #6524 - -- hyper: fix CONNECT to set 'data' as userdata - - Follow-up to 14e075d1a7fd - -- [Layla brought this change] - - connect: fix compile errors in `Curl_conninfo_local` - - .. for the `#else` (`!HAVE_GETSOCKNAME`) case - - Fixes https://github.com/curl/curl/issues/6548 - Closes #6549 - - Signed-off-by: Layla <layla@insightfulvr.com> - -- [Michał Antoniak brought this change] - - transfer: fix GCC 10 warning with flag '-Wint-in-bool-context' - - ... and return the error code from the Curl_mime_rewind call. - - Closes #6537 - -- [Michał Antoniak brought this change] - - avoid warning: enum constant in boolean context - -- copyright: fix missing year (range) updates - -- RELEASE-NOTES: synced - -- openssl: lowercase the hostname before using it for SNI - - ... because it turns out several servers out there don't actually behave - correctly otherwise in spite of the fact that the SNI field is - specifically said to be case insensitive in RFC 6066 section 3. - - Reported-by: David Earl - Fixes #6540 - Closes #6543 - -- KNOWN_BUGS: cmake: ExternalProject_Add does not set CURL_CA_PATH - - Closes #6313 - -- KNOWN_BUGS: Multi perform hangs waiting for threaded resolver - - Closes #4852 - -- KNOWN_BUGS: "pulseUI VPN client" is known to be buggy - - First entry in the new section "applications" for known problems in - libcurl using applications. - - Closes #6306 - -- tool_writeout: make %{errormsg} blank for no errors - - Closes #6539 - -Jay Satiro (27 Jan 2021) -- [Gisle Vanem brought this change] - - build: fix djgpp builds - - - Update build instructions in packages/DOS/README - - - Extend 'VPATH' with 'vquic' and 'vssh'. - - - Allow 'Makefile.dist' to build both 'lib' and 'src'. - - - Allow using the Windows hosted djgpp cross compiler to build for MSDOS - under Windows. - - - 'USE_SSL' -> 'USE_OPENSSL' - - - Added a 'link_EXE' macro. Etc, etc. - - - Linking 'curl.exe' needs '$(CURLX_CFILES)' too. - - - Do not pick-up '../lib/djgpp/*.o' files. Recompile locally. - - - Generate a gzipped 'tool_hugehelp.c' if 'USE_ZLIB=1'. - - - Remove 'djgpp-clean' - - - Adapt to new C-ares directory structure - - - Use conditional variable assignments - - Clarify the 'conditional variable assignment' in 'common.dj'. - - Closes https://github.com/curl/curl/pull/6382 - -Daniel Stenberg (27 Jan 2021) -- [Ikko Ashimine brought this change] - - hyper: fix typo in c-hyper.c - - settting -> setting - - Closes #6538 - -- libssh2: fix CURL_LIBSSH2_DEBUG-enabled build - - Follow-up to 2dcc940959772a - - Reported-by: Gisle Vanem - Bug: https://github.com/curl/curl/commit/2dcc940959772a652f6813fb6bd3092095a4877b#commitcomment-46420088 - -Jay Satiro (27 Jan 2021) -- asyn-thread: fix build for when getaddrinfo missing - - This is a follow-up to 8315343 which several days ago moved the resolver - pointer into the async struct but did not update the code that uses it - when getaddrinfo is not present. - - Closes https://github.com/curl/curl/pull/6536 - -Daniel Stenberg (27 Jan 2021) -- urldata: move 'ints' to the end of 'connectdata' - - To optimize storage slightly. - - Closes #6534 - -- urldata: store ip version in a single byte - - Closes #6534 - -- urldata: remove duplicate 'upkeep_interval_ms' from connectdata - - ... and rely only on the value already set in Curl_easy. - - Closes #6534 - -- urldata: remove 'local_ip' from the connectdata struct - - As the info is already stored in the transfer handle anyway, there's no - need to carry around a duplicate buffer for the life-time of the handle. - - Closes #6534 - -- urldata: remove duplicate port number storage - - ... and use 'int' for ports. We don't use 'unsigned short' since -1 is - still often used internally to signify "unknown value" and 0 - 65535 are - all valid port numbers. - - Closes #6534 - -- urldata: remove the duplicate 'ip_addr_str' field - - ... as the numerical IP address is already stored and kept in 'primary_ip'. - - Closes #6534 - -- select: convert Curl_select() to private static function - - The old function should not be used anywhere anymore (the only remaining - gskit use has to be fixed to instead use Curl_poll or none at all). - - The static function version is now called our_select() and is only built - if necessary. - - Closes #6531 - -- Curl_chunker: shrink the struct - - ... by removing a field, converting the hex index into a byte and - rearranging the order. Cuts it down from 48 bytes to 32 on x86_64. - - Closes #6527 - -- curl: include the file name in --xattr/--remote-time error msgs - -- curl: s/config->global/global/ in single_transfer() - -- curl: move fprintf outputs to warnf - - For setting and getting time of the download. To make the outputs - respect --silent etc. - - Reported-by: Viktor Szakats - Fixes #6533 - Closes #6535 - -- [Tatsuhiro Tsujikawa brought this change] - - ngtcp2: Fix http3 upload stall - - Closes #6521 - -- [Tatsuhiro Tsujikawa brought this change] - - ngtcp2: Fix stack buffer overflow - - Closes #6521 - -- warnless.h: remove the prototype for curlx_ultosi - - Follow-up to 217552503ff3 - -- warnless: remove curlx_ultosi - - ... not used anywhere - - Closes #6530 - -- [Patrick Monnerat brought this change] - - lib: remove conn->data uses - - Closes #6515 - -- pingpong: remove the 'conn' struct member - - ... as it's superfluous now when Curl_easy is passed in and we can - derive the connection from that instead and avoid the duplicate copy. - - Closes #6525 - -- hostip/proxy: remove conn->data use - - Closes #6513 - -- url: reduce conn->data references - - ... there are a few left but let's keep them to last - - Closes #6512 - -- scripts/singleuse: add curl_easy_option* - -Jay Satiro (25 Jan 2021) -- test410: fix for windows - - - Pass the very long request header via file instead of command line. - - Prior to this change the 49k very long request header string was passed - via command line and on Windows that is too long so it was truncated and - the test would fail (specifically msys CI). - - Closes https://github.com/curl/curl/pull/6516 - -Daniel Stenberg (25 Jan 2021) -- libssh2: move data from connection object to transfer object - - Readdir data, filenames and attributes are strictly related to the - transfer and not the connection. This also reduces the total size of the - fixed connectdata struct. - - Closes #6519 - -- RELEASE-NOTES: synced - -- [Patrick Monnerat brought this change] - - lib: remove conn->data uses - - Closes #6499 - -- hyper: remove the conn->data references - - Closes #6508 - -- travis: build ngtcp2 --with-gnutls - - ... since they disable it by default since a few days back. - - Closes #6506 - Fixes #6493 - -- hostip: remove conn->data from resolver functions - - This also moves the 'async' struct from the connectdata struct into the - Curl_easy struct, which seems like a better home for it. - - Closes #6497 - -Jay Satiro (22 Jan 2021) -- strerror: skip errnum >= 0 assertion on windows - - On Windows an error number may be greater than INT_MAX and negative once - cast to int. - - The assertion is checked only in debug builds. - - Closes https://github.com/curl/curl/pull/6504 - -Daniel Stenberg (21 Jan 2021) -- doh: make Curl_doh_is_resolved survive a NULL pointer - - ... if Curl_doh() returned a NULL, this function gets called anyway as - in a asynch procedure. Then the doh struct pointer is NULL and signifies - an OOM situation. - - Follow-up to 6246a1d8c6776 - -- wolfssh: remove conn->data references - - ... and repair recent build breakage - - Closes #6507 - -- http: empty reply connection are not left intact - - ... so mark the connection as closed in this condition to prevent that - verbose message to wrongly appear. - - Reported-by: Matt Holt - Bug: https://twitter.com/mholt6/status/1352130240265375744 - Closes #6503 - -- chunk/encoding: remove conn->data references - - ... by anchoring more functions on Curl_easy instead of connectdata - - Closes #6498 - -Jay Satiro (20 Jan 2021) -- [Erik Olsson brought this change] - - lib: save a bit of space with some structure packing - - - Reorder some internal struct members so that less padding is used. - - This is an attempt at saving a bit of space by packing some structs - (using pahole to find the holes) where it might make sense to do - so without losing readability. - - I.e., I tried to avoid separating fields that seem grouped - together (like the cwd... fields in struct ftp_conn for instance). - Also abstained from touching fields behind conditional macros as - that quickly can get complicated. - - Closes https://github.com/curl/curl/pull/6483 - -Daniel Stenberg (20 Jan 2021) -- INSTALL.md: fix typo - - Found-by: Marcel Raad - -- [Fabian Keil brought this change] - - http: get CURLOPT_REQUEST_TARGET working with a HTTP proxy - - Added test 1613 to verify. - - Closes #6490 - -- Merge branch 'bagder/curl_range-data-conn' - -- ftp: remove conn->data leftover - -- curl_range: remove conn->data - - Closes #6496 - -- INSTALL: now at 85 operating systems - -- quiche: fix unused parameter ‘conn’ - - Follow-up to 2bdec0b3 - -- transfer: fix ‘conn’ undeclared mistake for iconv build - - Follow-up to 219d9f8620d - -- doh: allocate state struct on demand - - ... instead of having it static within the Curl_easy struct. This takes - away 1176 bytes (18%) from the Curl_easy struct that aren't used very - often and instead makes the code allocate it when needed. - - Closes #6492 - -- socks: use the download buffer instead - - The SOCKS code now uses the generic download buffer for temporary - storage during the connection procedure, instead of having its own - private 600 byte buffer that adds to the connectdata struct size. This - works fine because this point the buffer is allocated but is not use for - download yet since the connection hasn't completed. - - This reduces the connection struct size by 22% on a 64bit arch! - - The SOCKS buffer needs to be at least 600 bytes, and the download buffer - is guaranteed to never be smaller than 1000 bytes. - - Closes #6491 - -- urldata: make magic be the first struct field - - By making the `magic` identifier the same size and at the same place - within the structs (easy, multi, share), libcurl will be able to more - reliably detect and safely error out if an application passes in the - wrong handle to APIs. Easier to detect and less likely to cause crashes - if done. - - Such mixups can't be detected at compile-time due to them being - typedefed void pointers - unless `CURL_STRICTER` is defined. - - Closes #6484 - -- http_chunks: correct and clarify a comment on hexnumber length - - ... and also rename the define for max length. - - Closes #6489 - -- curl_path: remove conn->data use - - Closes #6487 - -- transfer: remove conn->data use - - Closes #6486 - -- quic: remove conn->data use - - Closes #6485 - -- [Fabian Keil brought this change] - - Add test1181: Proxy request with --proxy-header "Connection: Keep-Alive" - -- [Fabian Keil brought this change] - - Add test1180: Proxy request with -H "Proxy-Connection: Keep-Alive" - - At the moment the test fails as curl sends two Proxy-Connection - headers. - -- c-hyper: avoid duplicated Proxy-Connection headers - -- http: make providing Proxy-Connection header not cause duplicated headers - - Fixes test 1180 - - Bug: https://curl.se/mail/lib-2021-01/0095.html - Reported-by: Fabian Keil - Closes #6472 - -- runtests: preprocess DISABLED to allow conditionals - - ... with this function provided, we can disable tests for specific - environments and setups directly within this file. - - Closes #6477 - -- runtests: turn preprocessing into a separate function - - ... and remove all other variable substitutions as they're now done once - and for all in the preprocessor. - -- lib/Makefile.inc: convert to listing each file on its own line - - ... to make it diff friendlier and easier to read. - - Closes #6448 - -- ftplistparser: remove use of conn->data - - Closes #6482 - -- lib: more conn->data cleanups - - Closes #6479 - -- [Patrick Monnerat brought this change] - - vtls: reduce conn->data use - - Closes #6474 - -- hyper: deliver data to application with Curl_client_write - - ... just as the native code path does. Avoids sending too large data - chunks in the callback and more. - - Reported-by: Gisle Vanem - Fixes #6462 - Closes #6473 - -- gopher: remove accidental conn->data leftover - -- libssh: avoid plain free() of libssh-memory - - Since curl's own memory debugging system redefines free() calls to track - and fiddle with memory, it cannot be used on memory allocated by 3rd - party libraries. - - Third party libraries SHOULD NOT require free() to release allocated - resources for this reason - and libs can use separate healp allocators - on some systems (like Windows) so free() doesn't necessarily work - anyway. - - Filed as an issue with libssh: https://bugs.libssh.org/T268 - - Closes #6481 - -- send: assert that Curl_write_plain() has a ->conn when called - - To help catch bad invokes. - - Closes #6476 - -- test410: verify HTTPS GET with a 49K request header - - skip test 410 for mesalink in the CI as it otherwise hangs "forever" - -- lib: pass in 'struct Curl_easy *' to most functions - - ... in most cases instead of 'struct connectdata *' but in some cases in - addition to. - - - We mostly operate on transfers and not connections. - - - We need the transfer handle to log, store data and more. Everything in - libcurl is driven by a transfer (the CURL * in the public API). - - - This work clarifies and separates the transfers from the connections - better. - - - We should avoid "conn->data". Since individual connections can be used - by many transfers when multiplexing, making sure that conn->data - points to the current and correct transfer at all times is difficult - and has been notoriously error-prone over the years. The goal is to - ultimately remove the conn->data pointer for this reason. - - Closes #6425 - -Emil Engler (17 Jan 2021) -- docs: fix typos in NEW-PROTOCOL.md - - This fixes a misspelled "it" and a grammatically wrong "-ing" suffix. - - Closes #6471 - -Daniel Stenberg (16 Jan 2021) -- RELEASE-NOTES: synced - -Jay Satiro (16 Jan 2021) -- [Razvan Cojocaru brought this change] - - cmake: expose CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG - - This does for cmake builds what --disable-openssl-auto-load-config - does for autoconf builds. - - Closes https://github.com/curl/curl/pull/6435 - -Daniel Stenberg (15 Jan 2021) -- test1918: verify curl_easy_option_by_name() and curl_easy_option_by_id() - - ... and as a practical side-effect, make sure that the - Curl_easyopts_check() function is asserted in debug builds, which we - want to detect mismatches between the options list in easyoptions.c and - the options in curl.h - - Found-by: Gisle Vanem - Bug: https://github.com/curl/curl/commit/08e8455dddc5e48e58a12ade3815c01ae3da3b64#commitcomment-45991815 - - Closes #6461 - -- [Gisle Vanem brought this change] - - easyoptions: add the missing AWS_SIGV4 - - Follow-up from AWS_SIGV4 - -- schannel_verify: fix safefree call typo - - Follow-up from e87ad71d1ba00519 - - Closes #6459 - -- mime: make sure setting MIMEPOST to NULL resets properly - - ... so that a function can first use MIMEPOST and then set it to NULL to - reset it back to a blank POST. - - Added test 584 to verify the fix. - - Reported-by: Christoph M. Becker - - Fixes #6455 - Closes #6456 - -- multi: set the PRETRANSFER time-stamp when we switch to PERFORM - - ... instead of at end of the DO state. This makes the timer more - accurate for the protocols that use the DOING state (such as FTP), and - simplifies how the function (now called init_perform) is called. - - The timer will then include the entire procedure up to PERFORM - - including all instructions for getting the transfer started. - - Closes #6454 - -- CURLINFO_PRETRANSFER_TIME.3: clarify - - ... the timer *does* include the instructions for getting the remote - file. - - Ref: #6452 - Closes #6453 - -- [Gisle Vanem brought this change] - - schannel: plug a memory-leak - - ... when built without -DUNICODE. - - Closes #6457 - -Jay Satiro (14 Jan 2021) -- gitattributes: Set batch files to CRLF line endings on checkout - - If a batch file is run without CRLF line endings (ie LF-only) then - arbitrary behavior may occur. I consider that a bug in Windows, however - the effects can be serious enough (eg unintended code executed) that - we're fixing it in the repo by requiring CRLF line endings for batch - files on checkout. - - Prior to this change the checked-out line endings of batch files were - dependent on a user's git preferences. On Windows it is common for git - users to have automatic CRLF conversion enabled (core.autocrlf true), - but those users that don't would run into this behavior. - - For example a user has reported running the Visual Studio project - generator batch file (projects/generate.bat) and it looped forever. - Output showed that the Windows OS interpreter was occasionally jumping - to arbitrary points in the batch file and executing commands. This - resulted in unintended files being removed (a removal sequence called) - and looping forever. - - Ref: https://serverfault.com/q/429594 - Ref: https://stackoverflow.com/q/232651 - Ref: https://www.dostips.com/forum/viewtopic.php?t=8988 - Ref: https://git-scm.com/docs/gitattributes#_checking_out_and_checking_in - Ref: https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_core_autocrlf - - Bug: https://github.com/curl/curl/discussions/6427 - Reported-by: Ganesh Kamath - - Closes https://github.com/curl/curl/pull/6442 - -Daniel Stenberg (14 Jan 2021) -- tool_operate: spellfix a comment - -- ROADMAP: refreshed - - o removed HSTS - already implemented - o added HTTPS RR records - o mention HTTP/3 completion - -- http_chunks: remove Curl_ prefix from static functions - -- transfer: remove Curl_ prefix from static functions - -- tftp: remove Curl_ prefix from static functions - -- multi: remove Curl_ prefix from static functions - -- ldap: remove Curl_ prefix from static functions - -- doh: remove Curl_ prefix from static functions - -- asyn-ares: remove Curl_ prefix from static functions - -- vtls: remove Curl_ prefix from static functions - -- bearssl: remove Curl_ prefix from static functions - -- mbedtls: remove Curl_ prefix from static functions - -- wolfssl: remove Curl_ prefix from static functions - -- nss: remove Curl_ prefix from static functions - -- gnutls: remove Curl_ prefix from static functions - -- openssl: remove Curl_ prefix from static functions - - ... as we reserve this prefix to library-wide functions. - - Closes #6443 - -- nss: get the run-time version instead of build-time - - Closes #6445 - -Jay Satiro (12 Jan 2021) -- tool_doswin: Restore original console settings on CTRL signal - - - Move Windows terminal init code from tool_main to tool_doswin. - - - Restore the original console settings on CTRL+C and CTRL+BREAK. - - Background: On Windows the curl tool changes the console settings to - enable virtual terminal processing (eg color output) if supported - (ie Win 10). The original settings are restored on exit but prior to - this change were not restored in the case of the CTRL signals. - - Windows VT behavior varies depending on console/powershell/terminal; - refer to the discussion in #6226. - - Assisted-by: Rich Turner - - Closes https://github.com/curl/curl/pull/6226 - -Daniel Stenberg (12 Jan 2021) -- gen.pl: fix perl syntax - - Follow-up to 324cf1d2e - -- [Emil Engler brought this change] - - help: update to current codebase - - This commit bumps the help to the current state of the project. - - Closes #6437 - -- [Emil Engler brought this change] - - docs: fix line length bug in gen.pl - - The script warns if the length of $opt and $desc is > 78. However, these - two variables are on totally separate lines so the check makes no sense. - Also the $bitmask field is totally forgotten. Currently this leads to - two warnings within `--resolve` and `--aws-sigv4`. - - Closes #6438 - -- [Emil Engler brought this change] - - docs: fix wrong documentation in help.d - - curl does not list all categories when you invoke "--help" without any - parameters. - - Closes #6436 - -- aws-sigv4.d: polish the wording - - Make it shorter and imperative form - - Closes #6439 - -- [Fabian Keil brought this change] - - misc: fix typos - - Bug: https://curl.se/mail/lib-2021-01/0063.html - Closes #6434 - -- multi_runsingle: bail out early on data->conn == NULL - - As that's a significant error condition and scan-build warns for NULL - pointer dereferences if we don't. - - Closes #6433 - -- multi: skip DONE state if there's no connection left for ftp wildcard - - ... to avoid running in that state with data->conn being NULL. - -- libssh2: fix "Value stored to 'readdir_len' is never read" - - Detected by scan-build - -- connect: mark intentional ignores of setsockopt return values - - Pointed out by Coverity - - Closes #6431 - -Jay Satiro (11 Jan 2021) -- http_proxy: Fix CONNECT chunked encoding race condition - - - During the end-of-headers response phase do not mark the tunnel - complete unless the response body was completely parsed/ignored. - - Prior to this change if the entirety of a CONNECT response with chunked - encoding was not received by the time the final header was parsed then - the connection would be marked done prematurely, before all the chunked - data could be read in and ignored (since this is what we do with any - CONNECT response body) and the connection could not be used. - - Bug: https://curl.se/mail/lib-2021-01/0033.html - Reported-by: Fabian Keil - - Closes https://github.com/curl/curl/pull/6432 - -Daniel Stenberg (11 Jan 2021) -- RELEASE-NOTES: synced - -- url: if IDNA conversion fails, fallback to Transitional - - This improves IDNA2003 compatiblity. - - Reported-by: Bubu on github - Fixes #6423 - Closes #6428 - -- travis: make the Hyper build from its master branch - - Closes #6430 - -- http: make 'authneg' also work for Hyper - - When doing a request with a request body expecting a 401/407 back, that - initial request is sent with a zero content-length. Test 177 and more. - - Closes #6424 - -Jay Satiro (8 Jan 2021) -- cmake: Add an option to disable libidn2 - - New option USE_LIBIDN2 defaults to ON for libidn2 detection. Prior to - this change libidn2 detection could not be turned off in cmake builds. - - Reported-by: William A Rowe Jr - - Fixes https://github.com/curl/curl/issues/6361 - Closes https://github.com/curl/curl/pull/6362 - -Daniel Stenberg (8 Jan 2021) -- HYPER: no longer needs the special branch - -- test179: use consistent header line endings - - ... to make "Hyper mode" work better. - -- file: don't provide content-length for directories - - ... as it is misleading. - - Ref #6379 - Closes #6421 - -- TODO: Directory listing for FILE: - - Ref #6379 - -- curl.h: add CURLPROTO_GOPHERS as own protocol identifier - - Follow-up to a1f06f32b860, to make sure it can be handled separately - from plain gopher. - - Closes #6418 - -- http: have CURLOPT_FAILONERROR fail after all headers - - ... so that Retry-After and other meta-content can still be used. - - Added 1634 to verify. Adjusted test 194 and 281 since --fail now also - includes the header-terminating CRLF in the output before it exits. - - Fixes #6408 - Closes #6409 - -- global_init: debug builds allocates a byte in init - - ... to make build tools/valgrind warn if no curl_global_cleanup is - called. - - This is conditionally only done for debug builds with the env variable - CURL_GLOBAL_INIT set. - - Closes #6410 - -- lib/unit tests: add missing curl_global_cleanup() calls - -- travis: adapt to Hyper build change - - Closes #6419 - -- pretransfer: setup the User-Agent header here - - ... and not in the connection setup, as for multiplexed transfers the - connection setup might be skipped and then the transfer would end up - without the set user-agent! - - Reported-by: Flameborn on github - Assisted-by: Andrey Gursky - Assisted-by: Jay Satiro - Assisted-by: Mike Gelfand - Fixes #6312 - Closes #6417 - -- test66: disable with Hyper - - ...as Hyper doesn't support HTTP/0.9 - -- c-hyper: poll the tasks until end correctly - - ... makes test 36 work. - - Closes #6412 - -- [Gergely Nagy brought this change] - - mk-ca-bundle.pl: deterministic output when using -t - - Printing trust purposes are now sorted, making the output deterministic - when running on the same input certdata.txt. - - Closes #6413 - -- KNOWN_BUGS: fixed "wolfSSL lacks support for renegotiation" - - Fixed by #6411 - -- [Himanshu Gupta brought this change] - - wolfssl: add SECURE_RENEGOTIATION support - - Closes #6411 - -- RELEASE-NOTES: synced - -- wolfssl: update copyright year range - - Follow-up to 7de2e96535e9 - -- c-hyper: make CURLE_GOT_NOTHING work - - Test 30 - - Closes #6407 - -- http_proxy: make CONNECT work with the Hyper backend - - Makes test 80 run - - Closes #6406 - -- TODO: --fail-with-body perchance? - -Jay Satiro (4 Jan 2021) -- tool_operate: fix the suppression logic of some error messages - - - Fix the failed truncation and failed writing body error messages to - not be shown unless error messages are shown. (ie the user has - specified -sS, or has not specified -s). - - - Also prefix same error messages with "curl: ", for example: - curl: (23) Failed to truncate, exiting - - Prior to this change the failed truncation error messages would be shown - if not -s, but did not account for -sS which should show. - - Prior to this change the failed writing body error messages would be - shown always. - - Ref: https://curl.se/docs/manpage.html#-S - - Bug: https://curl.se/mail/archive-2020-12/0017.html - Reported-by: Hongyi Zhao - - Closes https://github.com/curl/curl/pull/6402 - -- wolfssl: Support wolfSSL builds missing TLS 1.1 - - The wolfSSL TLS library defines NO_OLD_TLS in some of their build - configurations and that causes the library to be built without TLS 1.1. - For example if MD5 is explicitly disabled when building wolfSSL then - that defines NO_OLD_TLS and the library is built without TLS 1.1 [1]. - - Prior to this change attempting to build curl with a wolfSSL that was - built with NO_OLD_TLS would cause a build link error undefined reference - to wolfTLSv1_client_method. - - [1]: https://github.com/wolfSSL/wolfssl/blob/v4.5.0-stable/configure.ac#L2366 - - Bug: https://curl.se/mail/lib-2020-12/0121.html - Reported-by: Julian Montes - - Closes https://github.com/curl/curl/pull/6388 - -Daniel Stenberg (4 Jan 2021) -- test1633: set appropriate name - - "--retry with a 429 response and Retry-After:" - -- travis: limit the tests with quiche builds to HTTPS and FTPS only - - ... since it runs into the 50 minute time limit too often otherwise. - - Closes #6403 - -- HISTORY: added dates to early history - - Mostly thanks to this archived web page for urlget: - - https://web.archive.org/web/19980216125115/http://www.inf.ufrgs.br/~sagula/urlget.html - -- httpauth: make multi-request auth work with custom port - - When doing HTTP authentication and a port number set with CURLOPT_PORT, - the code would previously have the URL's port number override as if it - had been a redirect to an absolute URL. - - Added test 1568 to verify. - - Reported-by: UrsusArctos on github - Fixes #6397 - Closes #6400 - -- [Emil Engler brought this change] - - language: s/behaviour/behavior/g - - We currently use both spellings the british "behaviour" and the american - "behavior". However "behavior" is more used in the project so I think - it's worth dropping the british name. - - Closes #6395 - -- cmdline-opts/retry.d: mention response code 429 as well - - Reported-by: Cherish98 - Bug: https://curl.se/mail/archive-2020-12/0018.html - -- docs/HYPER.md: mention outstanding issues - - To make it more obvious to users what doesn't work (yet) - - Closes #6389 - -- COPYING/configure: bump copyright year range - -- c-hyper: add timecondition to the request - - Test 77-78 - - Closes #6391 - -- c-hyper: make Digest and NTLM work - - Test 64, 65, 67, 68, 69, 70, 72 - - Closes #6390 - -- examples/curlgtk.c: fix the copyright year range - - ... and make private functions static. - -- [Olaf Hering brought this change] - - docs/examples: adjust prototypes for CURLOPT_READFUNCTION - - The type of the buffer in curl_read_callback is 'char *', not 'void *'. - - Signed-off-by: Olaf Hering <olaf@aepfle.de> - Closes #6392 - -- examples: fix more empty expression statement has no effect - - Follow-up to 26e46617b9 - -- cleanup: fix two empty expression statement has no effect - - Follow-up to 26e46617b9 - -- configure: set -Wextra-semi-stmt for clang with --enable-debug - - To have it properly complain on empty statements with no effect. - - Ref: #6376 - Closes #6378 - -- tests/unit: fix empty statements with no effect - - ... by making macros use "do {} while(0)" - -- [Paul Groke brought this change] - - dns: extend CURLOPT_RESOLVE syntax for adding non-permanent entries - - Extend the syntax of CURLOPT_RESOLVE strings: allow using a '+' prefix - (similar to the existing '-' prefix for removing entries) to add - DNS cache entries that will time out just like entries that are added - by libcurl itself. - - Append " (non-permanent)" to info log message in case a non-permanent - entry is added. - - Adjust relevant comments to reflect the new behavior. - - Adjust documentation. - - Extend unit1607 to test the new functionality. - - Closes #6294 - -- schannel: fix "empty expression statement has no effect" - - Bug: https://github.com/curl/curl/commit/8ab78f720ae478d533e30b202baec4b451741579#commitcomment-45445950 - Reported-by: Gisle Vanem - Closes #6381 - -- [Denis Laxalde brought this change] - - docs: remove redundant "better" in --fail help - - Closes #6385 - -- [Kevin Ushey brought this change] - - curl.1: fix typo microsft -> microsoft - - Closes #6380 - -- [XhmikosR brought this change] - - misc: assorted typo fixes - - Closes #6375 - -- RELEASE-NOTES: synced - -- tool_operate: avoid NULL dereference of first_arg - - Follow-up to 6a5e020d4d2b04a - Identified by OSS-Fuzz - Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28999 - Closes #6377 - -- misc: fix "warning: empty expression statement has no effect" - - Turned several macros into do-while(0) style to allow their use to work - find with semicolon. - - Bug: https://github.com/curl/curl/commit/08e8455dddc5e48e58a12ade3815c01ae3da3b64#commitcomment-45433279 - Follow-up to 08e8455dddc5e4 - Reported-by: Gisle Vanem - Closes #6376 - -- KNOWN_BUGS: 6.10 curl never completes Negotiate over HTTP - - Closes #5235 - Closes #6370 - -- writeout: fix NULL dereference for "this url" - - Detected by torture test 1029 - - Follow-up to 7a90ddf88f5a - - Closes #6374 - -- failf: remove newline from formatting strings - - ... as failf adds one itself. - - Also: add an assert() to failf() that triggers on a newline in the - format string! - - Closes #6365 - -- [XhmikosR brought this change] - - CI: fix warning with the latest versions - - `git checkout HEAD^2` is no longer needed - - Closes #6369 - -- INSTALL: update the list known OSes and CPU archs curl has run on - - Closes #6366 - -- [Cherish98 brought this change] - - curl: fix handling of -q option - - The match of the "-q" option (short for "--disable") should: - a) allow concatenation with other single-letters; and - b) be case-sensitive, lest confusing with "-Q" ("--quote") - - Closes #6364 - -- tests/badsymbols.pl: ignore stand-alone single hash lines - - Bug: https://curl.se/mail/lib-2020-12/0084.html - Reported-by: Dennis Clarke - Assisted-by: Jay Satiro - - Closes #6355 - -- curl_easy_pause.3: add multiplexed pause effects - - and generally refresh and update. Remove details for ancient versions. - - Reviewed-by: Jay Satiro - Closes #6360 - -Jay Satiro (22 Dec 2020) -- curl_easy_pause.3: fix man page reference - - Follow-up to ac9a724 from earlier today. - - Ref: https://github.com/curl/curl/pull/6359 - -Daniel Stenberg (22 Dec 2020) -- EXPERIMENTAL: add the Hyper backend to the list - - ... of current experimental features in curl. - -- speedcheck: exclude paused transfers - - Paused transfers should not be stopped due to slow speed even when - CURLOPT_LOW_SPEED_LIMIT is set. Additionally, the slow speed timer is - now reset when the transfer is unpaused - as otherwise it would easily - just trigger immediately after unpausing. - - Reported-by: Harry Sintonen - Fixes #6358 - Closes #6359 - -- h2: do not wait for RECV on paused transfers - - ... as the socket might be readable all the time when paused and thus - causing a busy-loop. - - Reported-by: Harry Sintonen - Reviewed-by: Jay Satiro - Fixes #6356 - Closes #6357 - -- RELEASE-NOTES: synced - -- cmdline-opts/gen.pl: return hard on errors - - ... as the warnings tend to go unnoticed otherwise! - - Closes #6354 - -- examples/libtest: add .checksrc to dist - - ... so that (auto)builds from tarballs also get the correct instructions. - - Fixes #6176 - Closes #6353 - -- test: verify new --write-out variables - - Extended test 1029 and added 1188 - -- test970: adapted to the new internal order of variables - -- curl: add variables to --write-out - - In particular, these ones can help a user to create its own error - message when one or transfers fail. - - writeout: add 'onerror', 'url', 'urlnum', 'exitcode', 'errormsg' - - onerror - lets a user only show the rest on non-zero exit codes - - url - the input URL used for this transfer - - urlnum - the numerical URL counter (0 indexed) for this transfer - - exitcode - the numerical exit code for the transfer - - errormsg - obvious - - Reported-by: Earnestly on github - Fixes #6199 - Closes #6207 - -- [Matthias Gatto brought this change] - - tests: add very simple AWS HTTP v4 Signature test - - Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> - -- [Matthias Gatto brought this change] - - docs: add AWS HTTP v4 Signature - -- [Matthias Gatto brought this change] - - tool: add AWS HTTP v4 Signature support - - Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> - -- [Matthias Gatto brought this change] - - http: Make the call to v4 signature - - This patch allow to call the v4 signature introduce in previous commit - - Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> - -- [Matthias Gatto brought this change] - - http: introduce AWS HTTP v4 Signature - - It is a security process for HTTP. - - It doesn't seems to be standard, but it is used by some cloud providers. - - Aws: - https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html - Outscale: - https://wiki.outscale.net/display/EN/Creating+a+Canonical+Request - GCP (I didn't test that this code work with GCP though): - https://cloud.google.com/storage/docs/access-control/signing-urls-manually - - most of the code is in lib/http_v4_signature.c - - Information require by the algorithm: - - The URL - - Current time - - some prefix that are append to some of the signature parameters. - - The data extracted from the URL are: the URI, the region, - the host and the API type - - example: - https://api.eu-west-2.outscale.com/api/latest/ReadNets - ~~~ ~~~~~~~~ ~~~~~~~~~~~~~~~~~~~ - ^ ^ ^ - / \ URI - API type region - - Small description of the algorithm: - - make canonical header using content type, the host, and the date - - hash the post data - - make canonical_request using custom request, the URI, - the get data, the canonical header, the signed header - and post data hash - - hash canonical_request - - make str_to_sign using one of the prefix pass in parameter, - the date, the credential scope and the canonical_request hash - - compute hmac from date, using secret key as key. - - compute hmac from region, using above hmac as key - - compute hmac from api_type, using above hmac as key - - compute hmac from request_type, using above hmac as key - - compute hmac from str_to_sign using above hmac as key - - create Authorization header using above hmac, prefix pass in parameter, - the date, and above hash - - Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> - - Closes #5703 - -- [Matthias Gatto brought this change] - - http: add hmac support for sha256 - - It seems current hmac implementation use md5 for the hash, - V4 signature require sha256, so I've added the needed struct in - this commit. - - I've added the functions that do the hmac in v4 signature file - as a static function ,in the next patch of the serie, - because it's used only by this file. - - Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> - -- [Cristian Rodríguez brought this change] - - connect: on linux, enable reporting of all ICMP errors on UDP sockets - - The linux kernel does not report all ICMP errors back to userspace due - to historical reasons. - - IP*_RECVERR sockopt must be turned on to have the correct behaviour - which is to pass all ICMP errors to userspace. - - See https://bugzilla.kernel.org/show_bug.cgi?id=202355 - - Closes #6341 - -- curl: add --create-file-mode [mode] - - This option sets the (octal) mode to use for the remote file when one is - created, using the SFTP, SCP or FILE protocols. When not set, the - default is 0644. - - Closes #6244 - -- c-hyper: fix compiler warnings - - Identified by clang on windows. - - Reported-by: Gisle Vanem - Bug: 58974d25d8173aec154e593ed9d866da566c9811 - - Closes #6351 - -- KNOWN_BUGS: Remote recursive folder creation with SFTP - - Closes #5204 - -Jay Satiro (20 Dec 2020) -- badsymbols.pl: Add verbose mode -v - - Use -v as the first option to enable verbose mode which will show source - input, extracted symbol and line info. For example: - - Source: ./../include/curl/typecheck-gcc.h - Symbol: curlcheck_socket_info(info) - Line #423: #define curlcheck_socket_info(info) \ - - Ref: https://curl.se/mail/lib-2020-12/0084.html - - Closes https://github.com/curl/curl/pull/6349 - -- KNOWN_BUGS: Secure Transport disabling hostname validation also disables SNI - - That behavior is a limitation of Apple's Secure Transport. - - Reported-by: Cory Benfield - Reported-by: Ian Spence - Confirmed-by: Nick Zitzmann - - Ref: https://github.com/curl/curl/issues/998 - - Closes https://github.com/curl/curl/issues/6347 - Closes https://github.com/curl/curl/pull/6348 - -Daniel Stenberg (18 Dec 2020) -- TODO: alt-svc should fallback if alt-svc doesn't work - - Closes #4908 - -- travis: restrict the openssl3 job to only run https and ftps tests - - ... as it runs too long otherwise and the other tests are verified in - other builds anyway. - - Closes #6345 - -- build: repair http disabled but mqtt enabled build - - ... as the mqtt code reuses the "method" originally used for HTTP. - - Closes #6344 - -- [Jon Wilkes brought this change] - - cookie: avoid the C1001 internal compiler error with MSVC 14 - - Fixes #6112 - Closes #6135 - -- RELEASE-NOTES: synced - -- mqtt: handle POST/PUBLISH without a set POSTFIELDSIZE - - Detected by OSS-Fuzz - Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28735 - - Added test 1916 and 1917 to verify. - - Closes #6338 - -- travis: add CI job for Hyper build - -- tests: updated tests for Hyper - -- lib: introduce c-hyper for using Hyper - - ... as an alternative HTTP backend within libcurl. - -- tool_setopt: provide helper output in debug builds - - ... for when setopt() returns error. - -- setopt: adjust to Hyper and disabled HTTP builds - -- rtsp: disable if Hyper is used - -- getinfo: build with disabled HTTP support - -- version: include hyper version - -- docs: add HYPER.md - -- configure: add --with-hyper - - As the first (optional) HTTP backend alternative instead of native - - Close #6110 - -- test1522: add debug tracing - - I used this to track down some issues and I figured I could just as well - keep this extra logging in here for future needs. - - Closes #6331 - -- http: show the request as headers even when split-sending - - When the initial request isn't possible to send in its entirety, the - remainder of request would be delivered to the debug callback as data - and would wrongly be counted internally as body-bytes sent. - - Extended test 1295 to verify. - - Closes #6328 - -- multi: when erroring in TOOFAST state, act as for PERFORM - - When failing in TOOFAST, the multi_done() wasn't called so the same - cleanup and handling wasn't done like when it fails in PERFORM, which in - the case of FTP could mean that the control connection wouldn't be - marked as "dead" for the CURLE_ABORTED_BY_CALLBACK case. Which caused - ftp_disconnect() to use it to send "QUIT", which could end up waiting - for a response a long time before giving up! - - Reported-by: Tomas Berger - Fixes #6333 - Closes #6337 - -- cmake: enable gophers correctly in curl-config - - Closes #6336 - -- test1198/9: add two mqtt publish tests without payload lengths - - Closes #6335 - -- tests/mqttd: extract the client id from the correct offset - - Closes #6334 - -- TODO: Prevent terminal injection when writing to terminal - - Closes #6150 - -- Revert "CI/github: work-around for brew breakage on macOS" - - This reverts commit 4cbb17a2cbbbe6337142d39479e21c3990b9c22f. - - ... as the work-around now causes failures. - - Closes #6332 - -- examples: remove superfluous asterisk uses - - ... for function pointers. Breaks in ancient compilers. - -- RELEASE-NOTES: synced - -- test1272: fix line ending - - Follow-up to f24784f9143 - -- URL-SYNTAX: add gophers details - -- test1272: test gophers - -- runtests: add support for gophers, gopher over TLS - -- [parazyd brought this change] - - gopher: Implement secure gopher protocol. - - This commit introduces a "gophers" handler inside the gopher protocol if - USE_SSL is defined. This protocol is no different than the usual gopher - prococol, with the added TLS encapsulation upon connecting. The protocol - has been adopted in the gopher community, and many people have enabled - TLS in their gopher daemons like geomyidae(8), and clients, like clic(1) - and hurl(1). - - I have not implemented test units for this protocol because my knowledge - of Perl is sub-par. However, for someone more knowledgeable it might be - fairly trivial, because the same test that tests the plain gopher - protocol can be used for "gophers" just by adding a TLS listener. - - Signed-off-by: parazyd <parazyd@dyne.org> - - Closes #6208 - -- TODO: Package curl for Windows in a signed installer - - Closes #5424 - -- mqtt: deal with 0 byte reads correctly - - OSS-Fuzz found it - Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28676 - - Closes #6327 - -- BUG-BOUNTY: minor language update - - ... and remove the wording about entries from before 2019 as the "within - 12 months" is still there and covers that. - - Closes #6318 - -- tooĺ_writeout: fix the -w time output units - - Fix regression from commit fc813f80e1bcac (#6248) that changed the unit - to microseconds instead of seconds with fractions - - Reported-by: 不确定 - Fixes #6321 - Closes #6322 - -- quiche: remove fprintf() leftover - -Jay Satiro (14 Dec 2020) -- KNOWN_BUGS: SHA-256 digest not supported in Windows SSPI builds - - Closes https://github.com/curl/curl/issues/6302 - -- digest_sspi: Show InitializeSecurityContext errors in verbose mode - - The error is shown with infof rather than failf so that the user will - see the extended error message information only in verbose mode, and - will still see the standard CURLE_AUTH_ERROR message. For example: - - --- - - * schannel: InitializeSecurityContext failed: SEC_E_QOP_NOT_SUPPORTED - (0x8009030A) - The per-message Quality of Protection is not supported by - the security package - * multi_done - * Connection #1 to host 127.0.0.1 left intact - curl: (94) An authentication function returned an error - - --- - - Ref: https://github.com/curl/curl/issues/6302 - - Closes https://github.com/curl/curl/pull/6315 - -Daniel Stenberg (13 Dec 2020) -- URL-SYNTAX: add default port numbers and IDNA details - - Closes #6316 - -- URL-SYNTAX: mention how FILE:// access can access network on windows - - Closes #6314 - -Jay Satiro (12 Dec 2020) -- URL-SYNTAX: Document default SMTP port 25 - - Note that ports 25 and 587 are common ports for smtp, the former being - the default. - - Closes https://github.com/curl/curl/pull/6310 - -Daniel Stenberg (12 Dec 2020) -- CURLOPT_URL.3: remove scheme specific details - - ... that are now found in URL-SYNTAX.md - - Closes #6307 - -Dan Fandrich (12 Dec 2020) -- docs: Fix some typos - - [skip ci] - -Daniel Stenberg (12 Dec 2020) -- URL-SYNTAX: mention all supported schemes - - Closes #6311 - -- [Douglas R. Reno brought this change] - - URL-SYNTAX.md: minor language improvements - - Closes #6308 - -- docs/URL-SYNTAX: the URL syntax curl accepts and works with - - Closes #6285 - -- [0xflotus brought this change] - - docs: enable syntax highlighting in several docs files - - ... for better readability - - Closes #6286 - -- test1564/1565: require the 'wakeup' feature to run - - Fixes #6299 - Fixes #6300 - Closes #6301 - -- runtests: add 'wakeup' as a feature - -- tests/server/disabled: add "wakeup" - - To allow the test suite to know if wakeup support is disabled in the - build. - -- lib1564/5: verify that curl_multi_wakeup returns OK - -- tests: make --libcurl tests only test FTP options if ftp enabled - - Adjust six --libcurl tests to only check the FTP option if FTP is - actually present in the build. - - Fixes #6303 - Closes #6305 - -- runtests.pl: fix "uninitialized value" warning - - follow-up to e12825c642a88774 - -- runtests: add support for %if [feature] conditions - - ... to make tests run differently or expect different results depending - on what features that are present or not in curl. - - Bonus: initial minor 'Hyper' awareness but nothing is using that yet - - Closes #6304 - -- [Jon Rumsey brought this change] - - OS400: update ccsidcurl.c - - Add 'struct' to cast and declaration of cfcdata to fix compilation - error. - - Fixes #6292 - Closes #6297 - -- ngtcp2: make it build it current master again - - Closes #6296 - -- [Cristian Rodríguez brought this change] - - connect: defer port selection until connect() time - - If supported, defer port selection until connect() time - if --interface is given and source port is 0. - - Reproducer: - - * start fast webserver on port 80 - * starve system of ephemeral ports - $ sysctl net.ipv4.ip_local_port_range="60990 60999" - - * start a curl/libcurl "crawler" - $curl --keepalive --parallel --parallel-immediate --head --interface - 127.0.0.2 "http://127.0.0.[1-254]/file[001-002].txt" - - current result: - (possible some successful data) - curl: (45) bind failed with errno 98: Address already in use - - result after patch: - (complete success or few connections failing, higlhy depending on load) - - Fail only when all the possible 4-tuple combinations are exhausted, - which is impossible to do when port is selected at bind() time becuse - the kernel does not know if socket will be listen()'ed on or connect'ed - yet. - - Closes #6295 - -- [Hans-Christian Noren Egtvedt brought this change] - - connect: zero variable on stack to silence valgrind complaint - - Valgrind will complain that ssrem buffer usage if not explicit - initialized, hence initialize it to zero. - - This completes the change intially started in commit 2c0d7212151 ('ftp: - retry getpeername for FTP with TCP_FASTOPEN') where the ssloc buffer has - a similar memset to zero. - - Signed-off-by: Hans-Christian Noren Egtvedt <hegtvedt@cisco.com> - Closes #6289 - -- RELEASE-NOTES: synced - - start over on the next release cycle - -Version 7.74.0 (9 Dec 2020) - -Daniel Stenberg (9 Dec 2020) -- RELEASE-NOTES: synced - - for 7.74.0 - -Jay Satiro (7 Dec 2020) -- [Jacob Hoffman-Andrews brought this change] - - urldata: restore comment on ssl_connect_data.use - - This comment was originally on the `use` field, but was separated from - its field in 62a2534. - - Closes https://github.com/curl/curl/pull/6287 - -Daniel Stenberg (7 Dec 2020) -- VERSIONS: refreshed - - We always use the patch number these days: all releases are - "major.minor.patch" - -- [Jakub Zakrzewski brought this change] - - cmake: don't use reserved target name 'test' - - CMake up to 3.10 always reserves this name - - Fixes #6257 - Closes #6258 - -- openssl: make the OCSP verification verify the certificate id - - CVE-2020-8286 - - Reported by anonymous - - Bug: https://curl.se/docs/CVE-2020-8286.html - -- ftp: make wc_statemach loop instead of recurse - - CVE-2020-8285 - - Fixes #6255 - Bug: https://curl.se/docs/CVE-2020-8285.html - Reported-by: xnynx on github - -- ftp: CURLOPT_FTP_SKIP_PASV_IP by default - - The command line tool also independently sets --ftp-skip-pasv-ip by - default. - - Ten test cases updated to adapt the modified --libcurl output. - - Bug: https://curl.se/docs/CVE-2020-8284.html - CVE-2020-8284 - - Reported-by: Varnavas Papaioannou - -- urlapi: don't accept blank port number field without scheme - - ... as it makes the URL parser accept "very-long-hostname://" as a valid - host name and we don't want that. The parser now only accepts a blank - (no digits) after the colon if the URL starts with a scheme. - - Reported-by: d4d on hackerone - - Closes #6283 - -- Revert "multi: implement wait using winsock events" - - This reverts commit d2a7d7c185f98df8f3e585e5620cbc0482e45fac. - - This commit also reverts the subsequent follow-ups to that commit, which - were all done within windows #ifdefs that are removed in this - change. Marc helped me verify this. - - Fixes #6146 - Closes #6281 - -- [Klaus Crusius brought this change] - - ftp: retry getpeername for FTP with TCP_FASTOPEN - - In the case of TFO, the remote host name is not resolved at the - connetion time. - - For FTP that has lead to missing hostname for the secondary connection. - Therefore the name resolution is done at the time, when FTP requires it. - - Fixes #6252 - Closes #6265 - Closes #6282 - -- [Thomas Danielsson brought this change] - - scripts/completion.pl: parse all opts - - For tab-completion it may be preferable to include all the - available options. - - Closes #6280 - -- RELEASE-NOTES: synced - -- openssl: use OPENSSL_init_ssl() with >= 1.1.0 - - Reported-by: Kovalkov Dmitrii and Per Nilsson - Fixes #6254 - Fixes #6256 - Closes #6260 - -- SECURITY-PROCESS: disclose on hackerone - - Once a vulnerability has been published, the hackerone issue should be - disclosed. For tranparency. - - Closes #6275 - -Marc Hoersken (3 Dec 2020) -- tests/util.py: fix compatibility with Python 2 - - Backporting the Python 3 implementation of setStream - to ClosingFileHandler as a fallback within Python 2. - - Reported-by: Jay Satiro - - Fixes #6259 - Closes #6270 - -Daniel Gustafsson (3 Dec 2020) -- docs: fix typos and markup in ETag manpage sections - - Reported-by: emanruse on github - Fixes #6273 - -Daniel Stenberg (2 Dec 2020) -- quiche: close the connection - - Reported-by: Junho Choi - Fixes #6213 - Closes #6217 - -Jay Satiro (2 Dec 2020) -- ngtcp2: Fix build error due to symbol name change - - - NGTCP2_CRYPTO_LEVEL_APP -> NGTCP2_CRYPTO_LEVEL_APPLICATION - - ngtcp2/ngtcp2@76232e9 changed the name. - - ngtcp2 master is required to build curl with http3 support. - - Closes https://github.com/curl/curl/pull/6271 - -Daniel Stenberg (1 Dec 2020) -- [Klaus Crusius brought this change] - - cmake: check for linux/tcp.h - - The HAVE_LINUX_TCP_H define was not set by cmake. - - Closes #6252 diff --git a/libs/libcurl/docs/THANKS b/libs/libcurl/docs/THANKS index f003461c40..82755c72d3 100644 --- a/libs/libcurl/docs/THANKS +++ b/libs/libcurl/docs/THANKS @@ -4,15 +4,19 @@ If you have contributed but are missing here, please let us know! +0xee on github 0xflotus on github 1ocalhost on github 3dyd on github 3eka on github +8U61ife on github +a1346054 on github Aaro Koskinen Aaron Oneal Aaron Orenstein Aaron Scarisbrick aasivov on github +Abhinav Singh Abram Pousada accountantM on github AceCrow on Github @@ -51,6 +55,7 @@ Alejandro Colomar Alejandro R. Sedeño Aleksandar Milivojevic Aleksander Mazur +Aleksandr Krotov Aleksey Tulinov Ales Mlakar Ales Novak @@ -60,6 +65,7 @@ Alex aka WindEagle Alex Baines Alex Bligh Alex Chan +Alex Crichton Alex Fishman Alex Gaynor Alex Grebenschikov @@ -78,8 +84,10 @@ Alex Suykov Alex Vinnik Alex Xu Alexander Beedie +Alexander Chuykov Alexander Dyagilev Alexander Elgert +Alexander Kanavin Alexander Klauer Alexander Kourakos Alexander Krasnostavsky @@ -180,6 +188,7 @@ Anthon Pang Anthony Avina Anthony Bryan Anthony G. Basile +Anthony Hu Anthony Ramine Anthony Shaw Antoine Aubert @@ -193,6 +202,7 @@ Antoni Villalonga Antonio Larrosa Antony74 on github Antti Hätälä +April King arainchik on github Archangel_SDY on github Arkadiusz Miskiewicz @@ -204,6 +214,7 @@ Aron Bergman Aron Rotteveel Artak Galoyan Arthur Murray +Artur Sinila Arve Knudsen Arvid Norberg arvids-kokins-bidstack on github @@ -217,6 +228,7 @@ Augustus Saunders Austin Green Avery Fay awesomenode on github +Axel Morawietz Axel Tillequin Ayoub Boudhar Ayushman Singh Chauhan @@ -248,6 +260,7 @@ Ben Noordhuis Ben Van Hof Ben Voris Ben Winslow +Benau on github Benbuck Nason Benjamin Gerard Benjamin Gilbert @@ -268,6 +281,7 @@ Bernhard Walle Bert Huijben Bertrand Demiddelaer Bertrand Simonnet +beslick5 on github Bevan Weiss Bill Doyle Bill Egert @@ -275,6 +289,7 @@ Bill Hoffman Bill Middlecamp Bill Nagel Bill Pyne +billionai on github Billyzou0741326 on github Bin Lan Bin Meng @@ -287,12 +302,14 @@ Björn Stenberg Blaise Potard Blake Burkhart bnfp on github +Bo Anderson Bob Relyea Bob Richmond Bob Schader bobmitchell1956 on github Bodo Bergmann Bogdan Nicula +Boris Rasin Brad Burdick Brad Fitzpatrick Brad Harder @@ -341,6 +358,7 @@ Cameron Cawley Cameron Kaiser Cameron MacMinn Camille Moncelier +Cao ZhenXiang Caolan McNamara Captain Basil Carie Pointer @@ -424,6 +442,7 @@ coinhubs on github Colby Ranger Colin Blair Colin Hogben +Colin O'Dell Colin Watson Colm Buckley Constantine Sapuntzakis @@ -498,6 +517,7 @@ Daniel Silverstone Daniel Steinberg Daniel Stenberg Daniel Theron +Daniel Woelfel Daphne Luong Dario Nieuwenhuis Dario Weißer @@ -648,6 +668,7 @@ Ebe Janchivdorj ebejan on github Ebenezer Ikonne Ed Morley +Eddie Lumpkin Edgaras Janušauskas Edin Kadribasic Edmond Yu @@ -705,6 +726,7 @@ Erik Janssen Erik Johansson Erik Minekus Erik Olsson +Erik Stenlund Ernest Beinrohr Ernst Sjöstrand Erwan Legrand @@ -714,6 +736,7 @@ Ethan Glasser Camp Etienne Simard Eugene Kotlyarov Evan Jordan +Evangelos Foutras Even Rouault Evert Pot Evgeny Grin @@ -780,6 +803,7 @@ fullincome on github Gabriel Kuri Gabriel Simmer Gabriel Sjoberg +Gambit Communications Ganesh Kamath Garrett Holmstrom Gary Maxwell @@ -814,14 +838,18 @@ Gilles Blanc Gilles Vollant Giorgos Oikonomou Gisle Vanem +git-bruh on github GitYuanQu on github Giuseppe Attardi Giuseppe D'Ambrosio Giuseppe Persico +Gleb Ivanovsky Glen A Johnson Jr. Glen Nakamura Glen Scott +Glenn de boer Glenn Sheridan +Godwin Stewart Google Inc. Gordon Marler Gorilla Maguila @@ -853,6 +881,7 @@ GwanYeong Kim Gwenole Beauchesne Gökhan Şengün Götz Babin-Ebell +h1zzz on github H3RSKO on github Hagai Auro Haibo Huang @@ -875,6 +904,7 @@ Harold Stuart Harry Sintonen Harshal Pradhan Hauke Duden +Hayden Roche He Qin Heikki Korpela Heinrich Ko @@ -936,6 +966,7 @@ infinnovation-dev on github Ingmar Runge Ingo Ralf Blum Ingo Wilken +Inho Oh Ionuț-Francisc Oancea Irfan Adilovic Ironbars13 on github @@ -986,9 +1017,11 @@ Jan Chren Jan Ehrhardt Jan Koen Annot Jan Kunder +Jan Mazur Jan Schaumann Jan Schmidt Jan Van Boghout +Jan Verbeek JanB on github Janne Johansson Jared Jennings @@ -1031,11 +1064,13 @@ Jeff Mears Jeff Phillips Jeff Pohlmeyer Jeff Weber +Jeffrey Tolar Jeffrey Walton Jens Finkhaeuser Jens Rantil Jens Schleusener Jeremie Rapin +Jeremy Falcon Jeremy Friesner Jeremy Huddleston Jeremy Lainé @@ -1046,6 +1081,7 @@ Jeremy Tan Jeremy Thibault Jeroen Koekkoek Jeroen Ooms +Jerome Mao Jerome Muffat-Meridol Jerome Robert Jerome Vouillon @@ -1165,6 +1201,7 @@ joshhe on github Joshua Kwan Joshua Swink Josie Huddleston +Josip Medved Josue Andrade Gomes José Joaquín Atria Jozef Kralik @@ -1216,6 +1253,7 @@ Kamil Dudka Kane York Kang Lin Kang-Jin Lee +Kari Pahula Karl Chen Karl Moerder Karol Pietrzak @@ -1235,6 +1273,7 @@ Ken Rastatter Kenneth Davidson Kenny To Kent Boortz +Kerem Kat Keshav Krity Kevin Baughman Kevin Burke @@ -1250,6 +1289,7 @@ Kim Minjoong Kim Rinnewitz Kim Vandry Kimmo Kinnunen +Kirill Efimov Kirill Marchuk Kjell Ericson Kjetil Jacobsen @@ -1350,6 +1390,7 @@ Luca Altea Luca Boccassi Lucas Adamski Lucas Clemente Vella +Lucas Holt Lucas Pardue Lucas Servén Marín Lucas Severo @@ -1379,11 +1420,11 @@ Mahmoud Samir Fayed Maks Naumov Maksim Kuzevanov Maksim Stsepanenka +Malik Idrees Hasan Khan Mamoru Tasaka Mamta Upadhyay Mandy Wu Manfred Schwarb -MAntoniak on github Manuel Massing Manuj Bhatia Marc Aldorasi @@ -1474,6 +1515,7 @@ Mathias Gumz Mathieu Legare Matias N. Goldberg Mats Lidell +Mats Lindestam Matt Arsenault Matt Ford Matt Holt @@ -1517,6 +1559,7 @@ Mekonikum Melissa Mears Mert Yazıcıoğlu Mettgut Jamalla +Michael Afanasiev Michael Anti Michael Baentsch Michael Benedict @@ -1599,6 +1642,7 @@ Miroslav Spousta Mischa Salle Mitz Wark mkzero on github +modbw on github Mohamed Lrhazi Mohamed Osama Mohammad AlSaleh @@ -1606,6 +1650,7 @@ Mohammad Hasbini Mohammed Naser Mohun Biswas momala454 on github +Momoka Yamamoto moohoorama on github Morten Minde Neergaard Mostyn Bramley-Moore @@ -1674,6 +1719,7 @@ Nir Soffer Niranjan Hasabnis Nis Jorgensen nk +Noam Moshe NobodyXu on github Nobuhiro Ban Nodak Sodak @@ -1691,6 +1737,7 @@ Olaf Flebbe Olaf Hering Olaf Stüben Oleg Pudeyev +Oleguer Llopart Olen Andoni olesteban on github Oli Kingshott @@ -1708,6 +1755,7 @@ Oren Souroujon Oren Tirosh Orgad Shaneh Ori Avtalion +orycho on github osabc on github Oscar Koeroo Oscar Norlander @@ -1748,6 +1796,7 @@ Paul Harrington Paul Harris Paul Hoffman Paul Howarth +Paul Johnson Paul Joyce Paul Marks Paul Marquis @@ -1862,6 +1911,7 @@ Rafael Antonio Rafael Sagula Rafayel Mkrtchyan Rafaël Carré +Rafał Mikrut Rainer Canavan Rainer Jung Rainer Koenig @@ -1881,6 +1931,7 @@ Randy Armstrong Randy McMurchy Raphael Gozzo Rasmus Melchior Jacobsen +Raul Onitza-Klugman Ravi Pratap Ray Dassen Ray Pekowski @@ -1906,6 +1957,7 @@ Reuven Wachtfogel Reza Arbab Ricardo Cadime Ricardo Gomes +Ricardo Martins Rich Burridge Rich FitzJohn Rich Gray @@ -1936,6 +1988,7 @@ Richy Kim Rici Lake Rick Deist Rick Jones +Rick Lane Rick Richardson Rick Welykochy Rickard Hallerbäck @@ -1943,6 +1996,7 @@ Ricki Hirner Ricky Leverence Ricky-Tigg on github Rider Linden +RiderALT on github Rikard Falkeborn rl1987 on github Rob Cotrone @@ -1978,6 +2032,7 @@ Rodric Glaser Rodrigo Silva Roger Leigh Roger Orr +Roger Young Roland Blom Roland Hieber Roland Krikava @@ -1998,8 +2053,10 @@ Ronnie Mose Rosimildo da Silva Ross Burton Roy Bellingan +Roy Li Roy Shan Rui LIU +Rui Pinheiro Rune Kleveland Ruslan Baratov Ruslan Gazizov @@ -2009,10 +2066,12 @@ RuurdBeerstra on github Ryan Beck-Buysse Ryan Braud Ryan Chan +Ryan Mast Ryan Nelson Ryan Schmidt Ryan Scott Ryan Winograd +ryancaicse on github Ryuichi KAWAMATA Rémy Léone S. Moonesamy @@ -2028,6 +2087,7 @@ Sam Schanken Samanta Navarro Sampo Kellomaki Samuel Díaz García +Samuel Henrique Samuel Listopad Samuel Marks Samuel Surtees @@ -2055,6 +2115,7 @@ Sean Burford Sean MacLennan Sean McArthur Sean Miller +Sean Molenaar Sebastiaan van Erk Sebastian Haglund Sebastian Mundry @@ -2071,6 +2132,7 @@ Sergii Pylypenko Sergio Ballestrero Sergio Barresi Sergio Borghese +Sergio Durigan Junior sergio-nsk on github Serj Kalichev Seshubabu Pasam @@ -2083,6 +2145,7 @@ Shankar Jadhavar Shao Shuchao Sharad Gupta Shard +Sharon Brizinov Shaun Jackman Shawn Landden Shawn Poulson @@ -2122,6 +2185,7 @@ Stadler Stephan Stan van de Burgt Stanislav Ivochkin Stanislav Zidek +Stathis Kapnidis steelman on github Stefan Agner Stefan Bühler @@ -2188,14 +2252,15 @@ Symeon Paraschoudis Sébastien Willemijns T. Bharath T. Yamada +T200proX7 on github Tadej Vengust Tae Hyoung Ahn -Tae Wong Taiyu Len Taneli Vähäkangas Tanguy Fautre tarek112 on github Tatsuhiro Tsujikawa +tawmoto on github tbugfinder on github Teemu Yli-Elsila Temprimus @@ -2251,6 +2316,8 @@ Timothy Polich Timur Artikov Tinus van den Berg TJ Saunders +Tk Xiong +tlahn on github tmkk on github Tobias Blomberg Tobias Gabriel @@ -2353,11 +2420,13 @@ Ville Skyttä Vilmos Nebehaj Vincas Razma Vincent Bronner +Vincent Grande Vincent Le Normand Vincent Penquerc'h Vincent Sanders Vincent Torri vitaha85 on github +Vitaly Varyvdin Vlad Grachov Vlad Ureche Vladimir Grishchenko @@ -2402,6 +2471,7 @@ Wouter Van Rooy Wu Yongzheng Wyatt O'Day Wyatt OʼDay +x2018 on github Xavier Bouchoux XhmikosR on github XhstormR on github @@ -2413,6 +2483,7 @@ xnynx on github xwxbug on github Yaakov Selkowitz Yang Tse +Yaobin Wen Yarram Sunil Yasuharu Yamada Yasuhiro Matsumoto @@ -2437,6 +2508,8 @@ Yuriy Sosov Yusuke Nakamura Yves Arrouye Yves Lejeune +z2-2z on github +z2_ on hackerone Zachary Seguin Zdenek Pavlas Zekun Ni @@ -2454,6 +2527,7 @@ Zmey Petroff Zvi Har'El zzq1015 on github Ádler Jonas Gross +Érico Nogueira İsmail Dönmez Łukasz Domeradzki Štefan Kremeň diff --git a/libs/libcurl/include/curl/curl.h b/libs/libcurl/include/curl/curl.h index 521c254e77..6b6ac8a05e 100644 --- a/libs/libcurl/include/curl/curl.h +++ b/libs/libcurl/include/curl/curl.h @@ -25,9 +25,6 @@ /* * If you have libcurl problems, all docs and details are found here: * https://curl.se/libcurl/ - * - * curl-library mailing list subscription and unsubscription web interface: - * https://cool.haxx.se/mailman/listinfo/curl-library/ */ #ifdef CURL_NO_OLDIES @@ -49,8 +46,8 @@ #include <stdio.h> #include <limits.h> -#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) -/* Needed for __FreeBSD_version symbol definition */ +#if (defined(__FreeBSD__) && (__FreeBSD__ >= 2)) || defined(__MidnightBSD__) +/* Needed for __FreeBSD_version or __MidnightBSD_version symbol definition */ #include <osreldate.h> #endif @@ -76,6 +73,7 @@ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \ (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \ + (defined(__MidnightBSD_version) && (__MidnightBSD_version < 100000)) || \ defined(__VXWORKS__) #include <sys/select.h> #endif @@ -473,6 +471,20 @@ typedef int (*curl_debug_callback) size_t size, /* size of the data pointed to */ void *userptr); /* whatever the user please */ +/* This is the CURLOPT_PREREQFUNCTION callback prototype. */ +typedef int (*curl_prereq_callback)(void *clientp, + char *conn_primary_ip, + char *conn_local_ip, + int conn_primary_port, + int conn_local_port); + +/* Return code for when the pre-request callback has terminated without + any errors */ +#define CURL_PREREQFUNC_OK 0 +/* Return code for when the pre-request callback wants to abort the + request */ +#define CURL_PREREQFUNC_ABORT 1 + /* All possible error codes from all sorts of curl functions. Future versions may return other values, stay prepared. @@ -2046,7 +2058,8 @@ typedef enum { /* alt-svc cache file name to possibly read from/write to */ CURLOPT(CURLOPT_ALTSVC, CURLOPTTYPE_STRINGPOINT, 287), - /* maximum age of a connection to consider it for reuse (in seconds) */ + /* maximum age (idle time) of a connection to consider it for reuse + * (in seconds) */ CURLOPT(CURLOPT_MAXAGE_CONN, CURLOPTTYPE_LONG, 288), /* SASL authorisation identity */ @@ -2105,6 +2118,20 @@ typedef enum { this option is used only if PROXY_SSL_VERIFYPEER is true */ CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310), + /* used by scp/sftp to verify the host's public key */ + CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, CURLOPTTYPE_STRINGPOINT, 311), + + /* Function that will be called immediately before the initial request + is made on a connection (after any protocol negotiation step). */ + CURLOPT(CURLOPT_PREREQFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 312), + + /* Data passed to the CURLOPT_PREREQFUNCTION callback */ + CURLOPT(CURLOPT_PREREQDATA, CURLOPTTYPE_CBPOINT, 313), + + /* maximum age (since creation) of a connection to consider it for reuse + * (in seconds) */ + CURLOPT(CURLOPT_MAXLIFETIME_CONN, CURLOPTTYPE_LONG, 314), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/libs/libcurl/include/curl/curlver.h b/libs/libcurl/include/curl/curlver.h index d2ccdbaf83..6756c31bff 100644 --- a/libs/libcurl/include/curl/curlver.h +++ b/libs/libcurl/include/curl/curlver.h @@ -30,12 +30,12 @@ /* This is the version number of the libcurl package from which this header file origins: */ -#define LIBCURL_VERSION "7.78.0" +#define LIBCURL_VERSION "7.80.0" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 7 -#define LIBCURL_VERSION_MINOR 78 +#define LIBCURL_VERSION_MINOR 80 #define LIBCURL_VERSION_PATCH 0 /* This is the numeric version of the libcurl version number, meant for easier @@ -57,7 +57,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 0x074e00 +#define LIBCURL_VERSION_NUM 0x075000 /* * This is the date and time when the full source package was created. The @@ -68,7 +68,7 @@ * * "2007-11-23" */ -#define LIBCURL_TIMESTAMP "2021-07-21" +#define LIBCURL_TIMESTAMP "2021-11-10" #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/typecheck-gcc.h b/libs/libcurl/include/curl/typecheck-gcc.h index 34d0267ed9..9e14d8a372 100644 --- a/libs/libcurl/include/curl/typecheck-gcc.h +++ b/libs/libcurl/include/curl/typecheck-gcc.h @@ -317,6 +317,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t, (option) == CURLOPT_SERVICE_NAME || \ (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 || \ (option) == CURLOPT_SSH_KNOWNHOSTS || \ (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ @@ -363,6 +364,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t, (option) == CURLOPT_INTERLEAVEDATA || \ (option) == CURLOPT_IOCTLDATA || \ (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PREREQDATA || \ (option) == CURLOPT_PROGRESSDATA || \ (option) == CURLOPT_READDATA || \ (option) == CURLOPT_SEEKDATA || \ diff --git a/libs/libcurl/include/curl/urlapi.h b/libs/libcurl/include/curl/urlapi.h index 1d70880117..3c4b4e18aa 100644 --- a/libs/libcurl/include/curl/urlapi.h +++ b/libs/libcurl/include/curl/urlapi.h @@ -47,7 +47,8 @@ typedef enum { CURLUE_NO_HOST, /* 14 */ CURLUE_NO_PORT, /* 15 */ CURLUE_NO_QUERY, /* 16 */ - CURLUE_NO_FRAGMENT /* 17 */ + CURLUE_NO_FRAGMENT, /* 17 */ + CURLUE_LAST } CURLUcode; typedef enum { @@ -118,6 +119,12 @@ CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what, CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what, const char *part, unsigned int flags); +/* + * curl_url_strerror() turns a CURLUcode value into the equivalent human + * readable error string. This is useful for printing meaningful error + * messages. + */ +CURL_EXTERN const char *curl_url_strerror(CURLUcode); #ifdef __cplusplus } /* end of extern "C" */ diff --git a/libs/libcurl/src/.checksrc b/libs/libcurl/src/.checksrc new file mode 100644 index 0000000000..16133a44c5 --- /dev/null +++ b/libs/libcurl/src/.checksrc @@ -0,0 +1 @@ +enable STRERROR diff --git a/libs/libcurl/src/Makefile.am b/libs/libcurl/src/Makefile.am index b51796f91e..7693639415 100644 --- a/libs/libcurl/src/Makefile.am +++ b/libs/libcurl/src/Makefile.am @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -30,7 +30,7 @@ EXTRA_DIST = Makefile.m32 config-win32.h config-win32ce.h \ config-os400.h setup-os400.h \ config-tpf.h mk-ca-bundle.pl mk-ca-bundle.vbs $(CMAKE_DIST) \ firefox-db2pem.sh config-vxworks.h Makefile.vxworks checksrc.pl \ - setup-win32.h + setup-win32.h .checksrc lib_LTLIBRARIES = libcurl.la diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in index 2c01947112..188b2c4c25 100644 --- a/libs/libcurl/src/Makefile.in +++ b/libs/libcurl/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.3 from Makefile.am. +# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2020 Free Software Foundation, Inc. +# Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -728,8 +728,6 @@ am__define_uniq_tagged_files = \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.inc \ $(srcdir)/curl_config.h.in $(srcdir)/libcurl.vers.in \ $(top_srcdir)/depcomp @@ -755,6 +753,8 @@ CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPFLAG_CURL_STATICLIB = @CPPFLAG_CURL_STATICLIB@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ CURLVERSION = @CURLVERSION@ CURL_CA_BUNDLE = @CURL_CA_BUNDLE@ CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@ @@ -791,6 +791,7 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_SHARED = @ENABLE_SHARED@ ENABLE_STATIC = @ENABLE_STATIC@ +ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@ @@ -956,7 +957,7 @@ top_srcdir = @top_srcdir@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -979,7 +980,7 @@ EXTRA_DIST = Makefile.m32 config-win32.h config-win32ce.h \ config-os400.h setup-os400.h \ config-tpf.h mk-ca-bundle.pl mk-ca-bundle.vbs $(CMAKE_DIST) \ firefox-db2pem.sh config-vxworks.h Makefile.vxworks checksrc.pl \ - setup-win32.h + setup-win32.h .checksrc lib_LTLIBRARIES = libcurl.la @BUILD_UNITTESTS_FALSE@noinst_LTLIBRARIES = @@ -4190,7 +4191,6 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am diff --git a/libs/libcurl/src/Makefile.m32 b/libs/libcurl/src/Makefile.m32 index 9f1f5963d5..d78614da33 100644 --- a/libs/libcurl/src/Makefile.m32 +++ b/libs/libcurl/src/Makefile.m32 @@ -179,12 +179,10 @@ SYNC = 1 endif ifeq ($(findstring -rtmp,$(CFG)),-rtmp) RTMP = 1 -SSL = 1 ZLIB = 1 endif ifeq ($(findstring -ssh2,$(CFG)),-ssh2) SSH2 = 1 -SSL = 1 ZLIB = 1 endif ifeq ($(findstring -ssl,$(CFG)),-ssl) @@ -237,6 +235,13 @@ ifeq ($(findstring -unicode,$(CFG)),-unicode) UNICODE = 1 endif +# SSH2 and RTMP require an SSL library; assume OpenSSL if none specified +ifneq ($(SSH2)$(RTMP),) + ifeq ($(SSL)$(WINSSL),) + SSL = 1 + endif +endif + INCLUDES = -I. -I../include CFLAGS += -DBUILDING_LIBCURL ifdef SSL @@ -299,7 +304,7 @@ ifdef SSL endif endif ifneq "$(wildcard $(OPENSSL_INCLUDE)/openssl/opensslv.h)" "$(OPENSSL_INCLUDE)/openssl/opensslv.h" - $(error Invalid path to OpenSSL package: $(OPENSSL_PATH)) + $(error Invalid path to OpenSSL package: $(OPENSSL_PATH)) endif ifndef OPENSSL_LIBPATH ifeq "$(wildcard $(OPENSSL_PATH)/out)" "$(OPENSSL_PATH)/out" diff --git a/libs/libcurl/src/Makefile.netware b/libs/libcurl/src/Makefile.netware index cf7904aa72..92752128da 100644 --- a/libs/libcurl/src/Makefile.netware +++ b/libs/libcurl/src/Makefile.netware @@ -580,7 +580,6 @@ endif @echo $(DL)#define HAVE_SETLOCALE 1$(DL) >> $@ @echo $(DL)#define HAVE_SIGNAL 1$(DL) >> $@ @echo $(DL)#define HAVE_SIGNAL_H 1$(DL) >> $@ - @echo $(DL)#define HAVE_SIG_ATOMIC_T 1$(DL) >> $@ @echo $(DL)#define HAVE_SOCKET 1$(DL) >> $@ @echo $(DL)#define HAVE_STDLIB_H 1$(DL) >> $@ @echo $(DL)#define HAVE_STRDUP 1$(DL) >> $@ diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c index 839fabb86a..fc168baa6e 100644 --- a/libs/libcurl/src/asyn-ares.c +++ b/libs/libcurl/src/asyn-ares.c @@ -59,7 +59,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "multiif.h" #include "inet_pton.h" @@ -80,13 +79,33 @@ #define HAVE_CARES_CALLBACK_TIMEOUTS 1 #endif +#if ARES_VERSION >= 0x010601 +/* IPv6 supported since 1.6.1 */ +#define HAVE_CARES_IPV6 1 +#endif + +#if ARES_VERSION >= 0x010704 +#define HAVE_CARES_SERVERS_CSV 1 +#define HAVE_CARES_LOCAL_DEV 1 +#define HAVE_CARES_SET_LOCAL 1 +#endif + +#if ARES_VERSION >= 0x010b00 +#define HAVE_CARES_PORTS_CSV 1 +#endif + +#if ARES_VERSION >= 0x011000 +/* 1.16.0 or later has ares_getaddrinfo */ +#define HAVE_CARES_GETADDRINFO 1 +#endif + /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" #include "memdebug.h" struct thread_data { - int num_pending; /* number of ares_gethostbyname() requests */ + int num_pending; /* number of outstanding c-ares requests */ struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */ int last_status; @@ -322,7 +341,7 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) nfds = 0; if(!nfds) - /* Call ares_process() unconditonally here, even if we simply timed out + /* 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); @@ -490,6 +509,8 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, return result; } +#ifndef HAVE_CARES_GETADDRINFO + /* Connects results to the list */ static void compound_results(struct thread_data *res, struct Curl_addrinfo *ai) @@ -620,8 +641,99 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ } } } +#else +/* c-ares 1.16.0 or later */ /* + * ares2addr() converts an address list provided by c-ares to an internal + * libcurl compatible list + */ +static struct Curl_addrinfo *ares2addr(struct ares_addrinfo_node *node) +{ + /* traverse the ares_addrinfo_node list */ + struct ares_addrinfo_node *ai; + struct Curl_addrinfo *cafirst = NULL; + struct Curl_addrinfo *calast = NULL; + int error = 0; + + for(ai = node; ai != NULL; ai = ai->ai_next) { + size_t ss_size; + struct Curl_addrinfo *ca; + /* ignore elements with unsupported address family, */ + /* settle family-specific sockaddr structure size. */ + if(ai->ai_family == AF_INET) + ss_size = sizeof(struct sockaddr_in); +#ifdef ENABLE_IPV6 + else if(ai->ai_family == AF_INET6) + ss_size = sizeof(struct sockaddr_in6); +#endif + else + continue; + + /* ignore elements without required address info */ + if(!ai->ai_addr || !(ai->ai_addrlen > 0)) + continue; + + /* ignore elements with bogus address size */ + if((size_t)ai->ai_addrlen < ss_size) + continue; + + ca = malloc(sizeof(struct Curl_addrinfo) + ss_size); + if(!ca) { + error = EAI_MEMORY; + break; + } + + /* copy each structure member individually, member ordering, */ + /* size, or padding might be different for each platform. */ + + ca->ai_flags = ai->ai_flags; + ca->ai_family = ai->ai_family; + ca->ai_socktype = ai->ai_socktype; + ca->ai_protocol = ai->ai_protocol; + ca->ai_addrlen = (curl_socklen_t)ss_size; + ca->ai_addr = NULL; + ca->ai_canonname = NULL; + ca->ai_next = NULL; + + ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo)); + memcpy(ca->ai_addr, ai->ai_addr, ss_size); + + /* if the return list is empty, this becomes the first element */ + if(!cafirst) + cafirst = ca; + + /* add this element last in the return list */ + if(calast) + calast->ai_next = ca; + calast = ca; + } + + /* if we failed, destroy the Curl_addrinfo list */ + if(error) { + Curl_freeaddrinfo(cafirst); + cafirst = NULL; + } + + return cafirst; +} + +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); + } + res->num_pending--; +} + +#endif +/* * Curl_resolver_getaddrinfo() - when using ares * * Returns name information about the given hostname and port number. If @@ -658,8 +770,28 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, /* initial status - failed */ res->last_status = ARES_ENOTFOUND; -#if ARES_VERSION >= 0x010601 - /* IPv6 supported by c-ares since 1.6.1 */ +#ifdef HAVE_CARES_GETADDRINFO + { + struct ares_addrinfo_hints hints; + char service[12]; + int pf = PF_INET; + memset(&hints, 0, sizeof(hints)); +#ifdef CURLRES_IPV6 + if(Curl_ipv6works(data)) + /* The stack seems to be IPv6-enabled */ + pf = PF_UNSPEC; +#endif /* CURLRES_IPV6 */ + hints.ai_family = pf; + hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)? + SOCK_STREAM : SOCK_DGRAM; + msnprintf(service, sizeof(service), "%d", port); + res->num_pending = 1; + ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname, + service, &hints, addrinfo_cb, data); + } +#else + +#ifdef HAVE_CARES_IPV6 if(Curl_ipv6works(data)) { /* The stack seems to be IPv6-enabled */ res->num_pending = 2; @@ -671,7 +803,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, PF_INET6, query_completed_cb, data); } else -#endif /* ARES_VERSION >= 0x010601 */ +#endif { res->num_pending = 1; @@ -680,7 +812,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, hostname, PF_INET, query_completed_cb, data); } - +#endif *waitp = 1; /* expect asynchronous response */ } return NULL; /* no struct yet */ @@ -701,8 +833,8 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, if(!(servers && servers[0])) return CURLE_OK; -#if (ARES_VERSION >= 0x010704) -#if (ARES_VERSION >= 0x010b00) +#ifdef HAVE_CARES_SERVERS_CSV +#ifdef HAVE_CARES_PORTS_CSV ares_result = ares_set_servers_ports_csv(data->state.async.resolver, servers); #else @@ -732,7 +864,7 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, CURLcode Curl_set_dns_interface(struct Curl_easy *data, const char *interf) { -#if (ARES_VERSION >= 0x010704) +#ifdef HAVE_CARES_LOCAL_DEV if(!interf) interf = ""; @@ -749,7 +881,7 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data, CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, const char *local_ip4) { -#if (ARES_VERSION >= 0x010704) +#ifdef HAVE_CARES_SET_LOCAL struct in_addr a4; if((!local_ip4) || (local_ip4[0] == 0)) { @@ -775,7 +907,7 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, const char *local_ip6) { -#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6) +#if defined(HAVE_CARES_SET_LOCAL) && defined(ENABLE_IPV6) unsigned char a6[INET6_ADDRSTRLEN]; if((!local_ip6) || (local_ip6[0] == 0)) { diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c index 36f68cb493..149172ad3d 100644 --- a/libs/libcurl/src/asyn-thread.c +++ b/libs/libcurl/src/asyn-thread.c @@ -68,7 +68,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "multiif.h" #include "inet_ntop.h" diff --git a/libs/libcurl/src/c-hyper.c b/libs/libcurl/src/c-hyper.c index 2cc5d496e1..c253cd36ed 100644 --- a/libs/libcurl/src/c-hyper.c +++ b/libs/libcurl/src/c-hyper.c @@ -156,13 +156,15 @@ static int hyper_each_header(void *userdata, Curl_debug(data, CURLINFO_HEADER_IN, headp, len); - writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; - result = Curl_client_write(data, writetype, headp, len); - if(result) { - data->state.hresult = CURLE_ABORTED_BY_CALLBACK; - return HYPER_ITER_BREAK; + if(!data->state.hconnect || !data->set.suppress_connect_headers) { + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + result = Curl_client_write(data, writetype, headp, len); + if(result) { + data->state.hresult = CURLE_ABORTED_BY_CALLBACK; + return HYPER_ITER_BREAK; + } } data->info.header_size += (long)len; @@ -176,7 +178,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) size_t len = hyper_buf_len(chunk); struct Curl_easy *data = (struct Curl_easy *)userdata; struct SingleRequest *k = &data->req; - CURLcode result; + CURLcode result = CURLE_OK; if(0 == k->bodywrites++) { bool done = FALSE; @@ -192,8 +194,21 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) Curl_safefree(data->req.newurl); } #endif - if(data->state.hconnect && - (data->req.httpcode/100 != 2)) { + if(data->state.expect100header) { + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + if(data->req.httpcode < 400) { + k->exp100 = EXP100_SEND_DATA; + if(data->hyp.exp100_waker) { + hyper_waker_wake(data->hyp.exp100_waker); + data->hyp.exp100_waker = NULL; + } + } + else { /* >= 4xx */ + k->exp100 = EXP100_FAILED; + } + } + if(data->state.hconnect && (data->req.httpcode/100 != 2) && + data->state.authproxy.done) { done = TRUE; result = CURLE_OK; } @@ -245,6 +260,15 @@ static CURLcode status_line(struct Curl_easy *data, conn->httpversion = http_version == HYPER_HTTP_VERSION_1_1 ? 11 : (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10); + if(http_version == HYPER_HTTP_VERSION_1_0) + data->state.httpwant = CURL_HTTP_VERSION_1_0; + + if(data->state.hconnect) + /* CONNECT */ + data->info.httpproxycode = http_status; + + /* We need to set 'httpcodeq' for functions that check the response code in + a single place. */ data->req.httpcode = http_status; result = Curl_http_statusline(data, conn); @@ -262,16 +286,18 @@ static CURLcode status_line(struct Curl_easy *data, len = Curl_dyn_len(&data->state.headerb); Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb), len); - writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; - result = Curl_client_write(data, writetype, - Curl_dyn_ptr(&data->state.headerb), len); - if(result) { - data->state.hresult = CURLE_ABORTED_BY_CALLBACK; - return HYPER_ITER_BREAK; - } + if(!data->state.hconnect || !data->set.suppress_connect_headers) { + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + result = Curl_client_write(data, writetype, + Curl_dyn_ptr(&data->state.headerb), len); + if(result) { + data->state.hresult = CURLE_ABORTED_BY_CALLBACK; + return HYPER_ITER_BREAK; + } + } data->info.header_size += (long)len; data->req.headerbytecount += (long)len; data->req.httpcode = http_status; @@ -284,8 +310,14 @@ static CURLcode status_line(struct Curl_easy *data, */ static CURLcode empty_header(struct Curl_easy *data) { - return hyper_each_header(data, NULL, 0, NULL, 0) ? - CURLE_WRITE_ERROR : CURLE_OK; + CURLcode result = Curl_http_size(data); + if(!result) { + result = hyper_each_header(data, NULL, 0, NULL, 0) ? + CURLE_WRITE_ERROR : CURLE_OK; + if(result) + failf(data, "hyperstream: couldn't pass blank header"); + } + return result; } CURLcode Curl_hyper_stream(struct Curl_easy *data, @@ -306,8 +338,25 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, const uint8_t *reasonp; size_t reason_len; CURLcode result = CURLE_OK; + struct SingleRequest *k = &data->req; (void)conn; + if(k->exp100 > EXP100_SEND_DATA) { + struct curltime now = Curl_now(); + timediff_t ms = Curl_timediff(now, k->start100); + if(ms >= data->set.expect_100_timeout) { + /* we've waited long enough, continue anyway */ + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + infof(data, "Done waiting for 100-continue"); + if(data->hyp.exp100_waker) { + hyper_waker_wake(data->hyp.exp100_waker); + data->hyp.exp100_waker = NULL; + } + } + } + if(select_res & CURL_CSELECT_IN) { if(h->read_waker) hyper_waker_wake(h->read_waker); @@ -341,8 +390,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, hyper_task_free(task); if(t == HYPER_TASK_ERROR) { - hyper_code errnum = hyper_error_code(hypererr); - if(errnum == HYPERE_ABORTED_BY_CALLBACK) { + if(data->state.hresult) { /* override Hyper's view, might not even be an error */ result = data->state.hresult; infof(data, "hyperstream is done (by early callback)"); @@ -352,7 +400,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf)); hyper_code code = hyper_error_code(hypererr); failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf); - if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount) + if(code == HYPERE_ABORTED_BY_CALLBACK) + result = CURLE_OK; + else if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount) result = CURLE_GOT_NOTHING; else if(code == HYPERE_INVALID_PEER_MESSAGE) result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */ @@ -367,6 +417,11 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, /* end of transfer */ *done = TRUE; infof(data, "hyperstream is done!"); + if(!k->bodywrites) { + /* hyper doesn't always call the body write callback */ + bool stilldone; + result = Curl_http_firstwrite(data, data->conn, &stilldone); + } break; } else if(t != HYPER_TASK_RESPONSE) { @@ -405,11 +460,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, break; } - if(empty_header(data)) { - failf(data, "hyperstream: couldn't pass blank header"); - result = CURLE_OUT_OF_MEMORY; + result = empty_header(data); + if(result) break; - } /* Curl_http_auth_act() checks what authentication methods that are * available and decides which one (if any) to use. It will set 'newurl' @@ -523,7 +576,7 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers, free(ptr); } else - Curl_debug(data, CURLINFO_HEADER_OUT, (char *)line, linelen); + Curl_debug(data, CURLINFO_HEADER_OUT, (char *)n, linelen); } numh++; n += linelen; @@ -546,9 +599,22 @@ static CURLcode request_target(struct Curl_easy *data, if(result) return result; - if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r), - Curl_dyn_len(&r))) { - failf(data, "error setting path"); + 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), + Curl_dyn_len(&r))) { + failf(data, "error setting uri to hyper"); result = CURLE_OUT_OF_MEMORY; } else @@ -564,6 +630,16 @@ static int uploadpostfields(void *userdata, hyper_context *ctx, { struct Curl_easy *data = (struct Curl_easy *)userdata; (void)ctx; + if(data->req.exp100 > EXP100_SEND_DATA) { + if(data->req.exp100 == EXP100_FAILED) + return HYPER_POLL_ERROR; + + /* still waiting confirmation */ + if(data->hyp.exp100_waker) + hyper_waker_free(data->hyp.exp100_waker); + data->hyp.exp100_waker = hyper_context_waker(ctx); + return HYPER_POLL_PENDING; + } if(data->req.upload_done) *chunk = NULL; /* nothing more to deliver */ else { @@ -590,9 +666,21 @@ static int uploadstreamed(void *userdata, hyper_context *ctx, { size_t fillcount; struct Curl_easy *data = (struct Curl_easy *)userdata; - CURLcode result = - Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount); + CURLcode result; (void)ctx; + + if(data->req.exp100 > EXP100_SEND_DATA) { + if(data->req.exp100 == EXP100_FAILED) + return HYPER_POLL_ERROR; + + /* still waiting confirmation */ + if(data->hyp.exp100_waker) + hyper_waker_free(data->hyp.exp100_waker); + data->hyp.exp100_waker = hyper_context_waker(ctx); + return HYPER_POLL_PENDING; + } + + result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount); if(result) { data->state.hresult = result; return HYPER_POLL_ERROR; @@ -627,6 +715,7 @@ static CURLcode bodysend(struct Curl_easy *data, hyper_request *hyperreq, Curl_HttpReq httpreq) { + struct HTTP *http = data->req.p.http; CURLcode result = CURLE_OK; struct dynbuf req; if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) @@ -659,6 +748,7 @@ static CURLcode bodysend(struct Curl_easy *data, result = CURLE_OUT_OF_MEMORY; } } + http->sending = HTTPSEND_BODY; return result; } @@ -677,6 +767,48 @@ static CURLcode cookies(struct Curl_easy *data, return result; } +/* called on 1xx responses */ +static void http1xx_cb(void *arg, struct hyper_response *resp) +{ + struct Curl_easy *data = (struct Curl_easy *)arg; + hyper_headers *headers = NULL; + CURLcode result = CURLE_OK; + uint16_t http_status; + int http_version; + const uint8_t *reasonp; + size_t reason_len; + + infof(data, "Got HTTP 1xx informational"); + + http_status = hyper_response_status(resp); + http_version = hyper_response_version(resp); + reasonp = hyper_response_reason_phrase(resp); + reason_len = hyper_response_reason_phrase_len(resp); + + result = status_line(data, data->conn, + http_status, http_version, reasonp, reason_len); + if(!result) { + headers = hyper_response_headers(resp); + if(!headers) { + failf(data, "hyperstream: couldn't get 1xx response headers"); + result = CURLE_RECV_ERROR; + } + } + data->state.hresult = result; + + if(!result) { + /* the headers are already received */ + hyper_headers_foreach(headers, hyper_each_header, data); + /* this callback also sets data->state.hresult on error */ + + if(empty_header(data)) + result = CURLE_OUT_OF_MEMORY; + } + + if(data->state.hresult) + infof(data, "ERROR in 1xx, bail out!"); +} + /* * Curl_http() gets called from the generic multi_do() function when a HTTP * request is to be performed. This creates and sends a properly constructed @@ -694,13 +826,13 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) hyper_request *req = NULL; hyper_headers *headers = NULL; hyper_task *handshake = NULL; - hyper_error *hypererr = NULL; CURLcode result; const char *p_accept; /* Accept: string */ const char *method; Curl_HttpReq httpreq; bool h2 = FALSE; const char *te = NULL; /* transfer-encoding */ + hyper_code rc; /* Always consider the DO phase done after this function call, even if there may be parts of the request that is not yet sent, since we can deal with @@ -746,6 +878,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) io = hyper_io_new(); if(!io) { failf(data, "Couldn't create hyper IO"); + result = CURLE_OUT_OF_MEMORY; goto error; } /* tell Hyper how to read/write network data */ @@ -758,6 +891,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) h->exec = hyper_executor_new(); if(!h->exec) { failf(data, "Couldn't create hyper executor"); + result = CURLE_OUT_OF_MEMORY; goto error; } } @@ -765,6 +899,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) options = hyper_clientconn_options_new(); if(!options) { failf(data, "Couldn't create hyper client options"); + result = CURLE_OUT_OF_MEMORY; goto error; } if(conn->negnpn == CURL_HTTP_VERSION_2) { @@ -778,6 +913,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) handshake = hyper_clientconn_handshake(io, options); if(!handshake) { failf(data, "Couldn't create hyper client handshake"); + result = CURLE_OUT_OF_MEMORY; goto error; } io = NULL; @@ -785,6 +921,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) { failf(data, "Couldn't hyper_executor_push the handshake"); + result = CURLE_OUT_OF_MEMORY; goto error; } handshake = NULL; /* ownership passed on */ @@ -792,6 +929,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) task = hyper_executor_poll(h->exec); if(!task) { failf(data, "Couldn't hyper_executor_poll the handshake"); + result = CURLE_OUT_OF_MEMORY; goto error; } @@ -801,19 +939,22 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) req = hyper_request_new(); if(!req) { failf(data, "Couldn't hyper_request_new"); + result = CURLE_OUT_OF_MEMORY; goto error; } - if(data->state.httpwant == CURL_HTTP_VERSION_1_0) { + if(!Curl_use_http_1_1plus(data, conn)) { if(HYPERE_OK != hyper_request_set_version(req, HYPER_HTTP_VERSION_1_0)) { failf(data, "error setting HTTP version"); + result = CURLE_OUT_OF_MEMORY; goto error; } } if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) { failf(data, "error setting method"); + result = CURLE_OUT_OF_MEMORY; goto error; } @@ -824,47 +965,81 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) headers = hyper_request_headers(req); if(!headers) { failf(data, "hyper_request_headers"); + result = CURLE_OUT_OF_MEMORY; + goto error; + } + + rc = hyper_request_on_informational(req, http1xx_cb, data); + if(rc) { + result = CURLE_OUT_OF_MEMORY; goto error; } result = Curl_http_body(data, conn, httpreq, &te); if(result) - return result; - - if(data->state.aptr.host && - Curl_hyper_header(data, headers, data->state.aptr.host)) goto error; - if(data->state.aptr.proxyuserpwd && - Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd)) - 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. */ + result = Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host, + strlen(data->state.aptr.host)); + if(result) + goto error; + } - if(data->state.aptr.userpwd && - Curl_hyper_header(data, headers, data->state.aptr.userpwd)) - goto error; + if(data->state.aptr.proxyuserpwd) { + result = Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd); + if(result) + goto error; + } - if((data->state.use_range && data->state.aptr.rangeline) && - Curl_hyper_header(data, headers, data->state.aptr.rangeline)) - goto error; + if(data->state.aptr.userpwd) { + result = Curl_hyper_header(data, headers, data->state.aptr.userpwd); + if(result) + goto error; + } + + if((data->state.use_range && data->state.aptr.rangeline)) { + result = Curl_hyper_header(data, headers, data->state.aptr.rangeline); + if(result) + goto error; + } if(data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT] && - data->state.aptr.uagent && - Curl_hyper_header(data, headers, data->state.aptr.uagent)) - goto error; + data->state.aptr.uagent) { + result = Curl_hyper_header(data, headers, data->state.aptr.uagent); + if(result) + goto error; + } p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n"; - if(p_accept && Curl_hyper_header(data, headers, p_accept)) - goto error; - - if(te && Curl_hyper_header(data, headers, te)) - goto error; + if(p_accept) { + result = Curl_hyper_header(data, headers, p_accept); + if(result) + goto error; + } + if(te) { + result = Curl_hyper_header(data, headers, te); + if(result) + goto error; + } #ifndef CURL_DISABLE_PROXY if(conn->bits.httpproxy && !conn->bits.tunnel_proxy && !Curl_checkheaders(data, "Proxy-Connection") && !Curl_checkProxyheaders(data, conn, "Proxy-Connection")) { - if(Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive")) + result = Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"); + if(result) goto error; } #endif @@ -873,8 +1048,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(data->state.referer && !Curl_checkheaders(data, "Referer")) { data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer); if(!data->state.aptr.ref) - return CURLE_OUT_OF_MEMORY; - if(Curl_hyper_header(data, headers, data->state.aptr.ref)) + result = CURLE_OUT_OF_MEMORY; + else + result = Curl_hyper_header(data, headers, data->state.aptr.ref); + if(result) goto error; } @@ -884,8 +1061,11 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) data->state.aptr.accept_encoding = aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); if(!data->state.aptr.accept_encoding) - return CURLE_OUT_OF_MEMORY; - if(Curl_hyper_header(data, headers, data->state.aptr.accept_encoding)) + result = CURLE_OUT_OF_MEMORY; + else + result = Curl_hyper_header(data, headers, + data->state.aptr.accept_encoding); + if(result) goto error; } else @@ -895,61 +1075,58 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) /* we only consider transfer-encoding magic if libz support is built-in */ result = Curl_transferencode(data); if(result) - return result; - if(Curl_hyper_header(data, headers, data->state.aptr.te)) + goto error; + result = Curl_hyper_header(data, headers, data->state.aptr.te); + if(result) goto error; #endif result = cookies(data, conn, headers); if(result) - return result; + goto error; result = Curl_add_timecondition(data, headers); if(result) - return result; + goto error; result = Curl_add_custom_headers(data, FALSE, headers); if(result) - return result; + goto error; result = bodysend(data, conn, headers, req, httpreq); if(result) - return result; + goto error; - Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2); + result = Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2); + if(result) + goto error; data->req.upload_chunky = FALSE; sendtask = hyper_clientconn_send(client, req); if(!sendtask) { failf(data, "hyper_clientconn_send"); + result = CURLE_OUT_OF_MEMORY; goto error; } if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) { failf(data, "Couldn't hyper_executor_push the send"); + result = CURLE_OUT_OF_MEMORY; goto error; } hyper_clientconn_free(client); - do { - task = hyper_executor_poll(h->exec); - if(task) { - bool error = hyper_task_type(task) == HYPER_TASK_ERROR; - if(error) - hypererr = hyper_task_value(task); - hyper_task_free(task); - if(error) - goto error; - } - } while(task); - if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) { /* HTTP GET/HEAD download */ Curl_pgrsSetUploadSize(data, 0); /* nothing */ Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); } conn->datastream = Curl_hyper_stream; + if(data->state.expect100header) + /* Timeout count starts now since with Hyper we don't know exactly when + the full request has been sent. */ + data->req.start100 = Curl_now(); /* clear userpwd and proxyuserpwd to avoid re-using old credentials * from re-used connections */ @@ -957,7 +1134,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) Curl_safefree(data->state.aptr.proxyuserpwd); return CURLE_OK; error: - + DEBUGASSERT(result); if(io) hyper_io_free(io); @@ -967,16 +1144,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(handshake) hyper_task_free(handshake); - if(hypererr) { - uint8_t errbuf[256]; - size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf)); - hyper_code code = hyper_error_code(hypererr); - failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf); - hyper_error_free(hypererr); - if(data->state.hresult) - return data->state.hresult; - } - return CURLE_OUT_OF_MEMORY; + return result; } void Curl_hyper_done(struct Curl_easy *data) @@ -994,6 +1162,10 @@ void Curl_hyper_done(struct Curl_easy *data) hyper_waker_free(h->write_waker); h->write_waker = NULL; } + if(h->exp100_waker) { + hyper_waker_free(h->exp100_waker); + h->exp100_waker = NULL; + } } #endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */ diff --git a/libs/libcurl/src/c-hyper.h b/libs/libcurl/src/c-hyper.h index d60ed78d1d..d63defeffe 100644 --- a/libs/libcurl/src/c-hyper.h +++ b/libs/libcurl/src/c-hyper.h @@ -33,6 +33,7 @@ struct hyptransfer { hyper_waker *read_waker; const hyper_executor *exec; hyper_task *endtask; + hyper_waker *exp100_waker; }; size_t Curl_hyper_recv(void *userp, hyper_context *ctx, diff --git a/libs/libcurl/src/checksrc.pl b/libs/libcurl/src/checksrc.pl index a35535c191..8f98a99ab5 100644 --- a/libs/libcurl/src/checksrc.pl +++ b/libs/libcurl/src/checksrc.pl @@ -47,6 +47,7 @@ my @ignore_line; my %warnings_extended = ( 'COPYRIGHTYEAR' => 'copyright year incorrect', + 'STRERROR', => 'strerror() detected', ); my %warnings = ( @@ -87,7 +88,7 @@ my %warnings = ( 'EXCLAMATIONSPACE' => 'Whitespace after exclamation mark in expression', 'EMPTYLINEBRACE' => 'Empty line before the open brace', 'EQUALSNULL' => 'if/while comparison with == NULL', - 'NOTEQUALSZERO' => 'if/while comparison with != 0' + 'NOTEQUALSZERO', => 'if/while comparison with != 0', ); sub readskiplist { @@ -238,9 +239,17 @@ if(!$file) { print " -i<n> Indent spaces. Default: 2\n"; print " -m<n> Maximum line length. Default: 79\n"; print "\nDetects and warns for these problems:\n"; - for(sort keys %warnings) { - printf (" %-18s: %s\n", $_, $warnings{$_}); + my @allw = keys %warnings; + push @allw, keys %warnings_extended; + for my $w (sort @allw) { + if($warnings{$w}) { + printf (" %-18s: %s\n", $w, $warnings{$w}); + } + else { + printf (" %-18s: %s[*]\n", $w, $warnings_extended{$w}); + } } + print " [*] = disabled by default\n"; exit; } @@ -361,7 +370,10 @@ sub scanfile { my $line = 1; my $prevl=""; - my $l; + my $prevpl=""; + my $l = ""; + my $prep = 0; + my $prevp = 0; open(R, "<$file") || die "failed to open $file"; my $incomment=0; @@ -443,6 +455,14 @@ sub scanfile { # comments # ------------------------------------------------------------ + # prev line was a preprocessor **and** ended with a backslash + if($prep && ($prevpl =~ /\\ *\z/)) { + # this is still a preprocessor line + $prep = 1; + goto preproc; + } + $prep = 0; + # crude attempt to detect // comments without too many false # positives if($l =~ /^(([^"\*]*)[^:"]|)\/\//) { @@ -450,6 +470,13 @@ sub scanfile { $line, length($1), $file, $l, "\/\/ comment"); } + # detect and strip preprocessor directives + if($l =~ /^[ \t]*\#/) { + # preprocessor line + $prep = 1; + goto preproc; + } + my $nostr = nostrings($l); # check spaces after for/if/while/function call if($nostr =~ /^(.*)(for|if|while| ([a-zA-Z0-9_]+)) \((.)/) { @@ -520,7 +547,6 @@ sub scanfile { } elsif($even && $postparen && ($postparen !~ /^ *$/) && ($postparen !~ /^ *[,{&|\\]+/)) { - print STDERR "5: '$postparen'\n"; checkwarn("ONELINECONDITION", $line, length($l)-length($postparen), $file, $l, "conditional block on the same line"); @@ -621,7 +647,7 @@ sub scanfile { # check for space before the semicolon last in a line if($l =~ /^(.*[^ ].*) ;$/) { checkwarn("SPACESEMICOLON", - $line, length($1), $file, $ol, "space before last semicolon"); + $line, length($1), $file, $ol, "no space before semicolon"); } # scan for use of banned functions @@ -638,7 +664,18 @@ sub scanfile { $line, length($1), $file, $ol, "use of $2 is banned"); } - + if($warnings{"STRERROR"}) { + # scan for use of banned strerror. This is not a BANNEDFUNC to + # allow for individual enable/disable of this warning. + if($l =~ /^(.*\W)(strerror)\s*\(/x) { + if($1 !~ /^ *\#/) { + # skip preprocessor lines + checkwarn("STRERROR", + $line, length($1), $file, $ol, + "use of $2 is banned"); + } + } + } # scan for use of snprintf for curl-internals reasons if($l =~ /^(.*\W)(v?snprintf)\s*\(/x) { checkwarn("SNPRINTF", @@ -656,10 +693,9 @@ sub scanfile { } } - # check for open brace first on line but not first column - # only alert if previous line ended with a close paren and wasn't a cpp - # line - if((($prevl =~ /\)\z/) && ($prevl !~ /^ *#/)) && ($l =~ /^( +)\{/)) { + # check for open brace first on line but not first column only alert + # if previous line ended with a close paren and it wasn't a cpp line + if(($prevl =~ /\)\z/) && ($l =~ /^( +)\{/) && !$prevp) { checkwarn("BRACEPOS", $line, length($1), $file, $ol, "badly placed open brace"); } @@ -667,11 +703,10 @@ sub scanfile { # if the previous line starts with if/while/for AND ends with an open # brace, or an else statement, check that this line is indented $indent # more steps, if not a cpp line - if($prevl =~ /^( *)((if|while|for)\(.*\{|else)\z/) { + if(!$prevp && ($prevl =~ /^( *)((if|while|for)\(.*\{|else)\z/)) { my $first = length($1); - # this line has some character besides spaces - if(($l !~ /^ *#/) && ($l =~ /^( *)[^ ]/)) { + if($l =~ /^( *)[^ ]/) { my $second = length($1); my $expect = $first+$indent; if($expect != $second) { @@ -762,13 +797,13 @@ sub scanfile { $nostr =~ /^(.*(\S)) + [{?]/i) { checkwarn("MULTISPACE", $line, length($1)+1, $file, $ol, - "multiple space"); - print STDERR "L: $l\n"; - print STDERR "nostr: $nostr\n"; + "multiple spaces"); } - + preproc: $line++; - $prevl = $ol; + $prevp = $prep; + $prevl = $ol if(!$prep); + $prevpl = $ol if($prep); } if(!scalar(@copyright)) { diff --git a/libs/libcurl/src/config-amigaos.h b/libs/libcurl/src/config-amigaos.h index 0bbf4c41df..842cbc247b 100644 --- a/libs/libcurl/src/config-amigaos.h +++ b/libs/libcurl/src/config-amigaos.h @@ -55,7 +55,6 @@ #define HAVE_SETJMP_H 1 #define HAVE_SIGNAL 1 #define HAVE_SIGNAL_H 1 -#define HAVE_SIG_ATOMIC_T 1 #define HAVE_SOCKET 1 #define HAVE_STRCASECMP 1 #define HAVE_STRDUP 1 diff --git a/libs/libcurl/src/config-mac.h b/libs/libcurl/src/config-mac.h index c8833e3006..22d32d480d 100644 --- a/libs/libcurl/src/config-mac.h +++ b/libs/libcurl/src/config-mac.h @@ -67,7 +67,6 @@ #define HAVE_SIGACTION 1 #define HAVE_SIGNAL_H 1 -#define HAVE_SIG_ATOMIC_T 1 #ifdef MACOS_SSL_SUPPORT # define USE_OPENSSL 1 diff --git a/libs/libcurl/src/config-os400.h b/libs/libcurl/src/config-os400.h index cff9c3e624..d68cb4b18e 100644 --- a/libs/libcurl/src/config-os400.h +++ b/libs/libcurl/src/config-os400.h @@ -235,12 +235,6 @@ /* Define if you have the <signal.h> header file. */ #define HAVE_SIGNAL_H -/* Define if sig_atomic_t is an available typedef. */ -#define HAVE_SIG_ATOMIC_T - -/* Define if sig_atomic_t is already defined as volatile. */ -#undef HAVE_SIG_ATOMIC_T_VOLATILE - /* Define if you have the `socket' function. */ #define HAVE_SOCKET @@ -334,9 +328,6 @@ /* Define if you have the <unistd.h> header file. */ #define HAVE_UNISTD_H -/* Define if you have the <winsock.h> header file. */ -#undef HAVE_WINSOCK_H - /* Define if you have the <x509.h> header file. */ #undef HAVE_X509_H diff --git a/libs/libcurl/src/config-plan9.h b/libs/libcurl/src/config-plan9.h index 9b98a6e249..dbe9b82af6 100644 --- a/libs/libcurl/src/config-plan9.h +++ b/libs/libcurl/src/config-plan9.h @@ -149,7 +149,6 @@ #define HAVE_SIGNAL 1 #define HAVE_SIGNAL_H 1 #define HAVE_SIGSETJMP 1 -#define HAVE_SIG_ATOMIC_T 1 #define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 #define HAVE_SOCKET 1 #define HAVE_SSL_GET_SHUTDOWN 1 diff --git a/libs/libcurl/src/config-riscos.h b/libs/libcurl/src/config-riscos.h index 0535137bef..9986b20fba 100644 --- a/libs/libcurl/src/config-riscos.h +++ b/libs/libcurl/src/config-riscos.h @@ -227,12 +227,6 @@ /* Define if you have the <signal.h> header file. */ #define HAVE_SIGNAL_H -/* Define if sig_atomic_t is an available typedef. */ -#define HAVE_SIG_ATOMIC_T - -/* Define if sig_atomic_t is already defined as volatile. */ -#undef HAVE_SIG_ATOMIC_T_VOLATILE - /* Define if you have the `socket' function. */ #define HAVE_SOCKET @@ -311,9 +305,6 @@ /* Define if you have the <unistd.h> header file. */ #define HAVE_UNISTD_H -/* Define if you have the <winsock.h> header file. */ -#undef HAVE_WINSOCK_H - /* Define if you have the <x509.h> header file. */ #undef HAVE_X509_H diff --git a/libs/libcurl/src/config-tpf.h b/libs/libcurl/src/config-tpf.h index ab29bfccc2..cce06cedd8 100644 --- a/libs/libcurl/src/config-tpf.h +++ b/libs/libcurl/src/config-tpf.h @@ -366,12 +366,6 @@ /* Define to 1 if you have the <signal.h> header file. */ #define HAVE_SIGNAL_H 1 -/* Define to 1 if sig_atomic_t is an available typedef. */ -#define HAVE_SIG_ATOMIC_T 1 - -/* Define to 1 if sig_atomic_t is already defined as volatile. */ -/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ - /* If you have sigsetjmp */ /* #undef HAVE_SIGSETJMP */ @@ -489,9 +483,6 @@ /* Define to 1 if you have the <winsock2.h> header file. */ /* #undef HAVE_WINSOCK2_H */ -/* Define to 1 if you have the <winsock.h> header file. */ -/* #undef HAVE_WINSOCK_H */ - /* Define this symbol if your OS supports changing the contents of argv */ /* #undef HAVE_WRITABLE_ARGV */ diff --git a/libs/libcurl/src/config-vxworks.h b/libs/libcurl/src/config-vxworks.h index 22d2b964a4..af1d87345c 100644 --- a/libs/libcurl/src/config-vxworks.h +++ b/libs/libcurl/src/config-vxworks.h @@ -445,12 +445,6 @@ /* Define to 1 if you have the sigsetjmp function or macro. */ /* #undef HAVE_SIGSETJMP */ -/* Define to 1 if sig_atomic_t is an available typedef. */ -#define HAVE_SIG_ATOMIC_T 1 - -/* Define to 1 if sig_atomic_t is already defined as volatile. */ -/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ - /* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ #define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 @@ -607,9 +601,6 @@ /* Define to 1 if you have the winsock2.h header file. */ /* #undef HAVE_WINSOCK2_H */ -/* Define to 1 if you have the winsock.h header file. */ -/* #undef HAVE_WINSOCK_H */ - /* Define this symbol if your OS supports changing the contents of argv */ #define HAVE_WRITABLE_ARGV 1 diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h index 2021fab815..89593a815d 100644 --- a/libs/libcurl/src/config-win32.h +++ b/libs/libcurl/src/config-win32.h @@ -132,9 +132,6 @@ /* Define if you have the <windows.h> header file. */ #define HAVE_WINDOWS_H 1 -/* Define if you have the <winsock.h> header file. */ -#define HAVE_WINSOCK_H 1 - /* Define if you have the <winsock2.h> header file. */ #ifndef __SALFORDC__ #define HAVE_WINSOCK2_H 1 @@ -149,9 +146,6 @@ /* OTHER HEADER INFO */ /* ---------------------------------------------------------------- */ -/* Define if sig_atomic_t is an available typedef. */ -#define HAVE_SIG_ATOMIC_T 1 - /* Define if you have the ANSI C header files. */ #define STDC_HEADERS 1 @@ -231,10 +225,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. */ #ifdef __MINGW32__ #define HAVE_STRCASECMP 1 @@ -388,7 +378,6 @@ #ifdef USE_LWIPSOCK # undef USE_WINSOCK -# undef HAVE_WINSOCK_H # undef HAVE_WINSOCK2_H # undef HAVE_WS2TCPIP_H # undef HAVE_ERRNO_H @@ -419,7 +408,6 @@ #undef byte #undef word #undef USE_WINSOCK - #undef HAVE_WINSOCK_H #undef HAVE_WINSOCK2_H #undef HAVE_WS2TCPIP_H #define HAVE_GETADDRINFO @@ -677,9 +665,6 @@ Vista # 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 diff --git a/libs/libcurl/src/config-win32ce.h b/libs/libcurl/src/config-win32ce.h index f3f02e720a..889028b269 100644 --- a/libs/libcurl/src/config-win32ce.h +++ b/libs/libcurl/src/config-win32ce.h @@ -110,22 +110,16 @@ /* Define if you have the <windows.h> header file. */ #define HAVE_WINDOWS_H 1 -/* Define if you have the <winsock.h> header file. */ -#define HAVE_WINSOCK_H 1 - /* Define if you have the <winsock2.h> header file. */ -/* #define HAVE_WINSOCK2_H 1 */ +#define HAVE_WINSOCK2_H 1 /* Define if you have the <ws2tcpip.h> header file. */ -/* #define HAVE_WS2TCPIP_H 1 */ +#define HAVE_WS2TCPIP_H 1 /* ---------------------------------------------------------------- */ /* OTHER HEADER INFO */ /* ---------------------------------------------------------------- */ -/* Define if sig_atomic_t is an available typedef. */ -#define HAVE_SIG_ATOMIC_T 1 - /* Define if you have the ANSI C header files. */ #define STDC_HEADERS 1 diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c index 11e6b888b7..af60947314 100644 --- a/libs/libcurl/src/connect.c +++ b/libs/libcurl/src/connect.c @@ -85,7 +85,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error); -#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H) +#if defined(__DragonFly__) || defined(HAVE_WINSOCK2_H) /* DragonFlyBSD and Windows use millisecond units */ #define KEEPALIVE_FACTOR(x) (x *= 1000) #else @@ -589,12 +589,10 @@ static CURLcode trynextip(struct Curl_easy *data, struct Curl_addrinfo *ai = conn->tempaddr[tempindex]; while(ai) { - if(ai) { - result = singleipconnect(data, conn, ai, tempindex); - if(result == CURLE_COULDNT_CONNECT) { - ai = ainext(conn, tempindex, TRUE); - continue; - } + result = singleipconnect(data, conn, ai, tempindex); + if(result == CURLE_COULDNT_CONNECT) { + ai = ainext(conn, tempindex, TRUE); + continue; } break; } @@ -631,7 +629,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen, #ifdef ENABLE_IPV6 struct sockaddr_in6 *si6 = NULL; #endif -#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) +#if (defined(HAVE_SYS_UN_H) || defined(WIN32_SOCKADDR_UN)) && defined(AF_UNIX) struct sockaddr_un *su = NULL; #else (void)salen; @@ -658,7 +656,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen, } break; #endif -#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) +#if (defined(HAVE_SYS_UN_H) || defined(WIN32_SOCKADDR_UN)) && defined(AF_UNIX) case AF_UNIX: if(salen > (curl_socklen_t)sizeof(CURL_SA_FAMILY_T)) { su = (struct sockaddr_un*)sa; @@ -746,18 +744,15 @@ void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd, void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn, curl_socket_t sockfd) { - /* 'local_ip' and 'local_port' get filled with local's numerical - ip address and port number whenever an outgoing connection is - **established** from the primary socket to a remote address. */ + /* 'local_ip' and 'local_port' get filled with local's numerical ip address + and port number whenever an outgoing connection is **established** from + the primary socket to a remote address. */ char local_ip[MAX_IPADR_LEN] = ""; int local_port = -1; - if(conn->transport == TRNSPRT_TCP) { - if(!conn->bits.reuse && !conn->bits.tcp_fastopen) { - Curl_conninfo_remote(data, conn, sockfd); - Curl_conninfo_local(data, sockfd, local_ip, &local_port); - } - } /* end of TCP-only section */ + if(!conn->bits.reuse && !conn->bits.tcp_fastopen) + Curl_conninfo_remote(data, conn, sockfd); + Curl_conninfo_local(data, sockfd, local_ip, &local_port); /* persist connection info in session handle */ Curl_persistconninfo(data, conn, local_ip, local_port); diff --git a/libs/libcurl/src/content_encoding.c b/libs/libcurl/src/content_encoding.c index a84ff543b9..c03637a391 100644 --- a/libs/libcurl/src/content_encoding.c +++ b/libs/libcurl/src/content_encoding.c @@ -240,7 +240,8 @@ static CURLcode inflate_stream(struct Curl_easy *data, } zp->zlib_init = ZLIB_UNINIT; /* inflateEnd() already called. */ } - /* FALLTHROUGH */ + result = exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z)); + break; default: result = exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z)); break; diff --git a/libs/libcurl/src/curl_config.h.cmake b/libs/libcurl/src/curl_config.h.cmake index fa4f19c74f..d2a0f438cc 100644 --- a/libs/libcurl/src/curl_config.h.cmake +++ b/libs/libcurl/src/curl_config.h.cmake @@ -33,61 +33,91 @@ /* Location of default ca path */ #cmakedefine CURL_CA_PATH "${CURL_CA_PATH}" -/* to disable cookies support */ +/* disables alt-svc */ +#cmakedefine CURL_DISABLE_ALTSVC 1 + +/* disables cookies support */ #cmakedefine CURL_DISABLE_COOKIES 1 -/* to disable cryptographic authentication */ +/* disables cryptographic authentication */ #cmakedefine CURL_DISABLE_CRYPTO_AUTH 1 -/* to disable DICT */ +/* disables DICT */ #cmakedefine CURL_DISABLE_DICT 1 -/* to disable FILE */ +/* disables DNS-over-HTTPS */ +#cmakedefine CURL_DISABLE_DOH 1 + +/* disables FILE */ #cmakedefine CURL_DISABLE_FILE 1 -/* to disable FTP */ +/* disables FTP */ #cmakedefine CURL_DISABLE_FTP 1 -/* to disable GOPHER */ +/* disables GOPHER */ #cmakedefine CURL_DISABLE_GOPHER 1 -/* to disable IMAP */ -#cmakedefine CURL_DISABLE_IMAP 1 +/* disables HSTS support */ +#cmakedefine CURL_DISABLE_HSTS 1 -/* to disable HTTP */ +/* disables HTTP */ #cmakedefine CURL_DISABLE_HTTP 1 -/* to disable LDAP */ +/* disables IMAP */ +#cmakedefine CURL_DISABLE_IMAP 1 + +/* disables LDAP */ #cmakedefine CURL_DISABLE_LDAP 1 -/* to disable LDAPS */ +/* disables LDAPS */ #cmakedefine CURL_DISABLE_LDAPS 1 -/* to disable MQTT */ +/* disables --libcurl option from the curl tool */ +#cmakedefine CURL_DISABLE_LIBCURL_OPTION 1 + +/* disables MIME support */ +#cmakedefine CURL_DISABLE_MIME 1 + +/* disables MQTT */ #cmakedefine CURL_DISABLE_MQTT 1 -/* to disable POP3 */ +/* disables netrc parser */ +#cmakedefine CURL_DISABLE_NETRC 1 + +/* disables NTLM support */ +#cmakedefine CURL_DISABLE_NTLM 1 + +/* disables date parsing */ +#cmakedefine CURL_DISABLE_PARSEDATE 1 + +/* disables POP3 */ #cmakedefine CURL_DISABLE_POP3 1 -/* to disable proxies */ +/* disables built-in progress meter */ +#cmakedefine CURL_DISABLE_PROGRESS_METER 1 + +/* disables proxies */ #cmakedefine CURL_DISABLE_PROXY 1 -/* to disable RTSP */ +/* disables RTSP */ #cmakedefine CURL_DISABLE_RTSP 1 -/* to disable SMB */ +/* disables SMB */ #cmakedefine CURL_DISABLE_SMB 1 -/* to disable SMTP */ +/* disables SMTP */ #cmakedefine CURL_DISABLE_SMTP 1 -/* to disable TELNET */ +/* disables use of socketpair for curl_multi_poll */ +#cmakedefine CURL_DISABLE_SOCKETPAIR 1 + +/* disables TELNET */ #cmakedefine CURL_DISABLE_TELNET 1 -/* to disable TFTP */ +/* disables TFTP */ #cmakedefine CURL_DISABLE_TFTP 1 -/* to disable verbose strings */ +/* disables verbose strings */ #cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1 /* to make a symbol visible */ @@ -521,12 +551,6 @@ /* Define to 1 if you have the sigsetjmp function or macro. */ #cmakedefine HAVE_SIGSETJMP 1 -/* Define to 1 if sig_atomic_t is an available typedef. */ -#cmakedefine HAVE_SIG_ATOMIC_T 1 - -/* Define to 1 if sig_atomic_t is already defined as volatile. */ -#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE 1 - /* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ #cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 @@ -686,9 +710,6 @@ /* Define to 1 if you have the winsock2.h header file. */ #cmakedefine HAVE_WINSOCK2_H 1 -/* Define to 1 if you have the winsock.h header file. */ -#cmakedefine HAVE_WINSOCK_H 1 - /* Define this symbol if your OS supports changing the contents of argv */ #cmakedefine HAVE_WRITABLE_ARGV 1 @@ -931,9 +952,6 @@ ${SIZEOF_TIME_T_CODE} /* if Unix domain sockets are enabled */ #cmakedefine USE_UNIX_SOCKETS -/* to disable alt-svc */ -#cmakedefine CURL_DISABLE_ALTSVC 1 - /* Define to 1 if you are building a Windows target with large file support. */ #cmakedefine USE_WIN32_LARGE_FILES 1 diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in index 5a8190f8c0..751f6a4f65 100644 --- a/libs/libcurl/src/curl_config.h.in +++ b/libs/libcurl/src/curl_config.h.in @@ -588,12 +588,6 @@ /* Define to 1 if you have the sigsetjmp function or macro. */ #undef HAVE_SIGSETJMP -/* Define to 1 if sig_atomic_t is an available typedef. */ -#undef HAVE_SIG_ATOMIC_T - -/* Define to 1 if sig_atomic_t is already defined as volatile. */ -#undef HAVE_SIG_ATOMIC_T_VOLATILE - /* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID @@ -621,6 +615,9 @@ /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H +/* Define to 1 if you have the <stdio.h> header file. */ +#undef HAVE_STDIO_H + /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H @@ -765,9 +762,6 @@ /* Define to 1 if you have the winsock2.h header file. */ #undef HAVE_WINSOCK2_H -/* Define to 1 if you have the winsock.h header file. */ -#undef HAVE_WINSOCK_H - /* Define to 1 if you have the <wolfssh/ssh.h> header file. */ #undef HAVE_WOLFSSH_SSH_H @@ -924,7 +918,9 @@ /* The number of bytes in type time_t */ #undef SIZEOF_TIME_T -/* Define to 1 if you have the ANSI C header files. */ +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* Define to the type of arg 3 for strerror_r. */ @@ -1058,11 +1054,6 @@ # undef _ALL_SOURCE #endif -/* Enable large inode numbers on Mac OS X 10.5. */ -#ifndef _DARWIN_USE_64_BIT_INODE -# define _DARWIN_USE_64_BIT_INODE 1 -#endif - /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS diff --git a/libs/libcurl/src/curl_des.c b/libs/libcurl/src/curl_des.c index 8c5af19cd2..76185cbf21 100644 --- a/libs/libcurl/src/curl_des.c +++ b/libs/libcurl/src/curl_des.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2015 - 2020, Steve Holme, <steve_holme@hotmail.com>. + * Copyright (C) 2015 - 2021, Steve Holme, <steve_holme@hotmail.com>. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -22,7 +22,7 @@ #include "curl_setup.h" -#if defined(USE_NTLM) && !defined(USE_OPENSSL) +#if defined(USE_NTLM) && !defined(USE_OPENSSL) && !defined(USE_WOLFSSL) #include "curl_des.h" diff --git a/libs/libcurl/src/curl_gssapi.c b/libs/libcurl/src/curl_gssapi.c index 5810dad14b..8f340562bc 100644 --- a/libs/libcurl/src/curl_gssapi.c +++ b/libs/libcurl/src/curl_gssapi.c @@ -32,10 +32,12 @@ #include "curl_memory.h" #include "memdebug.h" -static char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02"; -gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes }; -static char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"; -gss_OID_desc Curl_krb5_mech_oid = { 9, &krb5_oid_bytes }; +gss_OID_desc Curl_spnego_mech_oid = { + 6, (char *)"\x2b\x06\x01\x05\x05\x02" +}; +gss_OID_desc Curl_krb5_mech_oid = { + 9, (char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" +}; OM_uint32 Curl_gss_init_sec_context( struct Curl_easy *data, diff --git a/libs/libcurl/src/curl_ntlm_core.c b/libs/libcurl/src/curl_ntlm_core.c index 749b44e4a9..ed123d0c1c 100644 --- a/libs/libcurl/src/curl_ntlm_core.c +++ b/libs/libcurl/src/curl_ntlm_core.c @@ -49,7 +49,14 @@ in NTLM type-3 messages. */ -#if defined(USE_OPENSSL) || defined(USE_WOLFSSL) +#if defined(USE_OPENSSL) + #include <openssl/opensslconf.h> + #if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_DEPRECATED_3_0) + #define USE_OPENSSL_DES + #endif +#endif + +#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL) #ifdef USE_WOLFSSL #include <wolfssl/options.h> @@ -97,7 +104,7 @@ #elif defined(USE_WIN32_CRYPTO) # include <wincrypt.h> #else -# error "Can't compile NTLM support without a crypto library." +# error "Can't compile NTLM support without a crypto library with DES." #endif #include "urldata.h" @@ -133,7 +140,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key) key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); } -#if defined(USE_OPENSSL) || defined(USE_WOLFSSL) +#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL) /* * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The * key schedule ks is also set. @@ -150,7 +157,7 @@ static void setup_des_key(const unsigned char *key_56, DES_set_odd_parity(&key); /* Set the key */ - DES_set_key(&key, ks); + DES_set_key_unchecked(&key, ks); } #elif defined(USE_GNUTLS) @@ -362,7 +369,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, const unsigned char *plaintext, unsigned char *results) { -#if defined(USE_OPENSSL) || defined(USE_WOLFSSL) +#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL) DES_key_schedule ks; setup_des_key(keys, DESKEY(ks)); @@ -420,7 +427,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, { /* Create LanManager hashed password. */ -#if defined(USE_OPENSSL) || defined(USE_WOLFSSL) +#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL) DES_key_schedule ks; setup_des_key(pw, DESKEY(ks)); diff --git a/libs/libcurl/src/curl_ntlm_wb.c b/libs/libcurl/src/curl_ntlm_wb.c index ca9e2874a7..5a3bc3c893 100644 --- a/libs/libcurl/src/curl_ntlm_wb.c +++ b/libs/libcurl/src/curl_ntlm_wb.c @@ -426,7 +426,8 @@ CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn, /* Use Samba's 'winbind' daemon to support NTLM authentication, * by delegating the NTLM challenge/response protocol to a helper * in ntlm_auth. - * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html + * https://web.archive.org/web/20190925164737 + * /devel.squid-cache.org/ntlm/squid_helper_protocol.html * https://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html * https://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this diff --git a/libs/libcurl/src/curl_sasl.c b/libs/libcurl/src/curl_sasl.c index f5ac99a68d..8d39e4f81b 100644 --- a/libs/libcurl/src/curl_sasl.c +++ b/libs/libcurl/src/curl_sasl.c @@ -56,8 +56,8 @@ /* Supported mechanisms */ static const struct { - const char *name; /* Name */ - size_t len; /* Name length */ + const char *name; /* Name */ + size_t len; /* Name length */ unsigned short bit; /* Flag bit */ } mechtable[] = { { "LOGIN", 5, SASL_MECH_LOGIN }, @@ -85,8 +85,11 @@ static const struct { * conn [in] - The connection data. * authused [in] - The authentication mechanism used. */ -void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused) +void Curl_sasl_cleanup(struct connectdata *conn, unsigned short authused) { + (void)conn; + (void)authused; + #if defined(USE_KERBEROS5) /* Cleanup the gssapi structure */ if(authused == SASL_MECH_GSSAPI) { @@ -107,12 +110,6 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused) Curl_auth_cleanup_ntlm(&conn->ntlm); } #endif - -#if !defined(USE_KERBEROS5) && !defined(USE_NTLM) - /* Reserved for future use */ - (void)conn; - (void)authused; -#endif } /* @@ -189,16 +186,35 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, * * Initializes the SASL structure. */ -void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params) +void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data, + const struct SASLproto *params) { + unsigned long auth = data->set.httpauth; + sasl->params = params; /* Set protocol dependent parameters */ sasl->state = SASL_STOP; /* Not yet running */ + sasl->curmech = NULL; /* No mechanism yet. */ sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */ - sasl->prefmech = SASL_AUTH_DEFAULT; /* Prefer all mechanisms */ - sasl->authused = SASL_AUTH_NONE; /* No the authentication mechanism used */ + sasl->prefmech = params->defmechs; /* Default preferred mechanisms */ + sasl->authused = SASL_AUTH_NONE; /* The authentication mechanism used */ sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */ sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */ sasl->force_ir = FALSE; /* Respect external option */ + + if(auth != CURLAUTH_BASIC) { + sasl->resetprefs = FALSE; + sasl->prefmech = SASL_AUTH_NONE; + if(auth & CURLAUTH_BASIC) + sasl->prefmech |= SASL_MECH_PLAIN | SASL_MECH_LOGIN; + if(auth & CURLAUTH_DIGEST) + sasl->prefmech |= SASL_MECH_DIGEST_MD5; + if(auth & CURLAUTH_NTLM) + sasl->prefmech |= SASL_MECH_NTLM; + if(auth & CURLAUTH_BEARER) + sasl->prefmech |= SASL_MECH_OAUTHBEARER | SASL_MECH_XOAUTH2; + if(auth & CURLAUTH_GSSAPI) + sasl->prefmech |= SASL_MECH_GSSAPI; + } } /* @@ -247,40 +263,45 @@ static void state(struct SASL *sasl, struct Curl_easy *data, static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data, struct bufref *out) { - unsigned char *msg; - size_t msglen; - char *serverdata = NULL; CURLcode result = CURLE_OK; - sasl->params->getmessage(data->state.buffer, &serverdata); - if(!serverdata) - result = CURLE_BAD_CONTENT_ENCODING; - else if(!*serverdata || *serverdata == '=') - Curl_bufref_set(out, NULL, 0, NULL); - else { - result = Curl_base64_decode(serverdata, &msg, &msglen); - if(!result) - Curl_bufref_set(out, msg, msglen, curl_free); + result = sasl->params->getmessage(data, out); + if(!result && (sasl->params->flags & SASL_FLAG_BASE64)) { + unsigned char *msg; + size_t msglen; + const char *serverdata = (const char *) Curl_bufref_ptr(out); + + if(!*serverdata || *serverdata == '=') + Curl_bufref_set(out, NULL, 0, NULL); + else { + result = Curl_base64_decode(serverdata, &msg, &msglen); + if(!result) + Curl_bufref_set(out, msg, msglen, curl_free); + } } return result; } /* Encode the outgoing SASL message. */ -static CURLcode build_message(struct Curl_easy *data, struct bufref *msg) +static CURLcode build_message(struct SASL *sasl, struct Curl_easy *data, + struct bufref *msg) { CURLcode result = CURLE_OK; - char *base64; - size_t base64len; - if(!Curl_bufref_ptr(msg)) /* Empty mesage. */ - Curl_bufref_set(msg, "", 0, NULL); - else if(!Curl_bufref_len(msg)) /* Explicit empty response. */ - Curl_bufref_set(msg, "=", 1, NULL); - else { - result = Curl_base64_encode(data, (const char *) Curl_bufref_ptr(msg), - Curl_bufref_len(msg), &base64, &base64len); - if(!result) - Curl_bufref_set(msg, base64, base64len, curl_free); + if(sasl->params->flags & SASL_FLAG_BASE64) { + if(!Curl_bufref_ptr(msg)) /* Empty message. */ + Curl_bufref_set(msg, "", 0, NULL); + else if(!Curl_bufref_len(msg)) /* Explicit empty response. */ + Curl_bufref_set(msg, "=", 1, NULL); + else { + char *base64; + size_t base64len; + + result = Curl_base64_encode(data, (const char *) Curl_bufref_ptr(msg), + Curl_bufref_len(msg), &base64, &base64len); + if(!result) + Curl_bufref_set(msg, base64, base64len, curl_free); + } } return result; @@ -310,11 +331,11 @@ bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn) * Calculate the required login details for SASL authentication. */ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, - struct connectdata *conn, bool force_ir, saslprogress *progress) { CURLcode result = CURLE_OK; - unsigned int enabledmechs; + struct connectdata *conn = data->conn; + unsigned short enabledmechs; const char *mech = NULL; struct bufref resp; saslstate state1 = SASL_STOP; @@ -471,16 +492,16 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, } if(!result && mech) { + sasl->curmech = mech; if(Curl_bufref_ptr(&resp)) - result = build_message(data, &resp); + result = build_message(sasl, data, &resp); if(sasl->params->maxirlen && strlen(mech) + Curl_bufref_len(&resp) > sasl->params->maxirlen) Curl_bufref_free(&resp); if(!result) - result = sasl->params->sendauth(data, conn, mech, - (const char *) Curl_bufref_ptr(&resp)); + result = sasl->params->sendauth(data, mech, &resp); if(!result) { *progress = SASL_INPROGRESS; @@ -498,10 +519,10 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, * Continue the authentication. */ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, - struct connectdata *conn, int code, saslprogress *progress) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; saslstate newstate = SASL_FINAL; struct bufref resp; const char * const hostname = SSL_HOST_NAME(); @@ -574,7 +595,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, result = Curl_auth_create_digest_md5_message(data, &serverdata, conn->user, conn->passwd, service, &resp); - newstate = SASL_DIGESTMD5_RESP; + if(!result && (sasl->params->flags & SASL_FLAG_BASE64)) + newstate = SASL_DIGESTMD5_RESP; break; case SASL_DIGESTMD5_RESP: /* Keep response NULL to output an empty line. */ @@ -630,7 +652,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, } else /* Decode the security challenge and create the response message */ - result = Curl_auth_create_gssapi_security_message(data, &serverdata, + result = Curl_auth_create_gssapi_security_message(data, + conn->sasl_authzid, + &serverdata, &conn->krb5, &resp); } @@ -639,7 +663,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, /* Decode the security challenge and create the response message */ result = get_server_message(sasl, data, &serverdata); if(!result) - result = Curl_auth_create_gssapi_security_message(data, &serverdata, + result = Curl_auth_create_gssapi_security_message(data, + conn->sasl_authzid, + &serverdata, &conn->krb5, &resp); break; @@ -687,7 +713,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, sasl->authmechs ^= sasl->authused; /* Start an alternative SASL authentication */ - return Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress); + return Curl_sasl_start(sasl, data, sasl->force_ir, progress); default: failf(data, "Unsupported SASL authentication mechanism"); result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */ @@ -699,14 +725,13 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, switch(result) { case CURLE_BAD_CONTENT_ENCODING: /* Cancel dialog */ - result = sasl->params->sendcont(data, conn, "*"); + result = sasl->params->cancelauth(data, sasl->curmech); newstate = SASL_CANCEL; break; case CURLE_OK: - result = build_message(data, &resp); + result = build_message(sasl, data, &resp); if(!result) - result = sasl->params->sendcont(data, conn, - (const char *) Curl_bufref_ptr(&resp)); + result = sasl->params->contauth(data, sasl->curmech, &resp); break; default: newstate = SASL_STOP; /* Stop on error */ diff --git a/libs/libcurl/src/curl_sasl.h b/libs/libcurl/src/curl_sasl.h index e17d323eba..91458c74a0 100644 --- a/libs/libcurl/src/curl_sasl.h +++ b/libs/libcurl/src/curl_sasl.h @@ -24,6 +24,8 @@ #include <curl/curl.h> +#include "bufref.h" + struct Curl_easy; struct connectdata; @@ -46,17 +48,20 @@ struct connectdata; #define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & ~SASL_MECH_EXTERNAL) /* Authentication mechanism strings */ -#define SASL_MECH_STRING_LOGIN "LOGIN" -#define SASL_MECH_STRING_PLAIN "PLAIN" -#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5" -#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5" -#define SASL_MECH_STRING_GSSAPI "GSSAPI" -#define SASL_MECH_STRING_EXTERNAL "EXTERNAL" -#define SASL_MECH_STRING_NTLM "NTLM" -#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2" -#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER" -#define SASL_MECH_STRING_SCRAM_SHA_1 "SCRAM-SHA-1" -#define SASL_MECH_STRING_SCRAM_SHA_256 "SCRAM-SHA-256" +#define SASL_MECH_STRING_LOGIN "LOGIN" +#define SASL_MECH_STRING_PLAIN "PLAIN" +#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5" +#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5" +#define SASL_MECH_STRING_GSSAPI "GSSAPI" +#define SASL_MECH_STRING_EXTERNAL "EXTERNAL" +#define SASL_MECH_STRING_NTLM "NTLM" +#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2" +#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER" +#define SASL_MECH_STRING_SCRAM_SHA_1 "SCRAM-SHA-1" +#define SASL_MECH_STRING_SCRAM_SHA_256 "SCRAM-SHA-256" + +/* SASL flags */ +#define SASL_FLAG_BASE64 0x0001 /* Messages are base64-encoded */ /* SASL machine states */ typedef enum { @@ -90,30 +95,37 @@ typedef enum { /* Protocol dependent SASL parameters */ struct SASLproto { const char *service; /* The service name */ - int contcode; /* Code to receive when continuation is expected */ - int finalcode; /* Code to receive upon authentication success */ - size_t maxirlen; /* Maximum initial response length */ - CURLcode (*sendauth)(struct Curl_easy *data, - struct connectdata *conn, - const char *mech, const char *ir); + CURLcode (*sendauth)(struct Curl_easy *data, const char *mech, + const struct bufref *ir); /* Send authentication command */ - CURLcode (*sendcont)(struct Curl_easy *data, - struct connectdata *conn, const char *contauth); + CURLcode (*contauth)(struct Curl_easy *data, const char *mech, + const struct bufref *contauth); /* Send authentication continuation */ - void (*getmessage)(char *buffer, char **outptr); + CURLcode (*cancelauth)(struct Curl_easy *data, const char *mech); + /* Cancel authentication. */ + CURLcode (*getmessage)(struct Curl_easy *data, struct bufref *out); /* Get SASL response message */ + size_t maxirlen; /* Maximum initial response + mechanism length, + or zero if no max. This is normally the max + command length - other characters count. + This has to be zero for non-base64 protocols. */ + int contcode; /* Code to receive when continuation is expected */ + int finalcode; /* Code to receive upon authentication success */ + unsigned short defmechs; /* Mechanisms enabled by default */ + unsigned short flags; /* Configuration flags. */ }; /* Per-connection parameters */ struct SASL { const struct SASLproto *params; /* Protocol dependent parameters */ - saslstate state; /* Current machine state */ + saslstate state; /* Current machine state */ + const char *curmech; /* Current mechanism id. */ unsigned short authmechs; /* Accepted authentication mechanisms */ unsigned short prefmech; /* Preferred authentication mechanism */ unsigned short authused; /* Auth mechanism used for the connection */ - bool resetprefs; /* For URL auth option parsing. */ - bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ - bool force_ir; /* Protocol always supports initial response */ + bool resetprefs; /* For URL auth option parsing. */ + bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ + bool force_ir; /* Protocol always supports initial response */ }; /* This is used to test whether the line starts with the given mechanism */ @@ -123,7 +135,7 @@ struct SASL { /* This is used to cleanup any libraries or curl modules used by the sasl functions */ -void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); +void Curl_sasl_cleanup(struct connectdata *conn, unsigned short authused); /* Convert a mechanism name to a token */ unsigned short Curl_sasl_decode_mech(const char *ptr, @@ -134,19 +146,18 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, const char *value, size_t len); /* Initializes an SASL structure */ -void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params); +void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data, + const struct SASLproto *params); /* Check if we have enough auth data and capabilities to authenticate */ bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn); /* Calculate the required login details for SASL authentication */ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, - struct connectdata *conn, bool force_ir, saslprogress *progress); /* Continue an SASL authentication */ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, - struct connectdata *conn, int code, saslprogress *progress); #endif /* HEADER_CURL_SASL_H */ diff --git a/libs/libcurl/src/curl_setup.h b/libs/libcurl/src/curl_setup.h index c0861d79b7..61384cdff6 100644 --- a/libs/libcurl/src/curl_setup.h +++ b/libs/libcurl/src/curl_setup.h @@ -166,41 +166,47 @@ */ #ifdef HTTP_ONLY -# ifndef CURL_DISABLE_TFTP -# define CURL_DISABLE_TFTP +# ifndef CURL_DISABLE_DICT +# define CURL_DISABLE_DICT +# endif +# ifndef CURL_DISABLE_FILE +# define CURL_DISABLE_FILE # endif # ifndef CURL_DISABLE_FTP # define CURL_DISABLE_FTP # endif +# ifndef CURL_DISABLE_GOPHER +# define CURL_DISABLE_GOPHER +# endif +# ifndef CURL_DISABLE_IMAP +# define CURL_DISABLE_IMAP +# endif # ifndef CURL_DISABLE_LDAP # define CURL_DISABLE_LDAP # endif -# ifndef CURL_DISABLE_TELNET -# define CURL_DISABLE_TELNET +# ifndef CURL_DISABLE_LDAPS +# define CURL_DISABLE_LDAPS # endif -# ifndef CURL_DISABLE_DICT -# define CURL_DISABLE_DICT +# ifndef CURL_DISABLE_MQTT +# define CURL_DISABLE_MQTT # endif -# ifndef CURL_DISABLE_FILE -# define CURL_DISABLE_FILE +# ifndef CURL_DISABLE_POP3 +# define CURL_DISABLE_POP3 # endif # ifndef CURL_DISABLE_RTSP # define CURL_DISABLE_RTSP # endif -# ifndef CURL_DISABLE_POP3 -# define CURL_DISABLE_POP3 -# endif -# ifndef CURL_DISABLE_IMAP -# define CURL_DISABLE_IMAP +# ifndef CURL_DISABLE_SMB +# define CURL_DISABLE_SMB # endif # ifndef CURL_DISABLE_SMTP # define CURL_DISABLE_SMTP # endif -# ifndef CURL_DISABLE_GOPHER -# define CURL_DISABLE_GOPHER +# ifndef CURL_DISABLE_TELNET +# define CURL_DISABLE_TELNET # endif -# ifndef CURL_DISABLE_SMB -# define CURL_DISABLE_SMB +# ifndef CURL_DISABLE_TFTP +# define CURL_DISABLE_TFTP # endif #endif @@ -711,7 +717,6 @@ int netware_init(void); #if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H) # if defined(SOCKET) || \ defined(USE_WINSOCK) || \ - defined(HAVE_WINSOCK_H) || \ defined(HAVE_WINSOCK2_H) || \ defined(HAVE_WS2TCPIP_H) # error "WinSock and lwIP TCP/IP stack definitions shall not coexist!" @@ -833,6 +838,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, ADDRESS_FAMILY sun_family; char sun_path[UNIX_PATH_MAX]; } SOCKADDR_UN, *PSOCKADDR_UN; +# define WIN32_SOCKADDR_UN # endif #endif diff --git a/libs/libcurl/src/curl_setup_once.h b/libs/libcurl/src/curl_setup_once.h index 22d0a063ef..38018d23c7 100644 --- a/libs/libcurl/src/curl_setup_once.h +++ b/libs/libcurl/src/curl_setup_once.h @@ -323,26 +323,6 @@ struct timeval { #include "curl_ctype.h" -/* - * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type. - */ - -#ifndef HAVE_SIG_ATOMIC_T -typedef int sig_atomic_t; -#define HAVE_SIG_ATOMIC_T -#endif - - -/* - * Convenience SIG_ATOMIC_T definition - */ - -#ifdef HAVE_SIG_ATOMIC_T_VOLATILE -#define SIG_ATOMIC_T static sig_atomic_t -#else -#define SIG_ATOMIC_T static volatile sig_atomic_t -#endif - /* * Macro used to include code only in debug builds. diff --git a/libs/libcurl/src/curl_sha256.h b/libs/libcurl/src/curl_sha256.h index b4579d7692..b14c475ef8 100644 --- a/libs/libcurl/src/curl_sha256.h +++ b/libs/libcurl/src/curl_sha256.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2017, Florin Petriuc, <petriuc.florin@gmail.com> - * Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,7 +28,14 @@ extern const struct HMAC_params Curl_HMAC_SHA256[1]; +#ifdef USE_WOLFSSL +/* SHA256_DIGEST_LENGTH is an enum value in wolfSSL. Need to import it from + * sha.h*/ +#include <wolfssl/options.h> +#include <openssl/sha.h> +#else #define SHA256_DIGEST_LENGTH 32 +#endif void Curl_sha256it(unsigned char *outbuffer, const unsigned char *input, const size_t len); diff --git a/libs/libcurl/src/doh.c b/libs/libcurl/src/doh.c index de0c902b86..d6a2167701 100644 --- a/libs/libcurl/src/doh.c +++ b/libs/libcurl/src/doh.c @@ -235,25 +235,6 @@ static CURLcode dohprobe(struct Curl_easy *data, p->dnstype = dnstype; Curl_dyn_init(&p->serverdoh, DYN_DOH_RESPONSE); - /* Note: this is code for sending the DoH request with GET but there's still - no logic that actually enables this. We should either add that ability or - yank out the GET code. Discuss! */ - if(data->set.doh_get) { - char *b64; - size_t b64len; - result = Curl_base64url_encode(data, (char *)p->dohbuffer, p->dohlen, - &b64, &b64len); - if(result) - goto error; - nurl = aprintf("%s?dns=%s", url, b64); - free(b64); - if(!nurl) { - result = CURLE_OUT_OF_MEMORY; - goto error; - } - url = nurl; - } - timeout_ms = Curl_timeleft(data, NULL, TRUE); if(timeout_ms <= 0) { result = CURLE_OPERATION_TIMEDOUT; @@ -268,10 +249,8 @@ static CURLcode dohprobe(struct Curl_easy *data, ERROR_CHECK_SETOPT(CURLOPT_URL, url); ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb); ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp); - if(!data->set.doh_get) { - ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->dohbuffer); - ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen); - } + ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->dohbuffer); + ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen); ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers); #ifdef USE_NGHTTP2 ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c index 588b1fb47e..2aca93845b 100644 --- a/libs/libcurl/src/easy.c +++ b/libs/libcurl/src/easy.c @@ -117,7 +117,7 @@ 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) -curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +curl_wcsdup_callback Curl_cwcsdup = Curl_wcsdup; #endif #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) diff --git a/libs/libcurl/src/easyoptions.c b/libs/libcurl/src/easyoptions.c index 4e65e3525b..b6131d4321 100644 --- a/libs/libcurl/src/easyoptions.c +++ b/libs/libcurl/src/easyoptions.c @@ -165,6 +165,7 @@ struct curl_easyoption Curl_easyopts[] = { {"MAXCONNECTS", CURLOPT_MAXCONNECTS, CURLOT_LONG, 0}, {"MAXFILESIZE", CURLOPT_MAXFILESIZE, CURLOT_LONG, 0}, {"MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE, CURLOT_OFF_T, 0}, + {"MAXLIFETIME_CONN", CURLOPT_MAXLIFETIME_CONN, CURLOT_LONG, 0}, {"MAXREDIRS", CURLOPT_MAXREDIRS, CURLOT_LONG, 0}, {"MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE, CURLOT_OFF_T, 0}, {"MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE, CURLOT_OFF_T, 0}, @@ -192,6 +193,8 @@ struct curl_easyoption Curl_easyopts[] = { {"POSTQUOTE", CURLOPT_POSTQUOTE, CURLOT_SLIST, 0}, {"POSTREDIR", CURLOPT_POSTREDIR, CURLOT_VALUES, 0}, {"PREQUOTE", CURLOPT_PREQUOTE, CURLOT_SLIST, 0}, + {"PREREQDATA", CURLOPT_PREREQDATA, CURLOT_CBPTR, 0}, + {"PREREQFUNCTION", CURLOPT_PREREQFUNCTION, CURLOT_FUNCTION, 0}, {"PRE_PROXY", CURLOPT_PRE_PROXY, CURLOT_STRING, 0}, {"PRIVATE", CURLOPT_PRIVATE, CURLOT_OBJECT, 0}, {"PROGRESSDATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS}, @@ -271,6 +274,8 @@ struct curl_easyoption Curl_easyopts[] = { {"SSH_COMPRESSION", CURLOPT_SSH_COMPRESSION, CURLOT_LONG, 0}, {"SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOT_STRING, 0}, + {"SSH_HOST_PUBLIC_KEY_SHA256", CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, + CURLOT_STRING, 0}, {"SSH_KEYDATA", CURLOPT_SSH_KEYDATA, CURLOT_CBPTR, 0}, {"SSH_KEYFUNCTION", CURLOPT_SSH_KEYFUNCTION, CURLOT_FUNCTION, 0}, {"SSH_KNOWNHOSTS", CURLOPT_SSH_KNOWNHOSTS, CURLOT_STRING, 0}, @@ -354,6 +359,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (310 + 1)); + return ((CURLOPT_LASTENTRY%10000) != (314 + 1)); } #endif diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c index 1a699de594..a8d209e3fb 100644 --- a/libs/libcurl/src/ftp.c +++ b/libs/libcurl/src/ftp.c @@ -876,11 +876,6 @@ static CURLcode ftp_state_cwd(struct Curl_easy *data, ftpc->count2 = 0; /* count2 counts failed CWDs */ - /* count3 is set to allow a MKD to fail once. In the case when first CWD - fails and then MKD fails (due to another session raced it to create the - dir) this then allows for a second try to CWD to it */ - ftpc->count3 = (data->set.ftp_create_missing_dirs == 2)?1:0; - if(conn->bits.reuse && ftpc->entrypath && /* no need to go to entrypath when we have an absolute path */ !(ftpc->dirdepth && ftpc->dirs[0][0] == '/')) { @@ -2681,9 +2676,12 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, /* we have now received a full FTP server response */ switch(ftpc->state) { case FTP_WAIT220: - if(ftpcode == 230) - /* 230 User logged in - already! */ - return ftp_state_user_resp(data, ftpcode, ftpc->state); + if(ftpcode == 230) { + /* 230 User logged in - already! Take as 220 if TLS required. */ + if(data->set.use_ssl <= CURLUSESSL_TRY || + conn->bits.ftp_use_control_ssl) + return ftp_state_user_resp(data, ftpcode, ftpc->state); + } else if(ftpcode != 220) { failf(data, "Got a %03d ftp-server response when 220 was expected", ftpcode); @@ -2740,6 +2738,9 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, case FTP_AUTH: /* we have gotten the response to a previous AUTH command */ + if(pp->cache_size) + return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */ + /* RFC2228 (page 5) says: * * If the server is willing to accept the named security mechanism, @@ -2996,6 +2997,12 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, ftpc->cwdcount && !ftpc->count2) { /* try making it */ ftpc->count2++; /* counter to prevent CWD-MKD loops */ + + /* count3 is set to allow MKD to fail once per dir. In the case when + CWD fails and then MKD fails (due to another session raced it to + create the dir) this then allows for a second try to CWD to it. */ + ftpc->count3 = (data->set.ftp_create_missing_dirs == 2) ? 1 : 0; + result = Curl_pp_sendf(data, &ftpc->pp, "MKD %s", ftpc->dirs[ftpc->cwdcount - 1]); if(!result) diff --git a/libs/libcurl/src/hostasyn.c b/libs/libcurl/src/hostasyn.c index b25de1d417..f7d99ce9a6 100644 --- a/libs/libcurl/src/hostasyn.c +++ b/libs/libcurl/src/hostasyn.c @@ -50,7 +50,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "curl_memory.h" /* The last #include file should be: */ diff --git a/libs/libcurl/src/hostip.c b/libs/libcurl/src/hostip.c index 30ce509267..c33c9af9d0 100644 --- a/libs/libcurl/src/hostip.c +++ b/libs/libcurl/src/hostip.c @@ -56,7 +56,6 @@ #include "hash.h" #include "rand.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "inet_ntop.h" #include "inet_pton.h" @@ -508,9 +507,6 @@ static struct Curl_addrinfo *get_localhost(int port) struct sockaddr_in sa; unsigned int ipv4; unsigned short port16 = (unsigned short)(port & 0xffff); - ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1); - if(!ca) - return NULL; /* memset to clear the sa.sin_zero field */ memset(&sa, 0, sizeof(sa)); @@ -520,6 +516,9 @@ static struct Curl_addrinfo *get_localhost(int port) return NULL; memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4)); + ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1); + if(!ca) + return NULL; ca->ai_flags = 0; ca->ai_family = AF_INET; ca->ai_socktype = SOCK_STREAM; @@ -533,6 +532,36 @@ static struct Curl_addrinfo *get_localhost(int port) return ca; } +#ifdef ENABLE_IPV6 +/* + * Curl_ipv6works() returns TRUE if IPv6 seems to work. + */ +bool Curl_ipv6works(struct Curl_easy *data) +{ + if(data) { + /* the nature of most system is that IPv6 status doesn't come and go + during a program's lifetime so we only probe the first time and then we + have the info kept for fast re-use */ + DEBUGASSERT(data); + DEBUGASSERT(data->multi); + return data->multi->ipv6_works; + } + else { + int ipv6_works = -1; + /* probe to see if we have a working IPv6 stack */ + curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); + if(s == CURL_SOCKET_BAD) + /* an IPv6 address was requested but we can't get/use one */ + ipv6_works = 0; + else { + ipv6_works = 1; + sclose(s); + } + return (ipv6_works>0)?TRUE:FALSE; + } +} +#endif /* ENABLE_IPV6 */ + /* * Curl_host_is_ipnum() returns TRUE if the given string is a numerical IPv4 * (or IPv6 if supported) address. @@ -674,9 +703,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, #endif /* !USE_RESOLVE_ON_IPS */ if(!addr) { - /* Check what IP specifics the app has requested and if we can provide - * it. If not, bail out. */ - if(!Curl_ipvalid(data, conn)) + if(conn->ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data)) return CURLRESOLV_ERROR; if(strcasecompare(hostname, "localhost")) @@ -684,6 +711,10 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, else if(allowDOH && data->set.doh && !ipnum) addr = Curl_doh(data, hostname, port, &respwait); else { + /* Check what IP specifics the app has requested and if we can provide + * it. If not, bail out. */ + if(!Curl_ipvalid(data, conn)) + return CURLRESOLV_ERROR; /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a non-zero value indicating that we need to wait for the response to the resolve call */ diff --git a/libs/libcurl/src/hostip.h b/libs/libcurl/src/hostip.h index 28f3b84018..67a688aebd 100644 --- a/libs/libcurl/src/hostip.h +++ b/libs/libcurl/src/hostip.h @@ -97,7 +97,7 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data, struct Curl_dns_entry **dnsentry, timediff_t timeoutms); -#ifdef CURLRES_IPV6 +#ifdef ENABLE_IPV6 /* * Curl_ipv6works() returns TRUE if IPv6 seems to work. */ diff --git a/libs/libcurl/src/hostip4.c b/libs/libcurl/src/hostip4.c index ac92126d8c..1fd791015c 100644 --- a/libs/libcurl/src/hostip4.c +++ b/libs/libcurl/src/hostip4.c @@ -50,7 +50,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" diff --git a/libs/libcurl/src/hostip6.c b/libs/libcurl/src/hostip6.c index 943cdd261c..c2d5f08e32 100644 --- a/libs/libcurl/src/hostip6.c +++ b/libs/libcurl/src/hostip6.c @@ -50,7 +50,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "inet_pton.h" #include "connect.h" @@ -60,34 +59,6 @@ #include "memdebug.h" /* - * Curl_ipv6works() returns TRUE if IPv6 seems to work. - */ -bool Curl_ipv6works(struct Curl_easy *data) -{ - if(data) { - /* the nature of most system is that IPv6 status doesn't come and go - during a program's lifetime so we only probe the first time and then we - have the info kept for fast re-use */ - DEBUGASSERT(data); - DEBUGASSERT(data->multi); - return data->multi->ipv6_works; - } - else { - int ipv6_works = -1; - /* probe to see if we have a working IPv6 stack */ - curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); - if(s == CURL_SOCKET_BAD) - /* an IPv6 address was requested but we can't get/use one */ - ipv6_works = 0; - else { - ipv6_works = 1; - sclose(s); - } - return (ipv6_works>0)?TRUE:FALSE; - } -} - -/* * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've * been set and returns TRUE if they are OK. */ diff --git a/libs/libcurl/src/hostsyn.c b/libs/libcurl/src/hostsyn.c index 550b43a085..c00c2744c4 100644 --- a/libs/libcurl/src/hostsyn.c +++ b/libs/libcurl/src/hostsyn.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -50,7 +50,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "curl_memory.h" /* The last #include file should be: */ diff --git a/libs/libcurl/src/hsts.c b/libs/libcurl/src/hsts.c index 0d5a584012..052dc11571 100644 --- a/libs/libcurl/src/hsts.c +++ b/libs/libcurl/src/hsts.c @@ -49,6 +49,7 @@ #define MAX_HSTS_HOSTLENSTR "256" #define MAX_HSTS_DATELEN 64 #define MAX_HSTS_DATELENSTR "64" +#define UNLIMITED "unlimited" #ifdef DEBUGBUILD /* to play well with debug builds, we can *set* a fixed time this will @@ -283,13 +284,17 @@ static CURLcode hsts_push(struct Curl_easy *data, e.namelen = strlen(sts->host); e.includeSubDomains = sts->includeSubDomains; - result = Curl_gmtime((time_t)sts->expires, &stamp); - if(result) - return result; + if(sts->expires != TIME_T_MAX) { + result = Curl_gmtime((time_t)sts->expires, &stamp); + if(result) + return result; - msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d", - stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, - stamp.tm_hour, stamp.tm_min, stamp.tm_sec); + msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d", + stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, + stamp.tm_hour, stamp.tm_min, stamp.tm_sec); + } + else + strcpy(e.expire, UNLIMITED); sc = data->set.hsts_write(data, &e, i, data->set.hsts_write_userp); @@ -303,14 +308,18 @@ static CURLcode hsts_push(struct Curl_easy *data, static CURLcode hsts_out(struct stsentry *sts, FILE *fp) { struct tm stamp; - CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp); - if(result) - return result; - - fprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n", - sts->includeSubDomains ? ".": "", sts->host, - stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, - stamp.tm_hour, stamp.tm_min, stamp.tm_sec); + if(sts->expires != TIME_T_MAX) { + CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp); + if(result) + return result; + fprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n", + sts->includeSubDomains ? ".": "", sts->host, + stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, + stamp.tm_hour, stamp.tm_min, stamp.tm_sec); + } + else + fprintf(fp, "%s%s \"%s\"\n", + sts->includeSubDomains ? ".": "", sts->host, UNLIMITED); return CURLE_OK; } @@ -403,7 +412,8 @@ static CURLcode hsts_add(struct hsts *h, char *line) "%" MAX_HSTS_HOSTLENSTR "s \"%" MAX_HSTS_DATELENSTR "[^\"]\"", host, date); if(2 == rc) { - time_t expires = Curl_getdate_capped(date); + time_t expires = strcmp(date, UNLIMITED) ? Curl_getdate_capped(date) : + TIME_T_MAX; CURLcode result; char *p = host; bool subdomain = FALSE; @@ -456,7 +466,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h) return result; } else if(sc == CURLSTS_FAIL) - return CURLE_BAD_FUNCTION_ARGUMENT; + return CURLE_ABORTED_BY_CALLBACK; } while(sc == CURLSTS_OK); } return CURLE_OK; @@ -526,7 +536,9 @@ CURLcode Curl_hsts_loadfile(struct Curl_easy *data, */ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h) { - return hsts_pull(data, h); + if(h) + return hsts_pull(data, h); + return CURLE_OK; } #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ diff --git a/libs/libcurl/src/hsts.h b/libs/libcurl/src/hsts.h index baa582864a..653c05348d 100644 --- a/libs/libcurl/src/hsts.h +++ b/libs/libcurl/src/hsts.h @@ -59,7 +59,7 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h); #else #define Curl_hsts_cleanup(x) -#define Curl_hsts_loadcb(x,y) +#define Curl_hsts_loadcb(x,y) CURLE_OK #define Curl_hsts_save(x,y,z) #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ #endif /* HEADER_CURL_HSTS_H */ diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c index 05b971b204..78ad10edea 100644 --- a/libs/libcurl/src/http.c +++ b/libs/libcurl/src/http.c @@ -323,7 +323,7 @@ static CURLcode http_output_basic(struct Curl_easy *data, bool proxy) pwd = data->state.aptr.passwd; } - out = aprintf("%s:%s", user, pwd ? pwd : ""); + out = aprintf("%s:%s", user ? user : "", pwd ? pwd : ""); if(!out) return CURLE_OUT_OF_MEMORY; @@ -1669,8 +1669,8 @@ CURLcode Curl_http_done(struct Curl_easy *data, * - if any server previously contacted to handle this request only supports * 1.0. */ -static bool use_http_1_1plus(const struct Curl_easy *data, - const struct connectdata *conn) +bool Curl_use_http_1_1plus(const struct Curl_easy *data, + const struct connectdata *conn) { if((data->state.httpversion == 10) || (conn->httpversion == 10)) return FALSE; @@ -1696,7 +1696,7 @@ static const char *get_http_string(const struct Curl_easy *data, return "2"; #endif - if(use_http_1_1plus(data, conn)) + if(Curl_use_http_1_1plus(data, conn)) return "1.1"; return "1.0"; @@ -1711,7 +1711,7 @@ static CURLcode expect100(struct Curl_easy *data, CURLcode result = CURLE_OK; data->state.expect100header = FALSE; /* default to false unless it is set to TRUE below */ - if(!data->state.disableexpect && use_http_1_1plus(data, conn) && + 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 Expect: 100-continue to the headers which actually speeds up post @@ -2348,7 +2348,7 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, if(conn->bits.authneg) /* don't enable chunked during auth neg */ ; - else if(use_http_1_1plus(data, conn)) { + else if(Curl_use_http_1_1plus(data, conn)) { if(conn->httpversion < 20) /* HTTP, upload, unknown file size and not HTTP 1.0 */ data->req.upload_chunky = TRUE; @@ -2711,14 +2711,16 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, int count = 0; if(data->cookies && data->state.cookie_engine) { + const char *host = data->state.aptr.cookiehost ? + data->state.aptr.cookiehost : conn->host.name; + const bool secure_context = + conn->handler->protocol&CURLPROTO_HTTPS || + strcasecompare("localhost", host) || + !strcmp(host, "127.0.0.1") || + !strcmp(host, "[::1]") ? TRUE : FALSE; Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - co = Curl_cookie_getlist(data->cookies, - data->state.aptr.cookiehost? - data->state.aptr.cookiehost: - conn->host.name, - data->state.up.path, - (conn->handler->protocol&CURLPROTO_HTTPS)? - TRUE:FALSE); + co = Curl_cookie_getlist(data->cookies, host, data->state.up.path, + secure_context); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } if(co) { @@ -2900,7 +2902,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data, bool *done) { struct SingleRequest *k = &data->req; - DEBUGASSERT(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)); + if(data->req.newurl) { if(conn->bits.close) { /* Abort after the headers if "follow Location" is set @@ -3401,17 +3403,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, NULL, 10, &contentlength); if(offt == CURL_OFFT_OK) { - if(data->set.max_filesize && - contentlength > data->set.max_filesize) { - failf(data, "Maximum file size exceeded"); - return CURLE_FILESIZE_EXCEEDED; - } k->size = contentlength; k->maxdownload = k->size; - /* we set the progress download size already at this point - just to make it easier for apps/callbacks to extract this - info as soon as possible */ - Curl_pgrsSetDownloadSize(data, k->size); } else if(offt == CURL_OFFT_FLOW) { /* out of range */ @@ -3502,6 +3495,12 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, TRUE); if(result) return result; + if(!k->chunk) { + /* if this isn't chunked, only close can signal the end of this transfer + as Content-Length is said not to be trusted for transfer-encoding! */ + connclose(conn, "HTTP/1.1 transfer-encoding without chunks"); + k->ignore_cl = TRUE; + } } else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) && data->set.str[STRING_ENCODING]) { @@ -3564,18 +3563,21 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, #if !defined(CURL_DISABLE_COOKIES) else if(data->cookies && data->state.cookie_engine && checkprefix("Set-Cookie:", headp)) { + /* If there is a custom-set Host: name, use it here, or else use real peer + host name. */ + const char *host = data->state.aptr.cookiehost? + data->state.aptr.cookiehost:conn->host.name; + const bool secure_context = + conn->handler->protocol&CURLPROTO_HTTPS || + strcasecompare("localhost", host) || + !strcmp(host, "127.0.0.1") || + !strcmp(host, "[::1]") ? TRUE : FALSE; + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - Curl_cookie_add(data, - data->cookies, TRUE, FALSE, - headp + strlen("Set-Cookie:"), - /* If there is a custom-set Host: name, use it - here, or else use real peer host name. */ - data->state.aptr.cookiehost? - data->state.aptr.cookiehost:conn->host.name, - data->state.up.path, - (conn->handler->protocol&CURLPROTO_HTTPS)? - TRUE:FALSE); + Curl_cookie_add(data, data->cookies, TRUE, FALSE, + headp + strlen("Set-Cookie:"), host, + data->state.up.path, secure_context); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } #endif @@ -3771,6 +3773,29 @@ CURLcode Curl_http_statusline(struct Curl_easy *data, return CURLE_OK; } +/* Content-Length must be ignored if any Transfer-Encoding is present in the + response. Refer to RFC 7230 section 3.3.3 and RFC2616 section 4.4. This is + figured out here after all headers have been received but before the final + call to the user's header callback, so that a valid content length can be + retrieved by the user in the final call. */ +CURLcode Curl_http_size(struct Curl_easy *data) +{ + struct SingleRequest *k = &data->req; + if(data->req.ignore_cl || k->chunk) { + k->size = k->maxdownload = -1; + } + else if(k->size != -1) { + if(data->set.max_filesize && + k->size > data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + Curl_pgrsSetDownloadSize(data, k->size); + k->maxdownload = k->size; + } + return CURLE_OK; +} + /* * Read any HTTP header lines from the server and pass them to the client app. */ @@ -3965,6 +3990,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, } } + if(!k->header) { + result = Curl_http_size(data); + if(result) + return result; + } + /* At this point we have some idea about the fate of the connection. If we are closing the connection it may result auth failure. */ #if defined(USE_NTLM) @@ -4121,31 +4152,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, reason */ *stop_reading = TRUE; #endif - else { - /* If we know the expected size of this document, we set the - maximum download size to the size of the expected - document or else, we won't know when to stop reading! - - Note that we set the download maximum even if we read a - "Connection: close" header, to make sure that - "Content-Length: 0" still prevents us from attempting to - read the (missing) response-body. - */ - /* According to RFC2616 section 4.4, we MUST ignore - Content-Length: headers if we are now receiving data - using chunked Transfer-Encoding. - */ - if(k->chunk) - k->maxdownload = k->size = -1; - } - if(-1 != k->size) { - /* We do this operation even if no_body is true, since this - data might be retrieved later with curl_easy_getinfo() - and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */ - - Curl_pgrsSetDownloadSize(data, k->size); - k->maxdownload = k->size; - } /* If max download size is *zero* (nothing) we already have nothing and can safely return ok now! But for HTTP/2, we'd @@ -4210,18 +4216,20 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * https://tools.ietf.org/html/rfc7230#section-3.1.2 * * The response code is always a three-digit number in HTTP as the spec - * says. We try to allow any number here, but we cannot make + * says. We allow any three-digit number here, but we cannot make * guarantees on future behaviors since it isn't within the protocol. */ char separator; char twoorthree[2]; int httpversion = 0; + char digit4 = 0; nc = sscanf(HEADER1, - " HTTP/%1d.%1d%c%3d", + " HTTP/%1d.%1d%c%3d%c", &httpversion_major, &httpversion, &separator, - &k->httpcode); + &k->httpcode, + &digit4); if(nc == 1 && httpversion_major >= 2 && 2 == sscanf(HEADER1, " HTTP/%1[23] %d", twoorthree, &k->httpcode)) { @@ -4230,7 +4238,19 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, separator = ' '; } - if((nc == 4) && (' ' == separator)) { + /* There can only be a 4th response code digit stored in 'digit4' if + all the other fields were parsed and stored first, so nc is 5 when + digit4 a digit. + + The sscanf() line above will also allow zero-prefixed and negative + numbers, so we check for that too here. + */ + else if(ISDIGIT(digit4) || (k->httpcode < 100)) { + failf(data, "Unsupported response code in HTTP response"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + if((nc >= 4) && (' ' == separator)) { httpversion += 10 * httpversion_major; switch(httpversion) { case 10: diff --git a/libs/libcurl/src/http.h b/libs/libcurl/src/http.h index bce171550d..cb5b56faf3 100644 --- a/libs/libcurl/src/http.h +++ b/libs/libcurl/src/http.h @@ -99,6 +99,8 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, const char **teep); CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, struct dynbuf *r, Curl_HttpReq httpreq); +bool Curl_use_http_1_1plus(const struct Curl_easy *data, + const struct connectdata *conn); #ifndef CURL_DISABLE_COOKIES CURLcode Curl_http_cookies(struct Curl_easy *data, struct connectdata *conn, @@ -287,6 +289,8 @@ struct http_conn { #endif }; +CURLcode Curl_http_size(struct Curl_easy *data); + CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, struct connectdata *conn, ssize_t *nread, diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c index 60e0143c15..992fbbb26d 100644 --- a/libs/libcurl/src/http2.c +++ b/libs/libcurl/src/http2.c @@ -100,6 +100,7 @@ static int http2_getsock(struct Curl_easy *data, const struct http_conn *c = &conn->proto.httpc; struct SingleRequest *k = &data->req; int bitmap = GETSOCK_BLANK; + struct HTTP *stream = data->req.p.http; sock[0] = conn->sock[FIRSTSOCKET]; @@ -108,9 +109,13 @@ static int http2_getsock(struct Curl_easy *data, frame so we should always be ready for one */ bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); - /* we're still uploading or the HTTP/2 layer wants to send data */ - if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) || - nghttp2_session_want_write(c->h2)) + /* 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_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) || + nghttp2_session_want_write(c->h2)) && + (nghttp2_session_get_remote_window_size(c->h2) && + nghttp2_session_get_stream_remote_window_size(c->h2, + stream->stream_id))) bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); return bitmap; @@ -763,6 +768,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, ncopy); stream->nread_header_recvbuf += ncopy; + DEBUGASSERT(stream->mem); H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p", ncopy, stream_id, stream->mem)); @@ -1624,10 +1630,6 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return -1; } - if(stream->closed) - /* closed overrides paused */ - return http2_handle_stream_close(conn, data, stream, err); - /* Nullify here because we call nghttp2_session_send() and they might refer to the old buffer. */ stream->upload_mem = NULL; @@ -1956,8 +1958,19 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, nghttp2_session_resume_data(h2, stream->stream_id); } - H2BUGF(infof(data, "http2_send returns %zu for stream %u", len, - stream->stream_id)); +#ifdef DEBUG_HTTP2 + if(!len) { + infof(data, "http2_send: easy %p (stream %u) win %u/%u", + data, stream->stream_id, + nghttp2_session_get_remote_window_size(httpc->h2), + nghttp2_session_get_stream_remote_window_size(httpc->h2, + stream->stream_id) + ); + + } + infof(data, "http2_send returns %zu for stream %u", len, + stream->stream_id); +#endif return len; } @@ -2218,6 +2231,16 @@ CURLcode Curl_http2_setup(struct Curl_easy *data, Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS); Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS); + stream->upload_left = 0; + stream->upload_mem = NULL; + stream->upload_len = 0; + stream->mem = data->state.buffer; + stream->len = data->set.buffer_size; + + multi_connchanged(data->multi); + /* below this point only connection related inits are done, which only needs + to be done once per connection */ + if((conn->handler == &Curl_handler_http2_ssl) || (conn->handler == &Curl_handler_http2)) return CURLE_OK; /* already done */ @@ -2234,11 +2257,10 @@ CURLcode Curl_http2_setup(struct Curl_easy *data, } infof(data, "Using HTTP2, server supports multiplexing"); - stream->upload_left = 0; - stream->upload_mem = NULL; - stream->upload_len = 0; - stream->mem = data->state.buffer; - stream->len = data->set.buffer_size; + + conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ + conn->httpversion = 20; + conn->bundle->multiuse = BUNDLE_MULTIPLEX; httpc->inbuflen = 0; httpc->nread_inbuf = 0; @@ -2246,12 +2268,7 @@ CURLcode Curl_http2_setup(struct Curl_easy *data, httpc->pause_stream_id = 0; httpc->drain_total = 0; - conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ - conn->httpversion = 20; - conn->bundle->multiuse = BUNDLE_MULTIPLEX; - infof(data, "Connection state changed (HTTP/2 confirmed)"); - multi_connchanged(data->multi); return CURLE_OK; } @@ -2340,15 +2357,8 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, DEBUGASSERT(httpc->nread_inbuf == 0); - /* Good enough to call it an end once the remaining payload is copied to the - * connection buffer. - * Some servers (e.g. nghttpx v1.43.0) may fulfill stream 1 immediately - * following the protocol switch other than waiting for the client-side - * connection preface. If h2_process_pending_input is invoked here to parse - * the remaining payload, stream 1 would be marked as closed too early and - * thus ignored in http2_recv (following 252790c53). - * The logic in lib/http.c and lib/transfer.c guarantees a following - * http2_recv would be invoked very soon. */ + if(-1 == h2_process_pending_input(data, httpc, &result)) + return CURLE_HTTP2; return CURLE_OK; } diff --git a/libs/libcurl/src/http_aws_sigv4.c b/libs/libcurl/src/http_aws_sigv4.c index 02663abd63..cbbecb7129 100644 --- a/libs/libcurl/src/http_aws_sigv4.c +++ b/libs/libcurl/src/http_aws_sigv4.c @@ -92,6 +92,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) char *signed_headers = NULL; Curl_HttpReq httpreq; const char *method; + size_t post_data_len; const char *post_data = data->set.postfields ? data->set.postfields : ""; unsigned char sha_hash[32]; char sha_hex[65]; @@ -281,8 +282,12 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) goto fail; } + if(data->set.postfieldsize < 0) + post_data_len = strlen(post_data); + else + post_data_len = (size_t)data->set.postfieldsize; Curl_sha256it(sha_hash, - (const unsigned char *) post_data, strlen(post_data)); + (const unsigned char *) post_data, post_data_len); sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex)); Curl_http_method(data, conn, &method, &httpreq); @@ -321,7 +326,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) /* * Google allow to use rsa key instead of HMAC, so this code might change - * In the furure, but for now we support only HMAC version + * In the future, but for now we support only HMAC version */ str_to_sign = curl_maprintf("%s4-HMAC-SHA256\n" /* Algorithm */ "%s\n" /* RequestDateTime */ diff --git a/libs/libcurl/src/http_ntlm.c b/libs/libcurl/src/http_ntlm.c index 627a11c5af..a6526db9f7 100644 --- a/libs/libcurl/src/http_ntlm.c +++ b/libs/libcurl/src/http_ntlm.c @@ -198,6 +198,12 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) #endif Curl_bufref_init(&ntlmmsg); + + /* connection is already authenticated, don't send a header in future + * requests so go directly to NTLMSTATE_LAST */ + if(*state == NTLMSTATE_TYPE3) + *state = NTLMSTATE_LAST; + switch(*state) { case NTLMSTATE_TYPE1: default: /* for the weird cases we (re)start here */ @@ -246,11 +252,6 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) } break; - case NTLMSTATE_TYPE3: - /* connection is already authenticated, - * don't send a header in future requests */ - *state = NTLMSTATE_LAST; - /* FALLTHROUGH */ case NTLMSTATE_LAST: Curl_safefree(*allocuserpwd); authp->done = TRUE; diff --git a/libs/libcurl/src/http_proxy.c b/libs/libcurl/src/http_proxy.c index a7f7aa353f..fc050a07d5 100644 --- a/libs/libcurl/src/http_proxy.c +++ b/libs/libcurl/src/http_proxy.c @@ -148,7 +148,7 @@ int Curl_connect_getsock(struct connectdata *conn) DEBUGASSERT(conn->connect_state); http = &conn->connect_state->http_proxy; - if(http->sending) + if(http->sending == HTTPSEND_REQUEST) return GETSOCK_WRITESOCK(0); return GETSOCK_READSOCK(0); @@ -207,9 +207,15 @@ static void connect_done(struct Curl_easy *data) Curl_dyn_free(&s->rcvbuf); Curl_dyn_free(&s->req); - /* retore the protocol pointer */ + /* restore the protocol pointer */ data->req.p.http = s->prot_save; s->prot_save = NULL; + data->info.httpcode = 0; /* clear it as it might've been used for the + proxy */ + data->req.ignorebody = FALSE; +#ifdef USE_HYPER + data->state.hconnect = FALSE; +#endif infof(data, "CONNECT phase completed!"); } } @@ -284,8 +290,7 @@ static CURLcode CONNECT(struct Curl_easy *data, /* This only happens if we've looped here due to authentication reasons, and we don't really use the newly cloned URL here then. Just free() it. */ - free(data->req.newurl); - data->req.newurl = NULL; + Curl_safefree(data->req.newurl); /* initialize send-buffer */ Curl_dyn_init(req, DYN_HTTP_REQUEST); @@ -300,32 +305,27 @@ static CURLcode CONNECT(struct Curl_easy *data, hostheader, TRUE); if(!result) { - const char *proxyconn = ""; - const char *useragent = ""; const char *httpv = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1"; - if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection")) - proxyconn = "Proxy-Connection: Keep-Alive\r\n"; - - if(!Curl_checkProxyheaders(data, conn, "User-Agent") && - data->set.str[STRING_USERAGENT]) - useragent = data->state.aptr.uagent; - result = Curl_dyn_addf(req, "CONNECT %s HTTP/%s\r\n" "%s" /* Host: */ - "%s" /* Proxy-Authorization */ - "%s" /* User-Agent */ - "%s", /* Proxy-Connection */ + "%s", /* Proxy-Authorization */ hostheader, httpv, host?host:"", data->state.aptr.proxyuserpwd? - data->state.aptr.proxyuserpwd:"", - useragent, - proxyconn); + data->state.aptr.proxyuserpwd:""); + + if(!result && !Curl_checkProxyheaders(data, conn, "User-Agent") && + data->set.str[STRING_USERAGENT]) + result = Curl_dyn_addf(req, "User-Agent: %s\r\n", + data->set.str[STRING_USERAGENT]); + + if(!result && !Curl_checkProxyheaders(data, conn, "Proxy-Connection")) + result = Curl_dyn_add(req, "Proxy-Connection: Keep-Alive\r\n"); if(!result) result = Curl_add_custom_headers(data, TRUE, req); @@ -390,6 +390,7 @@ static CURLcode CONNECT(struct Curl_easy *data, k->upload_fromhere += bytes_written; return result; } + http->sending = HTTPSEND_NADA; /* if nothing left to send, continue */ } { /* READING RESPONSE PHASE */ @@ -739,6 +740,7 @@ static CURLcode CONNECT(struct Curl_easy *data, io = hyper_io_new(); if(!io) { failf(data, "Couldn't create hyper IO"); + result = CURLE_OUT_OF_MEMORY; goto error; } /* tell Hyper how to read/write network data */ @@ -754,6 +756,7 @@ static CURLcode CONNECT(struct Curl_easy *data, h->exec = hyper_executor_new(); if(!h->exec) { failf(data, "Couldn't create hyper executor"); + result = CURLE_OUT_OF_MEMORY; goto error; } } @@ -761,6 +764,7 @@ static CURLcode CONNECT(struct Curl_easy *data, options = hyper_clientconn_options_new(); if(!options) { failf(data, "Couldn't create hyper client options"); + result = CURLE_OUT_OF_MEMORY; goto error; } @@ -771,6 +775,7 @@ static CURLcode CONNECT(struct Curl_easy *data, handshake = hyper_clientconn_handshake(io, options); if(!handshake) { failf(data, "Couldn't create hyper client handshake"); + result = CURLE_OUT_OF_MEMORY; goto error; } io = NULL; @@ -778,6 +783,7 @@ static CURLcode CONNECT(struct Curl_easy *data, if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) { failf(data, "Couldn't hyper_executor_push the handshake"); + result = CURLE_OUT_OF_MEMORY; goto error; } handshake = NULL; /* ownership passed on */ @@ -785,6 +791,7 @@ static CURLcode CONNECT(struct Curl_easy *data, task = hyper_executor_poll(h->exec); if(!task) { failf(data, "Couldn't hyper_executor_poll the handshake"); + result = CURLE_OUT_OF_MEMORY; goto error; } @@ -793,14 +800,24 @@ static CURLcode CONNECT(struct Curl_easy *data, req = hyper_request_new(); if(!req) { failf(data, "Couldn't hyper_request_new"); + result = CURLE_OUT_OF_MEMORY; goto error; } if(hyper_request_set_method(req, (uint8_t *)"CONNECT", strlen("CONNECT"))) { failf(data, "error setting method"); + result = CURLE_OUT_OF_MEMORY; goto error; } + infof(data, "Establish HTTP proxy tunnel to %s:%d", + hostname, remote_port); + + /* This only happens if we've looped here due to authentication + reasons, and we don't really use the newly cloned URL here + then. Just free() it. */ + Curl_safefree(data->req.newurl); + result = CONNECT_host(data, conn, hostname, remote_port, &hostheader, &host); if(result) @@ -810,6 +827,16 @@ static CURLcode CONNECT(struct Curl_easy *data, strlen(hostheader))) { failf(data, "error setting path"); result = CURLE_OUT_OF_MEMORY; + goto error; + } + if(data->set.verbose) { + char *se = aprintf("CONNECT %s HTTP/1.1\r\n", hostheader); + if(!se) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } + Curl_debug(data, CURLINFO_HEADER_OUT, se, strlen(se)); + free(se); } /* Setup the proxy-authorization header, if any */ result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET, @@ -823,40 +850,65 @@ static CURLcode CONNECT(struct Curl_easy *data, (HYPERE_OK != hyper_request_set_version(req, HYPER_HTTP_VERSION_1_0))) { failf(data, "error setting HTTP version"); + result = CURLE_OUT_OF_MEMORY; goto error; } headers = hyper_request_headers(req); if(!headers) { failf(data, "hyper_request_headers"); + result = CURLE_OUT_OF_MEMORY; goto error; } - if(host && Curl_hyper_header(data, headers, host)) - goto error; - Curl_safefree(host); + if(host) { + result = Curl_hyper_header(data, headers, host); + if(result) + goto error; + Curl_safefree(host); + } - if(data->state.aptr.proxyuserpwd && - Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd)) - goto error; + if(data->state.aptr.proxyuserpwd) { + result = Curl_hyper_header(data, headers, + data->state.aptr.proxyuserpwd); + if(result) + goto error; + } - if(data->set.str[STRING_USERAGENT] && - *data->set.str[STRING_USERAGENT] && - data->state.aptr.uagent && - Curl_hyper_header(data, headers, data->state.aptr.uagent)) - goto error; + if(!Curl_checkProxyheaders(data, conn, "User-Agent") && + data->set.str[STRING_USERAGENT]) { + struct dynbuf ua; + Curl_dyn_init(&ua, DYN_HTTP_REQUEST); + result = Curl_dyn_addf(&ua, "User-Agent: %s\r\n", + data->set.str[STRING_USERAGENT]); + if(result) + goto error; + result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&ua)); + if(result) + goto error; + Curl_dyn_free(&ua); + } - if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection") && - Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive")) + if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection")) { + result = Curl_hyper_header(data, headers, + "Proxy-Connection: Keep-Alive"); + if(result) + goto error; + } + + result = Curl_add_custom_headers(data, TRUE, headers); + if(result) goto error; sendtask = hyper_clientconn_send(client, req); if(!sendtask) { failf(data, "hyper_clientconn_send"); + result = CURLE_OUT_OF_MEMORY; goto error; } if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) { failf(data, "Couldn't hyper_executor_push the send"); + result = CURLE_OUT_OF_MEMORY; goto error; } @@ -869,8 +921,11 @@ static CURLcode CONNECT(struct Curl_easy *data, if(error) hypererr = hyper_task_value(task); hyper_task_free(task); - if(error) + if(error) { + /* this could probably use a better error code? */ + result = CURLE_OUT_OF_MEMORY; goto error; + } } } while(task); s->tunnel_state = TUNNEL_CONNECT; @@ -898,15 +953,23 @@ static CURLcode CONNECT(struct Curl_easy *data, h->write_waker = NULL; } } - /* FALLTHROUGH */ + break; + default: break; } + + /* If we are supposed to continue and request a new URL, which basically + * means the HTTP authentication is still going on so if the tunnel + * is complete we start over in INIT state */ + if(data->req.newurl && (TUNNEL_COMPLETE == s->tunnel_state)) { + infof(data, "CONNECT request done, loop to make another"); + connect_init(data, TRUE); /* reinit */ + } } while(data->req.newurl); result = CURLE_OK; if(s->tunnel_state == TUNNEL_COMPLETE) { - data->info.httpproxycode = data->req.httpcode; if(data->info.httpproxycode/100 != 2) { if(conn->bits.close && data->req.newurl) { conn->bits.proxy_connect_closed = TRUE; diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c index ab4d412ee3..bea964f79a 100644 --- a/libs/libcurl/src/imap.c +++ b/libs/libcurl/src/imap.c @@ -74,11 +74,11 @@ #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" -#include "strerror.h" #include "select.h" #include "multiif.h" #include "url.h" #include "strcase.h" +#include "bufref.h" #include "curl_sasl.h" #include "warnless.h" @@ -102,19 +102,19 @@ static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done); static CURLcode imap_setup_connection(struct Curl_easy *data, struct connectdata *conn); static char *imap_atom(const char *str, bool escape_only); -static CURLcode imap_sendf(struct Curl_easy *data, - struct connectdata *conn, const char *fmt, ...); +static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...); static CURLcode imap_parse_url_options(struct connectdata *conn); static CURLcode imap_parse_url_path(struct Curl_easy *data); static CURLcode imap_parse_custom_request(struct Curl_easy *data); static CURLcode imap_perform_authenticate(struct Curl_easy *data, - struct connectdata *conn, const char *mech, - const char *initresp); + const struct bufref *initresp); static CURLcode imap_continue_authenticate(struct Curl_easy *data, - struct connectdata *conn, - const char *resp); -static void imap_get_message(char *buffer, char **outptr); + const char *mech, + const struct bufref *resp); +static CURLcode imap_cancel_authenticate(struct Curl_easy *data, + const char *mech); +static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out); /* * IMAP protocol handler. @@ -181,12 +181,15 @@ const struct Curl_handler Curl_handler_imaps = { /* SASL parameters for the imap protocol */ static const struct SASLproto saslimap = { "imap", /* The service name */ - '+', /* Code received when continuation is expected */ - IMAP_RESP_OK, /* Code to receive upon authentication success */ - 0, /* Maximum initial response length (no max) */ imap_perform_authenticate, /* Send authentication command */ imap_continue_authenticate, /* Send authentication continuation */ - imap_get_message /* Get SASL response message */ + imap_cancel_authenticate, /* Send authentication cancellation */ + imap_get_message, /* Get SASL response message */ + 0, /* No maximum initial response length */ + '+', /* Code received when continuation is expected */ + IMAP_RESP_OK, /* Code to receive upon authentication success */ + SASL_AUTH_DEFAULT, /* Default mechanisms */ + SASL_FLAG_BASE64 /* Configuration flags */ }; @@ -294,6 +297,7 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn, !strcasecompare(imap->custom, "EXPUNGE") && !strcasecompare(imap->custom, "LSUB") && !strcasecompare(imap->custom, "UID") && + !strcasecompare(imap->custom, "GETQUOTAROOT") && !strcasecompare(imap->custom, "NOOP"))) return FALSE; break; @@ -353,34 +357,32 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn, * * Gets the authentication message from the response buffer. */ -static void imap_get_message(char *buffer, char **outptr) +static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out) { - size_t len = strlen(buffer); - char *message = NULL; + char *message = data->state.buffer; + size_t len = strlen(message); if(len > 2) { /* Find the start of the message */ len -= 2; - for(message = buffer + 2; *message == ' ' || *message == '\t'; - message++, len--) + for(message += 2; *message == ' ' || *message == '\t'; message++, len--) ; /* Find the end of the message */ - for(; len--;) + while(len--) if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && message[len] != '\t') break; /* Terminate the message */ - if(++len) { - message[len] = '\0'; - } + message[++len] = '\0'; + Curl_bufref_set(out, message, len, NULL); } else /* junk input => zero length output */ - message = &buffer[len]; + Curl_bufref_set(out, "", 0, NULL); - *outptr = message; + return CURLE_OK; } /*********************************************************************** @@ -438,7 +440,7 @@ static CURLcode imap_perform_capability(struct Curl_easy *data, imapc->tls_supported = FALSE; /* Clear the TLS capability */ /* Send the CAPABILITY command */ - result = imap_sendf(data, conn, "CAPABILITY"); + result = imap_sendf(data, "CAPABILITY"); if(!result) state(data, IMAP_CAPABILITY); @@ -452,11 +454,10 @@ static CURLcode imap_perform_capability(struct Curl_easy *data, * * Sends the STARTTLS command to start the upgrade to TLS. */ -static CURLcode imap_perform_starttls(struct Curl_easy *data, - struct connectdata *conn) +static CURLcode imap_perform_starttls(struct Curl_easy *data) { /* Send the STARTTLS command */ - CURLcode result = imap_sendf(data, conn, "STARTTLS"); + CURLcode result = imap_sendf(data, "STARTTLS"); if(!result) state(data, IMAP_STARTTLS); @@ -517,7 +518,7 @@ static CURLcode imap_perform_login(struct Curl_easy *data, passwd = imap_atom(conn->passwd, false); /* Send the LOGIN command */ - result = imap_sendf(data, conn, "LOGIN %s %s", user ? user : "", + result = imap_sendf(data, "LOGIN %s %s", user ? user : "", passwd ? passwd : ""); free(user); @@ -537,20 +538,19 @@ static CURLcode imap_perform_login(struct Curl_easy *data, * SASL authentication mechanism. */ static CURLcode imap_perform_authenticate(struct Curl_easy *data, - struct connectdata *conn, const char *mech, - const char *initresp) + const struct bufref *initresp) { CURLcode result = CURLE_OK; - (void)data; + const char *ir = (const char *) Curl_bufref_ptr(initresp); - if(initresp) { + if(ir) { /* Send the AUTHENTICATE command with the initial response */ - result = imap_sendf(data, conn, "AUTHENTICATE %s %s", mech, initresp); + result = imap_sendf(data, "AUTHENTICATE %s %s", mech, ir); } else { /* Send the AUTHENTICATE command */ - result = imap_sendf(data, conn, "AUTHENTICATE %s", mech); + result = imap_sendf(data, "AUTHENTICATE %s", mech); } return result; @@ -560,15 +560,34 @@ static CURLcode imap_perform_authenticate(struct Curl_easy *data, * * imap_continue_authenticate() * - * Sends SASL continuation data or cancellation. + * Sends SASL continuation data. */ static CURLcode imap_continue_authenticate(struct Curl_easy *data, - struct connectdata *conn, - const char *resp) + const char *mech, + const struct bufref *resp) { - struct imap_conn *imapc = &conn->proto.imapc; + struct imap_conn *imapc = &data->conn->proto.imapc; + + (void)mech; + + return Curl_pp_sendf(data, &imapc->pp, + "%s", (const char *) Curl_bufref_ptr(resp)); +} + +/*********************************************************************** + * + * imap_cancel_authenticate() + * + * Sends SASL cancellation. + */ +static CURLcode imap_cancel_authenticate(struct Curl_easy *data, + const char *mech) +{ + struct imap_conn *imapc = &data->conn->proto.imapc; + + (void)mech; - return Curl_pp_sendf(data, &imapc->pp, "%s", resp); + return Curl_pp_sendf(data, &imapc->pp, "*"); } /*********************************************************************** @@ -595,8 +614,7 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data, } /* Calculate the SASL login details */ - result = Curl_sasl_start(&imapc->sasl, data, conn, - imapc->ir_supported, &progress); + result = Curl_sasl_start(&imapc->sasl, data, imapc->ir_supported, &progress); if(!result) { if(progress == SASL_INPROGRESS) @@ -623,12 +641,11 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data, static CURLcode imap_perform_list(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct connectdata *conn = data->conn; struct IMAP *imap = data->req.p.imap; if(imap->custom) /* Send the custom request */ - result = imap_sendf(data, conn, "%s%s", imap->custom, + result = imap_sendf(data, "%s%s", imap->custom, imap->custom_params ? imap->custom_params : ""); else { /* Make sure the mailbox is in the correct atom format if necessary */ @@ -638,7 +655,7 @@ static CURLcode imap_perform_list(struct Curl_easy *data) return CURLE_OUT_OF_MEMORY; /* Send the LIST command */ - result = imap_sendf(data, conn, "LIST \"%s\" *", mailbox); + result = imap_sendf(data, "LIST \"%s\" *", mailbox); free(mailbox); } @@ -679,7 +696,7 @@ static CURLcode imap_perform_select(struct Curl_easy *data) return CURLE_OUT_OF_MEMORY; /* Send the SELECT command */ - result = imap_sendf(data, conn, "SELECT %s", mailbox); + result = imap_sendf(data, "SELECT %s", mailbox); free(mailbox); @@ -695,8 +712,7 @@ static CURLcode imap_perform_select(struct Curl_easy *data) * * Sends a FETCH command to initiate the download of a message. */ -static CURLcode imap_perform_fetch(struct Curl_easy *data, - struct connectdata *conn) +static CURLcode imap_perform_fetch(struct Curl_easy *data) { CURLcode result = CURLE_OK; struct IMAP *imap = data->req.p.imap; @@ -705,21 +721,21 @@ static CURLcode imap_perform_fetch(struct Curl_easy *data, /* Send the FETCH command */ if(imap->partial) - result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]<%s>", + result = imap_sendf(data, "UID FETCH %s BODY[%s]<%s>", imap->uid, imap->section ? imap->section : "", imap->partial); else - result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]", + result = imap_sendf(data, "UID FETCH %s BODY[%s]", imap->uid, imap->section ? imap->section : ""); } else if(imap->mindex) { /* Send the FETCH command */ if(imap->partial) - result = imap_sendf(data, conn, "FETCH %s BODY[%s]<%s>", + result = imap_sendf(data, "FETCH %s BODY[%s]<%s>", imap->mindex, imap->section ? imap->section : "", imap->partial); else - result = imap_sendf(data, conn, "FETCH %s BODY[%s]", + result = imap_sendf(data, "FETCH %s BODY[%s]", imap->mindex, imap->section ? imap->section : ""); } else { @@ -741,7 +757,6 @@ static CURLcode imap_perform_fetch(struct Curl_easy *data, static CURLcode imap_perform_append(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct connectdata *conn = data->conn; struct IMAP *imap = data->req.p.imap; char *mailbox; @@ -792,7 +807,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data) return CURLE_OUT_OF_MEMORY; /* Send the APPEND command */ - result = imap_sendf(data, conn, + result = imap_sendf(data, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}", mailbox, data->state.infilesize); @@ -810,8 +825,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data) * * Sends a SEARCH command. */ -static CURLcode imap_perform_search(struct Curl_easy *data, - struct connectdata *conn) +static CURLcode imap_perform_search(struct Curl_easy *data) { CURLcode result = CURLE_OK; struct IMAP *imap = data->req.p.imap; @@ -823,7 +837,7 @@ static CURLcode imap_perform_search(struct Curl_easy *data, } /* Send the SEARCH command */ - result = imap_sendf(data, conn, "SEARCH %s", imap->query); + result = imap_sendf(data, "SEARCH %s", imap->query); if(!result) state(data, IMAP_SEARCH); @@ -837,11 +851,10 @@ static CURLcode imap_perform_search(struct Curl_easy *data, * * Performs the logout action prior to sclose() being called. */ -static CURLcode imap_perform_logout(struct Curl_easy *data, - struct connectdata *conn) +static CURLcode imap_perform_logout(struct Curl_easy *data) { /* Send the LOGOUT command */ - CURLcode result = imap_sendf(data, conn, "LOGOUT"); + CURLcode result = imap_sendf(data, "LOGOUT"); if(!result) state(data, IMAP_LOGOUT); @@ -935,22 +948,18 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data, line += wordlen; } } - else if(imapcode == IMAP_RESP_OK) { - if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { - /* We don't have a SSL/TLS connection yet, but SSL is requested */ - if(imapc->tls_supported) - /* Switch to TLS connection now */ - result = imap_perform_starttls(data, conn); - else if(data->set.use_ssl == CURLUSESSL_TRY) - /* Fallback and carry on with authentication */ - result = imap_perform_authentication(data, conn); - else { - failf(data, "STARTTLS not supported."); - result = CURLE_USE_SSL_FAILED; - } + else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* PREAUTH is not compatible with STARTTLS. */ + if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) { + /* Switch to TLS connection now */ + result = imap_perform_starttls(data); } - else + else if(data->set.use_ssl <= CURLUSESSL_TRY) result = imap_perform_authentication(data, conn); + else { + failf(data, "STARTTLS not available."); + result = CURLE_USE_SSL_FAILED; + } } else result = imap_perform_authentication(data, conn); @@ -968,6 +977,10 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data, (void)instate; /* no use for this yet */ + /* Pipelining in response is forbidden. */ + if(data->conn->proto.imapc.pp.cache_size) + return CURLE_WEIRD_SERVER_REPLY; + if(imapcode != IMAP_RESP_OK) { if(data->set.use_ssl != CURLUSESSL_TRY) { failf(data, "STARTTLS denied"); @@ -994,7 +1007,7 @@ static CURLcode imap_state_auth_resp(struct Curl_easy *data, (void)instate; /* no use for this yet */ - result = Curl_sasl_continue(&imapc->sasl, data, conn, imapcode, &progress); + result = Curl_sasl_continue(&imapc->sasl, data, imapcode, &progress); if(!result) switch(progress) { case SASL_DONE: @@ -1095,9 +1108,9 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode, if(imap->custom) result = imap_perform_list(data); else if(imap->query) - result = imap_perform_search(data, conn); + result = imap_perform_search(data); else - result = imap_perform_fetch(data, conn); + result = imap_perform_fetch(data); } } else { @@ -1442,7 +1455,7 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done) /* Set the default preferred authentication type and mechanism */ imapc->preftype = IMAP_TYPE_ANY; - Curl_sasl_init(&imapc->sasl, &saslimap); + Curl_sasl_init(&imapc->sasl, data, &saslimap); Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD); /* Initialise the pingpong layer */ @@ -1569,10 +1582,10 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected, result = imap_perform_list(data); else if(!imap->custom && selected && (imap->uid || imap->mindex)) /* FETCH from the same mailbox */ - result = imap_perform_fetch(data, conn); + result = imap_perform_fetch(data); else if(!imap->custom && selected && imap->query) /* SEARCH the current mailbox */ - result = imap_perform_search(data, conn); + result = imap_perform_search(data); else if(imap->mailbox && !selected && (imap->custom || imap->uid || imap->mindex || imap->query)) /* SELECT the mailbox */ @@ -1644,7 +1657,7 @@ static CURLcode imap_disconnect(struct Curl_easy *data, /* The IMAP session may or may not have been allocated/setup at this point! */ if(!dead_connection && conn->bits.protoconnstart) { - if(!imap_perform_logout(data, conn)) + if(!imap_perform_logout(data)) (void)imap_block_statemach(data, conn, TRUE); /* ignore errors */ } @@ -1748,17 +1761,16 @@ static CURLcode imap_setup_connection(struct Curl_easy *data, * * Designed to never block. */ -static CURLcode imap_sendf(struct Curl_easy *data, - struct connectdata *conn, const char *fmt, ...) +static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...) { CURLcode result = CURLE_OK; - struct imap_conn *imapc = &conn->proto.imapc; + struct imap_conn *imapc = &data->conn->proto.imapc; DEBUGASSERT(fmt); /* Calculate the tag based on the connection ID and command ID */ msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d", - 'A' + curlx_sltosi(conn->connection_id % 26), + 'A' + curlx_sltosi(data->conn->connection_id % 26), (++imapc->cmdid)%1000); /* start with a blank buffer */ @@ -1912,8 +1924,6 @@ static CURLcode imap_parse_url_options(struct connectdata *conn) struct imap_conn *imapc = &conn->proto.imapc; const char *ptr = conn->options; - imapc->sasl.resetprefs = TRUE; - while(!result && ptr && *ptr) { const char *key = ptr; const char *value; diff --git a/libs/libcurl/src/krb5.c b/libs/libcurl/src/krb5.c index e25f526564..afe425b046 100644 --- a/libs/libcurl/src/krb5.c +++ b/libs/libcurl/src/krb5.c @@ -374,7 +374,7 @@ static void krb5_end(void *app_data) } } -static struct Curl_sec_client_mech Curl_krb5_client_mech = { +static const struct Curl_sec_client_mech Curl_krb5_client_mech = { "GSSAPI", sizeof(gss_ctx_id_t), krb5_init, @@ -684,7 +684,7 @@ int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, (void) data; if(!conn->mech) - /* not inititalized, return error */ + /* not initialized, return error */ return -1; DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); @@ -768,7 +768,7 @@ static int sec_set_protection_level(struct Curl_easy *data) } } - /* Now try to negiociate the protection level. */ + /* Now try to negotiate the protection level. */ code = ftp_send_command(data, "PROT %c", level_to_char(level)); if(code < 0) diff --git a/libs/libcurl/src/libcurl.plist b/libs/libcurl/src/libcurl.plist index 575e28da76..daf485621b 100644 --- a/libs/libcurl/src/libcurl.plist +++ b/libs/libcurl/src/libcurl.plist @@ -15,7 +15,7 @@ <string>se.curl.libcurl</string> <key>CFBundleVersion</key> - <string>7.78.0</string> + <string>7.80.0</string> <key>CFBundleName</key> <string>libcurl</string> @@ -27,9 +27,9 @@ <string>????</string> <key>CFBundleShortVersionString</key> - <string>libcurl 7.78.0</string> + <string>libcurl 7.80.0</string> <key>CFBundleGetInfoString</key> - <string>libcurl.plist 7.78.0</string> + <string>libcurl.plist 7.80.0</string> </dict> </plist> diff --git a/libs/libcurl/src/libcurl.rc b/libs/libcurl/src/libcurl.rc index 3f7ae16034..fde6c8cae1 100644 --- a/libs/libcurl/src/libcurl.rc +++ b/libs/libcurl/src/libcurl.rc @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -51,7 +51,7 @@ BEGIN VALUE "OriginalFilename", "libcurl.dll\0" VALUE "ProductName", "The curl library\0" VALUE "ProductVersion", LIBCURL_VERSION "\0" - VALUE "LegalCopyright", "\xa9 " LIBCURL_COPYRIGHT "\0" /* a9: Copyright symbol */ + VALUE "LegalCopyright", "Copyright (C) " LIBCURL_COPYRIGHT "\0" VALUE "License", "https://curl.se/docs/copyright.html\0" END END diff --git a/libs/libcurl/src/llist.c b/libs/libcurl/src/llist.c index e0ec7393d2..e78da7da82 100644 --- a/libs/libcurl/src/llist.c +++ b/libs/libcurl/src/llist.c @@ -106,9 +106,7 @@ Curl_llist_remove(struct Curl_llist *list, struct Curl_llist_element *e, e->next->prev = NULL; } else { - if(!e->prev) - list->head = e->next; - else + if(e->prev) e->prev->next = e->next; if(!e->next) diff --git a/libs/libcurl/src/md4.c b/libs/libcurl/src/md4.c index c651ddf669..d90e45475c 100644 --- a/libs/libcurl/src/md4.c +++ b/libs/libcurl/src/md4.c @@ -27,6 +27,7 @@ #include "curl_md4.h" #include "warnless.h" + #ifdef USE_OPENSSL #include <openssl/opensslconf.h> #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) @@ -35,9 +36,20 @@ #endif #endif /* USE_OPENSSL */ +#ifdef USE_WOLFSSL +#include <wolfssl/options.h> +#ifdef NO_MD4 +#define OPENSSL_NO_MD4 +#endif +#endif + #ifdef USE_MBEDTLS -#include <mbedtls/config.h> #include <mbedtls/version.h> +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 +#include <mbedtls/mbedtls_config.h> +#else +#include <mbedtls/config.h> +#endif #if(MBEDTLS_VERSION_NUMBER >= 0x02070000) #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS @@ -70,8 +82,9 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx) md4_digest(ctx, MD4_DIGEST_SIZE, result); } -#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4) -/* When OpenSSL is available we use the MD4-functions from OpenSSL */ +#elif (defined(USE_OPENSSL) || defined(USE_WOLFSSL)) && \ + !defined(OPENSSL_NO_MD4) +/* When OpenSSL or wolfSSL is available, we use their MD4 functions. */ #include <openssl/md4.h> #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ diff --git a/libs/libcurl/src/md5.c b/libs/libcurl/src/md5.c index 7a24fd8cf4..810c5fba8e 100644 --- a/libs/libcurl/src/md5.c +++ b/libs/libcurl/src/md5.c @@ -33,11 +33,26 @@ #ifdef USE_MBEDTLS #include <mbedtls/version.h> -#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) +#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \ + (MBEDTLS_VERSION_NUMBER < 0x03000000) #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS #endif #endif /* USE_MBEDTLS */ +#if defined(USE_OPENSSL) && !defined(USE_AMISSL) + #include <openssl/opensslconf.h> + #if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_DEPRECATED_3_0) + #define USE_OPENSSL_MD5 + #endif +#endif + +#ifdef USE_WOLFSSL + #include <wolfssl/options.h> + #ifndef NO_MD5 + #define USE_WOLFSSL_MD5 + #endif +#endif + #if defined(USE_GNUTLS) #include <nettle/md5.h> @@ -64,8 +79,9 @@ static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) md5_digest(ctx, 16, digest); } -#elif defined(USE_OPENSSL) && !defined(USE_AMISSL) -/* When OpenSSL is available we use the MD5-function from OpenSSL */ +#elif defined(USE_OPENSSL_MD5) || defined(USE_WOLFSSL_MD5) + +/* When OpenSSL or wolfSSL is available, we use their MD5 functions. */ #include <openssl/md5.h> #include "curl_memory.h" /* The last #include file should be: */ @@ -85,7 +101,7 @@ typedef mbedtls_md5_context MD5_CTX; static void MD5_Init(MD5_CTX *ctx) { #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_md5_starts(ctx); + (void) mbedtls_md5_starts(ctx); #else (void) mbedtls_md5_starts_ret(ctx); #endif @@ -96,7 +112,7 @@ static void MD5_Update(MD5_CTX *ctx, unsigned int length) { #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_md5_update(ctx, data, length); + (void) mbedtls_md5_update(ctx, data, length); #else (void) mbedtls_md5_update_ret(ctx, data, length); #endif @@ -105,7 +121,7 @@ static void MD5_Update(MD5_CTX *ctx, static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) { #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_md5_finish(ctx, digest); + (void) mbedtls_md5_finish(ctx, digest); #else (void) mbedtls_md5_finish_ret(ctx, digest); #endif diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c index 0bf1b46a4c..f40cc1a618 100644 --- a/libs/libcurl/src/mime.c +++ b/libs/libcurl/src/mime.c @@ -462,11 +462,13 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, /* Buffered data size can only be 0, 1 or 2. */ ptr[2] = ptr[3] = '='; i = 0; - switch(st->bufend - st->bufbeg) { - case 2: - i = (st->buf[st->bufbeg + 1] & 0xFF) << 8; - /* FALLTHROUGH */ - case 1: + + /* If there is buffered data */ + if(st->bufend != st->bufbeg) { + + if(st->bufend - st->bufbeg == 2) + i = (st->buf[st->bufbeg + 1] & 0xFF) << 8; + i |= (st->buf[st->bufbeg] & 0xFF) << 16; ptr[0] = base64[(i >> 18) & 0x3F]; ptr[1] = base64[(i >> 12) & 0x3F]; @@ -476,7 +478,6 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, } cursize += 4; st->pos += 4; - break; } } } @@ -1954,7 +1955,8 @@ void Curl_mime_unpause(curl_mimepart *part) } -#else /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */ +#else /* !CURL_DISABLE_HTTP && !CURL_DISABLE_MIME || + !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */ /* Mime not compiled in: define stubs for externally-referenced functions. */ curl_mime *curl_mime_init(CURL *easy) diff --git a/libs/libcurl/src/mk-ca-bundle.pl b/libs/libcurl/src/mk-ca-bundle.pl index 910fedb0ca..e5a7420c0e 100644 --- a/libs/libcurl/src/mk-ca-bundle.pl +++ b/libs/libcurl/src/mk-ca-bundle.pl @@ -436,9 +436,25 @@ while (<TXT>) { last if (/\*\*\*\*\* END LICENSE BLOCK \*\*\*\*\*/); } } - elsif(/^# (Issuer|Serial Number|Subject|Not Valid Before|Not Valid After |Fingerprint \(MD5\)|Fingerprint \(SHA1\)):/) { +# Not Valid After : Thu Sep 30 14:01:15 2021 + elsif(/^# Not Valid After : (.*)/) { + my $stamp = $1; + use Time::Piece; + my $t = Time::Piece->strptime + ($stamp, "%a %b %d %H:%M:%S %Y"); + my $delta = ($t->epoch - time()); # negative means no longer valid + if($delta < 0) { + $skipnum++; + report "Skipping: $caname is not valid anymore" if ($opt_v); + $valid = 0; + } + else { + $valid = 1; + } + next; + } + elsif(/^# (Issuer|Serial Number|Subject|Not Valid Before|Fingerprint \(MD5\)|Fingerprint \(SHA1\)):/) { push @precert, $_; - $valid = 1; next; } elsif(/^#|^\s*$/) { diff --git a/libs/libcurl/src/mqtt.c b/libs/libcurl/src/mqtt.c index f077e6c3dc..fcd40b41e6 100644 --- a/libs/libcurl/src/mqtt.c +++ b/libs/libcurl/src/mqtt.c @@ -128,6 +128,10 @@ static CURLcode mqtt_send(struct Curl_easy *data, mq->sendleftovers = sendleftovers; mq->nsend = nsend; } + else { + mq->sendleftovers = NULL; + mq->nsend = 0; + } return result; } diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c index 82d538d009..f307d63b93 100644 --- a/libs/libcurl/src/multi.c +++ b/libs/libcurl/src/multi.c @@ -1052,11 +1052,17 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { curl_socket_t s = CURL_SOCKET_BAD; - if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) { + if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK(sockbunch[i])) { + if(!FDSET_SOCK(sockbunch[i])) + /* pretend it doesn't exist */ + continue; FD_SET(sockbunch[i], read_fd_set); s = sockbunch[i]; } - if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) { + if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK(sockbunch[i])) { + if(!FDSET_SOCK(sockbunch[i])) + /* pretend it doesn't exist */ + continue; FD_SET(sockbunch[i], write_fd_set); s = sockbunch[i]; } @@ -1100,6 +1106,9 @@ static CURLMcode multi_wait(struct Curl_multi *multi, WSANETWORKEVENTS wsa_events; DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT); #endif +#ifndef ENABLE_WAKEUP + (void)use_wakeup; +#endif if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -2019,6 +2028,28 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, break; case MSTATE_DO: + if(data->set.fprereq) { + int prereq_rc; + + /* call the prerequest callback function */ + Curl_set_in_callback(data, true); + prereq_rc = data->set.fprereq(data->set.prereq_userp, + data->info.conn_primary_ip, + data->info.conn_local_ip, + data->info.conn_primary_port, + data->info.conn_local_port); + Curl_set_in_callback(data, false); + if(prereq_rc != CURL_PREREQFUNC_OK) { + failf(data, "operation aborted by pre-request callback"); + /* failure in pre-request callback - don't do any other processing */ + result = CURLE_ABORTED_BY_CALLBACK; + Curl_posttransfer(data); + multi_done(data, result, FALSE); + stream_error = TRUE; + break; + } + } + if(data->set.connect_only) { /* keep connection open for application to use the socket */ connkeep(data->conn, "CONNECT_ONLY"); @@ -2602,7 +2633,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) multi->magic = 0; /* not good anymore */ - /* Firsrt remove all remaining easy handles */ + /* First remove all remaining easy handles */ data = multi->easyp; while(data) { nextdata = data->next; @@ -3171,7 +3202,7 @@ CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles) static CURLMcode multi_timeout(struct Curl_multi *multi, long *timeout_ms) { - static struct curltime tv_zero = {0, 0}; + static const struct curltime tv_zero = {0, 0}; if(multi->timetree) { /* we have a tree of expire times */ diff --git a/libs/libcurl/src/non-ascii.c b/libs/libcurl/src/non-ascii.c index 932cf89eef..3b77ae98d5 100644 --- a/libs/libcurl/src/non-ascii.c +++ b/libs/libcurl/src/non-ascii.c @@ -31,6 +31,7 @@ #include "sendf.h" #include "urldata.h" #include "multiif.h" +#include "strerror.h" #include "curl_memory.h" /* The last #include file should be: */ @@ -104,6 +105,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, iconv_t *cd = &tmpcd; char *input_ptr, *output_ptr; size_t in_bytes, out_bytes, rc; + char ebuffer[STRERROR_LEN]; /* open an iconv conversion descriptor if necessary */ if(data) @@ -116,7 +118,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", CURL_ICONV_CODESET_OF_NETWORK, CURL_ICONV_CODESET_OF_HOST, - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } } @@ -130,7 +132,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "The Curl_convert_to_network iconv call failed with errno %i: %s", - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } #else @@ -170,6 +172,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data, iconv_t *cd = &tmpcd; char *input_ptr, *output_ptr; size_t in_bytes, out_bytes, rc; + char ebuffer[STRERROR_LEN]; /* open an iconv conversion descriptor if necessary */ if(data) @@ -182,7 +185,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data, "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", CURL_ICONV_CODESET_OF_HOST, CURL_ICONV_CODESET_OF_NETWORK, - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } } @@ -196,7 +199,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data, if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "Curl_convert_from_network iconv call failed with errno %i: %s", - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } #else @@ -237,6 +240,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data, char *input_ptr; char *output_ptr; size_t in_bytes, out_bytes, rc; + char ebuffer[STRERROR_LEN]; /* open an iconv conversion descriptor if necessary */ if(data) @@ -249,7 +253,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data, "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", CURL_ICONV_CODESET_OF_HOST, CURL_ICONV_CODESET_FOR_UTF8, - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } } @@ -263,7 +267,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data, if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "The Curl_convert_from_utf8 iconv call failed with errno %i: %s", - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } if(output_ptr < input_ptr) { diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c index 5fdd6f3e05..d4ca67877d 100644 --- a/libs/libcurl/src/pop3.c +++ b/libs/libcurl/src/pop3.c @@ -75,10 +75,10 @@ #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" -#include "strerror.h" #include "select.h" #include "multiif.h" #include "url.h" +#include "bufref.h" #include "curl_sasl.h" #include "curl_md5.h" #include "warnless.h" @@ -104,12 +104,12 @@ static CURLcode pop3_setup_connection(struct Curl_easy *data, static CURLcode pop3_parse_url_options(struct connectdata *conn); static CURLcode pop3_parse_url_path(struct Curl_easy *data); static CURLcode pop3_parse_custom_request(struct Curl_easy *data); -static CURLcode pop3_perform_auth(struct Curl_easy *data, - struct connectdata *conn, const char *mech, - const char *initresp); -static CURLcode pop3_continue_auth(struct Curl_easy *data, - struct connectdata *conn, const char *resp); -static void pop3_get_message(char *buffer, char **outptr); +static CURLcode pop3_perform_auth(struct Curl_easy *data, const char *mech, + const struct bufref *initresp); +static CURLcode pop3_continue_auth(struct Curl_easy *data, const char *mech, + const struct bufref *resp); +static CURLcode pop3_cancel_auth(struct Curl_easy *data, const char *mech); +static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out); /* * POP3 protocol handler. @@ -171,13 +171,16 @@ const struct Curl_handler Curl_handler_pop3s = { /* SASL parameters for the pop3 protocol */ static const struct SASLproto saslpop3 = { - "pop", /* The service name */ - '*', /* Code received when continuation is expected */ - '+', /* Code to receive upon authentication success */ - 255 - 8, /* Maximum initial response length (no max) */ - pop3_perform_auth, /* Send authentication command */ - pop3_continue_auth, /* Send authentication continuation */ - pop3_get_message /* Get SASL response message */ + "pop", /* The service name */ + pop3_perform_auth, /* Send authentication command */ + pop3_continue_auth, /* Send authentication continuation */ + pop3_cancel_auth, /* Send authentication cancellation */ + pop3_get_message, /* Get SASL response message */ + 255 - 8, /* Max line len - strlen("AUTH ") - 1 space - crlf */ + '*', /* Code received when continuation is expected */ + '+', /* Code to receive upon authentication success */ + SASL_AUTH_DEFAULT, /* Default mechanisms */ + SASL_FLAG_BASE64 /* Configuration flags */ }; #ifdef USE_SSL @@ -251,34 +254,32 @@ static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn, * * Gets the authentication message from the response buffer. */ -static void pop3_get_message(char *buffer, char **outptr) +static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out) { - size_t len = strlen(buffer); - char *message = NULL; + char *message = data->state.buffer; + size_t len = strlen(message); if(len > 2) { /* Find the start of the message */ len -= 2; - for(message = buffer + 2; *message == ' ' || *message == '\t'; - message++, len--) + for(message += 2; *message == ' ' || *message == '\t'; message++, len--) ; /* Find the end of the message */ - for(; len--;) + while(len--) if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && message[len] != '\t') break; /* Terminate the message */ - if(++len) { - message[len] = '\0'; - } + message[++len] = '\0'; + Curl_bufref_set(out, message, len, NULL); } else /* junk input => zero length output */ - message = &buffer[len]; + Curl_bufref_set(out, "", 0, NULL); - *outptr = message; + return CURLE_OK; } /*********************************************************************** @@ -475,16 +476,16 @@ static CURLcode pop3_perform_apop(struct Curl_easy *data, * authentication mechanism. */ static CURLcode pop3_perform_auth(struct Curl_easy *data, - struct connectdata *conn, const char *mech, - const char *initresp) + const struct bufref *initresp) { CURLcode result = CURLE_OK; - struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pop3_conn *pop3c = &data->conn->proto.pop3c; + const char *ir = (const char *) Curl_bufref_ptr(initresp); - if(initresp) { /* AUTH <mech> ...<crlf> */ + if(ir) { /* AUTH <mech> ...<crlf> */ /* Send the AUTH command with the initial response */ - result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s %s", mech, initresp); + result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s %s", mech, ir); } else { /* Send the AUTH command */ @@ -498,15 +499,33 @@ static CURLcode pop3_perform_auth(struct Curl_easy *data, * * pop3_continue_auth() * - * Sends SASL continuation data or cancellation. + * Sends SASL continuation data. */ static CURLcode pop3_continue_auth(struct Curl_easy *data, - struct connectdata *conn, - const char *resp) + const char *mech, + const struct bufref *resp) { - struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pop3_conn *pop3c = &data->conn->proto.pop3c; + + (void)mech; + + return Curl_pp_sendf(data, &pop3c->pp, + "%s", (const char *) Curl_bufref_ptr(resp)); +} + +/*********************************************************************** + * + * pop3_cancel_auth() + * + * Sends SASL cancellation. + */ +static CURLcode pop3_cancel_auth(struct Curl_easy *data, const char *mech) +{ + struct pop3_conn *pop3c = &data->conn->proto.pop3c; - return Curl_pp_sendf(data, &pop3c->pp, "%s", resp); + (void)mech; + + return Curl_pp_sendf(data, &pop3c->pp, "*"); } /*********************************************************************** @@ -533,7 +552,7 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data, if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) { /* Calculate the SASL login details */ - result = Curl_sasl_start(&pop3c->sasl, data, conn, FALSE, &progress); + result = Curl_sasl_start(&pop3c->sasl, data, FALSE, &progress); if(!result) if(progress == SASL_INPROGRESS) @@ -741,28 +760,23 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code, } } } - else if(pop3code == '+') { - if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { - /* We don't have a SSL/TLS connection yet, but SSL is requested */ - if(pop3c->tls_supported) - /* Switch to TLS connection now */ - result = pop3_perform_starttls(data, conn); - else if(data->set.use_ssl == CURLUSESSL_TRY) - /* Fallback and carry on with authentication */ - result = pop3_perform_authentication(data, conn); - else { - failf(data, "STLS not supported."); - result = CURLE_USE_SSL_FAILED; - } - } - else - result = pop3_perform_authentication(data, conn); - } else { /* Clear text is supported when CAPA isn't recognised */ - pop3c->authtypes |= POP3_TYPE_CLEARTEXT; + if(pop3code != '+') + pop3c->authtypes |= POP3_TYPE_CLEARTEXT; - result = pop3_perform_authentication(data, conn); + if(!data->set.use_ssl || conn->ssl[FIRSTSOCKET].use) + result = pop3_perform_authentication(data, conn); + else if(pop3code == '+' && pop3c->tls_supported) + /* Switch to TLS connection now */ + result = pop3_perform_starttls(data, conn); + else if(data->set.use_ssl <= CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = pop3_perform_authentication(data, conn); + else { + failf(data, "STLS not supported."); + result = CURLE_USE_SSL_FAILED; + } } return result; @@ -777,6 +791,10 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data, CURLcode result = CURLE_OK; (void)instate; /* no use for this yet */ + /* Pipelining in response is forbidden. */ + if(data->conn->proto.pop3c.pp.cache_size) + return CURLE_WEIRD_SERVER_REPLY; + if(pop3code != '+') { if(data->set.use_ssl != CURLUSESSL_TRY) { failf(data, "STARTTLS denied"); @@ -803,7 +821,7 @@ static CURLcode pop3_state_auth_resp(struct Curl_easy *data, (void)instate; /* no use for this yet */ - result = Curl_sasl_continue(&pop3c->sasl, data, conn, pop3code, &progress); + result = Curl_sasl_continue(&pop3c->sasl, data, pop3code, &progress); if(!result) switch(progress) { case SASL_DONE: @@ -1013,7 +1031,9 @@ static CURLcode pop3_statemachine(struct Curl_easy *data, break; case POP3_QUIT: - /* fallthrough, just stop! */ + state(data, POP3_STOP); + break; + default: /* internal error */ state(data, POP3_STOP); @@ -1104,7 +1124,7 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done) /* Set the default preferred authentication type and mechanism */ pop3c->preftype = POP3_TYPE_ANY; - Curl_sasl_init(&pop3c->sasl, &saslpop3); + Curl_sasl_init(&pop3c->sasl, data, &saslpop3); /* Initialise the pingpong layer */ Curl_pp_setup(pp); @@ -1345,8 +1365,6 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn) struct pop3_conn *pop3c = &conn->proto.pop3c; const char *ptr = conn->options; - pop3c->sasl.resetprefs = TRUE; - while(!result && ptr && *ptr) { const char *key = ptr; const char *value; diff --git a/libs/libcurl/src/progress.c b/libs/libcurl/src/progress.c index 4bcd615eba..f5ef6bd526 100644 --- a/libs/libcurl/src/progress.c +++ b/libs/libcurl/src/progress.c @@ -377,7 +377,12 @@ static curl_off_t trspeed(curl_off_t size, /* number of bytes */ { if(us < 1) return size * 1000000; - return (curl_off_t)((long double)size/us * 1000000); + else if(size < CURL_OFF_T_MAX/1000000) + return (size * 1000000) / us; + else if(us >= 1000000) + return size / (us / 1000000); + else + return CURL_OFF_T_MAX; } /* returns TRUE if it's time to show the progress meter */ diff --git a/libs/libcurl/src/select.c b/libs/libcurl/src/select.c index 52dca5a2c0..70d7ee5c26 100644 --- a/libs/libcurl/src/select.c +++ b/libs/libcurl/src/select.c @@ -64,7 +64,7 @@ * Waiting indefinitely with this function is not allowed, a * zero or negative timeout value will return immediately. * Timeout resolution, accuracy, as well as maximum supported - * value is system dependent, neither factor is a citical issue + * value is system dependent, neither factor is a critical issue * for the intended use of this function in the library. * * Return values: diff --git a/libs/libcurl/src/select.h b/libs/libcurl/src/select.h index 19da1e774b..59a571dbbd 100644 --- a/libs/libcurl/src/select.h +++ b/libs/libcurl/src/select.h @@ -97,8 +97,10 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, #if defined(TPF) #define VALID_SOCK(x) 1 #define VERIFY_SOCK(x) Curl_nop_stmt +#define FDSET_SOCK(x) 1 #elif defined(USE_WINSOCK) #define VALID_SOCK(s) ((s) < INVALID_SOCKET) +#define FDSET_SOCK(x) 1 #define VERIFY_SOCK(x) do { \ if(!VALID_SOCK(x)) { \ SET_SOCKERRNO(WSAEINVAL); \ @@ -106,17 +108,17 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, } \ } while(0) #else -#ifdef HAVE_POLL_FINE -#define VALID_SOCK(s) ((s) >= 0) /* FD_SETSIZE is irrelevant for poll */ -#else -#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) -#endif -#define VERIFY_SOCK(x) do { \ - if(!VALID_SOCK(x)) { \ - SET_SOCKERRNO(EINVAL); \ - return -1; \ - } \ -} while(0) +#define VALID_SOCK(s) ((s) >= 0) + +/* If the socket is small enough to get set or read from an fdset */ +#define FDSET_SOCK(s) ((s) < FD_SETSIZE) + +#define VERIFY_SOCK(x) do { \ + if(!VALID_SOCK(x) || !FDSET_SOCK(x)) { \ + SET_SOCKERRNO(EINVAL); \ + return -1; \ + } \ + } while(0) #endif #endif /* HEADER_CURL_SELECT_H */ diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c index 14ca84bfe5..bcfa27a501 100644 --- a/libs/libcurl/src/sendf.c +++ b/libs/libcurl/src/sendf.c @@ -608,7 +608,7 @@ static CURLcode chop_write(struct Curl_easy *data, /* Curl_client_write() sends data to the write callback(s) The bit pattern defines to what "streams" to write to. Body and/or header. - The defines are in sendf.h of course. "len" is not allowed to be 0. + The defines are in sendf.h of course. If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the local character encoding. This is a problem and should be changed in @@ -621,8 +621,10 @@ CURLcode Curl_client_write(struct Curl_easy *data, { struct connectdata *conn = data->conn; - DEBUGASSERT(len); - DEBUGASSERT(type <= 3); + DEBUGASSERT(!(type & ~CLIENTWRITE_BOTH)); + + if(!len) + return CURLE_OK; /* FTP data may need conversion. */ if((type & CLIENTWRITE_BODY) && diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c index 076fe5f59c..56d9c49926 100644 --- a/libs/libcurl/src/setopt.c +++ b/libs/libcurl/src/setopt.c @@ -2370,12 +2370,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_IGNORE_CONTENT_LENGTH: -#ifndef USE_HYPER data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE; break; -#else - return CURLE_NOT_BUILT_IN; -#endif case CURLOPT_CONNECT_ONLY: /* @@ -2481,6 +2477,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) va_arg(param, char *)); break; + case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256: + /* + * Option to allow for the SHA256 of the host public key to be checked + * for validation purposes. + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256], + va_arg(param, char *)); + break; + case CURLOPT_SSH_KNOWNHOSTS: /* * Store the file name to read known hosts from. @@ -2511,8 +2516,12 @@ 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; break; +#else + return CURLE_NOT_BUILT_IN; /* hyper doesn't support */ +#endif case CURLOPT_HTTP_CONTENT_DECODING: /* @@ -2933,6 +2942,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) return CURLE_BAD_FUNCTION_ARGUMENT; data->set.maxage_conn = arg; break; + case CURLOPT_MAXLIFETIME_CONN: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.maxlifetime_conn = arg; + break; case CURLOPT_TRAILERFUNCTION: #ifndef CURL_DISABLE_HTTP data->set.trailer_callback = va_arg(param, curl_trailer_callback); @@ -3008,6 +3023,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) return result; break; #endif + case CURLOPT_PREREQFUNCTION: + data->set.fprereq = va_arg(param, curl_prereq_callback); + break; + case CURLOPT_PREREQDATA: + data->set.prereq_userp = va_arg(param, void *); + break; default: /* unknown tag and its companion, just ignore: */ result = CURLE_UNKNOWN_OPTION; diff --git a/libs/libcurl/src/setup-win32.h b/libs/libcurl/src/setup-win32.h index c35dec88cb..fa8742f3b1 100644 --- a/libs/libcurl/src/setup-win32.h +++ b/libs/libcurl/src/setup-win32.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -25,11 +25,11 @@ /* * Include header files for windows builds before redefining anything. * Use this preprocessor block only to include or exclude windows.h, - * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs + * winsock2.h or ws2tcpip.h. Any other windows thing belongs * to any other further and independent block. Under Cygwin things work * just as under linux (e.g. <sys/socket.h>) and the winsock headers should * never be included when __CYGWIN__ is defined. configure script takes - * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H, + * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK2_H, * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined. */ @@ -47,10 +47,6 @@ # ifdef HAVE_WS2TCPIP_H # include <ws2tcpip.h> # endif -# else -# ifdef HAVE_WINSOCK_H -# include <winsock.h> -# endif # endif # include <tchar.h> # ifdef UNICODE @@ -67,10 +63,6 @@ #ifdef HAVE_WINSOCK2_H # define USE_WINSOCK 2 -#else -# ifdef HAVE_WINSOCK_H -# error "WinSock version 1 is no longer supported, version 2 is required!" -# endif #endif /* diff --git a/libs/libcurl/src/sha256.c b/libs/libcurl/src/sha256.c index c34f97e8f6..1391412ce5 100644 --- a/libs/libcurl/src/sha256.c +++ b/libs/libcurl/src/sha256.c @@ -29,11 +29,18 @@ #include "curl_sha256.h" #include "curl_hmac.h" +#ifdef USE_WOLFSSL +#include <wolfssl/options.h> +#ifndef NO_SHA256 +#define USE_OPENSSL_SHA256 +#endif +#endif + #if defined(USE_OPENSSL) #include <openssl/opensslv.h> -#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) +#if (OPENSSL_VERSION_NUMBER >= 0x0090700fL) #define USE_OPENSSL_SHA256 #endif @@ -42,8 +49,9 @@ #ifdef USE_MBEDTLS #include <mbedtls/version.h> -#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) - #define HAS_RESULT_CODE_BASED_FUNCTIONS +#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \ + (MBEDTLS_VERSION_NUMBER < 0x03000000) + #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS #endif #endif /* USE_MBEDTLS */ @@ -62,7 +70,36 @@ #if defined(USE_OPENSSL_SHA256) /* When OpenSSL is available we use the SHA256-function from OpenSSL */ -#include <openssl/sha.h> +#include <openssl/evp.h> + +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +struct sha256_ctx { + EVP_MD_CTX *openssl_ctx; +}; +typedef struct sha256_ctx my_sha256_ctx; + +static void my_sha256_init(my_sha256_ctx *ctx) +{ + ctx->openssl_ctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(ctx->openssl_ctx, EVP_sha256(), NULL); +} + +static void my_sha256_update(my_sha256_ctx *ctx, + const unsigned char *data, + unsigned int length) +{ + EVP_DigestUpdate(ctx->openssl_ctx, data, length); +} + +static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx) +{ + EVP_DigestFinal_ex(ctx->openssl_ctx, digest, NULL); + EVP_MD_CTX_destroy(ctx->openssl_ctx); +} #elif defined(USE_GNUTLS) @@ -73,21 +110,21 @@ /* The last #include file should be: */ #include "memdebug.h" -typedef struct sha256_ctx SHA256_CTX; +typedef struct sha256_ctx my_sha256_ctx; -static void SHA256_Init(SHA256_CTX *ctx) +static void my_sha256_init(my_sha256_ctx *ctx) { sha256_init(ctx); } -static void SHA256_Update(SHA256_CTX *ctx, - const unsigned char *data, - unsigned int length) +static void my_sha256_update(my_sha256_ctx *ctx, + const unsigned char *data, + unsigned int length) { sha256_update(ctx, length, data); } -static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) +static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx) { sha256_digest(ctx, SHA256_DIGEST_SIZE, digest); } @@ -101,32 +138,32 @@ static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) /* The last #include file should be: */ #include "memdebug.h" -typedef mbedtls_sha256_context SHA256_CTX; +typedef mbedtls_sha256_context my_sha256_ctx; -static void SHA256_Init(SHA256_CTX *ctx) +static void my_sha256_init(my_sha256_ctx *ctx) { -#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_sha256_starts(ctx, 0); +#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) + (void) mbedtls_sha256_starts(ctx, 0); #else (void) mbedtls_sha256_starts_ret(ctx, 0); #endif } -static void SHA256_Update(SHA256_CTX *ctx, - const unsigned char *data, - unsigned int length) +static void my_sha256_update(my_sha256_ctx *ctx, + const unsigned char *data, + unsigned int length) { -#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_sha256_update(ctx, data, length); +#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) + (void) mbedtls_sha256_update(ctx, data, length); #else (void) mbedtls_sha256_update_ret(ctx, data, length); #endif } -static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) +static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx) { -#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_sha256_finish(ctx, digest); +#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) + (void) mbedtls_sha256_finish(ctx, digest); #else (void) mbedtls_sha256_finish_ret(ctx, digest); #endif @@ -144,21 +181,21 @@ static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) /* The last #include file should be: */ #include "memdebug.h" -typedef CC_SHA256_CTX SHA256_CTX; +typedef CC_SHA256_CTX my_sha256_ctx; -static void SHA256_Init(SHA256_CTX *ctx) +static void my_sha256_init(my_sha256_ctx *ctx) { (void) CC_SHA256_Init(ctx); } -static void SHA256_Update(SHA256_CTX *ctx, - const unsigned char *data, - unsigned int length) +static void my_sha256_update(my_sha256_ctx *ctx, + const unsigned char *data, + unsigned int length) { (void) CC_SHA256_Update(ctx, data, length); } -static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) +static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx) { (void) CC_SHA256_Final(digest, ctx); } @@ -171,13 +208,13 @@ struct sha256_ctx { HCRYPTPROV hCryptProv; HCRYPTHASH hHash; }; -typedef struct sha256_ctx SHA256_CTX; +typedef struct sha256_ctx my_sha256_ctx; #if !defined(CALG_SHA_256) #define CALG_SHA_256 0x0000800c #endif -static void SHA256_Init(SHA256_CTX *ctx) +static void my_sha256_init(my_sha256_ctx *ctx) { if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { @@ -185,14 +222,14 @@ static void SHA256_Init(SHA256_CTX *ctx) } } -static void SHA256_Update(SHA256_CTX *ctx, - const unsigned char *data, - unsigned int length) +static void my_sha256_update(my_sha256_ctx *ctx, + const unsigned char *data, + unsigned int length) { CryptHashData(ctx->hHash, (unsigned char *) data, length, 0); } -static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) +static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx) { unsigned long length = 0; @@ -261,7 +298,7 @@ struct sha256_state { unsigned long state[8], curlen; unsigned char buf[64]; }; -typedef struct sha256_state SHA256_CTX; +typedef struct sha256_state my_sha256_ctx; /* The K array */ static const unsigned long K[64] = { @@ -338,7 +375,7 @@ static int sha256_compress(struct sha256_state *md, } /* Initialize the hash state */ -static void SHA256_Init(struct sha256_state *md) +static void my_sha256_init(struct sha256_state *md) { md->curlen = 0; md->length = 0; @@ -359,9 +396,9 @@ static void SHA256_Init(struct sha256_state *md) @param inlen The length of the data (octets) @return CRYPT_OK if successful */ -static int SHA256_Update(struct sha256_state *md, - const unsigned char *in, - unsigned long inlen) +static int my_sha256_update(struct sha256_state *md, + const unsigned char *in, + unsigned long inlen) { unsigned long n; @@ -400,8 +437,8 @@ static int SHA256_Update(struct sha256_state *md, @param out [out] The destination of the hash (32 bytes) @return CRYPT_OK if successful */ -static int SHA256_Final(unsigned char *out, - struct sha256_state *md) +static int my_sha256_final(unsigned char *out, + struct sha256_state *md) { int i; @@ -458,24 +495,24 @@ static int SHA256_Final(unsigned char *out, void Curl_sha256it(unsigned char *output, const unsigned char *input, const size_t length) { - SHA256_CTX ctx; + my_sha256_ctx ctx; - SHA256_Init(&ctx); - SHA256_Update(&ctx, input, curlx_uztoui(length)); - SHA256_Final(output, &ctx); + my_sha256_init(&ctx); + my_sha256_update(&ctx, input, curlx_uztoui(length)); + my_sha256_final(output, &ctx); } const struct HMAC_params Curl_HMAC_SHA256[] = { { /* Hash initialization function. */ - CURLX_FUNCTION_CAST(HMAC_hinit_func, SHA256_Init), + CURLX_FUNCTION_CAST(HMAC_hinit_func, my_sha256_init), /* Hash update function. */ - CURLX_FUNCTION_CAST(HMAC_hupdate_func, SHA256_Update), + CURLX_FUNCTION_CAST(HMAC_hupdate_func, my_sha256_update), /* Hash computation end function. */ - CURLX_FUNCTION_CAST(HMAC_hfinal_func, SHA256_Final), + CURLX_FUNCTION_CAST(HMAC_hfinal_func, my_sha256_final), /* Size of hash context structure. */ - sizeof(SHA256_CTX), + sizeof(my_sha256_ctx), /* Maximum key length. */ 64, /* Result size. */ diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c index 1a3da15599..8e0b046096 100644 --- a/libs/libcurl/src/smtp.c +++ b/libs/libcurl/src/smtp.c @@ -78,11 +78,11 @@ #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" -#include "strerror.h" #include "select.h" #include "multiif.h" #include "url.h" #include "curl_gethostname.h" +#include "bufref.h" #include "curl_sasl.h" #include "warnless.h" /* The last 3 #include files should be in this order */ @@ -109,12 +109,12 @@ static CURLcode smtp_parse_url_path(struct Curl_easy *data); static CURLcode smtp_parse_custom_request(struct Curl_easy *data); static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma, char **address, struct hostname *host); -static CURLcode smtp_perform_auth(struct Curl_easy *data, - struct connectdata *conn, const char *mech, - const char *initresp); -static CURLcode smtp_continue_auth(struct Curl_easy *data, - struct connectdata *conn, const char *resp); -static void smtp_get_message(char *buffer, char **outptr); +static CURLcode smtp_perform_auth(struct Curl_easy *data, const char *mech, + const struct bufref *initresp); +static CURLcode smtp_continue_auth(struct Curl_easy *data, const char *mech, + const struct bufref *resp); +static CURLcode smtp_cancel_auth(struct Curl_easy *data, const char *mech); +static CURLcode smtp_get_message(struct Curl_easy *data, struct bufref *out); /* * SMTP protocol handler. @@ -176,13 +176,16 @@ const struct Curl_handler Curl_handler_smtps = { /* SASL parameters for the smtp protocol */ static const struct SASLproto saslsmtp = { - "smtp", /* The service name */ - 334, /* Code received when continuation is expected */ - 235, /* Code to receive upon authentication success */ - 512 - 8, /* Maximum initial response length (no max) */ - smtp_perform_auth, /* Send authentication command */ - smtp_continue_auth, /* Send authentication continuation */ - smtp_get_message /* Get SASL response message */ + "smtp", /* The service name */ + smtp_perform_auth, /* Send authentication command */ + smtp_continue_auth, /* Send authentication continuation */ + smtp_cancel_auth, /* Cancel authentication */ + smtp_get_message, /* Get SASL response message */ + 512 - 8, /* Max line len - strlen("AUTH ") - 1 space - crlf */ + 334, /* Code received when continuation is expected */ + 235, /* Code to receive upon authentication success */ + SASL_AUTH_DEFAULT, /* Default mechanisms */ + SASL_FLAG_BASE64 /* Configuration flags */ }; #ifdef USE_SSL @@ -249,34 +252,32 @@ static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn, * * Gets the authentication message from the response buffer. */ -static void smtp_get_message(char *buffer, char **outptr) +static CURLcode smtp_get_message(struct Curl_easy *data, struct bufref *out) { - size_t len = strlen(buffer); - char *message = NULL; + char *message = data->state.buffer; + size_t len = strlen(message); if(len > 4) { /* Find the start of the message */ len -= 4; - for(message = buffer + 4; *message == ' ' || *message == '\t'; - message++, len--) + for(message += 4; *message == ' ' || *message == '\t'; message++, len--) ; /* Find the end of the message */ - for(; len--;) + while(len--) if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && message[len] != '\t') break; /* Terminate the message */ - if(++len) { - message[len] = '\0'; - } + message[++len] = '\0'; + Curl_bufref_set(out, message, len, NULL); } else /* junk input => zero length output */ - message = &buffer[len]; + Curl_bufref_set(out, "", 0, NULL); - *outptr = message; + return CURLE_OK; } /*********************************************************************** @@ -422,16 +423,16 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data) * authentication mechanism. */ static CURLcode smtp_perform_auth(struct Curl_easy *data, - struct connectdata *conn, const char *mech, - const char *initresp) + const struct bufref *initresp) { CURLcode result = CURLE_OK; - struct smtp_conn *smtpc = &conn->proto.smtpc; + struct smtp_conn *smtpc = &data->conn->proto.smtpc; + const char *ir = (const char *) Curl_bufref_ptr(initresp); - if(initresp) { /* AUTH <mech> ...<crlf> */ + if(ir) { /* AUTH <mech> ...<crlf> */ /* Send the AUTH command with the initial response */ - result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s %s", mech, initresp); + result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s %s", mech, ir); } else { /* Send the AUTH command */ @@ -445,14 +446,33 @@ static CURLcode smtp_perform_auth(struct Curl_easy *data, * * smtp_continue_auth() * - * Sends SASL continuation data or cancellation. + * Sends SASL continuation data. */ static CURLcode smtp_continue_auth(struct Curl_easy *data, - struct connectdata *conn, const char *resp) + const char *mech, + const struct bufref *resp) { - struct smtp_conn *smtpc = &conn->proto.smtpc; + struct smtp_conn *smtpc = &data->conn->proto.smtpc; + + (void)mech; - return Curl_pp_sendf(data, &smtpc->pp, "%s", resp); + return Curl_pp_sendf(data, &smtpc->pp, + "%s", (const char *) Curl_bufref_ptr(resp)); +} + +/*********************************************************************** + * + * smtp_cancel_auth() + * + * Sends SASL cancellation. + */ +static CURLcode smtp_cancel_auth(struct Curl_easy *data, const char *mech) +{ + struct smtp_conn *smtpc = &data->conn->proto.smtpc; + + (void)mech; + + return Curl_pp_sendf(data, &smtpc->pp, "*"); } /*********************************************************************** @@ -470,7 +490,7 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data) saslprogress progress; /* Check we have enough data to authenticate with, and the - server supports authentiation, and end the connect phase if not */ + server supports authentication, and end the connect phase if not */ if(!smtpc->auth_supported || !Curl_sasl_can_authenticate(&smtpc->sasl, conn)) { state(data, SMTP_STOP); @@ -478,7 +498,7 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data) } /* Calculate the SASL login details */ - result = Curl_sasl_start(&smtpc->sasl, data, conn, FALSE, &progress); + result = Curl_sasl_start(&smtpc->sasl, data, FALSE, &progress); if(!result) { if(progress == SASL_INPROGRESS) @@ -507,7 +527,7 @@ static CURLcode smtp_perform_command(struct Curl_easy *data) if(smtp->rcpt) { /* We notify the server we are sending UTF-8 data if a) it supports the - SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in + SMTPUTF8 extension and b) The mailbox contains UTF-8 characters, in either the local address or host name parts. This is regardless of whether the host name is encoded using IDN ACE */ bool utf8 = FALSE; @@ -580,7 +600,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data) struct connectdata *conn = data->conn; /* We notify the server we are sending UTF-8 data if a) it supports the - SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in + SMTPUTF8 extension and b) The mailbox contains UTF-8 characters, in either the local address or host name parts. This is regardless of whether the host name is encoded using IDN ACE */ bool utf8 = FALSE; @@ -835,6 +855,10 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data, CURLcode result = CURLE_OK; (void)instate; /* no use for this yet */ + /* Pipelining in response is forbidden. */ + if(data->conn->proto.smtpc.pp.cache_size) + return CURLE_WEIRD_SERVER_REPLY; + if(smtpcode != 220) { if(data->set.use_ssl != CURLUSESSL_TRY) { failf(data, "STARTTLS denied, code %d", smtpcode); @@ -982,7 +1006,7 @@ static CURLcode smtp_state_auth_resp(struct Curl_easy *data, (void)instate; /* no use for this yet */ - result = Curl_sasl_continue(&smtpc->sasl, data, conn, smtpcode, &progress); + result = Curl_sasl_continue(&smtpc->sasl, data, smtpcode, &progress); if(!result) switch(progress) { case SASL_DONE: @@ -1330,7 +1354,7 @@ static CURLcode smtp_connect(struct Curl_easy *data, bool *done) PINGPONG_SETUP(pp, smtp_statemachine, smtp_endofresp); /* Initialize the SASL storage */ - Curl_sasl_init(&smtpc->sasl, &saslsmtp); + Curl_sasl_init(&smtpc->sasl, data, &saslsmtp); /* Initialise the pingpong layer */ Curl_pp_setup(pp); @@ -1652,8 +1676,6 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn) struct smtp_conn *smtpc = &conn->proto.smtpc; const char *ptr = conn->options; - smtpc->sasl.resetprefs = TRUE; - while(!result && ptr && *ptr) { const char *key = ptr; const char *value; diff --git a/libs/libcurl/src/socks.c b/libs/libcurl/src/socks.c index 91c4223a5f..db4c80834e 100644 --- a/libs/libcurl/src/socks.c +++ b/libs/libcurl/src/socks.c @@ -99,24 +99,24 @@ int Curl_blockread_all(struct Curl_easy *data, /* transfer */ } #endif -#ifndef DEBUGBUILD -#define sxstate(x,y) socksstate(x,y) -#else +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) +#define DEBUG_AND_VERBOSE #define sxstate(x,y) socksstate(x,y, __LINE__) +#else +#define sxstate(x,y) socksstate(x,y) #endif - /* always use this function to change state, to make debugging easier */ static void socksstate(struct Curl_easy *data, enum connect_t state -#ifdef DEBUGBUILD +#ifdef DEBUG_AND_VERBOSE , int lineno #endif ) { struct connectdata *conn = data->conn; enum connect_t oldstate = conn->cnnct.state; -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) +#ifdef DEBUG_AND_VERBOSE /* synced with the state list in urldata.h */ static const char * const statename[] = { "INIT", @@ -146,7 +146,7 @@ static void socksstate(struct Curl_easy *data, conn->cnnct.state = state; -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) +#ifdef DEBUG_AND_VERBOSE infof(data, "SXSTATE: %s => %s conn %p; line %d", statename[oldstate], statename[conn->cnnct.state], conn, diff --git a/libs/libcurl/src/socks_gssapi.c b/libs/libcurl/src/socks_gssapi.c index 34bfa37d7f..8ef2f8f374 100644 --- a/libs/libcurl/src/socks_gssapi.c +++ b/libs/libcurl/src/socks_gssapi.c @@ -257,7 +257,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - if(socksreq[1] != 1) { /* status / messgae type */ + if(socksreq[1] != 1) { /* status / message type */ failf(data, "Invalid GSS-API authentication response type (%d %d).", socksreq[0], socksreq[1]); gss_release_name(&gss_status, &server); @@ -452,7 +452,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - if(socksreq[1] != 2) { /* status / messgae type */ + if(socksreq[1] != 2) { /* status / message type */ failf(data, "Invalid GSS-API encryption response type (%d %d).", socksreq[0], socksreq[1]); gss_delete_sec_context(&gss_status, &gss_context, NULL); diff --git a/libs/libcurl/src/socks_sspi.c b/libs/libcurl/src/socks_sspi.c index cb225b9b5a..ffc8703468 100644 --- a/libs/libcurl/src/socks_sspi.c +++ b/libs/libcurl/src/socks_sspi.c @@ -277,7 +277,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - if(socksreq[1] != 1) { /* status / messgae type */ + if(socksreq[1] != 1) { /* status / message type */ failf(data, "Invalid SSPI authentication response type (%u %u).", (unsigned int)socksreq[0], (unsigned int)socksreq[1]); free(service_name); diff --git a/libs/libcurl/src/splay.c b/libs/libcurl/src/splay.c index a94e2c85e9..1c1dafb920 100644 --- a/libs/libcurl/src/splay.c +++ b/libs/libcurl/src/splay.c @@ -154,7 +154,7 @@ struct Curl_tree *Curl_splaygetbest(struct curltime i, struct Curl_tree *t, struct Curl_tree **removed) { - static struct curltime tv_zero = {0, 0}; + static const struct curltime tv_zero = {0, 0}; struct Curl_tree *x; if(!t) { diff --git a/libs/libcurl/src/strdup.c b/libs/libcurl/src/strdup.c index 9af47ea473..85cf33b3ed 100644 --- a/libs/libcurl/src/strdup.c +++ b/libs/libcurl/src/strdup.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,6 +24,10 @@ #include <curl/curl.h> +#ifdef WIN32 +#include <wchar.h> +#endif + #include "strdup.h" #include "curl_memory.h" @@ -50,6 +54,28 @@ char *curlx_strdup(const char *str) } #endif +#ifdef WIN32 +/*************************************************************************** + * + * Curl_wcsdup(source) + * + * Copies the 'source' wchar string to a newly allocated buffer (that is + * returned). + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +wchar_t *Curl_wcsdup(const wchar_t *src) +{ + size_t length = wcslen(src); + + if(length > (SIZE_T_MAX / sizeof(wchar_t)) - 1) + return (wchar_t *)NULL; /* integer overflow */ + + return (wchar_t *)Curl_memdup(src, (length + 1) * sizeof(wchar_t)); +} +#endif + /*************************************************************************** * * Curl_memdup(source, length) diff --git a/libs/libcurl/src/strdup.h b/libs/libcurl/src/strdup.h index 0936956f89..8c8a6f20e1 100644 --- a/libs/libcurl/src/strdup.h +++ b/libs/libcurl/src/strdup.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,6 +26,9 @@ #ifndef HAVE_STRDUP extern char *curlx_strdup(const char *str); #endif +#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); diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c index a1ec539b90..31eb2bf790 100644 --- a/libs/libcurl/src/strerror.c +++ b/libs/libcurl/src/strerror.c @@ -453,6 +453,78 @@ curl_share_strerror(CURLSHcode error) #endif } +const char * +curl_url_strerror(CURLUcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(error) { + case CURLUE_OK: + return "No error"; + + case CURLUE_BAD_HANDLE: + return "An invalid CURLU pointer was passed as argument"; + + case CURLUE_BAD_PARTPOINTER: + return "An invalid 'part' argument was passed as argument"; + + case CURLUE_MALFORMED_INPUT: + return "A malformed input was passed to a URL API function"; + + case CURLUE_BAD_PORT_NUMBER: + return "The port number was not a decimal number between 0 and 65535"; + + case CURLUE_UNSUPPORTED_SCHEME: + return "This libcurl build doesn't support the given URL scheme"; + + case CURLUE_URLDECODE: + return "URL decode error, most likely because of rubbish in the input"; + + case CURLUE_OUT_OF_MEMORY: + return "A memory function failed"; + + case CURLUE_USER_NOT_ALLOWED: + return "Credentials was passed in the URL when prohibited"; + + case CURLUE_UNKNOWN_PART: + return "An unknown part ID was passed to a URL API function"; + + case CURLUE_NO_SCHEME: + return "There is no scheme part in the URL"; + + case CURLUE_NO_USER: + return "There is no user part in the URL"; + + case CURLUE_NO_PASSWORD: + return "There is no password part in the URL"; + + case CURLUE_NO_OPTIONS: + return "There is no options part in the URL"; + + case CURLUE_NO_HOST: + return "There is no host part in the URL"; + + case CURLUE_NO_PORT: + return "There is no port part in the URL"; + + case CURLUE_NO_QUERY: + return "There is no query part in the URL"; + + case CURLUE_NO_FRAGMENT: + return "There is no fragment part in the URL"; + + case CURLUE_LAST: + break; + } + + return "CURLUcode unknown"; +#else + if(error == CURLUE_OK) + return "No error"; + else + return "Error"; +#endif +} + #ifdef USE_WINSOCK /* This is a helper function for Curl_strerror that converts Winsock error * codes (WSAGetLastError) to error messages. @@ -735,7 +807,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) #if defined(WIN32) /* 'sys_nerr' is the maximum errno number, it is not widely portable */ if(err >= 0 && err < sys_nerr) - strncpy(buf, strerror(err), max); + strncpy(buf, sys_errlist[err], max); else #endif { @@ -786,6 +858,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) } #else { + /* !checksrc! disable STRERROR 1 */ const char *msg = strerror(err); if(msg) strncpy(buf, msg, max); diff --git a/libs/libcurl/src/system_win32.c b/libs/libcurl/src/system_win32.c index 2939fd0d74..d4e194831f 100644 --- a/libs/libcurl/src/system_win32.c +++ b/libs/libcurl/src/system_win32.c @@ -102,6 +102,8 @@ CURLcode Curl_win32_init(long flags) Curl_if_nametoindex = pIfNameToIndex; } + /* curlx_verify_windows_version must be called during init at least once + because it has its own initialization routine. */ if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT, VERSION_GREATER_THAN_EQUAL)) { Curl_isVistaOrGreater = TRUE; diff --git a/libs/libcurl/src/tftp.c b/libs/libcurl/src/tftp.c index 8aeb14a4f5..7e5246f010 100644 --- a/libs/libcurl/src/tftp.c +++ b/libs/libcurl/src/tftp.c @@ -720,7 +720,7 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event) /* There's a bug in tftpd-hpa that causes it to send us an ack for * 65535 when the block number wraps to 0. So when we're expecting * 0, also accept 65535. See - * http://syslinux.zytor.com/archives/2010-September/015253.html + * https://www.syslinux.org/archives/2010-September/015612.html * */ !(state->block == 0 && rblock == 65535)) { /* This isn't the expected block. Log it and up the retry counter */ @@ -1304,9 +1304,9 @@ static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done) /********************************************************** * - * tftp_peform + * tftp_perform * - * Entry point for transfer from tftp_do, sarts state mach + * Entry point for transfer from tftp_do, starts state mach * **********************************************************/ static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done) diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c index 3e650b5b9e..05fec7998c 100644 --- a/libs/libcurl/src/transfer.c +++ b/libs/libcurl/src/transfer.c @@ -1503,7 +1503,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) } #endif Curl_http2_init_state(&data->state); - Curl_hsts_loadcb(data, data->hsts); + result = Curl_hsts_loadcb(data, data->hsts); } /* diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c index 8a2845dddd..93b4397bff 100644 --- a/libs/libcurl/src/url.c +++ b/libs/libcurl/src/url.c @@ -622,6 +622,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT; set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */ set->maxage_conn = 118; + set->maxlifetime_conn = 0; set->http09_allowed = FALSE; set->httpwant = #ifdef USE_NGHTTP2 @@ -962,21 +963,36 @@ socks_proxy_info_matches(const struct proxy_info *data, #define socks_proxy_info_matches(x,y) FALSE #endif -/* A connection has to have been idle for a shorter time than 'maxage_conn' to - be subject for reuse. The success rate is just too low after this. */ +/* A connection has to have been idle for a shorter time than 'maxage_conn' + (the success rate is just too low after this), or created less than + 'maxlifetime_conn' ago, to be subject for reuse. */ static bool conn_maxage(struct Curl_easy *data, struct connectdata *conn, struct curltime now) { - timediff_t idletime = Curl_timediff(now, conn->lastused); + timediff_t idletime, lifetime; + + idletime = Curl_timediff(now, conn->lastused); idletime /= 1000; /* integer seconds is fine */ if(idletime > data->set.maxage_conn) { - infof(data, "Too old connection (%ld seconds), disconnect it", + infof(data, "Too old connection (%ld seconds idle), disconnect it", idletime); return TRUE; } + + lifetime = Curl_timediff(now, conn->created); + lifetime /= 1000; /* integer seconds is fine */ + + if(data->set.maxlifetime_conn && lifetime > data->set.maxlifetime_conn) { + infof(data, + "Too old connection (%ld seconds since creation), disconnect it", + lifetime); + return TRUE; + } + + return FALSE; } @@ -1892,9 +1908,13 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, #else scopeidx = if_nametoindex(zoneid); #endif - if(!scopeidx) + if(!scopeidx) { +#ifndef CURL_DISABLE_VERBOSE_STRINGS + char buffer[STRERROR_LEN]; infof(data, "Invalid zoneid: %s; %s", zoneid, - strerror(errno)); + Curl_strerror(errno, buffer, sizeof(buffer))); +#endif + } else conn->scope_id = scopeidx; } @@ -1950,7 +1970,8 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, CURLU_DISALLOW_USER : 0) | (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)); if(uc) { - DEBUGF(infof(data, "curl_url_set rejected %s", data->state.url)); + DEBUGF(infof(data, "curl_url_set rejected %s: %s", data->state.url, + curl_url_strerror(uc))); return Curl_uc_to_curlcode(uc); } @@ -2376,6 +2397,11 @@ static CURLcode parse_proxy(struct Curl_easy *data, CURLcode result = CURLE_OK; char *scheme = NULL; + if(!uhp) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } + /* When parsing the proxy, allowing non-supported schemes since we have these made up ones for proxies. Guess scheme for URLs without it. */ uc = curl_url_set(uhp, CURLUPART_URL, proxy, @@ -2759,7 +2785,7 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len, size_t plen; size_t olen; - /* the input length check is because this is called directcly from setopt + /* the input length check is because this is called directly from setopt and isn't going through the regular string length check */ size_t llen = strlen(login); if(llen > CURL_MAX_INPUT_LENGTH) @@ -4089,7 +4115,7 @@ CURLcode Curl_connect(struct Curl_easy *data, /* init the single-transfer specific data */ Curl_free_request_state(data); memset(&data->req, 0, sizeof(struct SingleRequest)); - data->req.maxdownload = -1; + data->req.size = data->req.maxdownload = -1; /* call the stuff that needs to be called */ result = create_conn(data, &conn, asyncp); diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c index 905c499d99..6d116b61bf 100644 --- a/libs/libcurl/src/urlapi.c +++ b/libs/libcurl/src/urlapi.c @@ -157,23 +157,23 @@ static size_t strlen_url(const char *url, bool relative) continue; } - switch(*ptr) { - case '?': - left = FALSE; - /* FALLTHROUGH */ - default: - if(urlchar_needs_escaping(*ptr)) - newlen += 2; - newlen++; - break; - case ' ': + if(*ptr == ' ') { if(left) newlen += 3; else newlen++; - break; + continue; } + + if (*ptr == '?') + left = FALSE; + + if(urlchar_needs_escaping(*ptr)) + newlen += 2; + + newlen++; } + return newlen; } @@ -202,19 +202,7 @@ static void strcpy_url(char *output, const char *url, bool relative) continue; } - switch(*iptr) { - case '?': - left = FALSE; - /* FALLTHROUGH */ - default: - if(urlchar_needs_escaping(*iptr)) { - msnprintf(optr, 4, "%%%02x", *iptr); - optr += 3; - } - else - *optr++=*iptr; - break; - case ' ': + if(*iptr == ' ') { if(left) { *optr++='%'; /* add a '%' */ *optr++='2'; /* add a '2' */ @@ -222,8 +210,18 @@ static void strcpy_url(char *output, const char *url, bool relative) } else *optr++='+'; /* add a '+' here */ - break; + continue; + } + + if(*iptr == '?') + left = FALSE; + + if(urlchar_needs_escaping(*iptr)) { + msnprintf(optr, 4, "%%%02x", *iptr); + optr += 3; } + else + *optr++ = *iptr; } *optr = 0; /* null-terminate output buffer */ @@ -656,7 +654,7 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname) } else { /* letters from the second string is not ok */ - len = strcspn(hostname, " "); + len = strcspn(hostname, " \r\n"); if(hlen != len) /* hostname with bad content */ return CURLUE_MALFORMED_INPUT; @@ -756,10 +754,35 @@ static bool ipv4_normalize(const char *hostname, char *outp, size_t olen) return TRUE; } +/* return strdup'ed version in 'outp', possibly percent decoded */ +static CURLUcode decode_host(char *hostname, char **outp) +{ + char *per = NULL; + if(hostname[0] != '[') + /* only decode if not an ipv6 numerical */ + per = strchr(hostname, '%'); + if(!per) { + *outp = strdup(hostname); + if(!*outp) + return CURLUE_OUT_OF_MEMORY; + } + else { + /* might be encoded */ + size_t dlen; + CURLcode result = Curl_urldecode(NULL, hostname, 0, + outp, &dlen, REJECT_CTRL); + if(result) + return CURLUE_MALFORMED_INPUT; + } + + return CURLUE_OK; +} + static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) { char *path; bool path_alloced = FALSE; + bool uncpath = FALSE; char *hostname; char *query = NULL; char *fragment = NULL; @@ -770,8 +793,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) size_t schemelen = 0; size_t urllen; - if(!url) - return CURLUE_MALFORMED_INPUT; + DEBUGASSERT(url); /************************************************************* * Parse the URL. @@ -799,7 +821,6 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) /* path has been allocated large enough to hold this */ strcpy(path, &url[5]); - hostname = NULL; /* no host for file: URLs */ u->scheme = strdup("file"); if(!u->scheme) return CURLUE_OUT_OF_MEMORY; @@ -821,10 +842,13 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) * * o the hostname matches "localhost" (case-insensitively), or * - * o the hostname is a FQDN that resolves to this machine. + * o the hostname is a FQDN that resolves to this machine, or + * + * o it is an UNC String transformed to an URI (Windows only, RFC 8089 + * Appendix E.3). * * For brevity, we only consider URLs with empty, "localhost", or - * "127.0.0.1" hostnames as local. + * "127.0.0.1" hostnames as local, otherwise as an UNC String. * * Additionally, there is an exception for URLs with a Windows drive * letter in the authority (which was accidentally omitted from RFC 8089 @@ -833,18 +857,43 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) if(ptr[0] != '/' && !STARTS_WITH_URL_DRIVE_PREFIX(ptr)) { /* the URL includes a host name, it must match "localhost" or "127.0.0.1" to be valid */ - if(!checkprefix("localhost/", ptr) && - !checkprefix("127.0.0.1/", ptr)) { + if(checkprefix("localhost/", ptr) || + checkprefix("127.0.0.1/", ptr)) { + ptr += 9; /* now points to the slash after the host */ + } + else { +#if defined(WIN32) + size_t len; + + /* the host name, NetBIOS computer name, can not contain disallowed + chars, and the delimiting slash character must be appended to the + host name */ + path = strpbrk(ptr, "/\\:*?\"<>|"); + if(!path || *path != '/') + return CURLUE_MALFORMED_INPUT; + + len = path - ptr; + if(len) { + memcpy(hostname, ptr, len); + hostname[len] = 0; + uncpath = TRUE; + } + + ptr -= 2; /* now points to the // before the host in UNC */ +#else /* Invalid file://hostname/, expected localhost or 127.0.0.1 or none */ return CURLUE_MALFORMED_INPUT; +#endif } - ptr += 9; /* now points to the slash after the host */ } path = ptr; } + if(!uncpath) + hostname = NULL; /* no host for file: URLs by default */ + #if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__) /* Don't allow Windows drive letters when not in Windows. * This catches both "file:/c:" and "file:c:" */ @@ -1004,20 +1053,22 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) if(0 == strlen(hostname) && (flags & CURLU_NO_AUTHORITY)) { /* Skip hostname check, it's allowed to be empty. */ + u->host = strdup(""); } else { - result = hostname_check(u, hostname); - if(result) - return result; + if(ipv4_normalize(hostname, normalized_ipv4, sizeof(normalized_ipv4))) + u->host = strdup(normalized_ipv4); + else { + result = decode_host(hostname, &u->host); + if(result) + return result; + result = hostname_check(u, u->host); + if(result) + return result; + } } - - if(ipv4_normalize(hostname, normalized_ipv4, sizeof(normalized_ipv4))) - u->host = strdup(normalized_ipv4); - else - u->host = strdup(hostname); if(!u->host) return CURLUE_OUT_OF_MEMORY; - if((flags & CURLU_GUESS_SCHEME) && !schemep) { /* legacy curl-style guess based on host name */ if(checkprefix("ftp.", hostname)) @@ -1112,6 +1163,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, CURLUcode ifmissing = CURLUE_UNKNOWN_PART; char portbuf[7]; bool urldecode = (flags & CURLU_URLDECODE)?1:0; + bool urlencode = (flags & CURLU_URLENCODE)?1:0; bool plusdecode = FALSE; (void)flags; if(!u) @@ -1229,16 +1281,54 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, if(h && !(h->flags & PROTOPT_URLOPTIONS)) options = NULL; - if((u->host[0] == '[') && u->zoneid) { - /* make it '[ host %25 zoneid ]' */ - size_t hostlen = strlen(u->host); - size_t alen = hostlen + 3 + strlen(u->zoneid) + 1; - allochost = malloc(alen); + if(u->host[0] == '[') { + if(u->zoneid) { + /* make it '[ host %25 zoneid ]' */ + size_t hostlen = strlen(u->host); + size_t alen = hostlen + 3 + strlen(u->zoneid) + 1; + allochost = malloc(alen); + if(!allochost) + return CURLUE_OUT_OF_MEMORY; + memcpy(allochost, u->host, hostlen - 1); + msnprintf(&allochost[hostlen - 1], alen - hostlen + 1, + "%%25%s]", u->zoneid); + } + } + else if(urlencode) { + allochost = curl_easy_escape(NULL, u->host, 0); if(!allochost) return CURLUE_OUT_OF_MEMORY; - memcpy(allochost, u->host, hostlen - 1); - msnprintf(&allochost[hostlen - 1], alen - hostlen + 1, - "%%25%s]", u->zoneid); + } + else { + /* only encode '%' in output host name */ + char *host = u->host; + size_t pcount = 0; + /* first, count number of percents present in the name */ + while(*host) { + if(*host == '%') + pcount++; + host++; + } + /* if there were percents, encode the host name */ + if(pcount) { + size_t hostlen = strlen(u->host); + size_t alen = hostlen + 2 * pcount + 1; + char *o = allochost = malloc(alen); + if(!allochost) + return CURLUE_OUT_OF_MEMORY; + + host = u->host; + while(*host) { + if(*host == '%') { + memcpy(o, "%25", 3); + o += 3; + host++; + continue; + } + *o++ = *host++; + } + *o = '\0'; + } } url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", @@ -1380,10 +1470,15 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, case CURLUPART_OPTIONS: storep = &u->options; break; - case CURLUPART_HOST: + case CURLUPART_HOST: { + size_t len = strcspn(part, " \r\n"); + if(strlen(part) != len) + /* hostname with bad content */ + return CURLUE_MALFORMED_INPUT; storep = &u->host; Curl_safefree(u->zoneid); break; + } case CURLUPART_ZONEID: storep = &u->zoneid; break; diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h index 1d99112088..22068882f0 100644 --- a/libs/libcurl/src/urldata.h +++ b/libs/libcurl/src/urldata.h @@ -330,7 +330,7 @@ struct digestdata { char *opaque; char *qop; char *algorithm; - int nc; /* nounce count */ + int nc; /* nonce count */ BIT(stale); /* set true for re-negotiation */ BIT(userhash); #endif @@ -704,14 +704,15 @@ struct SingleRequest { #ifndef CURL_DISABLE_DOH struct dohdata *doh; /* DoH specific data for this request */ #endif - BIT(header); /* incoming data has HTTP header */ + BIT(header); /* incoming data has HTTP header */ BIT(content_range); /* set TRUE if Content-Range: was found */ - 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! */ + 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! */ BIT(http_bodyless); /* HTTP response status code is between 100 and 199, 204 or 304 */ - BIT(chunk); /* if set, this is a chunked transfer-encoding */ + BIT(chunk); /* if set, this is a chunked transfer-encoding */ + BIT(ignore_cl); /* ignore content-length */ BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding on upload */ BIT(getheader); /* TRUE if header parsing is wanted */ @@ -1553,6 +1554,7 @@ enum dupstring { STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */ STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */ STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */ + STRING_SSH_HOST_PUBLIC_KEY_SHA256, /* sha256 of host public key in base64 */ STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */ STRING_PROXY_SERVICE_NAME, /* Proxy service name */ STRING_SERVICE_NAME, /* Service name */ @@ -1650,6 +1652,8 @@ struct UserDefined { curl_closesocket_callback fclosesocket; /* function for closing the socket */ void *closesocket_client; + curl_prereq_callback fprereq; /* pre-initial request callback */ + void *prereq_userp; /* pre-initial request user data */ void *seek_client; /* pointer to pass to the seek callback */ /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ @@ -1674,6 +1678,8 @@ struct UserDefined { long server_response_timeout; /* in milliseconds, 0 means no timeout */ long maxage_conn; /* in seconds, max idle time to allow a connection that is to be reused */ + long maxlifetime_conn; /* in seconds, max time since creation to allow a + connection that is to be reused */ long tftp_blksize; /* in bytes, 0 means use default */ curl_off_t filesize; /* size of file to upload, -1 means unknown */ long low_speed_limit; /* bytes/second */ @@ -1851,7 +1857,6 @@ struct UserDefined { BIT(abstract_unix_socket); BIT(disallow_username_in_url); /* disallow username in url */ BIT(doh); /* DNS-over-HTTPS enabled */ - BIT(doh_get); /* use GET for DoH requests, instead of POST */ BIT(doh_verifypeer); /* DoH certificate peer verification */ BIT(doh_verifyhost); /* DoH certificate hostname verification */ BIT(doh_verifystatus); /* DoH certificate status verification */ diff --git a/libs/libcurl/src/vauth/krb5_gssapi.c b/libs/libcurl/src/vauth/krb5_gssapi.c index fee24ee470..67d43bd567 100644 --- a/libs/libcurl/src/vauth/krb5_gssapi.c +++ b/libs/libcurl/src/vauth/krb5_gssapi.c @@ -170,6 +170,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, * Parameters: * * data [in] - The session handle. + * authzid [in] - The authorization identity if some. * chlg [in] - Optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. * out [out] - The result storage. @@ -177,6 +178,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *authzid, const struct bufref *chlg, struct kerberos5data *krb5, struct bufref *out) @@ -189,13 +191,10 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, OM_uint32 unused_status; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - unsigned int indata = 0; - unsigned int outdata = 0; + unsigned char *indata; gss_qop_t qop = GSS_C_QOP_DEFAULT; unsigned int sec_layer = 0; unsigned int max_size = 0; - gss_name_t username = GSS_C_NO_NAME; - gss_buffer_desc username_token; /* Ensure we have a valid challenge message */ if(!Curl_bufref_len(chlg)) { @@ -203,25 +202,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, return CURLE_BAD_CONTENT_ENCODING; } - /* Get the fully qualified username back from the context */ - major_status = gss_inquire_context(&minor_status, krb5->context, - &username, NULL, NULL, NULL, NULL, - NULL, NULL); - if(GSS_ERROR(major_status)) { - Curl_gss_log_error(data, "gss_inquire_context() failed: ", - major_status, minor_status); - return CURLE_AUTH_ERROR; - } - - /* Convert the username from internal format to a displayable token */ - major_status = gss_display_name(&minor_status, username, - &username_token, NULL); - if(GSS_ERROR(major_status)) { - Curl_gss_log_error(data, "gss_display_name() failed: ", - major_status, minor_status); - return CURLE_AUTH_ERROR; - } - /* Setup the challenge "input" security buffer */ input_token.value = (void *) Curl_bufref_ptr(chlg); input_token.length = Curl_bufref_len(chlg); @@ -232,32 +212,32 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_unwrap() failed: ", major_status, minor_status); - gss_release_buffer(&unused_status, &username_token); return CURLE_BAD_CONTENT_ENCODING; } /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ if(output_token.length != 4) { infof(data, "GSSAPI handshake failure (invalid security data)"); - gss_release_buffer(&unused_status, &username_token); return CURLE_BAD_CONTENT_ENCODING; } - /* Copy the data out and free the challenge as it is not required anymore */ - memcpy(&indata, output_token.value, 4); + /* Extract the security layer and the maximum message size */ + indata = output_token.value; + sec_layer = indata[0]; + max_size = (indata[1] << 16) | (indata[2] << 8) | indata[3]; + + /* Free the challenge as it is not required anymore */ gss_release_buffer(&unused_status, &output_token); - /* Extract the security layer */ - sec_layer = indata & 0x000000FF; + /* Process the security layer */ if(!(sec_layer & GSSAUTH_P_NONE)) { infof(data, "GSSAPI handshake failure (invalid security layer)"); - gss_release_buffer(&unused_status, &username_token); return CURLE_BAD_CONTENT_ENCODING; } + sec_layer &= GSSAUTH_P_NONE; /* We do not support a security layer */ - /* Extract the maximum message size the server can receive */ - max_size = ntohl(indata & 0xFFFFFF00); + /* Process the maximum message size the server can receive */ if(max_size > 0) { /* The server has told us it supports a maximum receive buffer, however, as we don't require one unless we are encrypting data, we tell the server @@ -266,26 +246,24 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, } /* Allocate our message */ - messagelen = sizeof(outdata) + username_token.length + 1; + messagelen = 4; + if(authzid) + messagelen += strlen(authzid); message = malloc(messagelen); - if(!message) { - gss_release_buffer(&unused_status, &username_token); + if(!message) return CURLE_OUT_OF_MEMORY; - } - /* Populate the message with the security layer, client supported receive - message size and authorization identity including the 0x00 based - terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization - identity is not terminated with the zero-valued (%x00) octet." it seems - necessary to include it. */ - outdata = htonl(max_size) | sec_layer; - memcpy(message, &outdata, sizeof(outdata)); - memcpy(message + sizeof(outdata), username_token.value, - username_token.length); - message[messagelen - 1] = '\0'; - - /* Free the username token as it is not required anymore */ - gss_release_buffer(&unused_status, &username_token); + /* Populate the message with the security layer and client supported receive + message size. */ + message[0] = sec_layer & 0xFF; + message[1] = (max_size >> 16) & 0xFF; + message[2] = (max_size >> 8) & 0xFF; + message[3] = max_size & 0xFF; + + /* If given, append the authorization identity. */ + + if(authzid && *authzid) + memcpy(message + 4, authzid, messagelen - 4); /* Setup the "authentication data" security buffer */ input_token.value = message; diff --git a/libs/libcurl/src/vauth/krb5_sspi.c b/libs/libcurl/src/vauth/krb5_sspi.c index 8f7a2b02de..c652fd7365 100644 --- a/libs/libcurl/src/vauth/krb5_sspi.c +++ b/libs/libcurl/src/vauth/krb5_sspi.c @@ -238,13 +238,15 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, * Parameters: * * data [in] - The session handle. - * chlg [in] - The optional challenge message. + * authzid [in] - The authorization identity if some. + * chlg [in] - The optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. * out [out] - The result storage. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *authzid, const struct bufref *chlg, struct kerberos5data *krb5, struct bufref *out) @@ -260,15 +262,12 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, SecBuffer wrap_buf[3]; SecBufferDesc input_desc; SecBufferDesc wrap_desc; - unsigned long indata = 0; - unsigned long outdata = 0; + unsigned char *indata; unsigned long qop = 0; unsigned long sec_layer = 0; unsigned long max_size = 0; SecPkgContext_Sizes sizes; - SecPkgCredentials_Names names; SECURITY_STATUS status; - char *user_name; #if defined(CURL_DISABLE_VERBOSE_STRINGS) (void) data; @@ -291,17 +290,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(status != SEC_E_OK) return CURLE_AUTH_ERROR; - /* Get the fully qualified username back from the context */ - status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials, - SECPKG_CRED_ATTR_NAMES, - &names); - - if(status == SEC_E_INSUFFICIENT_MEMORY) - return CURLE_OUT_OF_MEMORY; - - if(status != SEC_E_OK) - return CURLE_AUTH_ERROR; - /* Setup the "input" security buffer */ input_desc.ulVersion = SECBUFFER_VERSION; input_desc.cBuffers = 2; @@ -326,19 +314,22 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, return CURLE_BAD_CONTENT_ENCODING; } - /* Copy the data out and free the challenge as it is not required anymore */ - memcpy(&indata, input_buf[1].pvBuffer, 4); + /* Extract the security layer and the maximum message size */ + indata = input_buf[1].pvBuffer; + sec_layer = indata[0]; + max_size = (indata[1] << 16) | (indata[2] << 8) | indata[3]; + + /* Free the challenge as it is not required anymore */ s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer); - /* Extract the security layer */ - sec_layer = indata & 0x000000FF; + /* Process the security layer */ if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) { infof(data, "GSSAPI handshake failure (invalid security layer)"); return CURLE_BAD_CONTENT_ENCODING; } + sec_layer &= KERB_WRAP_NO_ENCRYPT; /* We do not support a security layer */ - /* Extract the maximum message size the server can receive */ - max_size = ntohl(indata & 0xFFFFFF00); + /* Process the maximum message size the server can receive */ if(max_size > 0) { /* The server has told us it supports a maximum receive buffer, however, as we don't require one unless we are encrypting data, we tell the server @@ -351,33 +342,28 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(!trailer) return CURLE_OUT_OF_MEMORY; - /* Convert the user name to UTF8 when operating with Unicode */ - user_name = curlx_convert_tchar_to_UTF8(names.sUserName); - if(!user_name) { - free(trailer); - - return CURLE_OUT_OF_MEMORY; - } - /* Allocate our message */ - messagelen = sizeof(outdata) + strlen(user_name) + 1; + messagelen = 4; + if(authzid) + messagelen += strlen(authzid); message = malloc(messagelen); if(!message) { free(trailer); - curlx_unicodefree(user_name); return CURLE_OUT_OF_MEMORY; } - /* Populate the message with the security layer, client supported receive - message size and authorization identity including the 0x00 based - terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization - identity is not terminated with the zero-valued (%x00) octet." it seems - necessary to include it. */ - outdata = htonl(max_size) | sec_layer; - memcpy(message, &outdata, sizeof(outdata)); - strcpy((char *) message + sizeof(outdata), user_name); - curlx_unicodefree(user_name); + /* Populate the message with the security layer and client supported receive + message size. */ + message[0] = sec_layer & 0xFF; + message[1] = (max_size >> 16) & 0xFF; + message[2] = (max_size >> 8) & 0xFF; + message[3] = max_size & 0xFF; + + /* If given, append the authorization identity. */ + + if(authzid && *authzid) + memcpy(message + 4, authzid, messagelen - 4); /* Allocate the padding */ padding = malloc(sizes.cbBlockSize); diff --git a/libs/libcurl/src/vauth/vauth.h b/libs/libcurl/src/vauth/vauth.h index ec5b0007f5..47a7c0bc81 100644 --- a/libs/libcurl/src/vauth/vauth.h +++ b/libs/libcurl/src/vauth/vauth.h @@ -194,6 +194,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, /* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security token message */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *authzid, const struct bufref *chlg, struct kerberos5data *krb5, struct bufref *out); diff --git a/libs/libcurl/src/version_win32.c b/libs/libcurl/src/version_win32.c index b8157e9893..2f845413cc 100644 --- a/libs/libcurl/src/version_win32.c +++ b/libs/libcurl/src/version_win32.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>. + * Copyright (C) 2016 - 2021, Steve Holme, <steve_holme@hotmail.com>. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,11 +26,28 @@ #include <curl/curl.h> #include "version_win32.h" +#include "warnless.h" /* The last #include files should be: */ #include "curl_memory.h" #include "memdebug.h" +/* This Unicode version struct works for VerifyVersionInfoW (OSVERSIONINFOEXW) + and RtlVerifyVersionInfo (RTLOSVERSIONINFOEXW) */ +struct OUR_OSVERSIONINFOEXW { + ULONG dwOSVersionInfoSize; + ULONG dwMajorVersion; + ULONG dwMinorVersion; + ULONG dwBuildNumber; + ULONG dwPlatformId; + WCHAR szCSDVersion[128]; + USHORT wServicePackMajor; + USHORT wServicePackMinor; + USHORT wSuiteMask; + UCHAR wProductType; + UCHAR wReserved; +}; + /* * curlx_verify_windows_version() * @@ -152,12 +169,23 @@ bool curlx_verify_windows_version(const unsigned int majorVersion, } #else ULONGLONG cm = 0; - OSVERSIONINFOEX osver; + struct OUR_OSVERSIONINFOEXW osver; BYTE majorCondition; BYTE minorCondition; BYTE spMajorCondition; BYTE spMinorCondition; + typedef LONG (APIENTRY *RTLVERIFYVERSIONINFO_FN) + (struct OUR_OSVERSIONINFOEXW *, ULONG, ULONGLONG); + static RTLVERIFYVERSIONINFO_FN pRtlVerifyVersionInfo; + static bool onetime = true; /* safe because first call is during init */ + + if(onetime) { + pRtlVerifyVersionInfo = CURLX_FUNCTION_CAST(RTLVERIFYVERSIONINFO_FN, + (GetProcAddress(GetModuleHandleA("ntdll"), "RtlVerifyVersionInfo"))); + onetime = false; + } + switch(condition) { case VERSION_LESS_THAN: majorCondition = VER_LESS; @@ -214,10 +242,23 @@ bool curlx_verify_windows_version(const unsigned int majorVersion, if(platform != PLATFORM_DONT_CARE) cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL); - if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION | - VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR), - cm)) - matched = TRUE; + /* Later versions of Windows have version functions that may not return the + real version of Windows unless the application is so manifested. We prefer + the real version always, so we use the Rtl variant of the function when + possible. Note though the function signatures have underlying fundamental + types that are the same, the return values are different. */ + if(pRtlVerifyVersionInfo) { + matched = !pRtlVerifyVersionInfo(&osver, + (VER_MAJORVERSION | VER_MINORVERSION | + VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR), + cm); + } + else { + matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver, + (VER_MAJORVERSION | VER_MINORVERSION | + VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR), + cm); + } #endif return matched; diff --git a/libs/libcurl/src/vquic/ngtcp2.c b/libs/libcurl/src/vquic/ngtcp2.c index fc449c4152..dfe8f96fb1 100644 --- a/libs/libcurl/src/vquic/ngtcp2.c +++ b/libs/libcurl/src/vquic/ngtcp2.c @@ -28,6 +28,9 @@ #include <nghttp3/nghttp3.h> #ifdef USE_OPENSSL #include <openssl/err.h> +#include <ngtcp2/ngtcp2_crypto_openssl.h> +#elif defined(USE_GNUTLS) +#include <ngtcp2/ngtcp2_crypto_gnutls.h> #endif #include "urldata.h" #include "sendf.h" @@ -58,6 +61,7 @@ #endif #define H3_ALPN_H3_29 "\x5h3-29" +#define H3_ALPN_H3 "\x2h3" /* * This holds outgoing HTTP/3 stream data that is used by nghttp3 until acked. @@ -117,42 +121,6 @@ static void quic_printf(void *user_data, const char *fmt, ...) } #endif -#ifdef USE_OPENSSL -static ngtcp2_crypto_level -quic_from_ossl_level(OSSL_ENCRYPTION_LEVEL ossl_level) -{ - switch(ossl_level) { - case ssl_encryption_initial: - return NGTCP2_CRYPTO_LEVEL_INITIAL; - case ssl_encryption_early_data: - return NGTCP2_CRYPTO_LEVEL_EARLY; - case ssl_encryption_handshake: - return NGTCP2_CRYPTO_LEVEL_HANDSHAKE; - case ssl_encryption_application: - return NGTCP2_CRYPTO_LEVEL_APPLICATION; - default: - assert(0); - } -} -#elif defined(USE_GNUTLS) -static ngtcp2_crypto_level -quic_from_gtls_level(gnutls_record_encryption_level_t gtls_level) -{ - switch(gtls_level) { - case GNUTLS_ENCRYPTION_LEVEL_INITIAL: - return NGTCP2_CRYPTO_LEVEL_INITIAL; - case GNUTLS_ENCRYPTION_LEVEL_EARLY: - return NGTCP2_CRYPTO_LEVEL_EARLY; - case GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE: - return NGTCP2_CRYPTO_LEVEL_HANDSHAKE; - case GNUTLS_ENCRYPTION_LEVEL_APPLICATION: - return NGTCP2_CRYPTO_LEVEL_APPLICATION; - default: - assert(0); - } -} -#endif - static void qlog_callback(void *user_data, uint32_t flags, const void *data, size_t datalen) { @@ -223,27 +191,9 @@ static int write_client_handshake(struct quicsocket *qs, ngtcp2_crypto_level level, const uint8_t *data, size_t len) { - struct quic_handshake *crypto_data; int rv; - crypto_data = &qs->crypto_data[level]; - if(!crypto_data->buf) { - crypto_data->buf = malloc(4096); - if(!crypto_data->buf) - return 0; - crypto_data->alloclen = 4096; - } - - /* TODO Just pretend that handshake does not grow more than 4KiB for - now */ - assert(crypto_data->len + len <= crypto_data->alloclen); - - memcpy(&crypto_data->buf[crypto_data->len], data, len); - crypto_data->len += len; - - rv = ngtcp2_conn_submit_crypto_data( - qs->qconn, level, (uint8_t *)(&crypto_data->buf[crypto_data->len] - len), - len); + rv = ngtcp2_conn_submit_crypto_data(qs->qconn, level, data, len); if(rv) { H3BUGF(fprintf(stderr, "write_client_handshake failed\n")); } @@ -260,7 +210,7 @@ static int quic_set_encryption_secrets(SSL *ssl, size_t secretlen) { struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl); - int level = quic_from_ossl_level(ossl_level); + int level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level); if(ngtcp2_crypto_derive_and_install_rx_key( qs->qconn, NULL, NULL, NULL, level, rx_secret, secretlen) != 0) @@ -282,7 +232,8 @@ static int quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, const uint8_t *data, size_t len) { struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl); - ngtcp2_crypto_level level = quic_from_ossl_level(ossl_level); + ngtcp2_crypto_level level = + ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level); return write_client_handshake(qs, level, data, len); } @@ -353,9 +304,10 @@ static int quic_init_ssl(struct quicsocket *qs) SSL_set_app_data(qs->ssl, qs); SSL_set_connect_state(qs->ssl); + SSL_set_quic_use_legacy_codepoint(qs->ssl, 0); - alpn = (const uint8_t *)H3_ALPN_H3_29; - alpnlen = sizeof(H3_ALPN_H3_29) - 1; + alpn = (const uint8_t *)H3_ALPN_H3_29 H3_ALPN_H3; + alpnlen = sizeof(H3_ALPN_H3_29) - 1 + sizeof(H3_ALPN_H3) - 1; if(alpn) SSL_set_alpn_protos(qs->ssl, alpn, (int)alpnlen); @@ -370,7 +322,8 @@ static int secret_func(gnutls_session_t ssl, const void *tx_secret, size_t secretlen) { struct quicsocket *qs = gnutls_session_get_ptr(ssl); - int level = quic_from_gtls_level(gtls_level); + int level = + ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gtls_level); if(level != NGTCP2_CRYPTO_LEVEL_EARLY && ngtcp2_crypto_derive_and_install_rx_key( @@ -395,7 +348,8 @@ static int read_func(gnutls_session_t ssl, size_t len) { struct quicsocket *qs = gnutls_session_get_ptr(ssl); - ngtcp2_crypto_level level = quic_from_gtls_level(gtls_level); + ngtcp2_crypto_level level = + ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gtls_level); int rv; if(htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC) @@ -465,7 +419,7 @@ static int tp_send_func(gnutls_session_t ssl, gnutls_buffer_t extdata) static int quic_init_ssl(struct quicsocket *qs) { - gnutls_datum_t alpn = {NULL, 0}; + gnutls_datum_t alpn[2]; /* this will need some attention when HTTPS proxy over QUIC get fixed */ const char * const hostname = qs->conn->host.name; int rc; @@ -487,12 +441,10 @@ static int quic_init_ssl(struct quicsocket *qs) gnutls_alert_set_read_function(qs->ssl, alert_read_func); rc = gnutls_session_ext_register(qs->ssl, "QUIC Transport Parameters", - 0xffa5, GNUTLS_EXT_TLS, - tp_recv_func, tp_send_func, - NULL, NULL, NULL, - GNUTLS_EXT_FLAG_TLS | - GNUTLS_EXT_FLAG_CLIENT_HELLO | - GNUTLS_EXT_FLAG_EE); + NGTCP2_TLSEXT_QUIC_TRANSPORT_PARAMETERS_V1, GNUTLS_EXT_TLS, + tp_recv_func, tp_send_func, NULL, NULL, NULL, + GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_EE); if(rc < 0) { H3BUGF(fprintf(stderr, "gnutls_session_ext_register failed: %s\n", gnutls_strerror(rc))); @@ -532,10 +484,12 @@ static int quic_init_ssl(struct quicsocket *qs) } /* strip the first byte (the length) from NGHTTP3_ALPN_H3 */ - alpn.data = (unsigned char *)H3_ALPN_H3_29 + 1; - alpn.size = sizeof(H3_ALPN_H3_29) - 2; - if(alpn.data) - gnutls_alpn_set_protocols(qs->ssl, &alpn, 1, 0); + alpn[0].data = (unsigned char *)H3_ALPN_H3_29 + 1; + alpn[0].size = sizeof(H3_ALPN_H3_29) - 2; + alpn[1].data = (unsigned char *)H3_ALPN_H3 + 1; + alpn[1].size = sizeof(H3_ALPN_H3) - 2; + + gnutls_alpn_set_protocols(qs->ssl, alpn, 2, GNUTLS_ALPN_MANDATORY); /* set SNI */ gnutls_server_name_set(qs->ssl, GNUTLS_NAME_DNS, hostname, strlen(hostname)); @@ -543,22 +497,6 @@ static int quic_init_ssl(struct quicsocket *qs) } #endif -static int -cb_recv_crypto_data(ngtcp2_conn *tconn, ngtcp2_crypto_level crypto_level, - uint64_t offset, - const uint8_t *data, size_t datalen, - void *user_data) -{ - (void)offset; - (void)user_data; - - if(ngtcp2_crypto_read_write_crypto_data(tconn, crypto_level, data, - datalen) != 0) - return NGTCP2_ERR_CRYPTO; - - return 0; -} - static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data) { (void)user_data; @@ -623,8 +561,8 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, return 0; } -static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id, - uint64_t app_error_code, +static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags, + int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data) { struct quicsocket *qs = (struct quicsocket *)user_data; @@ -633,6 +571,10 @@ static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; /* stream is closed... */ + if(!(flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET)) { + app_error_code = NGHTTP3_H3_NO_ERROR; + } + rv = nghttp3_conn_close_stream(qs->h3conn, stream_id, app_error_code); if(rv) { @@ -653,7 +595,25 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id, (void)app_error_code; (void)stream_user_data; - rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id); + rv = nghttp3_conn_shutdown_stream_read(qs->h3conn, stream_id); + if(rv) { + return NGTCP2_ERR_CALLBACK_FAILURE; + } + + return 0; +} + +static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id, + uint64_t app_error_code, void *user_data, + void *stream_user_data) +{ + struct quicsocket *qs = (struct quicsocket *)user_data; + int rv; + (void)tconn; + (void)app_error_code; + (void)stream_user_data; + + rv = nghttp3_conn_shutdown_stream_read(qs->h3conn, stream_id); if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -690,6 +650,20 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id, return 0; } +static void cb_rand(uint8_t *dest, size_t destlen, + const ngtcp2_rand_ctx *rand_ctx) +{ + CURLcode result; + (void)rand_ctx; + + result = Curl_rand(NULL, dest, destlen); + if(result) { + /* cb_rand is only used for non-cryptographic context. If Curl_rand + failed, just fill 0 and call it *random*. */ + memset(dest, 0, destlen); + } +} + static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid, uint8_t *token, size_t cidlen, void *user_data) @@ -713,14 +687,13 @@ static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid, static ngtcp2_callbacks ng_callbacks = { ngtcp2_crypto_client_initial_cb, NULL, /* recv_client_initial */ - cb_recv_crypto_data, + ngtcp2_crypto_recv_crypto_data_cb, cb_handshake_completed, NULL, /* recv_version_negotiation */ ngtcp2_crypto_encrypt_cb, ngtcp2_crypto_decrypt_cb, ngtcp2_crypto_hp_mask_cb, cb_recv_stream_data, - NULL, /* acked_crypto_offset */ cb_acked_stream_data_offset, NULL, /* stream_open */ cb_stream_close, @@ -728,7 +701,7 @@ static ngtcp2_callbacks ng_callbacks = { ngtcp2_crypto_recv_retry_cb, cb_extend_max_local_streams_bidi, NULL, /* extend_max_local_streams_uni */ - NULL, /* rand */ + cb_rand, cb_get_new_connection_id, NULL, /* remove_connection_id */ ngtcp2_crypto_update_key_cb, /* update_key */ @@ -745,7 +718,9 @@ static ngtcp2_callbacks ng_callbacks = { ngtcp2_crypto_delete_crypto_cipher_ctx_cb, NULL, /* recv_datagram */ NULL, /* ack_datagram */ - NULL /* lost_datagram */ + NULL, /* lost_datagram */ + ngtcp2_crypto_get_path_challenge_data_cb, + cb_stream_stop_sending }; /* @@ -817,7 +792,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, ngtcp2_addr_init(&path.remote, addr, addrlen); rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path, - NGTCP2_PROTO_VER_MIN, &ng_callbacks, + NGTCP2_PROTO_VER_V1, &ng_callbacks, &qs->settings, &qs->transport_params, NULL, qs); if(rc) return CURLE_QUIC_CONNECT_ERROR; @@ -833,7 +808,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, void Curl_quic_ver(char *p, size_t len) { const ngtcp2_info *ng2 = ngtcp2_version(0); - nghttp3_info *ht3 = nghttp3_version(0); + const nghttp3_info *ht3 = nghttp3_version(0); (void)msnprintf(p, len, "ngtcp2/%s nghttp3/%s", ng2->version_str, ht3->version_str); } @@ -859,7 +834,6 @@ static int ng_getsock(struct Curl_easy *data, struct connectdata *conn, static void qs_disconnect(struct quicsocket *qs) { - int i; if(!qs->conn) /* already closed */ return; qs->conn = NULL; @@ -880,8 +854,6 @@ static void qs_disconnect(struct quicsocket *qs) qs->cred = NULL; } #endif - for(i = 0; i < 3; i++) - Curl_safefree(qs->crypto_data[i].buf); nghttp3_conn_del(qs->h3conn); ngtcp2_conn_del(qs->qconn); #ifdef USE_OPENSSL @@ -1143,14 +1115,10 @@ static nghttp3_callbacks ngh3_callbacks = { NULL, /* begin_trailers */ cb_h3_recv_header, NULL, /* end_trailers */ - NULL, /* http_begin_push_promise */ - NULL, /* http_recv_push_promise */ - NULL, /* http_end_push_promise */ - NULL, /* http_cancel_push */ cb_h3_send_stop_sending, - NULL, /* push_stream */ NULL, /* end_stream */ NULL, /* reset_stream */ + NULL /* shutdown */ }; static int init_ngh3_conn(struct quicsocket *qs) @@ -1660,6 +1628,12 @@ static ssize_t ngh3_stream_send(struct Curl_easy *data, return -1; } + /* Reset post upload buffer after resumed. */ + if(stream->upload_mem) { + stream->upload_mem = NULL; + stream->upload_len = 0; + } + *curlcode = CURLE_OK; return sent; } @@ -1758,8 +1732,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, int rv; ssize_t sent; ssize_t outlen; - uint8_t out[NGTCP2_MAX_PKTLEN_IPV4]; - size_t pktlen; + uint8_t out[NGTCP2_MAX_UDP_PAYLOAD_SIZE]; ngtcp2_path_storage ps; ngtcp2_tstamp ts = timestamp(); struct sockaddr_storage remote_addr; @@ -1772,19 +1745,6 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, ssize_t ndatalen; uint32_t flags; - switch(qs->local_addr.ss_family) { - case AF_INET: - pktlen = NGTCP2_MAX_PKTLEN_IPV4; - break; -#ifdef ENABLE_IPV6 - case AF_INET6: - pktlen = NGTCP2_MAX_PKTLEN_IPV6; - break; -#endif - default: - assert(0); - } - rv = ngtcp2_conn_handle_expiry(qs->qconn, ts); if(rv) { failf(data, "ngtcp2_conn_handle_expiry returned error: %s", @@ -1811,15 +1771,16 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, flags = NGTCP2_WRITE_STREAM_FLAG_MORE | (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0); - outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out, pktlen, + outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out, + sizeof(out), &ndatalen, flags, stream_id, (const ngtcp2_vec *)vec, veccnt, ts); if(outlen == 0) { break; } if(outlen < 0) { - if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED || - outlen == NGTCP2_ERR_STREAM_SHUT_WR) { + switch(outlen) { + case NGTCP2_ERR_STREAM_DATA_BLOCKED: assert(ndatalen == -1); rv = nghttp3_conn_block_stream(qs->h3conn, stream_id); if(rv) { @@ -1828,8 +1789,17 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, return CURLE_SEND_ERROR; } continue; - } - else if(outlen == NGTCP2_ERR_WRITE_MORE) { + case NGTCP2_ERR_STREAM_SHUT_WR: + assert(ndatalen == -1); + rv = nghttp3_conn_shutdown_stream_write(qs->h3conn, stream_id); + if(rv) { + failf(data, + "nghttp3_conn_shutdown_stream_write returned error: %s\n", + nghttp3_strerror(rv)); + return CURLE_SEND_ERROR; + } + continue; + case NGTCP2_ERR_WRITE_MORE: assert(ndatalen >= 0); rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen); if(rv) { @@ -1838,8 +1808,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, return CURLE_SEND_ERROR; } continue; - } - else { + default: assert(ndatalen == -1); failf(data, "ngtcp2_conn_writev_stream returned error: %s", ngtcp2_strerror((int)outlen)); diff --git a/libs/libcurl/src/vquic/ngtcp2.h b/libs/libcurl/src/vquic/ngtcp2.h index cbede45146..501453042b 100644 --- a/libs/libcurl/src/vquic/ngtcp2.h +++ b/libs/libcurl/src/vquic/ngtcp2.h @@ -34,13 +34,6 @@ #include <gnutls/gnutls.h> #endif -struct quic_handshake { - char *buf; /* pointer to the buffer */ - size_t alloclen; /* size of allocation */ - size_t len; /* size of content in buffer */ - size_t nread; /* how many bytes have been read */ -}; - struct quicsocket { struct connectdata *conn; /* point back to the connection */ ngtcp2_conn *qconn; @@ -56,7 +49,6 @@ struct quicsocket { gnutls_certificate_credentials_t cred; gnutls_session_t ssl; #endif - struct quic_handshake crypto_data[3]; /* the last TLS alert description generated by the local endpoint */ uint8_t tls_alert; struct sockaddr_storage local_addr; diff --git a/libs/libcurl/src/vssh/libssh.c b/libs/libcurl/src/vssh/libssh.c index c2ca8ef63e..3e317e87c9 100644 --- a/libs/libcurl/src/vssh/libssh.c +++ b/libs/libcurl/src/vssh/libssh.c @@ -74,7 +74,6 @@ #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" -#include "strerror.h" #include "inet_ntop.h" #include "parsedate.h" /* for the week day and month names */ #include "sockaddr.h" /* required for Curl_sockaddr_storage */ diff --git a/libs/libcurl/src/vssh/libssh2.c b/libs/libcurl/src/vssh/libssh2.c index 5cbff0769a..7466840ffa 100644 --- a/libs/libcurl/src/vssh/libssh2.c +++ b/libs/libcurl/src/vssh/libssh2.c @@ -73,7 +73,6 @@ #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" -#include "strerror.h" #include "inet_ntop.h" #include "parsedate.h" /* for the week day and month names */ #include "sockaddr.h" /* required for Curl_sockaddr_storage */ @@ -82,6 +81,11 @@ #include "select.h" #include "warnless.h" #include "curl_path.h" +#include "strcase.h" + +#include <curl_base64.h> /* for base64 encoding/decoding */ +#include <curl_sha256.h> + /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -616,40 +620,142 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data) struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]; - char md5buffer[33]; + const char *pubkey_sha256 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256]; + + infof(data, "SSH MD5 public key: %s", + pubkey_md5 != NULL ? pubkey_md5 : "NULL"); + infof(data, "SSH SHA256 public key: %s", + pubkey_sha256 != NULL ? pubkey_sha256 : "NULL"); - const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session, - LIBSSH2_HOSTKEY_HASH_MD5); + if(pubkey_sha256) { + const char *fingerprint = NULL; + char *fingerprint_b64 = NULL; + size_t fingerprint_b64_len; + size_t pub_pos = 0; + size_t b64_pos = 0; - if(fingerprint) { +#ifdef LIBSSH2_HOSTKEY_HASH_SHA256 /* The fingerprint points to static storage (!), don't free() it. */ - int i; - for(i = 0; i < 16; i++) - msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]); - infof(data, "SSH MD5 fingerprint: %s", md5buffer); - } + fingerprint = libssh2_hostkey_hash(sshc->ssh_session, + LIBSSH2_HOSTKEY_HASH_SHA256); +#else + const char *hostkey; + size_t len = 0; + unsigned char hash[32]; + + hostkey = libssh2_session_hostkey(sshc->ssh_session, &len, NULL); + if(hostkey) { + Curl_sha256it(hash, (const unsigned char *) hostkey, len); + fingerprint = (char *) hash; + } +#endif - /* Before we authenticate we check the hostkey's MD5 fingerprint - * against a known fingerprint, if available. - */ - if(pubkey_md5 && strlen(pubkey_md5) == 32) { - if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) { - if(fingerprint) - failf(data, - "Denied establishing ssh session: mismatch md5 fingerprint. " - "Remote %s is not equal to %s", md5buffer, pubkey_md5); - else - failf(data, - "Denied establishing ssh session: md5 fingerprint not available"); + if(!fingerprint) { + failf(data, + "Denied establishing ssh session: sha256 fingerprint " + "not available"); + state(data, SSH_SESSION_FREE); + sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + return sshc->actualcode; + } + + /* The length of fingerprint is 32 bytes for SHA256. + * See libssh2_hostkey_hash documentation. */ + if(Curl_base64_encode (data, fingerprint, 32, &fingerprint_b64, + &fingerprint_b64_len) != CURLE_OK) { + state(data, SSH_SESSION_FREE); + sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + return sshc->actualcode; + } + + if(!fingerprint_b64) { + failf(data, + "sha256 fingerprint could not be encoded"); + state(data, SSH_SESSION_FREE); + sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + return sshc->actualcode; + } + + infof(data, "SSH SHA256 fingerprint: %s", fingerprint_b64); + + /* Find the position of any = padding characters in the public key */ + while((pubkey_sha256[pub_pos] != '=') && pubkey_sha256[pub_pos]) { + pub_pos++; + } + + /* Find the position of any = padding characters in the base64 coded + * hostkey fingerprint */ + while((fingerprint_b64[b64_pos] != '=') && fingerprint_b64[b64_pos]) { + b64_pos++; + } + + /* Before we authenticate we check the hostkey's sha256 fingerprint + * against a known fingerprint, if available. + */ + if((pub_pos != b64_pos) || + Curl_strncasecompare(fingerprint_b64, pubkey_sha256, pub_pos) != 1) { + free(fingerprint_b64); + + failf(data, + "Denied establishing ssh session: mismatch sha256 fingerprint. " + "Remote %s is not equal to %s", fingerprint, pubkey_sha256); state(data, SSH_SESSION_FREE); sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; return sshc->actualcode; } - infof(data, "MD5 checksum match!"); + + free(fingerprint_b64); + + infof(data, "SHA256 checksum match!"); + } + + if(pubkey_md5) { + char md5buffer[33]; + const char *fingerprint = NULL; + + fingerprint = libssh2_hostkey_hash(sshc->ssh_session, + LIBSSH2_HOSTKEY_HASH_MD5); + + if(fingerprint) { + /* The fingerprint points to static storage (!), don't free() it. */ + int i; + for(i = 0; i < 16; i++) { + msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]); + } + + infof(data, "SSH MD5 fingerprint: %s", md5buffer); + } + + /* Before we authenticate we check the hostkey's MD5 fingerprint + * against a known fingerprint, if available. + */ + if(pubkey_md5 && strlen(pubkey_md5) == 32) { + if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) { + if(fingerprint) { + failf(data, + "Denied establishing ssh session: mismatch md5 fingerprint. " + "Remote %s is not equal to %s", md5buffer, pubkey_md5); + } + else { + failf(data, + "Denied establishing ssh session: md5 fingerprint " + "not available"); + } + state(data, SSH_SESSION_FREE); + sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + return sshc->actualcode; + } + infof(data, "MD5 checksum match!"); + } + } + + if(!pubkey_md5 && !pubkey_sha256) { + return ssh_knownhost(data); + } + else { /* as we already matched, we skip the check for known hosts */ return CURLE_OK; } - return ssh_knownhost(data); } /* @@ -3611,7 +3717,7 @@ void Curl_ssh_cleanup(void) void Curl_ssh_version(char *buffer, size_t buflen) { - (void)msnprintf(buffer, buflen, "libssh2/%s", LIBSSH2_VERSION); + (void)msnprintf(buffer, buflen, "libssh2/%s", CURL_LIBSSH2_VERSION); } /* The SSH session is associated with the *CONNECTION* but the callback user diff --git a/libs/libcurl/src/vssh/wolfssh.c b/libs/libcurl/src/vssh/wolfssh.c index 4b1e2ec5e3..5b4cde91b0 100644 --- a/libs/libcurl/src/vssh/wolfssh.c +++ b/libs/libcurl/src/vssh/wolfssh.c @@ -449,7 +449,8 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) switch(sshc->state) { case SSH_INIT: state(data, SSH_S_STARTUP); - /* FALLTHROUGH */ + break; + case SSH_S_STARTUP: rc = wolfSSH_connect(sshc->ssh_session); if(rc != WS_SUCCESS) @@ -838,7 +839,8 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) break; } state(data, SSH_SFTP_READDIR); - /* FALLTHROUGH */ + break; + case SSH_SFTP_READDIR: name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path); if(!name) diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c index cbbb3b5deb..9b772d064d 100644 --- a/libs/libcurl/src/vtls/bearssl.c +++ b/libs/libcurl/src/vtls/bearssl.c @@ -68,6 +68,14 @@ struct cafile_parser { size_t dn_len; }; +#define CAFILE_SOURCE_PATH 1 +#define CAFILE_SOURCE_BLOB 2 +struct cafile_source { + const int type; + const char * const data; + const size_t len; +}; + static void append_dn(void *ctx, const void *buf, size_t len) { struct cafile_parser *ca = ctx; @@ -90,7 +98,8 @@ static void x509_push(void *ctx, const void *buf, size_t len) br_x509_decoder_push(&ca->xc, buf, len); } -static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, +static CURLcode load_cafile(struct cafile_source *source, + br_x509_trust_anchor **anchors, size_t *anchors_len) { struct cafile_parser ca; @@ -100,13 +109,22 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, br_x509_trust_anchor *new_anchors; size_t new_anchors_len; br_x509_pkey *pkey; - FILE *fp; - unsigned char buf[BUFSIZ], *p; + FILE *fp = 0; + unsigned char buf[BUFSIZ]; + const unsigned char *p; const char *name; size_t n, i, pushed; - fp = fopen(path, "rb"); - if(!fp) + DEBUGASSERT(source->type == CAFILE_SOURCE_PATH + || source->type == CAFILE_SOURCE_BLOB); + + if(source->type == CAFILE_SOURCE_PATH) { + fp = fopen(source->data, "rb"); + if(!fp) + return CURLE_SSL_CACERT_BADFILE; + } + + if(source->type == CAFILE_SOURCE_BLOB && source->len > (size_t)INT_MAX) return CURLE_SSL_CACERT_BADFILE; ca.err = CURLE_OK; @@ -115,11 +133,17 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, ca.anchors_len = 0; br_pem_decoder_init(&pc); br_pem_decoder_setdest(&pc, x509_push, &ca); - for(;;) { - n = fread(buf, 1, sizeof(buf), fp); - if(n == 0) - break; - p = buf; + do { + if(source->type == CAFILE_SOURCE_PATH) { + n = fread(buf, 1, sizeof(buf), fp); + if(n == 0) + break; + p = buf; + } + else if(source->type == CAFILE_SOURCE_BLOB) { + n = source->len; + p = (unsigned char *) source->data; + } while(n) { pushed = br_pem_decoder_push(&pc, p, n); if(ca.err) @@ -211,12 +235,13 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, goto fail; } } - } - if(ferror(fp)) + } while(source->type != CAFILE_SOURCE_BLOB); + if(fp && ferror(fp)) ca.err = CURLE_READ_ERROR; fail: - fclose(fp); + if(fp) + fclose(fp); if(ca.err == CURLE_OK) { *anchors = ca.anchors; *anchors_len = ca.anchors_len; @@ -299,7 +324,10 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; - const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob); + const char * const ssl_cafile = + /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ + (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile)); const char *hostname = SSL_HOST_NAME(); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const bool verifyhost = SSL_CONN_CONFIG(verifyhost); @@ -340,8 +368,30 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } + if(ca_info_blob) { + struct cafile_source source = { + CAFILE_SOURCE_BLOB, + ca_info_blob->data, + ca_info_blob->len, + }; + ret = load_cafile(&source, &backend->anchors, &backend->anchors_len); + if(ret != CURLE_OK) { + if(verifypeer) { + failf(data, "error importing CA certificate blob"); + return ret; + } + /* Only warn if no certificate verification is required. */ + infof(data, "error importing CA certificate blob, continuing anyway"); + } + } + if(ssl_cafile) { - ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len); + struct cafile_source source = { + CAFILE_SOURCE_PATH, + ssl_cafile, + 0, + }; + ret = load_cafile(&source, &backend->anchors, &backend->anchors_len); if(ret != CURLE_OK) { if(verifypeer) { failf(data, "error setting certificate verify locations." @@ -558,6 +608,7 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data, if(SSL_SET_OPTION(primary.sessionid)) { bool incache; + bool added = FALSE; void *oldsession; br_ssl_session_parameters *session; @@ -573,10 +624,11 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data, Curl_ssl_delsessionid(data, oldsession); ret = Curl_ssl_addsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE, - session, 0, sockindex); + session, 0, sockindex, &added); Curl_ssl_sessionid_unlock(data); - if(ret) { + if(!added) free(session); + if(ret) { return CURLE_OUT_OF_MEMORY; } } @@ -841,7 +893,7 @@ static CURLcode bearssl_sha256sum(const unsigned char *input, const struct Curl_ssl Curl_ssl_bearssl = { { CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */ - 0, + SSLSUPP_CAINFO_BLOB, sizeof(struct ssl_backend_data), Curl_none_init, /* init */ diff --git a/libs/libcurl/src/vtls/gskit.c b/libs/libcurl/src/vtls/gskit.c index af8fc92b27..e451f6aebe 100644 --- a/libs/libcurl/src/vtls/gskit.c +++ b/libs/libcurl/src/vtls/gskit.c @@ -180,6 +180,7 @@ static bool is_separator(char c) static CURLcode gskit_status(struct Curl_easy *data, int rc, const char *procname, CURLcode defcode) { + char buffer[STRERROR_LEN]; /* Process GSKit status and map it to a CURLcode. */ switch(rc) { case GSK_OK: @@ -208,7 +209,8 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc, case ENOMEM: return CURLE_OUT_OF_MEMORY; default: - failf(data, "%s I/O error: %s", procname, strerror(errno)); + failf(data, "%s I/O error: %s", procname, + Curl_strerror(errno, buffer, sizeof(buffer))); break; } break; @@ -223,13 +225,15 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc, static CURLcode set_enum(struct Curl_easy *data, gsk_handle h, GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok) { + char buffer[STRERROR_LEN]; int rc = gsk_attribute_set_enum(h, id, value); switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: - failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno)); + failf(data, "gsk_attribute_set_enum() I/O error: %s", + Curl_strerror(errno, buffer, sizeof(buffer))); break; case GSK_ATTRIBUTE_INVALID_ID: if(unsupported_ok) @@ -245,13 +249,15 @@ static CURLcode set_enum(struct Curl_easy *data, gsk_handle h, static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h, GSK_BUF_ID id, const char *buffer, bool unsupported_ok) { + char buffer[STRERROR_LEN]; int rc = gsk_attribute_set_buffer(h, id, buffer, 0); switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: - failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno)); + failf(data, "gsk_attribute_set_buffer() I/O error: %s", + Curl_strerror(errno, buffer, sizeof(buffer))); break; case GSK_ATTRIBUTE_INVALID_ID: if(unsupported_ok) @@ -267,6 +273,7 @@ static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h, static CURLcode set_numeric(struct Curl_easy *data, gsk_handle h, GSK_NUM_ID id, int value) { + char buffer[STRERROR_LEN]; int rc = gsk_attribute_set_numeric_value(h, id, value); switch(rc) { @@ -274,7 +281,7 @@ static CURLcode set_numeric(struct Curl_easy *data, return CURLE_OK; case GSK_ERROR_IO: failf(data, "gsk_attribute_set_numeric_value() I/O error: %s", - strerror(errno)); + Curl_strerror(errno, buffer, sizeof(buffer))); break; default: failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc)); @@ -287,13 +294,15 @@ static CURLcode set_numeric(struct Curl_easy *data, static CURLcode set_callback(struct Curl_easy *data, gsk_handle h, GSK_CALLBACK_ID id, void *info) { + char buffer[STRERROR_LEN]; int rc = gsk_attribute_set_callback(h, id, info); switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: - failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno)); + failf(data, "gsk_attribute_set_callback() I/O error: %s", + Curl_strerror(errno, buffer, sizeof(buffer))); break; default: failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc)); @@ -966,7 +975,9 @@ static CURLcode gskit_connect_step2(struct Curl_easy *data, continue; /* Retry. */ } if(errno != ETIME) { - failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno)); + char buffer[STRERROR_LEN]; + failf(data, "QsoWaitForIOCompletion() I/O error: %s", + Curl_strerror(errno, buffer, sizeof(buffer))); cancel_async_handshake(conn, sockindex); close_async_handshake(connssl); return CURLE_SSL_CONNECT_ERROR; @@ -1229,7 +1240,8 @@ static int gskit_shutdown(struct Curl_easy *data, nread = read(conn->sock[sockindex], buf, sizeof(buf)); if(nread < 0) { - failf(data, "read: %s", strerror(errno)); + char buffer[STRERROR_LEN]; + failf(data, "read: %s", Curl_strerror(errno, buffer, sizeof(buffer))); rc = -1; } diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c index 1b145d8ebb..2053fd439d 100644 --- a/libs/libcurl/src/vtls/gtls.c +++ b/libs/libcurl/src/vtls/gtls.c @@ -404,6 +404,7 @@ gtls_connect_step1(struct Curl_easy *data, const char * const hostname = SSL_HOST_NAME(); long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult); const char *tls13support; + CURLcode result; if(connssl->state == ssl_connection_complete) /* to make us tolerant against being called more than once for the @@ -557,31 +558,25 @@ gtls_connect_step1(struct Curl_easy *data, /* Ensure +SRP comes at the *end* of all relevant strings so that it can be * removed if a run-time error indicates that SRP is not supported by this * GnuTLS version */ - switch(SSL_CONN_CONFIG(version)) { - case CURL_SSLVERSION_TLSv1_3: - if(!tls13support) { - failf(data, "This GnuTLS installation does not support TLS 1.3"); - return CURLE_SSL_CONNECT_ERROR; - } - /* FALLTHROUGH */ - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - case CURL_SSLVERSION_TLSv1_0: - case CURL_SSLVERSION_TLSv1_1: - case CURL_SSLVERSION_TLSv1_2: { - CURLcode result = set_ssl_version_min_max(data, &prioritylist, - tls13support); - if(result) - return result; - break; - } - case CURL_SSLVERSION_SSLv2: - case CURL_SSLVERSION_SSLv3: - default: - failf(data, "GnuTLS does not support SSLv2 or SSLv3"); + + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2 || + SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3) { + failf(data, "GnuTLS does not support SSLv2 or SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_TLSv1_3) { + if(!tls13support) { + failf(data, "This GnuTLS installation does not support TLS 1.3"); return CURLE_SSL_CONNECT_ERROR; + } } + /* At this point we know we have a supported TLS version, so set it */ + result = set_ssl_version_min_max(data, &prioritylist, tls13support); + if(result) + return result; + #ifdef HAVE_GNUTLS_SRP /* Only add SRP to the cipher list if SRP is requested. Otherwise * GnuTLS will disable TLS 1.3 support. */ @@ -1287,6 +1282,7 @@ gtls_connect_step3(struct Curl_easy *data, if(connect_sessionid) { bool incache; + bool added = FALSE; void *ssl_sessionid; /* extract session ID to the allocated buffer */ @@ -1306,10 +1302,11 @@ gtls_connect_step3(struct Curl_easy *data, result = Curl_ssl_addsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE, connect_sessionid, connect_idsize, - sockindex); + sockindex, &added); Curl_ssl_sessionid_unlock(data); - if(result) { + if(!added) free(connect_sessionid); + if(result) { result = CURLE_OUT_OF_MEMORY; } } diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c index e986bea82d..08c79e1624 100644 --- a/libs/libcurl/src/vtls/mbedtls.c +++ b/libs/libcurl/src/vtls/mbedtls.c @@ -41,7 +41,9 @@ #include <mbedtls/net.h> #endif #include <mbedtls/ssl.h> +#if MBEDTLS_VERSION_NUMBER < 0x03000000 #include <mbedtls/certs.h> +#endif #include <mbedtls/x509.h> #include <mbedtls/error.h> @@ -183,6 +185,17 @@ static Curl_send mbed_send; static CURLcode mbedtls_version_from_curl(int *mbedver, long version) { +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + switch(version) { + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3: + break; + } +#else switch(version) { case CURL_SSLVERSION_TLSv1_0: *mbedver = MBEDTLS_SSL_MINOR_VERSION_1; @@ -196,6 +209,8 @@ static CURLcode mbedtls_version_from_curl(int *mbedver, long version) case CURL_SSLVERSION_TLSv1_3: break; } +#endif + return CURLE_SSL_CONNECT_ERROR; } @@ -205,8 +220,13 @@ set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn, { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_3; + int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_3; +#else int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1; +#endif long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); CURLcode result = CURLE_OK; @@ -257,7 +277,9 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob); const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); const char * const hostname = SSL_HOST_NAME(); +#ifndef CURL_DISABLE_VERBOSE_STRINGS const long int port = SSL_HOST_PORT(); +#endif int ret = -1; char errorbuf[128]; @@ -354,8 +376,15 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, if(SSL_SET_OPTION(key) || SSL_SET_OPTION(key_blob)) { if(SSL_SET_OPTION(key)) { +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd), + mbedtls_ctr_drbg_random, + &backend->ctr_drbg); +#else ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key), SSL_SET_OPTION(key_passwd)); +#endif if(ret) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); @@ -369,9 +398,17 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, const unsigned char *key_data = (const unsigned char *)ssl_key_blob->data; const char *passwd = SSL_SET_OPTION(key_passwd); +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len, + (const unsigned char *)passwd, + passwd ? strlen(passwd) : 0, + mbedtls_ctr_drbg_random, + &backend->ctr_drbg); +#else ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len, (const unsigned char *)passwd, passwd ? strlen(passwd) : 0); +#endif if(ret) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); @@ -426,10 +463,12 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: +#if MBEDTLS_VERSION_NUMBER < 0x03000000 mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Set min SSL version to TLS 1.0"); break; +#endif case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: @@ -629,10 +668,15 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, if(pinnedpubkey) { int size; CURLcode result; - mbedtls_x509_crt *p; - unsigned char pubkey[PUB_DER_MAX_BYTES]; + mbedtls_x509_crt *p = NULL; + unsigned char *pubkey = NULL; +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + if(!peercert || !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p) || + !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) { +#else if(!peercert || !peercert->raw.p || !peercert->raw.len) { +#endif failf(data, "Failed due to missing peer certificate"); return CURLE_SSL_PINNEDPUBKEYNOTMATCH; } @@ -642,39 +686,54 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, if(!p) return CURLE_OUT_OF_MEMORY; + pubkey = malloc(PUB_DER_MAX_BYTES); + + if(!pubkey) { + result = CURLE_OUT_OF_MEMORY; + goto pinnedpubkey_error; + } + mbedtls_x509_crt_init(p); /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der needs a non-const key, for now. https://github.com/ARMmbed/mbedtls/issues/396 */ +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + if(mbedtls_x509_crt_parse_der(p, + peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p), + peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len))) { +#else if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { +#endif failf(data, "Failed copying peer certificate"); - mbedtls_x509_crt_free(p); - free(p); - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + goto pinnedpubkey_error; } +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + size = mbedtls_pk_write_pubkey_der(&p->MBEDTLS_PRIVATE(pk), pubkey, + PUB_DER_MAX_BYTES); +#else size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); +#endif if(size <= 0) { failf(data, "Failed copying public key from peer certificate"); - mbedtls_x509_crt_free(p); - free(p); - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + goto pinnedpubkey_error; } /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ result = Curl_pin_peer_pubkey(data, pinnedpubkey, &pubkey[PUB_DER_MAX_BYTES - size], size); + pinnedpubkey_error: + mbedtls_x509_crt_free(p); + free(p); + free(pubkey); if(result) { - mbedtls_x509_crt_free(p); - free(p); return result; } - - mbedtls_x509_crt_free(p); - free(p); } #ifdef HAS_ALPN @@ -725,6 +784,7 @@ mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn, mbedtls_ssl_session *our_ssl_sessionid; void *old_ssl_sessionid = NULL; bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE; + bool added = FALSE; our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session)); if(!our_ssl_sessionid) @@ -748,11 +808,13 @@ mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn, Curl_ssl_delsessionid(data, old_ssl_sessionid); retcode = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid, - 0, sockindex); + 0, sockindex, &added); Curl_ssl_sessionid_unlock(data); - if(retcode) { + if(!added) { mbedtls_ssl_session_free(our_ssl_sessionid); free(our_ssl_sessionid); + } + if(retcode) { failf(data, "failed to store ssl session"); return retcode; } @@ -1064,12 +1126,17 @@ static CURLcode mbedtls_sha256sum(const unsigned char *input, unsigned char *sha256sum, size_t sha256len UNUSED_PARAM) { + /* TODO: explain this for different mbedtls 2.x vs 3 version */ (void)sha256len; #if MBEDTLS_VERSION_NUMBER < 0x02070000 mbedtls_sha256(input, inputlen, sha256sum, 0); #else /* returns 0 on success, otherwise failure */ +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0) +#else if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0) +#endif return CURLE_BAD_FUNCTION_ARGUMENT; #endif return CURLE_OK; diff --git a/libs/libcurl/src/vtls/mbedtls_threadlock.c b/libs/libcurl/src/vtls/mbedtls_threadlock.c index 473f5171e2..751755c239 100644 --- a/libs/libcurl/src/vtls/mbedtls_threadlock.c +++ b/libs/libcurl/src/vtls/mbedtls_threadlock.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2013 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2013 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> * * This software is licensed as described in the file COPYING, which @@ -55,10 +55,8 @@ int Curl_mbedtlsthreadlock_thread_setup(void) return 0; /* error, no number of threads defined */ for(i = 0; i < NUMT; i++) { - int ret; #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - ret = pthread_mutex_init(&mutex_buf[i], NULL); - if(ret) + if(pthread_mutex_init(&mutex_buf[i], NULL)) return 0; /* pthread_mutex_init failed */ #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) mutex_buf[i] = CreateMutex(0, FALSE, 0); @@ -78,14 +76,11 @@ int Curl_mbedtlsthreadlock_thread_cleanup(void) return 0; /* error, no threads locks defined */ for(i = 0; i < NUMT; i++) { - int ret; #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - ret = pthread_mutex_destroy(&mutex_buf[i]); - if(ret) + if(pthread_mutex_destroy(&mutex_buf[i])) return 0; /* pthread_mutex_destroy failed */ #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) - ret = CloseHandle(mutex_buf[i]); - if(!ret) + if(!CloseHandle(mutex_buf[i])) return 0; /* CloseHandle failed */ #endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ } @@ -98,17 +93,14 @@ int Curl_mbedtlsthreadlock_thread_cleanup(void) int Curl_mbedtlsthreadlock_lock_function(int n) { if(n < NUMT) { - int ret; #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - ret = pthread_mutex_lock(&mutex_buf[n]); - if(ret) { + if(pthread_mutex_lock(&mutex_buf[n])) { DEBUGF(fprintf(stderr, "Error: mbedtlsthreadlock_lock_function failed\n")); return 0; /* pthread_mutex_lock failed */ } #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) - ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0); - if(ret) { + if(WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED) { DEBUGF(fprintf(stderr, "Error: mbedtlsthreadlock_lock_function failed\n")); return 0; /* pthread_mutex_lock failed */ @@ -121,17 +113,14 @@ int Curl_mbedtlsthreadlock_lock_function(int n) int Curl_mbedtlsthreadlock_unlock_function(int n) { if(n < NUMT) { - int ret; #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - ret = pthread_mutex_unlock(&mutex_buf[n]); - if(ret) { + if(pthread_mutex_unlock(&mutex_buf[n])) { DEBUGF(fprintf(stderr, "Error: mbedtlsthreadlock_unlock_function failed\n")); return 0; /* pthread_mutex_unlock failed */ } #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) - ret = ReleaseMutex(mutex_buf[n]); - if(!ret) { + if(!ReleaseMutex(mutex_buf[n])) { DEBUGF(fprintf(stderr, "Error: mbedtlsthreadlock_unlock_function failed\n")); return 0; /* pthread_mutex_lock failed */ diff --git a/libs/libcurl/src/vtls/mesalink.c b/libs/libcurl/src/vtls/mesalink.c index 3db9184f79..0a1dea3ac0 100644 --- a/libs/libcurl/src/vtls/mesalink.c +++ b/libs/libcurl/src/vtls/mesalink.c @@ -365,7 +365,7 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex) if(!incache) { result = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid, 0, - sockindex); + sockindex, NULL); if(result) { Curl_ssl_sessionid_unlock(data); failf(data, "failed to store ssl session"); diff --git a/libs/libcurl/src/vtls/nss.c b/libs/libcurl/src/vtls/nss.c index cf657895f6..1897b9ab1d 100644 --- a/libs/libcurl/src/vtls/nss.c +++ b/libs/libcurl/src/vtls/nss.c @@ -955,7 +955,7 @@ static void display_cert_info(struct Curl_easy *data, subject = CERT_NameToAscii(&cert->subject); issuer = CERT_NameToAscii(&cert->issuer); common_name = CERT_GetCommonName(&cert->subject); - infof(data, "subject: %s\n", subject); + infof(data, "subject: %s", subject); CERT_GetCertTimes(cert, ¬Before, ¬After); PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime); @@ -2250,10 +2250,11 @@ static CURLcode nss_connect_common(struct Curl_easy *data, case CURLE_OK: break; case CURLE_AGAIN: + /* CURLE_AGAIN in non-blocking mode is not an error */ if(!blocking) - /* CURLE_AGAIN in non-blocking mode is not an error */ return CURLE_OK; - /* FALLTHROUGH */ + else + return result; default: return result; } diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c index 8af23b783a..a1baef9c3f 100644 --- a/libs/libcurl/src/vtls/openssl.c +++ b/libs/libcurl/src/vtls/openssl.c @@ -194,7 +194,7 @@ !defined(OPENSSL_IS_BORINGSSL)) #define HAVE_SSL_CTX_SET_CIPHERSUITES #define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH -/* SET_EC_CURVES available under the same preconditions: see +/* SET_EC_CURVES is available under the same preconditions: see * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html */ #define HAVE_SSL_CTX_SET_EC_CURVES @@ -209,8 +209,8 @@ #endif #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) -/* up2date versions of OpenSSL maintain the default reasonably secure without - * breaking compatibility, so it is better not to override the default by curl +/* up2date versions of OpenSSL maintain reasonably secure defaults without + * breaking compatibility, so it is better not to override the defaults in curl */ #define DEFAULT_CIPHER_SELECTION NULL #else @@ -227,6 +227,10 @@ #endif #endif +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +#define HAVE_RANDOM_INIT_BY_DEFAULT 1 +#endif + struct ssl_backend_data { struct Curl_easy *logger; /* transfer handle to pass trace logs to, only using sockindex 0 */ @@ -435,18 +439,21 @@ static bool rand_enough(void) static CURLcode ossl_seed(struct Curl_easy *data) { - char fname[256]; - /* This might get called before it has been added to a multi handle */ if(data->multi && data->multi->ssl_seeded) return CURLE_OK; if(rand_enough()) { - /* OpenSSL 1.1.0+ will return here */ + /* OpenSSL 1.1.0+ should return here */ if(data->multi) data->multi->ssl_seeded = TRUE; return CURLE_OK; } +#ifdef HAVE_RANDOM_INIT_BY_DEFAULT + /* with OpenSSL 1.1.0+, a failed RAND_status is a showstopper */ + failf(data, "Insufficient randomness"); + return CURLE_SSL_CONNECT_ERROR; +#else #ifndef RANDOM_FILE /* if RANDOM_FILE isn't defined, we only perform this if an option tells @@ -507,19 +514,23 @@ static CURLcode ossl_seed(struct Curl_easy *data) RAND_add(randb, (int)len, (double)len/2); } while(!rand_enough()); - /* generates a default path for the random seed file */ - fname[0] = 0; /* blank it first */ - RAND_file_name(fname, sizeof(fname)); - if(fname[0]) { - /* we got a file name to try */ - RAND_load_file(fname, RAND_LOAD_LENGTH); - if(rand_enough()) - return CURLE_OK; + { + /* generates a default path for the random seed file */ + char fname[256]; + fname[0] = 0; /* blank it first */ + RAND_file_name(fname, sizeof(fname)); + if(fname[0]) { + /* we got a file name to try */ + RAND_load_file(fname, RAND_LOAD_LENGTH); + if(rand_enough()) + return CURLE_OK; + } } infof(data, "libcurl is now using a weak random seed!"); return (rand_enough() ? CURLE_OK : - CURLE_SSL_CONNECT_ERROR /* confusing error code */); + CURLE_SSL_CONNECT_ERROR /* confusing error code */); +#endif } #ifndef SSL_FILETYPE_ENGINE @@ -1192,7 +1203,7 @@ static int ossl_init(void) CONF_MFLAGS_IGNORE_MISSING_FILE); #endif - /* Lets get nice error messages */ + /* Let's get nice error messages */ SSL_load_error_strings(); /* Init the global ciphers and digests */ @@ -1769,7 +1780,7 @@ static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn, /* we have the name entry and we will now convert this to a string that we can use for comparison. Doing this we support BMPstring, - UTF8 etc. */ + UTF8, etc. */ if(i >= 0) { ASN1_STRING *tmp = @@ -2060,6 +2071,10 @@ static const char *ssl_msg_type(int ssl_ver, int msg) case SSL3_MT_ENCRYPTED_EXTENSIONS: return "Encrypted Extensions"; #endif +#ifdef SSL3_MT_SUPPLEMENTAL_DATA + case SSL3_MT_SUPPLEMENTAL_DATA: + return "Supplemental data"; +#endif #ifdef SSL3_MT_END_OF_EARLY_DATA case SSL3_MT_END_OF_EARLY_DATA: return "End of early data"; @@ -2158,7 +2173,7 @@ static void ossl_trace(int direction, int ssl_ver, int content_type, /* Log progress for interesting records only (like Handshake or Alert), skip * all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0). - * For TLS 1.3, skip notification of the decrypted inner Content Type. + * For TLS 1.3, skip notification of the decrypted inner Content-Type. */ if(ssl_ver #ifdef SSL3_RT_INNER_CONTENT_TYPE @@ -2299,7 +2314,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn) long curl_ssl_version_min = SSL_CONN_CONFIG(version); long curl_ssl_version_max; - /* convert cURL min SSL version option to OpenSSL constant */ + /* convert curl min SSL version option to OpenSSL constant */ #if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER) uint16_t ossl_ssl_version_min = 0; uint16_t ossl_ssl_version_max = 0; @@ -2329,7 +2344,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn) We don't want to pass 0 to SSL_CTX_set_min_proto_version as it would enable all versions down to the lowest supported by the library. - So we skip this, and stay with the OS default + So we skip this, and stay with the library default */ if(curl_ssl_version_min != CURL_SSLVERSION_DEFAULT) { if(!SSL_CTX_set_min_proto_version(ctx, ossl_ssl_version_min)) { @@ -2340,7 +2355,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn) /* ... then, TLS max version */ curl_ssl_version_max = SSL_CONN_CONFIG(version_max); - /* convert cURL max SSL version option to OpenSSL constant */ + /* convert curl max SSL version option to OpenSSL constant */ switch(curl_ssl_version_max) { case CURL_SSLVERSION_MAX_TLSv1_0: ossl_ssl_version_max = TLS1_VERSION; @@ -2489,6 +2504,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) if(SSL_SET_OPTION(primary.sessionid)) { bool incache; + bool added = FALSE; void *old_ssl_sessionid = NULL; Curl_ssl_sessionid_lock(data); @@ -2507,9 +2523,11 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) if(!incache) { if(!Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid, - 0 /* unknown size */, sockindex)) { - /* the session has been put into the session cache */ - res = 1; + 0 /* unknown size */, sockindex, &added)) { + if(added) { + /* the session has been put into the session cache */ + res = 1; + } } else failf(data, "failed to store ssl session"); @@ -2523,7 +2541,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) static CURLcode load_cacert_from_memory(SSL_CTX *ctx, const struct curl_blob *ca_info_blob) { - /* these need freed at the end */ + /* these need to be freed at the end */ BIO *cbio = NULL; STACK_OF(X509_INFO) *inf = NULL; @@ -2658,8 +2676,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } - if(backend->ctx) - SSL_CTX_free(backend->ctx); + DEBUGASSERT(!backend->ctx); backend->ctx = SSL_CTX_new(req_method); if(!backend->ctx) { @@ -2681,23 +2698,23 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, } #endif - /* OpenSSL contains code to work-around lots of bugs and flaws in various + /* OpenSSL contains code to work around lots of bugs and flaws in various SSL-implementations. SSL_CTX_set_options() is used to enabled those work-arounds. The man page for this option states that SSL_OP_ALL enables all the work-arounds and that "It is usually safe to use SSL_OP_ALL to enable the bug workaround options if compatibility with somewhat broken implementations is desired." - The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to + The "-no_ticket" option was introduced in OpenSSL 0.9.8j. It's a flag to disable "rfc4507bis session ticket support". rfc4507bis was later turned into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077 The enabled extension concerns the session management. I wonder how often - libcurl stops a connection and then resumes a TLS session. also, sending - the session data is some overhead. .I suggest that you just use your + libcurl stops a connection and then resumes a TLS session. Also, sending + the session data is some overhead. I suggest that you just use your proposed patch (which explicitly disables TICKET). - If someone writes an application with libcurl and openssl who wants to + If someone writes an application with libcurl and OpenSSL who wants to enable the feature, one can do this in the SSL callback. SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper @@ -2733,7 +2750,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS - /* unless the user explicitly ask to allow the protocol vulnerability we + /* unless the user explicitly asks to allow the protocol vulnerability we use the work-around */ if(!SSL_SET_OPTION(enable_beast)) ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; @@ -2933,7 +2950,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, NULL, cert_name, sizeof(cert_name))) { strcpy(cert_name, "Unknown"); } - infof(data, "SSL: Checking cert %s\"\n", cert_name); + infof(data, "SSL: Checking cert \"%s\"", cert_name); #endif encoded_cert = (const unsigned char *)pContext->pbCertEncoded; @@ -3030,9 +3047,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, return result; } if(imported_native_ca) - infof(data, "successfully imported windows ca store"); + infof(data, "successfully imported Windows CA store"); else - infof(data, "error importing windows ca store, continuing anyway"); + infof(data, "error importing Windows CA store, continuing anyway"); } #endif @@ -3044,77 +3061,53 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, failf(data, "error importing CA certificate blob"); return result; } - /* Only warning if no certificate verification is required. */ + /* Only warn if no certificate verification is required. */ infof(data, "error importing CA certificate blob, continuing anyway"); } } + if(verifypeer && !imported_native_ca && (ssl_cafile || ssl_capath)) { #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */ - { - if(ssl_cafile) { - if(!SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) { - if(verifypeer && !imported_native_ca) { - /* Fail if we insist on successfully verifying the server. */ - failf(data, "error setting certificate file: %s", ssl_cafile); - return CURLE_SSL_CACERT_BADFILE; - } - /* Continue with a warning if no certificate verif is required. */ - infof(data, "error setting certificate file, continuing anyway"); - } - infof(data, " CAfile: %s", ssl_cafile); + if(ssl_cafile && + !SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate file: %s", ssl_cafile); + return CURLE_SSL_CACERT_BADFILE; } - if(ssl_capath) { - if(!SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) { - if(verifypeer && !imported_native_ca) { - /* Fail if we insist on successfully verifying the server. */ - failf(data, "error setting certificate path: %s", ssl_capath); - return CURLE_SSL_CACERT_BADFILE; - } - /* Continue with a warning if no certificate verif is required. */ - infof(data, "error setting certificate path, continuing anyway"); - } - infof(data, " CApath: %s", ssl_capath); + if(ssl_capath && + !SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate path: %s", ssl_capath); + return CURLE_SSL_CACERT_BADFILE; } - } #else - if(ssl_cafile || ssl_capath) { - /* tell SSL where to find CA certificates that are used to verify - the servers certificate. */ + /* tell OpenSSL where to find CA certificates that are used to verify the + server's certificate. */ if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) { - if(verifypeer && !imported_native_ca) { - /* Fail if we insist on successfully verifying the server. */ - failf(data, "error setting certificate verify locations:" - " CAfile: %s CApath: %s", - ssl_cafile ? ssl_cafile : "none", - ssl_capath ? ssl_capath : "none"); - return CURLE_SSL_CACERT_BADFILE; - } - /* Just continue with a warning if no strict certificate verification - is required. */ - infof(data, "error setting certificate verify locations," - " continuing anyway:"); - } - else { - /* Everything is fine. */ - infof(data, "successfully set certificate verify locations:"); + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate verify locations:" + " CAfile: %s CApath: %s", + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); + return CURLE_SSL_CACERT_BADFILE; } +#endif infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none"); infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none"); } -#endif #ifdef CURL_CA_FALLBACK if(verifypeer && !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) { /* verifying the peer without any CA certificates won't - work so use openssl's built in default as fallback */ + work so use openssl's built-in default as fallback */ SSL_CTX_set_default_verify_paths(backend->ctx); } #endif if(ssl_crlfile) { - /* tell SSL where to find CRL file that is used to check certificate + /* tell OpenSSL where to find CRL file that is used to check certificate * revocation */ lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx), X509_LOOKUP_file()); @@ -3124,7 +3117,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, return CURLE_SSL_CRL_BADFILE; } /* Everything is fine. */ - infof(data, "successfully load CRL file:"); + infof(data, "successfully loaded CRL file:"); X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); @@ -3150,7 +3143,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, only, instead of needing the whole chain. Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we - cannot do partial chains with CRL check. + cannot do partial chains with a CRL check. */ X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx), X509_V_FLAG_PARTIAL_CHAIN); @@ -3158,7 +3151,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif } - /* SSL always tries to verify the peer, this only says whether it should + /* OpenSSL always tries to verify the peer, this only says whether it should * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ @@ -3173,7 +3166,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif /* Enable the session cache because it's a prerequisite for the "new session" - * callback. Use the "external storage" mode to avoid that OpenSSL creates + * callback. Use the "external storage" mode to prevent OpenSSL from creating * an internal session cache. */ SSL_CTX_set_session_cache_mode(backend->ctx, @@ -3192,7 +3185,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, } } - /* Lets make an SSL structure */ + /* Let's make an SSL structure */ if(backend->handle) SSL_free(backend->handle); backend->handle = SSL_new(backend->ctx); @@ -3332,7 +3325,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, /* the connection failed, we're not waiting for anything else. */ connssl->connecting_state = ssl_connect_2; - /* Get the earliest error code from the thread's error queue and removes + /* Get the earliest error code from the thread's error queue and remove the entry. */ errdetail = ERR_get_error(); @@ -3361,7 +3354,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, !defined(LIBRESSL_VERSION_NUMBER) && \ !defined(OPENSSL_IS_BORINGSSL)) /* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on - OpenSSL version above v1.1.1, not Libre SSL nor BoringSSL */ + OpenSSL version above v1.1.1, not LibreSSL nor BoringSSL */ else if((lib == ERR_LIB_SSL) && (reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) { /* If client certificate is required, communicate the @@ -3378,7 +3371,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, /* detail is already set to the SSL error above */ /* If we e.g. use SSLv2 request-method and the server doesn't like us - * (RST connection etc.), OpenSSL gives no explanation whatsoever and + * (RST connection, etc.), OpenSSL gives no explanation whatsoever and * the SO_ERROR is also lost. */ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { @@ -3401,7 +3394,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, } } else { - /* we have been connected fine, we're not waiting for anything else. */ + /* we connected fine, we're not waiting for anything else. */ connssl->connecting_state = ssl_connect_3; /* Informational message */ @@ -3820,7 +3813,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, } /* - * Get the server cert, verify it and show it etc, only call failf() if the + * 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 * purposes only! * @@ -4021,7 +4014,7 @@ static CURLcode ossl_connect_step3(struct Curl_easy *data, /* * We check certificates to authenticate the server; otherwise we risk * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to - * verify the peer ignore faults and failures from the server cert + * verify the peer, ignore faults and failures from the server cert * operations. */ @@ -4059,7 +4052,7 @@ static CURLcode ossl_connect_common(struct Curl_easy *data, const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); if(timeout_ms < 0) { - /* no need to continue if time already is up */ + /* no need to continue if time is already up */ failf(data, "SSL connection timeout"); return CURLE_OPERATION_TIMEDOUT; } diff --git a/libs/libcurl/src/vtls/rustls.c b/libs/libcurl/src/vtls/rustls.c index 94a1ca8861..2ac97ce28e 100644 --- a/libs/libcurl/src/vtls/rustls.c +++ b/libs/libcurl/src/vtls/rustls.c @@ -34,7 +34,7 @@ #include "sendf.h" #include "vtls.h" #include "select.h" - +#include "strerror.h" #include "multiif.h" struct ssl_backend_data @@ -132,7 +132,9 @@ cr_recv(struct Curl_easy *data, int sockindex, infof(data, "sread: EAGAIN or EWOULDBLOCK"); } else if(io_error) { - failf(data, "reading from socket: %s", strerror(io_error)); + char buffer[STRERROR_LEN]; + failf(data, "reading from socket: %s", + Curl_strerror(io_error, buffer, sizeof(buffer))); *err = CURLE_READ_ERROR; return -1; } @@ -244,7 +246,9 @@ cr_send(struct Curl_easy *data, int sockindex, return -1; } else if(io_error) { - failf(data, "writing to socket: %s", strerror(io_error)); + char buffer[STRERROR_LEN]; + failf(data, "writing to socket: %s", + Curl_strerror(io_error, buffer, sizeof(buffer))); *err = CURLE_WRITE_ERROR; return -1; } diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c index 7ffba6cc19..44c59e7796 100644 --- a/libs/libcurl/src/vtls/schannel.c +++ b/libs/libcurl/src/vtls/schannel.c @@ -141,6 +141,12 @@ # define CALG_SHA_256 0x0000800c #endif +/* Work around typo in classic MinGW's w32api up to version 5.0, + see https://osdn.net/projects/mingw/ticket/38391 */ +#if !defined(ALG_CLASS_DHASH) && defined(ALG_CLASS_HASH) +#define ALG_CLASS_DHASH ALG_CLASS_HASH +#endif + #define BACKEND connssl->backend static Curl_recv schannel_recv; @@ -279,13 +285,7 @@ get_alg_id_by_name(char *name) #ifdef CALG_HMAC CIPHEROPTION(CALG_HMAC); #endif -#if !defined(__W32API_MAJOR_VERSION) || \ - !defined(__W32API_MINOR_VERSION) || \ - defined(__MINGW64_VERSION_MAJOR) || \ - (__W32API_MAJOR_VERSION > 5) || \ - ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0)) - /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0, - see https://osdn.net/projects/mingw/ticket/38391 */ +#ifdef CALG_TLS1PRF CIPHEROPTION(CALG_TLS1PRF); #endif #ifdef CALG_HASH_REPLACE_OWF @@ -716,8 +716,6 @@ schannel_acquire_credential_handle(struct Curl_easy *data, } BACKEND->cred->refcount = 1; - /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx - */ sspi_status = s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, @@ -1141,8 +1139,6 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, if(!host_name) return CURLE_OUT_OF_MEMORY; - /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx - */ sspi_status = s_pSecFn->InitializeSecurityContext( &BACKEND->cred->cred_handle, &BACKEND->ctxt->ctxt_handle, host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL, @@ -1364,7 +1360,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; bool isproxy = SSL_IS_PROXY(); -#ifdef DEBUGBUILD +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) const char * const hostname = SSL_HOST_NAME(); #endif #ifdef HAS_ALPN @@ -1436,6 +1432,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, /* save the current session data for possible re-use */ if(SSL_SET_OPTION(primary.sessionid)) { bool incache; + bool added = FALSE; struct Curl_schannel_cred *old_cred = NULL; Curl_ssl_sessionid_lock(data); @@ -1453,13 +1450,13 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, if(!incache) { result = Curl_ssl_addsessionid(data, conn, isproxy, BACKEND->cred, sizeof(struct Curl_schannel_cred), - sockindex); + sockindex, &added); if(result) { Curl_ssl_sessionid_unlock(data); failf(data, "schannel: failed to store credential handle"); return result; } - else { + else if(added) { /* this cred session is now also referenced by sessionid cache */ BACKEND->cred->refcount++; DEBUGF(infof(data, @@ -1970,12 +1967,12 @@ schannel_recv(struct Curl_easy *data, int sockindex, if(sspi_status == SEC_I_RENEGOTIATE) { infof(data, "schannel: remote party requests renegotiation"); if(*err && *err != CURLE_AGAIN) { - infof(data, "schannel: can't renogotiate, an error is pending"); + infof(data, "schannel: can't renegotiate, an error is pending"); goto cleanup; } if(BACKEND->encdata_offset) { *err = CURLE_RECV_ERROR; - infof(data, "schannel: can't renogotiate, " + infof(data, "schannel: can't renegotiate, " "encrypted data available"); goto cleanup; } @@ -2124,26 +2121,23 @@ static bool schannel_data_pending(const struct connectdata *conn, return FALSE; } -static void schannel_close(struct Curl_easy *data, struct connectdata *conn, - int sockindex) -{ - if(conn->ssl[sockindex].use) - /* if the SSL/TLS channel hasn't been shut down yet, do that now. */ - Curl_ssl_shutdown(data, conn, sockindex); -} - static void schannel_session_free(void *ptr) { /* this is expected to be called under sessionid lock */ struct Curl_schannel_cred *cred = ptr; - cred->refcount--; - if(cred->refcount == 0) { - s_pSecFn->FreeCredentialsHandle(&cred->cred_handle); - Curl_safefree(cred); + if(cred) { + cred->refcount--; + if(cred->refcount == 0) { + s_pSecFn->FreeCredentialsHandle(&cred->cred_handle); + Curl_safefree(cred); + } } } +/* shut down the SSL connection and clean up related memory. + this function can be called multiple times on the same connection including + if the SSL connection failed (eg connection made but failed handshake). */ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn, int sockindex) { @@ -2155,10 +2149,12 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn, DEBUGASSERT(data); - infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu", - hostname, conn->remote_port); + if(connssl->use) { + infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu", + hostname, conn->remote_port); + } - if(BACKEND->cred && BACKEND->ctxt) { + if(connssl->use && BACKEND->cred && BACKEND->ctxt) { SecBufferDesc BuffDesc; SecBuffer Buffer; SECURITY_STATUS sspi_status; @@ -2251,6 +2247,16 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn, return CURLE_OK; } +static void schannel_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex) +{ + if(conn->ssl[sockindex].use) + /* Curl_ssl_shutdown resets the socket state and calls schannel_shutdown */ + Curl_ssl_shutdown(data, conn, sockindex); + else + schannel_shutdown(data, conn, sockindex); +} + static int schannel_init(void) { return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0); diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c index 12fccaa8ee..1b283d0453 100644 --- a/libs/libcurl/src/vtls/schannel_verify.c +++ b/libs/libcurl/src/vtls/schannel_verify.c @@ -80,7 +80,7 @@ static int is_cr_or_lf(char c) /* Search the substring needle,needlelen into string haystack,haystacklen * Strings don't need to be terminated by a '\0'. * Similar of OSX/Linux memmem (not available on Visual Studio). - * Return position of beginning of first occurence or NULL if not found + * Return position of beginning of first occurrence or NULL if not found */ static const char *c_memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c index 26b833dd2a..0bf515460d 100644 --- a/libs/libcurl/src/vtls/sectransp.c +++ b/libs/libcurl/src/vtls/sectransp.c @@ -33,6 +33,8 @@ #include "strtok.h" #include "multiif.h" #include "strcase.h" +#include "x509asn1.h" +#include "strerror.h" #ifdef USE_SECTRANSP @@ -2107,7 +2109,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, } result = Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid, - ssl_sessionid_len, sockindex); + ssl_sessionid_len, sockindex, NULL); Curl_ssl_sessionid_unlock(data); if(result) { failf(data, "failed to store ssl session"); @@ -2854,13 +2856,60 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, } } +static CURLcode +add_cert_to_certinfo(struct Curl_easy *data, + SecCertificateRef server_cert, + int idx) +{ + CURLcode result = CURLE_OK; + const char *beg; + const char *end; + CFDataRef cert_data = SecCertificateCopyData(server_cert); + + if(!cert_data) + return CURLE_PEER_FAILED_VERIFICATION; + + beg = (const char *)CFDataGetBytePtr(cert_data); + end = beg + CFDataGetLength(cert_data); + result = Curl_extract_certinfo(data, idx, beg, end); + CFRelease(cert_data); + return result; +} + +static CURLcode +collect_server_cert_single(struct Curl_easy *data, + SecCertificateRef server_cert, + CFIndex idx) +{ + CURLcode result = CURLE_OK; #ifndef CURL_DISABLE_VERBOSE_STRINGS + if(data->set.verbose) { + char *certp; + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s", certp); + free(certp); + } + } +#endif + if(data->set.ssl.certinfo) + result = add_cert_to_certinfo(data, server_cert, (int)idx); + return result; +} + /* This should be called during step3 of the connection at the earliest */ -static void -show_verbose_server_cert(struct Curl_easy *data, - struct connectdata *conn, - int sockindex) +static CURLcode +collect_server_cert(struct Curl_easy *data, + struct connectdata *conn, + int sockindex) { +#ifndef CURL_DISABLE_VERBOSE_STRINGS + const bool show_verbose_server_cert = data->set.verbose; +#else + const bool show_verbose_server_cert = false; +#endif + CURLcode result = data->set.ssl.certinfo ? + CURLE_PEER_FAILED_VERIFICATION : CURLE_OK; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; CFArrayRef server_certs = NULL; @@ -2869,8 +2918,11 @@ show_verbose_server_cert(struct Curl_easy *data, CFIndex i, count; SecTrustRef trust = NULL; + if(!show_verbose_server_cert && !data->set.ssl.certinfo) + return CURLE_OK; + if(!backend->ssl_ctx) - return; + return result; #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS #if CURL_BUILD_IOS @@ -2880,15 +2932,11 @@ show_verbose_server_cert(struct Curl_easy *data, a null trust, so be on guard for that: */ if(err == noErr && trust) { count = SecTrustGetCertificateCount(trust); - for(i = 0L ; i < count ; i++) { - CURLcode result; - char *certp; + if(data->set.ssl.certinfo) + result = Curl_ssl_init_certinfo(data, (int)count); + for(i = 0L ; !result && (i < count) ; i++) { server_cert = SecTrustGetCertificateAtIndex(trust, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s", certp); - free(certp); - } + result = collect_server_cert_single(data, server_cert, i); } CFRelease(trust); } @@ -2906,15 +2954,11 @@ show_verbose_server_cert(struct Curl_easy *data, a null trust, so be on guard for that: */ if(err == noErr && trust) { count = SecTrustGetCertificateCount(trust); - for(i = 0L ; i < count ; i++) { - char *certp; - CURLcode result; + if(data->set.ssl.certinfo) + result = Curl_ssl_init_certinfo(data, (int)count); + for(i = 0L ; !result && (i < count) ; i++) { server_cert = SecTrustGetCertificateAtIndex(trust, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s", certp); - free(certp); - } + result = collect_server_cert_single(data, server_cert, i); } CFRelease(trust); } @@ -2925,16 +2969,12 @@ show_verbose_server_cert(struct Curl_easy *data, /* Just in case SSLCopyPeerCertificates() returns null too... */ if(err == noErr && server_certs) { count = CFArrayGetCount(server_certs); - for(i = 0L ; i < count ; i++) { - char *certp; - CURLcode result; + if(data->set.ssl.certinfo) + result = Curl_ssl_init_certinfo(data, (int)count); + for(i = 0L ; !result && (i < count) ; i++) { server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s", certp); - free(certp); - } + result = collect_server_cert_single(data, server_cert, i); } CFRelease(server_certs); } @@ -2946,21 +2986,17 @@ show_verbose_server_cert(struct Curl_easy *data, err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs); if(err == noErr) { count = CFArrayGetCount(server_certs); - for(i = 0L ; i < count ; i++) { - CURLcode result; - char *certp; + if(data->set.ssl.certinfo) + result = Curl_ssl_init_certinfo(data, (int)count); + for(i = 0L ; !result && (i < count) ; i++) { server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s", certp); - free(certp); - } + result = collect_server_cert_single(data, server_cert, i); } CFRelease(server_certs); } #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ + return result; } -#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ static CURLcode sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn, @@ -2969,12 +3005,11 @@ sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; /* There is no step 3! - * Well, okay, if verbose mode is on, let's print the details of the - * server certificates. */ -#ifndef CURL_DISABLE_VERBOSE_STRINGS - if(data->set.verbose) - show_verbose_server_cert(data, conn, sockindex); -#endif + * Well, okay, let's collect server certificates, and if verbose mode is on, + * let's print the details of the server certificates. */ + const CURLcode result = collect_server_cert(data, conn, sockindex); + if(result) + return result; connssl->connecting_state = ssl_connect_done; return CURLE_OK; @@ -3188,7 +3223,9 @@ static int sectransp_shutdown(struct Curl_easy *data, nread = read(conn->sock[sockindex], buf, sizeof(buf)); if(nread < 0) { - failf(data, "read: %s", strerror(errno)); + char buffer[STRERROR_LEN]; + failf(data, "read: %s", + Curl_strerror(errno, buffer, sizeof(buffer))); rc = -1; } @@ -3433,6 +3470,7 @@ const struct Curl_ssl Curl_ssl_sectransp = { { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */ SSLSUPP_CAINFO_BLOB | + SSLSUPP_CERTINFO | #ifdef SECTRANSP_PINNEDPUBKEY SSLSUPP_PINNEDPUBKEY, #else diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c index e5bbe1f5f0..6007bbba0f 100644 --- a/libs/libcurl/src/vtls/vtls.c +++ b/libs/libcurl/src/vtls/vtls.c @@ -516,7 +516,8 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, const bool isProxy, void *ssl_sessionid, size_t idsize, - int sockindex) + int sockindex, + bool *added) { size_t i; struct Curl_ssl_session *store; @@ -536,6 +537,10 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, const char *hostname = conn->host.name; #endif (void)sockindex; + + if(added) + *added = FALSE; + if(!data->state.session) return CURLE_OK; @@ -609,6 +614,9 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } + if(added) + *added = TRUE; + DEBUGF(infof(data, "Added Session ID to cache for %s://%s:%d [%s]", store->scheme, store->name, store->remote_port, isProxy ? "PROXY" : "server")); diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h index beaa83d9e3..c7bbba082d 100644 --- a/libs/libcurl/src/vtls/vtls.h +++ b/libs/libcurl/src/vtls/vtls.h @@ -261,7 +261,8 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, const bool isProxy, void *ssl_sessionid, size_t idsize, - int sockindex); + int sockindex, + bool *added); /* Kill a single session ID entry in the cache * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). * This will call engine-specific curlssl_session_free function, which must diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index 7cab17fb6e..8c5b9157b8 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -202,6 +202,43 @@ static int do_file_type(const char *type) return -1; } +#ifdef HAVE_LIBOQS +struct group_name_map { + const word16 group; + const char *name; +}; + +static const struct group_name_map gnm[] = { + { WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" }, + { WOLFSSL_KYBER_LEVEL3, "KYBER_LEVEL3" }, + { WOLFSSL_KYBER_LEVEL5, "KYBER_LEVEL5" }, + { WOLFSSL_NTRU_HPS_LEVEL1, "NTRU_HPS_LEVEL1" }, + { WOLFSSL_NTRU_HPS_LEVEL3, "NTRU_HPS_LEVEL3" }, + { WOLFSSL_NTRU_HPS_LEVEL5, "NTRU_HPS_LEVEL5" }, + { WOLFSSL_NTRU_HRSS_LEVEL3, "NTRU_HRSS_LEVEL3" }, + { WOLFSSL_SABER_LEVEL1, "SABER_LEVEL1" }, + { WOLFSSL_SABER_LEVEL3, "SABER_LEVEL3" }, + { WOLFSSL_SABER_LEVEL5, "SABER_LEVEL5" }, + { WOLFSSL_KYBER_90S_LEVEL1, "KYBER_90S_LEVEL1" }, + { WOLFSSL_KYBER_90S_LEVEL3, "KYBER_90S_LEVEL3" }, + { WOLFSSL_KYBER_90S_LEVEL5, "KYBER_90S_LEVEL5" }, + { WOLFSSL_P256_NTRU_HPS_LEVEL1, "P256_NTRU_HPS_LEVEL1" }, + { WOLFSSL_P384_NTRU_HPS_LEVEL3, "P384_NTRU_HPS_LEVEL3" }, + { WOLFSSL_P521_NTRU_HPS_LEVEL5, "P521_NTRU_HPS_LEVEL5" }, + { WOLFSSL_P384_NTRU_HRSS_LEVEL3, "P384_NTRU_HRSS_LEVEL3" }, + { WOLFSSL_P256_SABER_LEVEL1, "P256_SABER_LEVEL1" }, + { WOLFSSL_P384_SABER_LEVEL3, "P384_SABER_LEVEL3" }, + { WOLFSSL_P521_SABER_LEVEL5, "P521_SABER_LEVEL5" }, + { WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" }, + { WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" }, + { WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" }, + { WOLFSSL_P256_KYBER_90S_LEVEL1, "P256_KYBER_90S_LEVEL1" }, + { WOLFSSL_P384_KYBER_90S_LEVEL3, "P384_KYBER_90S_LEVEL3" }, + { WOLFSSL_P521_KYBER_90S_LEVEL5, "P521_KYBER_90S_LEVEL5" }, + { 0, NULL } +}; +#endif + /* * This function loads all the client/CA certificates and CRLs. Setup the TLS * layer and do all necessary magic. @@ -210,11 +247,15 @@ static CURLcode wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, int sockindex) { - char *ciphers; + char *ciphers, *curves; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; SSL_METHOD* req_method = NULL; curl_socket_t sockfd = conn->sock[sockindex]; +#ifdef HAVE_LIBOQS + word16 oqsAlg = 0; + size_t idx = 0; +#endif #ifdef HAVE_SNI bool sni = FALSE; #define use_sni(x) sni = (x) @@ -327,6 +368,26 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, infof(data, "Cipher selection: %s", ciphers); } + curves = SSL_CONN_CONFIG(curves); + if(curves) { + +#ifdef HAVE_LIBOQS + for(idx = 0; gnm[idx].name != NULL; idx++) { + if(strncmp(curves, gnm[idx].name, strlen(gnm[idx].name)) == 0) { + oqsAlg = gnm[idx].group; + break; + } + } + + if(oqsAlg == 0) +#endif + { + if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) { + failf(data, "failed setting curves list: '%s'", curves); + return CURLE_SSL_CIPHER; + } + } + } #ifndef NO_FILESYSTEM /* load trusted cacert */ if(SSL_CONN_CONFIG(CAfile)) { @@ -439,6 +500,14 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, return CURLE_OUT_OF_MEMORY; } +#ifdef HAVE_LIBOQS + if(oqsAlg) { + if(wolfSSL_UseKeyShare(backend->handle, oqsAlg) != WOLFSSL_SUCCESS) { + failf(data, "unable to use oqs KEM"); + } + } +#endif + #ifdef HAVE_ALPN if(conn->bits.tls_enable_alpn) { char protocols[128]; @@ -495,7 +564,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, /* we got a session id, use it! */ if(!SSL_set_session(backend->handle, ssl_sessionid)) { Curl_ssl_delsessionid(data, ssl_sessionid); - infof(data, "Can't use session ID, going on without\n"); + infof(data, "Can't use session ID, going on without"); } else infof(data, "SSL re-using session ID"); @@ -525,6 +594,8 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, const char * const dispname = SSL_HOST_DISPNAME(); const char * const pinnedpubkey = SSL_PINNED_PUB_KEY(); + ERR_clear_error(); + conn->recv[sockindex] = wolfssl_recv; conn->send[sockindex] = wolfssl_send; @@ -747,7 +818,7 @@ wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn, if(!incache) { result = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid, - 0, sockindex); + 0, sockindex, NULL); if(result) { Curl_ssl_sessionid_unlock(data); failf(data, "failed to store ssl session"); @@ -775,7 +846,11 @@ static ssize_t wolfssl_send(struct Curl_easy *data, struct ssl_backend_data *backend = connssl->backend; char error_buffer[WOLFSSL_MAX_ERROR_SZ]; int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; - int rc = SSL_write(backend->handle, mem, memlen); + int rc; + + ERR_clear_error(); + + rc = SSL_write(backend->handle, mem, memlen); if(rc <= 0) { int err = SSL_get_error(backend->handle, rc); @@ -831,7 +906,11 @@ static ssize_t wolfssl_recv(struct Curl_easy *data, struct ssl_backend_data *backend = connssl->backend; char error_buffer[WOLFSSL_MAX_ERROR_SZ]; int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; - int nread = SSL_read(backend->handle, buf, buffsize); + int nread; + + ERR_clear_error(); + + nread = SSL_read(backend->handle, buf, buffsize); if(nread < 0) { int err = SSL_get_error(backend->handle, nread); @@ -916,6 +995,7 @@ static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn, (void) data; if(backend->handle) { + ERR_clear_error(); SSL_free(backend->handle); backend->handle = NULL; } diff --git a/libs/libcurl/src/x509asn1.c b/libs/libcurl/src/x509asn1.c index c70378daca..1bdaeadc80 100644 --- a/libs/libcurl/src/x509asn1.c +++ b/libs/libcurl/src/x509asn1.c @@ -23,7 +23,7 @@ #include "curl_setup.h" #if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ - defined(USE_WOLFSSL) || defined(USE_SCHANNEL) + defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) #include <curl/curl.h> #include "urldata.h" @@ -34,6 +34,7 @@ #include "inet_pton.h" #include "curl_base64.h" #include "x509asn1.h" +#include "dynbuf.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -205,16 +206,16 @@ static const char *bool2str(const char *beg, const char *end) */ static const char *octet2str(const char *beg, const char *end) { - size_t n = end - beg; - char *buf = NULL; + struct dynbuf buf; + CURLcode result; - if(n <= (SIZE_T_MAX - 1) / 3) { - buf = malloc(3 * n + 1); - if(buf) - for(n = 0; beg < end; n += 3) - msnprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++); - } - return buf; + Curl_dyn_init(&buf, 3 * CURL_ASN1_MAX + 1); + result = Curl_dyn_addn(&buf, "", 0); + + while(!result && beg < end) + result = Curl_dyn_addf(&buf, "%02x:", (unsigned char) *beg++); + + return Curl_dyn_ptr(&buf); } static const char *bit2str(const char *beg, const char *end) @@ -1103,7 +1104,8 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, return CURLE_OK; } -#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */ +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL + * or USE_SECTRANSP */ #if defined(USE_GSKIT) diff --git a/libs/libcurl/src/x509asn1.h b/libs/libcurl/src/x509asn1.h index 326e32d588..3b51eeef8d 100644 --- a/libs/libcurl/src/x509asn1.h +++ b/libs/libcurl/src/x509asn1.h @@ -26,7 +26,7 @@ #include "curl_setup.h" #if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ - defined(USE_WOLFSSL) || defined(USE_SCHANNEL) + defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) #include "urldata.h" @@ -129,5 +129,6 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum, const char *beg, const char *end); CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn, const char *beg, const char *end); -#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */ +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL + * or USE_SECTRANSP */ #endif /* HEADER_CURL_X509ASN1_H */ |