From 2f0eaffffe7e5d3ac074797f880480494dbcc6f3 Mon Sep 17 00:00:00 2001 From: dartraiden Date: Sun, 7 Feb 2021 18:49:47 +0300 Subject: libcurl: update to 7.75.0 --- libs/libcurl/docs/CHANGES | 10055 ++++++++++++++-------------- libs/libcurl/docs/COPYING | 2 +- libs/libcurl/docs/THANKS | 30 + libs/libcurl/include/curl/curl.h | 14 +- libs/libcurl/include/curl/curlver.h | 8 +- libs/libcurl/include/curl/typecheck-gcc.h | 1 + libs/libcurl/libcurl.vcxproj | 8 + libs/libcurl/libcurl.vcxproj.filters | 12 + libs/libcurl/src/Makefile.in | 733 +- libs/libcurl/src/Makefile.inc | 351 +- libs/libcurl/src/asyn-ares.c | 144 +- libs/libcurl/src/asyn-thread.c | 148 +- libs/libcurl/src/asyn.h | 14 +- libs/libcurl/src/c-hyper.c | 908 +++ libs/libcurl/src/c-hyper.h | 56 + libs/libcurl/src/config-win32.h | 7 - libs/libcurl/src/conncache.c | 43 +- libs/libcurl/src/conncache.h | 42 +- libs/libcurl/src/connect.c | 236 +- libs/libcurl/src/connect.h | 25 +- libs/libcurl/src/content_encoding.c | 172 +- libs/libcurl/src/content_encoding.h | 14 +- libs/libcurl/src/cookie.c | 9 + libs/libcurl/src/cookie.h | 6 +- libs/libcurl/src/curl_addrinfo.c | 4 +- libs/libcurl/src/curl_config.h.cmake | 6 +- libs/libcurl/src/curl_config.h.in | 6 + libs/libcurl/src/curl_gssapi.c | 6 +- libs/libcurl/src/curl_krb5.h | 8 +- libs/libcurl/src/curl_ntlm_wb.c | 29 +- libs/libcurl/src/curl_ntlm_wb.h | 8 +- libs/libcurl/src/curl_path.c | 9 +- libs/libcurl/src/curl_path.h | 4 +- libs/libcurl/src/curl_range.c | 5 +- libs/libcurl/src/curl_range.h | 5 +- libs/libcurl/src/curl_rtmp.c | 48 +- libs/libcurl/src/curl_sasl.c | 36 +- libs/libcurl/src/curl_sasl.h | 14 +- libs/libcurl/src/curl_sha256.h | 3 + libs/libcurl/src/dict.c | 19 +- libs/libcurl/src/doh.c | 96 +- libs/libcurl/src/doh.h | 6 +- libs/libcurl/src/easy.c | 46 +- libs/libcurl/src/easyoptions.c | 5 +- libs/libcurl/src/file.c | 93 +- libs/libcurl/src/formdata.h | 10 +- libs/libcurl/src/ftp.c | 918 +-- libs/libcurl/src/ftp.h | 14 +- libs/libcurl/src/ftplistparser.c | 30 +- libs/libcurl/src/getinfo.c | 2 + libs/libcurl/src/gopher.c | 69 +- libs/libcurl/src/gopher.h | 3 + libs/libcurl/src/hash.c | 2 +- libs/libcurl/src/hostasyn.c | 20 +- libs/libcurl/src/hostip.c | 110 +- libs/libcurl/src/hostip.h | 25 +- libs/libcurl/src/hostip4.c | 11 +- libs/libcurl/src/hostip6.c | 30 +- libs/libcurl/src/hsts.c | 6 +- libs/libcurl/src/http.c | 2814 ++++---- libs/libcurl/src/http.h | 88 +- libs/libcurl/src/http2.c | 217 +- libs/libcurl/src/http2.h | 15 +- libs/libcurl/src/http_aws_sigv4.c | 394 ++ libs/libcurl/src/http_aws_sigv4.h | 29 + libs/libcurl/src/http_chunks.c | 43 +- libs/libcurl/src/http_chunks.h | 21 +- libs/libcurl/src/http_digest.c | 10 +- libs/libcurl/src/http_digest.h | 7 +- libs/libcurl/src/http_negotiate.c | 23 +- libs/libcurl/src/http_negotiate.h | 9 +- libs/libcurl/src/http_ntlm.c | 34 +- libs/libcurl/src/http_ntlm.h | 6 +- libs/libcurl/src/http_proxy.c | 386 +- libs/libcurl/src/http_proxy.h | 6 +- libs/libcurl/src/imap.c | 458 +- libs/libcurl/src/krb5.c | 106 +- libs/libcurl/src/ldap.c | 78 +- libs/libcurl/src/libcurl.plist | 6 +- libs/libcurl/src/makefile.dj | 4 +- libs/libcurl/src/mime.c | 3 +- libs/libcurl/src/mime.h | 4 +- libs/libcurl/src/mk-ca-bundle.pl | 4 +- libs/libcurl/src/mqtt.c | 153 +- libs/libcurl/src/multi.c | 217 +- libs/libcurl/src/multihandle.h | 8 +- libs/libcurl/src/multiif.h | 4 +- libs/libcurl/src/openldap.c | 92 +- libs/libcurl/src/pingpong.c | 66 +- libs/libcurl/src/pingpong.h | 42 +- libs/libcurl/src/pop3.c | 357 +- libs/libcurl/src/pop3.h | 6 +- libs/libcurl/src/progress.c | 20 +- libs/libcurl/src/progress.h | 6 +- libs/libcurl/src/quic.h | 15 +- libs/libcurl/src/rtsp.c | 107 +- libs/libcurl/src/rtsp.h | 8 +- libs/libcurl/src/select.c | 17 +- libs/libcurl/src/select.h | 8 +- libs/libcurl/src/sendf.c | 79 +- libs/libcurl/src/sendf.h | 15 +- libs/libcurl/src/setopt.c | 43 +- libs/libcurl/src/sha256.c | 33 +- libs/libcurl/src/share.c | 9 +- libs/libcurl/src/share.h | 6 +- libs/libcurl/src/smb.c | 261 +- libs/libcurl/src/smtp.c | 391 +- libs/libcurl/src/smtp.h | 6 +- libs/libcurl/src/socks.c | 134 +- libs/libcurl/src/socks.h | 10 +- libs/libcurl/src/socks_gssapi.c | 26 +- libs/libcurl/src/socks_sspi.c | 42 +- libs/libcurl/src/speedcheck.c | 4 + libs/libcurl/src/strerror.c | 4 +- libs/libcurl/src/system_win32.c | 2 +- libs/libcurl/src/telnet.c | 206 +- libs/libcurl/src/tftp.c | 155 +- libs/libcurl/src/transfer.c | 229 +- libs/libcurl/src/transfer.h | 21 +- libs/libcurl/src/url.c | 276 +- libs/libcurl/src/url.h | 26 +- libs/libcurl/src/urlapi.c | 14 +- libs/libcurl/src/urldata.h | 205 +- libs/libcurl/src/vauth/digest.c | 14 +- libs/libcurl/src/vauth/digest_sspi.c | 15 +- libs/libcurl/src/vauth/krb5_sspi.c | 2 +- libs/libcurl/src/vauth/ntlm_sspi.c | 2 +- libs/libcurl/src/vauth/spnego_sspi.c | 2 +- libs/libcurl/src/version.c | 26 +- libs/libcurl/src/vquic/ngtcp2.c | 267 +- libs/libcurl/src/vquic/ngtcp2.h | 5 +- libs/libcurl/src/vquic/quiche.c | 127 +- libs/libcurl/src/vssh/libssh.c | 497 +- libs/libcurl/src/vssh/libssh2.c | 833 +-- libs/libcurl/src/vssh/ssh.h | 29 +- libs/libcurl/src/vssh/wolfssh.c | 243 +- libs/libcurl/src/vtls/bearssl.c | 138 +- libs/libcurl/src/vtls/gskit.c | 112 +- libs/libcurl/src/vtls/gtls.c | 181 +- libs/libcurl/src/vtls/mbedtls.c | 138 +- libs/libcurl/src/vtls/mesalink.c | 115 +- libs/libcurl/src/vtls/nss.c | 238 +- libs/libcurl/src/vtls/openssl.c | 313 +- libs/libcurl/src/vtls/schannel.c | 234 +- libs/libcurl/src/vtls/schannel.h | 5 +- libs/libcurl/src/vtls/schannel_verify.c | 21 +- libs/libcurl/src/vtls/sectransp.c | 157 +- libs/libcurl/src/vtls/vtls.c | 185 +- libs/libcurl/src/vtls/vtls.h | 58 +- libs/libcurl/src/vtls/wolfssl.c | 155 +- libs/libcurl/src/warnless.c | 21 +- libs/libcurl/src/warnless.h | 4 +- libs/libcurl/src/x509asn1.c | 8 +- libs/libcurl/src/x509asn1.h | 6 +- 154 files changed, 14929 insertions(+), 12054 deletions(-) create mode 100644 libs/libcurl/src/c-hyper.c create mode 100644 libs/libcurl/src/c-hyper.h create mode 100644 libs/libcurl/src/http_aws_sigv4.c create mode 100644 libs/libcurl/src/http_aws_sigv4.h (limited to 'libs/libcurl') diff --git a/libs/libcurl/docs/CHANGES b/libs/libcurl/docs/CHANGES index 56859b4993..f3439fd046 100644 --- a/libs/libcurl/docs/CHANGES +++ b/libs/libcurl/docs/CHANGES @@ -6,4462 +6,4653 @@ Changelog -Version 7.74.0 (9 Dec 2020) +Version 7.75.0 (3 Feb 2021) -Daniel Stenberg (9 Dec 2020) +Daniel Stenberg (3 Feb 2021) - RELEASE-NOTES: synced - - for 7.74.0 -Jay Satiro (7 Dec 2020) -- [Jacob Hoffman-Andrews brought this change] +- THANKS: added contributors from 7.75.0 - 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 +- copyright: fix year ranges in need of updates -Daniel Stenberg (7 Dec 2020) -- VERSIONS: refreshed +- TODO: remove items for next SONAME bump etc - We always use the patch number these days: all releases are - "major.minor.patch" + We want to avoid that completely, so we don't plan for things after such + an event. -- [Jakub Zakrzewski brought this change] +- [Jay Satiro brought this change] - cmake: don't use reserved target name 'test' - - CMake up to 3.10 always reserves this name + ngtcp2: Fix build error due to change in ngtcp2_settings - Fixes #6257 - Closes #6258 - -- openssl: make the OCSP verification verify the certificate id + - Separate ngtcp2_transport_params. - CVE-2020-8286 + ngtcp2/ngtcp2@05d7adc made ngtcp2_transport_params separate from + ngtcp2_settings. - Reported by anonymous + ngtcp2 master is required to build curl with http3 support. - Bug: https://curl.se/docs/CVE-2020-8286.html + Closes #6554 -- ftp: make wc_statemach loop instead of recurse +- vtls: remove md5sum - CVE-2020-8285 + As it is not used anymore. - Fixes #6255 - Bug: https://curl.se/docs/CVE-2020-8285.html - Reported-by: xnynx on github + Reported-by: Jacob Hoffman-Andrews + Bug: https://curl.se/mail/lib-2021-02/0000.html + + Closes #6557 -- ftp: CURLOPT_FTP_SKIP_PASV_IP by default +- [Alessandro Ghedini brought this change] + + quiche: don't use primary_ip / primary_port - The command line tool also independently sets --ftp-skip-pasv-ip by - default. + 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 - Ten test cases updated to adapt the modified --libcurl output. + - 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. - Bug: https://curl.se/docs/CVE-2020-8284.html - CVE-2020-8284 + Closes #6524 + +- hyper: fix CONNECT to set 'data' as userdata - Reported-by: Varnavas Papaioannou + Follow-up to 14e075d1a7fd -- urlapi: don't accept blank port number field without scheme +- [Layla brought this change] + + connect: fix compile errors in `Curl_conninfo_local` - ... 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. + .. for the `#else` (`!HAVE_GETSOCKNAME`) case - Reported-by: d4d on hackerone + Fixes https://github.com/curl/curl/issues/6548 + Closes #6549 - Closes #6283 + Signed-off-by: Layla -- Revert "multi: implement wait using winsock events" - - This reverts commit d2a7d7c185f98df8f3e585e5620cbc0482e45fac. +- [Michał Antoniak brought this change] + + transfer: fix GCC 10 warning with flag '-Wint-in-bool-context' - 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. + ... and return the error code from the Curl_mime_rewind call. - Fixes #6146 - Closes #6281 + Closes #6537 -- [Klaus Crusius brought this change] +- [Michał Antoniak brought this change] - ftp: retry getpeername for FTP with TCP_FASTOPEN + 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 - In the case of TFO, the remote host name is not resolved at the - connetion time. + ... 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. - 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. + Reported-by: David Earl + Fixes #6540 + Closes #6543 + +- KNOWN_BUGS: cmake: ExternalProject_Add does not set CURL_CA_PATH - Fixes #6252 - Closes #6265 - Closes #6282 + Closes #6313 -- [Thomas Danielsson brought this change] +- KNOWN_BUGS: Multi perform hangs waiting for threaded resolver + + Closes #4852 - scripts/completion.pl: parse all opts +- KNOWN_BUGS: "pulseUI VPN client" is known to be buggy - For tab-completion it may be preferable to include all the - available options. + First entry in the new section "applications" for known problems in + libcurl using applications. - Closes #6280 + Closes #6306 -- RELEASE-NOTES: synced - -- openssl: use OPENSSL_init_ssl() with >= 1.1.0 +- tool_writeout: make %{errormsg} blank for no errors - Reported-by: Kovalkov Dmitrii and Per Nilsson - Fixes #6254 - Fixes #6256 - Closes #6260 + Closes #6539 -- SECURITY-PROCESS: disclose on hackerone +Jay Satiro (27 Jan 2021) +- [Gisle Vanem brought this change] + + build: fix djgpp builds - Once a vulnerability has been published, the hackerone issue should be - disclosed. For tranparency. + - Update build instructions in packages/DOS/README - Closes #6275 - -Marc Hoersken (3 Dec 2020) -- tests/util.py: fix compatibility with Python 2 + - Extend 'VPATH' with 'vquic' and 'vssh'. - Backporting the Python 3 implementation of setStream - to ClosingFileHandler as a fallback within Python 2. + - Allow 'Makefile.dist' to build both 'lib' and 'src'. - Reported-by: Jay Satiro + - Allow using the Windows hosted djgpp cross compiler to build for MSDOS + under Windows. - Fixes #6259 - Closes #6270 - -Daniel Gustafsson (3 Dec 2020) -- docs: fix typos and markup in ETag manpage sections + - 'USE_SSL' -> 'USE_OPENSSL' - Reported-by: emanruse on github - Fixes #6273 - -Daniel Stenberg (2 Dec 2020) -- quiche: close the connection + - Added a 'link_EXE' macro. Etc, etc. - Reported-by: Junho Choi - Fixes #6213 - Closes #6217 - -Jay Satiro (2 Dec 2020) -- ngtcp2: Fix build error due to symbol name change + - Linking 'curl.exe' needs '$(CURLX_CFILES)' too. - - NGTCP2_CRYPTO_LEVEL_APP -> NGTCP2_CRYPTO_LEVEL_APPLICATION + - Do not pick-up '../lib/djgpp/*.o' files. Recompile locally. - ngtcp2/ngtcp2@76232e9 changed the name. + - Generate a gzipped 'tool_hugehelp.c' if 'USE_ZLIB=1'. - ngtcp2 master is required to build curl with http3 support. + - Remove 'djgpp-clean' - Closes https://github.com/curl/curl/pull/6271 + - 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 (1 Dec 2020) -- [Klaus Crusius brought this change] +Daniel Stenberg (27 Jan 2021) +- [Ikko Ashimine brought this change] - cmake: check for linux/tcp.h + hyper: fix typo in c-hyper.c - The HAVE_LINUX_TCP_H define was not set by cmake. + settting -> setting - Closes #6252 + Closes #6538 -- NEW-PROTOCOL: document what needs to be done to add one +- libssh2: fix CURL_LIBSSH2_DEBUG-enabled build - Closes #6263 + Follow-up to 2dcc940959772a + + Reported-by: Gisle Vanem + Bug: https://github.com/curl/curl/commit/2dcc940959772a652f6813fb6bd3092095a4877b#commitcomment-46420088 -- splay: rename Curl_splayremovebyaddr to Curl_splayremove +Jay Satiro (27 Jan 2021) +- asyn-thread: fix build for when getaddrinfo missing - ... and remove the old unused proto for the old Curl_splayremove - version. + 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 #6269 + Closes https://github.com/curl/curl/pull/6536 -- openssl: free mem_buf in error path +Daniel Stenberg (27 Jan 2021) +- urldata: move 'ints' to the end of 'connectdata' - To fix a memory-leak. + To optimize storage slightly. - Closes #6267 + Closes #6534 -- openssl: remove #if 0 leftover +- urldata: store ip version in a single byte - Follow-up to 4c9768565ec3a9 (from Sep 2008) + Closes #6534 + +- urldata: remove duplicate 'upkeep_interval_ms' from connectdata - Closes #6268 + ... and rely only on the value already set in Curl_easy. + + Closes #6534 -- ntlm: avoid malloc(0) on zero length user and domain +- urldata: remove 'local_ip' from the connectdata struct - ... and simplify the too-long checks somewhat. + 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. - Detected by OSS-Fuzz + Closes #6534 + +- urldata: remove duplicate port number storage - Closes #6264 + ... 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 -- RELEASE-NOTES: synced +- urldata: remove the duplicate 'ip_addr_str' field + + ... as the numerical IP address is already stored and kept in 'primary_ip'. + + Closes #6534 -Marc Hoersken (28 Nov 2020) -- tests/server/tftpd.c: close upload file in case of abort +- select: convert Curl_select() to private static function - Commit c353207 removed the closing right after do_tftp - which covered the case of abort. This handles that case. + 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). - Reviewed-by: Jay Satiro - Reviewed-by: Daniel Stenberg + The static function version is now called our_select() and is only built + if necessary. - Follow up to #6209 - Closes #6234 + Closes #6531 -Daniel Stenberg (26 Nov 2020) -- [Daiki Ueno brought this change] - - ngtcp2: use the minimal version of QUIC supported by ngtcp2 +- Curl_chunker: shrink the struct - Closes #6250 + ... 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 -- [Daiki Ueno brought this change] +- curl: include the file name in --xattr/--remote-time error msgs - ngtcp2: advertise h3 ALPN unconditionally +- curl: s/config->global/global/ in single_transfer() + +- curl: move fprintf outputs to warnf - Closes #6250 + For setting and getting time of the download. To make the outputs + respect --silent etc. + + Reported-by: Viktor Szakats + Fixes #6533 + Closes #6535 -- [Daiki Ueno brought this change] +- [Tatsuhiro Tsujikawa brought this change] - vquic/ngtcp2.h: define local_addr as sockaddr_storage + ngtcp2: Fix http3 upload stall - This field needs to be wide enough to hold sockaddr_in6 when - connecting via IPv6. Otherwise, ngtcp2_conn_read_pkt will drop the - packets because of the address mismatch: - I00000022 [...] con ignore packet from unknown path + Closes #6521 + +- [Tatsuhiro Tsujikawa brought this change] + + ngtcp2: Fix stack buffer overflow - We can safely assume that struct sockaddr_storage is available, as it - is used in the public interface of ngtcp2. + Closes #6521 + +- warnless.h: remove the prototype for curlx_ultosi - Closes #6250 + Follow-up to 217552503ff3 -- socks: check for DNS entries with the right port number +- warnless: remove curlx_ultosi - The resolve call is done with the right port number, but the subsequent - check used the wrong one, which then could find a previous resolve which - would return and leave the fresh resolve "incomplete" and leaking - memory. + ... not used anywhere - Fixes #6247 - Closes #6253 + Closes #6530 -- curl_setup: USE_RESOLVE_ON_IPS is for Apple native resolver use +- [Patrick Monnerat brought this change] + + lib: remove conn->data uses - ... so don't define it when instructed to use c-ares! + Closes #6515 -- test506: make it not run in c-ares builds +- pingpong: remove the 'conn' struct member - As the asynch nature of it may trigger events in another order. A c-ares - upgrade made it break. + ... 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. - Reported-by: Marc Hörsken - Fixes #6247 + Closes #6525 -- runtests: make 'c-ares' a "feature" to depend on +- hostip/proxy: remove conn->data use - ... also added to the docs. + Closes #6513 -- tool_writeout: use off_t getinfo-types instead of doubles +- url: reduce conn->data references - Commit 3b80d3ca46b12e52342 (June 2017) introduced getinfo replacement - variables that use curl_off_t instead of doubles. Switch the --write-out - function over to use them. + ... there are a few left but let's keep them to last - Closes #6248 + Closes #6512 -- [Emil Engler brought this change] +- scripts/singleuse: add curl_easy_option* - file: avoid duplicated code sequence +Jay Satiro (25 Jan 2021) +- test410: fix for windows - file_disconnect() is identical with file_do() except the function header - but as the arguments are unused anyway so why not just return file_do() - directly! + - Pass the very long request header via file instead of command line. - Reviewed-by: Daniel Stenberg - Closes #6249 + 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 -- [Rikard Falkeborn brought this change] +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 - infof/failf calls: fix format specifiers +- RELEASE-NOTES: synced + +- [Patrick Monnerat brought this change] + + lib: remove conn->data uses - Update a few format specifiers to match what is being printed. + Closes #6499 + +- hyper: remove the conn->data references - Closes #6241 + Closes #6508 -- docs/INTERNALS: remove reference to Curl_sendf() +- travis: build ngtcp2 --with-gnutls - The function has been removed from common usage. Also removed comment in - gopher.c that still referenced it. + ... since they disable it by default since a few days back. - Reported-by: Rikard Falkeborn - Fixes #6242 - Closes #6243 + Closes #6506 + Fixes #6493 -- [Rikard Falkeborn brought this change] +- 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 - examples: update .gitignore +Jay Satiro (22 Jan 2021) +- strerror: skip errnum >= 0 assertion on windows - Add files that are generated by 'make examples' and remove some that - have been renamed. + On Windows an error number may be greater than INT_MAX and negative once + cast to int. - The commits that renamed the programs are e9625c5bc6c046a (imap.c and - simplesmtp.c were renamed to imap-fetch.c and smtp-send.c) and - ad39e7ec01e7 (pop3slist.c and pop3s.c were renamed to pop3-list.c and - pop3-ssl.c). + The assertion is checked only in debug builds. - Closes #6240 + Closes https://github.com/curl/curl/pull/6504 -- asyn: use 'struct thread_data *' instead of 'void *' +Daniel Stenberg (21 Jan 2021) +- doh: make Curl_doh_is_resolved survive a NULL pointer - To reduce use of types that can't be checked at compile time. Also - removes several typecasts. - - ... and rename the struct field from 'os_specific' to 'tdata'. + ... 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. - Closes #6239 - Reviewed-by: Jay Satiro + Follow-up to 6246a1d8c6776 -Viktor Szakats (23 Nov 2020) -- Makefile.m32: add support for UNICODE builds +- wolfssh: remove conn->data references - It requires the linker to support the `-municode` option. - This is available in more recent mingw-w64 releases. + ... and repair recent build breakage - Ref: https://gcc.gnu.org/onlinedocs/gcc/x86-Windows-Options.html - Ref: https://stackoverflow.com/questions/3571250/wwinmain-unicode-and-mingw/11706847#11706847 + Closes #6507 + +- http: empty reply connection are not left intact - Reviewed-by: Jay Satiro - Reviewed-by: Marcel Raad + ... so mark the connection as closed in this condition to prevent that + verbose message to wrongly appear. - Closes #6228 + Reported-by: Matt Holt + Bug: https://twitter.com/mholt6/status/1352130240265375744 + Closes #6503 -Daniel Stenberg (23 Nov 2020) -- urldata: remove 'void *protop' and create the union 'p' +- chunk/encoding: remove conn->data references - ... to avoid the use of 'void *' for the protocol specific structs done - per transfer. + ... by anchoring more functions on Curl_easy instead of connectdata - Closes #6238 + Closes #6498 -- winbuild: remove docs from Makefiles and refer to README.md +Jay Satiro (20 Jan 2021) +- [Erik Olsson brought this change] + + lib: save a bit of space with some structure packing - Reduce risk for conflicting docs and makes it to a single place to fix - and polish. + - Reorder some internal struct members so that less padding is used. - add these missing options to the readme: + 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. - ENABLE_OPENSSL_AUTO_LOAD_CONFIG and ENABLE_UNICODE + 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. - clarify ENABLE_SCHANNEL default varies + Closes https://github.com/curl/curl/pull/6483 + +Daniel Stenberg (20 Jan 2021) +- INSTALL.md: fix typo - Fixes #6216 - Closes #6227 - Co-Authored-by: Jay Satiro + Found-by: Marcel Raad -- [Daiki Ueno brought this change] +- [Fabian Keil brought this change] - http3: use the master branch of GnuTLS for testing + http: get CURLOPT_REQUEST_TARGET working with a HTTP proxy - Closes #6235 - -- KNOWN_BUGS: curl with wolfSSL lacks support for renegotiation + Added test 1613 to verify. - Closes #5839 + Closes #6490 -- KNOWN_BUGS: wakeup socket disconnect causes havoc +- Merge branch 'bagder/curl_range-data-conn' + +- ftp: remove conn->data leftover + +- curl_range: remove conn->data - Closes #6132 - Closes #6133 + Closes #6496 -- RELEASE-NOTES: synced +- INSTALL: now at 85 operating systems -- [Oliver Urbann brought this change] +- quiche: fix unused parameter ‘conn’ + + Follow-up to 2bdec0b3 - curl: add compatibility for Amiga and GCC 6.5 +- transfer: fix ‘conn’ undeclared mistake for iconv build - Changes are mainly reordering and adding of includes required - to compile with a more recent version of GCC. + Follow-up to 219d9f8620d + +- doh: allocate state struct on demand - Closes #6220 + ... 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 -Marc Hoersken (20 Nov 2020) -- tests/server/tftpd.c: close upload file right after transfer +- socks: use the download buffer instead - Make sure uploaded file is no longer locked after the - transfer while waiting for the final ACK to be handled. + 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. - Assisted-by: Daniel Stenberg + This reduces the connection struct size by 22% on a 64bit arch! - Bug: #6058 - Closes #6209 - -- CI/cirrus: simplify logic for disabled tests + The SOCKS buffer needs to be at least 600 bytes, and the download buffer + is guaranteed to never be smaller than 1000 bytes. - The OpenSSH server instance for the testsuite cannot - be started on FreeBSD, therefore the SFTP and SCP - tests are disabled right away from the beginning. + Closes #6491 + +- urldata: make magic be the first struct field - The previous OS version specific logic for SKIP_TESTS - is no longer needed/used and can therefore be removed. + 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. - Reviewed-by: Daniel Stenberg + Such mixups can't be detected at compile-time due to them being + typedefed void pointers - unless `CURL_STRICTER` is defined. - Follow up to #6211 - Closes #6229 + Closes #6484 -Daniel Gustafsson (20 Nov 2020) -- mailmap: Daniel Hwang +- http_chunks: correct and clarify a comment on hexnumber length - Add Daniel Hwang to the mailmap to cover the alternative spelling - Daniel Lee Hwang which was used in one commit. + ... and also rename the define for max length. - Closes #6230 - Reviewed-by: Daniel Stenberg + Closes #6489 -- openssl: guard against OOM on context creation +- curl_path: remove conn->data use - EVP_MD_CTX_create will allocate memory for the context and returns - NULL in case the allocation fails. Make sure to catch any allocation - failures and exit early if so. + Closes #6487 + +- transfer: remove conn->data use - In passing, also move to EVP_DigestInit rather than EVP_DigestInit_ex - as the latter is intended for ENGINE selection which we don't do. + Closes #6486 + +- quic: remove conn->data use - Closes #6224 - Reviewed-by: Daniel Stenberg - Reviewed-by: Emil Engler + Closes #6485 -Daniel Stenberg (19 Nov 2020) -- [Vincent Torri brought this change] +- [Fabian Keil brought this change] - cmake: use libcurl.rc in all Windows builds + 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" - Reviewed-by: Marcel Raad - Closes #6215 + At the moment the test fails as curl sends two Proxy-Connection + headers. -- [Cristian Morales Vega brought this change] +- c-hyper: avoid duplicated Proxy-Connection headers - cmake: make CURL_ZLIB a tri-state variable +- http: make providing Proxy-Connection header not cause duplicated headers - By differentiating between ON and AUTO it can make a missing zlib - library a hard error when CURL_ZLIB=ON is used. + Fixes test 1180 - Reviewed-by: Jakub Zakrzewski - Closes #6221 - Fixes #6173 + Bug: https://curl.se/mail/lib-2021-01/0095.html + Reported-by: Fabian Keil + Closes #6472 -- quiche: remove 'static' from local buffer +- runtests: preprocess DISABLED to allow conditionals - For thread-safety + ... with this function provided, we can disable tests for specific + environments and setups directly within this file. - Closes #6223 + Closes #6477 -- KNOWN_BUGS: cmake: libspsl is not supported +- runtests: turn preprocessing into a separate function - Closes #6214 + ... and remove all other variable substitutions as they're now done once + and for all in the preprocessor. -- KNOWN_BUGS: cmake autodetects cert paths when cross-compiling +- lib/Makefile.inc: convert to listing each file on its own line - Closes #6178 - -- KNOWN_BUGS: cmake build doesn't fail if zlib not found + ... to make it diff friendlier and easier to read. - Closes #6173 + Closes #6448 -- KNOWN_BUGS: cmake libcurl.pc uses absolute library paths +- ftplistparser: remove use of conn->data - Closes #6169 + Closes #6482 -- KNOWN_BUGS: cmake: generated .pc file contains strange entries +- lib: more conn->data cleanups - Closes #6167 + Closes #6479 -- KNOWN_BUGS: cmake uses -lpthread instead of Threads::Threads +- [Patrick Monnerat brought this change] + + vtls: reduce conn->data use - Closes #6166 + Closes #6474 -- KNOWN_BUGS: cmake build in Linux links libcurl to libdl +- hyper: deliver data to application with Curl_client_write - Closes #6165 + ... 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 -- KNOWN_BUGS: make a new section for cmake topics +- gopher: remove accidental conn->data leftover + +- libssh: avoid plain free() of libssh-memory - Closes #6219 + 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 -- [Emil Engler brought this change] +- send: assert that Curl_write_plain() has a ->conn when called + + To help catch bad invokes. + + Closes #6476 - cirrus: build with FreeBSD 12.2 in CirrusCI +- test410: verify HTTPS GET with a 49K request header - Closes #6211 + skip test 410 for mesalink in the CI as it otherwise hangs "forever" -Marc Hoersken (14 Nov 2020) -- tests/*server.py: close log file after each log line +- lib: pass in 'struct Curl_easy *' to most functions - Make sure the log file is not locked once a test has - finished and align with the behavior of our logmsg. + ... in most cases instead of 'struct connectdata *' but in some cases in + addition to. - Rename curl_test_data.py to be a general util.py. - Format and sort Python imports with isort/VSCode. + - We mostly operate on transfers and not connections. - Bug: #6058 - Closes #6206 + - 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 -Daniel Stenberg (13 Nov 2020) -- CURLOPT_HSTS.3: document the file format +Emil Engler (17 Jan 2021) +- docs: fix typos in NEW-PROTOCOL.md - Closes #6205 + This fixes a misspelled "it" and a grammatically wrong "-ing" suffix. + + Closes #6471 +Daniel Stenberg (16 Jan 2021) - RELEASE-NOTES: synced -- release-notes.pl: detect #[number] better for Ref: etc +Jay Satiro (16 Jan 2021) +- [Razvan Cojocaru brought this change] -- curl: only warn not fail, if not finding the home dir + cmake: expose CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG - ... as there's no good reason to error out completely. + This does for cmake builds what --disable-openssl-auto-load-config + does for autoconf builds. - Reported-by: Andreas Fischer - Fixes #6200 - Closes #6201 + Closes https://github.com/curl/curl/pull/6435 -- httpput-postfields.c: new example doing PUT with POSTFIELDS +Daniel Stenberg (15 Jan 2021) +- test1918: verify curl_easy_option_by_name() and curl_easy_option_by_id() - Proposed-by: Jeroen Ooms - Ref: #6186 - Closes #6188 + ... 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 -- [Tobias Hieta brought this change] +- [Gisle Vanem brought this change] - cmake: correctly handle linker flags for static libs + easyoptions: add the missing AWS_SIGV4 - curl CMake was setting the the EXE flags for static libraries which made - the /manifest:no flag ended up when linking the static library, which is - not a valid flag for lib.exe or llvm-lib.exe and caused llvm-lib to exit - with an error. + Follow-up from AWS_SIGV4 + +- schannel_verify: fix safefree call typo - The better way to handle this is to make sure that we pass the correct - linker flags to CMAKE_STATIC_LINKER_FLAGS instead. + Follow-up from e87ad71d1ba00519 - Reviewed-by: Jakub Zakrzewski - Closes #6195 + Closes #6459 -- [Tobias Hieta brought this change] +- 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 - cmake: don't pass -fvisibility=hidden to clang-cl on Windows +- multi: set the PRETRANSFER time-stamp when we switch to PERFORM - When using clang-cl on windows -fvisibility=hidden is not an known - argument. Instead it behaves exactly like MSVC in this case. So let's - make sure we take that path. + ... 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. - In CMake clang-cl sets both CMAKE_C_COMPILER_ID=clang and MSVC get's - defined since clang-cl is basically a MSVC emulator. So guarding like we - do in this patch seems logical. + The timer will then include the entire procedure up to PERFORM - + including all instructions for getting the transfer started. - Reviewed-by: Jakub Zakrzewski - Closes #6194 + Closes #6454 -- http_proxy: use enum with state names for 'keepon' +- CURLINFO_PRETRANSFER_TIME.3: clarify - To make the code clearer, change the 'keepon' from an int to an enum - with better state names. + ... the timer *does* include the instructions for getting the remote + file. - Reported-by: Niranjan Hasabnis - Bug: https://curl.se/mail/lib-2020-11/0026.html - Closes #6193 + Ref: #6452 + Closes #6453 -- curl_easy_escape: limit output string length to 3 * max input +- [Gisle Vanem brought this change] + + schannel: plug a memory-leak - ... instead of the limiting it to just the max input size. As every - input byte can be expanded to 3 output bytes, this could limit the input - string to 2.66 MB instead of the intended 8 MB. + ... when built without -DUNICODE. - Reported-by: Marc Schlatter - Closes #6192 + Closes #6457 -- docs: document the 8MB input string limit +Jay Satiro (14 Jan 2021) +- gitattributes: Set batch files to CRLF line endings on checkout - for curl_easy_escape and curl_easy_setopt() + 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. - The limit is there to catch mistakes and abuse. It is meant to be large - enough to allow virtually all "fine" use cases. + 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. - Reported-by: Marc Schlatter - Fixes #6190 - Closes #6191 + 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 -- mqttd: fclose test file when done +Daniel Stenberg (14 Jan 2021) +- tool_operate: spellfix a comment + +- ROADMAP: refreshed - Reported-by: Marc Hörsken - Reviewed-by: Jay Satiro - Bug: #6058 - Closes #6189 + o removed HSTS - already implemented + o added HTTPS RR records + o mention HTTP/3 completion -- RELEASE-NOTES: synced +- http_chunks: remove Curl_ prefix from static functions -- THANKS-filter: ignore autobuild links +- transfer: remove Curl_ prefix from static functions -- Revert "libcurl.pc: make it relocatable" +- 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 - This reverts commit 3862c37b6373a55ca704171d45ba5ee91dec2c9f. + ... as we reserve this prefix to library-wide functions. - That fix should either be done differently or with an option. + Closes #6443 + +- nss: get the run-time version instead of build-time - Reported-by: asavah on github - Fixes #6157 - Closes #6183 + Closes #6445 -- examples/httpput: remove use of CURLOPT_PUT +Jay Satiro (12 Jan 2021) +- tool_doswin: Restore original console settings on CTRL signal - It is deprecated and unnecessary since it already sets CURLOPT_UPLOAD. + - Move Windows terminal init code from tool_main to tool_doswin. - Reported-by: Jeroen Ooms - Fixes #6186 - Closes #6187 - -- Curl_pgrsStartNow: init speed limit time stamps at start + - Restore the original console settings on CTRL+C and CTRL+BREAK. - By setting the speed limit time stamps unconditionally at transfer - start, we can start off a transfer without speed limits and yet allow - them to get set during transfer and have an effect. + 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. - Reported-by: Kael1117 on github - Fixes #6162 - Closes #6184 - -- ngtcp2: adapt to recent nghttp3 updates + Windows VT behavior varies depending on console/powershell/terminal; + refer to the discussion in #6226. - 'reset_stream' was added to the nghttp3_conn_callbacks struct + Assisted-by: Rich Turner - Closes #6185 + Closes https://github.com/curl/curl/pull/6226 -- configure: pass -pthread to Libs.private for pkg-config +Daniel Stenberg (12 Jan 2021) +- gen.pl: fix perl syntax - Reported-by: Cristian Morales Vega - Fixes #6168 - Closes #6181 + Follow-up to 324cf1d2e -- altsvc: minimize variable scope and avoid "DEAD_STORE" - - Closes #6182 +- [Emil Engler brought this change] -- FAQ: remove "Why is there a HTTP/1.1 in my HTTP/2 request?" + help: update to current codebase - This hasn't been the case for a while now, remove. - -- FAQ: refresh "Why do I get "certificate verify failed" + This commit bumps the help to the current state of the project. - Add more details, remove references to ancient curl version. + Closes #6437 -- test493: verify --hsts upgrade and that %{url_effective} reflects that +- [Emil Engler brought this change] + + docs: fix line length bug in gen.pl - Closes #6175 + 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 -- url: make sure an HSTS upgrade updates URL and scheme correctly +- [Emil Engler brought this change] + + docs: fix wrong documentation in help.d - Closes #6175 + curl does not list all categories when you invoke "--help" without any + parameters. + + Closes #6436 -- tool_operate: set HSTS with CURLOPT_HSTS to pass on filename +- aws-sigv4.d: polish the wording - Closes #6175 + Make it shorter and imperative form + + Closes #6439 -- hsts: remove debug code leftovers +- [Fabian Keil brought this change] + + misc: fix typos - Closes #6175 + Bug: https://curl.se/mail/lib-2021-01/0063.html + Closes #6434 -- FAQ: refreshed +- multi_runsingle: bail out early on data->conn == NULL - - remove a few ancient questions - - add configure with static libs question - - updated wording in several places - - lowercased curl + As that's a significant error condition and scan-build warns for NULL + pointer dereferences if we don't. - Closes #6177 + Closes #6433 -Daniel Gustafsson (5 Nov 2020) -- examples: fix comment syntax +- multi: skip DONE state if there's no connection left for ftp wildcard - Commit ac0a88fd2 accidentally added a stray character outside of the - comment which broke compilation. Fix by removing. + ... to avoid running in that state with data->conn being NULL. + +- libssh2: fix "Value stored to 'readdir_len' is never read" - Reported-by: autobuild https://curl.se/dev/log.cgi?id=20201105084306-12742 + Detected by scan-build -- hsts: Remove pointless call to free in errorpath +- connect: mark intentional ignores of setsockopt return values - The line variable will always be NULL in the error path, so remove - the free call since it's pointless. + Pointed out by Coverity - Closes #6170 - Reviewed-by: Daniel Stenberg + Closes #6431 -- docs: Fix various typos in documentation +Jay Satiro (11 Jan 2021) +- http_proxy: Fix CONNECT chunked encoding race condition - Closes #6171 - Reviewed-by: Daniel Stenberg - -Daniel Stenberg (5 Nov 2020) -- copyright: fix year ranges + - During the end-of-headers response phase do not mark the tunnel + complete unless the response body was completely parsed/ignored. - Follow-up from 4d2f8006777 + 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 -- HISTORY: the new domain +Daniel Stenberg (11 Jan 2021) +- RELEASE-NOTES: synced -- curl.se: new home +- url: if IDNA conversion fails, fallback to Transitional - Closes #6172 - -- KNOWN_BUGS: FTPS with Schannel times out file list operation + This improves IDNA2003 compatiblity. - Reported-by: bobmitchell1956 on github - Closes #5284 + Reported-by: Bubu on github + Fixes #6423 + Closes #6428 -- KNOWN_BUGS: SMB tests fail with Python 2 +- travis: make the Hyper build from its master branch - Reported-by: Jay Satiro - Closes #5983 + Closes #6430 -- KNOWN_BUGS: LDAPS with NSS is slow +- http: make 'authneg' also work for Hyper - Reported-by: nosajsnikta on github - Closes #5874 + 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 -Sergei Nikulov (4 Nov 2020) -- travis: use ninja-build for CMake builds +Jay Satiro (8 Jan 2021) +- cmake: Add an option to disable libidn2 - Added package ninja-build to environment - Use ninja to speed up CMake builds + New option USE_LIBIDN2 defaults to ON for libidn2 detection. Prior to + this change libidn2 detection could not be turned off in cmake builds. - Closes #6077 - -Daniel Stenberg (4 Nov 2020) -- [Harry Sintonen brought this change] - - rtsp: error out on empty Session ID, unified the code - -- [Harry Sintonen brought this change] - - rtsp: fixed the RTST Session ID mismatch in test 570 + Reported-by: William A Rowe Jr - Closes #6161 + Fixes https://github.com/curl/curl/issues/6361 + Closes https://github.com/curl/curl/pull/6362 -- [Harry Sintonen brought this change] +Daniel Stenberg (8 Jan 2021) +- HYPER: no longer needs the special branch - rtsp: fixed Session ID comparison to refuse prefix +- test179: use consistent header line endings - Closes #6161 + ... to make "Hyper mode" work better. -- RELEASE-NOTES: synced +- file: don't provide content-length for directories - (forgot to update the list of contributors) + ... as it is misleading. + + Ref #6379 + Closes #6421 -- RELEASE-NOTES: synced +- TODO: Directory listing for FILE: + + Ref #6379 -- curlver: bumped to 7.74.0 +- 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 -- hsts: add read/write callbacks +- http: have CURLOPT_FAILONERROR fail after all headers - - read/write callback options - - man pages for the 4 new setopts - - test 1915 verifies the callbacks + ... so that Retry-After and other meta-content can still be used. - Closes #5896 + 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 -- hsts: add support for Strict-Transport-Security +- global_init: debug builds allocates a byte in init - - enable in the build (configure) - - header parsing - - host name lookup - - unit tests for the above - - CI build - - CURL_VERSION_HSTS bit - - curl_version_info support - - curl -V output - - curl-config --features - - CURLOPT_HSTS_CTRL - - man page for CURLOPT_HSTS_CTRL - - curl --hsts (sets CURLOPT_HSTS_CTRL and works with --libcurl) - - man page for --hsts - - save cache to disk - - load cache from disk - - CURLOPT_HSTS - - man page for CURLOPT_HSTS - - added docs/HSTS.md - - fixed --version docs - - adjusted curl_easy_duphandle + ... to make build tools/valgrind warn if no curl_global_cleanup is + called. - Closes #5896 + This is conditionally only done for debug builds with the env variable + CURL_GLOBAL_INIT set. + + Closes #6410 -- [Sergei Nikulov brought this change] +- lib/unit tests: add missing curl_global_cleanup() calls - CI/tests: enable test target on TravisCI for CMake builds +- travis: adapt to Hyper build change - Added test-nonflaky target to CMake builds + Closes #6419 + +- pretransfer: setup the User-Agent header here - Disabled test 1139 because the cmake build doesn't create docs/curl.1 + ... 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! - Closes #6074 + Reported-by: Flameborn on github + Assisted-by: Andrey Gursky + Assisted-by: Jay Satiro + Assisted-by: Mike Gelfand + Fixes #6312 + Closes #6417 -- tool_debug_cb: do not assume zero-terminated data +- test66: disable with Hyper - Follow-up to d70a5b5a0f5e3 + ...as Hyper doesn't support HTTP/0.9 -- sendf: move the verbose-check into Curl_debug +- c-hyper: poll the tasks until end correctly - Saves us from having the same check done everywhere. + ... makes test 36 work. - Closes #6159 + Closes #6412 -- travis: use valgrind when running tests for debug builds +- [Gergely Nagy brought this change] + + mk-ca-bundle.pl: deterministic output when using -t - Except the non-x86 and sanitizer builds + Printing trust purposes are now sorted, making the output deterministic + when running on the same input certdata.txt. - Closes #6154 + Closes #6413 -- header.d: fix syntax mistake +- KNOWN_BUGS: fixed "wolfSSL lacks support for renegotiation" - follow-up from 1144886f38fd0 + Fixed by #6411 -- [Harry Sintonen brought this change] +- [Himanshu Gupta brought this change] - gnutls: fix memory leaks (certfields memory wasn't released) + wolfssl: add SECURE_RENEGOTIATION support - Closes #6153 + Closes #6411 -- tests: add missing global_init/cleanup calls - - Without the cleanup call in these test files, the mbedTLS backend leaks - memory. - - Closes #6156 +- RELEASE-NOTES: synced -- tool_operate: --retry for HTTP 408 responses too +- wolfssl: update copyright year range - This was inadvertently dropped from the code when the parallel support - was added. + Follow-up to 7de2e96535e9 + +- c-hyper: make CURLE_GOT_NOTHING work - Regression since b88940850 (7.66.0) + Test 30 - Reviewed-by: Jay Satiro - Closes #6155 + Closes #6407 -- http: pass correct header size to debug callback for chunked post +- http_proxy: make CONNECT work with the Hyper backend - ... when the chunked framing was added, the size of the "body part" of - the data was calculated wrongly so the debug callback would get told a - header chunk a few bytes too big that would also contain the first few - bytes of the request body. + Makes test 80 run - Reported-by: Dirk Wetter - Ref: #6144 - Closes #6147 + Closes #6406 -- header.d: mention the "Transfer-Encoding: chunked" handling - - Ref: #6144 - Closes #6148 +- TODO: --fail-with-body perchance? -- acinclude: detect manually set minimum macos/ipod version +Jay Satiro (4 Jan 2021) +- tool_operate: fix the suppression logic of some error messages - ... even if set in the CC or IPHONEOS/MACOSX_DEPLOYMENT_TARGET - variables. + - 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). - Reported-by: hamstergene on github - Fixes #6138 - Closes #6140 - -Jay Satiro (29 Oct 2020) -- tests: fix some http/2 tests for older versions of nghttpx + - Also prefix same error messages with "curl: ", for example: + curl: (23) Failed to truncate, exiting - - Add regex that strips http/2 server header name to those http/2 tests - that don't already have it. + Prior to this change the failed truncation error messages would be shown + if not -s, but did not account for -sS which should show. - - Improve that regex in all http/2 tests. + Prior to this change the failed writing body error messages would be + shown always. - Tests 358 and 359 were failing for me before this change on a system - that uses an older version of nghttpx which includes its version number - in the server header. + Ref: https://curl.se/docs/manpage.html#-S - Closes https://github.com/curl/curl/pull/6139 - -Daniel Stenberg (30 Oct 2020) -- RELEASE-NOTES: synced - -- [Cristian Morales Vega brought this change] + Bug: https://curl.se/mail/archive-2020-12/0017.html + Reported-by: Hongyi Zhao + + Closes https://github.com/curl/curl/pull/6402 - configure: use pkgconfig to find openSSL when cross-compiling +- wolfssl: Support wolfSSL builds missing TLS 1.1 - This reverts 736a40fec (November 2004), which doesn't explain why it was - done. + 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]. - Closes #6145 - -- tool_operate: bail out proper on errors for parallel setup + 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. - ... otherwise for example trying to upload a missing file just causes a - loop. + [1]: https://github.com/wolfSSL/wolfssl/blob/v4.5.0-stable/configure.ac#L2366 - Reported-by: BrumBrum on hackerone - Closes #6141 + Bug: https://curl.se/mail/lib-2020-12/0121.html + Reported-by: Julian Montes + + Closes https://github.com/curl/curl/pull/6388 -- [Sergei Nikulov brought this change] +Daniel Stenberg (4 Jan 2021) +- test1633: set appropriate name + + "--retry with a 429 response and Retry-After:" - CMake: make BUILD_TESTING dependent option +- travis: limit the tests with quiche builds to HTTPS and FTPS only - CMake will now handle BUILD_TESTING depending on PERL_FOUND and - CURL_DISABLE_TESTING + ... since it runs into the 50 minute time limit too often otherwise. - Ref: #6036 - Closes #6072 + Closes #6403 -- libssh2: fix transport over HTTPS proxy +- HISTORY: added dates to early history - The fix in #6021 was not enough. This fix makes sure SCP/SFTP content - can also be transfered over a HTTPS proxy. + Mostly thanks to this archived web page for urlget: - Fixes #6113 - Closes #6128 + https://web.archive.org/web/19980216125115/http://www.inf.ufrgs.br/~sagula/urlget.html -- curl.1: add an "OUTPUT" section at the top of the manpage +- httpauth: make multi-request auth work with custom port - Explain the basic concepts behind curl output. + 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. - Inspired by #6124 + Added test 1568 to verify. - Closes #6134 + Reported-by: UrsusArctos on github + Fixes #6397 + Closes #6400 -- mailmap: set Viktor Szakats's email +- [Emil Engler brought this change] -- runtests: show keywords when no tests ran + language: s/behaviour/behavior/g - To help out future debugging, runtests now outputs the list of keywords - when it fails because no tests ran. + 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. - Ref: #6120 - Closes #6126 + Closes #6395 -Jay Satiro (26 Oct 2020) -- CURLOPT_DNS_USE_GLOBAL_CACHE.3: fix typo - - Reported-by: Rui LIU +- cmdline-opts/retry.d: mention response code 429 as well - Closes https://github.com/curl/curl/issues/6131 + Reported-by: Cherish98 + Bug: https://curl.se/mail/archive-2020-12/0018.html -- range.d: fix typo +- docs/HYPER.md: mention outstanding issues - Follow-up to 15ae039 from earlier today. + To make it more obvious to users what doesn't work (yet) + + Closes #6389 -Daniel Stenberg (26 Oct 2020) -- CI/github: work-around for brew breakage on macOS +- COPYING/configure: bump copyright year range + +- c-hyper: add timecondition to the request - ... and make it use OpenSSL 1.1 properly + Test 77-78 - Fixes #6130 - Closes #6129 - -- [José Joaquín Atria brought this change] + Closes #6391 - range.d: clarify that curl will not parse multipart responses +- c-hyper: make Digest and NTLM work - Closes #6127 - Fixes #6124 + Test 64, 65, 67, 68, 69, 70, 72 + + Closes #6390 -- RELEASE-NOTES: synced +- examples/curlgtk.c: fix the copyright year range + + ... and make private functions static. -- [Baruch Siach brought this change] +- [Olaf Hering brought this change] - libssh2: fix build with disabled proxy support + docs/examples: adjust prototypes for CURLOPT_READFUNCTION - Build breaks because the http_proxy field is missing: + The type of the buffer in curl_read_callback is 'char *', not 'void *'. - vssh/libssh2.c:3119:10: error: 'struct connectdata' has no member named 'http_proxy' + Signed-off-by: Olaf Hering + Closes #6392 + +- examples: fix more empty expression statement has no effect - Regression from #6021, shipped in curl 7.73.0 + Follow-up to 26e46617b9 + +- cleanup: fix two empty expression statement has no effect - Closes #6125 + Follow-up to 26e46617b9 -- alt-svc: enable by default +- configure: set -Wextra-semi-stmt for clang with --enable-debug - Remove CURLALTSVC_IMMEDIATELY, which was never implemented/supported. + To have it properly complain on empty statements with no effect. - alt-svc support in curl is no longer considered experimental + Ref: #6376 + Closes #6378 + +- tests/unit: fix empty statements with no effect - Closes #5868 + ... by making macros use "do {} while(0)" -- CI/appveyor: remove (unused) runtests.pl -b option +- [Paul Groke brought this change] -- [Emil Engler brought this change] - - tool_help: make "output" description less confusing + dns: extend CURLOPT_RESOLVE syntax for adding non-permanent entries - Currently the description of "output" is misleading when comparing it - "verbose". + 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. - Closes #6118 + 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 -- CI/appveyor: disable test 571 in two cmake builds +- schannel: fix "empty expression statement has no effect" - ... they're simply too flaky there. + 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 #6119 + Closes #6385 -- cmake: set the unicode feature in curl-config on Windows +- [Kevin Ushey brought this change] + + curl.1: fix typo microsft -> microsoft - ... if built that way. To make it match curl -V output. + Closes #6380 + +- [XhmikosR brought this change] + + misc: assorted typo fixes - Reviewed-by: Marcel Raad - Closes #6117 + Closes #6375 -- libssh2: require version 1.0 or later +- RELEASE-NOTES: synced + +- tool_operate: avoid NULL dereference of first_arg - ... and simplify the code accordingly. libssh2 version 1.0 was released - in April 2009. + 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" - Closes #6116 + 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: mention the individual cmake issues +- KNOWN_BUGS: 6.10 curl never completes Negotiate over HTTP - ... to make them easier to refer to and address separately and - one-by-one. + Closes #5235 + Closes #6370 -- CMake: store IDN2 information in curl_config.h +- writeout: fix NULL dereference for "this url" - This allows the build to enable IDN properly and it makes test 1014 - happier. + Detected by torture test 1029 - Ref: #6074 - Closes #6108 + Follow-up to 7a90ddf88f5a + + Closes #6374 -- CMake: call the feature unixsockets without dash +- failf: remove newline from formatting strings - ... so that curl-config gets correct and makes test 1014 happy! + ... as failf adds one itself. - Ref: #6074 - Closes #6108 + Also: add an assert() to failf() that triggers on a newline in the + format string! + + Closes #6365 -- CI/travis: add brotli and zstd to the libssh2 build +- [XhmikosR brought this change] + + CI: fix warning with the latest versions - ... to make sure such tests are run with valgrind. Suppress the zstd - valgrind warnings we get with version 1.3.3 on Ubuntu 18.04 (for debug - and non-debug builds). + `git checkout HEAD^2` is no longer needed - Closes #6105 + Closes #6369 -- runtests: revert the mistaken edit of $CURL +- INSTALL: update the list known OSes and CPU archs curl has run on - Regression from c4693adc62 + Closes #6366 -- RELEASE-NOTES: synced +- [Cherish98 brought this change] -- curl_url_set.3: fix typo in the RETURN VALUE section + curl: fix handling of -q option - Reported-by: Basuke Suzuki - Fixes #6102 - -Jay Satiro (17 Oct 2020) -- [Daniel Stenberg brought this change] + 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 - packages/OS400: make the source code-style compliant +- tests/badsymbols.pl: ignore stand-alone single hash lines - ... and make sure 'make checksrc' in the root dir also verifies the - packages/OS400 sources. + Bug: https://curl.se/mail/lib-2020-12/0084.html + Reported-by: Dennis Clarke + Assisted-by: Jay Satiro - Closes https://github.com/curl/curl/pull/6085 + Closes #6355 -- os400: Sync libcurl API options +- curl_easy_pause.3: add multiplexed pause effects - This fixes the OS400 build and also an incorrect entry for - CURLINFO_APPCONNECT_TIME_T where it was treated as - CURLINFO_STARTTRANSFER_TIME_T. + and generally refresh and update. Remove details for ancient versions. - Reported-by: Jon Rumsey + Reviewed-by: Jay Satiro + Closes #6360 + +Jay Satiro (22 Dec 2020) +- curl_easy_pause.3: fix man page reference - Fixes https://github.com/curl/curl/issues/6083 - Closes https://github.com/curl/curl/pull/6084 + Follow-up to ac9a724 from earlier today. + + Ref: https://github.com/curl/curl/pull/6359 -Daniel Stenberg (16 Oct 2020) -- CURLOPT_NOBODY.3: fix typo +Daniel Stenberg (22 Dec 2020) +- EXPERIMENTAL: add the Hyper backend to the list - Reported-by: Basuke Suzuki - Fixes #6097 + ... of current experimental features in curl. -Marc Hoersken (16 Oct 2020) -- CI/azure: improve on flakiness by avoiding libtool wrappers +- speedcheck: exclude paused transfers - Install curl binaries into MinGW bin folder and use that - for the tests in order to avoid libtool wrapper binaries. + 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. - The libtool wrapper binaries (not scripts) on Windows seem - to be one of the possible causes for the following issues: + Reported-by: Harry Sintonen + Fixes #6358 + Closes #6359 + +- h2: do not wait for RECV on paused transfers - 1. Process output can be lost in the wrapper process chain. - 2. Killing the wrapper process does not kill the actual one. + ... as the socket might be readable all the time when paused and thus + causing a busy-loop. - Derived from #5904 - Closes #6049 + Reported-by: Harry Sintonen + Reviewed-by: Jay Satiro + Fixes #6356 + Closes #6357 -Daniel Stenberg (16 Oct 2020) -- CURLOPT_URL.3: clarify SCP/SFTP URLs are for uploads as well +- RELEASE-NOTES: synced -- [Zenju brought this change] +- cmdline-opts/gen.pl: return hard on errors + + ... as the warnings tend to go unnoticed otherwise! + + Closes #6354 - CURLOPT_TCP_NODELAY.3: fix comment in example code +- examples/libtest: add .checksrc to dist - Closes #6096 + ... so that (auto)builds from tarballs also get the correct instructions. + + Fixes #6176 + Closes #6353 -- openssl: acknowledge SRP disabling in configure properly +- test: verify new --write-out variables - Follow-up to 68a513247409 + Extended test 1029 and added 1188 + +- test970: adapted to the new internal order of variables + +- curl: add variables to --write-out - Use a new separate define that is the combination of both - HAVE_OPENSSL_SRP and USE_TLS_SRP: USE_OPENSSL_SRP + In particular, these ones can help a user to create its own error + message when one or transfers fail. - Bug: https://curl.haxx.se/mail/lib-2020-10/0037.html + writeout: add 'onerror', 'url', 'urlnum', 'exitcode', 'errormsg' - Closes #6094 - -Viktor Szakats (16 Oct 2020) -- http3: fix two build errors, silence warnings + onerror - lets a user only show the rest on non-zero exit codes - * fix two build errors due to mismatch between function - declarations and their definitions - * silence two mismatched signs warnings via casts + url - the input URL used for this transfer - Approved-by: Daniel Stenberg - Closes #6093 - -- Makefile.m32: add support for HTTP/3 via ngtcp2+nghttp3 + urlnum - the numerical URL counter (0 indexed) for this transfer - Approved-by: Daniel Stenberg - Closes #6092 - -Daniel Stenberg (16 Oct 2020) -- tool_operate: fix compiler warning when --libcurl is disabled + exitcode - the numerical exit code for the transfer - Closes #6095 + errormsg - obvious + + Reported-by: Earnestly on github + Fixes #6199 + Closes #6207 -- checksrc: warn on empty line before open brace +- [Matthias Gatto brought this change] + + tests: add very simple AWS HTTP v4 Signature test - ... and fix a few occurances + Signed-off-by: Matthias Gatto + +- [Matthias Gatto brought this change] + + docs: add AWS HTTP v4 Signature + +- [Matthias Gatto brought this change] + + tool: add AWS HTTP v4 Signature support - Closes #6088 + Signed-off-by: Matthias Gatto -- urlapi: URL encode a '+' in the query part +- [Matthias Gatto brought this change] + + http: Make the call to v4 signature - ... when asked to with CURLU_URLENCODE. + This patch allow to call the v4 signature introduce in previous commit - Extended test 1560 to verify. - Reported-by: Dietmar Hauser - Fixes #6086 - Closes #6087 + Signed-off-by: Matthias Gatto -- [Cristian Morales Vega brought this change] +- [Matthias Gatto brought this change] - libcurl.pc: make it relocatable + http: introduce AWS HTTP v4 Signature - It supposes when people specify the libdir/includedir they do it to - change where under prefix/exec_prefix it should be, not to make it - independent of prefix/exec_prefix. + It is a security process for HTTP. - Closes #6061 - -- runtests: return error if no tests ran + It doesn't seems to be standard, but it is used by some cloud providers. - ... and make TESTFAIL stand out a little better by adding newlines - before and after. + 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 - Reported-by: Marc Hörsken - Issue: #6052 - Closes #6053 + 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 + + Closes #5703 -- docs/FEATURE: convert to markdown +- [Matthias Gatto brought this change] + + http: add hmac support for sha256 - ... and clean it up a bit. + It seems current hmac implementation use md5 for the hash, + V4 signature require sha256, so I've added the needed struct in + this commit. - Closes #6067 + 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 -- [Philipp Klaus Krause brought this change] +- [Cristian Rodríguez brought this change] - strerror: use 'const' as the string should never be modified + connect: on linux, enable reporting of all ICMP errors on UDP sockets - Closes #6068 + 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 -- [Jay Satiro brought this change] +- 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 - connect: repair build without ipv6 availability +- c-hyper: fix compiler warnings - Assisted-by: Daniel Stenberg - Reported-by: Tom G. Christensen + Identified by clang on windows. - Fixes https://github.com/curl/curl/issues/6069 - Closes https://github.com/curl/curl/pull/6071 + Reported-by: Gisle Vanem + Bug: 58974d25d8173aec154e593ed9d866da566c9811 + + Closes #6351 -- RELEASE-NOTES: synced +- KNOWN_BUGS: Remote recursive folder creation with SFTP - Started over for the journey to next release. + Closes #5204 -- src/tool_filetime: disable -Wformat on mingw for this file +Jay Satiro (20 Dec 2020) +- badsymbols.pl: Add verbose mode -v - With gcc 10 on mingw we otherwise get this warning: + Use -v as the first option to enable verbose mode which will show source + input, extracted symbol and line info. For example: - error: ISO C does not support the 'I' printf flag [-Werror=format=] + Source: ./../include/curl/typecheck-gcc.h + Symbol: curlcheck_socket_info(info) + Line #423: #define curlcheck_socket_info(info) \ - Fixes #6079 - Closes #6082 + Ref: https://curl.se/mail/lib-2020-12/0084.html + + Closes https://github.com/curl/curl/pull/6349 -- test122[12]: remove these two tests +- KNOWN_BUGS: Secure Transport disabling hostname validation also disables SNI - ... and remove the objnames scripts they tested. They're not used for - anything anymore so testing them serves no purpose! + That behavior is a limitation of Apple's Secure Transport. - Reported-by: Marc Hörsken - Fixes #6080 - Closes #6081 + 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 -Version 7.73.0 (14 Oct 2020) +Daniel Stenberg (18 Dec 2020) +- TODO: alt-svc should fallback if alt-svc doesn't work + + Closes #4908 -Daniel Stenberg (14 Oct 2020) -- RELEASE-NOTES: synced +- travis: restrict the openssl3 job to only run https and ftps tests - for 7.73.0 + ... as it runs too long otherwise and the other tests are verified in + other builds anyway. + + Closes #6345 -- THANKS: from 7.73.0 and .mailmap fixes +- build: repair http disabled but mqtt enabled build + + ... as the mqtt code reuses the "method" originally used for HTTP. + + Closes #6344 -- mailmap: fixups of some contributors +- [Jon Wilkes brought this change] -- projects/build-wolfssl.bat: fix the copyright year range + cookie: avoid the C1001 internal compiler error with MSVC 14 + + Fixes #6112 + Closes #6135 -Marc Hoersken (14 Oct 2020) -- [Sergei Nikulov brought this change] +- RELEASE-NOTES: synced - CI/tests: fix invocation of tests for CMake builds +- mqtt: handle POST/PUBLISH without a set POSTFIELDSIZE - Update appveyor.yml to set env variable TFLAGS and run tests - Remove curly braces due to CMake error (${TFLAGS} -> $TFLAGS) - Move testdeps build to build step (per review comments) + Detected by OSS-Fuzz + Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28735 - Reviewed-by: Marc Hörsken + Added test 1916 and 1917 to verify. - Closes #6066 - Fixes #6052 + Closes #6338 -- tests/server/util.c: fix support for Windows Unicode builds - - Detected via #6066 - Closes #6070 +- travis: add CI job for Hyper build -Daniel Stenberg (13 Oct 2020) -- [Jay Satiro brought this change] +- tests: updated tests for Hyper - strerror: Revert to local codepage for Windows error string +- lib: introduce c-hyper for using Hyper - - Change get_winapi_error() to return the error string in the local - codepage instead of UTF-8 encoding. + ... as an alternative HTTP backend within libcurl. + +- tool_setopt: provide helper output in debug builds - Two weeks ago bed5f84 fixed get_winapi_error() to work on xbox, but it - also changed the error string's encoding from local codepage to UTF-8. + ... 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 - We return the local codepage version of the error string because if it - is output to the user's terminal it will likely be with functions which - expect the local codepage (eg fprintf, failf, infof). + As the first (optional) HTTP backend alternative instead of native - This is essentially a partial revert of bed5f84. The support for xbox - remains but the error string is reverted back to local codepage. + Close #6110 + +- test1522: add debug tracing - Ref: https://github.com/curl/curl/pull/6005 + 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. - Reviewed-by: Marcel Raad - Closes #6065 + Closes #6331 -Marc Hoersken (13 Oct 2020) -- CI/tests: use verification curl for test reporting APIs +- http: show the request as headers even when split-sending - Avoid using our own, potentially installed, curl for - the test reporting APIs in case it is broken. + 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. - Reviewed-by: Daniel Stenberg + Extended test 1295 to verify. - Preparation for #6049 - Closes #6063 + Closes #6328 -Viktor Szakats (12 Oct 2020) -- windows: fix comparison of mismatched types warning +- multi: when erroring in TOOFAST state, act as for PERFORM - clang 10, mingw-w64: - ``` - vtls/openssl.c:2917:33: warning: comparison of integers of different signs: 'DWORD' (aka 'unsigned long') and 'HRESULT' (aka 'long') - [-Wsign-compare] - if(GetLastError() != CRYPT_E_NOT_FOUND) - ~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~ - ``` + 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! - Approved-by: Daniel Stenberg - Closes #6062 - -Daniel Stenberg (11 Oct 2020) -- [Viktor Szakats brought this change] + Reported-by: Tomas Berger + Fixes #6333 + Closes #6337 - src/Makefile.m32: fix undefined curlx_dyn_* errors +- cmake: enable gophers correctly in curl-config - by linking `lib/dynbuf.c` when building a static curl binary. - Previously this source file was only included when building - a dynamic curl binary. This was likely possibly because no - functions from the `src/Makefile.inc` / `CURLX_CFILES` sources - were actually required for a curl tool build. This has - recently changed with the introduction of `curlx_dyn_*()` - memory functions and their use by the tool sources. + Closes #6336 + +- test1198/9: add two mqtt publish tests without payload lengths - Closes #6060 + Closes #6335 -- HISTORY: curl verifies SSL certs by default since version 7.10 +- tests/mqttd: extract the client id from the correct offset + + Closes #6334 -Marc Hoersken (8 Oct 2020) -- runtests.pl: use $LIBDIR variable instead of hardcoded path +- TODO: Prevent terminal injection when writing to terminal - Reviewed-by: Daniel Stenberg - Closes #6051 + Closes #6150 -Daniel Stenberg (7 Oct 2020) -- checksrc: detect // comments on column 0 +- Revert "CI/github: work-around for brew breakage on macOS" - Spotted while working on #6045 + This reverts commit 4cbb17a2cbbbe6337142d39479e21c3990b9c22f. - Closes #6048 - -- [Frederik Wedel-Heinen brought this change] - - mbedtls: add missing header when defining MBEDTLS_DEBUG + ... as the work-around now causes failures. - Closes #6045 + Closes #6332 -- curl: make sure setopt CURLOPT_IPRESOLVE passes on a long - - Previously, it would pass on a define (int) which could make libcurl - read junk as a value - which prevented the CURLOPT_IPRESOLVE option to - "take". This could then make test 2100 do two DoH requests instead of - one! +- examples: remove superfluous asterisk uses - Fixes #6042 - Closes #6043 + ... for function pointers. Breaks in ancient compilers. - RELEASE-NOTES: synced -- scripts/release-notes.pl: don't "embed" $ in format string for printf() +- test1272: fix line ending - ... since they might contain %-codes that mess up the output! + Follow-up to f24784f9143 -Jay Satiro (5 Oct 2020) -- [M.R.T brought this change] +- URL-SYNTAX: add gophers details - build-wolfssl: fix build with Visual Studio 2019 - - Closes https://github.com/curl/curl/pull/6033 +- test1272: test gophers -Daniel Stenberg (4 Oct 2020) -- runtests: add %repeat[]% for test files - - ... and use this new keywords in all the test files larger than 50K to reduce - their sizes and make them a lot easier to read and understand. - - Closes #6040 +- runtests: add support for gophers, gopher over TLS -- [Emil Engler brought this change] +- [parazyd brought this change] - --help: move two options from the misc category + gopher: Implement secure gopher protocol. - The cmdline opts delegation and suppress-connect-headers - fit better into auth and proxy rather than misc. + 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). - Follow-up to aa8777f63febc - Closes #6038 - -- [Samanta Navarro brought this change] - - docs/opts: fix typos in two manual pages + 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. - Closes #6039 - -- ldap: reduce the amount of #ifdefs needed + Signed-off-by: parazyd - Closes #6035 + Closes #6208 -- runtests: provide curl's version string as %VERSION for tests - - ... so that we can check HTTP requests for User-Agent: curl/%VERSION +- TODO: Package curl for Windows in a signed installer - Update 600+ test cases accordingly. - - Closes #6037 + Closes #5424 -- checksrc: warn on space after exclamation mark +- mqtt: deal with 0 byte reads correctly - Closes #6034 - -- test1465: verify --libcurl with binary POST data - -- runtests: allow generating a binary sequence from hex - -- tool_setopt: escape binary data to hex, not octal - -- curl: make --libcurl show binary posts correctly + OSS-Fuzz found it + Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28676 - Reported-by: Stephan Mühlstrasser - Fixes #6031 - Closes #6032 + Closes #6327 -Jay Satiro (1 Oct 2020) -- strerror: fix null deref on winapi out-of-memory +- BUG-BOUNTY: minor language update - Follow-up to bed5f84 from several days ago. + ... and remove the wording about entries from before 2019 as the "within + 12 months" is still there and covers that. - Ref: https://github.com/curl/curl/pull/6005 + Closes #6318 -Daniel Stenberg (1 Oct 2020) -- [Kamil Dudka brought this change] - - vtls: deduplicate some DISABLE_PROXY ifdefs +- tooĺ_writeout: fix the -w time output units - ... in the code of gtls, nss, and openssl + Fix regression from commit fc813f80e1bcac (#6248) that changed the unit + to microseconds instead of seconds with fractions - Closes #5735 - -- RELEASE-NOTES: synced + Reported-by: 不确定 + Fixes #6321 + Closes #6322 -- [Emil Engler brought this change] +- quiche: remove fprintf() leftover - TODO: Add OpenBSD libtool notice +Jay Satiro (14 Dec 2020) +- KNOWN_BUGS: SHA-256 digest not supported in Windows SSPI builds - See #5862 - Closes #6030 + Closes https://github.com/curl/curl/issues/6302 -- tests/unit/README: convert to markdown +- digest_sspi: Show InitializeSecurityContext errors in verbose mode - ... and add to dist! + 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: - Closes #6028 - -- tests/README: convert to markdown + --- - Closes #6028 - -- include/README: convert to markdown + * 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 - Closes #6028 + --- + + Ref: https://github.com/curl/curl/issues/6302 + + Closes https://github.com/curl/curl/pull/6315 -- examples/README: convert to markdown +Daniel Stenberg (13 Dec 2020) +- URL-SYNTAX: add default port numbers and IDNA details - Closes #6028 + Closes #6316 -- configure: don't say HTTPS-proxy is enabled when disabled! +- URL-SYNTAX: mention how FILE:// access can access network on windows - Reported-by: Kamil Dudka - Reviewed-by: Kamil Dudka - Bug: https://github.com/curl/curl/pull/5735#issuecomment-701376388 - Closes #6029 + Closes #6314 -Daniel Gustafsson (30 Sep 2020) -- src: Consistently spell whitespace without whitespace +Jay Satiro (12 Dec 2020) +- URL-SYNTAX: Document default SMTP port 25 - Whitespace is spelled without a space between white and space, so - make sure to consistently spell it that way across the codebase. + Note that ports 25 and 587 are common ports for smtp, the former being + the default. - Closes #6023 - Reviewed-by: Daniel Stenberg - Reviewed-by: Emil Engler + Closes https://github.com/curl/curl/pull/6310 -- MANUAL: update examples to resolve without redirects +Daniel Stenberg (12 Dec 2020) +- CURLOPT_URL.3: remove scheme specific details - www.netscape.com is redirecting to a cookie consent form on Aol, and - cool.haxx.se isn't responding to FTP anymore. Replace with examples - that resolves in case users try out the commands when reading the - manual. + ... that are now found in URL-SYNTAX.md - Closes #6024 - Reviewed-by: Daniel Stenberg - Reviewed-by: Emil Engler - -Daniel Stenberg (30 Sep 2020) -- HISTORY: add some 2020 events + Closes #6307 -- sectransp: make it build with --disable-proxy +Dan Fandrich (12 Dec 2020) +- docs: Fix some typos - Follow-up from #5466 and f3d501dc678d80 - Reported-by: Javier Navarro - Fixes #6025 - Closes #6026 + [skip ci] -- ECH: renamed from ESNI in docs and configure - - Encrypted Client Hello (ECH) is the current name. +Daniel Stenberg (12 Dec 2020) +- URL-SYNTAX: mention all supported schemes - Closes #6022 + Closes #6311 -- configure: use "no" instead of "disabled" for the end summary - - ... for consistency but also to make them more distinctly stand out next - to the "enabled" lines. +- [Douglas R. Reno brought this change] -- TODO: SSH over HTTPS proxy with more backends + URL-SYNTAX.md: minor language improvements - ... as right now only the libssh2 backend supports it. + Closes #6308 -- libssh2: handle the SSH protocols done over HTTPS proxy +- docs/URL-SYNTAX: the URL syntax curl accepts and works with - Reported-by: Robin Douine - Fixes #4295 - Closes #6021 + Closes #6285 -- [Emil Engler brought this change] +- [0xflotus brought this change] - memdebug: remove 9 year old unused debug function + docs: enable syntax highlighting in several docs files - There used to be a way to have memdebug fill allocated memory. 9 years - later this has no value there (valgrind and ASAN etc are way better). If - people need to know about it they can have a look at VCS logs. + ... for better readability - Closes #5973 + Closes #6286 -- sendf: move Curl_sendf to dict.c and make it static - - ... as the only remaining user of that function. Also fix gopher.c to - instead use Curl_write() +- test1564/1565: require the 'wakeup' feature to run - Closes #6020 + Fixes #6299 + Fixes #6300 + Closes #6301 -- ROADMAP: updates and cleanups - - Fix the HSTS PR - - Remove DoT, thread-safe init and hard-coded localhost. I feel very - little interest for these with users so I downgrade them to plain "TODO" - entries again. +- runtests: add 'wakeup' as a feature -- schannel: return CURLE_PEER_FAILED_VERIFICATION for untrusted root - - This matches what is returned in other TLS backends in the same - situation. +- tests/server/disabled: add "wakeup" - Reviewed-by: Jay Satiro - Reviewed-by: Emil Engler - Follow-up to 5a3efb1 - Reported-by: iammrtau on github - Fixes #6003 - Closes #6018 + To allow the test suite to know if wakeup support is disabled in the + build. -- RELEASE-NOTES: synced +- lib1564/5: verify that curl_multi_wakeup returns OK -- ftp: make a 552 response return CURLE_REMOTE_DISK_FULL +- tests: make --libcurl tests only test FTP options if ftp enabled - Added test 348 to verify. Added a 'STOR' command to the test FTP - server to enable test 348. Documented the command in FILEFORMAT.md + Adjust six --libcurl tests to only check the FTP option if FTP is + actually present in the build. - Reported-by: Duncan Wilcox - Fixes #6016 - Closes #6017 + Fixes #6303 + Closes #6305 -- pause: only trigger a reread if the unpause sticks +- runtests.pl: fix "uninitialized value" warning - As an unpause might itself get paused again and then triggering another - reread doesn't help. + follow-up to e12825c642a88774 + +- runtests: add support for %if [feature] conditions - Follow-up from e040146f22608fd9 (shipped since 7.69.1) + ... to make tests run differently or expect different results depending + on what features that are present or not in curl. - Bug: https://curl.haxx.se/mail/lib-2020-09/0081.html - Patch-by: Kunal Chandarana - Fixes #5988 - Closes #6013 + Bonus: initial minor 'Hyper' awareness but nothing is using that yet + + Closes #6304 -- test163[12]: require http to be built-in to run +- [Jon Rumsey brought this change] + + OS400: update ccsidcurl.c - ... as speaking over an HTTPS proxy implies http! + Add 'struct' to cast and declaration of cfcdata to fix compilation + error. - Closes #6014 + Fixes #6292 + Closes #6297 -- ngtcp2: adapt to new NGTCP2_PROTO_VER_MAX define +- ngtcp2: make it build it current master again - Closes #6012 + Closes #6296 -- [Javier Blazquez brought this change] +- [Cristian Rodríguez brought this change] - strerror: honor Unicode API choice on Windows + connect: defer port selection until connect() time - Closes #6005 - -- imap: make imap_send use dynbuf for the send buffer management + If supported, defer port selection until connect() time + if --interface is given and source port is 0. - Reuses the buffer and thereby reduces number of mallocs over a transfer. + Reproducer: - Closes #6010 - -- Curl_send: return error when pre_receive_plain can't malloc + * start fast webserver on port 80 + * starve system of ephemeral ports + $ sysctl net.ipv4.ip_local_port_range="60990 60999" - ... will probably trigger some false DEAD CODE positives on non-windows - code analyzers for the conditional code. + * 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" - Closes #6011 - -- ftp: separate FTPS from FTP over "HTTPS proxy" + current result: + (possible some successful data) + curl: (45) bind failed with errno 98: Address already in use - When using HTTPS proxy, SSL is used but not in the view of the FTP - protocol handler itself so separate the connection's use of SSL from the - FTP control connection's sue. + result after patch: + (complete success or few connections failing, higlhy depending on load) - Reported-by: Mingtao Yang - Fixes #5523 - Closes #6006 - -Dan Fandrich (23 Sep 2020) -- tests/data: Fix some mismatched XML tags in test cases + 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. - This allows these test files to pass xmllint. + Closes #6295 -Daniel Stenberg (23 Sep 2020) -- pingpong: use a dynbuf for the *_pp_sendf() function - - ... reuses the same dynamic buffer instead of doing repeated malloc/free - cycles. +- [Hans-Christian Noren Egtvedt brought this change] + + connect: zero variable on stack to silence valgrind complaint - Test case 100 (FTP dir list PASV) does 7 fewer memory allocation calls - after this change in my test setup (132 => 125), curl 7.72.0 needed 140 - calls for this. + Valgrind will complain that ssrem buffer usage if not explicit + initialized, hence initialize it to zero. - Test case 103 makes 9 less allocations now (130). Down from 149 in - 7.72.0. + 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. - Closes #6004 + Signed-off-by: Hans-Christian Noren Egtvedt + Closes #6289 -- dynbuf: add Curl_dyn_vaddf +- RELEASE-NOTES: synced - Closes #6004 + start over on the next release cycle -- dynbuf: make *addf() not require extra mallocs +Version 7.74.0 (9 Dec 2020) + +Daniel Stenberg (9 Dec 2020) +- RELEASE-NOTES: synced - ... by introducing a printf() function that appends directly into a - dynbuf: Curl_dyn_vprintf(). This avoids the mandatory extra malloc so if - the buffer is already big enough it can just printf directly into it. + for 7.74.0 + +Jay Satiro (7 Dec 2020) +- [Jacob Hoffman-Andrews brought this change] + + urldata: restore comment on ssl_connect_data.use - Since this less-malloc version requires tthe use of a library internal - printf function, we only provide this version when building libcurl and - not for the dynbuf code that is used when building the curl tool. + This comment was originally on the `use` field, but was separated from + its field in 62a2534. - Closes #5998 + Closes https://github.com/curl/curl/pull/6287 -- KNOWN_BUGS: Unable to use PKCS12 certificate with Secure Transport +Daniel Stenberg (7 Dec 2020) +- VERSIONS: refreshed - Closes #5403 + We always use the patch number these days: all releases are + "major.minor.patch" -- pingpong: remove a malloc per Curl_pp_vsendf call +- [Jakub Zakrzewski brought this change] + + cmake: don't use reserved target name 'test' - This typically makes 7-9 fewer mallocs per FTP transfer. + CMake up to 3.10 always reserves this name - Closes #5997 + Fixes #6257 + Closes #6258 -- symbian: drop support +- openssl: make the OCSP verification verify the certificate id - The OS is deprecated. I see no traces of anyone having actually built - curl for Symbian after 2012. + CVE-2020-8286 - The public headers are unmodified. + Reported by anonymous - Closes #5989 - -- RELEASE-NOTES: synced + Bug: https://curl.se/docs/CVE-2020-8286.html -- curl_krb5.h: rename from krb5.h +- ftp: make wc_statemach loop instead of recurse - Follow-up from f4873ebd0be32cf + CVE-2020-8285 - Turns out some older openssl installations go bananas otherwise. - Reported-by: Tom van der Woerdt - Fixes #5995 - Closes #5996 - -- test1297: verify GOT_NOTHING with http proxy tunnel + Fixes #6255 + Bug: https://curl.se/docs/CVE-2020-8285.html + Reported-by: xnynx on github -- http_proxy: do not count proxy headers in the header bytecount +- ftp: CURLOPT_FTP_SKIP_PASV_IP by default - ... as that counter is subsequently used to detect if nothing was - returned from the peer. This made curl return CURLE_OK when it should - have returned CURLE_GOT_NOTHING. + The command line tool also independently sets --ftp-skip-pasv-ip by + default. - Fixes #5992 - Reported-by: Tom van der Woerdt - Closes #5994 - -- setopt: return CURLE_BAD_FUNCTION_ARGUMENT on bad argument + Ten test cases updated to adapt the modified --libcurl output. - Fixed two return code mixups. CURLE_UNKNOWN_OPTION is saved for when the - option is, yeah, not known. Clarified this in the setopt man page too. + Bug: https://curl.se/docs/CVE-2020-8284.html + CVE-2020-8284 - Closes #5993 + Reported-by: Varnavas Papaioannou -- krb5: merged security.c and krb specific FTP functions in here +- urlapi: don't accept blank port number field without scheme - These two files were always tightly connected and it was hard to - understand what went into which. This also allows us to make the - ftpsend() function static (moved from ftp.c). + ... 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. - Removed security.c - Renamed curl_sec.h to krb5.h + Reported-by: d4d on hackerone - Closes #5987 + Closes #6283 -- Curl_handler: add 'family' to each protocol - - Makes get_protocol_family() faster and it moves the knowledge about the - "families" to each protocol handler, where it belongs. +- Revert "multi: implement wait using winsock events" - Closes #5986 - -- parsedate: tune the date to epoch conversion + This reverts commit d2a7d7c185f98df8f3e585e5620cbc0482e45fac. - By avoiding an unnecessary error check and the temp use of the tm - struct, the time2epoch conversion function gets a little bit faster. - When repeating test 517, the updated version is perhaps 1% faster (on - one particular build on one particular architecture). + 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. - Closes #5985 + Fixes #6146 + Closes #6281 -- cmake: remove scary warning +- [Klaus Crusius brought this change] + + ftp: retry getpeername for FTP with TCP_FASTOPEN - Remove the text saying + In the case of TFO, the remote host name is not resolved at the + connetion time. - "the curl cmake build system is poorly maintained. Be aware" + 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. - ... not because anything changed just now, but to encourage users to use - it and subsequently improve it. + Fixes #6252 + Closes #6265 + Closes #6282 + +- [Thomas Danielsson brought this change] + + scripts/completion.pl: parse all opts - Closes #5984 + For tab-completion it may be preferable to include all the + available options. + + Closes #6280 -- docs/MQTT: remove outdated paaragraphs +- RELEASE-NOTES: synced -- docs/MQTT: not experimental anymore +- openssl: use OPENSSL_init_ssl() with >= 1.1.0 - Follow-up to e37e4468688d8f + Reported-by: Kovalkov Dmitrii and Per Nilsson + Fixes #6254 + Fixes #6256 + Closes #6260 -- docs/RESOURCES: remove +- SECURITY-PROCESS: disclose on hackerone - This document is not maintained and rather than trying to refresh it, - let's kill it. A more up-to-date document with relevant RFCs is this - page on the curl website: https://curl.haxx.se/rfc/ + Once a vulnerability has been published, the hackerone issue should be + disclosed. For tranparency. - Closes #5980 + Closes #6275 -- docs/TheArtOfHttpScripting: convert to markdown +Marc Hoersken (3 Dec 2020) +- tests/util.py: fix compatibility with Python 2 - Makes it easier to browse on github etc. Offers (better) links. + Backporting the Python 3 implementation of setStream + to ClosingFileHandler as a fallback within Python 2. - It should be noted that this document is already mostly outdated and - "Everything curl" at https://ec.haxx.se/ is a better resource and - tutorial. + Reported-by: Jay Satiro - Closes #5981 + Fixes #6259 + Closes #6270 -- BUGS: convert document to markdown +Daniel Gustafsson (3 Dec 2020) +- docs: fix typos and markup in ETag manpage sections - Closes #5979 + Reported-by: emanruse on github + Fixes #6273 -- --help: strdup the category - - ... since it is converted and the original pointer is freed on Windows - unicode handling. +Daniel Stenberg (2 Dec 2020) +- quiche: close the connection - Follow-up to aa8777f63febc - Fixes #5977 - Closes #5978 - Reported-by: xwxbug on github + Reported-by: Junho Choi + Fixes #6213 + Closes #6217 -- CHECKSRC: document two missing warnings +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 -- RELEASE-NOTES: synced +Daniel Stenberg (1 Dec 2020) +- [Klaus Crusius brought this change] -- ftp: avoid risk of reading uninitialized integers + cmake: check for linux/tcp.h - If the received PASV response doesn't match the expected pattern, we - could end up reading uninitialized integers for IP address and port - number. + The HAVE_LINUX_TCP_H define was not set by cmake. - Issue pointed out by muse.dev - Closes #5972 - -- [Quentin Balland brought this change] + Closes #6252 - easy_reset: clear retry counter +- NEW-PROTOCOL: document what needs to be done to add one - Closes #5975 - Fixes #5974 + Closes #6263 -- ftp: get rid of the PPSENDF macro +- splay: rename Curl_splayremovebyaddr to Curl_splayremove - The use of such a macro hides some of what's actually going on to the - reader and is generally disapproved of in the project. + ... and remove the old unused proto for the old Curl_splayremove + version. - Closes #5971 + Closes #6269 -- man pages: switch to https://example.com URLs +- openssl: free mem_buf in error path - Since HTTPS is "the new normal", this update changes a lot of man page - examples to use https://example.com instead of the previous "http://..." + To fix a memory-leak. - Closes #5969 + Closes #6267 -- github: remove the duplicate "Security vulnerability" entry +- openssl: remove #if 0 leftover - ... since github adds an entry automatically by itself. + Follow-up to 4c9768565ec3a9 (from Sep 2008) - Closes #5970 - -- [Emil Engler brought this change] + Closes #6268 - github: use new issue template feature +- ntlm: avoid malloc(0) on zero length user and domain - This helps us to avoid getting feature requests as well as security - bugs reported into the issue tracker. + ... and simplify the too-long checks somewhat. - Closes #5936 + Detected by OSS-Fuzz + + Closes #6264 -- [Emil Engler brought this change] +- RELEASE-NOTES: synced - urlapi: use more Curl_safefree +Marc Hoersken (28 Nov 2020) +- tests/server/tftpd.c: close upload file in case of abort - Closes #5968 - -Marc Hoersken (17 Sep 2020) -- multi: align WinSock mask variables in Curl_multi_wait - - Also skip pre-checking sockets to set timeout_ms to 0 - after the first socket has been detected to be ready. + Commit c353207 removed the closing right after do_tftp + which covered the case of abort. This handles that case. - Reviewed-by: rcombs on github + Reviewed-by: Jay Satiro Reviewed-by: Daniel Stenberg - Follow up to #5886 + Follow up to #6209 + Closes #6234 -- multi: reuse WinSock events variable in Curl_multi_wait - - Since the struct is quite large (1 long and 10 ints) we - declare it once at the beginning of the function instead - of multiple times inside loops to avoid stack movements. - - Reviewed-by: Viktor Szakats - Reviewed-by: Daniel Stenberg - - Closes #5886 +Daniel Stenberg (26 Nov 2020) +- [Daiki Ueno brought this change] -Daniel Stenberg (16 Sep 2020) -- TODO: dynamically decide to use socketpair + ngtcp2: use the minimal version of QUIC supported by ngtcp2 - Suggested-by: Anders Bakken + Closes #6250 + +- [Daiki Ueno brought this change] + + ngtcp2: advertise h3 ALPN unconditionally - Closes #4829 + Closes #6250 -- TODO: add PR reference for native IDN support on macOS +- [Daiki Ueno brought this change] + + vquic/ngtcp2.h: define local_addr as sockaddr_storage - As there was work started on this that never got completed. + This field needs to be wide enough to hold sockaddr_in6 when + connecting via IPv6. Otherwise, ngtcp2_conn_read_pkt will drop the + packets because of the address mismatch: + I00000022 [...] con ignore packet from unknown path - Closes #5371 - -- tool_help.h: update copyright year range + We can safely assume that struct sockaddr_storage is available, as it + is used in the public interface of ngtcp2. - Follow-up from aa8777f63febca + Closes #6250 -- CI/azure: disable test 571 in the msys2 builds +- socks: check for DNS entries with the right port number - It's just too flaky there + The resolve call is done with the right port number, but the subsequent + check used the wrong one, which then could find a previous resolve which + would return and leave the fresh resolve "incomplete" and leaking + memory. - Reviewed-by: Marc Hoersken - Closes #5954 + Fixes #6247 + Closes #6253 -- tool_writeout: protect fputs() from NULL +- curl_setup: USE_RESOLVE_ON_IPS is for Apple native resolver use - When the code was changed to do fputs() instead of fprintf() it got - sensitive for NULL pointers; add checks for that. + ... so don't define it when instructed to use c-ares! + +- test506: make it not run in c-ares builds - Follow-up from 0c1e767e83ec66 + As the asynch nature of it may trigger events in another order. A c-ares + upgrade made it break. - Closes #5963 + Reported-by: Marc Hörsken + Fixes #6247 -- test3015: verify stdout "as text" - - Follow-up from 0c1e767e83e to please win32 tests +- runtests: make 'c-ares' a "feature" to depend on - Closes #5962 + ... also added to the docs. -- travis: use libressl v3.1.4 instead of master +- tool_writeout: use off_t getinfo-types instead of doubles - ... as their git master seems too fragile to use (and 3.2.1 which is the - latest has a build failure). + Commit 3b80d3ca46b12e52342 (June 2017) introduced getinfo replacement + variables that use curl_off_t instead of doubles. Switch the --write-out + function over to use them. - Closes #5964 + Closes #6248 -- tests/FILEFORMAT: document type=shell for +- [Emil Engler brought this change] -- tests/FILEFORMAT: document nonewline support for + file: avoid duplicated code sequence - The one in , that creates files. + file_disconnect() is identical with file_do() except the function header + but as the arguments are unused anyway so why not just return file_do() + directly! - Follow-up from b83947c8df7 + Reviewed-by: Daniel Stenberg + Closes #6249 -- [anio brought this change] +- [Rikard Falkeborn brought this change] - tool_writeout: add new writeout variable, %{num_headers} + infof/failf calls: fix format specifiers - This variable gives the number of headers. + Update a few format specifiers to match what is being printed. - Closes #5947 + Closes #6241 -- tool_urlglob: fix compiler warning "unreachable code" +- docs/INTERNALS: remove reference to Curl_sendf() - (On Windows builds.) + The function has been removed from common usage. Also removed comment in + gopher.c that still referenced it. - Follow-up to 70a3b003d9 + Reported-by: Rikard Falkeborn + Fixes #6242 + Closes #6243 -- [Gergely Nagy brought this change] +- [Rikard Falkeborn brought this change] - vtls: deduplicate client certificates in ssl_config_data + examples: update .gitignore - Closes #5629 - -- ftp: a 550 response to SIZE returns CURLE_REMOTE_FILE_NOT_FOUND + Add files that are generated by 'make examples' and remove some that + have been renamed. - This is primarily interesting for cases where CURLOPT_NOBODY is set as - previously curl would not return an error for this case. + The commits that renamed the programs are e9625c5bc6c046a (imap.c and + simplesmtp.c were renamed to imap-fetch.c and smtp-send.c) and + ad39e7ec01e7 (pop3slist.c and pop3s.c were renamed to pop3-list.c and + pop3-ssl.c). - MDTM getting 550 now also returns this error (it returned - CURLE_FTP_COULDNT_RETR_FILE before) in order to unify return codes for - missing files across protocols and specific FTP commands. + Closes #6240 + +- asyn: use 'struct thread_data *' instead of 'void *' - libcurl already returns error on a 550 as a MDTM response (when - CURLOPT_FILETIME is set). If CURLOPT_NOBODY is not set, an error would - happen subsequently anyway since the RETR command would fail. + To reduce use of types that can't be checked at compile time. Also + removes several typecasts. - Add test 1913 and 1914 to verify. Updated several tests accordingly due - to the updated SIZE behavior. + ... and rename the struct field from 'os_specific' to 'tdata'. - Reported-by: Tomas Berger - Fixes #5953 - Closes #5957 + Closes #6239 + Reviewed-by: Jay Satiro -- curl: make checkpasswd use dynbuf +Viktor Szakats (23 Nov 2020) +- Makefile.m32: add support for UNICODE builds - Closes #5952 - -- curl: make glob_match_url use dynbuf + It requires the linker to support the `-municode` option. + This is available in more recent mingw-w64 releases. - Closes #5952 - -- curl: make file2memory use dynbuf + Ref: https://gcc.gnu.org/onlinedocs/gcc/x86-Windows-Options.html + Ref: https://stackoverflow.com/questions/3571250/wwinmain-unicode-and-mingw/11706847#11706847 - Closes #5952 - -- curl: make file2string use dynbuf + Reviewed-by: Jay Satiro + Reviewed-by: Marcel Raad - Closes #5952 - -- [Antarpreet Singh brought this change] + Closes #6228 - imap: set cselect_bits to CURL_CSELECT_IN initially - - ... when continuing a transfer from a FETCH response. +Daniel Stenberg (23 Nov 2020) +- urldata: remove 'void *protop' and create the union 'p' - When the size of the file was small enough that the entirety of the - transfer happens in a single go and schannel buffers holds the entire - data. However, it wasn't completely read in Curl_pp_readresp since a - line break was found before that could happen. So, by the time we are in - imap_state_fetch_resp - there's data in buffers that needs to be read - via Curl_read but nothing to read from the socket. After we setup a - transfer (Curl_setup_transfer), curl just waits on the socket state to - change - which doesn't happen since no new data ever comes. + ... to avoid the use of 'void *' for the protocol specific structs done + per transfer. - Closes #5961 - -- RELEASE-NOTES: synced + Closes #6238 -- test434: test -K use in a single line without newline +- winbuild: remove docs from Makefiles and refer to README.md - Closes #5946 - -- runtests: allow creating files without newlines + Reduce risk for conflicting docs and makes it to a single place to fix + and polish. - Closes #5946 - -- curl: use curlx_dynbuf for realloc when loading config files + add these missing options to the readme: - ... fixes an integer overflow at the same time. + ENABLE_OPENSSL_AUTO_LOAD_CONFIG and ENABLE_UNICODE - Reported-by: ihsinme on github - Assisted-by: Jay Satiro + clarify ENABLE_SCHANNEL default varies - Closes #5946 + Fixes #6216 + Closes #6227 + Co-Authored-by: Jay Satiro -- dynbuf: provide curlx_ names for reuse by the curl tool +- [Daiki Ueno brought this change] + + http3: use the master branch of GnuTLS for testing - Closes #5946 + Closes #6235 -- dynbuf: make sure Curl_dyn_tail() zero terminates +- KNOWN_BUGS: curl with wolfSSL lacks support for renegotiation - Closes #5959 + Closes #5839 -- tests: add test1912 to the dist +- KNOWN_BUGS: wakeup socket disconnect causes havoc - Follow-up to 70984ce1be4cab6c + Closes #6132 + Closes #6133 -- docs/LICENSE-MIXING: remove +- RELEASE-NOTES: synced + +- [Oliver Urbann brought this change] + + curl: add compatibility for Amiga and GCC 6.5 - This document is not maintained and I feel that it doesn't provide much - value to users anymore (if it ever did). + Changes are mainly reordering and adding of includes required + to compile with a more recent version of GCC. - Closes #5955 - -- [Laramie Leavitt brought this change] + Closes #6220 - http: consolidate nghttp2_session_mem_recv() call paths +Marc Hoersken (20 Nov 2020) +- tests/server/tftpd.c: close upload file right after transfer - Previously there were several locations that called - nghttp2_session_mem_recv and handled responses slightly differently. - Those have been converted to call the existing - h2_process_pending_input() function. + Make sure uploaded file is no longer locked after the + transfer while waiting for the final ACK to be handled. - Moved the end-of-session check to h2_process_pending_input() since the - only place the end-of-session state can change is after nghttp2 - processes additional input frames. + Assisted-by: Daniel Stenberg - This will likely fix the fuzzing error. While I don't have a root cause - the out-of-bounds read seems like a use after free, so moving the - nghttp2_session_check_request_allowed() call to a location with a - guaranteed nghttp2 session seems reasonable. - - Also updated a few nghttp2 callsites to include error messages and added - a few additional error checks. - - Closes #5648 - -- HISTORY: mention alt-svc added in 2019 - - ... and make 1996 the first year subtitle + Bug: #6058 + Closes #6209 -- base64: also build for pop3 and imap - - Follow-up to the fix in 20417a13fb8f83 +- CI/cirrus: simplify logic for disabled tests - Reported-by: Michael Olbrich - Fixes #5937 - Closes #5948 - -- base64: enable in build with SMTP + The OpenSSH server instance for the testsuite cannot + be started on FreeBSD, therefore the SFTP and SCP + tests are disabled right away from the beginning. - The oauth2 support is used with SMTP and it uses base64 functions. + The previous OS version specific logic for SKIP_TESTS + is no longer needed/used and can therefore be removed. - Reported-by: Michael Olbrich - Fixes #5937 - Closes #5938 - -- curl_mime_headers.3: fix the example's use of curl_slist_append + Reviewed-by: Daniel Stenberg - Reported-by: sofaboss on github - Fixes #5942 - Closes #5943 + Follow up to #6211 + Closes #6229 -- lib583: fix enum mixup +Daniel Gustafsson (20 Nov 2020) +- mailmap: Daniel Hwang - grrr the previous follow-up to 17fcdf6a31 was wrong - -- libtest: fix build errors + Add Daniel Hwang to the mailmap to cover the alternative spelling + Daniel Lee Hwang which was used in one commit. - Follow-up from 17fcdf6a310d4c8076 + Closes #6230 + Reviewed-by: Daniel Stenberg -- lib: fix -Wassign-enum warnings +- openssl: guard against OOM on context creation - configure --enable-debug now enables -Wassign-enum with clang, - identifying several enum "abuses" also fixed. + EVP_MD_CTX_create will allocate memory for the context and returns + NULL in case the allocation fails. Make sure to catch any allocation + failures and exit early if so. - Reported-by: Gisle Vanem - Bug: https://github.com/curl/curl/commit/879007f8118771f4896334731aaca5850a154675#commitcomment-42087553 + In passing, also move to EVP_DigestInit rather than EVP_DigestInit_ex + as the latter is intended for ENGINE selection which we don't do. - Closes #5929 - -- RELEASE-NOTES: synced + Closes #6224 + Reviewed-by: Daniel Stenberg + Reviewed-by: Emil Engler -- [Diven Qi brought this change] +Daniel Stenberg (19 Nov 2020) +- [Vincent Torri brought this change] - url: use blank credentials when using proxy w/o username and password - - Fixes proxy regression brought in commit ad829b21ae (7.71.0) + cmake: use libcurl.rc in all Windows builds - Fixed #5911 - Closes #5914 + Reviewed-by: Marcel Raad + Closes #6215 -- travis: add a build using libressl (from git master) +- [Cristian Morales Vega brought this change] + + cmake: make CURL_ZLIB a tri-state variable - The v3.2.1 tag (latest release atm) results in a broken build. + By differentiating between ON and AUTO it can make a missing zlib + library a hard error when CURL_ZLIB=ON is used. - Closes #5932 + Reviewed-by: Jakub Zakrzewski + Closes #6221 + Fixes #6173 -- configure: let --enable-debug set -Wenum-conversion with gcc >= 10 +- quiche: remove 'static' from local buffer - Unfortunately, this option is not detecting the same issues as clang's - -Wassign-enum flag, but should still be useful to detect future - mistakes. + For thread-safety - Closes #5930 + Closes #6223 -- openssl: consider ALERT_CERTIFICATE_EXPIRED a failed verification - - If the error reason from the lib is - SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED, libcurl will return - CURLE_PEER_FAILED_VERIFICATION and not CURLE_SSL_CONNECT_ERROR. +- KNOWN_BUGS: cmake: libspsl is not supported - This unifies the libcurl return code and makes libressl run test 313 - (CRL testing) fine. + Closes #6214 + +- KNOWN_BUGS: cmake autodetects cert paths when cross-compiling - Closes #5934 + Closes #6178 -- FAQ: refreshed some very old language +- KNOWN_BUGS: cmake build doesn't fail if zlib not found + + Closes #6173 -- cmake: make HTTP_ONLY also disable MQTT +- KNOWN_BUGS: cmake libcurl.pc uses absolute library paths - ... and alphasort the order of disabling protocols to make it easier to - browse. + Closes #6169 + +- KNOWN_BUGS: cmake: generated .pc file contains strange entries - Closes #5931 + Closes #6167 -- libtest: remove lib1541 leftovers +- KNOWN_BUGS: cmake uses -lpthread instead of Threads::Threads - Caused automake errors. + Closes #6166 + +- KNOWN_BUGS: cmake build in Linux links libcurl to libdl - Follow-up to 8ca54a03ea08a + Closes #6165 -- tests/libtests: remove test 1900 and 2033 +- KNOWN_BUGS: make a new section for cmake topics - We already remove the test files, now remove the libtest codes as well. + Closes #6219 + +- [Emil Engler brought this change] + + cirrus: build with FreeBSD 12.2 in CirrusCI - Follow-up to e50a877df74 + Closes #6211 -Marc Hoersken (7 Sep 2020) -- CI/azure: add test number to title for display in analytics +Marc Hoersken (14 Nov 2020) +- tests/*server.py: close log file after each log line - To ease identification of tests the test number is added to - the test case title in order to have it on the Azure DevOps - Analytics pages and reports which currently do not show it. + Make sure the log file is not locked once a test has + finished and align with the behavior of our logmsg. - Bump test case revision to make Azure DevOps update titles. + Rename curl_test_data.py to be a general util.py. + Format and sort Python imports with isort/VSCode. - Closes #5927 + Bug: #6058 + Closes #6206 -Daniel Stenberg (6 Sep 2020) -- altsvc: clone setting in curl_easy_duphandle - - The cache content is not duplicated, like other caches, but the setting - and specified file name are. - - Test 1908 is extended to verify this somewhat. Since the duplicated - handle gets the same file name, the test unfortunately overwrites the - same file twice (with different contents) which makes it hard to check - automatically. +Daniel Stenberg (13 Nov 2020) +- CURLOPT_HSTS.3: document the file format - Closes #5923 + Closes #6205 -- test1541: remove since it is a known bug +- RELEASE-NOTES: synced + +- release-notes.pl: detect #[number] better for Ref: etc + +- curl: only warn not fail, if not finding the home dir - A shared connection cache is not thread-safe is a known issue. Stop - testing this until we believe this issue is addressed. Reduces - occasional test failures we don't care about. + ... as there's no good reason to error out completely. - The test code in lib1541.c is left in git to allow us to restore it when - we get to fix this. + Reported-by: Andreas Fischer + Fixes #6200 + Closes #6201 + +- httpput-postfields.c: new example doing PUT with POSTFIELDS - Closes #5922 + Proposed-by: Jeroen Ooms + Ref: #6186 + Closes #6188 -- tests: remove pipelining tests +- [Tobias Hieta brought this change] + + cmake: correctly handle linker flags for static libs - Remove the tests 530, 584, 1900, 1901, 1902, 1903 and 2033. They were - previously disabled. + curl CMake was setting the the EXE flags for static libraries which made + the /manifest:no flag ended up when linking the static library, which is + not a valid flag for lib.exe or llvm-lib.exe and caused llvm-lib to exit + with an error. - The Pipelining code was removed from curl in commit 2f44e94efb3df8e, - April 2019. + The better way to handle this is to make sure that we pass the correct + linker flags to CMAKE_STATIC_LINKER_FLAGS instead. - Closes #5921 + Reviewed-by: Jakub Zakrzewski + Closes #6195 -- curl: retry delays in parallel mode no longer sleeps blocking - - The previous sleep for retries would block all other concurrent - transfers. Starting now, the retry will instead be properly marked to - not get restarted until after the delay time but other transfers can - still continue in the mean time. - - Closes #5917 +- [Tobias Hieta brought this change] -- curl:parallel_transfers: make sure retry readds the transfer + cmake: don't pass -fvisibility=hidden to clang-cl on Windows - Reported-by: htasta on github - Fixes #5905 - Closes #5917 - -- build: drop support for building with Watcom + When using clang-cl on windows -fvisibility=hidden is not an known + argument. Instead it behaves exactly like MSVC in this case. So let's + make sure we take that path. - These files are not maintained, they seem to have no users, Watcom - compilers look like not having users nor releases anymore. + In CMake clang-cl sets both CMAKE_C_COMPILER_ID=clang and MSVC get's + defined since clang-cl is basically a MSVC emulator. So guarding like we + do in this patch seems logical. - Closes #5918 + Reviewed-by: Jakub Zakrzewski + Closes #6194 -- winbuild/rundebug.cmd: remove +- http_proxy: use enum with state names for 'keepon' - Seems to have been added by mistake? Not included in dists. + To make the code clearer, change the 'keepon' from an int to an enum + with better state names. - Closes #5919 + Reported-by: Niranjan Hasabnis + Bug: https://curl.se/mail/lib-2020-11/0026.html + Closes #6193 -- curl: in retry output don't call all problems "transient" +- curl_easy_escape: limit output string length to 3 * max input - ... because when --retry-all-errors is used, the error isn't necessarily - transient at all. + ... instead of the limiting it to just the max input size. As every + input byte can be expanded to 3 output bytes, this could limit the input + string to 2.66 MB instead of the intended 8 MB. - Closes #5916 + Reported-by: Marc Schlatter + Closes #6192 -- easygetopt: pass a valid enum to avoid compiler warning +- docs: document the 8MB input string limit - "integer constant not in range of enumerated type 'CURLoption'" + for curl_easy_escape and curl_easy_setopt() - Reported-by: Gisle Vanem - Bug: https://github.com/curl/curl/commit/6ebe63fac23f38df911edc348e8ccc72280f9434#commitcomment-42042843 + The limit is there to catch mistakes and abuse. It is meant to be large + enough to allow virtually all "fine" use cases. - Closes #5915 - -- [Emil Engler brought this change] + Reported-by: Marc Schlatter + Fixes #6190 + Closes #6191 - tests: Add tests for new --help - - This commit is a part of "--help me if you can" +- mqttd: fclose test file when done - Closes #5680 - -- [Emil Engler brought this change] + Reported-by: Marc Hörsken + Reviewed-by: Jay Satiro + Bug: #6058 + Closes #6189 - tool: update --help with categories - - This commit is a part of "--help me if you can" - - Closes #5680 +- RELEASE-NOTES: synced -- [Emil Engler brought this change] +- THANKS-filter: ignore autobuild links - docs: add categories to all cmdline opts +- Revert "libcurl.pc: make it relocatable" - Adapted gen.pl with 'listcats' + This reverts commit 3862c37b6373a55ca704171d45ba5ee91dec2c9f. - This commit is a part of "--help me if you can" + That fix should either be done differently or with an option. - Closes #5680 + Reported-by: asavah on github + Fixes #6157 + Closes #6183 -- RELEASE-NOTES: synced +- examples/httpput: remove use of CURLOPT_PUT + + It is deprecated and unnecessary since it already sets CURLOPT_UPLOAD. + + Reported-by: Jeroen Ooms + Fixes #6186 + Closes #6187 -- [ihsinme brought this change] +- Curl_pgrsStartNow: init speed limit time stamps at start + + By setting the speed limit time stamps unconditionally at transfer + start, we can start off a transfer without speed limits and yet allow + them to get set during transfer and have an effect. + + Reported-by: Kael1117 on github + Fixes #6162 + Closes #6184 - connect.c: remove superfluous 'else' in Curl_getconnectinfo +- ngtcp2: adapt to recent nghttp3 updates - Closes #5912 + 'reset_stream' was added to the nghttp3_conn_callbacks struct + + Closes #6185 -- [Samuel Marks brought this change] +- configure: pass -pthread to Libs.private for pkg-config + + Reported-by: Cristian Morales Vega + Fixes #6168 + Closes #6181 - CMake: remove explicit `CMAKE_ANSI_CFLAGS` +- altsvc: minimize variable scope and avoid "DEAD_STORE" - This variable was removed from cmake in commit - https://gitlab.kitware.com/cmake/cmake/commit/5a834b0bb0bc288. A later - CMake commit removes the variable from the tests, claiming that it was - removed in CMake 2.6 + Closes #6182 + +- FAQ: remove "Why is there a HTTP/1.1 in my HTTP/2 request?" - Reviewed-By: Peter Wu - Closes #5439 + This hasn't been the case for a while now, remove. -- [cbe brought this change] +- FAQ: refresh "Why do I get "certificate verify failed" + + Add more details, remove references to ancient curl version. - libssh2: pass on the error from ssh_force_knownhost_key_type +- test493: verify --hsts upgrade and that %{url_effective} reflects that - Closes #5909 + Closes #6175 -- scripts/delta: add diffstat summary +- url: make sure an HSTS upgrade updates URL and scheme correctly - ... and make output more table-like + Closes #6175 -- [Martin Bašti brought this change] +- tool_operate: set HSTS with CURLOPT_HSTS to pass on filename + + Closes #6175 - http_proxy: do not crash with HTTPS_PROXY and NO_PROXY set +- hsts: remove debug code leftovers - ... in case NO_PROXY takes an effect + Closes #6175 + +- FAQ: refreshed - Without this patch, the following command crashes: + - remove a few ancient questions + - add configure with static libs question + - updated wording in several places + - lowercased curl - $ GIT_CURL_VERBOSE=1 NO_PROXY=github.com HTTPS_PROXY=https://example.com \ - git clone https://github.com/curl/curl.git + Closes #6177 + +Daniel Gustafsson (5 Nov 2020) +- examples: fix comment syntax - Minimal libcurl-based reproducer: + Commit ac0a88fd2 accidentally added a stray character outside of the + comment which broke compilation. Fix by removing. - #include + Reported-by: autobuild https://curl.se/dev/log.cgi?id=20201105084306-12742 + +- hsts: Remove pointless call to free in errorpath - int main() { - CURL *curl = curl_easy_init(); - if(curl) { - CURLcode ret; - curl_easy_setopt(curl, CURLOPT_URL, "https://github.com/"); - curl_easy_setopt(curl, CURLOPT_PROXY, "example.com"); - /* set the proxy type */ - curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS); - curl_easy_setopt(curl, CURLOPT_NOPROXY, "github.com"); - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - ret = curl_easy_perform(curl); - curl_easy_cleanup(curl); - return ret; - } - return -1; - } + The line variable will always be NULL in the error path, so remove + the free call since it's pointless. - Assisted-by: Kamil Dudka - Bug: https://bugzilla.redhat.com/1873327 - Closes #5902 + Closes #6170 + Reviewed-by: Daniel Stenberg -- travis: add a CI job with openssl3 (from git master) +- docs: Fix various typos in documentation - Closes #5908 + Closes #6171 + Reviewed-by: Daniel Stenberg -- openssl: avoid error conditions when importing native CA +Daniel Stenberg (5 Nov 2020) +- copyright: fix year ranges - The code section that is OpenSSL 3+ specific now uses the same logic as - is used in the version < 3 section. It caused a compiler error without - it. + Follow-up from 4d2f8006777 + +- HISTORY: the new domain + +- curl.se: new home - Closes #5907 + Closes #6172 -- setopt: avoid curl_ on local variable +- KNOWN_BUGS: FTPS with Schannel times out file list operation - Closes #5906 + Reported-by: bobmitchell1956 on github + Closes #5284 -- mqtt.c: avoid curl_ prefix on local variable +- KNOWN_BUGS: SMB tests fail with Python 2 - Closes #5906 + Reported-by: Jay Satiro + Closes #5983 -- wildcard: strip "curl_" prefix from private symbols +- KNOWN_BUGS: LDAPS with NSS is slow - Closes #5906 + Reported-by: nosajsnikta on github + Closes #5874 -- vtls: make it 'struct Curl_ssl_session' +Sergei Nikulov (4 Nov 2020) +- travis: use ninja-build for CMake builds - Use uppercase C for internal symbols. + Added package ninja-build to environment + Use ninja to speed up CMake builds - Closes #5906 + Closes #6077 -- curl_threads: make it 'struct Curl_actual_call' - - Internal names should not be prefixed "curl_" +Daniel Stenberg (4 Nov 2020) +- [Harry Sintonen brought this change] + + rtsp: error out on empty Session ID, unified the code + +- [Harry Sintonen brought this change] + + rtsp: fixed the RTST Session ID mismatch in test 570 - Closes #5906 + Closes #6161 -- schannel: make it 'struct Curl_schannel*' +- [Harry Sintonen brought this change] + + rtsp: fixed Session ID comparison to refuse prefix - As internal global names should use captical C. + Closes #6161 + +- RELEASE-NOTES: synced - Closes #5906 + (forgot to update the list of contributors) -- hash: make it 'struct Curl_hash' +- RELEASE-NOTES: synced + +- curlver: bumped to 7.74.0 + +- hsts: add read/write callbacks - As internal global names should use captical C. + - read/write callback options + - man pages for the 4 new setopts + - test 1915 verifies the callbacks - Closes #5906 + Closes #5896 -- llist: make it "struct Curl_llist" +- hsts: add support for Strict-Transport-Security - As internal global names should use captical C. + - enable in the build (configure) + - header parsing + - host name lookup + - unit tests for the above + - CI build + - CURL_VERSION_HSTS bit + - curl_version_info support + - curl -V output + - curl-config --features + - CURLOPT_HSTS_CTRL + - man page for CURLOPT_HSTS_CTRL + - curl --hsts (sets CURLOPT_HSTS_CTRL and works with --libcurl) + - man page for --hsts + - save cache to disk + - load cache from disk + - CURLOPT_HSTS + - man page for CURLOPT_HSTS + - added docs/HSTS.md + - fixed --version docs + - adjusted curl_easy_duphandle - Closes #5906 + Closes #5896 -Marc Hoersken (2 Sep 2020) -- telnet.c: depend on static requirement of WinSock version 2 +- [Sergei Nikulov brought this change] + + CI/tests: enable test target on TravisCI for CMake builds - Drop dynamic loading of ws2_32.dll and instead rely on the - imported version which is now required to be at least 2.2. + Added test-nonflaky target to CMake builds - Reviewed-by: Marcel Raad - Reviewed-by: Jay Satiro - Reviewed-by: Daniel Stenberg - Reviewed-by: Viktor Szakats + Disabled test 1139 because the cmake build doesn't create docs/curl.1 - Closes #5854 + Closes #6074 -- win32: drop support for WinSock version 1, require version 2 - - IPv6, telnet and now also the multi API require WinSock - version 2 which is available starting with Windows 95. - - Therefore we think it is time to drop support for version 1. - - Reviewed-by: Marcel Raad - Reviewed-by: Jay Satiro - Reviewed-by: Daniel Stenberg - Reviewed-by: Viktor Szakats +- tool_debug_cb: do not assume zero-terminated data - Follow up to #5634 - Closes #5854 + Follow-up to d70a5b5a0f5e3 -- select: align poll emulation to return all relevant events +- sendf: move the verbose-check into Curl_debug - The poll emulation via select already consumes POLLRDNORM, - POLLWRNORM and POLLRDBAND as input events. Therefore it - should also return them as output events if signaled. + Saves us from having the same check done everywhere. - Also fix indentation in input event handling block. + Closes #6159 + +- travis: use valgrind when running tests for debug builds - Assisted-by: Jay Satiro - Reviewed-by: Daniel Stenberg + Except the non-x86 and sanitizer builds - Replaces #5852 - Closes #5883 + Closes #6154 -- CI/azure: MQTT is now enabled by default - - Reviewed-by: Daniel Stenberg +- header.d: fix syntax mistake - Follow up to #5858 - Closes #5903 + follow-up from 1144886f38fd0 -Daniel Stenberg (2 Sep 2020) -- copyright.pl: ignore buildconf +- [Harry Sintonen brought this change] -- test971: show test mismatches "inline" + gnutls: fix memory leaks (certfields memory wasn't released) + + Closes #6153 -- lib/Makefile.am: bump VERSIONINFO due to new functions +- tests: add missing global_init/cleanup calls - ... we're generally bad at this, but we are adding new functions for - this release. + Without the cleanup call in these test files, the mbedTLS backend leaks + memory. - Closes #5899 + Closes #6156 -- optiontable: use DEBUGBUILD +- tool_operate: --retry for HTTP 408 responses too - Follow-up to commit 6e18568ba38 (#5877) - -- cmdline-opts/gen.pl: generate nicer "See Also" in curl.1 + This was inadvertently dropped from the code when the parallel support + was added. - If there are more than two items in the list, use commas for all but the - last separator which is set to 'and'. Reads better. + Regression since b88940850 (7.66.0) - Closes #5898 + Reviewed-by: Jay Satiro + Closes #6155 -- curl.1: add see also no-progress-meter on two spots +- http: pass correct header size to debug callback for chunked post - Ref: #5894 + ... when the chunked framing was added, the size of the "body part" of + the data was calculated wrongly so the debug callback would get told a + header chunk a few bytes too big that would also contain the first few + bytes of the request body. - Closes #5897 + Reported-by: Dirk Wetter + Ref: #6144 + Closes #6147 -- RELEASE-NOTES: synced +- header.d: mention the "Transfer-Encoding: chunked" handling + + Ref: #6144 + Closes #6148 -- mqtt: enable by default +- acinclude: detect manually set minimum macos/ipod version - No longer considered experimental. + ... even if set in the CC or IPHONEOS/MACOSX_DEPLOYMENT_TARGET + variables. - Closes #5858 - -- [Michael Baentsch brought this change] + Reported-by: hamstergene on github + Fixes #6138 + Closes #6140 - tls: add CURLOPT_SSL_EC_CURVES and --curves +Jay Satiro (29 Oct 2020) +- tests: fix some http/2 tests for older versions of nghttpx - Closes #5892 + - Add regex that strips http/2 server header name to those http/2 tests + that don't already have it. + + - Improve that regex in all http/2 tests. + + Tests 358 and 359 were failing for me before this change on a system + that uses an older version of nghttpx which includes its version number + in the server header. + + Closes https://github.com/curl/curl/pull/6139 -- url: remove funny embedded comments in Curl_disonnect calls +Daniel Stenberg (30 Oct 2020) +- RELEASE-NOTES: synced -- [Chris Paulson-Ellis brought this change] +- [Cristian Morales Vega brought this change] - conn: check for connection being dead before reuse - - Prevents incorrect reuse of an HTTP connection that has been prematurely - shutdown() by the server. + configure: use pkgconfig to find openSSL when cross-compiling - Partial revert of 755083d00deb16 + This reverts 736a40fec (November 2004), which doesn't explain why it was + done. - Fixes #5884 - Closes #5893 + Closes #6145 -Marc Hoersken (29 Aug 2020) -- buildconf: exec autoreconf to avoid additional process - - Also make buildconf exit with the return code of autoreconf. +- tool_operate: bail out proper on errors for parallel setup - Reviewed-by: Daniel Stenberg + ... otherwise for example trying to upload a missing file just causes a + loop. - Follow up to #5853 - Closes #5890 + Reported-by: BrumBrum on hackerone + Closes #6141 -- CI/azure: no longer ignore results of test 1013 - - Follow up to #5771 - Closes #5889 +- [Sergei Nikulov brought this change] -- docs: add description about CI platforms to CONTRIBUTE.md + CMake: make BUILD_TESTING dependent option - Reviewed-by: Daniel Stenberg - Reviewed-by: Marcel Raad - Reviewed-by: Jay Satiro + CMake will now handle BUILD_TESTING depending on PERL_FOUND and + CURL_DISABLE_TESTING - Closes #5882 + Ref: #6036 + Closes #6072 -Daniel Stenberg (29 Aug 2020) -- tests/getpart: use MIME::Base64 instead of home-cooked - - Since we already use the base64 package since a while back, we can just - as well switch to that here too. +- libssh2: fix transport over HTTPS proxy - It also happens to use the exact same function name, which otherwise - causes a run-time warning. + The fix in #6021 was not enough. This fix makes sure SCP/SFTP content + can also be transfered over a HTTPS proxy. - Reported-by: Marc Hörsken - Fixes #5885 - Closes #5887 + Fixes #6113 + Closes #6128 -Marcel Raad (29 Aug 2020) -- ntlm: fix condition for curl_ntlm_core usage +- curl.1: add an "OUTPUT" section at the top of the manpage - `USE_WINDOWS_SSPI` without `USE_WIN32_CRYPTO` but with any other DES - backend is fine, but was excluded before. + Explain the basic concepts behind curl output. - This also fixes test 1013 as the condition for SMB support in - configure.ac didn't match the condition in the source code. Now it - does. + Inspired by #6124 - Fixes https://github.com/curl/curl/issues/1262 - Closes https://github.com/curl/curl/pull/5771 + Closes #6134 -- AppVeyor: switch 64-bit Schannel Debug CMake builds to Unicode +- mailmap: set Viktor Szakats's email + +- runtests: show keywords when no tests ran - The Schannel builds are the most useful to verify as they make the most - use of the Windows API. Classic MinGW doesn't support Unicode at all, - only MinGW-w64 and MSVC do. + To help out future debugging, runtests now outputs the list of keywords + when it fails because no tests ran. - Closes https://github.com/curl/curl/pull/5843 + Ref: #6120 + Closes #6126 -- CMake: add option to enable Unicode on Windows +Jay Satiro (26 Oct 2020) +- CURLOPT_DNS_USE_GLOBAL_CACHE.3: fix typo - As already existing for winbuild. + Reported-by: Rui LIU - Closes https://github.com/curl/curl/pull/5843 + Closes https://github.com/curl/curl/issues/6131 -Marc Hoersken (29 Aug 2020) -- select: simplify return code handling for poll and select +- range.d: fix typo - poll and select already return -1 on error according to POSIX, - so there is no need to perform a <0 to -1 conversion in code. + Follow-up to 15ae039 from earlier today. + +Daniel Stenberg (26 Oct 2020) +- CI/github: work-around for brew breakage on macOS - Also we can just use one check with <= 0 on the return code. + ... and make it use OpenSSL 1.1 properly - Assisted-by: Daniel Stenberg - Reviewed-by: Jay Satiro + Fixes #6130 + Closes #6129 + +- [José Joaquín Atria brought this change] + + range.d: clarify that curl will not parse multipart responses - Replaces #5852 - Closes #5880 + Closes #6127 + Fixes #6124 -Daniel Stenberg (28 Aug 2020) - RELEASE-NOTES: synced -- [Jeroen Ooms brought this change] +- [Baruch Siach brought this change] - tests: add test1912 with typechecks - - Validates that gcc-typecheck macros match the new option type API. + libssh2: fix build with disabled proxy support - Closes #5873 - -- easyoptions: provide debug function when DEBUGBUILD + Build breaks because the http_proxy field is missing: - ... not CURLDEBUG as they're not always set in conjunction. + vssh/libssh2.c:3119:10: error: 'struct connectdata' has no member named 'http_proxy' - Follow-up to 6ebe63fac23f38df + Regression from #6021, shipped in curl 7.73.0 - Fixes #5877 - Closes #5878 + Closes #6125 -Marc Hoersken (28 Aug 2020) -- sockfilt: handle FD_CLOSE winsock event on write socket +- alt-svc: enable by default - Learn from the way Cygwin handles and maps the WinSock events - to simulate correct and complete poll and select behaviour - according to Richard W. Stevens Network Programming book. + Remove CURLALTSVC_IMMEDIATELY, which was never implemented/supported. - Follow up to #5867 - Closes #5879 - -- multi: handle connection state winsock events + alt-svc support in curl is no longer considered experimental - Learn from the way Cygwin handles and maps the WinSock events - to simulate correct and complete poll and select behaviour - according to Richard W. Stevens Network Programming book. + Closes #5868 + +- CI/appveyor: remove (unused) runtests.pl -b option + +- [Emil Engler brought this change] + + tool_help: make "output" description less confusing - Reviewed-by: Jay Satiro - Reviewed-by: Marcel Raad + Currently the description of "output" is misleading when comparing it + "verbose". - Follow up to #5634 - Closes #5867 + Closes #6118 -Daniel Stenberg (28 Aug 2020) -- Curl_pgrsTime - return new time to avoid timeout integer overflow - - Setting a timeout to INT_MAX could cause an immediate error to get - returned as timeout because of an overflow when different values of - 'now' were used. +- CI/appveyor: disable test 571 in two cmake builds - This is primarily fixed by having Curl_pgrsTime() return the "now" when - TIMER_STARTSINGLE is set so that the parent function will continue using - that time. + ... they're simply too flaky there. - Reported-by: Ionuț-Francisc Oancea - Fixes #5583 - Closes #5847 + Closes #6119 -- TLS: fix SRP detection by using the proper #ifdefs - - USE_TLS_SRP will be true if *any* selected TLS backend can use SRP +- cmake: set the unicode feature in curl-config on Windows - HAVE_OPENSSL_SRP is defined when OpenSSL can use it + ... if built that way. To make it match curl -V output. - HAVE_GNUTLS_SRP is defined when GnuTLS can use it + Reviewed-by: Marcel Raad + Closes #6117 + +- libssh2: require version 1.0 or later - Clarify in the curl_verison_info docs that CURL_VERSION_TLSAUTH_SRP is - set if at least one of the supported backends offers SRP. + ... and simplify the code accordingly. libssh2 version 1.0 was released + in April 2009. - Reported-by: Stefan Strogin - Fixes #5865 - Closes #5870 + Closes #6116 -- [Dan Kenigsberg brought this change] +- KNOWN_BUGS: mention the individual cmake issues + + ... to make them easier to refer to and address separately and + one-by-one. - docs: SSLCERTS: fix English syntax +- CMake: store IDN2 information in curl_config.h - Signed-off-by: Dan Kenigsberg + This allows the build to enable IDN properly and it makes test 1014 + happier. - Closes #5876 - -- [Alessandro Ghedini brought this change] + Ref: #6074 + Closes #6108 - docs: non-existing macros in man pages - - As reported by man(1) when invoked as: +- CMake: call the feature unixsockets without dash - man --warnings -E UTF-8 -l -Tutf8 -Z >/dev/null + ... so that curl-config gets correct and makes test 1014 happy! - Closes #5846 - -- [Alessandro Ghedini brought this change] + Ref: #6074 + Closes #6108 - curl.1: fix typo invokved -> invoked +- CI/travis: add brotli and zstd to the libssh2 build - Closes #5846 - -- buildconf: invoke 'autoreconf -fi' instead + ... to make sure such tests are run with valgrind. Suppress the zstd + valgrind warnings we get with version 1.3.3 on Ubuntu 18.04 (for debug + and non-debug builds). - The custom script isn't necessary anymore - but remains for simplicity - and just invokes autoreconf. + Closes #6105 + +- runtests: revert the mistaken edit of $CURL - Closes #5853 + Regression from c4693adc62 -- [Emil Engler brought this change] +- RELEASE-NOTES: synced - lib: make Curl_gethostname accept a const pointer - - The address of that variable never gets changed, only the data in it so - why not make it a "char * const"? +- curl_url_set.3: fix typo in the RETURN VALUE section - Closes #5866 + Reported-by: Basuke Suzuki + Fixes #6102 -- docs/libcurl: update "Added in" version for curl_easy_option* - - Follow-up to 6ebe63fac23f38 +Jay Satiro (17 Oct 2020) +- [Daniel Stenberg brought this change] -- scripts: improve the "get latest curl release tag" logic + packages/OS400: make the source code-style compliant - ... by insiting on it matching "^curl-". + ... and make sure 'make checksrc' in the root dir also verifies the + packages/OS400 sources. + + Closes https://github.com/curl/curl/pull/6085 -- configure: added --disable-get-easy-options +- os400: Sync libcurl API options - To allow disabling of the curl_easy_option APIs in a build. + This fixes the OS400 build and also an incorrect entry for + CURLINFO_APPCONNECT_TIME_T where it was treated as + CURLINFO_STARTTRANSFER_TIME_T. - Closes #5365 + Reported-by: Jon Rumsey + + Fixes https://github.com/curl/curl/issues/6083 + Closes https://github.com/curl/curl/pull/6084 -- options: API for meta-data about easy options +Daniel Stenberg (16 Oct 2020) +- CURLOPT_NOBODY.3: fix typo - const struct curl_easyoption *curl_easy_option_by_name(const char *name); + Reported-by: Basuke Suzuki + Fixes #6097 + +Marc Hoersken (16 Oct 2020) +- CI/azure: improve on flakiness by avoiding libtool wrappers - const struct curl_easyoption *curl_easy_option_by_id (CURLoption id); + Install curl binaries into MinGW bin folder and use that + for the tests in order to avoid libtool wrapper binaries. - const struct curl_easyoption * - curl_easy_option_next(const struct curl_easyoption *prev); + The libtool wrapper binaries (not scripts) on Windows seem + to be one of the possible causes for the following issues: - The purpose is to provide detailed enough information to allow for - example libcurl bindings to get option information at run-time about - what easy options that exist and what arguments they expect. + 1. Process output can be lost in the wrapper process chain. + 2. Killing the wrapper process does not kill the actual one. - Assisted-by: Jeroen Ooms - Closes #5365 + Derived from #5904 + Closes #6049 -- [Eric Curtin brought this change] +Daniel Stenberg (16 Oct 2020) +- CURLOPT_URL.3: clarify SCP/SFTP URLs are for uploads as well - HTTP/3: update to OpenSSL_1_1_1g-quic-draft-29 - - Closes #5871 +- [Zenju brought this change] -- RELEASE-NOTES: synced + CURLOPT_TCP_NODELAY.3: fix comment in example code + + Closes #6096 -Jay Satiro (26 Aug 2020) -- openssl: Fix wincrypt symbols conflict with BoringSSL +- openssl: acknowledge SRP disabling in configure properly - OpenSSL undefines the conflicting symbols but BoringSSL does not so we - must do it ourselves. + Follow-up to 68a513247409 - Reported-by: Samuel Tranchet - Assisted-by: Javier Blazquez + Use a new separate define that is the combination of both + HAVE_OPENSSL_SRP and USE_TLS_SRP: USE_OPENSSL_SRP - Ref: https://bugs.chromium.org/p/boringssl/issues/detail?id=371 - Ref: https://github.com/openssl/openssl/blob/OpenSSL_1_1_1g/include/openssl/ossl_typ.h#L66-L73 + Bug: https://curl.haxx.se/mail/lib-2020-10/0037.html - Fixes https://github.com/curl/curl/issues/5669 - Closes https://github.com/curl/curl/pull/5857 + Closes #6094 -Daniel Stenberg (26 Aug 2020) -- socketpair: allow CURL_DISABLE_SOCKETPAIR +Viktor Szakats (16 Oct 2020) +- http3: fix two build errors, silence warnings - ... to completely disable the use of socketpair + * fix two build errors due to mismatch between function + declarations and their definitions + * silence two mismatched signs warnings via casts - Closes #5850 + Approved-by: Daniel Stenberg + Closes #6093 -- curl_get_line: build only if cookies or alt-svc are enabled +- Makefile.m32: add support for HTTP/3 via ngtcp2+nghttp3 - Closes #5851 + Approved-by: Daniel Stenberg + Closes #6092 -- [fullincome brought this change] +Daniel Stenberg (16 Oct 2020) +- tool_operate: fix compiler warning when --libcurl is disabled + + Closes #6095 - schannel: fix memory leak when using get_cert_location +- checksrc: warn on empty line before open brace - The get_cert_location function allocates memory only on success. - Previously get_cert_location was able to allocate memory and return - error. It wasn't obvious and in this case the memory wasn't - released. + ... and fix a few occurances - Fixes #5855 - Closes #5860 - -- [Emil Engler brought this change] + Closes #6088 - git: ignore libtests in 3XXX area +- urlapi: URL encode a '+' in the query part - Currently the file tests/libtest/lib3010 is not getting - ignored by git. This fixes it by adding the 3XXX area to - the according .gitignore file. + ... when asked to with CURLU_URLENCODE. - Closes #5859 + Extended test 1560 to verify. + Reported-by: Dietmar Hauser + Fixes #6086 + Closes #6087 -- [Emil Engler brought this change] +- [Cristian Morales Vega brought this change] - doh: add error message for DOH_DNS_NAME_TOO_LONG + libcurl.pc: make it relocatable - When this error code was introduced in b6a53fff6c1d07e8a9, it was - forgotten to be added in the errors array and doh_strerror function. + It supposes when people specify the libdir/includedir they do it to + change where under prefix/exec_prefix it should be, not to make it + independent of prefix/exec_prefix. - Closes #5863 + Closes #6061 -- ngtcp2: adapt to the new pkt_info arguments +- runtests: return error if no tests ran - Guidance-by: Tatsuhiro Tsujikawa + ... and make TESTFAIL stand out a little better by adding newlines + before and after. - Closes #5864 + Reported-by: Marc Hörsken + Issue: #6052 + Closes #6053 -- winbuild/README.md: make visible +- docs/FEATURE: convert to markdown - Follow-up to be753add31c2d8c - -- winbuild: convert the instruction text to README.md + ... and clean it up a bit. - Closes #5861 + Closes #6067 -- lib1560: verify "redirect" to double-slash leading URL - - Closes #5849 +- [Philipp Klaus Krause brought this change] -Marc Hoersken (25 Aug 2020) -- multi: expand pre-check for socket readiness + strerror: use 'const' as the string should never be modified - Check readiness of all sockets before waiting on them - to avoid locking in case the one-time event FD_WRITE - was already consumed by a previous wait operation. + Closes #6068 + +- [Jay Satiro brought this change] + + connect: repair build without ipv6 availability - More information about WinSock network events: - https://docs.microsoft.com/en-us/windows/win32/api/ - winsock2/nf-winsock2-wsaeventselect#return-value + Assisted-by: Daniel Stenberg + Reported-by: Tom G. Christensen - Closes #5634 + Fixes https://github.com/curl/curl/issues/6069 + Closes https://github.com/curl/curl/pull/6071 -- [rcombs brought this change] +- RELEASE-NOTES: synced + + Started over for the journey to next release. - multi: implement wait using winsock events +- src/tool_filetime: disable -Wformat on mingw for this file - This avoids using a pair of TCP ports to provide wakeup functionality - for every multi instance on Windows, where socketpair() is emulated - using a TCP socket on loopback which could in turn lead to socket - resource exhaustion. + With gcc 10 on mingw we otherwise get this warning: - A previous version of this patch failed to account for how in WinSock, - FD_WRITE is set only once when writing becomes possible and not again - until after a send has failed due to the buffer filling. This contrasts - to how FD_READ and FD_OOB continue to be set until the conditions they - refer to no longer apply. This meant that if a user wrote some data to - a socket, but not enough data to completely fill its send buffer, then - waited on that socket to become writable, we'd erroneously stall until - their configured timeout rather than returning immediately. + error: ISO C does not support the 'I' printf flag [-Werror=format=] - This version of the patch addresses that issue by checking each socket - we're waiting on to become writable with select() before the wait, and - zeroing the timeout if it's already writable. + Fixes #6079 + Closes #6082 + +- test122[12]: remove these two tests - Assisted-by: Marc Hörsken - Reviewed-by: Marcel Raad - Reviewed-by: Daniel Stenberg - Tested-by: Gergely Nagy - Tested-by: Rasmus Melchior Jacobsen - Tested-by: Tomas Berger + ... and remove the objnames scripts they tested. They're not used for + anything anymore so testing them serves no purpose! - Replaces #5397 - Reverts #5632 - Closes #5634 + Reported-by: Marc Hörsken + Fixes #6080 + Closes #6081 -- select: reduce duplication of Curl_poll in Curl_socket_check +Version 7.73.0 (14 Oct 2020) + +Daniel Stenberg (14 Oct 2020) +- RELEASE-NOTES: synced - Change Curl_socket_check to use select-fallback in Curl_poll - instead of implementing it in Curl_socket_check and Curl_poll. + for 7.73.0 + +- THANKS: from 7.73.0 and .mailmap fixes + +- mailmap: fixups of some contributors + +- projects/build-wolfssl.bat: fix the copyright year range + +Marc Hoersken (14 Oct 2020) +- [Sergei Nikulov brought this change] + + CI/tests: fix invocation of tests for CMake builds - Reviewed-by: Daniel Stenberg - Reviewed-by: Jay Satiro + Update appveyor.yml to set env variable TFLAGS and run tests + Remove curly braces due to CMake error (${TFLAGS} -> $TFLAGS) + Move testdeps build to build step (per review comments) - Replaces #5262 and #5492 - Closes #5707 + Reviewed-by: Marc Hörsken + + Closes #6066 + Fixes #6052 -- select: fix poll-based check not detecting connect failure +- tests/server/util.c: fix support for Windows Unicode builds - This commit changes Curl_socket_check to use POLLPRI to - check for connect failure on the write socket, because - POLLPRI maps to fds_err. This is in line with select(2). + Detected via #6066 + Closes #6070 + +Daniel Stenberg (13 Oct 2020) +- [Jay Satiro brought this change] + + strerror: Revert to local codepage for Windows error string - The select-based socket check correctly checks for connect - failures by adding the write socket also to fds_err. + - Change get_winapi_error() to return the error string in the local + codepage instead of UTF-8 encoding. - The poll-based implementation (which internally can itself - fallback to select again) did not previously check for - connect failure by using POLLPRI with the write socket. + Two weeks ago bed5f84 fixed get_winapi_error() to work on xbox, but it + also changed the error string's encoding from local codepage to UTF-8. - See the follow up commit to this for more information. + We return the local codepage version of the error string because if it + is output to the user's terminal it will likely be with functions which + expect the local codepage (eg fprintf, failf, infof). - This commit makes sure connect failures can be detected - and handled if HAVE_POLL_FINE is defined, eg. on msys2-devel. + This is essentially a partial revert of bed5f84. The support for xbox + remains but the error string is reverted back to local codepage. - Reviewed-by: Daniel Stenberg - Reviewed-by: Jay Satiro + Ref: https://github.com/curl/curl/pull/6005 - Replaces #5509 - Prepares #5707 + Reviewed-by: Marcel Raad + Closes #6065 -- select.h: make socket validation macros test for INVALID_SOCKET +Marc Hoersken (13 Oct 2020) +- CI/tests: use verification curl for test reporting APIs - With Winsock the valid range is [0..INVALID_SOCKET-1] according to - https://docs.microsoft.com/en-us/windows/win32/winsock/socket-data-type-2 + Avoid using our own, potentially installed, curl for + the test reporting APIs in case it is broken. - Reviewed-by: Jay Satiro - Reviewed-by: Marcel Raad Reviewed-by: Daniel Stenberg - Closes #5760 + Preparation for #6049 + Closes #6063 -Daniel Stenberg (24 Aug 2020) -- docs: --output-dir is added in 7.73.0, nothing else +Viktor Szakats (12 Oct 2020) +- windows: fix comparison of mismatched types warning - Follow-up to 5620d2cc78c0 + clang 10, mingw-w64: + ``` + vtls/openssl.c:2917:33: warning: comparison of integers of different signs: 'DWORD' (aka 'unsigned long') and 'HRESULT' (aka 'long') + [-Wsign-compare] + if(GetLastError() != CRYPT_E_NOT_FOUND) + ~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~ + ``` + + Approved-by: Daniel Stenberg + Closes #6062 -- curl: add --output-dir +Daniel Stenberg (11 Oct 2020) +- [Viktor Szakats brought this change] + + src/Makefile.m32: fix undefined curlx_dyn_* errors - Works with --create-dirs and with -J + by linking `lib/dynbuf.c` when building a static curl binary. + Previously this source file was only included when building + a dynamic curl binary. This was likely possibly because no + functions from the `src/Makefile.inc` / `CURLX_CFILES` sources + were actually required for a curl tool build. This has + recently changed with the introduction of `curlx_dyn_*()` + memory functions and their use by the tool sources. - Add test 3008, 3009, 3011, 3012 and 3013 to verify. + Closes #6060 + +- HISTORY: curl verifies SSL certs by default since version 7.10 + +Marc Hoersken (8 Oct 2020) +- runtests.pl: use $LIBDIR variable instead of hardcoded path - Closes #5637 + Reviewed-by: Daniel Stenberg + Closes #6051 -- configure: fix pkg-config detecting wolfssl +Daniel Stenberg (7 Oct 2020) +- checksrc: detect // comments on column 0 - When amending the include path with "/wolfssl", this now properly strips - off all whitespace from the path variable! Previously this would lead to - pkg-config builds creating bad command lines. + Spotted while working on #6045 - Closes #5848 + Closes #6048 -- [Michael Musset brought this change] +- [Frederik Wedel-Heinen brought this change] - sftp: add the option CURLKHSTAT_FINE_REPLACE + mbedtls: add missing header when defining MBEDTLS_DEBUG - Replace the old fingerprint of the host with a new. + Closes #6045 + +- curl: make sure setopt CURLOPT_IPRESOLVE passes on a long - Closes #5685 + Previously, it would pass on a define (int) which could make libcurl + read junk as a value - which prevented the CURLOPT_IPRESOLVE option to + "take". This could then make test 2100 do two DoH requests instead of + one! + + Fixes #6042 + Closes #6043 - RELEASE-NOTES: synced - - The next release is now to become 7.73.0 -- checksrc: verify do-while and spaces between the braces - - Updated mprintf.c to comply +- scripts/release-notes.pl: don't "embed" $ in format string for printf() - Closes #5845 + ... since they might contain %-codes that mess up the output! -- curl: support XDG_CONFIG_HOME to find .curlrc - - Added test433 to verify. Updated documentation. - - Reviewed-by: Jay Satiro - Suggested-by: Eli Schwartz - Fixes #5829 - Closes #5837 +Jay Satiro (5 Oct 2020) +- [M.R.T brought this change] -- etag: save and use the full received contents + build-wolfssl: fix build with Visual Studio 2019 - ... which makes it support weak tags and non-standard etags too! + Closes https://github.com/curl/curl/pull/6033 + +Daniel Stenberg (4 Oct 2020) +- runtests: add %repeat[]% for test files - Added test case 347 to verify blank incoming ETag: + ... and use this new keywords in all the test files larger than 50K to reduce + their sizes and make them a lot easier to read and understand. - Fixes #5610 - Closes #5833 + Closes #6040 -- setopt: if the buffer exists, refuse the new BUFFERSIZE +- [Emil Engler brought this change] + + --help: move two options from the misc category - The buffer only exists during transfer and then we shouldn't change the - size (the setopt is not documented to work then). + The cmdline opts delegation and suppress-connect-headers + fit better into auth and proxy rather than misc. - Reported-by: Harry Sintonen - Closes #5842 + Follow-up to aa8777f63febc + Closes #6038 -- [COFFEETALES brought this change] +- [Samanta Navarro brought this change] - sftp: add new quote commands 'atime' and 'mtime' + docs/opts: fix typos in two manual pages - Closes #5810 + Closes #6039 -- CURLE_PROXY: new error code +- ldap: reduce the amount of #ifdefs needed - Failures clearly returned from a (SOCKS) proxy now causes this return - code. Previously the situation was not very clear as what would be - returned and when. + Closes #6035 + +- runtests: provide curl's version string as %VERSION for tests - In addition: when this error code is returned, an application can use - CURLINFO_PROXY_ERROR to query libcurl for the detailed error, which then - returns a value from the new 'CURLproxycode' enum. + ... so that we can check HTTP requests for User-Agent: curl/%VERSION - Closes #5770 + Update 600+ test cases accordingly. + + Closes #6037 -- runtests: make cleardir() erase dot files too +- checksrc: warn on space after exclamation mark - Because test cases might use dot files. + Closes #6034 + +- test1465: verify --libcurl with binary POST data + +- runtests: allow generating a binary sequence from hex + +- tool_setopt: escape binary data to hex, not octal + +- curl: make --libcurl show binary posts correctly - Closes #5838 + Reported-by: Stephan Mühlstrasser + Fixes #6031 + Closes #6032 -- KNOWN_BUGS: 'no_proxy' string-matches IPv6 numerical addreses +Jay Satiro (1 Oct 2020) +- strerror: fix null deref on winapi out-of-memory - Also: the current behavior is now documented in the curl.1 and - CURLOPT_NOPROXY.3 man pages. + Follow-up to bed5f84 from several days ago. - Reported-by: Andrew Barnes - Closes #5745 - Closes #5841 + Ref: https://github.com/curl/curl/pull/6005 -Viktor Szakats (22 Aug 2020) -- Makefile.m32: add ability to override zstd libs [ci skip] - - Similarly to brotli, where this was already possible. - E.g. it allows to link zstd statically to libcurl.dll. +Daniel Stenberg (1 Oct 2020) +- [Kamil Dudka brought this change] + + vtls: deduplicate some DISABLE_PROXY ifdefs - Ref: https://github.com/curl/curl-for-win/issues/12 - Ref: https://github.com/curl/curl-for-win/commit/d9b266afd2e5d3f5604483010ef62340b5918c89 + ... in the code of gtls, nss, and openssl - Closes https://github.com/curl/curl/pull/5840 + Closes #5735 -Daniel Stenberg (21 Aug 2020) -- runtests: avoid 'fail to start' repeated messages in attempt loops +- RELEASE-NOTES: synced + +- [Emil Engler brought this change] + + TODO: Add OpenBSD libtool notice - Closes #5834 + See #5862 + Closes #6030 -- runtests: clear pid variables when failing to start a server +- tests/unit/README: convert to markdown - ... as otherwise the parent doesn't detect the failure and believe it - actually worked to start. + ... and add to dist! - Reported-by: Christian Weisgerber - Bug: https://curl.haxx.se/mail/lib-2020-08/0018.html - Closes #5834 + Closes #6028 -- TODO: Virtual external sockets +- tests/README: convert to markdown - Closes #5835 + Closes #6028 -- [Don J Olmstead brought this change] +- include/README: convert to markdown + + Closes #6028 - dist: add missing CMake Find modules to the distribution +- examples/README: convert to markdown - Closes #5836 + Closes #6028 -- RELEASE-NOTES: synced +- configure: don't say HTTPS-proxy is enabled when disabled! - ... and version bumped to 7.72.1 + Reported-by: Kamil Dudka + Reviewed-by: Kamil Dudka + Bug: https://github.com/curl/curl/pull/5735#issuecomment-701376388 + Closes #6029 -- tls: provide the CApath verbose log on its own line +Daniel Gustafsson (30 Sep 2020) +- src: Consistently spell whitespace without whitespace - ... not newline separated from the previous line. This makes it output - asterisk prefixed properly like other verbose putput! + Whitespace is spelled without a space between white and space, so + make sure to consistently spell it that way across the codebase. - Reported-by: jmdavitt on github - Fixes #5826 - Closes #5827 - -Version 7.72.0 (19 Aug 2020) + Closes #6023 + Reviewed-by: Daniel Stenberg + Reviewed-by: Emil Engler -Daniel Stenberg (19 Aug 2020) -- RELEASE-NOTES: synced +- MANUAL: update examples to resolve without redirects - The curl 7.72.0 release + www.netscape.com is redirecting to a cookie consent form on Aol, and + cool.haxx.se isn't responding to FTP anymore. Replace with examples + that resolves in case users try out the commands when reading the + manual. + + Closes #6024 + Reviewed-by: Daniel Stenberg + Reviewed-by: Emil Engler -- THANKS: add names from curl 7.72.0 release +Daniel Stenberg (30 Sep 2020) +- HISTORY: add some 2020 events -Jay Satiro (18 Aug 2020) -- KNOWN_BUGS: Schannel TLS 1.2 handshake bug in old Windows versions - - Reported-by: plujon@users.noreply.github.com +- sectransp: make it build with --disable-proxy - Closes https://github.com/curl/curl/issues/5488 + Follow-up from #5466 and f3d501dc678d80 + Reported-by: Javier Navarro + Fixes #6025 + Closes #6026 -Daniel Stenberg (17 Aug 2020) -- Curl_easy: remember last connection by id, not by pointer +- ECH: renamed from ESNI in docs and configure - CVE-2020-8231 + Encrypted Client Hello (ECH) is the current name. - Bug: https://curl.haxx.se/docs/CVE-2020-8231.html + Closes #6022 + +- configure: use "no" instead of "disabled" for the end summary - Reported-by: Marc Aldorasi - Closes #5824 + ... for consistency but also to make them more distinctly stand out next + to the "enabled" lines. -- examples/rtsp.c: correct the copyright year +- TODO: SSH over HTTPS proxy with more backends + + ... as right now only the libssh2 backend supports it. -- RELEASE-PROCEDURE.md: add more future release dates +- libssh2: handle the SSH protocols done over HTTPS proxy + + Reported-by: Robin Douine + Fixes #4295 + Closes #6021 -- [H3RSKO brought this change] +- [Emil Engler brought this change] - docs: change "web site" to "website" - - According to wikipedia: + memdebug: remove 9 year old unused debug function - While "web site" was the original spelling, this variant has become - rarely used, and "website" has become the standard spelling + There used to be a way to have memdebug fill allocated memory. 9 years + later this has no value there (valgrind and ASAN etc are way better). If + people need to know about it they can have a look at VCS logs. - Closes #5822 + Closes #5973 -- [Bevan Weiss brought this change] +- sendf: move Curl_sendf to dict.c and make it static + + ... as the only remaining user of that function. Also fix gopher.c to + instead use Curl_write() + + Closes #6020 - CMake: don't complain about missing nroff +- ROADMAP: updates and cleanups - The curl_nroff_check() was always being called, and complaining if - *NROFF wasn't found, even when not making the manual. + Fix the HSTS PR - Only check for nroff (and complain) if actually making the manual + Remove DoT, thread-safe init and hard-coded localhost. I feel very + little interest for these with users so I downgrade them to plain "TODO" + entries again. + +- schannel: return CURLE_PEER_FAILED_VERIFICATION for untrusted root - Closes #5817 + This matches what is returned in other TLS backends in the same + situation. + + Reviewed-by: Jay Satiro + Reviewed-by: Emil Engler + Follow-up to 5a3efb1 + Reported-by: iammrtau on github + Fixes #6003 + Closes #6018 -- [Brian Inglis brought this change] +- RELEASE-NOTES: synced - libtest/Makefile.am: add -no-undefined for libstubgss for Cygwin - - copy the LDFLAGS approach for adding same option with `libhostname` in - `libtest/Makefile.am`: +- ftp: make a 552 response return CURLE_REMOTE_DISK_FULL - - init `libstubgss_la_LDFLAGS_EXTRA` variable, - - add option to variable inside conditional, - - use variable in `libstubgss_la_LDFLAGS` + Added test 348 to verify. Added a 'STOR' command to the test FTP + server to enable test 348. Documented the command in FILEFORMAT.md - Fixes #5819 - Closes #5820 + Reported-by: Duncan Wilcox + Fixes #6016 + Closes #6017 -- docs: clarify MAX_SEND/RECV_SPEED functionality +- pause: only trigger a reread if the unpause sticks - ... in particular what happens if the maximum speed limit is set to a - value that's smaller than the transfer buffer size in use. + As an unpause might itself get paused again and then triggering another + reread doesn't help. - Reported-by: Tomas Berger - Fixes #5788 - Closes #5813 + Follow-up from e040146f22608fd9 (shipped since 7.69.1) + + Bug: https://curl.haxx.se/mail/lib-2020-09/0081.html + Patch-by: Kunal Chandarana + Fixes #5988 + Closes #6013 -- test1140: compare stdout +- test163[12]: require http to be built-in to run - To make problems more immediately obvious when tests fail. + ... as speaking over an HTTPS proxy implies http! - Closes #5814 + Closes #6014 -- asyn-ares: correct some bad comments +- ngtcp2: adapt to new NGTCP2_PROTO_VER_MAX define - Closes #5812 + Closes #6012 -- [Emil Engler brought this change] +- [Javier Blazquez brought this change] - docs: Add video link to docs/CONTRIBUTE.md + strerror: honor Unicode API choice on Windows - Closes #5811 + Closes #6005 -- curl-config: ignore REQUIRE_LIB_DEPS in --libs output +- imap: make imap_send use dynbuf for the send buffer management - Fixes a curl-config issue on cygwin by making sure REQUIRE_LIB_DEPS is - not considered for the --libs output. + Reuses the buffer and thereby reduces number of mallocs over a transfer. - Reported-by: ramsay-jones on github - Assisted-by: Brian Inglis and Ken Brown - Fixes #5793 - Closes #5808 - -- copyright: update/correct the year range on a few files - -- scripts/copyright.pl: ignore .muse files - -- [Emil Engler brought this change] + Closes #6010 - multi: Remove 10-year old out-commented code +- Curl_send: return error when pre_receive_plain can't malloc - The code hasn't been touched since 2010-08-18 + ... will probably trigger some false DEAD CODE positives on non-windows + code analyzers for the conditional code. - Closes #5805 + Closes #6011 -- KNOWN_BUGS: A shared connection cache is not thread-safe +- ftp: separate FTPS from FTP over "HTTPS proxy" - Closes #4915 - Closes #5802 - -- CONTRIBUTE: extend git commit message description + When using HTTPS proxy, SSL is used but not in the view of the FTP + protocol handler itself so separate the connection's use of SSL from the + FTP control connection's sue. - In particular how the first line works. + Reported-by: Mingtao Yang + Fixes #5523 + Closes #6006 + +Dan Fandrich (23 Sep 2020) +- tests/data: Fix some mismatched XML tags in test cases - Closes #5803 + This allows these test files to pass xmllint. -- RELEASE-NOTES: synced +Daniel Stenberg (23 Sep 2020) +- pingpong: use a dynbuf for the *_pp_sendf() function + + ... reuses the same dynamic buffer instead of doing repeated malloc/free + cycles. + + Test case 100 (FTP dir list PASV) does 7 fewer memory allocation calls + after this change in my test setup (132 => 125), curl 7.72.0 needed 140 + calls for this. + + Test case 103 makes 9 less allocations now (130). Down from 149 in + 7.72.0. + + Closes #6004 -- [Stefan Yohansson brought this change] +- dynbuf: add Curl_dyn_vaddf + + Closes #6004 - transfer: move retrycount from connect struct to easy handle +- dynbuf: make *addf() not require extra mallocs - This flag was applied to the connection struct that is released on - retry. These changes move the retry counter into Curl_easy struct that - lives across retries and retains the new connection. + ... by introducing a printf() function that appends directly into a + dynbuf: Curl_dyn_vprintf(). This avoids the mandatory extra malloc so if + the buffer is already big enough it can just printf directly into it. - Reported-by: Cherish98 on github - Fixes #5794 - Closes #5800 + Since this less-malloc version requires tthe use of a library internal + printf function, we only provide this version when building libcurl and + not for the dynbuf code that is used when building the curl tool. + + Closes #5998 -- libssh2: s/ssherr/sftperr/ +- KNOWN_BUGS: Unable to use PKCS12 certificate with Secure Transport - The debug output used ssherr instead of sftperr which not only outputs - the wrong error code but also casues a warning on Windows. + Closes #5403 + +- pingpong: remove a malloc per Curl_pp_vsendf call - Follow-up to 7370b4e39f1 + This typically makes 7-9 fewer mallocs per FTP transfer. - Reported-by: Gisle Vanem - Bug: https://github.com/curl/curl/commit/7370b4e39f1390e701f5b68d910c619151daf72b#r41334700 - Closes #5799 + Closes #5997 -- ftp: don't do ssl_shutdown instead of ssl_close - - The shutdown function is for downgrading a connection from TLS to plain, - and this is not requested here. +- symbian: drop support - Have ssl_close reset the TLS connection state. + The OS is deprecated. I see no traces of anyone having actually built + curl for Symbian after 2012. - This partially reverts commit f002c850d98d + The public headers are unmodified. - Reported-by: Rasmus Melchior Jacobsen - Reported-by: Denis Goleshchikhin - Fixes #5797 + Closes #5989 -Marc Hoersken (9 Aug 2020) -- CI/azure: fix test outcome values and use latest API version +- RELEASE-NOTES: synced + +- curl_krb5.h: rename from krb5.h - This makes sure that tests ignored or skipped are not shown - just in the category "Other", but with their correct state. + Follow-up from f4873ebd0be32cf - Closes #5796 + Turns out some older openssl installations go bananas otherwise. + Reported-by: Tom van der Woerdt + Fixes #5995 + Closes #5996 -- CI/azure: show runtime stats to investigate slowness +- test1297: verify GOT_NOTHING with http proxy tunnel + +- http_proxy: do not count proxy headers in the header bytecount - Also avoid naming conflict of TFLAGS env and tflags variables. + ... as that counter is subsequently used to detect if nothing was + returned from the peer. This made curl return CURLE_OK when it should + have returned CURLE_GOT_NOTHING. - Closes #5776 + Fixes #5992 + Reported-by: Tom van der Woerdt + Closes #5994 -Daniel Stenberg (8 Aug 2020) -- TLS naming: fix more Winssl and Darwinssl leftovers +- setopt: return CURLE_BAD_FUNCTION_ARGUMENT on bad argument - The CMake option is now called CMAKE_USE_SCHANNEL + Fixed two return code mixups. CURLE_UNKNOWN_OPTION is saved for when the + option is, yeah, not known. Clarified this in the setopt man page too. - The winbuild flag is USE_SCHANNEL + Closes #5993 + +- krb5: merged security.c and krb specific FTP functions in here - The CI jobs and build scripts only use the new names and the new name - options + These two files were always tightly connected and it was hard to + understand what went into which. This also allows us to make the + ftpsend() function static (moved from ftp.c). - Tests now require 'Schannel' (when necessary) + Removed security.c + Renamed curl_sec.h to krb5.h - Closes #5795 + Closes #5987 -- smtp_parse_address: handle blank input string properly +- Curl_handler: add 'family' to each protocol - Closes #5792 + Makes get_protocol_family() faster and it moves the knowledge about the + "families" to each protocol handler, where it belongs. + + Closes #5986 -- runtests: run the DICT server on a random port number +- parsedate: tune the date to epoch conversion - Removed support for -b (base port number) + By avoiding an unnecessary error check and the temp use of the tm + struct, the time2epoch conversion function gets a little bit faster. + When repeating test 517, the updated version is perhaps 1% faster (on + one particular build on one particular architecture). - Closes #5783 - -- RELEASE-NOTES: synced + Closes #5985 -- runtests: move the TELNET server to a dynamic port +- cmake: remove scary warning - Rename the port variable to TELNETPORT to better match the existing - pattern. + Remove the text saying - Closes #5785 - -- ngtcp2: adapt to error code rename + "the curl cmake build system is poorly maintained. Be aware" - Closes #5786 - -- runtests: move the smbserver to use a dynamic port number + ... not because anything changed just now, but to encourage users to use + it and subsequently improve it. - Closes #5782 + Closes #5984 -- runtests: run the http2 tests on a random port number - - Closes #5779 +- docs/MQTT: remove outdated paaragraphs -- gtls: survive not being able to get name/issuer +- docs/MQTT: not experimental anymore - Closes #5778 + Follow-up to e37e4468688d8f -- runtests: move the gnutls-serv tests to a dynamic port +- docs/RESOURCES: remove - Affects test 320, 321, 322 and 324. + This document is not maintained and rather than trying to refresh it, + let's kill it. A more up-to-date document with relevant RFCs is this + page on the curl website: https://curl.haxx.se/rfc/ - Closes #5778 + Closes #5980 -- runtests: support dynamicly base64 encoded sections in tests - - This allows us to make test cases to use base64 at run-time and still - use and verify information determined at run-time, such as the IMAP test - server's port number in test 842. +- docs/TheArtOfHttpScripting: convert to markdown - This change makes 12 tests run again that basically never ran since we - moved to dynamic port numbers. + Makes it easier to browse on github etc. Offers (better) links. - ftpserver.pl is adjusted to load test instructions and test number from - the preprocessed test file. + It should be noted that this document is already mostly outdated and + "Everything curl" at https://ec.haxx.se/ is a better resource and + tutorial. - FILEFORMAT.md now documents the new base64 encoding syntax. + Closes #5981 + +- BUGS: convert document to markdown - Reported-by: Marcel Raad - Fixes #5761 - Closes #5775 + Closes #5979 -- curl.1: add a few missing valid exit codes +- --help: strdup the category - 93 - 96 can be returned as well. + ... since it is converted and the original pointer is freed on Windows + unicode handling. - Closes #5777 + Follow-up to aa8777f63febc + Fixes #5977 + Closes #5978 + Reported-by: xwxbug on github -- TODO: Use multiple parallel transfers for a single download - - Closes #5774 +- CHECKSRC: document two missing warnings -- TODO: Set the modification date on an uploaded file +- RELEASE-NOTES: synced + +- ftp: avoid risk of reading uninitialized integers - Closes #5768 + If the received PASV response doesn't match the expected pattern, we + could end up reading uninitialized integers for IP address and port + number. + + Issue pointed out by muse.dev + Closes #5972 -- [Thomas M. DuBuisson brought this change] +- [Quentin Balland brought this change] - CI: Add muse CI config + easy_reset: clear retry counter - Closes #5772 - -- [Thomas M. DuBuisson brought this change] + Closes #5975 + Fixes #5974 - travis/script.sh: fix use of `-n' with unquoted envvar +- ftp: get rid of the PPSENDF macro - Shellcheck tells us "-n doesn't work with unquoted arguments. quote or - use [[ ]]." + The use of such a macro hides some of what's actually going on to the + reader and is generally disapproved of in the project. - And testing shows: + Closes #5971 + +- man pages: switch to https://example.com URLs - ``` - docker run --rm -it ubuntu bash - root@fe85ce156856:/# [ -n $DOES_NOT_EXIST ] && echo "I ran" - I ran - root@fe85ce156856:/# [ -n "$DOES_NOT_EXIST" ] && echo "I ran" - root@fe85ce156856:/# - ``` + Since HTTPS is "the new normal", this update changes a lot of man page + examples to use https://example.com instead of the previous "http://..." - Closes #5773 + Closes #5969 -- h2: repair trailer handling +- github: remove the duplicate "Security vulnerability" entry - The previous h2 trailer fix in 54a2b63 was wrong and caused a - regression: it cannot deal with trailers immediately when read since - they may be read off the connection by the wrong 'data' owner. + ... since github adds an entry automatically by itself. - This change reverts the logic back to gathering all trailers into a - single buffer, like before 54a2b63. + Closes #5970 + +- [Emil Engler brought this change] + + github: use new issue template feature - Reported-by: Tadej Vengust - Fixes #5663 - Closes #5769 + This helps us to avoid getting feature requests as well as security + bugs reported into the issue tracker. + + Closes #5936 -Viktor Szakats (3 Aug 2020) -- windows: disable Unix Sockets for old mingw +- [Emil Engler brought this change] + + urlapi: use more Curl_safefree - Classic mingw and 10y+ old versions of mingw-w64 don't ship with - Windows headers having the typedef necessary for Unix Sockets - support, so try detecting these environments to disable this - feature. + Closes #5968 + +Marc Hoersken (17 Sep 2020) +- multi: align WinSock mask variables in Curl_multi_wait - Ref: https://sourceforge.net/p/mingw-w64/mingw-w64/ci/cf6afc57179a5910621215f8f4037d406892072c/ + Also skip pre-checking sockets to set timeout_ms to 0 + after the first socket has been detected to be ready. + Reviewed-by: rcombs on github Reviewed-by: Daniel Stenberg - Fixes #5674 - Closes #5758 + Follow up to #5886 -Marcel Raad (3 Aug 2020) -- test1908: treat file as text +- multi: reuse WinSock events variable in Curl_multi_wait - Fixes the line endings on Windows. + Since the struct is quite large (1 long and 10 ints) we + declare it once at the beginning of the function instead + of multiple times inside loops to avoid stack movements. - Closes https://github.com/curl/curl/pull/5767 + Reviewed-by: Viktor Szakats + Reviewed-by: Daniel Stenberg + + Closes #5886 -- TrackMemory tests: ignore realloc and free in getenv.c +Daniel Stenberg (16 Sep 2020) +- TODO: dynamically decide to use socketpair - These are only called for WIN32. + Suggested-by: Anders Bakken - Closes https://github.com/curl/curl/pull/5767 - -Daniel Stenberg (3 Aug 2020) -- tests/FILEFORMAT.md: mention %HTTP2PORT - -- RELEASE-NOTES: synced + Closes #4829 -- tlsv1.3.d. only for TLS-using connections +- TODO: add PR reference for native IDN support on macOS - ... and rephrase that "not all" TLS backends support it. + As there was work started on this that never got completed. - Closes #5764 + Closes #5371 -- tls-max.d: this option is only for TLS-using connections +- tool_help.h: update copyright year range - Ref: #5763 - Closes #5764 - -Marcel Raad (2 Aug 2020) -- [Cameron Cawley brought this change] + Follow-up from aa8777f63febca - tool_doswin: Simplify Windows version detection +- CI/azure: disable test 571 in the msys2 builds - Closes https://github.com/curl/curl/pull/5754 - -- [Cameron Cawley brought this change] - - win32: Add Curl_verify_windows_version() to curlx + It's just too flaky there - Closes https://github.com/curl/curl/pull/5754 + Reviewed-by: Marc Hoersken + Closes #5954 -- runtests.pl: treat LibreSSL and BoringSSL as OpenSSL +- tool_writeout: protect fputs() from NULL - This makes the tests that require the OpenSSL feature also run for - those two compatible libraries. + When the code was changed to do fputs() instead of fprintf() it got + sensitive for NULL pointers; add checks for that. - Closes https://github.com/curl/curl/pull/5762 + Follow-up from 0c1e767e83ec66 + + Closes #5963 -Daniel Stenberg (1 Aug 2020) -- multi: Condition 'extrawait' is always true +- test3015: verify stdout "as text" - Reported by Codacy. + Follow-up from 0c1e767e83e to please win32 tests - Reviewed-by: Marcel Raad - Closes #5759 + Closes #5962 -Marcel Raad (1 Aug 2020) -- openssl: fix build with LibreSSL < 2.9.1 - - `SSL_CTX_add0_chain_cert` and `SSL_CTX_clear_chain_certs` were - introduced in LibreSSL 2.9.1 [0]. +- travis: use libressl v3.1.4 instead of master - [0] https://github.com/libressl-portable/openbsd/commit/0db809ee178457c8170abfae3931d7bd13abf3ef + ... as their git master seems too fragile to use (and 3.2.1 which is the + latest has a build failure). - Closes https://github.com/curl/curl/pull/5757 + Closes #5964 -Daniel Stenberg (1 Aug 2020) -- [Marc Aldorasi brought this change] +- tests/FILEFORMAT: document type=shell for - multi_remove_handle: close unused connect-only connections +- tests/FILEFORMAT: document nonewline support for - Previously any connect-only connections in a multi handle would be kept - alive until the multi handle was closed. Since these connections cannot - be re-used, they can be marked for closure when the associated easy - handle is removed from the multi handle. + The one in , that creates files. - Closes #5749 + Follow-up from b83947c8df7 -- checksrc: invoke script with -D to find .checksrc proper +- [anio brought this change] + + tool_writeout: add new writeout variable, %{num_headers} - Without the -D command line option, checksrc.pl won't know which - directory to load the ".checksrc" file from when building out of the - source tree. + This variable gives the number of headers. - Reported-by: Marcel Raad - Fixes #5715 - Closes #5755 - -- [Carlo Marcelo Arenas Belón brought this change] + Closes #5947 - buildconf: retire ares buildconf invocation +- tool_urlglob: fix compiler warning "unreachable code" - no longer needed after 4259d2df7dd95637a4b1e3fb174fe5e5aef81069 - -- [Carlo Marcelo Arenas Belón brought this change] - - buildconf: excempt defunct reference to ACLOCAL_FLAGS + (On Windows builds.) - retired with 09f278121e815028adb24d228d8092fc6cb022aa but kept around as - the name is generic enough that it might be in use and relied upon from - the environment. + Follow-up to 70a3b003d9 -- [Carlo Marcelo Arenas Belón brought this change] +- [Gergely Nagy brought this change] - buildconf: avoid array concatenation in die() + vtls: deduplicate client certificates in ssl_config_data - reported as error SC2145[1] by shellcheck, but not expected to cause - any behavioural differences otherwise. + Closes #5629 + +- ftp: a 550 response to SIZE returns CURLE_REMOTE_FILE_NOT_FOUND - [1] https://github.com/koalaman/shellcheck/wiki/SC2145 + This is primarily interesting for cases where CURLOPT_NOBODY is set as + previously curl would not return an error for this case. - Closes #5701 - -- travis: add ppc64le and s390x builds + MDTM getting 550 now also returns this error (it returned + CURLE_FTP_COULDNT_RETR_FILE before) in order to unify return codes for + missing files across protocols and specific FTP commands. - Closes #5752 - -Marc Hoersken (31 Jul 2020) -- connect: remove redundant message about connect failure + libcurl already returns error on a 550 as a MDTM response (when + CURLOPT_FILETIME is set). If CURLOPT_NOBODY is not set, an error would + happen subsequently anyway since the RETR command would fail. - Reviewed-by: Daniel Stenberg + Add test 1913 and 1914 to verify. Updated several tests accordingly due + to the updated SIZE behavior. - Closes #5708 + Reported-by: Tomas Berger + Fixes #5953 + Closes #5957 -- tests/sshserver.pl: fix compatibility with OpenSSH for Windows +- curl: make checkpasswd use dynbuf - Follow up to #5721 + Closes #5952 -- CI/azure: install libssh2 for use with msys2-based builds - - This enables building and running the SFTP tests. - Unfortunately OpenSSH for Windows does not support SCP (yet). - - Reviewed-by: Daniel Stenberg +- curl: make glob_match_url use dynbuf - Closes #5721 + Closes #5952 -- CI/azure: increase Windows job timeout once again - - Avoid aborted jobs due to performance issues on Azure DevOps. - - Reviewed-by: Daniel Stenberg - Reviewed-by: Jay Satiro +- curl: make file2memory use dynbuf - Closes #5738 + Closes #5952 -Jay Satiro (30 Jul 2020) -- TODO: Schannel: 'Add option to allow abrupt server closure' - - We should offer an option to allow abrupt server closures (server closes - SSL transfer without sending a known termination point such as length of - transfer or close_notify alert). Abrupt server closures are usually - because of misconfigured or very old servers. +- curl: make file2string use dynbuf - Closes https://github.com/curl/curl/issues/4427 + Closes #5952 -- url: fix CURLU and location following +- [Antarpreet Singh brought this change] + + imap: set cselect_bits to CURL_CSELECT_IN initially - Prior to this change if the user set a URL handle (CURLOPT_CURLU) it was - incorrectly used for the location follow, resulting in infinite requests - to the original location. + ... when continuing a transfer from a FETCH response. - Reported-by: sspiri@users.noreply.github.com + When the size of the file was small enough that the entirety of the + transfer happens in a single go and schannel buffers holds the entire + data. However, it wasn't completely read in Curl_pp_readresp since a + line break was found before that could happen. So, by the time we are in + imap_state_fetch_resp - there's data in buffers that needs to be read + via Curl_read but nothing to read from the socket. After we setup a + transfer (Curl_setup_transfer), curl just waits on the socket state to + change - which doesn't happen since no new data ever comes. - Fixes https://github.com/curl/curl/issues/5709 - Closes https://github.com/curl/curl/pull/5713 + Closes #5961 -Daniel Stenberg (30 Jul 2020) - RELEASE-NOTES: synced -- [divinity76 brought this change] - - docs: add date of 7.20 to CURLM_CALL_MULTI_PERFORM mentions +- test434: test -K use in a single line without newline - it helps make it obvious that most developers don't have to care about - the CURLM_CALL_MULTI_PERFORM value (last release using it is nearly 11 - years old, November 4 2009) + Closes #5946 + +- runtests: allow creating files without newlines - Closes #5744 + Closes #5946 -Jay Satiro (29 Jul 2020) -- tool_cb_wrt: fix outfile mode flags for Windows +- curl: use curlx_dynbuf for realloc when loading config files - - Use S_IREAD and S_IWRITE mode permission flags to create the file - on Windows instead of S_IRUSR, S_IWUSR, etc. + ... fixes an integer overflow at the same time. - Windows only accepts a combination of S_IREAD and S_IWRITE. It does not - acknowledge other combinations, for which it may generate an assertion. + Reported-by: ihsinme on github + Assisted-by: Jay Satiro - This is a follow-up to 81b4e99 from yesterday, which improved the - existing file check with -J. + Closes #5946 + +- dynbuf: provide curlx_ names for reuse by the curl tool - Ref: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/open-wopen#remarks - Ref: https://github.com/curl/curl/pull/5731 + Closes #5946 + +- dynbuf: make sure Curl_dyn_tail() zero terminates - Closes https://github.com/curl/curl/pull/5742 + Closes #5959 -Daniel Stenberg (28 Jul 2020) -- checksrc: ban gmtime/localtime +- tests: add test1912 to the dist - They're not thread-safe so they should not be used in libcurl code. + Follow-up to 70984ce1be4cab6c + +- docs/LICENSE-MIXING: remove - Explictly enabled when deemed necessary and in examples and tests + This document is not maintained and I feel that it doesn't provide much + value to users anymore (if it ever did). - Reviewed-by: Nicolas Sterchele - Closes #5732 + Closes #5955 -- transfer: fix data_pending for builds with both h2 and h3 enabled - - Closes #5734 +- [Laramie Leavitt brought this change] -- curl_multi_setopt: fix compiler warning "result is always false" + http: consolidate nghttp2_session_mem_recv() call paths - On systems with 32 bit long the expression is always false. Avoid - the warning. + Previously there were several locations that called + nghttp2_session_mem_recv and handled responses slightly differently. + Those have been converted to call the existing + h2_process_pending_input() function. - Reported-by: Gisle Vanem - Bug: https://github.com/curl/curl/commit/61a08508f6a458fe21bbb18cd2a9bac2f039452b#commitcomment-40941232 - Closes #5736 - -- curl: improve the existing file check with -J + Moved the end-of-session check to h2_process_pending_input() since the + only place the end-of-session state can change is after nghttp2 + processes additional input frames. - Previously a file that isn't user-readable but is user-writable would - not be properly avoided and would get overwritten. + This will likely fix the fuzzing error. While I don't have a root cause + the out-of-bounds read seems like a use after free, so moving the + nghttp2_session_check_request_allowed() call to a location with a + guaranteed nghttp2 session seems reasonable. - Reported-by: BrumBrum on hackerone - Assisted-by: Jay Satiro - Bug: https://hackerone.com/reports/926638 - Closes #5731 + Also updated a few nghttp2 callsites to include error messages and added + a few additional error checks. + + Closes #5648 -- [Jonathan Nieder brought this change] +- HISTORY: mention alt-svc added in 2019 + + ... and make 1996 the first year subtitle - multi: update comment to say easyp list is linear +- base64: also build for pop3 and imap - Since 09b9fc900 (multi: remove 'Curl_one_easy' struct, phase 1, - 2013-08-02), the easy handle list is not circular but ends with - ->next pointing to NULL. + Follow-up to the fix in 20417a13fb8f83 - Reported-by: Masaya Suzuki - Closes #5737 + Reported-by: Michael Olbrich + Fixes #5937 + Closes #5948 -- CURLOPT_NOBODY.3: fix the syntax for referring to options +- base64: enable in build with SMTP - As test 1140 fails otherwise! + The oauth2 support is used with SMTP and it uses base64 functions. - Follow-up to e1bac81cc815 + Reported-by: Michael Olbrich + Fixes #5937 + Closes #5938 -- ngtcp2: store address in sockaddr_storage +- curl_mime_headers.3: fix the example's use of curl_slist_append - Reported-by: Tatsuhiro Tsujikawa - Closes #5733 + Reported-by: sofaboss on github + Fixes #5942 + Closes #5943 -- CURLOPT_NOBODY.3: clarify what setting to 0 means +- lib583: fix enum mixup - ... and mention that HTTP with other methods than HEAD might get a body and - there's no option available to stop that. + grrr the previous follow-up to 17fcdf6a31 was wrong + +- libtest: fix build errors - Closes #5729 + Follow-up from 17fcdf6a310d4c8076 -- setopt: unset NOBODY switches to GET if still HEAD +- lib: fix -Wassign-enum warnings - Unsetting CURLOPT_NOBODY with 0L when doing HTTP has no documented - action but before 7.71.0 that used to switch back to GET and with this - change (assuming the method is still set to HEAD) this behavior is - brought back. + configure --enable-debug now enables -Wassign-enum with clang, + identifying several enum "abuses" also fixed. - Reported-by: causal-agent on github - Fixes #5725 - Closes #5728 + Reported-by: Gisle Vanem + Bug: https://github.com/curl/curl/commit/879007f8118771f4896334731aaca5850a154675#commitcomment-42087553 + + Closes #5929 -- [Ehren Bendler brought this change] +- RELEASE-NOTES: synced - configure: cleanup wolfssl + pkg-config conflicts when cross compiling. +- [Diven Qi brought this change] + + url: use blank credentials when using proxy w/o username and password - Also choose a different wolfSSL function to test for NTLM support. + Fixes proxy regression brought in commit ad829b21ae (7.71.0) - Fixes #5605 - Closes #5682 + Fixed #5911 + Closes #5914 -- configure: show zstd "no" in summary when built without it +- travis: add a build using libressl (from git master) - Reported-by: Marc Hörsken - Fixes #5720 - Closes #5730 - -- quiche: handle calling disconnect twice + The v3.2.1 tag (latest release atm) results in a broken build. - Reported-by: lilongyan-huawei on github - Fixes #5726 - Closes #5727 - -- [Nicolas Sterchele brought this change] + Closes #5932 - getinfo: reset retry-after value in initinfo +- configure: let --enable-debug set -Wenum-conversion with gcc >= 10 - - Avoid re-using retry_after value from preceding request - - Add libtest 3010 to verify + Unfortunately, this option is not detecting the same issues as clang's + -Wassign-enum flag, but should still be useful to detect future + mistakes. - Reported-by: joey-l-us on github - Fixes #5661 - Closes #5672 + Closes #5930 -Marcel Raad (27 Jul 2020) -- WIN32: stop forcing narrow-character API +- openssl: consider ALERT_CERTIFICATE_EXPIRED a failed verification - Except where the results are only used for character output. - getenv is not touched because it's part of the public API, and having - it return UTF-8 instead of ANSI would be a breaking change. + If the error reason from the lib is + SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED, libcurl will return + CURLE_PEER_FAILED_VERIFICATION and not CURLE_SSL_CONNECT_ERROR. - Fixes https://github.com/curl/curl/issues/5658 - Fixes https://github.com/curl/curl/issues/5712 - Closes https://github.com/curl/curl/pull/5718 + This unifies the libcurl return code and makes libressl run test 313 + (CRL testing) fine. + + Closes #5934 -Jay Satiro (27 Jul 2020) -- [Tobias Stoeckmann brought this change] +- FAQ: refreshed some very old language - mprintf: Fix stack overflows - - Stack overflows can occur with precisions for integers and floats. +- cmake: make HTTP_ONLY also disable MQTT - Proof of concepts: - - curl_mprintf("%d, %.*1$d", 500, 1); - - curl_mprintf("%d, %+0500.*1$f", 500, 1); + ... and alphasort the order of disabling protocols to make it easier to + browse. - Ideally, compile with -fsanitize=address which makes this undefined - behavior a bit more defined for debug purposes. + Closes #5931 + +- libtest: remove lib1541 leftovers - The format strings are valid. The overflows occur due to invalid - arguments. If these arguments are variables with contents controlled - by an attacker, the function's stack can be corrupted. + Caused automake errors. - Also see CVE-2016-9586 which partially fixed the float aspect. + Follow-up to 8ca54a03ea08a + +- tests/libtests: remove test 1900 and 2033 - Signed-off-by: Tobias Stoeckmann + We already remove the test files, now remove the libtest codes as well. - Closes https://github.com/curl/curl/pull/5722 - -- [Tobias Stoeckmann brought this change] + Follow-up to e50a877df74 - mprintf: Fix dollar string handling - - Verify that specified parameters are in range. If parameters are too - large, fail early on and avoid out of boundary accesses. +Marc Hoersken (7 Sep 2020) +- CI/azure: add test number to title for display in analytics - Also do not read behind boundaries of illegal format strings. + To ease identification of tests the test number is added to + the test case title in order to have it on the Azure DevOps + Analytics pages and reports which currently do not show it. - These are defensive measures since it is expected that format strings - are well-formed. Format strings should not be modifiable by user - input due to possible generic format string attacks. + Bump test case revision to make Azure DevOps update titles. - Closes https://github.com/curl/curl/pull/5722 + Closes #5927 -Daniel Stenberg (26 Jul 2020) -- ntlm: free target_info before (re-)malloc +Daniel Stenberg (6 Sep 2020) +- altsvc: clone setting in curl_easy_duphandle - OSS-Fuzz found a way this could get called again with the pointer still - pointing to a malloc'ed memory, leading to a leak. + The cache content is not duplicated, like other caches, but the setting + and specified file name are. - Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24379 + Test 1908 is extended to verify this somewhat. Since the duplicated + handle gets the same file name, the test unfortunately overwrites the + same file twice (with different contents) which makes it hard to check + automatically. - Closes #5724 + Closes #5923 -Marcel Raad (26 Jul 2020) -- CI/macos: set minimum macOS version +- test1541: remove since it is a known bug - This enables some deprecation warnings. - Previously, autotools defaulted to 10.8. + A shared connection cache is not thread-safe is a known issue. Stop + testing this until we believe this issue is addressed. Reduces + occasional test failures we don't care about. - Closes https://github.com/curl/curl/pull/5723 - -Daniel Stenberg (26 Jul 2020) -- RELEASE-NOTES: synced - -Marcel Raad (25 Jul 2020) -- CI/macos: enable warnings as errors for CMake builds + The test code in lib1541.c is left in git to allow us to restore it when + we get to fix this. - Closes https://github.com/curl/curl/pull/5716 + Closes #5922 -- CMake: fix test for warning suppressions +- tests: remove pipelining tests - GCC doesn't warn for unknown `-Wno-` options, except if there are other - warnings or errors [0]. This was problematic with `CURL_WERROR` as that - warning-as-error cannot be suppressed. Notably, this always happened - with `-Wno-pedantic-ms-format` when not targeting Windows. So test for - the positive form of the warning instead, which should always result in - a diagnostic if unknown. + Remove the tests 530, 584, 1900, 1901, 1902, 1903 and 2033. They were + previously disabled. - [0] https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html + The Pipelining code was removed from curl in commit 2f44e94efb3df8e, + April 2019. - Closes https://github.com/curl/curl/pull/5714 + Closes #5921 -Jay Satiro (23 Jul 2020) -- curl.h: update CURLINFO_LASTONE +- curl: retry delays in parallel mode no longer sleeps blocking - CURLINFO_LASTONE should have been updated when - CURLINFO_EFFECTIVE_METHOD was added. + The previous sleep for retries would block all other concurrent + transfers. Starting now, the retry will instead be properly marked to + not get restarted until after the delay time but other transfers can + still continue in the mean time. - Reported-by: xwxbug@users.noreply.github.com + Closes #5917 + +- curl:parallel_transfers: make sure retry readds the transfer - Fixes https://github.com/curl/curl/issues/5711 + Reported-by: htasta on github + Fixes #5905 + Closes #5917 -Marc Hoersken (22 Jul 2020) -- CI/azure: unconditionally enable warnings-as-errors with autotools +- build: drop support for building with Watcom - Reviewed-by: Marcel Raad + These files are not maintained, they seem to have no users, Watcom + compilers look like not having users nor releases anymore. - Follow up to #5694 - Closes #5706 + Closes #5918 -Marcel Raad (21 Jul 2020) -- doh: remove redundant cast +- winbuild/rundebug.cmd: remove - Closes https://github.com/curl/curl/pull/5704 + Seems to have been added by mistake? Not included in dists. + + Closes #5919 -- CI/macos: unconditionally enable warnings-as-errors with autotools +- curl: in retry output don't call all problems "transient" - Previously, warnings were only visible in the output for most jobs. + ... because when --retry-all-errors is used, the error isn't necessarily + transient at all. - Closes https://github.com/curl/curl/pull/5694 + Closes #5916 -- util: silence conversion warnings +- easygetopt: pass a valid enum to avoid compiler warning - timeval::tv_usec might be a 32-bit integer and timespec::tv_nsec might - be a 64-bit integer. This is the case when building for recent macOS - versions, for example. Just treat tv_usec as an int, which should - hopefully always be sufficient on systems with - `HAVE_CLOCK_GETTIME_MONOTONIC`. + "integer constant not in range of enumerated type 'CURLoption'" - Closes https://github.com/curl/curl/pull/5695 + Reported-by: Gisle Vanem + Bug: https://github.com/curl/curl/commit/6ebe63fac23f38df911edc348e8ccc72280f9434#commitcomment-42042843 + + Closes #5915 -- md(4|5): don't use deprecated macOS functions +- [Emil Engler brought this change] + + tests: Add tests for new --help - They are marked as deprecated for -mmacosx-version-min >= 10.15, - which might result in warnings-as-errors. + This commit is a part of "--help me if you can" - Closes https://github.com/curl/curl/pull/5695 + Closes #5680 -Daniel Stenberg (18 Jul 2020) -- strdup: remove the odd strlen check +- [Emil Engler brought this change] + + tool: update --help with categories - It confuses code analyzers with its use of -1 for unsigned value. Also, - a check that's not normally used in strdup() code - and not necessary. + This commit is a part of "--help me if you can" - Closes #5697 + Closes #5680 -- [Alessandro Ghedini brought this change] +- [Emil Engler brought this change] - travis: update quiche builds for new boringssl layout + docs: add categories to all cmdline opts - This is required after https://github.com/cloudflare/quiche/pull/593 - moved BoringSSL around slightly. + Adapted gen.pl with 'listcats' - This also means that Go is not needed to build BoringSSL anymore (the - one provided by quiche anyway). + This commit is a part of "--help me if you can" - Closes #5691 + Closes #5680 -Marcel Raad (17 Jul 2020) -- configure: allow disabling warnings - - When using `--enable-warnings`, it was not possible to disable warnings - via CFLAGS that got explicitly enabled. Now warnings are not enabled - anymore if they are explicitly disabled (or enabled) in CFLAGS. This - works for at least GCC, clang, and TCC as they have corresponding - `-Wno-` options for every warning. - - Closes https://github.com/curl/curl/pull/5689 +- RELEASE-NOTES: synced -Daniel Stenberg (16 Jul 2020) -- ngtcp2: adjust to recent sockaddr updates +- [ihsinme brought this change] + + connect.c: remove superfluous 'else' in Curl_getconnectinfo - Closes #5690 + Closes #5912 -- page-header: provide protocol details in the curl.1 man page +- [Samuel Marks brought this change] + + CMake: remove explicit `CMAKE_ANSI_CFLAGS` - Add protocol and version specific information about all protocols curl - supports. + This variable was removed from cmake in commit + https://gitlab.kitware.com/cmake/cmake/commit/5a834b0bb0bc288. A later + CMake commit removes the variable from the tests, claiming that it was + removed in CMake 2.6 - Fixes #5679 - Reported-by: tbugfinder on github - Closes #5686 + Reviewed-By: Peter Wu + Closes #5439 -Daniel Gustafsson (16 Jul 2020) -- docs: Update a few leftover mentions of DarwinSSL +- [cbe brought this change] + + libssh2: pass on the error from ssh_force_knownhost_key_type - Commit 76a9c3c4be10b3d4d379d5b23ca76806bbae536a renamed DarwinSSL to the - more correct/common name Secure Transport, but a few mentions in the docs - remained. + Closes #5909 + +- scripts/delta: add diffstat summary - Closes #5688 - Reviewed-by: Daniel Stenberg + ... and make output more table-like -Daniel Stenberg (16 Jul 2020) -- file2memory: use a define instead of -1 unsigned value +- [Martin Bašti brought this change] + + http_proxy: do not crash with HTTPS_PROXY and NO_PROXY set - ... to use the maximum value for 'size_t' when detecting integer overflow. - Changed the limit to max/4 as already that seems unreasonably large. + ... in case NO_PROXY takes an effect - Codacy didn't like the previous approach. + Without this patch, the following command crashes: - Closes #5683 - -- CURL_PUSH_ERROROUT: allow the push callback to fail the parent stream + $ GIT_CURL_VERBOSE=1 NO_PROXY=github.com HTTPS_PROXY=https://example.com \ + git clone https://github.com/curl/curl.git - ... by adding support for a new dedicated return code. + Minimal libcurl-based reproducer: - Suggested-by: Jonathan Cardoso - Assisted-by: Erik Johansson - URL: https://curl.haxx.se/mail/lib-2020-06/0099.html - Closes #5636 + #include + + int main() { + CURL *curl = curl_easy_init(); + if(curl) { + CURLcode ret; + curl_easy_setopt(curl, CURLOPT_URL, "https://github.com/"); + curl_easy_setopt(curl, CURLOPT_PROXY, "example.com"); + /* set the proxy type */ + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS); + curl_easy_setopt(curl, CURLOPT_NOPROXY, "github.com"); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + ret = curl_easy_perform(curl); + curl_easy_cleanup(curl); + return ret; + } + return -1; + } + + Assisted-by: Kamil Dudka + Bug: https://bugzilla.redhat.com/1873327 + Closes #5902 -- [Baruch Siach brought this change] +- travis: add a CI job with openssl3 (from git master) + + Closes #5908 - nss: fix build with disabled proxy support +- openssl: avoid error conditions when importing native CA - Avoid reference to fields that do not exist when CURL_DISABLE_PROXY is - defined. + The code section that is OpenSSL 3+ specific now uses the same logic as + is used in the version < 3 section. It caused a compiler error without + it. - Closes #5667 + Closes #5907 -- test1139: make it display the difference on test failures +- setopt: avoid curl_ on local variable + + Closes #5906 -- test1119: verify stdout in the test +- mqtt.c: avoid curl_ prefix on local variable - So that failures will be displayed in the terminal, as it makes test failures - visually displayed easier and faster. + Closes #5906 + +- wildcard: strip "curl_" prefix from private symbols - Closes #5644 + Closes #5906 -- curl: add %{method} to the -w variables +- vtls: make it 'struct Curl_ssl_session' - Gets the CURLINFO_EFFECTIVE_METHOD from libcurl. + Use uppercase C for internal symbols. - Added test 1197 to verify. + Closes #5906 -- CURLINFO_EFFECTIVE_METHOD: added +- curl_threads: make it 'struct Curl_actual_call' - Provide the HTTP method that was used on the latest request, which might - be relevant for users when there was one or more redirects involved. + Internal names should not be prefixed "curl_" - Closes #5511 + Closes #5906 -Viktor Szakats (14 Jul 2020) -- windows: add unicode to feature list +- schannel: make it 'struct Curl_schannel*' - Reviewed-by: Marcel Raad - Reviewed-by: Marc Hörsken + As internal global names should use captical C. - Closes #5491 + Closes #5906 -Daniel Stenberg (14 Jul 2020) -- multi: remove two checks always true +- hash: make it 'struct Curl_hash' - Detected by Codacy - Closes #5676 - -Marc Hoersken (13 Jul 2020) -- workflows: limit what branches to run CodeQL on + As internal global names should use captical C. - Align CodeQL action with existing CI actions: - - Update branch filter to avoid duplicate CI runs. - - Shorten workflow name due to informative job name. + Closes #5906 + +- llist: make it "struct Curl_llist" - Reviewed-by: Daniel Stenberg + As internal global names should use captical C. - Closes #5660 + Closes #5906 -- appveyor: collect libcurl.dll variants with prefix or suffix +Marc Hoersken (2 Sep 2020) +- telnet.c: depend on static requirement of WinSock version 2 - On some platforms libcurl is build with a platform-specific - prefix and/or a version number suffix. + Drop dynamic loading of ws2_32.dll and instead rely on the + imported version which is now required to be at least 2.2. - Assisted-by: Jay Satiro + Reviewed-by: Marcel Raad + Reviewed-by: Jay Satiro + Reviewed-by: Daniel Stenberg + Reviewed-by: Viktor Szakats - Closes #5659 - -Daniel Stenberg (12 Jul 2020) -- [ihsinme brought this change] + Closes #5854 - socks: use size_t for size variable +- win32: drop support for WinSock version 1, require version 2 - Use the unsigned type (size_t) in the arithmetic of pointers. In this - context, the signed type (ssize_t) is used unnecessarily. + IPv6, telnet and now also the multi API require WinSock + version 2 which is available starting with Windows 95. - Authored-by: ihsinme on github - Closes #5654 - -- RELEASE-NOTES: synced + Therefore we think it is time to drop support for version 1. - ... and bumped to 7.72.0 as the next release version number - -- [Gilles Vollant brought this change] + Reviewed-by: Marcel Raad + Reviewed-by: Jay Satiro + Reviewed-by: Daniel Stenberg + Reviewed-by: Viktor Szakats + + Follow up to #5634 + Closes #5854 - content_encoding: add zstd decoding support +- select: align poll emulation to return all relevant events - include zstd curl patch for Makefile.m32 from vszakats - and include Add CMake support for zstd from Peter Wu + The poll emulation via select already consumes POLLRDNORM, + POLLWRNORM and POLLRDBAND as input events. Therefore it + should also return them as output events if signaled. - Helped-by: Viktor Szakats - Helped-by: Peter Wu - Closes #5453 - -- asyn.h: remove the Curl_resolver_getsock define + Also fix indentation in input event handling block. - - not used - - used the wrong number of arguments - - confused the Codeacy code analyzer + Assisted-by: Jay Satiro + Reviewed-by: Daniel Stenberg - Closes #5647 - -- [Nicolas Sterchele brought this change] + Replaces #5852 + Closes #5883 - configure.ac: Sort features name in summary +- CI/azure: MQTT is now enabled by default - - Same as protocols + Reviewed-by: Daniel Stenberg - Closes #5656 + Follow up to #5858 + Closes #5903 -- [Matthias Naegler brought this change] +Daniel Stenberg (2 Sep 2020) +- copyright.pl: ignore buildconf - cmake: fix windows xp build +- test971: show test mismatches "inline" + +- lib/Makefile.am: bump VERSIONINFO due to new functions - Reviewed-by: Marcel Raad - Closes #5662 + ... we're generally bad at this, but we are adding new functions for + this release. + + Closes #5899 -- ngtcp2: update to modified qlog callback prototype +- optiontable: use DEBUGBUILD - Closes #5675 + Follow-up to commit 6e18568ba38 (#5877) -- transfer: fix memory-leak with CURLOPT_CURLU in a duped handle +- cmdline-opts/gen.pl: generate nicer "See Also" in curl.1 - Added test case 674 to reproduce and verify the bug report. + If there are more than two items in the list, use commas for all but the + last separator which is set to 'and'. Reads better. - Fixes #5665 - Reported-by: NobodyXu on github - Closes #5673 - -- [Baruch Siach brought this change] + Closes #5898 - bearssl: fix build with disabled proxy support +- curl.1: add see also no-progress-meter on two spots - Avoid reference to fields that do not exist when CURL_DISABLE_PROXY is - defined. + Ref: #5894 - Reviewed-by: Nicolas Sterchele - Closes #5666 + Closes #5897 - RELEASE-NOTES: synced -Jay Satiro (11 Jul 2020) -- [Carlo Marcelo Arenas Belón brought this change] - - cirrus-ci: upgrade 11-STABLE to 11.4 +- mqtt: enable by default - Meant to be the last of the 11 series and so make sure that all - other references reflect all 11 versions so they can be retired - together later. + No longer considered experimental. - Closes https://github.com/curl/curl/pull/5668 + Closes #5858 -- [Filip Salomonsson brought this change] +- [Michael Baentsch brought this change] - CURLINFO_CERTINFO.3: fix typo + tls: add CURLOPT_SSL_EC_CURVES and --curves - Closes https://github.com/curl/curl/pull/5655 + Closes #5892 -Daniel Stenberg (4 Jul 2020) -- http2: only do the *done() cleanups for HTTP - - Follow-up to ef86daf4d3 - - Closes #5650 - Fixes #5646 +- url: remove funny embedded comments in Curl_disonnect calls -- [Alex Kiernan brought this change] +- [Chris Paulson-Ellis brought this change] - gnutls: repair the build with `CURL_DISABLE_PROXY` + conn: check for connection being dead before reuse - `http_proxy`/`proxy_ssl`/`tunnel_proxy` will not be available in `conn` - if `CURL_DISABLE_PROXY` is enabled. Repair the build with that - configuration. + Prevents incorrect reuse of an HTTP connection that has been prematurely + shutdown() by the server. - Signed-off-by: Alex Kiernan - Closes #5645 - -Alex Kiernan (3 Jul 2020) -- gnutls: Fetch backend when using proxy + Partial revert of 755083d00deb16 - Fixes: 89865c149 ("gnutls: remove the BACKEND define kludge") - Signed-off-by: Alex Kiernan - -Daniel Stenberg (3 Jul 2020) -- [Laramie Leavitt brought this change] + Fixes #5884 + Closes #5893 - http2: close the http2 connection when no more requests may be sent - - Well-behaving HTTP2 servers send two GOAWAY messages. The first - message is a warning that indicates that the server is going to - stop accepting streams. The second one actually closes the stream. +Marc Hoersken (29 Aug 2020) +- buildconf: exec autoreconf to avoid additional process - nghttp2 reports this state (and the other state of no more stream - identifiers) via the call nghttp2_session_check_request_allowed(). - In this state the client should not create more streams on the - session (tcp connection), and in curl this means that the server - has requested that the connection is closed. + Also make buildconf exit with the return code of autoreconf. - It would be also be possible to put the connclose() call into the - on_http2_frame_recv() function that triggers on the GOAWAY message. + Reviewed-by: Daniel Stenberg - This fixes a bug seen when the client sees the following sequence of - frames: + Follow up to #5853 + Closes #5890 + +- CI/azure: no longer ignore results of test 1013 - // advisory GOAWAY - HTTP2 GOAWAY [stream-id = 0, promised-stream-id = -1] - ... some additional frames + Follow up to #5771 + Closes #5889 + +- docs: add description about CI platforms to CONTRIBUTE.md - // final GOAWAY - HTTP2 GOAWAY [stream-id = 0, promised-stream-id = N ] + Reviewed-by: Daniel Stenberg + Reviewed-by: Marcel Raad + Reviewed-by: Jay Satiro - Before this change, curl will attempt to reuse the connection even - after the last stream, will encounter this error: + Closes #5882 + +Daniel Stenberg (29 Aug 2020) +- tests/getpart: use MIME::Base64 instead of home-cooked - * Found bundle for host localhost: 0x5595f0a694e0 [can multiplex] - * Re-using existing connection! (#0) with host localhost - * Connected to localhost (::1) port 10443 (#0) - * Using Stream ID: 9 (easy handle 0x5595f0a72e30) - > GET /index.html?5 HTTP/2 - > Host: localhost:10443 - > user-agent: curl/7.68.0 - > accept: */* - > - * stopped the pause stream! - * Connection #0 to host localhost left intact - curl: (16) Error in the HTTP2 framing layer + Since we already use the base64 package since a while back, we can just + as well switch to that here too. - This error may posion the connection cache, causing future requests - which resolve to the same curl connection to go through the same error - path. + It also happens to use the exact same function name, which otherwise + causes a run-time warning. - Closes #5643 + Reported-by: Marc Hörsken + Fixes #5885 + Closes #5887 -- ftpserver: don't verify SMTP MAIL FROM names +Marcel Raad (29 Aug 2020) +- ntlm: fix condition for curl_ntlm_core usage - Rely on tests asking the names to get refused instead - test servers - should be as dumb as possible. Edited test 914, 955 and 959 accordingly. + `USE_WINDOWS_SSPI` without `USE_WIN32_CRYPTO` but with any other DES + backend is fine, but was excluded before. - Closes #5639 + This also fixes test 1013 as the condition for SMB support in + configure.ac didn't match the condition in the source code. Now it + does. + + Fixes https://github.com/curl/curl/issues/1262 + Closes https://github.com/curl/curl/pull/5771 -- curl_version_info.3: CURL_VERSION_KERBEROS4 is deprecated +- AppVeyor: switch 64-bit Schannel Debug CMake builds to Unicode - This came up in #5640. It make sense to clarify this in the docs! + The Schannel builds are the most useful to verify as they make the most + use of the Windows API. Classic MinGW doesn't support Unicode at all, + only MinGW-w64 and MSVC do. - Reminded-by: Kamil Dudka - Closes #5642 + Closes https://github.com/curl/curl/pull/5843 -Kamil Dudka (3 Jul 2020) -- tool_getparam: make --krb option work again +- CMake: add option to enable Unicode on Windows - It was disabled by mistake in commit curl-7_37_1-23-ge38ba4301. + As already existing for winbuild. - Bug: https://bugzilla.redhat.com/1833193 - Closes #5640 - -Daniel Stenberg (2 Jul 2020) -- [Jeremy Maitin-Shepard brought this change] + Closes https://github.com/curl/curl/pull/5843 - http2: fix nghttp2_strerror -> nghttp2_http2_strerror in debug messages +Marc Hoersken (29 Aug 2020) +- select: simplify return code handling for poll and select - Confusingly, nghttp2 has two different error code enums: + poll and select already return -1 on error according to POSIX, + so there is no need to perform a <0 to -1 conversion in code. - - nghttp2_error, to be used with nghttp2_strerror - - nghttp2_error_code, to be used with nghttp2_http2_strerror + Also we can just use one check with <= 0 on the return code. - Closes #5641 - -Marcel Raad (2 Jul 2020) -- url: silence MSVC warning - - Since commit f3d501dc678, if proxy support is disabled, MSVC warns: - url.c : warning C4701: potentially uninitialized local variable - 'hostaddr' used - url.c : error C4703: potentially uninitialized local pointer variable - 'hostaddr' used - - That could actually only happen if both `conn->bits.proxy` and - `CURL_DISABLE_PROXY` were enabled. - Initialize it to NULL to silence the warning. + Assisted-by: Daniel Stenberg + Reviewed-by: Jay Satiro - Closes https://github.com/curl/curl/pull/5638 + Replaces #5852 + Closes #5880 -Daniel Stenberg (1 Jul 2020) +Daniel Stenberg (28 Aug 2020) - RELEASE-NOTES: synced -Version 7.71.1 (30 Jun 2020) - -Daniel Stenberg (30 Jun 2020) -- RELEASE-NOTES: curl 7.71.1 - -- THANKS: add contributors to 7.71.1 - -- scripts/copyright.pl: skip .dcignore +- [Jeroen Ooms brought this change] -- Revert "multi: implement wait using winsock events" - - This reverts commit 8bc25c590e530de87595d1bb3577f699eb1309b9. + tests: add test1912 with typechecks - That commit (from #5397) introduced a regression in 7.71.0. + Validates that gcc-typecheck macros match the new option type API. - Reported-by: tmkk on github - Fixes #5631 - Closes #5632 - -- TODO: Add flag to specify download directory - -- TODO: return code to CURLMOPT_PUSHFUNCTION to fail connection + Closes #5873 -- cirrus-ci: disable FreeBSD 13 (again) - - It has been failing for a good while again. This time we better leave it - disabled until we have more reason to believe it behaves. +- easyoptions: provide debug function when DEBUGBUILD - Closes #5628 - -- ngtcp2: sync with current master + ... not CURLDEBUG as they're not always set in conjunction. - ngtcp2 added two new callbacks + Follow-up to 6ebe63fac23f38df - Reported-by: Lucien Zürcher - Fixes #5624 - Closes #5627 + Fixes #5877 + Closes #5878 -- examples/multithread.c: call curl_global_cleanup() +Marc Hoersken (28 Aug 2020) +- sockfilt: handle FD_CLOSE winsock event on write socket - Reported-by: qiandu2006 on github - Fixes #5622 - Closes #5623 - -- vtls: compare cert blob when finding a connection to reuse + Learn from the way Cygwin handles and maps the WinSock events + to simulate correct and complete poll and select behaviour + according to Richard W. Stevens Network Programming book. - Reported-by: Gergely Nagy - Fixes #5617 - Closes #5619 - -- RELEASE-NOTES: synced + Follow up to #5867 + Closes #5879 -- terminology: call them null-terminated strings +- multi: handle connection state winsock events - Updated terminology in docs, comments and phrases to refer to C strings - as "null-terminated". Done to unify with how most other C oriented docs - refer of them and what users in general seem to prefer (based on a - single highly unscientific poll on twitter). + Learn from the way Cygwin handles and maps the WinSock events + to simulate correct and complete poll and select behaviour + according to Richard W. Stevens Network Programming book. - Reported-by: coinhubs on github - Fixes #5598 - Closes #5608 + Reviewed-by: Jay Satiro + Reviewed-by: Marcel Raad + + Follow up to #5634 + Closes #5867 -- http: fix proxy auth with blank password +Daniel Stenberg (28 Aug 2020) +- Curl_pgrsTime - return new time to avoid timeout integer overflow - Regression in 7.71.0 + Setting a timeout to INT_MAX could cause an immediate error to get + returned as timeout because of an overflow when different values of + 'now' were used. - Added test case 346 to verify. + This is primarily fixed by having Curl_pgrsTime() return the "now" when + TIMER_STARTSINGLE is set so that the parent function will continue using + that time. - Reported-by: Kristoffer Gleditsch - Fixes #5613 - Closes #5616 + Reported-by: Ionuț-Francisc Oancea + Fixes #5583 + Closes #5847 -- .dcignore: ignore tests and docs directories +- TLS: fix SRP detection by using the proper #ifdefs - This is a config file for deepcode.ai, a static code analyzer. - -Jay Satiro (26 Jun 2020) -- tool_cb_hdr: Fix etag warning output and return code + USE_TLS_SRP will be true if *any* selected TLS backend can use SRP - - Return 'failure' on failure, to follow the existing style. + HAVE_OPENSSL_SRP is defined when OpenSSL can use it - - Put Warning: and the warning message on the same line. + HAVE_GNUTLS_SRP is defined when GnuTLS can use it - Ref: https://github.com/curl/curl/issues/5610 + Clarify in the curl_verison_info docs that CURL_VERSION_TLSAUTH_SRP is + set if at least one of the supported backends offers SRP. - Closes https://github.com/curl/curl/pull/5612 + Reported-by: Stefan Strogin + Fixes #5865 + Closes #5870 -Daniel Stenberg (26 Jun 2020) -- CURLOPT_READFUNCTION.3: provide the upload data size up front - - Assisted-by: Jay Satiro - Closes #5607 +- [Dan Kenigsberg brought this change] -- test1539: do a HTTP 1.0 POST without a set size (fails) + docs: SSLCERTS: fix English syntax - Attempt to reproduce #5593. Test case 1514 is very similar but uses - HTTP/1.1 and thus switches to chunked. + Signed-off-by: Dan Kenigsberg - Closes #5595 + Closes #5876 -- [Baruch Siach brought this change] +- [Alessandro Ghedini brought this change] - mbedtls: fix build with disabled proxy support - - Don't reference fields that do not exist. Fixes build failure: + docs: non-existing macros in man pages - vtls/mbedtls.c: In function 'mbed_connect_step1': - vtls/mbedtls.c:249:54: error: 'struct connectdata' has no member named 'http_proxy' + As reported by man(1) when invoked as: - Closes #5615 - -- codeql-analysis.yml: fix the 'languages' setting + man --warnings -E UTF-8 -l -Tutf8 -Z >/dev/null - It needs a 'with:' in front of it. + Closes #5846 -GitHub (26 Jun 2020) -- [Daniel Stenberg brought this change] +- [Alessandro Ghedini brought this change] - gtihub: codeql-analysis.yml + curl.1: fix typo invokved -> invoked - enables code security scanning with github actions + Closes #5846 -Daniel Stenberg (25 Jun 2020) -- tests: verify newline in username and password for HTTP +- buildconf: invoke 'autoreconf -fi' instead - test 1296 is a simply command line test + The custom script isn't necessary anymore - but remains for simplicity + and just invokes autoreconf. - test 1910 is a libcurl test including a redirect + Closes #5853 -- url: allow user + password to contain "control codes" for HTTP(S) - - Reported-by: Jon Johnson Jr - Fixes #5582 - Closes #5592 +- [Emil Engler brought this change] -- escape: make the URL decode able to reject only %00 bytes + lib: make Curl_gethostname accept a const pointer - ... or all "control codes" or nothing. + The address of that variable never gets changed, only the data in it so + why not make it a "char * const"? - Assisted-by: Nicolas Sterchele + Closes #5866 -- http2: set the correct URL in pushed transfers - - ...previously CURLINFO_EFFECTIVE_URL would report the URL of the - original "mother transfer", not the actually pushed resource. +- docs/libcurl: update "Added in" version for curl_easy_option* - Reported-by: Jonathan Cardoso Machado - Fixes #5589 - Closes #5591 - -Jay Satiro (25 Jun 2020) -- [Javier Blazquez brought this change] + Follow-up to 6ebe63fac23f38 - openssl: Fix compilation on Windows when ngtcp2 is enabled - - - Include wincrypt before OpenSSL includes so that the latter can - properly handle any conflicts between the two. +- scripts: improve the "get latest curl release tag" logic - Closes https://github.com/curl/curl/pull/5606 + ... by insiting on it matching "^curl-". -Daniel Stenberg (25 Jun 2020) -- test543: extended to verify zero length input +- configure: added --disable-get-easy-options - As was reported in #5601 + To allow disabling of the curl_easy_option APIs in a build. + + Closes #5365 -- escape: zero length input should return a zero length output +- options: API for meta-data about easy options - Regression added in 7.71.0. + const struct curl_easyoption *curl_easy_option_by_name(const char *name); - Fixes #5601 - Reported-by: Kristoffer Gleditsch - Closes #5602 - -- Curl_inet_ntop: always check the return code + const struct curl_easyoption *curl_easy_option_by_id (CURLoption id); - Reported-by: Siva Sivaraman - Fixes #5412 - Closes #5597 - -- sendf: improve the message on client write errors + const struct curl_easyoption * + curl_easy_option_next(const struct curl_easyoption *prev); - Replace "Failed writing body (X != Y)" with - "Failure writing output to destination". Possibly slightly less cryptic. + The purpose is to provide detailed enough information to allow for + example libcurl bindings to get option information at run-time about + what easy options that exist and what arguments they expect. - Reported-by: coinhubs on github - Fixes #5594 - Closes #5596 - -- RELEASE-NOTES: synced - -- curlver: start working on 7.71.1 + Assisted-by: Jeroen Ooms + Closes #5365 -- [Denis Baručić brought this change] +- [Eric Curtin brought this change] - DYNBUF.md: fix a typo: trail => tail + HTTP/3: update to OpenSSL_1_1_1g-quic-draft-29 - Closes #5599 - -Version 7.71.0 (23 Jun 2020) - -Daniel Stenberg (23 Jun 2020) -- RELEASE-NOTES: curl 7.71.0 release + Closes #5871 -- THANKS: curl 7.71.0 additions +- RELEASE-NOTES: synced -- url: make sure pushed streams get an allocated download buffer - - Follow-up to c4e6968127e876b0 - - When a new transfer is created, as a resuly of an acknowledged push, - that transfer needs a download buffer allocated. +Jay Satiro (26 Aug 2020) +- openssl: Fix wincrypt symbols conflict with BoringSSL - Closes #5590 - -Jay Satiro (22 Jun 2020) -- openssl: Don't ignore CA paths when using Windows CA store + OpenSSL undefines the conflicting symbols but BoringSSL does not so we + must do it ourselves. - This commit changes the behavior of CURLSSLOPT_NATIVE_CA so that it does - not override CURLOPT_CAINFO / CURLOPT_CAPATH, or the hardcoded default - locations. Instead the CA store can now be used at the same time. + Reported-by: Samuel Tranchet + Assisted-by: Javier Blazquez - The change is due to the impending release. The issue is still being - discussed. The behavior of CURLSSLOPT_NATIVE_CA is subject to change and - is now documented as experimental. + Ref: https://bugs.chromium.org/p/boringssl/issues/detail?id=371 + Ref: https://github.com/openssl/openssl/blob/OpenSSL_1_1_1g/include/openssl/ossl_typ.h#L66-L73 - Ref: bc052cc (parent commit) - Ref: https://github.com/curl/curl/issues/5585 + Fixes https://github.com/curl/curl/issues/5669 + Closes https://github.com/curl/curl/pull/5857 -- tool_operate: Don't use Windows CA store as a fallback - - Background: - - 148534d added CURLSSLOPT_NATIVE_CA to use the Windows OS certificate - store in libcurl w/ OpenSSL on Windows. CURLSSLOPT_NATIVE_CA overrides - CURLOPT_CAINFO if both are set. The curl tool will fall back to - CURLSSLOPT_NATIVE_CA if it could not find a certificate bundle to set - via CURLOPT_CAINFO. - - Problem: - - libcurl may be built with hardcoded paths to a certificate bundle or - directory, and if CURLSSLOPT_NATIVE_CA is used then those paths are - ignored. - - Solution: +Daniel Stenberg (26 Aug 2020) +- socketpair: allow CURL_DISABLE_SOCKETPAIR - A solution is still being discussed but since there's an impending - release this commit removes using CURLSSLOPT_NATIVE_CA in the curl tool. + ... to completely disable the use of socketpair - Ref: https://github.com/curl/curl/issues/5585 + Closes #5850 -- openssl: Fix CA fallback logic for OpenSSL 3.0 build - - Prior to this change I assume a build error would occur when - CURL_CA_FALLBACK was used. +- curl_get_line: build only if cookies or alt-svc are enabled - Closes https://github.com/curl/curl/pull/5587 - -Daniel Stenberg (22 Jun 2020) -- copyright: update mismatched copyright years + Closes #5851 -- test1460: verify that -Ji is not ok +- [fullincome brought this change] -- tool_getparam: -i is not OK if -J is used + schannel: fix memory leak when using get_cert_location - Reported-by: sn on hackerone - Bug: https://curl.haxx.se/docs/CVE-2020-8177.html - -- [Peter Wu brought this change] - - CMake: ignore INTERFACE_LIBRARY targets for pkg-config file + The get_cert_location function allocates memory only on success. + Previously get_cert_location was able to allocate memory and return + error. It wasn't obvious and in this case the memory wasn't + released. - Reviewed-by: Marcel Raad - Fixes #5512 - Closes #5517 + Fixes #5855 + Closes #5860 -- [Valentyn Korniienko brought this change] +- [Emil Engler brought this change] - multibyte: Fixed access-> waccess to file for Windows Plarform + git: ignore libtests in 3XXX area - Reviewed-by: Marcel Raad - Closes #5580 - -- altsvc: bump to h3-29 + Currently the file tests/libtest/lib3010 is not getting + ignored by git. This fixes it by adding the 3XXX area to + the according .gitignore file. - Closes #5584 + Closes #5859 -- urlglob: treat literal IPv6 addresses with zone IDs as a host name +- [Emil Engler brought this change] + + doh: add error message for DOH_DNS_NAME_TOO_LONG - ... and not as a "glob". Now done by passing the supposed host to the - URL parser which supposedly will do a better job at identifying "real" - numerical IPv6 addresses. + When this error code was introduced in b6a53fff6c1d07e8a9, it was + forgotten to be added in the errors array and doh_strerror function. - Reported-by: puckipedia on github - Fixes #5576 - Closes #5579 - -- test1179: verify error message for non-existing cmdline option + Closes #5863 -- tool_getparam: repair the error message for unknown flag +- ngtcp2: adapt to the new pkt_info arguments - Follow-up to 9e5669f3880674 - Detected by Coverity CID 1464582 ("Logically dead code") + Guidance-by: Tatsuhiro Tsujikawa - Closes #5577 - -- FILEFORMAT: describe verify/stderr + Closes #5864 -- connect: improve happy eyeballs handling - - For QUIC but also for regular TCP when the second family runs out of IPs - with a failure while the first family is still trying to connect. +- winbuild/README.md: make visible - Separated the timeout handling for IPv4 and IPv6 connections when they - both have a number of addresses to iterate over. + Follow-up to be753add31c2d8c -- ngtcp2: never call fprintf() in lib code in release version +- winbuild: convert the instruction text to README.md + + Closes #5861 -- ngtcp2: fix happy eyeballs quic connect crash +- lib1560: verify "redirect" to double-slash leading URL - Reported-by: Peter Wu - Fixes #5565 - Closes #5568 + Closes #5849 -- select: remove the unused ELAPSED_MS() macro +Marc Hoersken (25 Aug 2020) +- multi: expand pre-check for socket readiness - Closes #5573 + Check readiness of all sockets before waiting on them + to avoid locking in case the one-time event FD_WRITE + was already consumed by a previous wait operation. + + More information about WinSock network events: + https://docs.microsoft.com/en-us/windows/win32/api/ + winsock2/nf-winsock2-wsaeventselect#return-value + + Closes #5634 -Marc Hoersken (17 Jun 2020) - [rcombs brought this change] multi: implement wait using winsock events @@ -4471,2970 +4662,2786 @@ Marc Hoersken (17 Jun 2020) using a TCP socket on loopback which could in turn lead to socket resource exhaustion. - Reviewed-by: Gergely Nagy - Reviewed-by: Marc Hörsken + A previous version of this patch failed to account for how in WinSock, + FD_WRITE is set only once when writing becomes possible and not again + until after a send has failed due to the buffer filling. This contrasts + to how FD_READ and FD_OOB continue to be set until the conditions they + refer to no longer apply. This meant that if a user wrote some data to + a socket, but not enough data to completely fill its send buffer, then + waited on that socket to become writable, we'd erroneously stall until + their configured timeout rather than returning immediately. - Closes #5397 - -Daniel Stenberg (17 Jun 2020) -- manpage: add three missing environment variables + This version of the patch addresses that issue by checking each socket + we're waiting on to become writable with select() before the wait, and + zeroing the timeout if it's already writable. - CURL_SSL_BACKEND, QLOGDIR and SSLKEYLOGFILE + Assisted-by: Marc Hörsken + Reviewed-by: Marcel Raad + Reviewed-by: Daniel Stenberg + Tested-by: Gergely Nagy + Tested-by: Rasmus Melchior Jacobsen + Tested-by: Tomas Berger - Closes #5571 - -- RELEASE-NOTES: synced + Replaces #5397 + Reverts #5632 + Closes #5634 -- configure: for wolfSSL, check for the DES func needed for NTLM +- select: reduce duplication of Curl_poll in Curl_socket_check - Also adds pkg-config support for the wolfSSL detection. - -- [Ruurd Beerstra brought this change] - - ntlm: enable NTLM support with wolfSSL + Change Curl_socket_check to use select-fallback in Curl_poll + instead of implementing it in Curl_socket_check and Curl_poll. - When wolfSSL is built with its OpenSSL API layer, it fetures the same DES* - functions that OpenSSL has. This change take advantage of that. + Reviewed-by: Daniel Stenberg + Reviewed-by: Jay Satiro - Co-authored-by: Daniel Stenberg - Closes #5556 - Fixes #5548 + Replaces #5262 and #5492 + Closes #5707 -- http: move header storage to Curl_easy from connectdata +- select: fix poll-based check not detecting connect failure - Since the connection can be used by many independent requests (using - HTTP/2 or HTTP/3), things like user-agent and other transfer-specific - data MUST NOT be kept connection oriented as it could lead to requests - getting the wrong string for their requests. This struct data was - lingering like this due to old HTTP1 legacy thinking where it didn't - mattered.. + This commit changes Curl_socket_check to use POLLPRI to + check for connect failure on the write socket, because + POLLPRI maps to fds_err. This is in line with select(2). - Fixes #5566 - Closes #5567 - -- CODE_REVIEW.md: how to do code reviews in curl + The select-based socket check correctly checks for connect + failures by adding the write socket also to fds_err. - Assisted-by: Daniel Gustafsson - Assisted-by: Rich Salz - Assisted-by: Hugo van Kemenade - Assisted-by: James Fuller - Assisted-by: Marc Hörsken - Assisted-by: Jay Satiro + The poll-based implementation (which internally can itself + fallback to select again) did not previously check for + connect failure by using POLLPRI with the write socket. - Closes #5555 - -- altsvc: remove the num field from the altsvc struct + See the follow up commit to this for more information. - It was superfluous since we have the list.size alredy + This commit makes sure connect failures can be detected + and handled if HAVE_POLL_FINE is defined, eg. on msys2-devel. - Reported-by: Jay Satiro - Fixes #5553 - Closes #5563 + Reviewed-by: Daniel Stenberg + Reviewed-by: Jay Satiro + + Replaces #5509 + Prepares #5707 -- version.d: expanded and alpha-sorted +- select.h: make socket validation macros test for INVALID_SOCKET - Added a few missing features not previously mentioned. Ordered them - alphabetically. + With Winsock the valid range is [0..INVALID_SOCKET-1] according to + https://docs.microsoft.com/en-us/windows/win32/winsock/socket-data-type-2 - Closes #5558 + Reviewed-by: Jay Satiro + Reviewed-by: Marcel Raad + Reviewed-by: Daniel Stenberg + + Closes #5760 -- ABI.md: rename to .md and polish the markdown +Daniel Stenberg (24 Aug 2020) +- docs: --output-dir is added in 7.73.0, nothing else - Closes #5562 + Follow-up to 5620d2cc78c0 -- HELP-US: add a section for "smaller tasks" +- curl: add --output-dir - The point of this section is to meet the CII Best Practices gold level - critera: + Works with --create-dirs and with -J - "The project MUST clearly identify small tasks that can be performed by - new or casual contributors" + Add test 3008, 3009, 3011, 3012 and 3013 to verify. - Closes #5560 + Closes #5637 -- TODO: retry on the redirected-to URL +- configure: fix pkg-config detecting wolfssl - Closes #5462 - -- mailmap: Nicolas Sterchele + When amending the include path with "/wolfssl", this now properly strips + off all whitespace from the path variable! Previously this would lead to + pkg-config builds creating bad command lines. + + Closes #5848 -- [Nicolas Sterchele brought this change] +- [Michael Musset brought this change] - TODO: remove 19.3 section title + sftp: add the option CURLKHSTAT_FINE_REPLACE - Follow-up to ad6416986755e417c66e2c6, which caused wrong formatting on - curl documentation website + Replace the old fingerprint of the host with a new. - Closes #5561 - -- [Martin V brought this change] + Closes #5685 - test1560: avoid possibly negative association in wording +- RELEASE-NOTES: synced - Closes #5549 + The next release is now to become 7.73.0 -- share: don't set the share flag it something fails - - When asking for a specific feature to be shared in the share object, - that bit was previously set unconditionally even if the shared feature - failed or otherwise wouldn't work. +- checksrc: verify do-while and spaces between the braces - Closes #5554 - -- buildconf: remove -print from the find command that removes files + Updated mprintf.c to comply - It's just too annoying and unnecessary to get a long list of files shown - -- RELEASE-NOTES: synced + Closes #5845 -- wording: avoid blacklist/whitelist stereotypes +- curl: support XDG_CONFIG_HOME to find .curlrc - Instead of discussing if there's value or meaning (implied or not) in - the colors, let's use words without the same possibly negative - associations. + Added test433 to verify. Updated documentation. - Closes #5546 + Reviewed-by: Jay Satiro + Suggested-by: Eli Schwartz + Fixes #5829 + Closes #5837 -Jay Satiro (9 Jun 2020) -- tool_getparam: fix memory leak in parse_args +- etag: save and use the full received contents - Prior to this change in Windows Unicode builds most parsed options would - not be freed. + ... which makes it support weak tags and non-standard etags too! - Found using _CrtDumpMemoryLeaks(). + Added test case 347 to verify blank incoming ETag: - Ref: https://github.com/curl/curl/issues/5545 + Fixes #5610 + Closes #5833 -Daniel Stenberg (8 Jun 2020) -- socks: detect connection close during handshake +- setopt: if the buffer exists, refuse the new BUFFERSIZE - The SOCKS4/5 state machines weren't properly terminated when the proxy - connection got closed, leading to a busy-loop. + The buffer only exists during transfer and then we shouldn't change the + size (the setopt is not documented to work then). - Reported-By: zloi-user on github - Fixes #5532 - Closes #5542 + Reported-by: Harry Sintonen + Closes #5842 -- [James Fuller brought this change] +- [COFFEETALES brought this change] - multi: add defensive check on data->multi->num_alive + sftp: add new quote commands 'atime' and 'mtime' - Closes #5540 + Closes #5810 -- Curl_addrinfo: use one malloc instead of three +- CURLE_PROXY: new error code - To reduce the amount of allocations needed for creating a Curl_addrinfo - struct, make a single larger malloc instead of three separate smaller - ones. + Failures clearly returned from a (SOCKS) proxy now causes this return + code. Previously the situation was not very clear as what would be + returned and when. - Closes #5533 - -- [Alessandro Ghedini brought this change] + In addition: when this error code is returned, an application can use + CURLINFO_PROXY_ERROR to query libcurl for the detailed error, which then + returns a value from the new 'CURLproxycode' enum. + + Closes #5770 - quiche: update SSLKEYLOGFILE support +- runtests: make cleardir() erase dot files too - quiche now requires the application to explicitly set the keylog path - for each connection, rather than reading the environment variable - itself. + Because test cases might use dot files. - Closes #5541 + Closes #5838 -- tests: add two simple tests for --login-options +- KNOWN_BUGS: 'no_proxy' string-matches IPv6 numerical addreses - Test 895 and 896 - as a follow-up to a3e972313b + Also: the current behavior is now documented in the curl.1 and + CURLOPT_NOPROXY.3 man pages. - Closes #5539 + Reported-by: Andrew Barnes + Closes #5745 + Closes #5841 -- ngtcp2: update with recent API changes +Viktor Szakats (22 Aug 2020) +- Makefile.m32: add ability to override zstd libs [ci skip] - Syncs with ngtcp2 commit 7e9a917d386d98 merged June 7 2020. + Similarly to brotli, where this was already possible. + E.g. it allows to link zstd statically to libcurl.dll. - Assisted-by: Tatsuhiro Tsujikawa - Closes #5538 - -- [James Fuller brought this change] + Ref: https://github.com/curl/curl-for-win/issues/12 + Ref: https://github.com/curl/curl-for-win/commit/d9b266afd2e5d3f5604483010ef62340b5918c89 + + Closes https://github.com/curl/curl/pull/5840 - socks: remove unreachable breaks in socks.c and mime.c +Daniel Stenberg (21 Aug 2020) +- runtests: avoid 'fail to start' repeated messages in attempt loops - Closes #5537 + Closes #5834 -- tool_cfgable: free login_options at exit +- runtests: clear pid variables when failing to start a server - Memory leak - Reported-by: Geeknik Labs - Fixes #5535 - Closes #5536 + ... as otherwise the parent doesn't detect the failure and believe it + actually worked to start. + + Reported-by: Christian Weisgerber + Bug: https://curl.haxx.se/mail/lib-2020-08/0018.html + Closes #5834 -- libssh2: keep sftp errors as 'unsigned long' +- TODO: Virtual external sockets - Remove weird work-around for storing the SFTP errors as int instead of - the "unsigned long" that libssh2 actually returns for SFTP errors. + Closes #5835 + +- [Don J Olmstead brought this change] + + dist: add missing CMake Find modules to the distribution - Closes #5534 + Closes #5836 -Marc Hoersken (6 Jun 2020) -- timeouts: move ms timeouts to timediff_t from int and long +- RELEASE-NOTES: synced - Now that all functions in select.[ch] take timediff_t instead - of the limited int or long, we can remove type conversions - and related preprocessor checks to silence compiler warnings. + ... and version bumped to 7.72.1 + +- tls: provide the CApath verbose log on its own line - Avoiding conversions from time_t was already done in 842f73de. + ... not newline separated from the previous line. This makes it output + asterisk prefixed properly like other verbose putput! - Based upon #5262 - Supersedes #5214, #5220 and #5221 - Follow up to #5343 and #5479 - Closes #5490 + Reported-by: jmdavitt on github + Fixes #5826 + Closes #5827 -Daniel Stenberg (6 Jun 2020) -- [François Rigault brought this change] +Version 7.72.0 (19 Aug 2020) - openssl: set FLAG_TRUSTED_FIRST unconditionally +Daniel Stenberg (19 Aug 2020) +- RELEASE-NOTES: synced - On some systems, openssl 1.0.x is still the default, but it has been - patched to contain all the recent security fixes. As a result of this - patching, it is possible for macro X509_V_FLAG_NO_ALT_CHAINS to be - defined, while the previous behavior of openssl to not look at trusted - chains first, remains. + The curl 7.72.0 release + +- THANKS: add names from curl 7.72.0 release + +Jay Satiro (18 Aug 2020) +- KNOWN_BUGS: Schannel TLS 1.2 handshake bug in old Windows versions - Fix it: ensure X509_V_FLAG_TRUSTED_FIRST is always set, do not try to - probe for the behavior of openssl based on the existence ofmacros. + Reported-by: plujon@users.noreply.github.com - Closes #5530 + Closes https://github.com/curl/curl/issues/5488 -- server/util: fix logmsg format using curl_off_t argument +Daniel Stenberg (17 Aug 2020) +- Curl_easy: remember last connection by id, not by pointer - ... this caused segfaults on armv7. + CVE-2020-8231 - Regression added in dd0365d560aea5a (7.70.0) + Bug: https://curl.haxx.se/docs/CVE-2020-8231.html - Reviewed-by: Jay Satiro - Closes #5529 + Reported-by: Marc Aldorasi + Closes #5824 -- RELEASE-NOTES: synced +- examples/rtsp.c: correct the copyright year -- [Cherish98 brought this change] +- RELEASE-PROCEDURE.md: add more future release dates - socks: fix expected length of SOCKS5 reply +- [H3RSKO brought this change] + + docs: change "web site" to "website" - Commit 4a4b63d forgot to set the expected SOCKS5 reply length when the - reply ATYP is X'01'. This resulted in erroneously expecting more bytes - when the request length is greater than the reply length (e.g., when - remotely resolving the hostname). + According to wikipedia: - Closes #5527 - -Marc Hoersken (5 Jun 2020) -- .gitignore: add directory containing the stats repo + While "web site" was the original spelling, this variant has become + rarely used, and "website" has become the standard spelling - Since the new curl/stats repository is designed to be - checked out into the curl repository working tree as stats/ - it should be on the ignore list to aid in commit staging. + Closes #5822 -Daniel Stenberg (5 Jun 2020) -- [Adnan Khan brought this change] +- [Bevan Weiss brought this change] - HTTP3.md: clarify cargo build directory + CMake: don't complain about missing nroff - Cargo needs to be called from within the 'quiche' directory. + The curl_nroff_check() was always being called, and complaining if + *NROFF wasn't found, even when not making the manual. - Closes #5522 - -- user-agent.d: spell out what happens given a blank argument + Only check for nroff (and complain) if actually making the manual - Closes #5525 + Closes #5817 -- trailers: switch h1-trailer logic to use dynbuf +- [Brian Inglis brought this change] + + libtest/Makefile.am: add -no-undefined for libstubgss for Cygwin - In the continued effort to remove "manual" realloc schemes. + copy the LDFLAGS approach for adding same option with `libhostname` in + `libtest/Makefile.am`: - Closes #5524 - -- CURLINFO_ACTIVESOCKET.3: clarify the description + - init `libstubgss_la_LDFLAGS_EXTRA` variable, + - add option to variable inside conditional, + - use variable in `libstubgss_la_LDFLAGS` - Reported-by: Jay Satiro - Fixes #5299 - Closes #5520 - -- mailmap: Don J Olmstead + Fixes #5819 + Closes #5820 -- configure: only strip first -L from LDFLAGS - - In the logic that works out if a given OpenSSL path works, it stripped - off a possibly leading -L flag using an incorrect sed pattern which - would remove all instances of -L in the string, including if the path - itself contained that two-letter sequence! +- docs: clarify MAX_SEND/RECV_SPEED functionality - The same pattern was used and is now updated in multiple places. Now it - only removes -L if it starts the strings. + ... in particular what happens if the maximum speed limit is set to a + value that's smaller than the transfer buffer size in use. - Reported-by: Mohamed Osama - Fixes #5519 - Closes #5521 + Reported-by: Tomas Berger + Fixes #5788 + Closes #5813 -Peter Wu (4 Jun 2020) -- quiche: advertise draft 28 support +- test1140: compare stdout - Fix the verbose message while at it, quiche currently supports draft - 27 and draft 28 simultaneously. + To make problems more immediately obvious when tests fail. - Closes #5518 + Closes #5814 -Daniel Stenberg (4 Jun 2020) -- KNOWN_BUGS: RTSP authentication breaks without redirect support +- asyn-ares: correct some bad comments - Closes #4750 + Closes #5812 -Jay Satiro (4 Jun 2020) -- projects: Add crypt32.lib to dependencies for all OpenSSL configs - - Windows project configurations that use OpenSSL with USE_WIN32_CRYPTO - need crypt32. - - Follow-up to 148534d which added CURLSSLOPT_NATIVE_CA for 7.71.0. - - The changes that are in this commit were made by script. - - Ref: https://gist.github.com/jay/a1861b50ecce2b32931237180f856e28 +- [Emil Engler brought this change] + + docs: Add video link to docs/CONTRIBUTE.md - Closes https://github.com/curl/curl/pull/5516 + Closes #5811 -Marc Hoersken (3 Jun 2020) -- CI/macos: fix 'is already installed' errors by using bundle +- curl-config: ignore REQUIRE_LIB_DEPS in --libs output - Avoid failing CI builds due to nghttp2 being already installed. + Fixes a curl-config issue on cygwin by making sure REQUIRE_LIB_DEPS is + not considered for the --libs output. - Closes #5513 + Reported-by: ramsay-jones on github + Assisted-by: Brian Inglis and Ken Brown + Fixes #5793 + Closes #5808 -Daniel Stenberg (3 Jun 2020) -- altsvc: fix 'dsthost' may be used uninitialized in this function +- copyright: update/correct the year range on a few files -- RELEASE-NOTES: synced +- scripts/copyright.pl: ignore .muse files -- urldata: let the HTTP method be in the set.* struct - - When the method is updated inside libcurl we must still not change the - method as set by the user as then repeated transfers with that same - handle might not execute the same operation anymore! - - This fixes the libcurl part of #5462 +- [Emil Engler brought this change] + + multi: Remove 10-year old out-commented code - Test 1633 added to verify. + The code hasn't been touched since 2010-08-18 - Closes #5499 + Closes #5805 -- hostip: fix the memory-leak introduced in 67d2802 +- KNOWN_BUGS: A shared connection cache is not thread-safe - Fixes #5503 - Closes #5504 + Closes #4915 + Closes #5802 -- test970: make it require proxy support +- CONTRIBUTE: extend git commit message description - This test verifies the -w %json output and the test case includes a full - generated "blob". If there's no proxy support built into libcurl, it - will return an error for proxy related info variables and they will not - be included in the json, thus causing a mismatch and this test fails. + In particular how the first line works. - Reported-by: Marc Hörsken - Fixes #5501 - Closes #5502 - -- [Radoslav Georgiev brought this change] + Closes #5803 - examples/http2-down/upload: add error checks - - If `index.html` does not exist in the directory from which the example - is invoked, the fopen(upload, "rb") invocation in `setup` would fail, - returning NULL. This value is subsequently passed as the FILE* argument - of the `fread` invocation in the `read_callback` function, which is the - actual cause of the crash (apparently `fread` assumes that argument to - be non-null). - - In addition, mitigate some possible crashes of similar origin. - - Closes #5463 +- RELEASE-NOTES: synced -- [kotoriのねこ brought this change] +- [Stefan Yohansson brought this change] - examples/ephiperfifo: turn off interval when setting timerfd + transfer: move retrycount from connect struct to easy handle - Reported-by: therealhirudo on github - Fixes #5485 - Closes #5497 - -- [Saleem Abdulrasool brought this change] + This flag was applied to the connection struct that is released on + retry. These changes move the retry counter into Curl_easy struct that + lives across retries and retains the new connection. + + Reported-by: Cherish98 on github + Fixes #5794 + Closes #5800 - vtls: repair the build with `CURL_DISABLE_PROXY` +- libssh2: s/ssherr/sftperr/ - `http_proxy` will not be available in `conndata` if `CURL_DISABLE_PROXY` - is enabled. Repair the build with that configuration. + The debug output used ssherr instead of sftperr which not only outputs + the wrong error code but also casues a warning on Windows. - Follow-up to f3d501dc67 + Follow-up to 7370b4e39f1 - Closes #5498 + Reported-by: Gisle Vanem + Bug: https://github.com/curl/curl/commit/7370b4e39f1390e701f5b68d910c619151daf72b#r41334700 + Closes #5799 -- transfer: remove k->str NULL check +- ftp: don't do ssl_shutdown instead of ssl_close - "Null-checking k->str suggests that it may be null, but it has already - been dereferenced on all paths leading to the check" - and it can't - legally be NULL at this point. Remove check. + The shutdown function is for downgrading a connection from TLS to plain, + and this is not requested here. - Detected by Coverity CID 1463884 + Have ssl_close reset the TLS connection state. - Closes #5495 - -Marc Hoersken (1 Jun 2020) -- select: always use Sleep in Curl_wait_ms on Win32 + This partially reverts commit f002c850d98d - Since Win32 almost always will also have USE_WINSOCK, - we can reduce complexity and always use Sleep there. + Reported-by: Rasmus Melchior Jacobsen + Reported-by: Denis Goleshchikhin + Fixes #5797 + +Marc Hoersken (9 Aug 2020) +- CI/azure: fix test outcome values and use latest API version - Assisted-by: Jay Satiro - Reviewed-by: Daniel Stenberg + This makes sure that tests ignored or skipped are not shown + just in the category "Other", but with their correct state. - Follow up to #5343 - Closes #5489 + Closes #5796 -Daniel Stenberg (31 May 2020) -- conncache: download buffer needs +1 size for trailing zero +- CI/azure: show runtime stats to investigate slowness - Follow-up to c4e6968127e - Detected by OSS-Fuzz: https://oss-fuzz.com/testcase-detail/5727799779524608 + Also avoid naming conflict of TFLAGS env and tflags variables. + + Closes #5776 -Marc Hoersken (31 May 2020) -- azure: use matrix strategy to avoid configuration redundancy +Daniel Stenberg (8 Aug 2020) +- TLS naming: fix more Winssl and Darwinssl leftovers - This also includes the following changes: + The CMake option is now called CMAKE_USE_SCHANNEL - - Use the same timeout for all jobs on Linux (60 minutes) - and Windows (90 minutes) - - Use CLI stable apt-get install -y instead of apt install - which warns about that and run apt-get update first - - Enable MQTT for Windows msys2 builds instead of - legacy msys1 builds - - Add ./configure --prefix parameter to the msys2 builds - - The MSYSTEM environment variable is now preset inside - the container images for the msys2 builds + The winbuild flag is USE_SCHANNEL - Note: on Azure Pipelines the matrix strategy is basically - just a simple list of job copies and not really a matrix. + The CI jobs and build scripts only use the new names and the new name + options - Closes #5468 + Tests now require 'Schannel' (when necessary) + + Closes #5795 -Daniel Stenberg (30 May 2020) -- build: disable more code/data when built without proxy support +- smtp_parse_address: handle blank input string properly - Added build to travis to verify + Closes #5792 + +- runtests: run the DICT server on a random port number - Closes #5466 + Removed support for -b (base port number) + + Closes #5783 -- url: alloc the download buffer at transfer start +- RELEASE-NOTES: synced + +- runtests: move the TELNET server to a dynamic port - ... and free it as soon as the transfer is done. It removes the extra - alloc when a new size is set with setopt() and reduces memory for unused - easy handles. + Rename the port variable to TELNETPORT to better match the existing + pattern. - In addition: the closure_handle now doesn't use an allocated buffer at - all but the smallest supported size as a stack based one. + Closes #5785 + +- ngtcp2: adapt to error code rename - Closes #5472 + Closes #5786 -- timeouts: change millisecond timeouts to timediff_t from time_t +- runtests: move the smbserver to use a dynamic port number - For millisecond timers we like timediff_t better. Also, time_t can be - unsigned so returning a negative value doesn't work then. + Closes #5782 + +- runtests: run the http2 tests on a random port number - Closes #5479 + Closes #5779 -Marc Hoersken (30 May 2020) -- select: add overflow checks for timeval conversions +- gtls: survive not being able to get name/issuer - Using time_t and suseconds_t if suseconds_t is available, - long on Windows (maybe others in the future) and int elsewhere. + Closes #5778 + +- runtests: move the gnutls-serv tests to a dynamic port - Also handle case of ULONG_MAX being greater or equal to INFINITE. + Affects test 320, 321, 322 and 324. - Assisted-by: Jay Satiro - Reviewed-by: Daniel Stenberg + Closes #5778 + +- runtests: support dynamicly base64 encoded sections in tests - Part of #5343 + This allows us to make test cases to use base64 at run-time and still + use and verify information determined at run-time, such as the IMAP test + server's port number in test 842. + + This change makes 12 tests run again that basically never ran since we + moved to dynamic port numbers. + + ftpserver.pl is adjusted to load test instructions and test number from + the preprocessed test file. + + FILEFORMAT.md now documents the new base64 encoding syntax. + + Reported-by: Marcel Raad + Fixes #5761 + Closes #5775 -- select: use timediff_t instead of time_t and int for timeout_ms +- curl.1: add a few missing valid exit codes - Make all functions in select.[ch] take timeout_ms as timediff_t - which should always be large enough and signed on all platforms - to take all possible timeout values and avoid type conversions. + 93 - 96 can be returned as well. - Reviewed-by: Jay Satiro - Reviewed-by: Daniel Stenberg + Closes #5777 + +- TODO: Use multiple parallel transfers for a single download - Replaces #5107 and partially #5262 - Related to #5240 and #5286 - Closes #5343 + Closes #5774 -- unit1604.c: fix implicit conv from 'SANITIZEcode' to 'CURLcode' +- TODO: Set the modification date on an uploaded file - GCC 10 warns about this with warning: implicit conversion - from 'SANITIZEcode' to 'CURLcode' [-Wenum-conversion] + Closes #5768 + +- [Thomas M. DuBuisson brought this change] + + CI: Add muse CI config - Since 'expected_result' is not really of type 'CURLcode' and - it is not exposed in any way, we can just use 'SANITIZEcode'. + Closes #5772 + +- [Thomas M. DuBuisson brought this change] + + travis/script.sh: fix use of `-n' with unquoted envvar - Reviewed-by: Daniel Stenberg - Reviewed-by: Marcel Raad + Shellcheck tells us "-n doesn't work with unquoted arguments. quote or + use [[ ]]." - Closes #5476 + And testing shows: + + ``` + docker run --rm -it ubuntu bash + root@fe85ce156856:/# [ -n $DOES_NOT_EXIST ] && echo "I ran" + I ran + root@fe85ce156856:/# [ -n "$DOES_NOT_EXIST" ] && echo "I ran" + root@fe85ce156856:/# + ``` + + Closes #5773 -- tests/libtest: fix undefined reference to 'curlx_win32_fopen' +- h2: repair trailer handling - Since curl_setup.h now makes use of curlx_win32_fopen for Win32 - builds with USE_WIN32_LARGE_FILES or USE_WIN32_SMALL_FILES defined, - we need to include the relevant files for tests using fopen, - because the libtest sources are also including curl_setup.h + The previous h2 trailer fix in 54a2b63 was wrong and caused a + regression: it cannot deal with trailers immediately when read since + they may be read off the connection by the wrong 'data' owner. - Reviewed-by: Marcel Raad - Reviewed-by: Daniel Stenberg + This change reverts the logic back to gathering all trailers into a + single buffer, like before 54a2b63. - Follow up to #3784 (ffdddb45d9) - Closes #5475 + Reported-by: Tadej Vengust + Fixes #5663 + Closes #5769 -- appveyor: add non-debug plain autotools-based build +Viktor Szakats (3 Aug 2020) +- windows: disable Unix Sockets for old mingw - This should enable us to catch linking issues with the - testsuite early, like the one described/fixed in #5475. + Classic mingw and 10y+ old versions of mingw-w64 don't ship with + Windows headers having the typedef necessary for Unix Sockets + support, so try detecting these environments to disable this + feature. + + Ref: https://sourceforge.net/p/mingw-w64/mingw-w64/ci/cf6afc57179a5910621215f8f4037d406892072c/ Reviewed-by: Daniel Stenberg - Reviewed-by: Marcel Raad - Closes #5477 + Fixes #5674 + Closes #5758 + +Marcel Raad (3 Aug 2020) +- test1908: treat file as text + + Fixes the line endings on Windows. + + Closes https://github.com/curl/curl/pull/5767 + +- TrackMemory tests: ignore realloc and free in getenv.c + + These are only called for WIN32. + + Closes https://github.com/curl/curl/pull/5767 + +Daniel Stenberg (3 Aug 2020) +- tests/FILEFORMAT.md: mention %HTTP2PORT -Daniel Stenberg (29 May 2020) - RELEASE-NOTES: synced -- Revert "buildconf: use find -execdir" +- tlsv1.3.d. only for TLS-using connections - This partially reverts commit c712009838f44211958854de431315586995bc61. + ... and rephrase that "not all" TLS backends support it. - Keep the ares_ files removed but bring back the older way to run find, - to make it work with busybox's find, as apparently that's being used. + Closes #5764 + +- tls-max.d: this option is only for TLS-using connections - Reported-by: Max Peal - Fixes #5483 - Closes #5484 + Ref: #5763 + Closes #5764 -- server/sws: fix asan warning on use of uninitialized variable +Marcel Raad (2 Aug 2020) +- [Cameron Cawley brought this change] -- libssh2: improved error output for wrong quote syntax + tool_doswin: Simplify Windows version detection - Reported-by: Werner Stolz + Closes https://github.com/curl/curl/pull/5754 + +- [Cameron Cawley brought this change] + + win32: Add Curl_verify_windows_version() to curlx - Closes #5474 + Closes https://github.com/curl/curl/pull/5754 -- mk-lib1521: generate code for testing BLOB options as well +- runtests.pl: treat LibreSSL and BoringSSL as OpenSSL - Follow-up to cac5374298b3 + This makes the tests that require the OpenSSL feature also run for + those two compatible libraries. - Closes #5478 + Closes https://github.com/curl/curl/pull/5762 -- configure: repair the check if argv can be written to +Daniel Stenberg (1 Aug 2020) +- multi: Condition 'extrawait' is always true - Due to bad escaping of the test code, the test wouldn't build and thus - result in a negative test result, which would lead to the unconditional - assumption that overwriting the arguments doesn't work and thus curl - would never hide credentials given in the command line, even when it - would otherwise be possible. + Reported by Codacy. - Regression from commit 2d4c2152c (7.60.0) + Reviewed-by: Marcel Raad + Closes #5759 + +Marcel Raad (1 Aug 2020) +- openssl: fix build with LibreSSL < 2.9.1 - Reported-by: huzunhao on github - Fixes #5470 - Closes #5471 + `SSL_CTX_add0_chain_cert` and `SSL_CTX_clear_chain_certs` were + introduced in LibreSSL 2.9.1 [0]. + + [0] https://github.com/libressl-portable/openbsd/commit/0db809ee178457c8170abfae3931d7bd13abf3ef + + Closes https://github.com/curl/curl/pull/5757 -Peter Wu (28 May 2020) -- CMake: rebuild Makefile.inc.cmake when Makefile.inc changes +Daniel Stenberg (1 Aug 2020) +- [Marc Aldorasi brought this change] + + multi_remove_handle: close unused connect-only connections - Otherwise the build might fail due to missing source files, as - demonstrated by the recent keylog.c addition on an existing build dir. + Previously any connect-only connections in a multi handle would be kept + alive until the multi handle was closed. Since these connections cannot + be re-used, they can be marked for closure when the associated easy + handle is removed from the multi handle. - Closes #5469 + Closes #5749 -Daniel Stenberg (28 May 2020) -- urldata: fix comments: Curl_done() is called multi_done() now +- checksrc: invoke script with -D to find .checksrc proper - ... since 575e885db + Without the -D command line option, checksrc.pl won't know which + directory to load the ".checksrc" file from when building out of the + source tree. + + Reported-by: Marcel Raad + Fixes #5715 + Closes #5755 -Peter Wu (27 May 2020) -- ngtcp2: use common key log routine for better thread-safety +- [Carlo Marcelo Arenas Belón brought this change] + + buildconf: retire ares buildconf invocation - Tested with ngtcp2 built against the OpenSSL library. Additionally - tested with MultiSSL (NSS for TLS and ngtcp2+OpenSSL for QUIC). + no longer needed after 4259d2df7dd95637a4b1e3fb174fe5e5aef81069 + +- [Carlo Marcelo Arenas Belón brought this change] + + buildconf: excempt defunct reference to ACLOCAL_FLAGS - The TLS backend (independent of QUIC) may or may not already have opened - the keylog file before. Therefore Curl_tls_keylog_open is always called - to ensure the file is open. + retired with 09f278121e815028adb24d228d8092fc6cb022aa but kept around as + the name is generic enough that it might be in use and relied upon from + the environment. -- wolfssl: add SSLKEYLOGFILE support +- [Carlo Marcelo Arenas Belón brought this change] + + buildconf: avoid array concatenation in die() - Tested following the same curl and tshark commands as in commit - "vtls: Extract and simplify key log file handling from OpenSSL" using - WolfSSL v4.4.0-stable-128-g5179503e8 from git master built with - `./configure --enable-all --enable-debug CFLAGS=-DHAVE_SECRET_CALLBACK`. + reported as error SC2145[1] by shellcheck, but not expected to cause + any behavioural differences otherwise. - Full support for this feature requires certain wolfSSL build options, - see "Availability note" in lib/vtls/wolfssl.c for details. + [1] https://github.com/koalaman/shellcheck/wiki/SC2145 - Closes #5327 + Closes #5701 -- vtls: Extract and simplify key log file handling from OpenSSL +- travis: add ppc64le and s390x builds - Create a set of routines for TLS key log file handling to enable reuse - with other TLS backends. Simplify the OpenSSL backend as follows: + Closes #5752 + +Marc Hoersken (31 Jul 2020) +- connect: remove redundant message about connect failure - - Drop the ENABLE_SSLKEYLOGFILE macro as it is unconditionally enabled. - - Do not perform dynamic memory allocation when preparing a log entry. - Unless the TLS specifications change we can suffice with a reasonable - fixed-size buffer. - - Simplify state tracking when SSL_CTX_set_keylog_callback is - unavailable. My original sslkeylog.c code included this tracking in - order to handle multiple calls to SSL_connect and detect new keys - after renegotiation (via SSL_read/SSL_write). For curl however we can - be sure that a single master secret eventually becomes available - after SSL_connect, so a simple flag is sufficient. An alternative to - the flag is examining SSL_state(), but this seems more complex and is - not pursued. Capturing keys after server renegotiation was already - unsupported in curl and remains unsupported. + Reviewed-by: Daniel Stenberg - Tested with curl built against OpenSSL 0.9.8zh, 1.0.2u, and 1.1.1f - (`SSLKEYLOGFILE=keys.txt curl -vkso /dev/null https://localhost:4433`) - against an OpenSSL 1.1.1f server configured with: + Closes #5708 + +- tests/sshserver.pl: fix compatibility with OpenSSH for Windows - # Force non-TLSv1.3, use TLSv1.0 since 0.9.8 fails with 1.1 or 1.2 - openssl s_server -www -tls1 - # Likewise, but fail the server handshake. - openssl s_server -www -tls1 -Verify 2 - # TLS 1.3 test. No need to test the failing server handshake. - openssl s_server -www -tls1_3 + Follow up to #5721 + +- CI/azure: install libssh2 for use with msys2-based builds - Verify that all secrets (1 for TLS 1.0, 4 for TLS 1.3) are correctly - written using Wireshark. For the first and third case, expect four - matches per connection (decrypted Server Finished, Client Finished, HTTP - Request, HTTP Response). For the second case where the handshake fails, - expect a decrypted Server Finished only. + This enables building and running the SFTP tests. + Unfortunately OpenSSH for Windows does not support SCP (yet). - tshark -i lo -pf tcp -otls.keylog_file:keys.txt -Tfields \ - -eframe.number -eframe.time -etcp.stream -e_ws.col.Info \ - -dtls.port==4433,http -ohttp.desegment_body:FALSE \ - -Y 'tls.handshake.verify_data or http' + Reviewed-by: Daniel Stenberg - A single connection can easily be identified via the `tcp.stream` field. + Closes #5721 -Daniel Stenberg (27 May 2020) -- FILEFORMAT: add more features that tests can depend on +- CI/azure: increase Windows job timeout once again + + Avoid aborted jobs due to performance issues on Azure DevOps. + + Reviewed-by: Daniel Stenberg + Reviewed-by: Jay Satiro + + Closes #5738 -- [Michael Kaufmann brought this change] +Jay Satiro (30 Jul 2020) +- TODO: Schannel: 'Add option to allow abrupt server closure' + + We should offer an option to allow abrupt server closures (server closes + SSL transfer without sending a known termination point such as length of + transfer or close_notify alert). Abrupt server closures are usually + because of misconfigured or very old servers. + + Closes https://github.com/curl/curl/issues/4427 - transfer: close connection after excess data has been read +- url: fix CURLU and location following - For HTTP 1.x, it's a protocol error when the server sends more bytes - than announced. If this happens, don't reuse the connection, because the - start position of the next response is undefined. + Prior to this change if the user set a URL handle (CURLOPT_CURLU) it was + incorrectly used for the location follow, resulting in infinite requests + to the original location. - Closes #5440 + Reported-by: sspiri@users.noreply.github.com + + Fixes https://github.com/curl/curl/issues/5709 + Closes https://github.com/curl/curl/pull/5713 -- [Estanislau Augé-Pujadas brought this change] +Daniel Stenberg (30 Jul 2020) +- RELEASE-NOTES: synced - Revert "ssh: ignore timeouts during disconnect" +- [divinity76 brought this change] + + docs: add date of 7.20 to CURLM_CALL_MULTI_PERFORM mentions - This reverts commit f31760e63b4e9ef1eb25f8f211390f8239388515. Shipped in - curl 7.54.1. + it helps make it obvious that most developers don't have to care about + the CURLM_CALL_MULTI_PERFORM value (last release using it is nearly 11 + years old, November 4 2009) - Bug: https://curl.haxx.se/mail/lib-2020-05/0068.html - Closes #5465 + Closes #5744 -- urldata: connect related booleans live in struct ConnectBits +Jay Satiro (29 Jul 2020) +- tool_cb_wrt: fix outfile mode flags for Windows - And remove a few unused booleans! + - Use S_IREAD and S_IWRITE mode permission flags to create the file + on Windows instead of S_IRUSR, S_IWUSR, etc. - Closes #5461 + Windows only accepts a combination of S_IREAD and S_IWRITE. It does not + acknowledge other combinations, for which it may generate an assertion. + + This is a follow-up to 81b4e99 from yesterday, which improved the + existing file check with -J. + + Ref: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/open-wopen#remarks + Ref: https://github.com/curl/curl/pull/5731 + + Closes https://github.com/curl/curl/pull/5742 -- hostip: on macOS avoid DoH when given a numerical IP address +Daniel Stenberg (28 Jul 2020) +- checksrc: ban gmtime/localtime - When USE_RESOLVE_ON_IPS is set (defined on macOS), it means that - numerical IP addresses still need to get "resolved" - but not with DoH. + They're not thread-safe so they should not be used in libcurl code. - Reported-by: Viktor Szakats - Fixes #5454 - Closes #5459 + Explictly enabled when deemed necessary and in examples and tests + + Reviewed-by: Nicolas Sterchele + Closes #5732 -- ngtcp2: cleanup memory when failing to connect +- transfer: fix data_pending for builds with both h2 and h3 enabled - Reported-by: Peter Wu - Fixes #5447 (the ngtcp2 side of it) - Closes #5451 + Closes #5734 -- quiche: clean up memory properly when failing to connect +- curl_multi_setopt: fix compiler warning "result is always false" - Addresses the quiche side of #5447 - Reported-by: Peter Wu - Closes #5450 + On systems with 32 bit long the expression is always false. Avoid + the warning. + + Reported-by: Gisle Vanem + Bug: https://github.com/curl/curl/commit/61a08508f6a458fe21bbb18cd2a9bac2f039452b#commitcomment-40941232 + Closes #5736 -- cleanup: use a single space after equals sign in assignments +- curl: improve the existing file check with -J + + Previously a file that isn't user-readable but is user-writable would + not be properly avoided and would get overwritten. + + Reported-by: BrumBrum on hackerone + Assisted-by: Jay Satiro + Bug: https://hackerone.com/reports/926638 + Closes #5731 -- url: accept "any length" credentials for proxy auth +- [Jonathan Nieder brought this change] + + multi: update comment to say easyp list is linear - They're only limited to the maximum string input restrictions, not to - 256 bytes. + Since 09b9fc900 (multi: remove 'Curl_one_easy' struct, phase 1, + 2013-08-02), the easy handle list is not circular but ends with + ->next pointing to NULL. - Added test 1178 to verify + Reported-by: Masaya Suzuki + Closes #5737 + +- CURLOPT_NOBODY.3: fix the syntax for referring to options - Reported-by: Will Roberts - Fixes #5448 - Closes #5449 + As test 1140 fails otherwise! + + Follow-up to e1bac81cc815 -- [Maksim Stsepanenka brought this change] +- ngtcp2: store address in sockaddr_storage + + Reported-by: Tatsuhiro Tsujikawa + Closes #5733 - test1167: fixes in badsymbols.pl +- CURLOPT_NOBODY.3: clarify what setting to 0 means - Closes #5442 + ... and mention that HTTP with other methods than HEAD might get a body and + there's no option available to stop that. + + Closes #5729 -- altsvc: fix parser for lines ending with CRLF +- setopt: unset NOBODY switches to GET if still HEAD + + Unsetting CURLOPT_NOBODY with 0L when doing HTTP has no documented + action but before 7.71.0 that used to switch back to GET and with this + change (assuming the method is still set to HEAD) this behavior is + brought back. + + Reported-by: causal-agent on github + Fixes #5725 + Closes #5728 + +- [Ehren Bendler brought this change] + + configure: cleanup wolfssl + pkg-config conflicts when cross compiling. + + Also choose a different wolfSSL function to test for NTLM support. + + Fixes #5605 + Closes #5682 + +- configure: show zstd "no" in summary when built without it + + Reported-by: Marc Hörsken + Fixes #5720 + Closes #5730 + +- quiche: handle calling disconnect twice + + Reported-by: lilongyan-huawei on github + Fixes #5726 + Closes #5727 + +- [Nicolas Sterchele brought this change] + + getinfo: reset retry-after value in initinfo + + - Avoid re-using retry_after value from preceding request + - Add libtest 3010 to verify + + Reported-by: joey-l-us on github + Fixes #5661 + Closes #5672 + +Marcel Raad (27 Jul 2020) +- WIN32: stop forcing narrow-character API + + Except where the results are only used for character output. + getenv is not touched because it's part of the public API, and having + it return UTF-8 instead of ANSI would be a breaking change. + + Fixes https://github.com/curl/curl/issues/5658 + Fixes https://github.com/curl/curl/issues/5712 + Closes https://github.com/curl/curl/pull/5718 + +Jay Satiro (27 Jul 2020) +- [Tobias Stoeckmann brought this change] + + mprintf: Fix stack overflows + + Stack overflows can occur with precisions for integers and floats. + + Proof of concepts: + - curl_mprintf("%d, %.*1$d", 500, 1); + - curl_mprintf("%d, %+0500.*1$f", 500, 1); + + Ideally, compile with -fsanitize=address which makes this undefined + behavior a bit more defined for debug purposes. - Fixed the alt-svc parser to treat a newline as end of line. + The format strings are valid. The overflows occur due to invalid + arguments. If these arguments are variables with contents controlled + by an attacker, the function's stack can be corrupted. - The unit tests in test 1654 were done without CRLF and thus didn't quite - match the real world. Now they use CRLF as well. + Also see CVE-2016-9586 which partially fixed the float aspect. - Reported-by: Peter Wu - Assisted-by: Peter Wu - Assisted-by: Jay Satiro - Fixes #5445 - Closes #5446 - -Viktor Szakats (25 May 2020) -- all: fix codespell errors + Signed-off-by: Tobias Stoeckmann - Reviewed-by: Jay Satiro - Reviewed-by: Daniel Stenberg - Closes https://github.com/curl/curl/pull/5452 + Closes https://github.com/curl/curl/pull/5722 -Peter Wu (25 May 2020) -- ngtcp2: fix build with current ngtcp2 master implementing draft 28 +- [Tobias Stoeckmann brought this change] + + mprintf: Fix dollar string handling - Based on client.cc changes from ngtcp2. Tested with current git master, - ngtcp2 commit c77d5731ce92, nghttp3 commit 65ff479d4380. + Verify that specified parameters are in range. If parameters are too + large, fail early on and avoid out of boundary accesses. - Fixes #5444 - Closes #5443 - -Daniel Stenberg (25 May 2020) -- RELEASE-NOTES: synced + Also do not read behind boundaries of illegal format strings. - moved the new setopts up to a "change" - -- RELEASE-NOTES: synced - -- copyright: updated year ranges out of sync + These are defensive measures since it is expected that format strings + are well-formed. Format strings should not be modifiable by user + input due to possible generic format string attacks. - ... and whitelisted a few more files in the the copyright.pl script. - -- [Gilles Vollant brought this change] + Closes https://github.com/curl/curl/pull/5722 - setopt: add CURLOPT_PROXY_ISSUERCERT(_BLOB) for coherency +Daniel Stenberg (26 Jul 2020) +- ntlm: free target_info before (re-)malloc - Closes #5431 - -- curl: remove -J "informational" written on stdout + OSS-Fuzz found a way this could get called again with the pointer still + pointing to a malloc'ed memory, leading to a leak. - curl would previously show "curl: Saved to filename 'name from header'" - if -J was used and a name was picked from the Content-Disposition - header. That output could interfer with other stdout output, such as -w. + Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24379 - This commit removes that output line. - Bug: https://curl.haxx.se/mail/archive-2020-05/0044.html - Reported-by: Коваленко Анатолий Викторович - Closes #5435 + Closes #5724 -Peter Wu (22 May 2020) -- travis: simplify quiche build instructions wrt boringssl +Marcel Raad (26 Jul 2020) +- CI/macos: set minimum macOS version - quiche builds boringssl as static library, reuse that instead of - building another shared library. + This enables some deprecation warnings. + Previously, autotools defaulted to 10.8. - Closes #5438 + Closes https://github.com/curl/curl/pull/5723 -- configure: fix pthread check with static boringssl +Daniel Stenberg (26 Jul 2020) +- RELEASE-NOTES: synced + +Marcel Raad (25 Jul 2020) +- CI/macos: enable warnings as errors for CMake builds - A shared boringssl/OpenSSL library requires -lcrypto only for linking. - A static build additionally requires `-ldl -lpthread`. In the latter - case `-lpthread` is added to LIBS which prevented `-pthread` from being - added to CFLAGS. Clear LIBS to fix linking failures for libtest tests. + Closes https://github.com/curl/curl/pull/5716 -Daniel Stenberg (22 May 2020) -- Revert "sendf: make failf() use the mvsnprintf() return code" +- CMake: fix test for warning suppressions - This reverts commit 74623551f306990e70c7c5515b88972005604a74. + GCC doesn't warn for unknown `-Wno-` options, except if there are other + warnings or errors [0]. This was problematic with `CURL_WERROR` as that + warning-as-error cannot be suppressed. Notably, this always happened + with `-Wno-pedantic-ms-format` when not targeting Windows. So test for + the positive form of the warning instead, which should always result in + a diagnostic if unknown. - Instead mark the function call with (void). Getting the return code and - using it instead triggered Coverity warning CID 1463596 because - snprintf() can return a negative value... + [0] https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html - Closes #5441 + Closes https://github.com/curl/curl/pull/5714 -- typecheck-gcc.h: CURLINFO_PRIVATE does not need a 'char *' +Jay Satiro (23 Jul 2020) +- curl.h: update CURLINFO_LASTONE - Reported-by: Billyzou0741326 on github - Fixes #5432 - Closes #5436 - -- tests/server/util.h: add extern to silence compiler warning + CURLINFO_LASTONE should have been updated when + CURLINFO_EFFECTIVE_METHOD was added. - Follow-up from a3b0699d5c1 + Reported-by: xwxbug@users.noreply.github.com + + Fixes https://github.com/curl/curl/issues/5711 -- typecheck-gcc.h: fix the OFF_T check +Marc Hoersken (22 Jul 2020) +- CI/azure: unconditionally enable warnings-as-errors with autotools - The option number also needs to be less than CURLOPTTYPE_BLOB. + Reviewed-by: Marcel Raad - Follow-up to cac5374298 - Reported-by: Jeroen Ooms - Bug: https://github.com/curl/curl/pull/5365#issuecomment-631084114 + Follow up to #5694 + Closes #5706 -- TODO: --dry-run +Marcel Raad (21 Jul 2020) +- doh: remove redundant cast - Closes #5426 + Closes https://github.com/curl/curl/pull/5704 -- TODO: Ratelimit or wait between serial requests +- CI/macos: unconditionally enable warnings-as-errors with autotools - Closes #5406 - -- tool_paramhlp: fixup C89 mistake + Previously, warnings were only visible in the output for most jobs. - Follow-up to c5f0a9db22. - -- [Siva Sivaraman brought this change] + Closes https://github.com/curl/curl/pull/5694 - tool_paramhlp: fixed potentially uninitialized strtol() variable +- util: silence conversion warnings - Seems highly unlikely to actually be possible, but better safe than - sorry. + timeval::tv_usec might be a 32-bit integer and timespec::tv_nsec might + be a 64-bit integer. This is the case when building for recent macOS + versions, for example. Just treat tv_usec as an int, which should + hopefully always be sufficient on systems with + `HAVE_CLOCK_GETTIME_MONOTONIC`. - Closes #5417 - -- [Siva Sivaraman brought this change] + Closes https://github.com/curl/curl/pull/5695 - tool_operate: fixed potentially uninitialized variables +- md(4|5): don't use deprecated macOS functions - ... in curl_easy_getinfo() calls. They're harmless but clearing the - variables makes the code safer and comforts the reader. + They are marked as deprecated for -mmacosx-version-min >= 10.15, + which might result in warnings-as-errors. - Closes #5416 + Closes https://github.com/curl/curl/pull/5695 -- sha256: move assign to the declaration line +Daniel Stenberg (18 Jul 2020) +- strdup: remove the odd strlen check - Follow-up to fae30656. Should've been squashed with that commit... + It confuses code analyzers with its use of -1 for unsigned value. Also, + a check that's not normally used in strdup() code - and not necessary. + + Closes #5697 -- [Siva Sivaraman brought this change] +- [Alessandro Ghedini brought this change] - sha256: fixed potentially uninitialized variable + travis: update quiche builds for new boringssl layout - Closes #5414 - -- sendf: make failf() use the mvsnprintf() return code + This is required after https://github.com/cloudflare/quiche/pull/593 + moved BoringSSL around slightly. - ... and avoid a strlen() call. Fixes a MonocleAI warning. + This also means that Go is not needed to build BoringSSL anymore (the + one provided by quiche anyway). - Reported-by: MonocleAI - Fixes #5413 - Closes #5420 + Closes #5691 -- hostip: make Curl_printable_address not return anything +Marcel Raad (17 Jul 2020) +- configure: allow disabling warnings - It was not used much anyway and instead we let it store a blank buffer - in case of failure. + When using `--enable-warnings`, it was not possible to disable warnings + via CFLAGS that got explicitly enabled. Now warnings are not enabled + anymore if they are explicitly disabled (or enabled) in CFLAGS. This + works for at least GCC, clang, and TCC as they have corresponding + `-Wno-` options for every warning. - Reported-by: MonocleAI - Fixes #5411 - Closes #5418 + Closes https://github.com/curl/curl/pull/5689 -- ftp: mark return-ignoring calls to Curl_GetFTPResponse with (void) +Daniel Stenberg (16 Jul 2020) +- ngtcp2: adjust to recent sockaddr updates - They're done on purpose, make that visible in the code. - Reported-by: MonocleAI - Fixes #5412 - Closes #549 + Closes #5690 -- TODO: forbid TLS post-handshake auth and do TLS record padding +- page-header: provide protocol details in the curl.1 man page - Closes #5396 - Closes #5398 - -- RELEASE-NOTES: synced + Add protocol and version specific information about all protocols curl + supports. + + Fixes #5679 + Reported-by: tbugfinder on github + Closes #5686 -- dynbuf: return NULL when there's no buffer length +Daniel Gustafsson (16 Jul 2020) +- docs: Update a few leftover mentions of DarwinSSL - ... as returning a "" is not a good idea as the string is supposed to be - allocated and returning a const string will cause issues. + Commit 76a9c3c4be10b3d4d379d5b23ca76806bbae536a renamed DarwinSSL to the + more correct/common name Secure Transport, but a few mentions in the docs + remained. - Reported-by: Brian Carpenter - Follow-up to ed35d6590e72c - Closes #5405 + Closes #5688 + Reviewed-by: Daniel Stenberg -Peter Wu (16 May 2020) -- travis: upgrade to bionic, clang-9, improve readability +Daniel Stenberg (16 Jul 2020) +- file2memory: use a define instead of -1 unsigned value - Changes, partially to reduce build failures from external dependencies: - - Upgrade Ubuntu and drop unnecessary third-party repos. - - Properly clone apt config to ensure retries. - - Upgrade to clang-9 from the standard repos. - - Use Ubuntu 20.04 focal for the libssh build, use of ssh_get_publickey - fails on -Werror=deprecated-declarations in Ubuntu 18.04. Do not use - focal everywhere yet since Travis CI has not documented this option. - In focal, python-impacket (Py2.7) has been removed, leaving only - python3-impacket. Since it is only needed for SMB tests and not SSH, - skip it for the libssh job since it might need more work. - - apt: Remove gcc-8 and libstdc++-8-dev, already installed via g++-8. + ... to use the maximum value for 'size_t' when detecting integer overflow. + Changed the limit to max/4 as already that seems unreasonably large. - Non-functional cleanups: - - Simplify test matrix, drop redundant os and compiler keys. - - Deprecation fixes: remove sudo, rename matrix -> jobs. - - Every job has an 'env' key, put this key first in a list item. + Codacy didn't like the previous approach. - Closes #5370 + Closes #5683 -- travis: whitespace-only changes for consistency +- CURL_PUSH_ERROROUT: allow the push callback to fail the parent stream - Automatically apply a consistent indentation with: + ... by adding support for a new dedicated return code. - python3 -c 'from ruamel.yaml import YAML;y=YAML();d=y.load(open(".travis.yml"));y.width=500;y.dump(d,open(".travis.yml.new","w"))' + Suggested-by: Jonathan Cardoso + Assisted-by: Erik Johansson + URL: https://curl.haxx.se/mail/lib-2020-06/0099.html + Closes #5636 + +- [Baruch Siach brought this change] + + nss: fix build with disabled proxy support - followed by manually re-indenting three comments. + Avoid reference to fields that do not exist when CURL_DISABLE_PROXY is + defined. - Closes #5370 + Closes #5667 -- CMake: add libssh build support - - Closes #5372 +- test1139: make it display the difference on test failures -Daniel Stenberg (15 May 2020) -- KNOWN_BUGS: wolfssh: publickey auth doesn't work +- test1119: verify stdout in the test - Closes #4820 - -- KNOWN_BUGS: OS400 port requires deprecated IBM library + So that failures will be displayed in the terminal, as it makes test failures + visually displayed easier and faster. - Closes #5176 - -- [Vyron Tsingaras brought this change] + Closes #5644 - http2: keep trying to send pending frames after req.upload_done +- curl: add %{method} to the -w variables - Fixes #1410 - Closes #5401 + Gets the CURLINFO_EFFECTIVE_METHOD from libcurl. + + Added test 1197 to verify. -- [Gilles Vollant brought this change] +- CURLINFO_EFFECTIVE_METHOD: added + + Provide the HTTP method that was used on the latest request, which might + be relevant for users when there was one or more redirects involved. + + Closes #5511 - setopt: support certificate options in memory with struct curl_blob +Viktor Szakats (14 Jul 2020) +- windows: add unicode to feature list - This change introduces a generic way to provide binary data in setopt - options, called BLOBs. + Reviewed-by: Marcel Raad + Reviewed-by: Marc Hörsken - This change introduces these new setopts: + Closes #5491 + +Daniel Stenberg (14 Jul 2020) +- multi: remove two checks always true - CURLOPT_ISSUERCERT_BLOB, CURLOPT_PROXY_SSLCERT_BLOB, - CURLOPT_PROXY_SSLKEY_BLOB, CURLOPT_SSLCERT_BLOB and CURLOPT_SSLKEY_BLOB. + Detected by Codacy + Closes #5676 + +Marc Hoersken (13 Jul 2020) +- workflows: limit what branches to run CodeQL on + + Align CodeQL action with existing CI actions: + - Update branch filter to avoid duplicate CI runs. + - Shorten workflow name due to informative job name. Reviewed-by: Daniel Stenberg - Closes #5357 + + Closes #5660 -- source cleanup: remove all custom typedef structs +- appveyor: collect libcurl.dll variants with prefix or suffix - - Stick to a single unified way to use structs - - Make checksrc complain on 'typedef struct {' - - Allow them in tests, public headers and examples + On some platforms libcurl is build with a platform-specific + prefix and/or a version number suffix. - - Let MD4_CTX, MD5_CTX, and SHA256_CTX typedefs remain as they actually - typedef different types/structs depending on build conditions. + Assisted-by: Jay Satiro - Closes #5338 + Closes #5659 -- travis: remove the .checksrc fiddling +Daniel Stenberg (12 Jul 2020) +- [ihsinme brought this change] -- ftp: make domore_getsock() return the secondary socket properly + socks: use size_t for size variable - Previously, after PASV and immediately after the data connection has - connected, the function would only return the control socket to wait for - which then made the data connection simply timeout and not get polled - correctly. This become obvious when running test 1631 and 1632 event- - based. + Use the unsigned type (size_t) in the arithmetic of pointers. In this + context, the signed type (ssize_t) is used unnecessarily. + + Authored-by: ihsinme on github + Closes #5654 -- test1632: verify FTP through HTTPS-proxy with connection re-use +- RELEASE-NOTES: synced + + ... and bumped to 7.72.0 as the next release version number -- test1631: verify FTP download through HTTPS-proxy +- [Gilles Vollant brought this change] -- sws: as last resort, get test number from server cmd file + content_encoding: add zstd decoding support - If it can't be found in the request. Also support --cmdfile to set it to - a custom file name. + include zstd curl patch for Makefile.m32 from vszakats + and include Add CMake support for zstd from Peter Wu - runtests.pl always writes this file with the test number in it since a - while back. + Helped-by: Viktor Szakats + Helped-by: Peter Wu + Closes #5453 -- ftp: shut down the secondary connection properly when SSL is used +- asyn.h: remove the Curl_resolver_getsock define - Reported-by: Neal Poole - Fixes #5340 - Closes #5385 + - not used + - used the wrong number of arguments + - confused the Codeacy code analyzer + + Closes #5647 -Marcel Raad (14 May 2020) -- KNOWN_BUGS: adapt 5.5 to recent changes +- [Nicolas Sterchele brought this change] + + configure.ac: Sort features name in summary - It only applies to non-Unicode builds now. - Also merge 5.10 into it as it's effectively a duplicate. + - Same as protocols - Closes https://github.com/curl/curl/pull/3784 + Closes #5656 -- curl_setup: support Unicode functions to open files on Windows +- [Matthias Naegler brought this change] + + cmake: fix windows xp build - Use them only if `_UNICODE` is defined, in which case command-line - arguments have been converted to UTF-8. + Reviewed-by: Marcel Raad + Closes #5662 + +- ngtcp2: update to modified qlog callback prototype - Closes https://github.com/curl/curl/pull/3784 + Closes #5675 -- tool: support UTF-16 command line on Windows +- transfer: fix memory-leak with CURLOPT_CURLU in a duped handle - - use `wmain` instead of `main` when `_UNICODE` is defined [0] - - define `argv_item_t` as `wchar_t *` in this case - - use the curl_multibyte gear to convert the command-line arguments to - UTF-8 + Added test case 674 to reproduce and verify the bug report. - This makes it possible to pass parameters with characters outside of - the current locale on Windows, which is required for some tests, e.g. - the IDN tests. Out of the box, this currently only works with the - Visual Studio project files, which default to Unicode, and winbuild - with the `ENABLE_UNICODE` option. + Fixes #5665 + Reported-by: NobodyXu on github + Closes #5673 + +- [Baruch Siach brought this change] + + bearssl: fix build with disabled proxy support - [0] https://devblogs.microsoft.com/oldnewthing/?p=40643 + Avoid reference to fields that do not exist when CURL_DISABLE_PROXY is + defined. - Ref: https://github.com/curl/curl/issues/3747 - Closes https://github.com/curl/curl/pull/3784 + Reviewed-by: Nicolas Sterchele + Closes #5666 -- curl_multibyte: add to curlx +- RELEASE-NOTES: synced + +Jay Satiro (11 Jul 2020) +- [Carlo Marcelo Arenas Belón brought this change] + + cirrus-ci: upgrade 11-STABLE to 11.4 - This will also be needed in the tool and tests. + Meant to be the last of the 11 series and so make sure that all + other references reflect all 11 versions so they can be retired + together later. - Ref: https://github.com/curl/curl/pull/3758#issuecomment-482197512 - Closes https://github.com/curl/curl/pull/3784 + Closes https://github.com/curl/curl/pull/5668 -Daniel Stenberg (14 May 2020) -- url: make the updated credentials URL-encoded in the URL +- [Filip Salomonsson brought this change] + + CURLINFO_CERTINFO.3: fix typo - Found-by: Gregory Jefferis - Reported-by: Jeroen Ooms - Added test 1168 to verify. Bug spotted when doing a redirect. - Bug: https://github.com/jeroen/curl/issues/224 - Closes #5400 + Closes https://github.com/curl/curl/pull/5655 -- tests: add https-proxy support to the test suite +Daniel Stenberg (4 Jul 2020) +- http2: only do the *done() cleanups for HTTP - Initial test 1630 added with basic HTTPS-proxy use. HTTPS-proxy is like - HTTP proxy but with a full TLS connection to the proxy. + Follow-up to ef86daf4d3 - Closes #5399 - -- mailmap: James Fuller + Closes #5650 + Fixes #5646 -- [Major_Tom brought this change] +- [Alex Kiernan brought this change] - vauth/cleartext: fix theoretical integer overflow + gnutls: repair the build with `CURL_DISABLE_PROXY` - Fix theoretical integer overflow in Curl_auth_create_plain_message. + `http_proxy`/`proxy_ssl`/`tunnel_proxy` will not be available in `conn` + if `CURL_DISABLE_PROXY` is enabled. Repair the build with that + configuration. - The security impact of the overflow was discussed on hackerone. We - agreed this is more of a theoretical vulnerability, as the integer - overflow would only be triggerable on systems using 32-bits size_t with - over 4GB of available memory space for the process. + Signed-off-by: Alex Kiernan + Closes #5645 + +Alex Kiernan (3 Jul 2020) +- gnutls: Fetch backend when using proxy - Closes #5391 + Fixes: 89865c149 ("gnutls: remove the BACKEND define kludge") + Signed-off-by: Alex Kiernan -Jay Satiro (13 May 2020) -- curl.1: Quote globbed URLs +Daniel Stenberg (3 Jul 2020) +- [Laramie Leavitt brought this change] + + http2: close the http2 connection when no more requests may be sent - - Quote the globbing example URLs that contain characters [] {} since - otherwise they may be interpreted as shell metacharacters. + Well-behaving HTTP2 servers send two GOAWAY messages. The first + message is a warning that indicates that the server is going to + stop accepting streams. The second one actually closes the stream. + + nghttp2 reports this state (and the other state of no more stream + identifiers) via the call nghttp2_session_check_request_allowed(). + In this state the client should not create more streams on the + session (tcp connection), and in curl this means that the server + has requested that the connection is closed. + + It would be also be possible to put the connclose() call into the + on_http2_frame_recv() function that triggers on the GOAWAY message. + + This fixes a bug seen when the client sees the following sequence of + frames: + + // advisory GOAWAY + HTTP2 GOAWAY [stream-id = 0, promised-stream-id = -1] + ... some additional frames - Bug: https://github.com/curl/curl/issues/5388 - Reported-by: John Simpson + // final GOAWAY + HTTP2 GOAWAY [stream-id = 0, promised-stream-id = N ] - Closes https://github.com/curl/curl/pull/5394 - -Daniel Stenberg (14 May 2020) -- checksrc: enhance the ASTERISKSPACE and update code accordingly + Before this change, curl will attempt to reuse the connection even + after the last stream, will encounter this error: - Fine: "struct hello *world" + * Found bundle for host localhost: 0x5595f0a694e0 [can multiplex] + * Re-using existing connection! (#0) with host localhost + * Connected to localhost (::1) port 10443 (#0) + * Using Stream ID: 9 (easy handle 0x5595f0a72e30) + > GET /index.html?5 HTTP/2 + > Host: localhost:10443 + > user-agent: curl/7.68.0 + > accept: */* + > + * stopped the pause stream! + * Connection #0 to host localhost left intact + curl: (16) Error in the HTTP2 framing layer - Not fine: "struct hello* world" (and variations) + This error may posion the connection cache, causing future requests + which resolve to the same curl connection to go through the same error + path. - Closes #5386 + Closes #5643 -- docs/options-in-versions: which version added each cmdline option +- ftpserver: don't verify SMTP MAIL FROM names - Added test 971 to verify that the list is in sync with the files in - cmdline-opts. The check also verifies that .d-files that uses Added: - specify the same version number as the options-in-versions file does. + Rely on tests asking the names to get refused instead - test servers + should be as dumb as possible. Edited test 914, 955 and 959 accordingly. - Closes #5381 + Closes #5639 -- docs: unify protocol lists +- curl_version_info.3: CURL_VERSION_KERBEROS4 is deprecated - We boast support for 25 transfer protocols. Make sure the lists are - consistent + This came up in #5640. It make sense to clarify this in the docs! - Closes #5384 + Reminded-by: Kamil Dudka + Closes #5642 -- OpenSSL: have CURLOPT_CRLFILE imply CURLSSLOPT_NO_PARTIALCHAIN +Kamil Dudka (3 Jul 2020) +- tool_getparam: make --krb option work again - ... to avoid an OpenSSL bug that otherwise makes the CRL check to fail. + It was disabled by mistake in commit curl-7_37_1-23-ge38ba4301. - Reported-by: Michael Kaufmann - Fixes #5374 - Closes #5376 - -- tls13-ciphers.d: shorten the Arg - -- sasl-authzid.d: add Arg: and shorten the desc + Bug: https://bugzilla.redhat.com/1833193 + Closes #5640 -- cert-type.d: mention the available types in the desc +Daniel Stenberg (2 Jul 2020) +- [Jeremy Maitin-Shepard brought this change] -- tool: shorten 3 --help descriptions + http2: fix nghttp2_strerror -> nghttp2_http2_strerror in debug messages - --happy-eyeballs-timeout-ms, --resolve and --ssl-revoke-best-effort + Confusingly, nghttp2 has two different error code enums: - gen.pl already warned about these lines but we didn't listen + - nghttp2_error, to be used with nghttp2_strerror + - nghttp2_error_code, to be used with nghttp2_http2_strerror - Closes #5379 + Closes #5641 -- configure: the wolfssh backend does not provide SCP +Marcel Raad (2 Jul 2020) +- url: silence MSVC warning - Closes #5387 - -- RELEASE-NOTES: synced - -- url: reject too long input when parsing credentials + Since commit f3d501dc678, if proxy support is disabled, MSVC warns: + url.c : warning C4701: potentially uninitialized local variable + 'hostaddr' used + url.c : error C4703: potentially uninitialized local pointer variable + 'hostaddr' used - Since input passed to libcurl with CURLOPT_USERPWD and - CURLOPT_PROXYUSERPWD circumvents the regular string length check we have - in Curl_setstropt(), the input length limit is enforced in - Curl_parse_login_details too, separately. + That could actually only happen if both `conn->bits.proxy` and + `CURL_DISABLE_PROXY` were enabled. + Initialize it to NULL to silence the warning. - Reported-by: Thomas Bouzerar - Closes #5383 - -- list-only.d: this option existed already in 4.0 + Closes https://github.com/curl/curl/pull/5638 -Jay Satiro (12 May 2020) -- retry-all-errors.d: Shorten the summary line - - Follow-up to b995bb5 from a few moments ago. - - Reported-by: Daniel Stenberg - - Ref: https://github.com/curl/curl/commit/b995bb5#r39108929 +Daniel Stenberg (1 Jul 2020) +- RELEASE-NOTES: synced -- [denzor brought this change] +Version 7.71.1 (30 Jun 2020) - easy: fix dangling pointer on easy_perform fail - - Closes https://github.com/curl/curl/pull/5363 +Daniel Stenberg (30 Jun 2020) +- RELEASE-NOTES: curl 7.71.1 -- tool: Add option --retry-all-errors to retry on any error - - The "sledgehammer" of retrying. - - Closes https://github.com/curl/curl/pull/5185 +- THANKS: add contributors to 7.71.1 -Daniel Stenberg (12 May 2020) -- [James Le Cuirot brought this change] +- scripts/copyright.pl: skip .dcignore - libcurl.pc: Merge Libs.private into Libs for static-only builds - - A project being built entirely statically will call pkg-config with - --static, which utilises the Libs.private field. Conversely it will - not use --static when not being built entirely statically, even if - there is only a static build of libcurl available. This will most - likely cause the build to fail due to underlinking unless we merge the - Libs fields. +- Revert "multi: implement wait using winsock events" - Consider that this is what the Meson build system does when it - generates pkg-config files. + This reverts commit 8bc25c590e530de87595d1bb3577f699eb1309b9. - I have also reflected this in the --libs argument of curl-config even - though REQUIRE_LIB_DEPS always seems to be "yes" anyway. + That commit (from #5397) introduced a regression in 7.71.0. - Closes #5373 - -- [Peter Wu brought this change] + Reported-by: tmkk on github + Fixes #5631 + Closes #5632 - CMake: fix runtests.pl with CMake, add new test targets - - * runtests.pl: - - Fix out-of-tree build under CMake when srcdir is not set. Default - srcdir to the location of runtests.pl. - - Add a hack to allow CMake to use the TFLAGS option as documented - in tests/README and used in scripts/travis/script.sh. - * Bump CMake version to 3.2 for USES_TERMINAL, dropping Debian Jessie - support (no one should care, it is already EOL.). - * Remove CTest since it defines its own 'test' target with no tests - since all unittests are already broken and not built by default. - * Add new test targets based on the options from Makefile.am. Since - new test targets are rarely added, I opted for duplicating the - runtests.pl options as opposed to creating a new Makefile.inc file. - Use top-level target names (test-x) instead of x-test since that is - used by CI and others. - - Closes #5358 +- TODO: Add flag to specify download directory -- [Peter Wu brought this change] +- TODO: return code to CURLMOPT_PUSHFUNCTION to fail connection - CMake: do not build test programs by default +- cirrus-ci: disable FreeBSD 13 (again) - The default target should only build libcurl and curl. Add a dedicated - 'testdeps' target which will be used later when running tests. Note that - unittests are currently broken in CMake and already excluded. + It has been failing for a good while again. This time we better leave it + disabled until we have more reason to believe it behaves. - Closes #5368 - -- FILEFORMAT: moved up the variables section and further polished + Closes #5628 -- runtests: remove ftp2 support, not used +- ngtcp2: sync with current master - We once supported two separate ftp instances in the test suite. Has not - been used the last decade. + ngtcp2 added two new callbacks - Closes #5375 + Reported-by: Lucien Zürcher + Fixes #5624 + Closes #5627 -- url: sort the protocol schemes in rough popularity order - - When looking for a protocol match among supported schemes, check the - most "popular" schemes first. It has zero functionality difference and - for all practical purposes a speed difference will not be measureable - but it still think it makes sense to put the least likely matches last. - - "Popularity" based on the 2019 user survey. +- examples/multithread.c: call curl_global_cleanup() - Closes #5377 + Reported-by: qiandu2006 on github + Fixes #5622 + Closes #5623 -Marc Hoersken (11 May 2020) -- test1238: avoid tftpd being busy for tests shortly following - - The tftpd server may still be busy if the total timeout of - 25 seconds has not been reached or no sread error was received - during or after the execution of the timeout test 1238. - - Once the next TFTP test comes around (eg. 1242 or 1243), - those will fail because the tftpd server is still waiting - on data from curl due to the UDP protocol being stateless - and having no connection close. On Linux this error may not - happen, because ICMP errors generated due to a swrite error - can also be returned async on the next sread call instead. - - Therefore we will now just kill the tftpd server after test - 1238 to make sure that the following tests are not affected. - - This enables us to no longer ignore tests 1242, 1243, 2002 - and 2003 on the CI platforms CirrusCI and AppVeyor. +- vtls: compare cert blob when finding a connection to reuse - Assisted-by: Peter Wu - Closes #5364 + Reported-by: Gergely Nagy + Fixes #5617 + Closes #5619 -Daniel Stenberg (11 May 2020) -- write-out.d: added "response_code" +- RELEASE-NOTES: synced -- KNOWN_BUGS: Build with staticly built dependency +- terminology: call them null-terminated strings - I rewrote the item 5.4 to be more generic about static dependencies. - -- ROADMAP: remove old entries + Updated terminology in docs, comments and phrases to refer to C strings + as "null-terminated". Done to unify with how most other C oriented docs + refer of them and what users in general seem to prefer (based on a + single highly unscientific poll on twitter). - MQTT - the start has already landed + Reported-by: coinhubs on github + Fixes #5598 + Closes #5608 + +- http: fix proxy auth with blank password - tiny-curl - also mostly landed and is a continuous work + Regression in 7.71.0 - make menuconfig - basically no interest from users, not pushing there - -- [Peter Wu brought this change] - - travis: Add ngtcp2 and quiche tests for CMake + Added test case 346 to verify. - To avoid an explosion of jobs, extend the existing CMake tests with - ngtcp2 and quiche support. macOS was previously moved to GitHub actions, - so the non-Linux case can be dropped. - -- [Peter Wu brought this change] + Reported-by: Kristoffer Gleditsch + Fixes #5613 + Closes #5616 - CMake: add ENABLE_ALT_SVC option +- .dcignore: ignore tests and docs directories - Tested alt-svc with quiche. While at it, add missing MultiSSL reporting - (not tested). - -- [Peter Wu brought this change] + This is a config file for deepcode.ai, a static code analyzer. - CMake: add HTTP/3 support (ngtcp2+nghttp3, quiche) - - Add three new CMake Find modules (using the curl license, but I grant - others the right to apply the CMake BSD license instead). +Jay Satiro (26 Jun 2020) +- tool_cb_hdr: Fix etag warning output and return code - This CMake config is simpler than the autotools one because it assumes - ngtcp2 and nghttp3 to be used together. Another difference is that this - CMake config checks whether QUIC is actually supported by the TLS - library (patched OpenSSL or boringssl) since this can be a common - configuration mistake that could result in build errors later. + - Return 'failure' on failure, to follow the existing style. - Unlike autotools, CMake does not warn you that the features are - experimental. The user is supposed to already know that and read the - documentation. It requires a very special build environment anyway. + - Put Warning: and the warning message on the same line. - Tested with ngtcp2+OpenSSL+nghttp3 and quiche+boringssl, both built from - current git master. Use `LD_DEBUG=files src/curl |& grep need` to figure - out which features (libldap-2.4, libssh2) to disable due to conflicts - with boringssl. + Ref: https://github.com/curl/curl/issues/5610 - Closes #5359 + Closes https://github.com/curl/curl/pull/5612 -Marc Hoersken (10 May 2020) -- tests/server/tftpd.c: fix include and enhance debug logging +Daniel Stenberg (26 Jun 2020) +- CURLOPT_READFUNCTION.3: provide the upload data size up front - setjmp.h should only be included if HAVE_SETJMP_H is defined. + Assisted-by: Jay Satiro + Closes #5607 + +- test1539: do a HTTP 1.0 POST without a set size (fails) - Add additional log statements to see wether reads and writes - are blocking or finishing before an alarm signal is received. + Attempt to reproduce #5593. Test case 1514 is very similar but uses + HTTP/1.1 and thus switches to chunked. - Assisted-by: Peter Wu - Part of #5364 + Closes #5595 -Daniel Stenberg (10 May 2020) -- tool_operate: only set CURLOPT_SSL_OPTIONS if SSL support is present - - Reported-by: Marcel Raad - Follow-up to 148534db5 - Fixes #5367 - Closes #5369 +- [Baruch Siach brought this change] -Marc Hoersken (9 May 2020) -- appveyor: update comments to be clear about toolchain + mbedtls: fix build with disabled proxy support - - CMake-based MSYS builds use mingw-w64 to cross-compile. - - autotools-based builds are compiled using msys2-devel. + Don't reference fields that do not exist. Fixes build failure: - The difference is that the later ones are not cross-compiled - to Windows and instead require the msys2 runtime to be present. + vtls/mbedtls.c: In function 'mbed_connect_step1': + vtls/mbedtls.c:249:54: error: 'struct connectdata' has no member named 'http_proxy' - At the moment only the Azure Pipelines CI builds actually - run autotools-based cross-compilation builds for Windows. + Closes #5615 -- TODO: update regarding missing Schannel features - - Some aspects have already been implemented over the years. - - 15.1 Client certificates are now supported: - - - System stores via e35b0256eb34f1fe562e3e2a2615beb50a391c52 - - PKCS#12 files via 0fdf96512613574591f501d63fe49495ba40e1d5 - - 15.2 Ciphers can now be specified through: - - - Algorithms via 9aefbff30d280c60fc9d8cc3e0b2f19fc70a2f28 +- codeql-analysis.yml: fix the 'languages' setting - Reviewed-by: Daniel Stenberg and Marcel Raad - Closes #5358 + It needs a 'with:' in front of it. -Daniel Stenberg (8 May 2020) -- checksrc: close the .checksrc file handle when done reading +GitHub (26 Jun 2020) +- [Daniel Stenberg brought this change] -- RELEASE-NOTES: synced + gtihub: codeql-analysis.yml - And bumped next version to 7.71.0 - -- [Gilles Vollant brought this change] + enables code security scanning with github actions - CURLOPT_SSL_OPTIONS: add *_NATIVE_CA to use Windows CA store (with openssl) +Daniel Stenberg (25 Jun 2020) +- tests: verify newline in username and password for HTTP + + test 1296 is a simply command line test - Closes #4346 + test 1910 is a libcurl test including a redirect -- TODO: native IDN support on macOS +- url: allow user + password to contain "control codes" for HTTP(S) + + Reported-by: Jon Johnson Jr + Fixes #5582 + Closes #5592 -- urlapi: accept :: as a valid IPv6 address +- escape: make the URL decode able to reject only %00 bytes - Text 1560 is extended to verify. + ... or all "control codes" or nothing. - Reported-by: Pavel Volgarev - Fixes #5344 - Closes #5351 - -- THANKS-filter: Peter Wang - -- [Peter Wang brought this change] + Assisted-by: Nicolas Sterchele - *_sspi: fix bad uses of CURLE_NOT_BUILT_IN +- http2: set the correct URL in pushed transfers - Return CURLE_AUTH_ERROR instead of CURLE_NOT_BUILT_IN for other - instances of QuerySecurityPackageInfo failing, as in - commit 2a81439553286f12cd04a4bdcdf66d8e026d8201. + ...previously CURLINFO_EFFECTIVE_URL would report the URL of the + original "mother transfer", not the actually pushed resource. - Closes #5355 + Reported-by: Jonathan Cardoso Machado + Fixes #5589 + Closes #5591 -- docs/HTTP3: add qlog to the quiche build instruction +Jay Satiro (25 Jun 2020) +- [Javier Blazquez brought this change] -- ngtcp2: introduce qlog support - - If the QLOGDIR environment variable is set, enable qlogging. + openssl: Fix compilation on Windows when ngtcp2 is enabled - ... and create Curl_qlogdir() in the new generic vquic/vquic.c file for - QUIC functions that are backend independent. + - Include wincrypt before OpenSSL includes so that the latter can + properly handle any conflicts between the two. - Closes #5353 + Closes https://github.com/curl/curl/pull/5606 -- ntlm_sspi: fix bad use of CURLE_NOT_BUILT_IN - - That return code is reserved for build-time conditional code not being - present while this was a regular run-time error from a Windows API. +Daniel Stenberg (25 Jun 2020) +- test543: extended to verify zero length input - Reported-by: wangp on github - Fixes #5349 - Closes #5350 - -- runtests: show elapsed test time with higher precision (ms) - -- RELEASE-NOTES: synced + As was reported in #5601 -- http2: simplify and clean up trailer handling - - Triggered by a crash detected by OSS-Fuzz after the dynbuf introduction in - ed35d6590e72. This should make the trailer handling more straight forward and - hopefully less error-prone. +- escape: zero length input should return a zero length output - Deliver the trailer header to the callback already at receive-time. No - longer caches the trailers to get delivered at end of stream. + Regression added in 7.71.0. - Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22030 - Closes #5348 + Fixes #5601 + Reported-by: Kristoffer Gleditsch + Closes #5602 -Marc Hoersken (7 May 2020) -- appveyor: disable test 1139 instead of ignoring it +- Curl_inet_ntop: always check the return code - Spending time on manpage checking makes no sense - for these builds due to lacking manpage support. + Reported-by: Siva Sivaraman + Fixes #5412 + Closes #5597 -- appveyor: disable flaky test 1501 and ignore broken 1056 +- sendf: improve the message on client write errors - Test 1501 is flaky on Windows CI due to being time sensitive - and the testsuite relying on taskkill.exe to check for the - existance of processes which can take to much time itself. + Replace "Failed writing body (X != Y)" with + "Failure writing output to destination". Possibly slightly less cryptic. - Test 1056 is broken in autotools-based Windows builds due - to scope ID support missing in these builds at the moment. + Reported-by: coinhubs on github + Fixes #5594 + Closes #5596 -- test613.pl: make tests 613 and 614 work with OpenSSH for Windows - - OpenSSH for Windows shows group and other/world permissions as *, - because those concepts do not exist on Windows. It also does not - show the current or parent directory, so we just ignore those. - - Reviewed-by: Daniel Stenberg - Closes #5328 +- RELEASE-NOTES: synced -Daniel Stenberg (6 May 2020) -- runtests: set +x mode again +- curlver: start working on 7.71.1 -- libssh2: convert over to use dynbuf - - In my very basic test that lists sftp://127.0.0.1/tmp/, this patched - code makes 161 allocations compared to 194 in git master. A 17% - reduction. +- [Denis Baručić brought this change] + + DYNBUF.md: fix a typo: trail => tail - Closes #5336 + Closes #5599 + +Version 7.71.0 (23 Jun 2020) -- travis: add "qlog" as feature in the quiche build +Daniel Stenberg (23 Jun 2020) +- RELEASE-NOTES: curl 7.71.0 release -- quiche: enable qlog output - - quiche has the potential to log qlog files. To enable this, you must - build quiche with the qlog feature enabled `cargo build --features - qlog`. curl then passes a file descriptor to quiche, which takes - ownership of the file. The FD transfer only works on UNIX. +- THANKS: curl 7.71.0 additions + +- url: make sure pushed streams get an allocated download buffer - The convention is to enable logging when the QLOGDIR environment is - set. This should be a path to a folder where files are written with the - naming template .qlog. + Follow-up to c4e6968127e876b0 - Co-authored-by: Lucas Pardue - Replaces #5337 - Closes #5341 - -- urldata.h: remove #define HEADERSIZE, not used anymore + When a new transfer is created, as a resuly of an acknowledged push, + that transfer needs a download buffer allocated. - Follow-up to ed35d6590e72c + Closes #5590 -- ngtcp2: convert to dynbuf +Jay Satiro (22 Jun 2020) +- openssl: Don't ignore CA paths when using Windows CA store - Closes #5335 - -- connect: make happy eyeballs work for QUIC (again) + This commit changes the behavior of CURLSSLOPT_NATIVE_CA so that it does + not override CURLOPT_CAINFO / CURLOPT_CAPATH, or the hardcoded default + locations. Instead the CA store can now be used at the same time. - Follow-up from dbd16c3e256c6c (regression in 7.70.0) + The change is due to the impending release. The issue is still being + discussed. The behavior of CURLSSLOPT_NATIVE_CA is subject to change and + is now documented as experimental. - Closes #5334 - -- connect: add two asserts to clue code analyzers in a little + Ref: bc052cc (parent commit) + Ref: https://github.com/curl/curl/issues/5585 -- http_proxy: ported to use dynbuf instead of a static size buffer +- tool_operate: Don't use Windows CA store as a fallback - Removes a 16K static buffer from the easy handle. Simplifies the code. - -- dynbuf: introduce internal generic dynamic buffer functions + Background: - A common set of functions instead of many separate implementations for - creating buffers that can grow when appending data to them. Existing - functionality has been ported over. + 148534d added CURLSSLOPT_NATIVE_CA to use the Windows OS certificate + store in libcurl w/ OpenSSL on Windows. CURLSSLOPT_NATIVE_CA overrides + CURLOPT_CAINFO if both are set. The curl tool will fall back to + CURLSSLOPT_NATIVE_CA if it could not find a certificate bundle to set + via CURLOPT_CAINFO. - In my early basic testing, the total number of allocations seem at - roughly the same amount as before, possibly a few less. + Problem: - See docs/DYNBUF.md for a description of the API. + libcurl may be built with hardcoded paths to a certificate bundle or + directory, and if CURLSSLOPT_NATIVE_CA is used then those paths are + ignored. - Closes #5300 - -- runtests: remove sleep calls + Solution: - Remove many one second sleeps that were done *after* each newly started - test server already has been verified. They should not have any purpose - there. + A solution is still being discussed but since there's an impending + release this commit removes using CURLSSLOPT_NATIVE_CA in the curl tool. - Closes #5323 + Ref: https://github.com/curl/curl/issues/5585 -- asyn-*: remove support for never-used NULL entry pointers +- openssl: Fix CA fallback logic for OpenSSL 3.0 build - ... and instead convert those to asserts to make sure they are truly - never NULL. + Prior to this change I assume a build error would occur when + CURL_CA_FALLBACK was used. - Closes #5324 + Closes https://github.com/curl/curl/pull/5587 -- [Emil Engler brought this change] +Daniel Stenberg (22 Jun 2020) +- copyright: update mismatched copyright years - doc: Rename VERSIONS to VERSIONS.md as it already has Markdown syntax - - Closes #5325 +- test1460: verify that -Ji is not ok -Jay Satiro (2 May 2020) -- asyn-thread: fix cppcheck warning - - - Check for NULL entry parameter before attempting to deref entry in - Curl_resolver_is_resolved, like is already done in asyn-ares. - - This is to silence cppcheck which does not seem to understand that - asyn-ares and asyn-thread have separate Curl_resolver_is_resolved - and those units are mutually exclusive. Prior to this change it warned - of a scenario where asyn-thread's Curl_resolver_is_resolved is called - with a NULL entry from asyn-ares, but that couldn't happen. - - Reported-by: rl1987@users.noreply.github.com +- tool_getparam: -i is not OK if -J is used - Fixes https://github.com/curl/curl/issues/5326 + Reported-by: sn on hackerone + Bug: https://curl.haxx.se/docs/CVE-2020-8177.html -- select: fix overflow protection in Curl_socket_check - - Follow-up to a96c752 which changed the timeout_ms type from time_t to - timediff_t. - - Ref: https://github.com/curl/curl/pull/5240 - - Closes https://github.com/curl/curl/pull/5286 +- [Peter Wu brought this change] -Marc Hoersken (2 May 2020) -- sockfilt: make select_ws stop waiting on exit signal event - - This makes sure that select_ws behaves similar to real select - which stops waiting on a signal handler being triggered. - - This makes it possible to gracefully stop sockfilt.exe on - Windows with taskkill /IM sockfilt.exe (without /F force flag). + CMake: ignore INTERFACE_LIBRARY targets for pkg-config file - Reviewed-by: Jay Satiro - Part of #5260 + Reviewed-by: Marcel Raad + Fixes #5512 + Closes #5517 -- tests/server/util.[ch]: add exit event to stop waiting on Windows - - This commit adds a global exit event to the test servers that - Windows-specific wait routines can use to get triggered if the - program was signaled to be terminated, eg. select_ws in sockfilt.c - - The exit event will be managed by the signal handling code and is - set to not reset automatically to support multiple wait routines. - - Reviewed-by: Jay Satiro - Closes #5260 +- [Valentyn Korniienko brought this change] -- tests/server/util.c: fix thread handle not being closed + multibyte: Fixed access-> waccess to file for Windows Plarform - Reviewed-by: Jay Satiro - Part of #5260 + Reviewed-by: Marcel Raad + Closes #5580 -- tests/server/util.c: use raise instead of calling signal handler - - Use raise to trigger signal handler instead of calling it - directly and causing potential unexpected control flow. +- altsvc: bump to h3-29 - Reviewed-by: Jay Satiro - Part of #5260 + Closes #5584 -- tests: add support for SSH server variant specific transfer paths +- urlglob: treat literal IPv6 addresses with zone IDs as a host name - OpenSSH for Windows requires paths in the format of /C:/ - instead of the pseudo-POSIX paths /cygdrive/c/ or just /c/ + ... and not as a "glob". Now done by passing the supposed host to the + URL parser which supposedly will do a better job at identifying "real" + numerical IPv6 addresses. - Reviewed-by: Daniel Stenberg - Closes #5298 + Reported-by: puckipedia on github + Fixes #5576 + Closes #5579 -Daniel Stenberg (2 May 2020) -- RELEASE-NOTES: synced +- test1179: verify error message for non-existing cmdline option -- libssh2: set the expected total size in SCP upload init +- tool_getparam: repair the error message for unknown flag - ... as otherwise the progress callback gets called without that - information, making the progress meter have less info. + Follow-up to 9e5669f3880674 + Detected by Coverity CID 1464582 ("Logically dead code") - Reported-by: Murugan Balraj - Bug: https://curl.haxx.se/mail/archive-2020-05/0000.html - Closes #5317 + Closes #5577 -- runtests: make the logmsg from the ssh server only show in verbose +- FILEFORMAT: describe verify/stderr -- tests: make test 1248 + 1249 use %NOLISTENPORT +- connect: improve happy eyeballs handling - ... instead of a port of a non-running server so that it works - stand-alone. + For QUIC but also for regular TCP when the second family runs out of IPs + with a failure while the first family is still trying to connect. - Closes #5318 + Separated the timeout handling for IPv4 and IPv6 connections when they + both have a number of addresses to iterate over. -- examples: remove asiohiper.cpp - - This example has repeatedly been reported to contain bugs, and as users - copy and paste code from this into production, I now deem it better to - not provide the example at all. - - Closes #5090 - Closes #5322 +- ngtcp2: never call fprintf() in lib code in release version -- [Emil Engler brought this change] +- ngtcp2: fix happy eyeballs quic connect crash + + Reported-by: Peter Wu + Fixes #5565 + Closes #5568 - doc: add missing closing parenthesis in CURLINFO_SSL_VERIFYRESULT.3 +- select: remove the unused ELAPSED_MS() macro - Closes #5320 + Closes #5573 -- [Emil Engler brought this change] +Marc Hoersken (17 Jun 2020) +- [rcombs brought this change] - KNOWN_BUGS: Remove "curl --upload-file . hang if delay in STDIN" + multi: implement wait using winsock events + + This avoids using a pair of TCP ports to provide wakeup functionality + for every multi instance on Windows, where socketpair() is emulated + using a TCP socket on loopback which could in turn lead to socket + resource exhaustion. - It was fixed in 9a2cbf3 + Reviewed-by: Gergely Nagy + Reviewed-by: Marc Hörsken - Closes #5319 + Closes #5397 -- cirrus: disable SFTP and SCP tests +Daniel Stenberg (17 Jun 2020) +- manpage: add three missing environment variables - ... as we can't seem to start the sshd server on it. Those problems - existed before d1239b50bececd (running the SSH server on a random port), - but they're more noticable now since there are more failed attempts in - the logs. + CURL_SSL_BACKEND, QLOGDIR and SSLKEYLOGFILE - Closes #5315 + Closes #5571 -- [Emil Engler brought this change] +- RELEASE-NOTES: synced - runtests: fix typo in the existence of disabled tests checker +- configure: for wolfSSL, check for the DES func needed for NTLM - Closes #5316 + Also adds pkg-config support for the wolfSSL detection. -Dan Fandrich (30 Apr 2020) -- test75: Remove precheck test - - This has not been needed since commit 9fa42bed and often prevents it - from running at all with dynamic test ports. +- [Ruurd Beerstra brought this change] -- tests: Stop referring to server ports when they're not used + ntlm: enable NTLM support with wolfSSL - Several tests referred to specific server ports even when the test - didn't actually use that server or specify that it's needed. In such - cases, the test harness substitutes the text "[not running]" as the port - number which causes many such tests to fail due to the inability to - parse the URL. These tests are changed to use %NOLISTENPORT which will - always be substituted correctly. - -Daniel Stenberg (30 Apr 2020) -- [Emil Engler brought this change] - - GnuTLS: Backend support for CURLINFO_SSL_VERIFYRESULT + When wolfSSL is built with its OpenSSL API layer, it fetures the same DES* + functions that OpenSSL has. This change take advantage of that. - Closes #5287 + Co-authored-by: Daniel Stenberg + Closes #5556 + Fixes #5548 -- conncache: various concept cleanups - - More connection cache accesses are protected by locks. - - CONNCACHE_* is a beter prefix for the connection cache lock macros. - - Curl_attach_connnection: now called as soon as there's a connection - struct available and before the connection is added to the connection - cache. +- http: move header storage to Curl_easy from connectdata - Curl_disconnect: now assumes that the connection is already removed from - the connection cache. + Since the connection can be used by many independent requests (using + HTTP/2 or HTTP/3), things like user-agent and other transfer-specific + data MUST NOT be kept connection oriented as it could lead to requests + getting the wrong string for their requests. This struct data was + lingering like this due to old HTTP1 legacy thinking where it didn't + mattered.. - Ref: #4915 - Closes #5009 + Fixes #5566 + Closes #5567 -- tests: tests: run stunnel for HTTPS and FTPS on dynamic ports +- CODE_REVIEW.md: how to do code reviews in curl - As stunnel is an external tool and it has no specific option to export - the actually used port number when asked to listen to 0, runtests - instead iterates over ten randomly picked high number ports and sticks - to the first one stunnel can listen to. + Assisted-by: Daniel Gustafsson + Assisted-by: Rich Salz + Assisted-by: Hugo van Kemenade + Assisted-by: James Fuller + Assisted-by: Marc Hörsken + Assisted-by: Jay Satiro - Closes #5267 + Closes #5555 -- tests: pick a random port number for SSH +- altsvc: remove the num field from the altsvc struct - Since sshd doesn't have such an option by itself, we iterate over a - series of random ports until one works. + It was superfluous since we have the list.size alredy - Closes #5273 - -- [Rikard Falkeborn brought this change] + Reported-by: Jay Satiro + Fixes #5553 + Closes #5563 - libtest/cmake: Remove commented code +- version.d: expanded and alpha-sorted - These were commented out in e9dd0998706a when Makefile.inc was included - instead. 11 years have passed since then and the commented code is of - course very outdated. Remove it to avoid confusion. + Added a few missing features not previously mentioned. Ordered them + alphabetically. - Closes #5311 + Closes #5558 -- schannel: source code reindent - - White space edits only. Conform better to standard curl source code - indenting style. +- ABI.md: rename to .md and polish the markdown - Closes #5305 + Closes #5562 -Kamil Dudka (29 Apr 2020) -- test1177: look for curl.h in source directory - - If we use a separate build directory, there is no copy of the header. +- HELP-US: add a section for "smaller tasks" - Closes #5310 - -- tests: look for preprocessed tests in build directory + The point of this section is to meet the CII Best Practices gold level + critera: - ... which is not always the same directory as source directory + "The project MUST clearly identify small tasks that can be performed by + new or casual contributors" - Closes #5310 + Closes #5560 -Daniel Stenberg (29 Apr 2020) -- RELEASE-NOTES: synced +- TODO: retry on the redirected-to URL - ... and bumped curlver.h to 7.70.1 - -Version 7.70.0 (29 Apr 2020) + Closes #5462 -Daniel Stenberg (29 Apr 2020) -- RELEASE-NOTES: 7.70.0 +- mailmap: Nicolas Sterchele -- THANKS: synced with the 7.70.0 release +- [Nicolas Sterchele brought this change] -- headers: copyright range fix + TODO: remove 19.3 section title + + Follow-up to ad6416986755e417c66e2c6, which caused wrong formatting on + curl documentation website + + Closes #5561 -- [Rikard Falkeborn brought this change] +- [Martin V brought this change] - doh: Constify some input pointers + test1560: avoid possibly negative association in wording - Closes #5306 + Closes #5549 -- nss: check for PK11_CreateDigestContext() returning NULL +- share: don't set the share flag it something fails - ... to avoid crashes! + When asking for a specific feature to be shared in the share object, + that bit was previously set unconditionally even if the shared feature + failed or otherwise wouldn't work. - Reported-by: Hao Wu - Fixes #5302 - Closes #5303 + Closes #5554 -- travis: bump the wolfssl CI build to use 4.4.0 +- buildconf: remove -print from the find command that removes files - Closes #5301 + It's just too annoying and unnecessary to get a long list of files shown -- copyright updates: adjust year ranges +- RELEASE-NOTES: synced -Marc Hoersken (26 Apr 2020) -- CI: do not include */ci branches in PR builds +- wording: avoid blacklist/whitelist stereotypes - Align Azure Pipelines with GitHub Actions. - -Daniel Stenberg (25 Apr 2020) -- runtests: check for the disabled tests relative srcdir + Instead of discussing if there's value or meaning (implied or not) in + the colors, let's use words without the same possibly negative + associations. - To make it work correctly for out-of-tree builds. + Closes #5546 + +Jay Satiro (9 Jun 2020) +- tool_getparam: fix memory leak in parse_args - Follow-up to 75e8feb6fb08b + Prior to this change in Windows Unicode builds most parsed options would + not be freed. - Bug: https://github.com/curl/curl/pull/5288#issuecomment-619346389 - Reported-by: Marcel Raad - Closes #5297 - -- runtests: revert commenting out a line I did for debugging + Found using _CrtDumpMemoryLeaks(). - Follow-up to 11091cd4d. It was not meant to be pushed! + Ref: https://github.com/curl/curl/issues/5545 -- smtp: set auth correctly +Daniel Stenberg (8 Jun 2020) +- socks: detect connection close during handshake - Regression since 7.69.0 and 68fb25fa3fcff. + The SOCKS4/5 state machines weren't properly terminated when the proxy + connection got closed, leading to a busy-loop. - The code wrongly assigned 'from' instead of 'auth' which probably was a - copy and paste mistake from other code, leading to that auth could - remain NULL and later cause an error to be returned. + Reported-By: zloi-user on github + Fixes #5532 + Closes #5542 + +- [James Fuller brought this change] + + multi: add defensive check on data->multi->num_alive - Assisted-by: Eric Sauvageau - Fixes #5294 - Closes #5295 + Closes #5540 -Marcel Raad (25 Apr 2020) -- lib: clean up whitespace +- Curl_addrinfo: use one malloc instead of three + + To reduce the amount of allocations needed for creating a Curl_addrinfo + struct, make a single larger malloc instead of three separate smaller + ones. - This fixes CodeFactor warnings. + Closes #5533 -Daniel Stenberg (25 Apr 2020) -- [Anderson Toshiyuki Sasaki brought this change] +- [Alessandro Ghedini brought this change] - libssh: avoid options override by configuration files - - Previously, options set explicitly through command line options could be - overridden by the configuration files parsed automatically when - ssh_connect() was called. + quiche: update SSLKEYLOGFILE support - By calling ssh_options_parse_config() explicitly, the configuration - files are parsed before setting the options, avoiding the options - override. Once the configuration files are parsed, the automatic - configuration parsing is not executed. + quiche now requires the application to explicitly set the keylog path + for each connection, rather than reading the environment variable + itself. - Fixes #4972 - Closes #5283 - Signed-off-by: Anderson Toshiyuki Sasaki + Closes #5541 -- runtests: when mentions http, kill http/2 too +- tests: add two simple tests for --login-options + + Test 895 and 896 - as a follow-up to a3e972313b - Since the http2 test server is a mere proxy that needs to know about the - dynamic port the HTTP server is using, it too needs to get restarted - when the http server is killed. + Closes #5539 + +- ngtcp2: update with recent API changes - A regression caused by 80d6515. + Syncs with ngtcp2 commit 7e9a917d386d98 merged June 7 2020. - Fixes #5289 - Closes #5291 + Assisted-by: Tatsuhiro Tsujikawa + Closes #5538 -- [Yuri Slobodyanyuk brought this change] +- [James Fuller brought this change] - docs: fix two typos + socks: remove unreachable breaks in socks.c and mime.c - Closes #5292 - -- [Emil Engler brought this change] + Closes #5537 - tests/git: ignore mqttd and port files +- tool_cfgable: free login_options at exit - Closes #5290 + Memory leak + Reported-by: Geeknik Labs + Fixes #5535 + Closes #5536 -- tests: make runtests check that disabled tests exists +- libssh2: keep sftp errors as 'unsigned long' - ... and error out if so. Removed '536' from DISABLED as there is no such - test file. + Remove weird work-around for storing the SFTP errors as int instead of + the "unsigned long" that libssh2 actually returns for SFTP errors. - Closes #5288 - -- test1154: set a proper name + Closes #5534 -- select: make Curl_socket_check take timediff_t timeout +Marc Hoersken (6 Jun 2020) +- timeouts: move ms timeouts to timediff_t from int and long - Coverity found CID 1461718: + Now that all functions in select.[ch] take timediff_t instead + of the limited int or long, we can remove type conversions + and related preprocessor checks to silence compiler warnings. - Integer handling issues (CONSTANT_EXPRESSION_RESULT) "timeout_ms > - 9223372036854775807L" is always false regardless of the values of its - operands. This occurs as the logical second operand of "||". + Avoiding conversions from time_t was already done in 842f73de. - Closes #5240 - -- [i-ky brought this change] + Based upon #5262 + Supersedes #5214, #5220 and #5221 + Follow up to #5343 and #5479 + Closes #5490 - libcurl-multi.3: added missing full stop - - Closes #5285 +Daniel Stenberg (6 Jun 2020) +- [François Rigault brought this change] -Jay Satiro (22 Apr 2020) -- transfer: Switch PUT to GET/HEAD on 303 redirect + openssl: set FLAG_TRUSTED_FIRST unconditionally - Prior to this change if there was a 303 reply to a PUT request then - the subsequent request to respond to that redirect would also be a PUT. - It was determined that was most likely incorrect based on the language - of the RFCs. Basically 303 means "see other" resource, which implies it - is most likely not the same resource, therefore we should not try to PUT - to that different resource. + On some systems, openssl 1.0.x is still the default, but it has been + patched to contain all the recent security fixes. As a result of this + patching, it is possible for macro X509_V_FLAG_NO_ALT_CHAINS to be + defined, while the previous behavior of openssl to not look at trusted + chains first, remains. - Refer to the discussions in #5237 and #5248 for more information. + Fix it: ensure X509_V_FLAG_TRUSTED_FIRST is always set, do not try to + probe for the behavior of openssl based on the existence ofmacros. - Fixes https://github.com/curl/curl/issues/5237 - Closes https://github.com/curl/curl/pull/5248 + Closes #5530 -Daniel Stenberg (22 Apr 2020) -- lib/mk-ca-bundle: skip empty certs +- server/util: fix logmsg format using curl_off_t argument - Reviewed-by: Emil Engler - Reported-by: Ashwin Metpalli - Fixes #5278 - Closes #5280 - -- version: skip idn2_check_version() check and add precaution + ... this caused segfaults on armv7. - A gcc-10's -fanalyze complaint made me spot and do these improvements. + Regression added in dd0365d560aea5a (7.70.0) - Closes #5281 + Reviewed-by: Jay Satiro + Closes #5529 - RELEASE-NOTES: synced -- [Brian Bergeron brought this change] +- [Cherish98 brought this change] - curl.h: update comment typo - - "routines with be invoked" -> "routines will be invoked" + socks: fix expected length of SOCKS5 reply - Closes #5279 - -- [Emil Engler brought this change] - - GnuTLS: Don't skip really long certificate fields + Commit 4a4b63d forgot to set the expected SOCKS5 reply length when the + reply ATYP is X'01'. This resulted in erroneously expecting more bytes + when the request length is greater than the reply length (e.g., when + remotely resolving the hostname). - Closes #5271 + Closes #5527 -- gnutls: bump lowest supported version to 3.1.10 - - GnuTLS 3.1.10 added new functions we want to use. That version was - released on Mar 22, 2013. Removing support for older versions also - greatly simplifies the code. +Marc Hoersken (5 Jun 2020) +- .gitignore: add directory containing the stats repo - Ref: #5271 - Closes #5276 + Since the new curl/stats repository is designed to be + checked out into the curl repository working tree as stats/ + it should be on the ignore list to aid in commit staging. -- mqtt: make NOSTATE get within the debug name array +Daniel Stenberg (5 Jun 2020) +- [Adnan Khan brought this change] -- tests: run the RTSP test server on a dynamic port number + HTTP3.md: clarify cargo build directory - To avoid port collisions. + Cargo needs to be called from within the 'quiche' directory. - Closes #5272 + Closes #5522 -- tests: add %NOLISTENPORT and use it - - The purpose with this variable is to provide a port number that is - reasonably likely to not have a listener on the local host so that tests - can try connect failures against it. It uses port 47 - "reserved" - according to IANA. - - Updated six tests to use it instead of the previous different ports. +- user-agent.d: spell out what happens given a blank argument - Assisted-by: Emil Engler - Closes #5270 + Closes #5525 -- mqtt: remove code with no purpose +- trailers: switch h1-trailer logic to use dynbuf - Detected by Coverity. CID 1462319. + In the continued effort to remove "manual" realloc schemes. - "The same code is executed when the condition result is true or false, - because the code in the if-then branch and after the if statement is - identical." + Closes #5524 + +- CURLINFO_ACTIVESOCKET.3: clarify the description - Closes #5275 + Reported-by: Jay Satiro + Fixes #5299 + Closes #5520 -- mqtt: fix Curl_read() error handling while reading remaining length +- mailmap: Don J Olmstead + +- configure: only strip first -L from LDFLAGS - Detected by Coverity. CID 1462320. + In the logic that works out if a given OpenSSL path works, it stripped + off a possibly leading -L flag using an incorrect sed pattern which + would remove all instances of -L in the string, including if the path + itself contained that two-letter sequence! - Closes #5274 - -- server/tftpd: fix compiler warning + The same pattern was used and is now updated in multiple places. Now it + only removes -L if it starts the strings. - Follow-up from 369ce38ac1d - Reported-by: Marc Hörsken + Reported-by: Mohamed Osama + Fixes #5519 + Closes #5521 -- http: free memory when Alt-Used header creation fails due to OOM +Peter Wu (4 Jun 2020) +- quiche: advertise draft 28 support - Reported-by: James Fuller - Fixes #5268 - Closes #5269 - -Daniel Gustafsson (20 Apr 2020) -- lib: fix typos in comments and errormessages + Fix the verbose message while at it, quiche currently supports draft + 27 and draft 28 simultaneously. - This fixes a few randomly spotted typos in recently merged code, most - notably one in a userfacing errormessage the schannel code. + Closes #5518 -Daniel Stenberg (20 Apr 2020) -- tests: run the SOCKS test server on a dynamic port number +Daniel Stenberg (4 Jun 2020) +- KNOWN_BUGS: RTSP authentication breaks without redirect support - Closes #5266 - -- [Johannes Schindelin brought this change] + Closes #4750 - multi-ssl: reset the SSL backend on `Curl_global_cleanup()` - - When cURL is compiled with support for multiple SSL backends, it is - possible to configure an SSL backend via `curl_global_sslset()`, but - only *before* `curl_global_init()` was called. +Jay Satiro (4 Jun 2020) +- projects: Add crypt32.lib to dependencies for all OpenSSL configs - If another SSL backend should be used after that, a user might be - tempted to call `curl_global_cleanup()` to start over. However, we did - not foresee that use case and forgot to reset the SSL backend in that - cleanup. + Windows project configurations that use OpenSSL with USE_WIN32_CRYPTO + need crypt32. - Let's allow that use case. + Follow-up to 148534d which added CURLSSLOPT_NATIVE_CA for 7.71.0. - Fixes #5255 - Closes #5257 - Reported-by: davidedec on github - Signed-off-by: Johannes Schindelin - -- tests: run the TFTP test server on a dynamic port number + The changes that are in this commit were made by script. - Picking a dynamic unused port is better than a fixed to avoid the - collision risk. + Ref: https://gist.github.com/jay/a1861b50ecce2b32931237180f856e28 - Closes #5265 + Closes https://github.com/curl/curl/pull/5516 -- mqtt: improve the state machine - - To handle PUBLISH before SUBACK and more. +Marc Hoersken (3 Jun 2020) +- CI/macos: fix 'is already installed' errors by using bundle - Updated the existing tests and added three new ones. + Avoid failing CI builds due to nghttp2 being already installed. - Reported-by: Christoph Krey - Bug: https://curl.haxx.se/mail/lib-2020-04/0021.html - Closes #5246 + Closes #5513 -- runtests: always put test number in servercmd file +Daniel Stenberg (3 Jun 2020) +- altsvc: fix 'dsthost' may be used uninitialized in this function - RELEASE-NOTES: synced -- release-notes.pl: fix parsing typo - -James Fuller (20 Apr 2020) -- ensure all references to ports are replaced by vars - -- add more alt-svc test coverage - -Daniel Stenberg (20 Apr 2020) -- test1247: use http server to get the port number set +- urldata: let the HTTP method be in the set.* struct - Follow-up to 0f5db7b263f - -- runtests: use a unix domain socket path with the pid in the name + When the method is updated inside libcurl we must still not change the + method as set by the user as then repeated transfers with that same + handle might not execute the same operation anymore! - To make it impossible for test cases to access the file name without - using the proper variable for the purpose. + This fixes the libcurl part of #5462 - Closes #5264 - -Daniel Gustafsson (19 Apr 2020) -- [Mipsters on github brought this change] - - src: Remove C99 constructs to ensure C89 compliance + Test 1633 added to verify. - This fixes the error: 'for' loop initial declaration used outside C99 - mode by declaring the loop increment variable in the beginning of the - block instead of inside the for loop. + Closes #5499 + +- hostip: fix the memory-leak introduced in 67d2802 - Fixes #5254 - Reviewed-by: Daniel Gustafsson + Fixes #5503 + Closes #5504 -Daniel Stenberg (19 Apr 2020) -- runtests: dummy init the ports variables to avoid warnings +- test970: make it require proxy support + + This test verifies the -w %json output and the test case includes a full + generated "blob". If there's no proxy support built into libcurl, it + will return an error for proxy related info variables and they will not + be included in the json, thus causing a mismatch and this test fails. - ... and generate something that can help debug test cases. + Reported-by: Marc Hörsken + Fixes #5501 + Closes #5502 -- [Patrick Monnerat brought this change] +- [Radoslav Georgiev brought this change] - mime: properly check Content-Type even if it has parameters + examples/http2-down/upload: add error checks - New test 669 checks this fix is effective. + If `index.html` does not exist in the directory from which the example + is invoked, the fopen(upload, "rb") invocation in `setup` would fail, + returning NULL. This value is subsequently passed as the FILE* argument + of the `fread` invocation in the `read_callback` function, which is the + actual cause of the crash (apparently `fread` assumes that argument to + be non-null). - Fixes #5256 - Closes #5258 - Reported-by: thanhchungbtc on github - -- tests/FILEFORMAT: converted to markdown and extended + In addition, mitigate some possible crashes of similar origin. - Closes #5261 + Closes #5463 -- test1245: make it work with dynamic FTP server port +- [kotoriのねこ brought this change] -- test1055: make it work with dynamic FTP port + examples/ephiperfifo: turn off interval when setting timerfd + + Reported-by: therealhirudo on github + Fixes #5485 + Closes #5497 -- test1028: make it run on dynamic FTP server port +- [Saleem Abdulrasool brought this change] -- tests: move pingpong server to dynamic listening port + vtls: repair the build with `CURL_DISABLE_PROXY` + + `http_proxy` will not be available in `conndata` if `CURL_DISABLE_PROXY` + is enabled. Repair the build with that configuration. - FTP, IMAP, POP3, SMTP and their IPv6 versions are now all on dynamic - ports + Follow-up to f3d501dc67 - Test 842-845 are unfortunately a bit hard to move over to this concept - right now and require "default port" still... - -- test1056: work with dynamic HTTP ipv6 port + Closes #5498 -- test1448: work with dynamic HTTP server port +- transfer: remove k->str NULL check + + "Null-checking k->str suggests that it may be null, but it has already + been dereferenced on all paths leading to the check" - and it can't + legally be NULL at this point. Remove check. + + Detected by Coverity CID 1463884 + + Closes #5495 -- tests: introduce preprocessed test cases +Marc Hoersken (1 Jun 2020) +- select: always use Sleep in Curl_wait_ms on Win32 - The runtests script now always performs variable replacement on the - entire test source file before the test gets executed, and saves the - updated version in a temporary file (log/test[num]) so that all test - case readers/servers can use that version (if present) and thus enjoy - the powers of test case variable substitution. + Since Win32 almost always will also have USE_WINSOCK, + we can reduce complexity and always use Sleep there. - This is necessary to allow complete port number freedom. + Assisted-by: Jay Satiro + Reviewed-by: Daniel Stenberg - Test 309 is updated to work with a non-fixed port number thanks to this. + Follow up to #5343 + Closes #5489 -- tests: make 2006-2010 handle different port number lengths +Daniel Stenberg (31 May 2020) +- conncache: download buffer needs +1 size for trailing zero + + Follow-up to c4e6968127e + Detected by OSS-Fuzz: https://oss-fuzz.com/testcase-detail/5727799779524608 -- tests: run the sws server on "any port" +Marc Hoersken (31 May 2020) +- azure: use matrix strategy to avoid configuration redundancy - Makes the test servers for HTTP and Gopher pop up on a currently unused - port and runtests adapts to that! + This also includes the following changes: - Closes #5247 - -Marc Hoersken (18 Apr 2020) -- sockfilt: tidy variable naming and data structure in select_ws + - Use the same timeout for all jobs on Linux (60 minutes) + and Windows (90 minutes) + - Use CLI stable apt-get install -y instead of apt install + which warns about that and run apt-get update first + - Enable MQTT for Windows msys2 builds instead of + legacy msys1 builds + - Add ./configure --prefix parameter to the msys2 builds + - The MSYSTEM environment variable is now preset inside + the container images for the msys2 builds - This commit does not introduce any logical changes to the code. + Note: on Azure Pipelines the matrix strategy is basically + just a simple list of job copies and not really a matrix. - Reviewed-by: Jay Satiro and Marcel Raad - Closes #5238 - -Daniel Stenberg (17 Apr 2020) -- [Anderson Toshiyuki Sasaki brought this change] + Closes #5468 - libssh: Use new ECDSA key types to check known hosts +Daniel Stenberg (30 May 2020) +- build: disable more code/data when built without proxy support - From libssh 0.9.0, ssh_key_type() returns different key types for ECDSA - keys depending on the curve. + Added build to travis to verify - Signed-off-by: Anderson Toshiyuki Sasaki - Fixes #5252 - Closes #5253 + Closes #5466 -Marcel Raad (17 Apr 2020) -- appveyor: add Unicode winbuild jobs +- url: alloc the download buffer at transfer start - These are cheap as they don't build tests. + ... and free it as soon as the transfer is done. It removes the extra + alloc when a new size is set with setopt() and reduces memory for unused + easy handles. - Closes https://github.com/curl/curl/pull/5063 - -Daniel Stenberg (16 Apr 2020) -- mqttd: s/errno/SOCKERRNO + In addition: the closure_handle now doesn't use an allocated buffer at + all but the smallest supported size as a stack based one. - To behave proper on Windows - Reported-by: Gisle Vanem - Bug: https://github.com/curl/curl/commit/5e855bbd18f84a02c951be7cac6188276818cdac#r38507132 - Closes #5241 + Closes #5472 -- buildconf: use find -execdir instead, remove -print and the ares files +- timeouts: change millisecond timeouts to timediff_t from time_t - Follow-up to 1e41bec96a6e + For millisecond timers we like timediff_t better. Also, time_t can be + unsigned so returning a negative value doesn't work then. - Suggested-by: Marc Hörsken - -- [Alexander V. Tikhonov brought this change] + Closes #5479 - buildconf: avoid using tempfile when removing files +Marc Hoersken (30 May 2020) +- select: add overflow checks for timeval conversions - Closes #5213 - -- copyright: bump the copyright year range - -- scripts/release-notes.pl: accept colon after the Fixes/Closes keywords - -- [JP Mens brought this change] - - docs/MQTT: replace confusing 80 by 75 + Using time_t and suseconds_t if suseconds_t is available, + long on Windows (maybe others in the future) and int elsewhere. + + Also handle case of ULONG_MAX being greater or equal to INFINITE. - I was a bit surprised by the `80`: first thought: what's HTTP doing - here? ;) + Assisted-by: Jay Satiro + Reviewed-by: Daniel Stenberg - Closes #5236 + Part of #5343 -- [Brad King brought this change] +- select: use timediff_t instead of time_t and int for timeout_ms + + Make all functions in select.[ch] take timeout_ms as timediff_t + which should always be large enough and signed on all platforms + to take all possible timeout values and avoid type conversions. + + Reviewed-by: Jay Satiro + Reviewed-by: Daniel Stenberg + + Replaces #5107 and partially #5262 + Related to #5240 and #5286 + Closes #5343 - cmake: Avoid MSVC C4273 warnings in send/recv checks +- unit1604.c: fix implicit conv from 'SANITIZEcode' to 'CURLcode' - We use `check_c_source_compiles` to check possible send/recv signatures - by reproducing the forward declarations from system headers. On Windows - the `winsock2.h` header adds dll linkage settings to its forward - declaration. If ours does not match the compiler warns: + GCC 10 warns about this with warning: implicit conversion + from 'SANITIZEcode' to 'CURLcode' [-Wenum-conversion] - warning C4273: 'recv': inconsistent dll linkage + Since 'expected_result' is not really of type 'CURLcode' and + it is not exposed in any way, we can just use 'SANITIZEcode'. - Add `WINSOCK_API_LINKAGE` to our test signatures when it is defined so - that our linkage is consistent with that from `winsock2.h`. + Reviewed-by: Daniel Stenberg + Reviewed-by: Marcel Raad - Fixes #4764 - Closes #5232 + Closes #5476 -Jay Satiro (14 Apr 2020) -- KNOWN_BUGS: Add entry 'Blocking socket operations' - - - Add threaded resolver cleanup and GSSAPI for FTP to the TODO list of - known blocking operations. - - - New known bugs entry 'Blocking socket operations in non-blocking API' - that directs to the TODO's list of known blocking operations. +- tests/libtest: fix undefined reference to 'curlx_win32_fopen' - Ref: https://github.com/curl/curl/pull/5214#issuecomment-612488021 + Since curl_setup.h now makes use of curlx_win32_fopen for Win32 + builds with USE_WIN32_LARGE_FILES or USE_WIN32_SMALL_FILES defined, + we need to include the relevant files for tests using fopen, + because the libtest sources are also including curl_setup.h - Reported-by: Marc Hoersken + Reviewed-by: Marcel Raad + Reviewed-by: Daniel Stenberg - Closes https://github.com/curl/curl/pull/5216 + Follow up to #3784 (ffdddb45d9) + Closes #5475 -Marc Hoersken (14 Apr 2020) -- test2043: use revoked.badssl.com instead of revoked.grc.com - - The certificate of revoked.grc.com has expired on 2020-04-13. +- appveyor: add non-debug plain autotools-based build - Reviewed-by: Jay Satiro + This should enable us to catch linking issues with the + testsuite early, like the one described/fixed in #5475. - Closes #5233 - -- sockfilt: fix broken pipe on Windows to be ready in select_ws + Reviewed-by: Daniel Stenberg + Reviewed-by: Marcel Raad - Closes #5228 + Closes #5477 -Daniel Stenberg (14 Apr 2020) +Daniel Stenberg (29 May 2020) - RELEASE-NOTES: synced -- scripts/release-notes: fix duplicate output header - -- github/workflow: enable MQTT in the macOS debug build - -- azure: add mqtt support to one of the Windows builds - -- travis: add mqtt job on Linux - -- tests: add four MQTT tests 1190 - 1193 - -- tests: add the mqtt test server mqttd - -- tests: support hex encoded data and mqtt server +- Revert "buildconf: use find -execdir" + + This partially reverts commit c712009838f44211958854de431315586995bc61. + + Keep the ares_ files removed but bring back the older way to run find, + to make it work with busybox's find, as apparently that's being used. - The mqtt server is started using a "random" port. + Reported-by: Max Peal + Fixes #5483 + Closes #5484 -- [Björn Stenberg brought this change] +- server/sws: fix asan warning on use of uninitialized variable - mqtt: add new experimental protocol +- libssh2: improved error output for wrong quote syntax - Closes #5173 - -- TODO: Consider convenience options for JSON and XML? + Reported-by: Werner Stolz - Closes #5203 + Closes #5474 -- tool: do not declare functions with Curl_ prefix +- mk-lib1521: generate code for testing BLOB options as well - To avoid collision risks with private libcurl symbols when linked with - static versions (or just versions not hiding internal symbols). + Follow-up to cac5374298b3 - Reported-by: hydra3333 on github - Fixes #5219 - Closes #5234 - -- [Nathaniel R. Lewis brought this change] + Closes #5478 - cmake: add aliases so exported target names are available in tree +- configure: repair the check if argv can be written to - Reviewed-by: Brad King - Closes #5206 - -- version: increase buffer space for ssl version output + Due to bad escaping of the test code, the test wouldn't build and thus + result in a negative test result, which would lead to the unconditional + assumption that overwriting the arguments doesn't work and thus curl + would never hide credentials given in the command line, even when it + would otherwise be possible. - To avoid it getting truncated, especially when several SSL backends are - built-in. + Regression from commit 2d4c2152c (7.60.0) - Reported-by: Gisle Vanem - Fixes #5222 - Closes #5226 + Reported-by: huzunhao on github + Fixes #5470 + Closes #5471 -Marc Hoersken (13 Apr 2020) -- cirrus: no longer ignore test 504 which is working again +Peter Wu (28 May 2020) +- CMake: rebuild Makefile.inc.cmake when Makefile.inc changes - The test is working again, because TCP blackholing is disabled. - -- appveyor: completely disable tests that fail to timeout early + Otherwise the build might fail due to missing source files, as + demonstrated by the recent keylog.c addition on an existing build dir. - The tests changed from ignored to disabled are tests that are - about connecting to non-listening socket. On AppVeyor these - tests are not reliable, because for some unknown reason the - connect is not timing out before the test time limit is reached. + Closes #5469 -Daniel Stenberg (13 Apr 2020) -- test1908: avoid using fixed port number in test data +Daniel Stenberg (28 May 2020) +- urldata: fix comments: Curl_done() is called multi_done() now - Closes #5225 - -Jay Satiro (12 Apr 2020) -- [Andrew Kurushin brought this change] + ... since 575e885db - schannel: Fix blocking timeout logic +Peter Wu (27 May 2020) +- ngtcp2: use common key log routine for better thread-safety - - Fix schannel_send for the case when no timeout was set. + Tested with ngtcp2 built against the OpenSSL library. Additionally + tested with MultiSSL (NSS for TLS and ngtcp2+OpenSSL for QUIC). + + The TLS backend (independent of QUIC) may or may not already have opened + the keylog file before. Therefore Curl_tls_keylog_open is always called + to ensure the file is open. + +- wolfssl: add SSLKEYLOGFILE support - Prior to this change schannel would error if the socket was not ready - to send data and no timeout was set. + Tested following the same curl and tshark commands as in commit + "vtls: Extract and simplify key log file handling from OpenSSL" using + WolfSSL v4.4.0-stable-128-g5179503e8 from git master built with + `./configure --enable-all --enable-debug CFLAGS=-DHAVE_SECRET_CALLBACK`. - This commit is similar to parent commit 89dc6e0 which recently made the - same change for SOCKS, for the same reason. Basically it was not well - understood that when Curl_timeleft returns 0 it is not a timeout of 0 ms - but actually means no timeout. + Full support for this feature requires certain wolfSSL build options, + see "Availability note" in lib/vtls/wolfssl.c for details. - Fixes https://github.com/curl/curl/issues/5177 - Closes https://github.com/curl/curl/pull/5221 + Closes #5327 -- socks: Fix blocking timeout logic - - - Document in Curl_timeleft's comment block that returning 0 signals no - timeout (ie there's infinite time left). +- vtls: Extract and simplify key log file handling from OpenSSL - - Fix SOCKS' Curl_blockread_all for the case when no timeout was set. + Create a set of routines for TLS key log file handling to enable reuse + with other TLS backends. Simplify the OpenSSL backend as follows: - Prior to this change if the timeout had a value of 0 and that was passed - to SOCKET_READABLE it would return right away instead of blocking. That - was likely because it was not well understood that when Curl_timeleft - returns 0 it is not a timeout of 0 ms but actually means no timeout. + - Drop the ENABLE_SSLKEYLOGFILE macro as it is unconditionally enabled. + - Do not perform dynamic memory allocation when preparing a log entry. + Unless the TLS specifications change we can suffice with a reasonable + fixed-size buffer. + - Simplify state tracking when SSL_CTX_set_keylog_callback is + unavailable. My original sslkeylog.c code included this tracking in + order to handle multiple calls to SSL_connect and detect new keys + after renegotiation (via SSL_read/SSL_write). For curl however we can + be sure that a single master secret eventually becomes available + after SSL_connect, so a simple flag is sufficient. An alternative to + the flag is examining SSL_state(), but this seems more complex and is + not pursued. Capturing keys after server renegotiation was already + unsupported in curl and remains unsupported. - Ref: https://github.com/curl/curl/pull/5214#issuecomment-612512360 + Tested with curl built against OpenSSL 0.9.8zh, 1.0.2u, and 1.1.1f + (`SSLKEYLOGFILE=keys.txt curl -vkso /dev/null https://localhost:4433`) + against an OpenSSL 1.1.1f server configured with: - Closes https://github.com/curl/curl/pull/5220 - -- [Marc Hoersken brought this change] - - gopher: check remaining time left during write busy loop + # Force non-TLSv1.3, use TLSv1.0 since 0.9.8 fails with 1.1 or 1.2 + openssl s_server -www -tls1 + # Likewise, but fail the server handshake. + openssl s_server -www -tls1 -Verify 2 + # TLS 1.3 test. No need to test the failing server handshake. + openssl s_server -www -tls1_3 - Prior to this change gopher's blocking code would block forever, - ignoring any set timeout value. + Verify that all secrets (1 for TLS 1.0, 4 for TLS 1.3) are correctly + written using Wireshark. For the first and third case, expect four + matches per connection (decrypted Server Finished, Client Finished, HTTP + Request, HTTP Response). For the second case where the handshake fails, + expect a decrypted Server Finished only. - Assisted-by: Jay Satiro - Reviewed-by: Daniel Stenberg + tshark -i lo -pf tcp -otls.keylog_file:keys.txt -Tfields \ + -eframe.number -eframe.time -etcp.stream -e_ws.col.Info \ + -dtls.port==4433,http -ohttp.desegment_body:FALSE \ + -Y 'tls.handshake.verify_data or http' - Similar to #5220 and #5221 - Closes #5214 + A single connection can easily be identified via the `tcp.stream` field. -Daniel Stenberg (13 Apr 2020) -- [Dirkjan Bussink brought this change] +Daniel Stenberg (27 May 2020) +- FILEFORMAT: add more features that tests can depend on - gnutls: ensure TLS 1.3 when SRP isn't requested - - When SRP is requested in the priority string, GnuTLS will disable - support for TLS 1.3. Before this change, curl would always add +SRP to - the priority list, effectively always disabling TLS 1.3 support. - - With this change, +SRP is only added to the priority list when SRP - authentication is also requested. This also allows updating the error - handling here to not have to retry without SRP. This is because SRP is - only added when requested and in that case a retry is not needed. - - Closes #5223 +- [Michael Kaufmann brought this change] -Marc Hoersken (12 Apr 2020) -- tests/server: add hidden window to gracefully handle WM_CLOSE + transfer: close connection after excess data has been read - Forward Window events as signals to existing signal event handler. - -- tests/server: add CTRL event handler for Win32 consoles + For HTTP 1.x, it's a protocol error when the server sends more bytes + than announced. If this happens, don't reuse the connection, because the + start position of the next response is undefined. - Forward CTRL events as signals to existing signal event handler. + Closes #5440 -- tests/server: move all signal handling routines to util.[ch] - - Avoid code duplication to prepare for portability enhancements. +- [Estanislau Augé-Pujadas brought this change] -Daniel Stenberg (12 Apr 2020) -- compressed.d: stress that the headers are not modified + Revert "ssh: ignore timeouts during disconnect" - Suggested-by: Michael Osipov - Assisted-by: Jay Satiro - Bug: https://github.com/curl/curl/issues/5182#issuecomment-611638008 - Closes #5217 + This reverts commit f31760e63b4e9ef1eb25f8f211390f8239388515. Shipped in + curl 7.54.1. + + Bug: https://curl.haxx.se/mail/lib-2020-05/0068.html + Closes #5465 -Marc Hoersken (11 Apr 2020) -- tests/server/util.c: use curl_off_t instead of long for pid +- urldata: connect related booleans live in struct ConnectBits - Avoid potential overflow of huge PIDs on Windows. + And remove a few unused booleans! - Related to #5188 - Assisted-by: Marcel Raad + Closes #5461 -- tests: use Cygwin/msys PIDs for stunnel and sshd on Windows - - Since the Windows versions of both programs would write Windows - PIDs to their pidfiles which we cannot handle, we need to use - our known perl.exe Cygwin/msys PID together with exec() in order - to tie the spawned processes to the existance of our perl.exe +- hostip: on macOS avoid DoH when given a numerical IP address - The perl.exe that is executing secureserver.pl and sshserver.pl - has a Cygwin/msys PID, because it is started inside Cygwin/msys. + When USE_RESOLVE_ON_IPS is set (defined on macOS), it means that + numerical IP addresses still need to get "resolved" - but not with DoH. - Related to #5188 + Reported-by: Viktor Szakats + Fixes #5454 + Closes #5459 -- tests: add Windows compatible pidwait like pidkill and pidterm +- ngtcp2: cleanup memory when failing to connect - Related to #5188 + Reported-by: Peter Wu + Fixes #5447 (the ngtcp2 side of it) + Closes #5451 -- tests: fix conflict between Cygwin/msys and Windows PIDs - - Add 65536 to Windows PIDs to allow Windows specific treatment - by having disjunct ranges for Cygwin/msys and Windows PIDs. - - See also: - - https://cygwin.com/git/?p=newlib-cygwin.git;a=commit; ↵ - h=b5e1003722cb14235c4f166be72c09acdffc62ea - - https://cygwin.com/git/?p=newlib-cygwin.git;a=commit; ↵ - h=448cf5aa4b429d5a9cebf92a0da4ab4b5b6d23fe +- quiche: clean up memory properly when failing to connect - Replaces #5178 - Closes #5188 - -Daniel Stenberg (11 Apr 2020) -- RELEASE-NOTES: synced + Addresses the quiche side of #5447 + Reported-by: Peter Wu + Closes #5450 -- release-notes.pl: detect the start of the references in cleanup mode +- cleanup: use a single space after equals sign in assignments -- Revert "file: on Windows, refuse paths that start with \\" +- url: accept "any length" credentials for proxy auth - This reverts commit 1b71bc532bde8621fd3260843f8197182a467ff2. + They're only limited to the maximum string input restrictions, not to + 256 bytes. - Reminded-by: Chris Roberts - Bug: https://curl.haxx.se/mail/archive-2020-04/0013.html + Added test 1178 to verify - Closes #5215 + Reported-by: Will Roberts + Fixes #5448 + Closes #5449 -Jay Satiro (11 Apr 2020) -- lib: fix conversion warnings for SOCKET_WRITABLE/READABLE - - - If loss of data may occur converting a timediff_t to time_t and - the time value is > TIME_T_MAX then treat it as TIME_T_MAX. - - This is a follow-up to 8843678 which removed the (time_t) typecast - from the macros so that conversion warnings could be identified. - - Closes https://github.com/curl/curl/pull/5199 +- [Maksim Stsepanenka brought this change] -- test1148: tolerate progress updates better (again) - - - Ignore intermediate progress updates. - - - Support locales that use a character other than period as decimal - separator (eg 100,0%). - - test1148 checks that the progress finishes at 100% and has the right - bar width. Prior to this change the test assumed that the only progress - reported for such a quick transfer was 100%, however in rare instances - (like in the CI where transfer time can slow considerably) there may be - intermediate updates. For example, below is stderrlog1148 from a failed - CI run with explicit \r and \n added (it is one line; broken up so that - it's easier to understand). - - \r - \r################################## 48.3% - \r######################################################################## 100.0% - \n + test1167: fixes in badsymbols.pl - Closes https://github.com/curl/curl/pull/5194 - -Marc Hoersken (10 Apr 2020) -- sshserver.pl: use cached Win32 environment check variable + Closes #5442 -- appveyor: partially revert 3413a110 to keep build without proxy +- altsvc: fix parser for lines ending with CRLF - Ref: #5211 and #4526 - Reported-by: Marcel Raad - -- appveyor: ignore failing 'connect to non-listening proxy' tests + Fixed the alt-svc parser to treat a newline as end of line. - Closes #5211 - -- CI/macos: convert CRLF to LF and align indentation - -Daniel Stenberg (9 Apr 2020) -- url: allow non-HTTPS altsvc-matching for debug builds + The unit tests in test 1654 were done without CRLF and thus didn't quite + match the real world. Now they use CRLF as well. - This is already partly supported but this part was missing. - Reported-by: James Fuller + Reported-by: Peter Wu + Assisted-by: Peter Wu + Assisted-by: Jay Satiro + Fixes #5445 + Closes #5446 + +Viktor Szakats (25 May 2020) +- all: fix codespell errors - Closes #5205 + Reviewed-by: Jay Satiro + Reviewed-by: Daniel Stenberg + Closes https://github.com/curl/curl/pull/5452 -- server/resolve: remove AI_CANONNAME to make macos tell the truth +Peter Wu (25 May 2020) +- ngtcp2: fix build with current ngtcp2 master implementing draft 28 - With this bit set, my mac successfully resolves "ip6-localhost" when in - fact there is no such host known to my machine! That in turn made test - 241 wrongly execute and fail. + Based on client.cc changes from ngtcp2. Tested with current git master, + ngtcp2 commit c77d5731ce92, nghttp3 commit 65ff479d4380. - Closes #5202 + Fixes #5444 + Closes #5443 -- runtests: fix warning about using an undefined variable +Daniel Stenberg (25 May 2020) +- RELEASE-NOTES: synced - Follow-up from 4d939ef6ceb2db1 + moved the new setopts up to a "change" -- release-notes: fix the initial reference list output +- RELEASE-NOTES: synced -- github actions: run when pushed to master or */ci + PRs - - Avoid double-builds when using "local" branches for PRs. For both macos - and fuzz jobs. +- copyright: updated year ranges out of sync - Closes #5201 - -- runtests: provide nicer errormsg when protocol "dump" file is empty + ... and whitelisted a few more files in the the copyright.pl script. - [Gilles Vollant brought this change] - schannel: support .P12 or .PFX client certificates - - Used with curl command line option like this: --cert - : --cert-type p12 + setopt: add CURLOPT_PROXY_ISSUERCERT(_BLOB) for coherency - Closes #5193 + Closes #5431 -- tests: verify split initial HTTP requests with CURL_SMALLREQSEND - - test1294: "split request" being when the entire request isn't sent in - the first go, and the remainder is sent in the PERFORM state. A GET - request is otherwise not sending anything during PERFORM. +- curl: remove -J "informational" written on stdout - test1295: same kind of split but with POST + curl would previously show "curl: Saved to filename 'name from header'" + if -J was used and a name was picked from the Content-Disposition + header. That output could interfer with other stdout output, such as -w. - Closes #5197 + This commit removes that output line. + Bug: https://curl.haxx.se/mail/archive-2020-05/0044.html + Reported-by: Коваленко Анатолий Викторович + Closes #5435 -- http: don't consider upload done if the request isn't completely sent off +Peter Wu (22 May 2020) +- travis: simplify quiche build instructions wrt boringssl - Fixes #4919 - Closes #5197 + quiche builds boringssl as static library, reuse that instead of + building another shared library. + + Closes #5438 -- http: allow Curl_add_buffer_send() to do a short first send by force +- configure: fix pthread check with static boringssl - In a debug build, settting the environment variable "CURL_SMALLREQSEND" - will make the first HTTP request send not send more bytes than the set - amount, thus ending up verifying that the logic for handling a split - HTTP request send works correctly. + A shared boringssl/OpenSSL library requires -lcrypto only for linking. + A static build additionally requires `-ldl -lpthread`. In the latter + case `-lpthread` is added to LIBS which prevented `-pthread` from being + added to CFLAGS. Clear LIBS to fix linking failures for libtest tests. -- connect: store connection info for QUIC connections +Daniel Stenberg (22 May 2020) +- Revert "sendf: make failf() use the mvsnprintf() return code" + + This reverts commit 74623551f306990e70c7c5515b88972005604a74. - Restores the --head functionality to the curl utility which extracts - 'protocol' that is stored that way. + Instead mark the function call with (void). Getting the return code and + using it instead triggered Coverity warning CID 1463596 because + snprintf() can return a negative value... - Reported-by: James Fuller - Fixes #5196 - Closes #5198 + Closes #5441 -- tests/README: update the port numbers list +- typecheck-gcc.h: CURLINFO_PRIVATE does not need a 'char *' - Since the pipelining server is long gone. - Reported-by: James Fuller + Reported-by: Billyzou0741326 on github + Fixes #5432 + Closes #5436 -- select: remove typecast from SOCKET_WRITABLE/READABLE macros - - So that they don't hide conversions-by-mistake +- tests/server/util.h: add extern to silence compiler warning - Reviewed-by: Jay Satiro - Closes #5190 + Follow-up from a3b0699d5c1 -- CURLOPT_WRITEFUNCTION.3: add inline example and new see-also +- typecheck-gcc.h: fix the OFF_T check - Closes #5192 - -- release-notes: output trailing references sorted numerically - -- cleanup: correct copyright year range on a few files - -- configure: remove use of -vec-report0 from CFLAGS with icc + The option number also needs to be less than CURLOPTTYPE_BLOB. - ... as it apparently isn't (always) supported. - Reported-by: Alain Miniussi - Fixes #5096 - Closes #5191 + Follow-up to cac5374298 + Reported-by: Jeroen Ooms + Bug: https://github.com/curl/curl/pull/5365#issuecomment-631084114 -- warnless: remove code block for icc that didn't work +- TODO: --dry-run - Reported-by: Alain Miniussi - Fixes #5096 + Closes #5426 -Marc Hoersken (6 Apr 2020) -- dist: add missing setup-win32.h +- TODO: Ratelimit or wait between serial requests - Follow up to d820224b8b - -Daniel Stenberg (6 Apr 2020) -- RELEASE-NOTES: synced + Closes #5406 -- scripts/release-notes.pl: add helper script for RELEASE-NOTES maintenance +- tool_paramhlp: fixup C89 mistake - This script helps putting entries in the RELEASE-NOTES using a coherent - style and sorting with a minimal human editing effort - as long as the - first line in the commit message is good enough! There's a short howto - at the top of the file. + Follow-up to c5f0a9db22. -- [Dennis Felsing brought this change] +- [Siva Sivaraman brought this change] - configure: don't check for Security.framework when cross-compiling + tool_paramhlp: fixed potentially uninitialized strtol() variable - Since it checks for the local file, not the cross-compiled one. + Seems highly unlikely to actually be possible, but better safe than + sorry. - Closes #5189 + Closes #5417 -- TODO: Option to make -Z merge lined based outputs on stdout - - Closes #5175 +- [Siva Sivaraman brought this change] -- lib: never define CURL_CA_BUNDLE with a getenv - - - it breaks the build (since 6de756c9b1de34b7a1) - - it's not documented and not consistent across platforms - - the curl tool does that getenv magic + tool_operate: fixed potentially uninitialized variables - Bug: https://github.com/curl/curl/commit/6de756c#r38127030 - Reported-by: Gisle Vanem + ... in curl_easy_getinfo() calls. They're harmless but clearing the + variables makes the code safer and comforts the reader. - Closes #5187 - -Marc Hoersken (5 Apr 2020) -- lib670: use the same Win32 API check as all other lib tests + Closes #5416 -- appveyor: use random test server ports based upon APPVEYOR_API_URL - - Avoid conflicts of test server ports with AppVeyor API on localhost. +- sha256: move assign to the declaration line - Closes #5034 + Follow-up to fae30656. Should've been squashed with that commit... -- appveyor: sort builds by type and add two new variants - - Related to #5034 and #5063 +- [Siva Sivaraman brought this change] -- appveyor: show failed tests in log even if test is ignored + sha256: fixed potentially uninitialized variable - And print API response with newline only if there is one - -- appveyor: turn disabled tests into ignored result tests + Closes #5414 -Daniel Stenberg (5 Apr 2020) -- KNOWN_BUGS: fixed "USE_UNIX_SOCKETS on Windows" +- sendf: make failf() use the mvsnprintf() return code - Fixed with #5170 (commit 23a870f2fd041278) + ... and avoid a strlen() call. Fixes a MonocleAI warning. + + Reported-by: MonocleAI + Fixes #5413 + Closes #5420 -- test1566: verify --etag-compare that gets a 304 back +- hostip: make Curl_printable_address not return anything - Verifies the fix in #5183 + It was not used much anyway and instead we let it store a blank buffer + in case of failure. - Closes #5186 - -- [Kwon-Young Choi brought this change] + Reported-by: MonocleAI + Fixes #5411 + Closes #5418 - CURLINFO_CONDITION_UNMET: return true for 304 http status code +- ftp: mark return-ignoring calls to Curl_GetFTPResponse with (void) - In libcurl, CURLINFO_CONDITION_UNMET is used to avoid writing to the - output file if the server did not transfered a file based on time - condition. In the same manner, getting a 304 HTTP response back from the - server, for example after passing a custom If-Match-* header, also - fulfill this condition. + They're done on purpose, make that visible in the code. + Reported-by: MonocleAI + Fixes #5412 + Closes #549 + +- TODO: forbid TLS post-handshake auth and do TLS record padding - Fixes #5181 - Closes #5183 + Closes #5396 + Closes #5398 -- [Kwon-Young Choi brought this change] +- RELEASE-NOTES: synced - curl: allow both --etag-compare and --etag-save with same file name - - This change inverse the order of processing for the --etag-compare and - --etag-save option to process first --etag-compare. This in turn allows - to use the same file name to compare and save an etag. +- dynbuf: return NULL when there's no buffer length - The original behavior of not failing if the etag file does not exists is - conserved. + ... as returning a "" is not a good idea as the string is supposed to be + allocated and returning a const string will cause issues. - Fixes #5179 - Closes #5180 + Reported-by: Brian Carpenter + Follow-up to ed35d6590e72c + Closes #5405 -Viktor Szakats (4 Apr 2020) -- windows: enable UnixSockets with all build toolchains - - Extend existing unix socket support in Windows builds to be - enabled for all toolchain vendors or versions. (Previously - it was only supported with certain MSVC versions + more recent - Windows 10 SDKs) +Peter Wu (16 May 2020) +- travis: upgrade to bionic, clang-9, improve readability - Ref: https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ - Ref: https://github.com/curl/curl/issues/5162 - Closes: https://github.com/curl/curl/pull/5170 - -Daniel Stenberg (4 Apr 2020) -- KNOWN_BUGS: Store TLS context per transfer instead of per connection + Changes, partially to reduce build failures from external dependencies: + - Upgrade Ubuntu and drop unnecessary third-party repos. + - Properly clone apt config to ensure retries. + - Upgrade to clang-9 from the standard repos. + - Use Ubuntu 20.04 focal for the libssh build, use of ssh_get_publickey + fails on -Werror=deprecated-declarations in Ubuntu 18.04. Do not use + focal everywhere yet since Travis CI has not documented this option. + In focal, python-impacket (Py2.7) has been removed, leaving only + python3-impacket. Since it is only needed for SMB tests and not SSH, + skip it for the libssh job since it might need more work. + - apt: Remove gcc-8 and libstdc++-8-dev, already installed via g++-8. - Closes #5102 - -Marc Hoersken (3 Apr 2020) -- sockfilt: remove redundancy in timeout handling + Non-functional cleanups: + - Simplify test matrix, drop redundant os and compiler keys. + - Deprecation fixes: remove sudo, rename matrix -> jobs. + - Every job has an 'env' key, put this key first in a list item. - And update other logmsg output in select_ws on Windows. + Closes #5370 -- sockfilt: fix handling of ready closed sockets on Windows - - Replace the incomplete workaround regarding FD_CLOSE - only signalling once by instead doing a pre-check with - standard select and storing the result for later use. +- travis: whitespace-only changes for consistency - select keeps triggering on closed sockets on Windows while - WSAEventSelect fires only once with data still available. - By doing the pre-check we do not run in a deadlock - due to waiting forever for another FD_CLOSE event. - -- sockfilt: fix race-condition of waiting threads and event handling + Automatically apply a consistent indentation with: - Fix race-condition of waiting threads finishing while events are - already being processed which lead to invalid or skipped events. + python3 -c 'from ruamel.yaml import YAML;y=YAML();d=y.load(open(".travis.yml"));y.width=500;y.dump(d,open(".travis.yml.new","w"))' - Use mutex to check for one event at a time or do post-processing. - In addition to mutex-based locking use specific event as signal. + followed by manually re-indenting three comments. - Closes #5156 - -Daniel Stenberg (2 Apr 2020) -- [Leo Neat brought this change] + Closes #5370 - CI-fuzz: increase fuzz time to 40 minutes +- CMake: add libssh build support - Closes #5174 + Closes #5372 -Marc Hoersken (2 Apr 2020) -- CI: increase Azure Pipelines timeouts due to performance issues +Daniel Stenberg (15 May 2020) +- KNOWN_BUGS: wolfssh: publickey auth doesn't work - The current demand on Azure negatively impacts the CI performance. - -- runtests.pl: log host OS as detected by Perl environment - -- ftpserver.pl: log before and after data connection is closed - -Daniel Stenberg (1 Apr 2020) -- RELEASE-NOTES: synced - -- RELEASE-PROCEDURE.md: run the copyright.pl script! + Closes #4820 -- vquic/ngtcp2.h: update copyright year range +- KNOWN_BUGS: OS400 port requires deprecated IBM library - Follow-up to 0736ee73d346a52 - -- [Daiki Ueno brought this change] - - CI: add build with ngtcp2 + gnutls on Travis CI + Closes #5176 -- [Daiki Ueno brought this change] +- [Vyron Tsingaras brought this change] - vquic: add support for GnuTLS backend of ngtcp2 - - Currently, the TLS backend used by vquic/ngtcp2.c is selected at compile - time. Therefore OpenSSL support needs to be explicitly disabled. + http2: keep trying to send pending frames after req.upload_done - Signed-off-by: Daiki Ueno - Closes #5148 + Fixes #1410 + Closes #5401 -- [Gisle Vanem brought this change] +- [Gilles Vollant brought this change] - examples/sessioninfo.c: add include to fix compiler warning + setopt: support certificate options in memory with struct curl_blob - Fixes #5171 - -- misc: copyright year updates + This change introduces a generic way to provide binary data in setopt + options, called BLOBs. - Follow-up to 7a71965e9 - -- [Harry Sintonen brought this change] - - build: fixed build for systems with select() in unistd.h + This change introduces these new setopts: - Closes #5169 - -- memdebug: don't log free(NULL) + CURLOPT_ISSUERCERT_BLOB, CURLOPT_PROXY_SSLCERT_BLOB, + CURLOPT_PROXY_SSLKEY_BLOB, CURLOPT_SSLCERT_BLOB and CURLOPT_SSLKEY_BLOB. - ... it serves no purpose and fills up the log. + Reviewed-by: Daniel Stenberg + Closes #5357 -- cleanup: insert newline after if() conditions +- source cleanup: remove all custom typedef structs - Our code style mandates we put the conditional block on a separate - line. These mistakes are now detected by the updated checksrc. - -- checksrc: warn on obvious conditional blocks on the same line as if() + - Stick to a single unified way to use structs + - Make checksrc complain on 'typedef struct {' + - Allow them in tests, public headers and examples - Closes #5164 - -- [Roger Orr brought this change] - - cmake: add CMAKE_MSVC_RUNTIME_LIBRARY + - Let MD4_CTX, MD5_CTX, and SHA256_CTX typedefs remain as they actually + typedef different types/structs depending on build conditions. - Fixes #5165 - Closes #5167 + Closes #5338 -- [Daiki Ueno brought this change] +- travis: remove the .checksrc fiddling - ngtcp2: update to git master for the key installation API change - - This updates the ngtcp2 OpenSSL backend to follow the API change in - commit 32e703164 of ngtcp2. - - Notable changes are: - - ngtcp2_crypto_derive_and_install_{rx,tx}_key have been added to replace - ngtcp2_crypto_derive_and_install_key - - the 'side' argument of ngtcp2_crypto_derive_and_install_initial_key - has been removed +- ftp: make domore_getsock() return the secondary socket properly - Fixes #5166 - Closes #5168 + Previously, after PASV and immediately after the data connection has + connected, the function would only return the control socket to wait for + which then made the data connection simply timeout and not get polled + correctly. This become obvious when running test 1631 and 1632 event- + based. -- [Cyrus brought this change] +- test1632: verify FTP through HTTPS-proxy with connection re-use - SECURITY.md: minor rephrase - - Closes #5158 +- test1631: verify FTP download through HTTPS-proxy -- output.d: quote the URL when globbing +- sws: as last resort, get test number from server cmd file - Some shells do globbing of their own unless the URL is quoted, so maybe - encourage this. + If it can't be found in the request. Also support --cmdfile to set it to + a custom file name. - Co-authored-by: Jay Satiro - Closes #5160 + runtests.pl always writes this file with the test number in it since a + while back. -- dist: add tests/version-scan.pl to tarball - - ... used in test 1177. +- ftp: shut down the secondary connection properly when SSL is used - Follow-up to a97d826f6de3 - -- test1177: verify that all the CURL_VERSION_ bits are documented + Reported-by: Neal Poole + Fixes #5340 + Closes #5385 -- curl.h: remnove CURL_VERSION_ESNI. Never supported nor documented +Marcel Raad (14 May 2020) +- KNOWN_BUGS: adapt 5.5 to recent changes - Considered experimental and therefore we can do this. + It only applies to non-Unicode builds now. + Also merge 5.10 into it as it's effectively a duplicate. - Closes #5157 + Closes https://github.com/curl/curl/pull/3784 -- KNOWN_BUGS: DoH doesn't inherit all transfer options +- curl_setup: support Unicode functions to open files on Windows - Closes #4578 - Closes #4579 - -- KNOWN_BUGS: DoH leaks memory after followlocation + Use them only if `_UNICODE` is defined, in which case command-line + arguments have been converted to UTF-8. - Closes #4592 + Closes https://github.com/curl/curl/pull/3784 -- KNOWN_BUGS: "FTPS needs session reuse" +- tool: support UTF-16 command line on Windows - Closes #4654 - -- KNOWN_BUGS: "stick to same family over SOCKS pro" is presumed fixed - -- TODO: Set custom client ip when using haproxy protocol + - use `wmain` instead of `main` when `_UNICODE` is defined [0] + - define `argv_item_t` as `wchar_t *` in this case + - use the curl_multibyte gear to convert the command-line arguments to + UTF-8 - Closes #5125 - -Michael Kaufmann (27 Mar 2020) -- writeout_json: Fix data type issues + This makes it possible to pass parameters with characters outside of + the current locale on Windows, which is required for some tests, e.g. + the IDN tests. Out of the box, this currently only works with the + Visual Studio project files, which default to Unicode, and winbuild + with the `ENABLE_UNICODE` option. - Load long values correctly (e.g. for http_code). + [0] https://devblogs.microsoft.com/oldnewthing/?p=40643 - Use curl_off_t (not long) for: - - size_download (CURLINFO_SIZE_DOWNLOAD_T) - - size_upload (CURLINFO_SIZE_UPLOAD_T) + Ref: https://github.com/curl/curl/issues/3747 + Closes https://github.com/curl/curl/pull/3784 + +- curl_multibyte: add to curlx - The unit for these values is bytes/second, not microseconds: - - speed_download (CURLINFO_SPEED_DOWNLOAD_T) - - speed_upload (CURLINFO_SPEED_UPLOAD_T) + This will also be needed in the tool and tests. - Fixes #5131 - Closes #5152 + Ref: https://github.com/curl/curl/pull/3758#issuecomment-482197512 + Closes https://github.com/curl/curl/pull/3784 -Daniel Stenberg (27 Mar 2020) -- mailmap: fixup a few author names/fields +Daniel Stenberg (14 May 2020) +- url: make the updated credentials URL-encoded in the URL - Douglas Steinwand, Gökhan Şengün, Jessa Chandler, Julian Z and - Svyatoslav Mishyn + Found-by: Gregory Jefferis + Reported-by: Jeroen Ooms + Added test 1168 to verify. Bug spotted when doing a redirect. + Bug: https://github.com/jeroen/curl/issues/224 + Closes #5400 -- version: add 'cainfo' and 'capath' to version info struct +- tests: add https-proxy support to the test suite - Suggested-by: Timothe Litt - URL: https://curl.haxx.se/mail/lib-2020-03/0090.html - Reviewed-by: Jay Satiro + Initial test 1630 added with basic HTTPS-proxy use. HTTPS-proxy is like + HTTP proxy but with a full TLS connection to the proxy. - Closes #5150 + Closes #5399 -- RELEASE-NOTES: synced +- mailmap: James Fuller + +- [Major_Tom brought this change] -Jay Satiro (26 Mar 2020) -- SSLCERTS.md: Fix example code for setting CA cert file + vauth/cleartext: fix theoretical integer overflow - Prior to this change the documentation erroneously said use - CURLOPT_CAPATH to set a CA cert file. + Fix theoretical integer overflow in Curl_auth_create_plain_message. - Bug: https://curl.haxx.se/mail/lib-2020-03/0121.html - Reported-by: Timothe Litt + The security impact of the overflow was discussed on hackerone. We + agreed this is more of a theoretical vulnerability, as the integer + overflow would only be triggerable on systems using 32-bits size_t with + over 4GB of available memory space for the process. - Closes https://github.com/curl/curl/pull/5151 + Closes #5391 -Marc Hoersken (26 Mar 2020) -- sockfilt: add logmsg output to select_ws_wait_thread on Windows +Jay Satiro (13 May 2020) +- curl.1: Quote globbed URLs - Assisted-by: Jay Satiro - Reviewed-by: Daniel Stenberg + - Quote the globbing example URLs that contain characters [] {} since + otherwise they may be interpreted as shell metacharacters. - Closes #5086 + Bug: https://github.com/curl/curl/issues/5388 + Reported-by: John Simpson + + Closes https://github.com/curl/curl/pull/5394 -Daniel Stenberg (26 Mar 2020) -- docs/make: generate curl.1 from listed files only +Daniel Stenberg (14 May 2020) +- checksrc: enhance the ASTERISKSPACE and update code accordingly - Previously it rendered the page from files matching "*.d" in the correct - directory, which worked fine in git builds when the files were added but - made it easy to forget adding the files to the dist. + Fine: "struct hello *world" - Now, only man page sections listed in DPAGES in Makefile.inc will be - used, thus "forcing" us to update this to get the man page right and get - it included in the dist at the same time. + Not fine: "struct hello* world" (and variations) - Ref: #5146 - Closes #5149 + Closes #5386 -- openssl: adapt to functions marked as deprecated since version 3 - - OpenSSL 3 deprecates SSL_CTX_load_verify_locations and the MD4, DES - functions we use. - - Fix the MD4 and SSL_CTX_load_verify_locations warnings. +- docs/options-in-versions: which version added each cmdline option - In configure, detect OpenSSL v3 and if so, inhibit the deprecation - warnings. OpenSSL v3 deprecates the DES functions we use for NTLM and - until we rewrite the code to use non-deprecated functions we better - ignore these warnings as they don't help us. + Added test 971 to verify that the list is in sync with the files in + cmdline-opts. The check also verifies that .d-files that uses Added: + specify the same version number as the options-in-versions file does. - Closes #5139 + Closes #5381 -- dist: add mail-rcpt-allowfails.d to the tarball +- docs: unify protocol lists - Reported-by: Maksim Stsepanenka - Reviewed-by: Jat Satiro + We boast support for 25 transfer protocols. Make sure the lists are + consistent - Closes #5146 + Closes #5384 diff --git a/libs/libcurl/docs/COPYING b/libs/libcurl/docs/COPYING index 9d9e4af8d8..48f144758e 100644 --- a/libs/libcurl/docs/COPYING +++ b/libs/libcurl/docs/COPYING @@ -1,6 +1,6 @@ COPYRIGHT AND PERMISSION NOTICE -Copyright (c) 1996 - 2020, Daniel Stenberg, , and many +Copyright (c) 1996 - 2021, Daniel Stenberg, , and many contributors, see the THANKS file. All rights reserved. diff --git a/libs/libcurl/docs/THANKS b/libs/libcurl/docs/THANKS index fcac1f5f30..69c3c11dca 100644 --- a/libs/libcurl/docs/THANKS +++ b/libs/libcurl/docs/THANKS @@ -4,6 +4,7 @@ If you have contributed but are missing here, please let us know! +0xflotus on github 1ocalhost on github 3dyd on github Aaro Koskinen @@ -151,6 +152,7 @@ Andrew Moise Andrew Potter Andrew Robbins Andrew Wansink +Andrey Gursky Andrey Labunets Andrii Moiseiev Andrius Merkys @@ -305,6 +307,7 @@ Bruno Thomsen Bryan Henderson Bryan Kemp bsammon on github +Bubu on github buzo-ffm on github bxac on github Bylon2 on github @@ -489,6 +492,7 @@ David Blaikie David Byron David Cohen David E. Narváez +David Earl David Eriksson David Garske David Houlder @@ -525,6 +529,7 @@ Denis Baručić Denis Chaplygin Denis Feklushkin Denis Goleshchikhin +Denis Laxalde Denis Ollier Dennis Clarke Dennis Felsing @@ -569,6 +574,7 @@ Dmitry Mikhirev Dmitry Popov Dmitry Rechkin Dmitry S. Baikov +Dmitry Wagin dnivras on github Dolbneff A.V Domenico Andreoli @@ -585,6 +591,7 @@ Douglas E. Wegscheid Douglas Kilpatrick Douglas Mencken Douglas R. Horner +Douglas R. Reno Douglas Steinwand Dov Murik dpull on github @@ -661,6 +668,7 @@ Erik Jacobsen Erik Janssen Erik Johansson Erik Minekus +Erik Olsson Ernest Beinrohr Ernst Sjöstrand Erwan Legrand @@ -698,6 +706,7 @@ Felix Yan Feng Tu Fernando Muñoz Filip Salomonsson +Flameborn on github Flavio Medeiros Florian Pritz Florian Schoppmann @@ -731,6 +740,7 @@ FuccDucc on github fullincome on github Gabriel Kuri Gabriel Sjoberg +Ganesh Kamath Garrett Holmstrom Gary Maxwell Gaurav Malhotra @@ -811,6 +821,7 @@ Hannes Magnusson Hanno Böck Hanno Kranzhoff Hans Steegers +Hans-Christian Noren Egtvedt Hans-Jurgen May Hao Wu Hardeep Singh @@ -834,9 +845,11 @@ Henry Ludemann Henry Roeland Herve Amblard Hidemoto Nakada +Himanshu Gupta Ho-chi Chen Hoi-Ho Chan Hongli Lai +Hongyi Zhao Howard Blaise Howard Chu hsiao yi @@ -853,6 +866,7 @@ Ian Fette Ian Ford Ian Gulliver Ian Lynagh +Ian Spence Ian Turner Ian Wilkes Ignacio Vazquez-Abrams @@ -864,6 +878,7 @@ Igor Polyakov Ihor Karpenko ihsinme on github Iida Yosiaki +Ikko Ashimine Ilguiz Latypov Ilja van Sprundel Ilya Kosarev @@ -978,6 +993,7 @@ Jeremy Lin Jeremy Maitin-Shepard Jeremy Pearson Jeremy Tan +Jeremy Thibault Jeroen Koekkoek Jeroen Ooms Jerome Muffat-Meridol @@ -1065,6 +1081,7 @@ Jon Spencer Jon Torrey Jon Travis Jon Turner +Jon Wilkes Jonas Forsman Jonas Minnberg Jonas Schnelli @@ -1100,6 +1117,7 @@ Judson Bishop Juergen Hoetzel Juergen Wilke Jukka Pihl +Julian Montes Julian Noble Julian Ospald Julian Romero Nieto @@ -1163,6 +1181,7 @@ Kevin R. Bulgrien Kevin Reed Kevin Roth Kevin Smith +Kevin Ushey Kim Minjoong Kim Rinnewitz Kim Vandry @@ -1378,6 +1397,7 @@ Mathieu Legare Mats Lidell Matt Arsenault Matt Ford +Matt Holt Matt Kraai Matt McClure Matt Veenstra @@ -1392,6 +1412,7 @@ Matthew Hall Matthew Kerwin Matthew Whitehead Matthias Bolte +Matthias Gatto Matthias Naegler Mattias Fornander Matus Uzak @@ -1473,6 +1494,7 @@ Mike Crowe Mike Dobbs Mike Dowell Mike Frysinger +Mike Gelfand Mike Giancola Mike Hasselberg Mike Henshaw @@ -1482,6 +1504,7 @@ Mike Norton Mike Power Mike Protts Mike Revi +Mike Tzou Miklos Nemeth Miloš Ljumović Mingliang Zhu @@ -1576,6 +1599,7 @@ Ofer Okhin Vasilij Ola Mork Olaf Flebbe +Olaf Hering Olaf Stüben Oleg Pudeyev Olen Andoni @@ -1606,6 +1630,7 @@ Palo Markovic Paolo Mossino Paolo Piacentini Paras Sethia +parazyd on github Pascal Gaudette Pascal Terjan Pasha Kuznetsov @@ -1886,6 +1911,7 @@ Ryan Winograd Ryuichi KAWAMATA Rémy Léone S. Moonesamy +Sai Ram Kunala Salah-Eddin Shaban Saleem Abdulrasool Salvador Dávila @@ -1922,6 +1948,7 @@ Scott McCreary Sean Boudreau Sean Burford Sean MacLennan +Sean McArthur Sean Miller Sebastiaan van Erk Sebastian Haglund @@ -2180,6 +2207,7 @@ Ulf Samuelsson Ulrich Doehner Ulrich Telle Ulrich Zadow +UrsusArctos on github Valentin David Valentyn Korniienko Valerii Zapodovnikov @@ -2247,6 +2275,7 @@ Wouter Van Rooy Wu Yongzheng Wyatt O'Day Xavier Bouchoux +XhmikosR on github XhstormR on github Xiang Xiao Xiangbin Li @@ -2295,4 +2324,5 @@ zzq1015 on github Štefan Kremeň Коваленко Анатолий Викторович Никита Дорохин +不确定 加藤郁之 diff --git a/libs/libcurl/include/curl/curl.h b/libs/libcurl/include/curl/curl.h index a73418dcea..71204ee327 100644 --- a/libs/libcurl/include/curl/curl.h +++ b/libs/libcurl/include/curl/curl.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -787,6 +787,7 @@ typedef enum { #define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) #define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) #define CURLAUTH_BEARER (((unsigned long)1)<<6) +#define CURLAUTH_AWS_SIGV4 (((unsigned long)1)<<7) #define CURLAUTH_ONLY (((unsigned long)1)<<31) #define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) #define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) @@ -1015,6 +1016,7 @@ typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy, #define CURLPROTO_SMB (1<<26) #define CURLPROTO_SMBS (1<<27) #define CURLPROTO_MQTT (1<<28) +#define CURLPROTO_GOPHERS (1<<29) #define CURLPROTO_ALL (~0) /* enable everything */ /* long may be 32 or 64 bits, but we should never depend on anything else @@ -1614,7 +1616,7 @@ typedef enum { CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159), CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160), - /* Set the behaviour of POST when redirecting. Values must be set to one + /* Set the behavior of POST when redirecting. Values must be set to one of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_VALUES, 161), @@ -2073,6 +2075,9 @@ typedef enum { CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303), CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304), + /* Parameters for V4 signature */ + CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; @@ -2849,6 +2854,7 @@ typedef enum { CURLVERSION_SIXTH, CURLVERSION_SEVENTH, CURLVERSION_EIGHTH, + CURLVERSION_NINTH, CURLVERSION_LAST /* never actually use this */ } CURLversion; @@ -2857,7 +2863,7 @@ typedef enum { meant to be a built-in version number for what kind of struct the caller expects. If the struct ever changes, we redefine the NOW to another enum from above. */ -#define CURLVERSION_NOW CURLVERSION_EIGHTH +#define CURLVERSION_NOW CURLVERSION_NINTH struct curl_version_info_data { CURLversion age; /* age of the returned struct */ @@ -2908,6 +2914,8 @@ struct curl_version_info_data { (MAJOR << 24) | (MINOR << 12) | PATCH */ const char *zstd_version; /* human readable string. */ + /* These fields were added in CURLVERSION_NINTH */ + const char *hyper_version; /* human readable string. */ }; typedef struct curl_version_info_data curl_version_info_data; diff --git a/libs/libcurl/include/curl/curlver.h b/libs/libcurl/include/curl/curlver.h index 0acb5a8cbf..81e9aa3429 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.74.0" +#define LIBCURL_VERSION "7.75.0" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 7 -#define LIBCURL_VERSION_MINOR 74 +#define LIBCURL_VERSION_MINOR 75 #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 0x074a00 +#define LIBCURL_VERSION_NUM 0x074b00 /* * This is the date and time when the full source package was created. The @@ -68,7 +68,7 @@ * * "2007-11-23" */ -#define LIBCURL_TIMESTAMP "2020-12-09" +#define LIBCURL_TIMESTAMP "2021-02-03" #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 6d84150dc2..230f4c1067 100644 --- a/libs/libcurl/include/curl/typecheck-gcc.h +++ b/libs/libcurl/include/curl/typecheck-gcc.h @@ -334,6 +334,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t, (option) == CURLOPT_URL || \ (option) == CURLOPT_USERAGENT || \ (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_AWS_SIGV4 || \ (option) == CURLOPT_USERPWD || \ (option) == CURLOPT_XOAUTH2_BEARER || \ (option) == CURLOPT_SSL_EC_CURVES || \ diff --git a/libs/libcurl/libcurl.vcxproj b/libs/libcurl/libcurl.vcxproj index 13e026a676..7677636521 100644 --- a/libs/libcurl/libcurl.vcxproj +++ b/libs/libcurl/libcurl.vcxproj @@ -41,6 +41,9 @@ NotUsing + + NotUsing + NotUsing @@ -182,6 +185,9 @@ NotUsing + + NotUsing + NotUsing @@ -435,6 +441,7 @@ + @@ -498,6 +505,7 @@ + diff --git a/libs/libcurl/libcurl.vcxproj.filters b/libs/libcurl/libcurl.vcxproj.filters index 7c975c65db..9a6fcc2b65 100644 --- a/libs/libcurl/libcurl.vcxproj.filters +++ b/libs/libcurl/libcurl.vcxproj.filters @@ -17,6 +17,9 @@ Source Files + + Source Files + Source Files @@ -155,6 +158,9 @@ Source Files + + Source Files + Source Files @@ -457,6 +463,9 @@ Header Files + + Header Files + Header Files @@ -643,6 +652,9 @@ Header Files + + Header Files + Header Files diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in index ce7fe0d34f..2960c281cf 100644 --- a/libs/libcurl/src/Makefile.in +++ b/libs/libcurl/src/Makefile.in @@ -21,7 +21,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. +# Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -181,30 +181,33 @@ LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) libcurl_la_LIBADD = am__objects_1 = libcurl_la-altsvc.lo libcurl_la-amigaos.lo \ libcurl_la-asyn-ares.lo libcurl_la-asyn-thread.lo \ - libcurl_la-base64.lo libcurl_la-conncache.lo \ - libcurl_la-connect.lo libcurl_la-content_encoding.lo \ - libcurl_la-cookie.lo libcurl_la-curl_addrinfo.lo \ - libcurl_la-curl_ctype.lo libcurl_la-curl_des.lo \ - libcurl_la-curl_endian.lo libcurl_la-curl_fnmatch.lo \ - libcurl_la-curl_get_line.lo libcurl_la-curl_gethostname.lo \ - libcurl_la-curl_gssapi.lo libcurl_la-curl_memrchr.lo \ - libcurl_la-curl_multibyte.lo libcurl_la-curl_ntlm_core.lo \ - libcurl_la-curl_ntlm_wb.lo libcurl_la-curl_path.lo \ - libcurl_la-curl_range.lo libcurl_la-curl_rtmp.lo \ - libcurl_la-curl_sasl.lo libcurl_la-curl_sspi.lo \ - libcurl_la-curl_threads.lo libcurl_la-dict.lo \ - libcurl_la-dotdot.lo libcurl_la-easy.lo libcurl_la-escape.lo \ - libcurl_la-file.lo libcurl_la-fileinfo.lo \ - libcurl_la-formdata.lo libcurl_la-ftp.lo libcurl_la-url.lo \ + libcurl_la-base64.lo libcurl_la-c-hyper.lo \ + libcurl_la-conncache.lo libcurl_la-connect.lo \ + libcurl_la-content_encoding.lo libcurl_la-cookie.lo \ + libcurl_la-curl_addrinfo.lo libcurl_la-curl_ctype.lo \ + libcurl_la-curl_des.lo libcurl_la-curl_endian.lo \ + libcurl_la-curl_fnmatch.lo libcurl_la-curl_get_line.lo \ + libcurl_la-curl_gethostname.lo libcurl_la-curl_gssapi.lo \ + libcurl_la-curl_memrchr.lo libcurl_la-curl_multibyte.lo \ + libcurl_la-curl_ntlm_core.lo libcurl_la-curl_ntlm_wb.lo \ + libcurl_la-curl_path.lo libcurl_la-curl_range.lo \ + libcurl_la-curl_rtmp.lo libcurl_la-curl_sasl.lo \ + libcurl_la-curl_sspi.lo libcurl_la-curl_threads.lo \ + libcurl_la-dict.lo libcurl_la-doh.lo libcurl_la-dotdot.lo \ + libcurl_la-dynbuf.lo libcurl_la-easy.lo \ + libcurl_la-easygetopt.lo libcurl_la-easyoptions.lo \ + libcurl_la-escape.lo libcurl_la-file.lo libcurl_la-fileinfo.lo \ + libcurl_la-formdata.lo libcurl_la-ftp.lo \ libcurl_la-ftplistparser.lo libcurl_la-getenv.lo \ libcurl_la-getinfo.lo libcurl_la-gopher.lo libcurl_la-hash.lo \ libcurl_la-hmac.lo libcurl_la-hostasyn.lo \ libcurl_la-hostcheck.lo libcurl_la-hostip.lo \ libcurl_la-hostip4.lo libcurl_la-hostip6.lo \ - libcurl_la-hostsyn.lo libcurl_la-http.lo libcurl_la-http2.lo \ - libcurl_la-http_chunks.lo libcurl_la-http_digest.lo \ - libcurl_la-http_negotiate.lo libcurl_la-http_ntlm.lo \ - libcurl_la-http_proxy.lo libcurl_la-idn_win32.lo \ + libcurl_la-hostsyn.lo libcurl_la-hsts.lo libcurl_la-http.lo \ + libcurl_la-http2.lo libcurl_la-http_chunks.lo \ + libcurl_la-http_digest.lo libcurl_la-http_negotiate.lo \ + libcurl_la-http_ntlm.lo libcurl_la-http_proxy.lo \ + libcurl_la-http_aws_sigv4.lo libcurl_la-idn_win32.lo \ libcurl_la-if2ip.lo libcurl_la-imap.lo libcurl_la-inet_ntop.lo \ libcurl_la-inet_pton.lo libcurl_la-krb5.lo libcurl_la-ldap.lo \ libcurl_la-llist.lo libcurl_la-md4.lo libcurl_la-md5.lo \ @@ -214,23 +217,20 @@ am__objects_1 = libcurl_la-altsvc.lo libcurl_la-amigaos.lo \ libcurl_la-nonblock.lo libcurl_la-openldap.lo \ libcurl_la-parsedate.lo libcurl_la-pingpong.lo \ libcurl_la-pop3.lo libcurl_la-progress.lo libcurl_la-psl.lo \ - libcurl_la-doh.lo libcurl_la-rand.lo libcurl_la-rename.lo \ - libcurl_la-rtsp.lo libcurl_la-select.lo libcurl_la-sendf.lo \ - libcurl_la-setopt.lo libcurl_la-sha256.lo libcurl_la-share.lo \ - libcurl_la-slist.lo libcurl_la-smb.lo libcurl_la-smtp.lo \ - libcurl_la-socketpair.lo libcurl_la-socks.lo \ - libcurl_la-socks_gssapi.lo libcurl_la-socks_sspi.lo \ - libcurl_la-speedcheck.lo libcurl_la-splay.lo \ - libcurl_la-strcase.lo libcurl_la-strdup.lo \ + libcurl_la-rand.lo libcurl_la-rename.lo libcurl_la-rtsp.lo \ + libcurl_la-select.lo libcurl_la-sendf.lo libcurl_la-setopt.lo \ + libcurl_la-sha256.lo libcurl_la-share.lo libcurl_la-slist.lo \ + libcurl_la-smb.lo libcurl_la-smtp.lo libcurl_la-socketpair.lo \ + libcurl_la-socks.lo libcurl_la-socks_gssapi.lo \ + libcurl_la-socks_sspi.lo libcurl_la-speedcheck.lo \ + libcurl_la-splay.lo libcurl_la-strcase.lo libcurl_la-strdup.lo \ libcurl_la-strerror.lo libcurl_la-strtok.lo \ libcurl_la-strtoofft.lo libcurl_la-system_win32.lo \ libcurl_la-telnet.lo libcurl_la-tftp.lo libcurl_la-timeval.lo \ - libcurl_la-transfer.lo libcurl_la-urlapi.lo \ - libcurl_la-version.lo libcurl_la-warnless.lo \ - libcurl_la-wildcard.lo libcurl_la-x509asn1.lo \ - libcurl_la-dynbuf.lo libcurl_la-version_win32.lo \ - libcurl_la-easyoptions.lo libcurl_la-easygetopt.lo \ - libcurl_la-hsts.lo + libcurl_la-transfer.lo libcurl_la-url.lo libcurl_la-urlapi.lo \ + libcurl_la-version.lo libcurl_la-version_win32.lo \ + libcurl_la-warnless.lo libcurl_la-wildcard.lo \ + libcurl_la-x509asn1.lo am__dirstamp = $(am__leading_dot)dirstamp am__objects_2 = vauth/libcurl_la-cleartext.lo vauth/libcurl_la-cram.lo \ vauth/libcurl_la-digest.lo vauth/libcurl_la-digest_sspi.lo \ @@ -268,43 +268,45 @@ libcurl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ libcurlu_la_LIBADD = am__objects_9 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \ libcurlu_la-asyn-ares.lo libcurlu_la-asyn-thread.lo \ - libcurlu_la-base64.lo libcurlu_la-conncache.lo \ - libcurlu_la-connect.lo libcurlu_la-content_encoding.lo \ - libcurlu_la-cookie.lo libcurlu_la-curl_addrinfo.lo \ - libcurlu_la-curl_ctype.lo libcurlu_la-curl_des.lo \ - libcurlu_la-curl_endian.lo libcurlu_la-curl_fnmatch.lo \ - libcurlu_la-curl_get_line.lo libcurlu_la-curl_gethostname.lo \ - libcurlu_la-curl_gssapi.lo libcurlu_la-curl_memrchr.lo \ - libcurlu_la-curl_multibyte.lo libcurlu_la-curl_ntlm_core.lo \ - libcurlu_la-curl_ntlm_wb.lo libcurlu_la-curl_path.lo \ - libcurlu_la-curl_range.lo libcurlu_la-curl_rtmp.lo \ - libcurlu_la-curl_sasl.lo libcurlu_la-curl_sspi.lo \ - libcurlu_la-curl_threads.lo libcurlu_la-dict.lo \ - libcurlu_la-dotdot.lo libcurlu_la-easy.lo \ + libcurlu_la-base64.lo libcurlu_la-c-hyper.lo \ + libcurlu_la-conncache.lo libcurlu_la-connect.lo \ + libcurlu_la-content_encoding.lo libcurlu_la-cookie.lo \ + libcurlu_la-curl_addrinfo.lo libcurlu_la-curl_ctype.lo \ + libcurlu_la-curl_des.lo libcurlu_la-curl_endian.lo \ + libcurlu_la-curl_fnmatch.lo libcurlu_la-curl_get_line.lo \ + libcurlu_la-curl_gethostname.lo libcurlu_la-curl_gssapi.lo \ + libcurlu_la-curl_memrchr.lo libcurlu_la-curl_multibyte.lo \ + libcurlu_la-curl_ntlm_core.lo libcurlu_la-curl_ntlm_wb.lo \ + libcurlu_la-curl_path.lo libcurlu_la-curl_range.lo \ + libcurlu_la-curl_rtmp.lo libcurlu_la-curl_sasl.lo \ + libcurlu_la-curl_sspi.lo libcurlu_la-curl_threads.lo \ + libcurlu_la-dict.lo libcurlu_la-doh.lo libcurlu_la-dotdot.lo \ + libcurlu_la-dynbuf.lo libcurlu_la-easy.lo \ + libcurlu_la-easygetopt.lo libcurlu_la-easyoptions.lo \ libcurlu_la-escape.lo libcurlu_la-file.lo \ libcurlu_la-fileinfo.lo libcurlu_la-formdata.lo \ - libcurlu_la-ftp.lo libcurlu_la-url.lo \ - libcurlu_la-ftplistparser.lo libcurlu_la-getenv.lo \ - libcurlu_la-getinfo.lo libcurlu_la-gopher.lo \ - libcurlu_la-hash.lo libcurlu_la-hmac.lo \ + libcurlu_la-ftp.lo libcurlu_la-ftplistparser.lo \ + libcurlu_la-getenv.lo libcurlu_la-getinfo.lo \ + libcurlu_la-gopher.lo libcurlu_la-hash.lo libcurlu_la-hmac.lo \ libcurlu_la-hostasyn.lo libcurlu_la-hostcheck.lo \ libcurlu_la-hostip.lo libcurlu_la-hostip4.lo \ libcurlu_la-hostip6.lo libcurlu_la-hostsyn.lo \ - libcurlu_la-http.lo libcurlu_la-http2.lo \ + libcurlu_la-hsts.lo libcurlu_la-http.lo libcurlu_la-http2.lo \ libcurlu_la-http_chunks.lo libcurlu_la-http_digest.lo \ libcurlu_la-http_negotiate.lo libcurlu_la-http_ntlm.lo \ - libcurlu_la-http_proxy.lo libcurlu_la-idn_win32.lo \ - libcurlu_la-if2ip.lo libcurlu_la-imap.lo \ - libcurlu_la-inet_ntop.lo libcurlu_la-inet_pton.lo \ - libcurlu_la-krb5.lo libcurlu_la-ldap.lo libcurlu_la-llist.lo \ - libcurlu_la-md4.lo libcurlu_la-md5.lo libcurlu_la-memdebug.lo \ - libcurlu_la-mime.lo libcurlu_la-mprintf.lo libcurlu_la-mqtt.lo \ + libcurlu_la-http_proxy.lo libcurlu_la-http_aws_sigv4.lo \ + libcurlu_la-idn_win32.lo libcurlu_la-if2ip.lo \ + libcurlu_la-imap.lo libcurlu_la-inet_ntop.lo \ + libcurlu_la-inet_pton.lo libcurlu_la-krb5.lo \ + libcurlu_la-ldap.lo libcurlu_la-llist.lo libcurlu_la-md4.lo \ + libcurlu_la-md5.lo libcurlu_la-memdebug.lo libcurlu_la-mime.lo \ + libcurlu_la-mprintf.lo libcurlu_la-mqtt.lo \ libcurlu_la-multi.lo libcurlu_la-netrc.lo \ libcurlu_la-non-ascii.lo libcurlu_la-nonblock.lo \ libcurlu_la-openldap.lo libcurlu_la-parsedate.lo \ libcurlu_la-pingpong.lo libcurlu_la-pop3.lo \ - libcurlu_la-progress.lo libcurlu_la-psl.lo libcurlu_la-doh.lo \ - libcurlu_la-rand.lo libcurlu_la-rename.lo libcurlu_la-rtsp.lo \ + libcurlu_la-progress.lo libcurlu_la-psl.lo libcurlu_la-rand.lo \ + libcurlu_la-rename.lo libcurlu_la-rtsp.lo \ libcurlu_la-select.lo libcurlu_la-sendf.lo \ libcurlu_la-setopt.lo libcurlu_la-sha256.lo \ libcurlu_la-share.lo libcurlu_la-slist.lo libcurlu_la-smb.lo \ @@ -316,12 +318,10 @@ am__objects_9 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \ libcurlu_la-strtok.lo libcurlu_la-strtoofft.lo \ libcurlu_la-system_win32.lo libcurlu_la-telnet.lo \ libcurlu_la-tftp.lo libcurlu_la-timeval.lo \ - libcurlu_la-transfer.lo libcurlu_la-urlapi.lo \ - libcurlu_la-version.lo libcurlu_la-warnless.lo \ - libcurlu_la-wildcard.lo libcurlu_la-x509asn1.lo \ - libcurlu_la-dynbuf.lo libcurlu_la-version_win32.lo \ - libcurlu_la-easyoptions.lo libcurlu_la-easygetopt.lo \ - libcurlu_la-hsts.lo + libcurlu_la-transfer.lo libcurlu_la-url.lo \ + libcurlu_la-urlapi.lo libcurlu_la-version.lo \ + libcurlu_la-version_win32.lo libcurlu_la-warnless.lo \ + libcurlu_la-wildcard.lo libcurlu_la-x509asn1.lo am__objects_10 = vauth/libcurlu_la-cleartext.lo \ vauth/libcurlu_la-cram.lo vauth/libcurlu_la-digest.lo \ vauth/libcurlu_la-digest_sspi.lo \ @@ -371,6 +371,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurl_la-asyn-ares.Plo \ ./$(DEPDIR)/libcurl_la-asyn-thread.Plo \ ./$(DEPDIR)/libcurl_la-base64.Plo \ + ./$(DEPDIR)/libcurl_la-c-hyper.Plo \ ./$(DEPDIR)/libcurl_la-conncache.Plo \ ./$(DEPDIR)/libcurl_la-connect.Plo \ ./$(DEPDIR)/libcurl_la-content_encoding.Plo \ @@ -419,6 +420,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurl_la-hsts.Plo \ ./$(DEPDIR)/libcurl_la-http.Plo \ ./$(DEPDIR)/libcurl_la-http2.Plo \ + ./$(DEPDIR)/libcurl_la-http_aws_sigv4.Plo \ ./$(DEPDIR)/libcurl_la-http_chunks.Plo \ ./$(DEPDIR)/libcurl_la-http_digest.Plo \ ./$(DEPDIR)/libcurl_la-http_negotiate.Plo \ @@ -484,6 +486,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo \ ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo \ ./$(DEPDIR)/libcurlu_la-base64.Plo \ + ./$(DEPDIR)/libcurlu_la-c-hyper.Plo \ ./$(DEPDIR)/libcurlu_la-conncache.Plo \ ./$(DEPDIR)/libcurlu_la-connect.Plo \ ./$(DEPDIR)/libcurlu_la-content_encoding.Plo \ @@ -533,6 +536,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ ./$(DEPDIR)/libcurlu_la-hsts.Plo \ ./$(DEPDIR)/libcurlu_la-http.Plo \ ./$(DEPDIR)/libcurlu_la-http2.Plo \ + ./$(DEPDIR)/libcurlu_la-http_aws_sigv4.Plo \ ./$(DEPDIR)/libcurlu_la-http_chunks.Plo \ ./$(DEPDIR)/libcurlu_la-http_digest.Plo \ ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo \ @@ -845,6 +849,7 @@ USE_ARES = @USE_ARES@ USE_BEARSSL = @USE_BEARSSL@ USE_GNUTLS = @USE_GNUTLS@ USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@ +USE_HYPER = @USE_HYPER@ USE_LIBRTMP = @USE_LIBRTMP@ USE_LIBSSH = @USE_LIBSSH@ USE_LIBSSH2 = @USE_LIBSSH2@ @@ -997,62 +1002,314 @@ libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA) libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS) libcurlu_la_CFLAGS = $(AM_CFLAGS) -LIB_VAUTH_CFILES = vauth/cleartext.c vauth/cram.c vauth/digest.c \ - vauth/digest_sspi.c vauth/krb5_gssapi.c vauth/krb5_sspi.c vauth/ntlm.c \ - vauth/ntlm_sspi.c vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \ +LIB_VAUTH_CFILES = \ + vauth/cleartext.c \ + vauth/cram.c \ + vauth/digest.c \ + vauth/digest_sspi.c \ + vauth/krb5_gssapi.c \ + vauth/krb5_sspi.c \ + vauth/ntlm.c \ + vauth/ntlm_sspi.c \ + vauth/oauth2.c \ + vauth/spnego_gssapi.c \ + vauth/spnego_sspi.c \ vauth/vauth.c -LIB_VAUTH_HFILES = vauth/digest.h vauth/ntlm.h vauth/vauth.h -LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/keylog.c \ - vtls/mbedtls.c vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c \ - vtls/openssl.c vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \ - vtls/vtls.c vtls/wolfssl.c - -LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/keylog.h \ - vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h \ - vtls/openssl.h vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h - -LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c -LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h vquic/vquic.h -LIB_VSSH_CFILES = vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c -LIB_VSSH_HFILES = vssh/ssh.h -LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c \ - conncache.c connect.c content_encoding.c cookie.c curl_addrinfo.c \ - curl_ctype.c curl_des.c curl_endian.c curl_fnmatch.c curl_get_line.c \ - curl_gethostname.c curl_gssapi.c curl_memrchr.c curl_multibyte.c \ - curl_ntlm_core.c curl_ntlm_wb.c curl_path.c curl_range.c curl_rtmp.c \ - curl_sasl.c curl_sspi.c curl_threads.c dict.c dotdot.c easy.c escape.c \ - file.c fileinfo.c formdata.c ftp.c url.c ftplistparser.c getenv.c getinfo.c \ - gopher.c hash.c hmac.c hostasyn.c hostcheck.c hostip.c hostip4.c hostip6.c \ - hostsyn.c http.c http2.c http_chunks.c http_digest.c http_negotiate.c \ - http_ntlm.c http_proxy.c idn_win32.c if2ip.c imap.c inet_ntop.c inet_pton.c \ - krb5.c ldap.c llist.c md4.c md5.c memdebug.c mime.c mprintf.c mqtt.c \ - multi.c netrc.c non-ascii.c nonblock.c openldap.c parsedate.c pingpong.c \ - pop3.c progress.c psl.c doh.c rand.c rename.c rtsp.c select.c \ - sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \ - socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c \ - strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c \ - transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c \ - version_win32.c easyoptions.c easygetopt.c hsts.c - -LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h \ - content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h \ - curl_des.h curl_endian.h curl_fnmatch.h curl_get_line.h curl_gethostname.h \ - curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memory.h \ - curl_memrchr.h curl_multibyte.h curl_ntlm_core.h curl_ntlm_wb.h curl_path.h \ - curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h curl_krb5.h curl_setup.h \ - curl_setup_once.h curl_sha256.h curl_sspi.h curl_threads.h curlx.h dict.h \ - dotdot.h easyif.h escape.h file.h fileinfo.h formdata.h ftp.h url.h \ - ftplistparser.h getinfo.h gopher.h hash.h hostcheck.h hostip.h http.h \ - http2.h http_chunks.h http_digest.h http_negotiate.h http_ntlm.h \ - http_proxy.h if2ip.h imap.h inet_ntop.h inet_pton.h llist.h memdebug.h \ - mime.h mqtt.h multihandle.h multiif.h netrc.h non-ascii.h nonblock.h \ - parsedate.h pingpong.h pop3.h progress.h psl.h doh.h quic.h rand.h rename.h \ - rtsp.h select.h sendf.h setopt.h setup-vms.h share.h sigpipe.h slist.h \ - smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \ - strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h \ - timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h \ - x509asn1.h dynbuf.h version_win32.h easyoptions.h hsts.h +LIB_VAUTH_HFILES = \ + vauth/digest.h \ + vauth/ntlm.h \ + vauth/vauth.h + +LIB_VTLS_CFILES = \ + vtls/bearssl.c \ + vtls/gskit.c \ + vtls/gtls.c \ + vtls/keylog.c \ + vtls/mbedtls.c \ + vtls/mbedtls_threadlock.c \ + vtls/mesalink.c \ + vtls/nss.c \ + vtls/openssl.c \ + vtls/schannel.c \ + vtls/schannel_verify.c \ + vtls/sectransp.c \ + vtls/vtls.c \ + vtls/wolfssl.c + +LIB_VTLS_HFILES = \ + vtls/bearssl.h \ + vtls/gskit.h \ + vtls/gtls.h \ + vtls/keylog.h \ + vtls/mbedtls.h \ + vtls/mbedtls_threadlock.h \ + vtls/mesalink.h \ + vtls/nssg.h \ + vtls/openssl.h \ + vtls/schannel.h \ + vtls/sectransp.h \ + vtls/vtls.h \ + vtls/wolfssl.h + +LIB_VQUIC_CFILES = \ + vquic/ngtcp2.c \ + vquic/quiche.c \ + vquic/vquic.c + +LIB_VQUIC_HFILES = \ + vquic/ngtcp2.h \ + vquic/quiche.h \ + vquic/vquic.h + +LIB_VSSH_CFILES = \ + vssh/libssh.c \ + vssh/libssh2.c \ + vssh/wolfssh.c + +LIB_VSSH_HFILES = \ + vssh/ssh.h + +LIB_CFILES = \ + altsvc.c \ + amigaos.c \ + asyn-ares.c \ + asyn-thread.c \ + base64.c \ + c-hyper.c \ + conncache.c \ + connect.c \ + content_encoding.c \ + cookie.c \ + curl_addrinfo.c \ + curl_ctype.c \ + curl_des.c \ + curl_endian.c \ + curl_fnmatch.c \ + curl_get_line.c \ + curl_gethostname.c \ + curl_gssapi.c \ + curl_memrchr.c \ + curl_multibyte.c \ + curl_ntlm_core.c \ + curl_ntlm_wb.c \ + curl_path.c \ + curl_range.c \ + curl_rtmp.c \ + curl_sasl.c \ + curl_sspi.c \ + curl_threads.c \ + dict.c \ + doh.c \ + dotdot.c \ + dynbuf.c \ + easy.c \ + easygetopt.c \ + easyoptions.c \ + escape.c \ + file.c \ + fileinfo.c \ + formdata.c \ + ftp.c \ + ftplistparser.c \ + getenv.c \ + getinfo.c \ + gopher.c \ + hash.c \ + hmac.c \ + hostasyn.c \ + hostcheck.c \ + hostip.c \ + hostip4.c \ + hostip6.c \ + hostsyn.c \ + hsts.c \ + http.c \ + http2.c \ + http_chunks.c \ + http_digest.c \ + http_negotiate.c \ + http_ntlm.c \ + http_proxy.c \ + http_aws_sigv4.c \ + idn_win32.c \ + if2ip.c \ + imap.c \ + inet_ntop.c \ + inet_pton.c \ + krb5.c \ + ldap.c \ + llist.c \ + md4.c \ + md5.c \ + memdebug.c \ + mime.c \ + mprintf.c \ + mqtt.c \ + multi.c \ + netrc.c \ + non-ascii.c \ + nonblock.c \ + openldap.c \ + parsedate.c \ + pingpong.c \ + pop3.c \ + progress.c \ + psl.c \ + rand.c \ + rename.c \ + rtsp.c \ + select.c \ + sendf.c \ + setopt.c \ + sha256.c \ + share.c \ + slist.c \ + smb.c \ + smtp.c \ + socketpair.c \ + socks.c \ + socks_gssapi.c \ + socks_sspi.c \ + speedcheck.c \ + splay.c \ + strcase.c \ + strdup.c \ + strerror.c \ + strtok.c \ + strtoofft.c \ + system_win32.c \ + telnet.c \ + tftp.c \ + timeval.c \ + transfer.c \ + url.c \ + urlapi.c \ + version.c \ + version_win32.c \ + warnless.c \ + wildcard.c \ + x509asn1.c + +LIB_HFILES = \ + altsvc.h \ + amigaos.h \ + arpa_telnet.h \ + asyn.h \ + c-hyper.h \ + conncache.h \ + connect.h \ + content_encoding.h \ + cookie.h \ + curl_addrinfo.h \ + curl_base64.h \ + curl_ctype.h \ + curl_des.h \ + curl_endian.h \ + curl_fnmatch.h \ + curl_get_line.h \ + curl_gethostname.h \ + curl_gssapi.h \ + curl_hmac.h \ + curl_krb5.h \ + curl_ldap.h \ + curl_md4.h \ + curl_md5.h \ + curl_memory.h \ + curl_memrchr.h \ + curl_multibyte.h \ + curl_ntlm_core.h \ + curl_ntlm_wb.h \ + curl_path.h \ + curl_printf.h \ + curl_range.h \ + curl_rtmp.h \ + curl_sasl.h \ + curl_setup.h \ + curl_setup_once.h \ + curl_sha256.h \ + curl_sspi.h \ + curl_threads.h \ + curlx.h \ + dict.h \ + doh.h \ + dotdot.h \ + dynbuf.h \ + easyif.h \ + easyoptions.h \ + escape.h \ + file.h \ + fileinfo.h \ + formdata.h \ + ftp.h \ + ftplistparser.h \ + getinfo.h \ + gopher.h \ + hash.h \ + hostcheck.h \ + hostip.h \ + hsts.h \ + http.h \ + http2.h \ + http_chunks.h \ + http_digest.h \ + http_negotiate.h \ + http_ntlm.h \ + http_proxy.h \ + http_aws_sigv4.h \ + if2ip.h \ + imap.h \ + inet_ntop.h \ + inet_pton.h \ + llist.h \ + memdebug.h \ + mime.h \ + mqtt.h \ + multihandle.h \ + multiif.h \ + netrc.h \ + non-ascii.h \ + nonblock.h \ + parsedate.h \ + pingpong.h \ + pop3.h \ + progress.h \ + psl.h \ + quic.h \ + rand.h \ + rename.h \ + rtsp.h \ + select.h \ + sendf.h \ + setopt.h \ + setup-vms.h \ + share.h \ + sigpipe.h \ + slist.h \ + smb.h \ + smtp.h \ + sockaddr.h \ + socketpair.h \ + socks.h \ + speedcheck.h \ + splay.h \ + strcase.h \ + strdup.h \ + strerror.h \ + strtok.h \ + strtoofft.h \ + system_win32.h \ + telnet.h \ + tftp.h \ + timeval.h \ + transfer.h \ + url.h \ + urlapi-int.h \ + urldata.h \ + version_win32.h \ + warnless.h \ + wildcard.h \ + x509asn1.h LIB_RCFILES = libcurl.rc CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \ @@ -1349,6 +1606,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-ares.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-thread.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-base64.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-c-hyper.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-conncache.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-connect.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-content_encoding.Plo@am__quote@ # am--include-marker @@ -1398,6 +1656,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hsts.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_aws_sigv4.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_chunks.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_digest.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_negotiate.Plo@am__quote@ # am--include-marker @@ -1466,6 +1725,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-ares.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-thread.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-base64.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-c-hyper.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-conncache.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-connect.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-content_encoding.Plo@am__quote@ # am--include-marker @@ -1515,6 +1775,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hsts.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_aws_sigv4.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_chunks.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_digest.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_negotiate.Plo@am__quote@ # am--include-marker @@ -1708,6 +1969,13 @@ libcurl_la-base64.lo: base64.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c +libcurl_la-c-hyper.lo: c-hyper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-c-hyper.lo -MD -MP -MF $(DEPDIR)/libcurl_la-c-hyper.Tpo -c -o libcurl_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-c-hyper.Tpo $(DEPDIR)/libcurl_la-c-hyper.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='c-hyper.c' object='libcurl_la-c-hyper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c + libcurl_la-conncache.lo: conncache.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-conncache.lo -MD -MP -MF $(DEPDIR)/libcurl_la-conncache.Tpo -c -o libcurl_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-conncache.Tpo $(DEPDIR)/libcurl_la-conncache.Plo @@ -1869,6 +2137,13 @@ libcurl_la-dict.lo: dict.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c +libcurl_la-doh.lo: doh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-doh.lo -MD -MP -MF $(DEPDIR)/libcurl_la-doh.Tpo -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-doh.Tpo $(DEPDIR)/libcurl_la-doh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='doh.c' object='libcurl_la-doh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c + libcurl_la-dotdot.lo: dotdot.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dotdot.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dotdot.Tpo -c -o libcurl_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dotdot.Tpo $(DEPDIR)/libcurl_la-dotdot.Plo @@ -1876,6 +2151,13 @@ libcurl_la-dotdot.lo: dotdot.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c +libcurl_la-dynbuf.lo: dynbuf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dynbuf.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dynbuf.Tpo -c -o libcurl_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dynbuf.Tpo $(DEPDIR)/libcurl_la-dynbuf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dynbuf.c' object='libcurl_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c + libcurl_la-easy.lo: easy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easy.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easy.Tpo -c -o libcurl_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easy.Tpo $(DEPDIR)/libcurl_la-easy.Plo @@ -1883,6 +2165,20 @@ libcurl_la-easy.lo: easy.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c +libcurl_la-easygetopt.lo: easygetopt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easygetopt.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easygetopt.Tpo -c -o libcurl_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easygetopt.Tpo $(DEPDIR)/libcurl_la-easygetopt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='easygetopt.c' object='libcurl_la-easygetopt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c + +libcurl_la-easyoptions.lo: easyoptions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easyoptions.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easyoptions.Tpo -c -o libcurl_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easyoptions.Tpo $(DEPDIR)/libcurl_la-easyoptions.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='easyoptions.c' object='libcurl_la-easyoptions.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c + libcurl_la-escape.lo: escape.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-escape.lo -MD -MP -MF $(DEPDIR)/libcurl_la-escape.Tpo -c -o libcurl_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-escape.Tpo $(DEPDIR)/libcurl_la-escape.Plo @@ -1918,13 +2214,6 @@ libcurl_la-ftp.lo: ftp.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c -libcurl_la-url.lo: url.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-url.lo -MD -MP -MF $(DEPDIR)/libcurl_la-url.Tpo -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-url.Tpo $(DEPDIR)/libcurl_la-url.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='url.c' object='libcurl_la-url.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c - libcurl_la-ftplistparser.lo: ftplistparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ftplistparser.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ftplistparser.Tpo -c -o libcurl_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ftplistparser.Tpo $(DEPDIR)/libcurl_la-ftplistparser.Plo @@ -2009,6 +2298,13 @@ libcurl_la-hostsyn.lo: hostsyn.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c +libcurl_la-hsts.lo: hsts.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hsts.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hsts.Tpo -c -o libcurl_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hsts.Tpo $(DEPDIR)/libcurl_la-hsts.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hsts.c' object='libcurl_la-hsts.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c + libcurl_la-http.lo: http.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http.Tpo -c -o libcurl_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http.Tpo $(DEPDIR)/libcurl_la-http.Plo @@ -2058,6 +2354,13 @@ libcurl_la-http_proxy.lo: http_proxy.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c +libcurl_la-http_aws_sigv4.lo: http_aws_sigv4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http_aws_sigv4.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http_aws_sigv4.Tpo -c -o libcurl_la-http_aws_sigv4.lo `test -f 'http_aws_sigv4.c' || echo '$(srcdir)/'`http_aws_sigv4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http_aws_sigv4.Tpo $(DEPDIR)/libcurl_la-http_aws_sigv4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_aws_sigv4.c' object='libcurl_la-http_aws_sigv4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_aws_sigv4.lo `test -f 'http_aws_sigv4.c' || echo '$(srcdir)/'`http_aws_sigv4.c + libcurl_la-idn_win32.lo: idn_win32.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-idn_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-idn_win32.Tpo -c -o libcurl_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-idn_win32.Tpo $(DEPDIR)/libcurl_la-idn_win32.Plo @@ -2226,13 +2529,6 @@ libcurl_la-psl.lo: psl.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c -libcurl_la-doh.lo: doh.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-doh.lo -MD -MP -MF $(DEPDIR)/libcurl_la-doh.Tpo -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-doh.Tpo $(DEPDIR)/libcurl_la-doh.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='doh.c' object='libcurl_la-doh.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c - libcurl_la-rand.lo: rand.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-rand.lo -MD -MP -MF $(DEPDIR)/libcurl_la-rand.Tpo -c -o libcurl_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-rand.Tpo $(DEPDIR)/libcurl_la-rand.Plo @@ -2422,6 +2718,13 @@ libcurl_la-transfer.lo: transfer.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c +libcurl_la-url.lo: url.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-url.lo -MD -MP -MF $(DEPDIR)/libcurl_la-url.Tpo -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-url.Tpo $(DEPDIR)/libcurl_la-url.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='url.c' object='libcurl_la-url.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c + libcurl_la-urlapi.lo: urlapi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-urlapi.lo -MD -MP -MF $(DEPDIR)/libcurl_la-urlapi.Tpo -c -o libcurl_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-urlapi.Tpo $(DEPDIR)/libcurl_la-urlapi.Plo @@ -2436,6 +2739,13 @@ libcurl_la-version.lo: version.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c +libcurl_la-version_win32.lo: version_win32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-version_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-version_win32.Tpo -c -o libcurl_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-version_win32.Tpo $(DEPDIR)/libcurl_la-version_win32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='version_win32.c' object='libcurl_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c + libcurl_la-warnless.lo: warnless.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-warnless.lo -MD -MP -MF $(DEPDIR)/libcurl_la-warnless.Tpo -c -o libcurl_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-warnless.Tpo $(DEPDIR)/libcurl_la-warnless.Plo @@ -2457,41 +2767,6 @@ libcurl_la-x509asn1.lo: x509asn1.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c -libcurl_la-dynbuf.lo: dynbuf.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dynbuf.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dynbuf.Tpo -c -o libcurl_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dynbuf.Tpo $(DEPDIR)/libcurl_la-dynbuf.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dynbuf.c' object='libcurl_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c - -libcurl_la-version_win32.lo: version_win32.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-version_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-version_win32.Tpo -c -o libcurl_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-version_win32.Tpo $(DEPDIR)/libcurl_la-version_win32.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='version_win32.c' object='libcurl_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c - -libcurl_la-easyoptions.lo: easyoptions.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easyoptions.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easyoptions.Tpo -c -o libcurl_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easyoptions.Tpo $(DEPDIR)/libcurl_la-easyoptions.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='easyoptions.c' object='libcurl_la-easyoptions.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c - -libcurl_la-easygetopt.lo: easygetopt.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easygetopt.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easygetopt.Tpo -c -o libcurl_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easygetopt.Tpo $(DEPDIR)/libcurl_la-easygetopt.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='easygetopt.c' object='libcurl_la-easygetopt.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c - -libcurl_la-hsts.lo: hsts.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hsts.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hsts.Tpo -c -o libcurl_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hsts.Tpo $(DEPDIR)/libcurl_la-hsts.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hsts.c' object='libcurl_la-hsts.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c - vauth/libcurl_la-cleartext.lo: vauth/cleartext.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-cleartext.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-cleartext.Tpo -c -o vauth/libcurl_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-cleartext.Tpo vauth/$(DEPDIR)/libcurl_la-cleartext.Plo @@ -2751,6 +3026,13 @@ libcurlu_la-base64.lo: base64.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c +libcurlu_la-c-hyper.lo: c-hyper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-c-hyper.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-c-hyper.Tpo -c -o libcurlu_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-c-hyper.Tpo $(DEPDIR)/libcurlu_la-c-hyper.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='c-hyper.c' object='libcurlu_la-c-hyper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c + libcurlu_la-conncache.lo: conncache.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-conncache.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-conncache.Tpo -c -o libcurlu_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-conncache.Tpo $(DEPDIR)/libcurlu_la-conncache.Plo @@ -2912,6 +3194,13 @@ libcurlu_la-dict.lo: dict.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c +libcurlu_la-doh.lo: doh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-doh.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-doh.Tpo -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-doh.Tpo $(DEPDIR)/libcurlu_la-doh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='doh.c' object='libcurlu_la-doh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c + libcurlu_la-dotdot.lo: dotdot.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dotdot.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dotdot.Tpo -c -o libcurlu_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dotdot.Tpo $(DEPDIR)/libcurlu_la-dotdot.Plo @@ -2919,6 +3208,13 @@ libcurlu_la-dotdot.lo: dotdot.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c +libcurlu_la-dynbuf.lo: dynbuf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dynbuf.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dynbuf.Tpo -c -o libcurlu_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dynbuf.Tpo $(DEPDIR)/libcurlu_la-dynbuf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dynbuf.c' object='libcurlu_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c + libcurlu_la-easy.lo: easy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easy.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easy.Tpo -c -o libcurlu_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easy.Tpo $(DEPDIR)/libcurlu_la-easy.Plo @@ -2926,6 +3222,20 @@ libcurlu_la-easy.lo: easy.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c +libcurlu_la-easygetopt.lo: easygetopt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easygetopt.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easygetopt.Tpo -c -o libcurlu_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easygetopt.Tpo $(DEPDIR)/libcurlu_la-easygetopt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='easygetopt.c' object='libcurlu_la-easygetopt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c + +libcurlu_la-easyoptions.lo: easyoptions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easyoptions.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easyoptions.Tpo -c -o libcurlu_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easyoptions.Tpo $(DEPDIR)/libcurlu_la-easyoptions.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='easyoptions.c' object='libcurlu_la-easyoptions.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c + libcurlu_la-escape.lo: escape.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-escape.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-escape.Tpo -c -o libcurlu_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-escape.Tpo $(DEPDIR)/libcurlu_la-escape.Plo @@ -2961,13 +3271,6 @@ libcurlu_la-ftp.lo: ftp.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c -libcurlu_la-url.lo: url.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-url.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-url.Tpo -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-url.Tpo $(DEPDIR)/libcurlu_la-url.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='url.c' object='libcurlu_la-url.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c - libcurlu_la-ftplistparser.lo: ftplistparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ftplistparser.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ftplistparser.Tpo -c -o libcurlu_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ftplistparser.Tpo $(DEPDIR)/libcurlu_la-ftplistparser.Plo @@ -3052,6 +3355,13 @@ libcurlu_la-hostsyn.lo: hostsyn.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c +libcurlu_la-hsts.lo: hsts.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hsts.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hsts.Tpo -c -o libcurlu_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hsts.Tpo $(DEPDIR)/libcurlu_la-hsts.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hsts.c' object='libcurlu_la-hsts.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c + libcurlu_la-http.lo: http.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http.Tpo -c -o libcurlu_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http.Tpo $(DEPDIR)/libcurlu_la-http.Plo @@ -3101,6 +3411,13 @@ libcurlu_la-http_proxy.lo: http_proxy.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c +libcurlu_la-http_aws_sigv4.lo: http_aws_sigv4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http_aws_sigv4.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http_aws_sigv4.Tpo -c -o libcurlu_la-http_aws_sigv4.lo `test -f 'http_aws_sigv4.c' || echo '$(srcdir)/'`http_aws_sigv4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http_aws_sigv4.Tpo $(DEPDIR)/libcurlu_la-http_aws_sigv4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_aws_sigv4.c' object='libcurlu_la-http_aws_sigv4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_aws_sigv4.lo `test -f 'http_aws_sigv4.c' || echo '$(srcdir)/'`http_aws_sigv4.c + libcurlu_la-idn_win32.lo: idn_win32.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-idn_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-idn_win32.Tpo -c -o libcurlu_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-idn_win32.Tpo $(DEPDIR)/libcurlu_la-idn_win32.Plo @@ -3269,13 +3586,6 @@ libcurlu_la-psl.lo: psl.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c -libcurlu_la-doh.lo: doh.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-doh.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-doh.Tpo -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-doh.Tpo $(DEPDIR)/libcurlu_la-doh.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='doh.c' object='libcurlu_la-doh.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c - libcurlu_la-rand.lo: rand.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-rand.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-rand.Tpo -c -o libcurlu_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-rand.Tpo $(DEPDIR)/libcurlu_la-rand.Plo @@ -3465,6 +3775,13 @@ libcurlu_la-transfer.lo: transfer.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c +libcurlu_la-url.lo: url.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-url.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-url.Tpo -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-url.Tpo $(DEPDIR)/libcurlu_la-url.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='url.c' object='libcurlu_la-url.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c + libcurlu_la-urlapi.lo: urlapi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-urlapi.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-urlapi.Tpo -c -o libcurlu_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-urlapi.Tpo $(DEPDIR)/libcurlu_la-urlapi.Plo @@ -3479,6 +3796,13 @@ libcurlu_la-version.lo: version.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c +libcurlu_la-version_win32.lo: version_win32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-version_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-version_win32.Tpo -c -o libcurlu_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-version_win32.Tpo $(DEPDIR)/libcurlu_la-version_win32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='version_win32.c' object='libcurlu_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c + libcurlu_la-warnless.lo: warnless.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-warnless.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-warnless.Tpo -c -o libcurlu_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-warnless.Tpo $(DEPDIR)/libcurlu_la-warnless.Plo @@ -3500,41 +3824,6 @@ libcurlu_la-x509asn1.lo: x509asn1.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c -libcurlu_la-dynbuf.lo: dynbuf.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dynbuf.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dynbuf.Tpo -c -o libcurlu_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dynbuf.Tpo $(DEPDIR)/libcurlu_la-dynbuf.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dynbuf.c' object='libcurlu_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c - -libcurlu_la-version_win32.lo: version_win32.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-version_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-version_win32.Tpo -c -o libcurlu_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-version_win32.Tpo $(DEPDIR)/libcurlu_la-version_win32.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='version_win32.c' object='libcurlu_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c - -libcurlu_la-easyoptions.lo: easyoptions.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easyoptions.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easyoptions.Tpo -c -o libcurlu_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easyoptions.Tpo $(DEPDIR)/libcurlu_la-easyoptions.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='easyoptions.c' object='libcurlu_la-easyoptions.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c - -libcurlu_la-easygetopt.lo: easygetopt.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easygetopt.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easygetopt.Tpo -c -o libcurlu_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easygetopt.Tpo $(DEPDIR)/libcurlu_la-easygetopt.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='easygetopt.c' object='libcurlu_la-easygetopt.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c - -libcurlu_la-hsts.lo: hsts.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hsts.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hsts.Tpo -c -o libcurlu_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hsts.Tpo $(DEPDIR)/libcurlu_la-hsts.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hsts.c' object='libcurlu_la-hsts.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c - vauth/libcurlu_la-cleartext.lo: vauth/cleartext.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-cleartext.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-cleartext.Tpo -c -o vauth/libcurlu_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-cleartext.Tpo vauth/$(DEPDIR)/libcurlu_la-cleartext.Plo @@ -3911,6 +4200,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo -rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo -rm -f ./$(DEPDIR)/libcurl_la-base64.Plo + -rm -f ./$(DEPDIR)/libcurl_la-c-hyper.Plo -rm -f ./$(DEPDIR)/libcurl_la-conncache.Plo -rm -f ./$(DEPDIR)/libcurl_la-connect.Plo -rm -f ./$(DEPDIR)/libcurl_la-content_encoding.Plo @@ -3960,6 +4250,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurl_la-hsts.Plo -rm -f ./$(DEPDIR)/libcurl_la-http.Plo -rm -f ./$(DEPDIR)/libcurl_la-http2.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_aws_sigv4.Plo -rm -f ./$(DEPDIR)/libcurl_la-http_chunks.Plo -rm -f ./$(DEPDIR)/libcurl_la-http_digest.Plo -rm -f ./$(DEPDIR)/libcurl_la-http_negotiate.Plo @@ -4028,6 +4319,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo -rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo -rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-c-hyper.Plo -rm -f ./$(DEPDIR)/libcurlu_la-conncache.Plo -rm -f ./$(DEPDIR)/libcurlu_la-connect.Plo -rm -f ./$(DEPDIR)/libcurlu_la-content_encoding.Plo @@ -4077,6 +4369,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcurlu_la-hsts.Plo -rm -f ./$(DEPDIR)/libcurlu_la-http.Plo -rm -f ./$(DEPDIR)/libcurlu_la-http2.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_aws_sigv4.Plo -rm -f ./$(DEPDIR)/libcurlu_la-http_chunks.Plo -rm -f ./$(DEPDIR)/libcurlu_la-http_digest.Plo -rm -f ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo @@ -4254,6 +4547,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo -rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo -rm -f ./$(DEPDIR)/libcurl_la-base64.Plo + -rm -f ./$(DEPDIR)/libcurl_la-c-hyper.Plo -rm -f ./$(DEPDIR)/libcurl_la-conncache.Plo -rm -f ./$(DEPDIR)/libcurl_la-connect.Plo -rm -f ./$(DEPDIR)/libcurl_la-content_encoding.Plo @@ -4303,6 +4597,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurl_la-hsts.Plo -rm -f ./$(DEPDIR)/libcurl_la-http.Plo -rm -f ./$(DEPDIR)/libcurl_la-http2.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_aws_sigv4.Plo -rm -f ./$(DEPDIR)/libcurl_la-http_chunks.Plo -rm -f ./$(DEPDIR)/libcurl_la-http_digest.Plo -rm -f ./$(DEPDIR)/libcurl_la-http_negotiate.Plo @@ -4371,6 +4666,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo -rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo -rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-c-hyper.Plo -rm -f ./$(DEPDIR)/libcurlu_la-conncache.Plo -rm -f ./$(DEPDIR)/libcurlu_la-connect.Plo -rm -f ./$(DEPDIR)/libcurlu_la-content_encoding.Plo @@ -4420,6 +4716,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcurlu_la-hsts.Plo -rm -f ./$(DEPDIR)/libcurlu_la-http.Plo -rm -f ./$(DEPDIR)/libcurlu_la-http2.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_aws_sigv4.Plo -rm -f ./$(DEPDIR)/libcurlu_la-http_chunks.Plo -rm -f ./$(DEPDIR)/libcurlu_la-http_digest.Plo -rm -f ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo diff --git a/libs/libcurl/src/Makefile.inc b/libs/libcurl/src/Makefile.inc index 6d35704c02..e8d2259f2f 100644 --- a/libs/libcurl/src/Makefile.inc +++ b/libs/libcurl/src/Makefile.inc @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. +# Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -20,67 +20,314 @@ # ########################################################################### -LIB_VAUTH_CFILES = vauth/cleartext.c vauth/cram.c vauth/digest.c \ - vauth/digest_sspi.c vauth/krb5_gssapi.c vauth/krb5_sspi.c vauth/ntlm.c \ - vauth/ntlm_sspi.c vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \ +LIB_VAUTH_CFILES = \ + vauth/cleartext.c \ + vauth/cram.c \ + vauth/digest.c \ + vauth/digest_sspi.c \ + vauth/krb5_gssapi.c \ + vauth/krb5_sspi.c \ + vauth/ntlm.c \ + vauth/ntlm_sspi.c \ + vauth/oauth2.c \ + vauth/spnego_gssapi.c \ + vauth/spnego_sspi.c \ vauth/vauth.c -LIB_VAUTH_HFILES = vauth/digest.h vauth/ntlm.h vauth/vauth.h +LIB_VAUTH_HFILES = \ + vauth/digest.h \ + vauth/ntlm.h \ + vauth/vauth.h -LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/keylog.c \ - vtls/mbedtls.c vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c \ - vtls/openssl.c vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \ - vtls/vtls.c vtls/wolfssl.c +LIB_VTLS_CFILES = \ + vtls/bearssl.c \ + vtls/gskit.c \ + vtls/gtls.c \ + vtls/keylog.c \ + vtls/mbedtls.c \ + vtls/mbedtls_threadlock.c \ + vtls/mesalink.c \ + vtls/nss.c \ + vtls/openssl.c \ + vtls/schannel.c \ + vtls/schannel_verify.c \ + vtls/sectransp.c \ + vtls/vtls.c \ + vtls/wolfssl.c -LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/keylog.h \ - vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h \ - vtls/openssl.h vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h +LIB_VTLS_HFILES = \ + vtls/bearssl.h \ + vtls/gskit.h \ + vtls/gtls.h \ + vtls/keylog.h \ + vtls/mbedtls.h \ + vtls/mbedtls_threadlock.h \ + vtls/mesalink.h \ + vtls/nssg.h \ + vtls/openssl.h \ + vtls/schannel.h \ + vtls/sectransp.h \ + vtls/vtls.h \ + vtls/wolfssl.h -LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c +LIB_VQUIC_CFILES = \ + vquic/ngtcp2.c \ + vquic/quiche.c \ + vquic/vquic.c -LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h vquic/vquic.h +LIB_VQUIC_HFILES = \ + vquic/ngtcp2.h \ + vquic/quiche.h \ + vquic/vquic.h -LIB_VSSH_CFILES = vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c +LIB_VSSH_CFILES = \ + vssh/libssh.c \ + vssh/libssh2.c \ + vssh/wolfssh.c -LIB_VSSH_HFILES = vssh/ssh.h +LIB_VSSH_HFILES = \ + vssh/ssh.h -LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c \ - conncache.c connect.c content_encoding.c cookie.c curl_addrinfo.c \ - curl_ctype.c curl_des.c curl_endian.c curl_fnmatch.c curl_get_line.c \ - curl_gethostname.c curl_gssapi.c curl_memrchr.c curl_multibyte.c \ - curl_ntlm_core.c curl_ntlm_wb.c curl_path.c curl_range.c curl_rtmp.c \ - curl_sasl.c curl_sspi.c curl_threads.c dict.c dotdot.c easy.c escape.c \ - file.c fileinfo.c formdata.c ftp.c url.c ftplistparser.c getenv.c getinfo.c \ - gopher.c hash.c hmac.c hostasyn.c hostcheck.c hostip.c hostip4.c hostip6.c \ - hostsyn.c http.c http2.c http_chunks.c http_digest.c http_negotiate.c \ - http_ntlm.c http_proxy.c idn_win32.c if2ip.c imap.c inet_ntop.c inet_pton.c \ - krb5.c ldap.c llist.c md4.c md5.c memdebug.c mime.c mprintf.c mqtt.c \ - multi.c netrc.c non-ascii.c nonblock.c openldap.c parsedate.c pingpong.c \ - pop3.c progress.c psl.c doh.c rand.c rename.c rtsp.c select.c \ - sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \ - socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c \ - strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c \ - transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c \ - version_win32.c easyoptions.c easygetopt.c hsts.c +LIB_CFILES = \ + altsvc.c \ + amigaos.c \ + asyn-ares.c \ + asyn-thread.c \ + base64.c \ + c-hyper.c \ + conncache.c \ + connect.c \ + content_encoding.c \ + cookie.c \ + curl_addrinfo.c \ + curl_ctype.c \ + curl_des.c \ + curl_endian.c \ + curl_fnmatch.c \ + curl_get_line.c \ + curl_gethostname.c \ + curl_gssapi.c \ + curl_memrchr.c \ + curl_multibyte.c \ + curl_ntlm_core.c \ + curl_ntlm_wb.c \ + curl_path.c \ + curl_range.c \ + curl_rtmp.c \ + curl_sasl.c \ + curl_sspi.c \ + curl_threads.c \ + dict.c \ + doh.c \ + dotdot.c \ + dynbuf.c \ + easy.c \ + easygetopt.c \ + easyoptions.c \ + escape.c \ + file.c \ + fileinfo.c \ + formdata.c \ + ftp.c \ + ftplistparser.c \ + getenv.c \ + getinfo.c \ + gopher.c \ + hash.c \ + hmac.c \ + hostasyn.c \ + hostcheck.c \ + hostip.c \ + hostip4.c \ + hostip6.c \ + hostsyn.c \ + hsts.c \ + http.c \ + http2.c \ + http_chunks.c \ + http_digest.c \ + http_negotiate.c \ + http_ntlm.c \ + http_proxy.c \ + http_aws_sigv4.c \ + idn_win32.c \ + if2ip.c \ + imap.c \ + inet_ntop.c \ + inet_pton.c \ + krb5.c \ + ldap.c \ + llist.c \ + md4.c \ + md5.c \ + memdebug.c \ + mime.c \ + mprintf.c \ + mqtt.c \ + multi.c \ + netrc.c \ + non-ascii.c \ + nonblock.c \ + openldap.c \ + parsedate.c \ + pingpong.c \ + pop3.c \ + progress.c \ + psl.c \ + rand.c \ + rename.c \ + rtsp.c \ + select.c \ + sendf.c \ + setopt.c \ + sha256.c \ + share.c \ + slist.c \ + smb.c \ + smtp.c \ + socketpair.c \ + socks.c \ + socks_gssapi.c \ + socks_sspi.c \ + speedcheck.c \ + splay.c \ + strcase.c \ + strdup.c \ + strerror.c \ + strtok.c \ + strtoofft.c \ + system_win32.c \ + telnet.c \ + tftp.c \ + timeval.c \ + transfer.c \ + url.c \ + urlapi.c \ + version.c \ + version_win32.c \ + warnless.c \ + wildcard.c \ + x509asn1.c -LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h \ - content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h \ - curl_des.h curl_endian.h curl_fnmatch.h curl_get_line.h curl_gethostname.h \ - curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memory.h \ - curl_memrchr.h curl_multibyte.h curl_ntlm_core.h curl_ntlm_wb.h curl_path.h \ - curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h curl_krb5.h curl_setup.h \ - curl_setup_once.h curl_sha256.h curl_sspi.h curl_threads.h curlx.h dict.h \ - dotdot.h easyif.h escape.h file.h fileinfo.h formdata.h ftp.h url.h \ - ftplistparser.h getinfo.h gopher.h hash.h hostcheck.h hostip.h http.h \ - http2.h http_chunks.h http_digest.h http_negotiate.h http_ntlm.h \ - http_proxy.h if2ip.h imap.h inet_ntop.h inet_pton.h llist.h memdebug.h \ - mime.h mqtt.h multihandle.h multiif.h netrc.h non-ascii.h nonblock.h \ - parsedate.h pingpong.h pop3.h progress.h psl.h doh.h quic.h rand.h rename.h \ - rtsp.h select.h sendf.h setopt.h setup-vms.h share.h sigpipe.h slist.h \ - smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \ - strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h \ - timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h \ - x509asn1.h dynbuf.h version_win32.h easyoptions.h hsts.h +LIB_HFILES = \ + altsvc.h \ + amigaos.h \ + arpa_telnet.h \ + asyn.h \ + c-hyper.h \ + conncache.h \ + connect.h \ + content_encoding.h \ + cookie.h \ + curl_addrinfo.h \ + curl_base64.h \ + curl_ctype.h \ + curl_des.h \ + curl_endian.h \ + curl_fnmatch.h \ + curl_get_line.h \ + curl_gethostname.h \ + curl_gssapi.h \ + curl_hmac.h \ + curl_krb5.h \ + curl_ldap.h \ + curl_md4.h \ + curl_md5.h \ + curl_memory.h \ + curl_memrchr.h \ + curl_multibyte.h \ + curl_ntlm_core.h \ + curl_ntlm_wb.h \ + curl_path.h \ + curl_printf.h \ + curl_range.h \ + curl_rtmp.h \ + curl_sasl.h \ + curl_setup.h \ + curl_setup_once.h \ + curl_sha256.h \ + curl_sspi.h \ + curl_threads.h \ + curlx.h \ + dict.h \ + doh.h \ + dotdot.h \ + dynbuf.h \ + easyif.h \ + easyoptions.h \ + escape.h \ + file.h \ + fileinfo.h \ + formdata.h \ + ftp.h \ + ftplistparser.h \ + getinfo.h \ + gopher.h \ + hash.h \ + hostcheck.h \ + hostip.h \ + hsts.h \ + http.h \ + http2.h \ + http_chunks.h \ + http_digest.h \ + http_negotiate.h \ + http_ntlm.h \ + http_proxy.h \ + http_aws_sigv4.h \ + if2ip.h \ + imap.h \ + inet_ntop.h \ + inet_pton.h \ + llist.h \ + memdebug.h \ + mime.h \ + mqtt.h \ + multihandle.h \ + multiif.h \ + netrc.h \ + non-ascii.h \ + nonblock.h \ + parsedate.h \ + pingpong.h \ + pop3.h \ + progress.h \ + psl.h \ + quic.h \ + rand.h \ + rename.h \ + rtsp.h \ + select.h \ + sendf.h \ + setopt.h \ + setup-vms.h \ + share.h \ + sigpipe.h \ + slist.h \ + smb.h \ + smtp.h \ + sockaddr.h \ + socketpair.h \ + socks.h \ + speedcheck.h \ + splay.h \ + strcase.h \ + strdup.h \ + strerror.h \ + strtok.h \ + strtoofft.h \ + system_win32.h \ + telnet.h \ + tftp.h \ + timeval.h \ + transfer.h \ + url.h \ + urlapi-int.h \ + urldata.h \ + version_win32.h \ + warnless.h \ + wildcard.h \ + x509asn1.h LIB_RCFILES = libcurl.rc diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c index 1747571889..2484a7b498 100644 --- a/libs/libcurl/src/asyn-ares.c +++ b/libs/libcurl/src/asyn-ares.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -133,8 +133,8 @@ void Curl_resolver_global_cleanup(void) } -static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd, - int readable, int writable) +static void sock_state_cb(void *data, ares_socket_t socket_fd, + int readable, int writable) { struct Curl_easy *easy = data; if(!readable && !writable) { @@ -155,7 +155,7 @@ CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver) int status; struct ares_options options; int optmask = ARES_OPT_SOCK_STATE_CB; - options.sock_state_cb = Curl_ares_sock_state_cb; + options.sock_state_cb = sock_state_cb; options.sock_state_cb_data = easy; status = ares_init_options((ares_channel*)resolver, &options, optmask); if(status != ARES_SUCCESS) { @@ -204,22 +204,22 @@ static void destroy_async_data(struct Curl_async *async); /* * Cancel all possibly still on-going resolves for this connection. */ -void Curl_resolver_cancel(struct connectdata *conn) +void Curl_resolver_cancel(struct Curl_easy *data) { - if(conn->data && conn->data->state.resolver) - ares_cancel((ares_channel)conn->data->state.resolver); - destroy_async_data(&conn->async); + if(data && data->state.async.resolver) + ares_cancel((ares_channel)data->state.async.resolver); + destroy_async_data(&data->state.async); } /* * We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We * never block. */ -void Curl_resolver_kill(struct connectdata *conn) +void Curl_resolver_kill(struct Curl_easy *data) { /* We don't need to check the resolver state because we can be called safely at any time and we always do the same thing. */ - Curl_resolver_cancel(conn); + Curl_resolver_cancel(data); } /* @@ -253,25 +253,25 @@ static void destroy_async_data(struct Curl_async *async) * Returns: sockets-in-use-bitmap */ -int Curl_resolver_getsock(struct connectdata *conn, +int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks) { struct timeval maxtime; struct timeval timebuf; struct timeval *timeout; long milli; - int max = ares_getsock((ares_channel)conn->data->state.resolver, + int max = ares_getsock((ares_channel)data->state.async.resolver, (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE); maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; maxtime.tv_usec = 0; - timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime, + timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime, &timebuf); milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000); if(milli == 0) milli += 10; - Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME); + Curl_expire(data, milli, EXPIRE_ASYNC_NAME); return max; } @@ -286,9 +286,8 @@ int Curl_resolver_getsock(struct connectdata *conn, * return number of sockets it worked on */ -static int waitperform(struct connectdata *conn, timediff_t timeout_ms) +static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) { - struct Curl_easy *data = conn->data; int nfds; int bitmask; ares_socket_t socks[ARES_GETSOCK_MAXNUM]; @@ -296,7 +295,7 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms) int i; int num = 0; - bitmask = ares_getsock((ares_channel)data->state.resolver, socks, + bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks, ARES_GETSOCK_MAXNUM); for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) { @@ -324,12 +323,12 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms) if(!nfds) /* Call ares_process() unconditonally here, even if we simply timed out above, as otherwise the ares name resolve won't timeout! */ - ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD, + ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD, ARES_SOCKET_BAD); else { /* move through the descriptors and ask for processing on them */ for(i = 0; i < num; i++) - ares_process_fd((ares_channel)data->state.resolver, + ares_process_fd((ares_channel)data->state.async.resolver, (pfd[i].revents & (POLLRDNORM|POLLIN))? pfd[i].fd:ARES_SOCKET_BAD, (pfd[i].revents & (POLLWRNORM|POLLOUT))? @@ -345,17 +344,16 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms) * * Returns normal CURLcode errors. */ -CURLcode Curl_resolver_is_resolved(struct connectdata *conn, +CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dns) { - struct Curl_easy *data = conn->data; - struct thread_data *res = conn->async.tdata; + struct thread_data *res = data->state.async.tdata; CURLcode result = CURLE_OK; DEBUGASSERT(dns); *dns = NULL; - waitperform(conn, 0); + waitperform(data, 0); /* Now that we've checked for any last minute results above, see if there are any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer @@ -376,26 +374,27 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, ARES_ECANCELLED synchronously for all pending responses. This will leave us with res->num_pending == 0, which is perfect for the next block. */ - ares_cancel((ares_channel)data->state.resolver); + ares_cancel((ares_channel)data->state.async.resolver); DEBUGASSERT(res->num_pending == 0); } if(res && !res->num_pending) { - (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai); + (void)Curl_addrinfo_callback(data, res->last_status, res->temp_ai); /* temp_ai ownership is moved to the connection, so we need not free-up them */ res->temp_ai = NULL; - if(!conn->async.dns) { + if(!data->state.async.dns) { failf(data, "Could not resolve: %s (%s)", - conn->async.hostname, ares_strerror(conn->async.status)); - result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: + data->state.async.hostname, + ares_strerror(data->state.async.status)); + result = data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: CURLE_COULDNT_RESOLVE_HOST; } else - *dns = conn->async.dns; + *dns = data->state.async.dns; - destroy_async_data(&conn->async); + destroy_async_data(&data->state.async); } return result; @@ -412,11 +411,10 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. */ -CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, +CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, struct Curl_dns_entry **entry) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; timediff_t timeout; struct curltime now = Curl_now(); @@ -426,7 +424,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, timeout = Curl_timeleft(data, &now, TRUE); if(timeout < 0) { /* already expired! */ - connclose(conn, "Timed out before name resolve started"); + connclose(data->conn, "Timed out before name resolve started"); return CURLE_OPERATION_TIMEDOUT; } if(!timeout) @@ -447,7 +445,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, store.tv_sec = itimeout/1000; store.tv_usec = (itimeout%1000)*1000; - tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv); + tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv); /* use the timeout period ares returned to us above if less than one second is left, otherwise just use 1000ms to make sure the progress @@ -457,13 +455,13 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, else timeout_ms = 1000; - waitperform(conn, timeout_ms); - result = Curl_resolver_is_resolved(conn, entry); + waitperform(data, timeout_ms); + result = Curl_resolver_is_resolved(data, entry); - if(result || conn->async.done) + if(result || data->state.async.done) break; - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; else { struct curltime now2 = Curl_now(); @@ -481,17 +479,17 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, } if(result) /* failure, so we cancel the ares operation */ - ares_cancel((ares_channel)data->state.resolver); + ares_cancel((ares_channel)data->state.async.resolver); /* Operation complete, if the lookup was successful we now have the entry in the cache. */ if(entry) - *entry = conn->async.dns; + *entry = data->state.async.dns; if(result) /* close the connection, since we can't return failure here without cleaning up this connection properly. */ - connclose(conn, "c-ares resolve failed"); + connclose(data->conn, "c-ares resolve failed"); return result; } @@ -525,7 +523,7 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ #endif struct hostent *hostent) { - struct connectdata *conn = (struct connectdata *)arg; + struct Curl_easy *data = (struct Curl_easy *)arg; struct thread_data *res; #ifdef HAVE_CARES_CALLBACK_TIMEOUTS @@ -537,12 +535,12 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ be valid so only defer it when we know the 'status' says its fine! */ return; - res = conn->async.tdata; + res = data->state.async.tdata; if(res) { res->num_pending--; if(CURL_ASYNC_SUCCESS == status) { - struct Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port); + struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port); if(ai) { compound_results(res, ai); } @@ -607,8 +605,8 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ c-ares retry cycle each request is. */ res->happy_eyeballs_dns_time = Curl_now(); - Curl_expire( - conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS); + Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT, + EXPIRE_HAPPY_EYEBALLS_DNS); } } } @@ -621,19 +619,18 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ * memory we need to free after use. That memory *MUST* be freed with * Curl_freeaddrinfo(), nothing else. */ -struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, +struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, const char *hostname, int port, int *waitp) { char *bufp; - struct Curl_easy *data = conn->data; int family = PF_INET; *waitp = 0; /* default to synchronous response */ #ifdef ENABLE_IPV6 - switch(conn->ip_version) { + switch(data->set.ipver) { default: #if ARES_VERSION >= 0x010601 family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older @@ -653,39 +650,39 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, bufp = strdup(hostname); if(bufp) { struct thread_data *res = NULL; - free(conn->async.hostname); - conn->async.hostname = bufp; - conn->async.port = port; - conn->async.done = FALSE; /* not done */ - conn->async.status = 0; /* clear */ - conn->async.dns = NULL; /* clear */ + free(data->state.async.hostname); + data->state.async.hostname = bufp; + data->state.async.port = port; + data->state.async.done = FALSE; /* not done */ + data->state.async.status = 0; /* clear */ + data->state.async.dns = NULL; /* clear */ res = calloc(sizeof(struct thread_data), 1); if(!res) { - free(conn->async.hostname); - conn->async.hostname = NULL; + free(data->state.async.hostname); + data->state.async.hostname = NULL; return NULL; } - conn->async.tdata = res; + data->state.async.tdata = res; /* initial status - failed */ res->last_status = ARES_ENOTFOUND; #ifdef ENABLE_IPV6 if(family == PF_UNSPEC) { - if(Curl_ipv6works(conn)) { + if(Curl_ipv6works(data)) { res->num_pending = 2; /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.resolver, hostname, - PF_INET, query_completed_cb, conn); - ares_gethostbyname((ares_channel)data->state.resolver, hostname, - PF_INET6, query_completed_cb, conn); + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET, query_completed_cb, data); + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET6, query_completed_cb, data); } else { res->num_pending = 1; /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.resolver, hostname, - PF_INET, query_completed_cb, conn); + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET, query_completed_cb, data); } } else @@ -694,8 +691,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, res->num_pending = 1; /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.resolver, hostname, family, - query_completed_cb, conn); + ares_gethostbyname((ares_channel)data->state.async.resolver, + hostname, family, + query_completed_cb, data); } *waitp = 1; /* expect asynchronous response */ @@ -720,9 +718,10 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, #if (ARES_VERSION >= 0x010704) #if (ARES_VERSION >= 0x010b00) - ares_result = ares_set_servers_ports_csv(data->state.resolver, servers); + ares_result = ares_set_servers_ports_csv(data->state.async.resolver, + servers); #else - ares_result = ares_set_servers_csv(data->state.resolver, servers); + ares_result = ares_set_servers_csv(data->state.async.resolver, servers); #endif switch(ares_result) { case ARES_SUCCESS: @@ -752,7 +751,7 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data, if(!interf) interf = ""; - ares_set_local_dev((ares_channel)data->state.resolver, interf); + ares_set_local_dev((ares_channel)data->state.async.resolver, interf); return CURLE_OK; #else /* c-ares version too old! */ @@ -777,7 +776,8 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, } } - ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr)); + ares_set_local_ip4((ares_channel)data->state.async.resolver, + ntohl(a4.s_addr)); return CURLE_OK; #else /* c-ares version too old! */ @@ -803,7 +803,7 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, } } - ares_set_local_ip6((ares_channel)data->state.resolver, a6); + ares_set_local_ip6((ares_channel)data->state.async.resolver, a6); return CURLE_OK; #else /* c-ares version too old! */ diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c index 7c85982748..9fcbc3c1fd 100644 --- a/libs/libcurl/src/asyn-thread.c +++ b/libs/libcurl/src/asyn-thread.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -145,13 +145,13 @@ static void destroy_async_data(struct Curl_async *); /* * Cancel all possibly still on-going resolves for this connection. */ -void Curl_resolver_cancel(struct connectdata *conn) +void Curl_resolver_cancel(struct Curl_easy *data) { - destroy_async_data(&conn->async); + destroy_async_data(&data->state.async); } /* This function is used to init a threaded resolve */ -static bool init_resolve_thread(struct connectdata *conn, +static bool init_resolve_thread(struct Curl_easy *data, const char *hostname, int port, const struct addrinfo *hints); @@ -160,12 +160,11 @@ static bool init_resolve_thread(struct connectdata *conn, struct thread_sync_data { curl_mutex_t *mtx; int done; - + int port; char *hostname; /* hostname to resolve, Curl_async.hostname duplicate */ - int port; #ifdef USE_SOCKETPAIR - struct connectdata *conn; + struct Curl_easy *data; curl_socket_t sock_pair[2]; /* socket pair */ #endif int sock_error; @@ -183,9 +182,9 @@ struct thread_data { struct thread_sync_data tsd; }; -static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn) +static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data) { - return &(conn->async.tdata->tsd); + return &(data->state.async.tdata->tsd); } /* Destroy resolver thread synchronization data */ @@ -269,12 +268,12 @@ int init_thread_sync_data(struct thread_data *td, return 0; } -static int getaddrinfo_complete(struct connectdata *conn) +static int getaddrinfo_complete(struct Curl_easy *data) { - struct thread_sync_data *tsd = conn_thread_sync_data(conn); + struct thread_sync_data *tsd = conn_thread_sync_data(data); int rc; - rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res); + rc = Curl_addrinfo_callback(data, tsd->sock_error, tsd->res); /* The tsd->res structure has been copied to async.dns and perhaps the DNS cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it. */ @@ -385,7 +384,7 @@ static void destroy_async_data(struct Curl_async *async) int done; #ifdef USE_SOCKETPAIR curl_socket_t sock_rd = td->tsd.sock_pair[0]; - struct connectdata *conn = td->tsd.conn; + struct Curl_easy *data = td->tsd.data; #endif /* @@ -413,8 +412,7 @@ static void destroy_async_data(struct Curl_async *async) * ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL */ - if(conn) - Curl_multi_closed(conn->data, sock_rd); + Curl_multi_closed(data, sock_rd); sclose(sock_rd); #endif } @@ -430,32 +428,33 @@ static void destroy_async_data(struct Curl_async *async) * * Returns FALSE in case of failure, otherwise TRUE. */ -static bool init_resolve_thread(struct connectdata *conn, +static bool init_resolve_thread(struct Curl_easy *data, const char *hostname, int port, const struct addrinfo *hints) { struct thread_data *td = calloc(1, sizeof(struct thread_data)); int err = ENOMEM; + struct Curl_async *asp = &data->state.async; - conn->async.tdata = td; + data->state.async.tdata = td; if(!td) goto errno_exit; - conn->async.port = port; - conn->async.done = FALSE; - conn->async.status = 0; - conn->async.dns = NULL; + asp->port = port; + asp->done = FALSE; + asp->status = 0; + asp->dns = NULL; td->thread_hnd = curl_thread_t_null; if(!init_thread_sync_data(td, hostname, port, hints)) { - conn->async.tdata = NULL; + asp->tdata = NULL; free(td); goto errno_exit; } - free(conn->async.hostname); - conn->async.hostname = strdup(hostname); - if(!conn->async.hostname) + free(asp->hostname); + asp->hostname = strdup(hostname); + if(!asp->hostname) goto err_exit; /* The thread will set this to 1 when complete. */ @@ -477,7 +476,7 @@ static bool init_resolve_thread(struct connectdata *conn, return TRUE; err_exit: - destroy_async_data(&conn->async); + destroy_async_data(asp); errno_exit: errno = err; @@ -489,12 +488,13 @@ static bool init_resolve_thread(struct connectdata *conn, * error */ -static CURLcode resolver_error(struct connectdata *conn) +static CURLcode resolver_error(struct Curl_easy *data) { const char *host_or_proxy; CURLcode result; #ifndef CURL_DISABLE_PROXY + struct connectdata *conn = data->conn; if(conn->bits.httpproxy) { host_or_proxy = "proxy"; result = CURLE_COULDNT_RESOLVE_PROXY; @@ -506,8 +506,8 @@ static CURLcode resolver_error(struct connectdata *conn) result = CURLE_COULDNT_RESOLVE_HOST; } - failf(conn->data, "Could not resolve %s: %s", host_or_proxy, - conn->async.hostname); + failf(data, "Could not resolve %s: %s", host_or_proxy, + data->state.async.hostname); return result; } @@ -515,37 +515,39 @@ static CURLcode resolver_error(struct connectdata *conn) /* * 'entry' may be NULL and then no data is returned */ -static CURLcode thread_wait_resolv(struct connectdata *conn, +static CURLcode thread_wait_resolv(struct Curl_easy *data, struct Curl_dns_entry **entry, bool report) { - struct thread_data *td = conn->async.tdata; + struct thread_data *td; CURLcode result = CURLE_OK; - DEBUGASSERT(conn && td); + DEBUGASSERT(data); + td = data->state.async.tdata; + DEBUGASSERT(td); DEBUGASSERT(td->thread_hnd != curl_thread_t_null); /* wait for the thread to resolve the name */ if(Curl_thread_join(&td->thread_hnd)) { if(entry) - result = getaddrinfo_complete(conn); + result = getaddrinfo_complete(data); } else DEBUGASSERT(0); - conn->async.done = TRUE; + data->state.async.done = TRUE; if(entry) - *entry = conn->async.dns; + *entry = data->state.async.dns; - if(!conn->async.dns && report) + if(!data->state.async.dns && report) /* a name was not resolved, report error */ - result = resolver_error(conn); + result = resolver_error(data); - destroy_async_data(&conn->async); + destroy_async_data(&data->state.async); - if(!conn->async.dns && report) - connclose(conn, "asynch resolve failed"); + if(!data->state.async.dns && report) + connclose(data->conn, "asynch resolve failed"); return result; } @@ -555,17 +557,17 @@ static CURLcode thread_wait_resolv(struct connectdata *conn, * Until we gain a way to signal the resolver threads to stop early, we must * simply wait for them and ignore their results. */ -void Curl_resolver_kill(struct connectdata *conn) +void Curl_resolver_kill(struct Curl_easy *data) { - struct thread_data *td = conn->async.tdata; + struct thread_data *td = data->state.async.tdata; /* If we're still resolving, we must wait for the threads to fully clean up, unfortunately. Otherwise, we can simply cancel to clean up any resolver data. */ if(td && td->thread_hnd != curl_thread_t_null) - (void)thread_wait_resolv(conn, NULL, FALSE); + (void)thread_wait_resolv(data, NULL, FALSE); else - Curl_resolver_cancel(conn); + Curl_resolver_cancel(data); } /* @@ -581,10 +583,10 @@ void Curl_resolver_kill(struct connectdata *conn) * * This is the version for resolves-in-a-thread. */ -CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, +CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, struct Curl_dns_entry **entry) { - return thread_wait_resolv(conn, entry, TRUE); + return thread_wait_resolv(data, entry, TRUE); } /* @@ -592,11 +594,10 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, * name resolve request has completed. It should also make sure to time-out if * the operation seems to take too long. */ -CURLcode Curl_resolver_is_resolved(struct connectdata *conn, +CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **entry) { - struct Curl_easy *data = conn->data; - struct thread_data *td = conn->async.tdata; + struct thread_data *td = data->state.async.tdata; int done = 0; DEBUGASSERT(entry); @@ -612,15 +613,15 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, Curl_mutex_release(td->tsd.mtx); if(done) { - getaddrinfo_complete(conn); + getaddrinfo_complete(data); - if(!conn->async.dns) { - CURLcode result = resolver_error(conn); - destroy_async_data(&conn->async); + if(!data->state.async.dns) { + CURLcode result = resolver_error(data); + destroy_async_data(&data->state.async); return result; } - destroy_async_data(&conn->async); - *entry = conn->async.dns; + destroy_async_data(&data->state.async); + *entry = data->state.async.dns; } else { /* poll for name lookup done with exponential backoff up to 250ms */ @@ -641,22 +642,20 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, td->poll_interval = 250; td->interval_end = elapsed + td->poll_interval; - Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME); + Curl_expire(data, td->poll_interval, EXPIRE_ASYNC_NAME); } return CURLE_OK; } -int Curl_resolver_getsock(struct connectdata *conn, - curl_socket_t *socks) +int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks) { int ret_val = 0; timediff_t milli; timediff_t ms; - struct Curl_easy *data = conn->data; - struct resdata *reslv = (struct resdata *)data->state.resolver; + struct resdata *reslv = (struct resdata *)data->state.async.resolver; #ifdef USE_SOCKETPAIR - struct thread_data *td = conn->async.tdata; + struct thread_data *td = data->state.async.tdata; #else (void)socks; #endif @@ -665,8 +664,7 @@ int Curl_resolver_getsock(struct connectdata *conn, if(td) { /* return read fd to client for polling the DNS resolution status */ socks[0] = td->tsd.sock_pair[0]; - DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn); - td->tsd.conn = conn; + td->tsd.data = data; ret_val = GETSOCK_READSOCK(0); } else { @@ -693,25 +691,24 @@ int Curl_resolver_getsock(struct connectdata *conn, /* * Curl_getaddrinfo() - for platforms without getaddrinfo */ -struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, +struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, const char *hostname, int port, int *waitp) { - struct Curl_easy *data = conn->data; - struct resdata *reslv = (struct resdata *)data->state.resolver; + struct resdata *reslv = (struct resdata *)data->state.async.resolver; *waitp = 0; /* default to synchronous response */ reslv->start = Curl_now(); /* fire up a new resolver thread! */ - if(init_resolve_thread(conn, hostname, port, NULL)) { + if(init_resolve_thread(data, hostname, port, NULL)) { *waitp = 1; /* expect asynchronous response */ return NULL; } - failf(conn->data, "getaddrinfo() thread failed\n"); + failf(data, "getaddrinfo() thread failed"); return NULL; } @@ -721,15 +718,14 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, /* * Curl_resolver_getaddrinfo() - for getaddrinfo */ -struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, +struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, const char *hostname, int port, int *waitp) { struct addrinfo hints; int pf = PF_INET; - struct Curl_easy *data = conn->data; - struct resdata *reslv = (struct resdata *)data->state.resolver; + struct resdata *reslv = (struct resdata *)data->state.async.resolver; *waitp = 0; /* default to synchronous response */ @@ -737,7 +733,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, /* * Check if a limited name resolve has been requested. */ - switch(conn->ip_version) { + switch(data->set.ipver) { case CURL_IPRESOLVE_V4: pf = PF_INET; break; @@ -749,24 +745,24 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, break; } - if((pf != PF_INET) && !Curl_ipv6works(conn)) + if((pf != PF_INET) && !Curl_ipv6works(data)) /* The stack seems to be a non-IPv6 one */ pf = PF_INET; #endif /* CURLRES_IPV6 */ memset(&hints, 0, sizeof(hints)); hints.ai_family = pf; - hints.ai_socktype = (conn->transport == TRNSPRT_TCP)? + hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)? SOCK_STREAM : SOCK_DGRAM; reslv->start = Curl_now(); /* fire up a new resolver thread! */ - if(init_resolve_thread(conn, hostname, port, &hints)) { + if(init_resolve_thread(data, hostname, port, &hints)) { *waitp = 1; /* expect asynchronous response */ return NULL; } - failf(data, "getaddrinfo() thread failed to start\n"); + failf(data, "getaddrinfo() thread failed to start"); return NULL; } diff --git a/libs/libcurl/src/asyn.h b/libs/libcurl/src/asyn.h index 73a9b7268f..3130395826 100644 --- a/libs/libcurl/src/asyn.h +++ b/libs/libcurl/src/asyn.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -91,7 +91,7 @@ CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, * * It is safe to call this when conn is in any state. */ -void Curl_resolver_cancel(struct connectdata *conn); +void Curl_resolver_cancel(struct Curl_easy *data); /* * Curl_resolver_kill(). @@ -104,7 +104,7 @@ void Curl_resolver_cancel(struct connectdata *conn); * * It is safe to call this when conn is in any state. */ -void Curl_resolver_kill(struct connectdata *conn); +void Curl_resolver_kill(struct Curl_easy *data); /* Curl_resolver_getsock() * @@ -114,7 +114,7 @@ void Curl_resolver_kill(struct connectdata *conn); * return bitmask indicating what file descriptors (referring to array indexes * in the 'sock' array) to wait for, read/write. */ -int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock); +int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *sock); /* * Curl_resolver_is_resolved() @@ -125,7 +125,7 @@ int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock); * * Returns normal CURLcode errors. */ -CURLcode Curl_resolver_is_resolved(struct connectdata *conn, +CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dns); /* @@ -139,7 +139,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. */ -CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, +CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, struct Curl_dns_entry **dnsentry); /* @@ -153,7 +153,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, * Each resolver backend must of course make sure to return data in the * correct format to comply with this. */ -struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, +struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, const char *hostname, int port, int *waitp); diff --git a/libs/libcurl/src/c-hyper.c b/libs/libcurl/src/c-hyper.c new file mode 100644 index 0000000000..10bd7ef9bf --- /dev/null +++ b/libs/libcurl/src/c-hyper.c @@ -0,0 +1,908 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "transfer.h" +#include "multiif.h" +#include "progress.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +size_t Curl_hyper_recv(void *userp, hyper_context *ctx, + uint8_t *buf, size_t buflen) +{ + struct Curl_easy *data = userp; + struct connectdata *conn = data->conn; + CURLcode result; + ssize_t nread; + DEBUGASSERT(conn); + (void)ctx; + + result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread); + if(result == CURLE_AGAIN) { + /* would block, register interest */ + if(data->hyp.read_waker) + hyper_waker_free(data->hyp.read_waker); + data->hyp.read_waker = hyper_context_waker(ctx); + if(!data->hyp.read_waker) { + failf(data, "Couldn't make the read hyper_context_waker"); + return HYPER_IO_ERROR; + } + return HYPER_IO_PENDING; + } + else if(result) { + failf(data, "Curl_read failed"); + return HYPER_IO_ERROR; + } + return (size_t)nread; +} + +size_t Curl_hyper_send(void *userp, hyper_context *ctx, + const uint8_t *buf, size_t buflen) +{ + struct Curl_easy *data = userp; + struct connectdata *conn = data->conn; + CURLcode result; + ssize_t nwrote; + + result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote); + if(result == CURLE_AGAIN) { + /* would block, register interest */ + if(data->hyp.write_waker) + hyper_waker_free(data->hyp.write_waker); + data->hyp.write_waker = hyper_context_waker(ctx); + if(!data->hyp.write_waker) { + failf(data, "Couldn't make the write hyper_context_waker"); + return HYPER_IO_ERROR; + } + return HYPER_IO_PENDING; + } + else if(result) { + failf(data, "Curl_write failed"); + return HYPER_IO_ERROR; + } + return (size_t)nwrote; +} + +static int hyper_each_header(void *userdata, + const uint8_t *name, + size_t name_len, + const uint8_t *value, + size_t value_len) +{ + struct Curl_easy *data = (struct Curl_easy *)userdata; + size_t len; + char *headp; + CURLcode result; + Curl_dyn_reset(&data->state.headerb); + if(name_len) { + if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n", + (int) name_len, name, (int) value_len, value)) + return HYPER_ITER_BREAK; + } + else { + if(Curl_dyn_add(&data->state.headerb, "\r\n")) + return HYPER_ITER_BREAK; + } + len = Curl_dyn_len(&data->state.headerb); + headp = Curl_dyn_ptr(&data->state.headerb); + + result = Curl_http_header(data, data->conn, headp); + if(result) { + data->state.hresult = result; + return HYPER_ITER_BREAK; + } + + Curl_debug(data, CURLINFO_HEADER_IN, headp, len); + + result = Curl_client_write(data, CLIENTWRITE_HEADER, headp, 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; + return HYPER_ITER_CONTINUE; +} + +static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) +{ + char *buf = (char *)hyper_buf_bytes(chunk); + size_t len = hyper_buf_len(chunk); + struct Curl_easy *data = (struct Curl_easy *)userdata; + struct SingleRequest *k = &data->req; + CURLcode result; + + if(0 == k->bodywrites++) { + bool done = FALSE; + result = Curl_http_firstwrite(data, data->conn, &done); + if(result || done) { + infof(data, "Return early from hyper_body_chunk\n"); + data->state.hresult = result; + return HYPER_ITER_BREAK; + } + } + if(k->ignorebody) + return HYPER_ITER_CONTINUE; + Curl_debug(data, CURLINFO_DATA_IN, buf, len); + result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len); + + if(result) { + data->state.hresult = result; + return HYPER_ITER_BREAK; + } + + data->req.bytecount += len; + Curl_pgrsSetDownloadCounter(data, data->req.bytecount); + return HYPER_ITER_CONTINUE; +} + +/* + * Hyper does not consider the status line, the first line in a HTTP/1 + * response, to be a header. The libcurl API does. This function sends the + * status line in the header callback. */ +static CURLcode status_line(struct Curl_easy *data, + struct connectdata *conn, + uint16_t http_status, + int http_version, + const uint8_t *reason, size_t rlen) +{ + CURLcode result; + size_t wrote; + size_t len; + const char *vstr; + curl_write_callback writeheader = + data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func; + vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" : + (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0"); + conn->httpversion = + http_version == HYPER_HTTP_VERSION_1_1 ? 11 : + (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10); + data->req.httpcode = http_status; + + result = Curl_http_statusline(data, conn); + if(result) + return result; + + Curl_dyn_reset(&data->state.headerb); + + result = Curl_dyn_addf(&data->state.headerb, "HTTP/%s %03d %.*s\r\n", + vstr, + (int)http_status, + (int)rlen, reason); + if(result) + return result; + len = Curl_dyn_len(&data->state.headerb); + Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb), + len); + Curl_set_in_callback(data, true); + wrote = writeheader(Curl_dyn_ptr(&data->state.headerb), 1, len, + data->set.writeheader); + Curl_set_in_callback(data, false); + if(wrote != len) + return CURLE_WRITE_ERROR; + + data->info.header_size += (long)len; + data->req.headerbytecount += (long)len; + data->req.httpcode = http_status; + return CURLE_OK; +} + +/* + * Hyper does not pass on the last empty response header. The libcurl API + * does. This function sends an empty header in the header callback. + */ +static CURLcode empty_header(struct Curl_easy *data) +{ + return hyper_each_header(data, NULL, 0, NULL, 0) ? + CURLE_WRITE_ERROR : CURLE_OK; +} + +CURLcode Curl_hyper_stream(struct Curl_easy *data, + struct connectdata *conn, + int *didwhat, + bool *done, + int select_res) +{ + hyper_response *resp = NULL; + uint16_t http_status; + int http_version; + hyper_headers *headers = NULL; + hyper_body *resp_body = NULL; + struct hyptransfer *h = &data->hyp; + hyper_task *task; + hyper_task *foreach; + hyper_error *hypererr = NULL; + const uint8_t *reasonp; + size_t reason_len; + CURLcode result = CURLE_OK; + (void)conn; + + if(select_res & CURL_CSELECT_IN) { + if(h->read_waker) + hyper_waker_wake(h->read_waker); + h->read_waker = NULL; + } + if(select_res & CURL_CSELECT_OUT) { + if(h->write_waker) + hyper_waker_wake(h->write_waker); + h->write_waker = NULL; + } + + *done = FALSE; + do { + hyper_task_return_type t; + task = hyper_executor_poll(h->exec); + if(!task) { + *didwhat = KEEP_RECV; + break; + } + t = hyper_task_type(task); + switch(t) { + case HYPER_TASK_ERROR: + hypererr = hyper_task_value(task); + break; + case HYPER_TASK_RESPONSE: + resp = hyper_task_value(task); + break; + default: + break; + } + hyper_task_free(task); + + if(t == HYPER_TASK_ERROR) { + hyper_code errnum = hyper_error_code(hypererr); + if(errnum == HYPERE_ABORTED_BY_CALLBACK) { + /* override Hyper's view, might not even be an error */ + result = data->state.hresult; + infof(data, "hyperstream is done (by early callback)\n"); + } + else { + 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); + if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount) + result = CURLE_GOT_NOTHING; + else + result = CURLE_RECV_ERROR; + } + *done = TRUE; + hyper_error_free(hypererr); + break; + } + else if(h->endtask == task) { + /* end of transfer */ + *done = TRUE; + infof(data, "hyperstream is done!\n"); + break; + } + else if(t != HYPER_TASK_RESPONSE) { + *didwhat = KEEP_RECV; + break; + } + /* HYPER_TASK_RESPONSE */ + + *didwhat = KEEP_RECV; + if(!resp) { + failf(data, "hyperstream: couldn't get response"); + return CURLE_RECV_ERROR; + } + + 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, conn, + http_status, http_version, reasonp, reason_len); + if(result) + break; + + headers = hyper_response_headers(resp); + if(!headers) { + failf(data, "hyperstream: couldn't get response headers"); + result = CURLE_RECV_ERROR; + break; + } + + /* the headers are already received */ + hyper_headers_foreach(headers, hyper_each_header, data); + if(data->state.hresult) { + result = data->state.hresult; + break; + } + + if(empty_header(data)) { + failf(data, "hyperstream: couldn't pass blank header"); + result = CURLE_OUT_OF_MEMORY; + break; + } + + /* Curl_http_auth_act() checks what authentication methods that are + * available and decides which one (if any) to use. It will set 'newurl' + * if an auth method was picked. */ + result = Curl_http_auth_act(data); + if(result) + break; + + resp_body = hyper_response_body(resp); + if(!resp_body) { + failf(data, "hyperstream: couldn't get response body"); + result = CURLE_RECV_ERROR; + break; + } + foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data); + if(!foreach) { + failf(data, "hyperstream: body foreach failed"); + result = CURLE_OUT_OF_MEMORY; + break; + } + DEBUGASSERT(hyper_task_type(foreach) == HYPER_TASK_EMPTY); + if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) { + failf(data, "Couldn't hyper_executor_push the body-foreach"); + result = CURLE_OUT_OF_MEMORY; + break; + } + h->endtask = foreach; + + hyper_response_free(resp); + resp = NULL; + } while(1); + if(resp) + hyper_response_free(resp); + return result; +} + +static CURLcode debug_request(struct Curl_easy *data, + const char *method, + const char *path, + bool h2) +{ + char *req = aprintf("%s %s HTTP/%s\r\n", method, path, + h2?"2":"1.1"); + if(!req) + return CURLE_OUT_OF_MEMORY; + Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req)); + free(req); + return CURLE_OK; +} + +/* + * Given a full header line "name: value" (optional CRLF in the input, should + * be in the output), add to Hyper and send to the debug callback. + * + * Supports multiple headers. + */ + +CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers, + const char *line) +{ + const char *p; + const char *n; + size_t nlen; + const char *v; + size_t vlen; + bool newline = TRUE; + int numh = 0; + + if(!line) + return CURLE_OK; + n = line; + do { + size_t linelen = 0; + + p = strchr(n, ':'); + if(!p) + /* this is fine if we already added at least one header */ + return numh ? CURLE_OK : CURLE_BAD_FUNCTION_ARGUMENT; + nlen = p - n; + p++; /* move past the colon */ + while(*p == ' ') + p++; + v = p; + p = strchr(v, '\r'); + if(!p) { + p = strchr(v, '\n'); + if(p) + linelen = 1; /* LF only */ + else { + p = strchr(v, '\0'); + newline = FALSE; /* no newline */ + } + } + else + linelen = 2; /* CRLF ending */ + linelen += (p - n); + if(!n) + return CURLE_BAD_FUNCTION_ARGUMENT; + vlen = p - v; + + if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen, + (uint8_t *)v, vlen)) { + failf(data, "hyper_headers_add host"); + return CURLE_OUT_OF_MEMORY; + } + if(data->set.verbose) { + char *ptr = NULL; + if(!newline) { + ptr = aprintf("%.*s\r\n", (int)linelen, line); + if(!ptr) + return CURLE_OUT_OF_MEMORY; + Curl_debug(data, CURLINFO_HEADER_OUT, ptr, linelen + 2); + free(ptr); + } + else + Curl_debug(data, CURLINFO_HEADER_OUT, (char *)line, linelen); + } + numh++; + n += linelen; + } while(newline); + return CURLE_OK; +} + +static CURLcode request_target(struct Curl_easy *data, + struct connectdata *conn, + const char *method, + bool h2, + hyper_request *req) +{ + CURLcode result; + struct dynbuf r; + + Curl_dyn_init(&r, DYN_HTTP_REQUEST); + + result = Curl_http_target(data, conn, &r); + 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"); + result = CURLE_OUT_OF_MEMORY; + } + else + result = debug_request(data, method, Curl_dyn_ptr(&r), h2); + + Curl_dyn_free(&r); + + return result; +} + +static int uploadpostfields(void *userdata, hyper_context *ctx, + hyper_buf **chunk) +{ + struct Curl_easy *data = (struct Curl_easy *)userdata; + (void)ctx; + if(data->req.upload_done) + *chunk = NULL; /* nothing more to deliver */ + else { + /* send everything off in a single go */ + *chunk = hyper_buf_copy(data->set.postfields, + (size_t)data->req.p.http->postsize); + data->req.upload_done = TRUE; + } + return HYPER_POLL_READY; +} + +static int uploadstreamed(void *userdata, hyper_context *ctx, + hyper_buf **chunk) +{ + size_t fillcount; + struct Curl_easy *data = (struct Curl_easy *)userdata; + CURLcode result = + Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount); + (void)ctx; + if(result) + return HYPER_POLL_ERROR; + if(!fillcount) + /* done! */ + *chunk = NULL; + else + *chunk = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount); + return HYPER_POLL_READY; +} + +/* + * bodysend() sets up headers in the outgoing request for a HTTP transfer that + * sends a body + */ + +static CURLcode bodysend(struct Curl_easy *data, + struct connectdata *conn, + hyper_headers *headers, + hyper_request *hyperreq, + Curl_HttpReq httpreq) +{ + CURLcode result = CURLE_OK; + struct dynbuf req; + if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) + Curl_pgrsSetUploadSize(data, 0); /* no request body */ + else { + hyper_body *body; + Curl_dyn_init(&req, DYN_HTTP_REQUEST); + result = Curl_http_bodysend(data, conn, &req, httpreq); + + if(!result) + result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req)); + + Curl_dyn_free(&req); + + body = hyper_body_new(); + hyper_body_set_userdata(body, data); + if(data->set.postfields) + hyper_body_set_data_func(body, uploadpostfields); + else { + result = Curl_get_upload_buffer(data); + if(result) + return result; + /* init the "upload from here" pointer */ + data->req.upload_fromhere = data->state.ulbuf; + hyper_body_set_data_func(body, uploadstreamed); + } + if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) { + /* fail */ + hyper_body_free(body); + result = CURLE_OUT_OF_MEMORY; + } + } + return result; +} + +static CURLcode cookies(struct Curl_easy *data, + struct connectdata *conn, + hyper_headers *headers) +{ + struct dynbuf req; + CURLcode result; + Curl_dyn_init(&req, DYN_HTTP_REQUEST); + + result = Curl_http_cookies(data, conn, &req); + if(!result) + result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req)); + Curl_dyn_free(&req); + return result; +} + +/* + * 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 + * HTTP request. + */ +CURLcode Curl_http(struct Curl_easy *data, bool *done) +{ + struct connectdata *conn = data->conn; + struct hyptransfer *h = &data->hyp; + hyper_io *io = NULL; + hyper_clientconn_options *options = NULL; + hyper_task *task = NULL; /* for the handshake */ + hyper_task *sendtask = NULL; /* for the send */ + hyper_clientconn *client = NULL; + 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 */ + + /* 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 + the rest of the request in the PERFORM phase. */ + *done = TRUE; + + infof(data, "Time for the Hyper dance\n"); + memset(h, 0, sizeof(struct hyptransfer)); + + result = Curl_http_host(data, conn); + if(result) + return result; + + Curl_http_method(data, conn, &method, &httpreq); + + /* setup the authentication headers */ + { + char *pq = NULL; + if(data->state.up.query) { + pq = aprintf("%s?%s", data->state.up.path, data->state.up.query); + if(!pq) + return CURLE_OUT_OF_MEMORY; + } + result = Curl_http_output_auth(data, conn, method, httpreq, + (pq ? pq : data->state.up.path), FALSE); + free(pq); + if(result) + return result; + } + + result = Curl_http_resume(data, conn, httpreq); + if(result) + return result; + + result = Curl_http_range(data, httpreq); + if(result) + return result; + + result = Curl_http_useragent(data); + if(result) + return result; + + io = hyper_io_new(); + if(!io) { + failf(data, "Couldn't create hyper IO"); + goto error; + } + /* tell Hyper how to read/write network data */ + hyper_io_set_userdata(io, data); + hyper_io_set_read(io, Curl_hyper_recv); + hyper_io_set_write(io, Curl_hyper_send); + + /* create an executor to poll futures */ + if(!h->exec) { + h->exec = hyper_executor_new(); + if(!h->exec) { + failf(data, "Couldn't create hyper executor"); + goto error; + } + } + + options = hyper_clientconn_options_new(); + if(!options) { + failf(data, "Couldn't create hyper client options"); + goto error; + } + if(conn->negnpn == CURL_HTTP_VERSION_2) { + hyper_clientconn_options_http2(options, 1); + h2 = TRUE; + } + + hyper_clientconn_options_exec(options, h->exec); + + /* "Both the `io` and the `options` are consumed in this function call" */ + handshake = hyper_clientconn_handshake(io, options); + if(!handshake) { + failf(data, "Couldn't create hyper client handshake"); + goto error; + } + io = NULL; + options = NULL; + + if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) { + failf(data, "Couldn't hyper_executor_push the handshake"); + goto error; + } + handshake = NULL; /* ownership passed on */ + + task = hyper_executor_poll(h->exec); + if(!task) { + failf(data, "Couldn't hyper_executor_poll the handshake"); + goto error; + } + + client = hyper_task_value(task); + hyper_task_free(task); + + req = hyper_request_new(); + if(!req) { + failf(data, "Couldn't hyper_request_new"); + goto error; + } + + if(data->set.httpversion == CURL_HTTP_VERSION_1_0) { + if(HYPERE_OK != hyper_request_set_version(req, + HYPER_HTTP_VERSION_1_0)) { + failf(data, "error setting HTTP version"); + goto error; + } + } + + if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) { + failf(data, "error setting method"); + goto error; + } + + result = request_target(data, conn, method, h2, req); + if(result) + goto error; + + headers = hyper_request_headers(req); + if(!headers) { + failf(data, "hyper_request_headers"); + 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(data->state.aptr.userpwd && + Curl_hyper_header(data, headers, data->state.aptr.userpwd)) + goto error; + + if((data->state.use_range && data->state.aptr.rangeline) && + Curl_hyper_header(data, headers, data->state.aptr.rangeline)) + 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; + + 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; + +#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")) + goto error; + } +#endif + + Curl_safefree(data->state.aptr.ref); + if(data->change.referer && !Curl_checkheaders(data, "Referer")) { + data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + if(!data->state.aptr.ref) + return CURLE_OUT_OF_MEMORY; + if(Curl_hyper_header(data, headers, data->state.aptr.ref)) + goto error; + } + + result = cookies(data, conn, headers); + if(result) + return result; + + result = Curl_add_timecondition(data, headers); + if(result) + return result; + + result = Curl_add_custom_headers(data, FALSE, headers); + if(result) + return result; + + result = bodysend(data, conn, headers, req, httpreq); + if(result) + return result; + + Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2); + + data->req.upload_chunky = FALSE; + sendtask = hyper_clientconn_send(client, req); + if(!sendtask) { + failf(data, "hyper_clientconn_send"); + goto error; + } + + if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) { + failf(data, "Couldn't hyper_executor_push the send"); + 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; + + return CURLE_OK; + error: + + if(io) + hyper_io_free(io); + + if(options) + hyper_clientconn_options_free(options); + + 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); + } + return CURLE_OUT_OF_MEMORY; +} + +void Curl_hyper_done(struct Curl_easy *data) +{ + struct hyptransfer *h = &data->hyp; + if(h->exec) { + hyper_executor_free(h->exec); + h->exec = NULL; + } + if(h->read_waker) { + hyper_waker_free(h->read_waker); + h->read_waker = NULL; + } + if(h->write_waker) { + hyper_waker_free(h->write_waker); + h->write_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 new file mode 100644 index 0000000000..d60ed78d1d --- /dev/null +++ b/libs/libcurl/src/c-hyper.h @@ -0,0 +1,56 @@ +#ifndef HEADER_CURL_HYPER_H +#define HEADER_CURL_HYPER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) + +#include + +/* per-transfer data for the Hyper backend */ +struct hyptransfer { + hyper_waker *write_waker; + hyper_waker *read_waker; + const hyper_executor *exec; + hyper_task *endtask; +}; + +size_t Curl_hyper_recv(void *userp, hyper_context *ctx, + uint8_t *buf, size_t buflen); +size_t Curl_hyper_send(void *userp, hyper_context *ctx, + const uint8_t *buf, size_t buflen); +CURLcode Curl_hyper_stream(struct Curl_easy *data, + struct connectdata *conn, + int *didwhat, + bool *done, + int select_res); + +CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers, + const char *line); +void Curl_hyper_done(struct Curl_easy *); + +#else +#define Curl_hyper_done(x) + +#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */ +#endif /* HEADER_CURL_HYPER_H */ diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h index 4b98a6ad37..e3095576f8 100644 --- a/libs/libcurl/src/config-win32.h +++ b/libs/libcurl/src/config-win32.h @@ -246,10 +246,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. */ /* #define HAVE_STRCASECMP 1 */ @@ -717,9 +713,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/conncache.c b/libs/libcurl/src/conncache.c index cb3170c480..8dfdc0ac81 100644 --- a/libs/libcurl/src/conncache.c +++ b/libs/libcurl/src/conncache.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -179,12 +179,14 @@ size_t Curl_conncache_size(struct Curl_easy *data) connectdata struct is setup to use. **NOTE**: When it returns, it holds the connection cache lock! */ -struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, - struct conncache *connc, - const char **hostp) +struct connectbundle * +Curl_conncache_find_bundle(struct Curl_easy *data, + struct connectdata *conn, + struct conncache *connc, + const char **hostp) { struct connectbundle *bundle = NULL; - CONNCACHE_LOCK(conn->data); + CONNCACHE_LOCK(data); if(connc) { char key[HASHKEY_SIZE]; hashkey(conn, key, sizeof(key), hostp); @@ -227,15 +229,17 @@ static void conncache_remove_bundle(struct conncache *connc, } } -CURLcode Curl_conncache_add_conn(struct conncache *connc, - struct connectdata *conn) +CURLcode Curl_conncache_add_conn(struct Curl_easy *data) { CURLcode result = CURLE_OK; struct connectbundle *bundle = NULL; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; + struct conncache *connc = data->state.conn_cache; + DEBUGASSERT(conn); /* *find_bundle() locks the connection cache */ - bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache, NULL); + bundle = Curl_conncache_find_bundle(data, conn, data->state.conn_cache, + NULL); if(!bundle) { int rc; char key[HASHKEY_SIZE]; @@ -259,7 +263,7 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, conn->connection_id = connc->next_connection_id++; connc->num_conn++; - DEBUGF(infof(conn->data, "Added connection %ld. " + DEBUGF(infof(data, "Added connection %ld. " "The cache now contains %zu members\n", conn->connection_id, connc->num_conn)); @@ -270,8 +274,8 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, } /* - * Removes the connectdata object from the connection cache, but does *not* - * clear the conn->data association. The transfer still owns this connection. + * Removes the connectdata object from the connection cache, but the transfer + * still owns this connection. * * Pass TRUE/FALSE in the 'lock' argument depending on if the parent function * already holds the lock or not. @@ -318,7 +322,8 @@ void Curl_conncache_remove_conn(struct Curl_easy *data, bool Curl_conncache_foreach(struct Curl_easy *data, struct conncache *connc, void *param, - int (*func)(struct connectdata *conn, void *param)) + int (*func)(struct Curl_easy *data, + struct connectdata *conn, void *param)) { struct Curl_hash_iterator iter; struct Curl_llist_element *curr; @@ -344,7 +349,7 @@ bool Curl_conncache_foreach(struct Curl_easy *data, struct connectdata *conn = curr->ptr; curr = curr->next; - if(1 == func(conn, param)) { + if(1 == func(data, conn, param)) { CONNCACHE_UNLOCK(data); return TRUE; } @@ -444,7 +449,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data, while(curr) { conn = curr->ptr; - if(!CONN_INUSE(conn) && !conn->data) { + if(!CONN_INUSE(conn)) { /* Set higher score for the age passed since the connection was used */ score = Curl_timediff(now, conn->lastused); @@ -502,7 +507,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data) while(curr) { conn = curr->ptr; - if(!CONN_INUSE(conn) && !conn->data && !conn->bits.close && + if(!CONN_INUSE(conn) && !conn->bits.close && !conn->bits.connect_only) { /* Set higher score for the age passed since the connection was used */ score = Curl_timediff(now, conn->lastused); @@ -543,12 +548,10 @@ void Curl_conncache_close_all_connections(struct conncache *connc) conn = conncache_find_first_connection(connc); while(conn) { SIGPIPE_VARIABLE(pipe_st); - conn->data = connc->closure_handle; - - sigpipe_ignore(conn->data, &pipe_st); + sigpipe_ignore(connc->closure_handle, &pipe_st); /* This will remove the connection from the cache */ connclose(conn, "kill all"); - Curl_conncache_remove_conn(conn->data, conn, TRUE); + Curl_conncache_remove_conn(connc->closure_handle, conn, TRUE); (void)Curl_disconnect(connc->closure_handle, conn, FALSE); sigpipe_restore(&pipe_st); diff --git a/libs/libcurl/src/conncache.h b/libs/libcurl/src/conncache.h index ac5460ff4b..e9c1e32f87 100644 --- a/libs/libcurl/src/conncache.h +++ b/libs/libcurl/src/conncache.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2015 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2015 - 2021, Daniel Stenberg, , et al. * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, * * This software is licensed as described in the file COPYING, which @@ -29,6 +29,10 @@ * be shared. */ +#include "timeval.h" + +struct connectdata; + struct conncache { struct Curl_hash hash; size_t num_conn; @@ -45,17 +49,24 @@ struct conncache { #ifdef CURLDEBUG /* the debug versions of these macros make extra certain that the lock is never doubly locked or unlocked */ -#define CONNCACHE_LOCK(x) if((x)->share) { \ - Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \ - DEBUGASSERT(!(x)->state.conncache_lock); \ - (x)->state.conncache_lock = TRUE; \ - } +#define CONNCACHE_LOCK(x) \ + do { \ + if((x)->share) { \ + Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, \ + CURL_LOCK_ACCESS_SINGLE); \ + DEBUGASSERT(!(x)->state.conncache_lock); \ + (x)->state.conncache_lock = TRUE; \ + } \ + } while(0) -#define CONNCACHE_UNLOCK(x) if((x)->share) { \ - DEBUGASSERT((x)->state.conncache_lock); \ - (x)->state.conncache_lock = FALSE; \ - Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \ - } +#define CONNCACHE_UNLOCK(x) \ + do { \ + if((x)->share) { \ + DEBUGASSERT((x)->state.conncache_lock); \ + (x)->state.conncache_lock = FALSE; \ + Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \ + } \ + } while(0) #else #define CONNCACHE_LOCK(x) if((x)->share) \ Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE) @@ -74,7 +85,8 @@ int Curl_conncache_init(struct conncache *, int size); void Curl_conncache_destroy(struct conncache *connc); /* return the correct bundle, to a host or a proxy */ -struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, +struct connectbundle *Curl_conncache_find_bundle(struct Curl_easy *data, + struct connectdata *conn, struct conncache *connc, const char **hostp); /* returns number of connections currently held in the connection cache */ @@ -82,15 +94,15 @@ size_t Curl_conncache_size(struct Curl_easy *data); bool Curl_conncache_return_conn(struct Curl_easy *data, struct connectdata *conn); -CURLcode Curl_conncache_add_conn(struct conncache *connc, - struct connectdata *conn) WARN_UNUSED_RESULT; +CURLcode Curl_conncache_add_conn(struct Curl_easy *data) WARN_UNUSED_RESULT; void Curl_conncache_remove_conn(struct Curl_easy *data, struct connectdata *conn, bool lock); bool Curl_conncache_foreach(struct Curl_easy *data, struct conncache *connc, void *param, - int (*func)(struct connectdata *conn, + int (*func)(struct Curl_easy *data, + struct connectdata *conn, void *param)); struct connectdata * diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c index e65d24d9e9..baab1840e1 100644 --- a/libs/libcurl/src/connect.c +++ b/libs/libcurl/src/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -160,7 +160,8 @@ tcpkeepalive(struct Curl_easy *data, } static CURLcode -singleipconnect(struct connectdata *conn, +singleipconnect(struct Curl_easy *data, + struct connectdata *conn, const struct Curl_addrinfo *ai, /* start connecting to this */ int tempindex); /* 0 or 1 among the temp ones */ @@ -236,11 +237,10 @@ timediff_t Curl_timeleft(struct Curl_easy *data, return timeout_ms; } -static CURLcode bindlocal(struct connectdata *conn, +static CURLcode bindlocal(struct Curl_easy *data, curl_socket_t sockfd, int af, unsigned int scope) { - struct Curl_easy *data = conn->data; - + struct connectdata *conn = data->conn; struct Curl_sockaddr_storage sa; struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ @@ -256,6 +256,9 @@ static CURLcode bindlocal(struct connectdata *conn, int portnum = data->set.localportrange; const char *dev = data->set.str[STRING_DEVICE]; int error; +#ifdef IP_BIND_ADDRESS_NO_PORT + int on = 1; +#endif /************************************************************* * Select device to bind socket to @@ -345,7 +348,7 @@ static CURLcode bindlocal(struct connectdata *conn, * of the connection. The resolve functions should really be changed * to take a type parameter instead. */ - long ipver = conn->ip_version; + unsigned char ipver = conn->ip_version; int rc; if(af == AF_INET) @@ -355,9 +358,9 @@ static CURLcode bindlocal(struct connectdata *conn, conn->ip_version = CURL_IPRESOLVE_V6; #endif - rc = Curl_resolv(conn, dev, 0, FALSE, &h); + rc = Curl_resolv(data, dev, 0, FALSE, &h); if(rc == CURLRESOLV_PENDING) - (void)Curl_resolver_wait_resolv(conn, &h); + (void)Curl_resolver_wait_resolv(data, &h); conn->ip_version = ipver; if(h) { @@ -441,7 +444,9 @@ static CURLcode bindlocal(struct connectdata *conn, sizeof_sa = sizeof(struct sockaddr_in); } } - +#ifdef IP_BIND_ADDRESS_NO_PORT + (void)setsockopt(sockfd, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &on, sizeof(on)); +#endif for(;;) { if(bind(sockfd, sock, sizeof_sa) >= 0) { /* we succeeded to bind */ @@ -568,7 +573,8 @@ static struct Curl_addrinfo *ainext(struct connectdata *conn, /* Used within the multi interface. Try next IP address, returns error if no more address exists or error */ -static CURLcode trynextip(struct connectdata *conn, +static CURLcode trynextip(struct Curl_easy *data, + struct connectdata *conn, int sockindex, int tempindex) { @@ -586,7 +592,7 @@ static CURLcode trynextip(struct connectdata *conn, while(ai) { if(ai) { - result = singleipconnect(conn, ai, tempindex); + result = singleipconnect(data, conn, ai, tempindex); if(result == CURLE_COULDNT_CONNECT) { ai = ainext(conn, tempindex, TRUE); continue; @@ -597,21 +603,25 @@ static CURLcode trynextip(struct connectdata *conn, } if(fd_to_close != CURL_SOCKET_BAD) - Curl_closesocket(conn, fd_to_close); + Curl_closesocket(data, conn, fd_to_close); return result; } -/* Copies connection info into the session handle to make it available - when the session handle is no longer associated with a connection. */ -void Curl_persistconninfo(struct connectdata *conn) +/* Copies connection info into the transfer handle to make it available when + the transfer handle is no longer associated with the connection. */ +void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn, + char *local_ip, long local_port) { - memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); - memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN); - conn->data->info.conn_scheme = conn->handler->scheme; - conn->data->info.conn_protocol = conn->handler->protocol; - conn->data->info.conn_primary_port = conn->primary_port; - conn->data->info.conn_local_port = conn->local_port; + memcpy(data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); + if(local_ip && local_ip[0]) + memcpy(data->info.conn_local_ip, local_ip, MAX_IPADR_LEN); + else + data->info.conn_local_ip[0] = 0; + data->info.conn_scheme = conn->handler->scheme; + data->info.conn_protocol = conn->handler->protocol; + data->info.conn_primary_port = conn->port; + data->info.conn_local_port = local_port; } /* retrieves ip address and port from a sockaddr structure. @@ -673,27 +683,30 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen, /* retrieves the start/end point information of a socket of an established connection */ -void Curl_conninfo_remote(struct connectdata *conn, curl_socket_t sockfd) +void Curl_conninfo_remote(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t sockfd) { #ifdef HAVE_GETPEERNAME char buffer[STRERROR_LEN]; struct Curl_sockaddr_storage ssrem; curl_socklen_t plen; + long port; plen = sizeof(struct Curl_sockaddr_storage); + memset(&ssrem, 0, sizeof(ssrem)); if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) { int error = SOCKERRNO; - failf(conn->data, "getpeername() failed with errno %d: %s", + failf(data, "getpeername() failed with errno %d: %s", error, Curl_strerror(error, buffer, sizeof(buffer))); return; } if(!Curl_addr2string((struct sockaddr*)&ssrem, plen, - conn->primary_ip, &conn->primary_port)) { - failf(conn->data, "ssrem inet_ntop() failed with errno %d: %s", + conn->primary_ip, &port)) { + failf(data, "ssrem inet_ntop() failed with errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); return; } - memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); #else + (void)data; (void)conn; (void)sockfd; #endif @@ -701,7 +714,8 @@ void Curl_conninfo_remote(struct connectdata *conn, curl_socket_t sockfd) /* retrieves the start/end point information of a socket of an established connection */ -void Curl_conninfo_local(struct connectdata *conn, curl_socket_t sockfd) +void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd, + char *local_ip, long *local_port) { #ifdef HAVE_GETSOCKNAME char buffer[STRERROR_LEN]; @@ -711,35 +725,44 @@ void Curl_conninfo_local(struct connectdata *conn, curl_socket_t sockfd) memset(&ssloc, 0, sizeof(ssloc)); if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) { int error = SOCKERRNO; - failf(conn->data, "getsockname() failed with errno %d: %s", + failf(data, "getsockname() failed with errno %d: %s", error, Curl_strerror(error, buffer, sizeof(buffer))); return; } if(!Curl_addr2string((struct sockaddr*)&ssloc, slen, - conn->local_ip, &conn->local_port)) { - failf(conn->data, "ssloc inet_ntop() failed with errno %d: %s", + local_ip, local_port)) { + failf(data, "ssloc inet_ntop() failed with errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); return; } #else - (void)conn; + (void)data; (void)sockfd; + (void)local_ip; + (void)local_port; #endif } /* retrieves the start/end point information of a socket of an established connection */ -void Curl_updateconninfo(struct connectdata *conn, 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. */ + char local_ip[MAX_IPADR_LEN] = ""; + long local_port = -1; + if(conn->transport == TRNSPRT_TCP) { if(!conn->bits.reuse && !conn->bits.tcp_fastopen) { - Curl_conninfo_remote(conn, sockfd); - Curl_conninfo_local(conn, sockfd); + Curl_conninfo_remote(data, conn, sockfd); + Curl_conninfo_local(data, sockfd, local_ip, &local_port); } } /* end of TCP-only section */ /* persist connection info in session handle */ - Curl_persistconninfo(conn); + Curl_persistconninfo(data, conn, local_ip, local_port); } /* After a TCP connection to the proxy has been verified, this function does @@ -749,12 +772,13 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) Note: this function's sub-functions call failf() */ -static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex, +static CURLcode connect_SOCKS(struct Curl_easy *data, int sockindex, bool *done) { CURLcode result = CURLE_OK; #ifndef CURL_DISABLE_PROXY CURLproxycode pxresult = CURLPX_OK; + struct connectdata *conn = data->conn; if(conn->bits.socksproxy) { /* for the secondary socket (FTP), use the "connect to host" * but ignore the "connect to port" (use the secondary port) @@ -775,27 +799,27 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex, case CURLPROXY_SOCKS5: case CURLPROXY_SOCKS5_HOSTNAME: pxresult = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd, - host, port, sockindex, conn, done); + host, port, sockindex, data, done); break; case CURLPROXY_SOCKS4: case CURLPROXY_SOCKS4A: pxresult = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex, - conn, done); + data, done); break; default: - failf(conn->data, "unknown proxytype option given"); + failf(data, "unknown proxytype option given"); result = CURLE_COULDNT_CONNECT; } /* switch proxytype */ if(pxresult) { result = CURLE_PROXY; - conn->data->info.pxcode = pxresult; + data->info.pxcode = pxresult; } } else #else - (void)conn; + (void)data; (void)sockindex; #endif /* CURL_DISABLE_PROXY */ *done = TRUE; /* no SOCKS proxy, so consider us connected */ @@ -807,7 +831,8 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex, * post_SOCKS() is called after a successful connect to the peer, which * *could* be a SOCKS proxy */ -static void post_SOCKS(struct connectdata *conn, +static void post_SOCKS(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool *connected) { @@ -815,21 +840,21 @@ static void post_SOCKS(struct connectdata *conn, *connected = TRUE; if(sockindex == FIRSTSOCKET) - Curl_pgrsTime(conn->data, TIMER_CONNECT); /* connect done */ - Curl_updateconninfo(conn, conn->sock[sockindex]); - Curl_verboseconnect(conn); - conn->data->info.numconnects++; /* to track the number of connections made */ + Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ + Curl_updateconninfo(data, conn, conn->sock[sockindex]); + Curl_verboseconnect(data, conn); + data->info.numconnects++; /* to track the number of connections made */ } /* * Curl_is_connected() checks if the socket has connected. */ -CURLcode Curl_is_connected(struct connectdata *conn, +CURLcode Curl_is_connected(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool *connected) { - struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; timediff_t allow; int error = 0; @@ -860,9 +885,9 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(SOCKS_STATE(conn->cnnct.state)) { /* still doing SOCKS */ - result = connect_SOCKS(conn, sockindex, connected); + result = connect_SOCKS(data, sockindex, connected); if(!result && *connected) - post_SOCKS(conn, sockindex, connected); + post_SOCKS(data, conn, sockindex, connected); return result; } @@ -873,13 +898,13 @@ CURLcode Curl_is_connected(struct connectdata *conn, error = 0; #ifdef ENABLE_QUIC if(conn->transport == TRNSPRT_QUIC) { - result = Curl_quic_is_connected(conn, i, connected); + result = Curl_quic_is_connected(data, conn, i, connected); if(!result && *connected) { /* use this socket from now on */ conn->sock[sockindex] = conn->tempsock[i]; conn->ip_addr = conn->tempaddr[i]; conn->tempsock[i] = CURL_SOCKET_BAD; - post_SOCKS(conn, sockindex, connected); + post_SOCKS(data, conn, sockindex, connected); connkeep(conn, "HTTP/3 default"); return CURLE_OK; } @@ -914,7 +939,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, (Curl_timediff(now, conn->connecttime) >= data->set.happy_eyeballs_timeout)) { conn->bits.parallel_connect = TRUE; /* starting now */ - trynextip(conn, sockindex, 1); + trynextip(data, conn, sockindex, 1); } } else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) { @@ -931,17 +956,17 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* close the other socket, if open */ if(conn->tempsock[other] != CURL_SOCKET_BAD) { - Curl_closesocket(conn, conn->tempsock[other]); + Curl_closesocket(data, conn, conn->tempsock[other]); conn->tempsock[other] = CURL_SOCKET_BAD; } /* see if we need to kick off any SOCKS proxy magic once we connected */ - result = connect_SOCKS(conn, sockindex, connected); + result = connect_SOCKS(data, sockindex, connected); if(result || !*connected) return result; - post_SOCKS(conn, sockindex, connected); + post_SOCKS(data, conn, sockindex, connected); return CURLE_OK; } @@ -972,7 +997,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ? allow : allow / 2; ainext(conn, i, TRUE); - status = trynextip(conn, sockindex, i); + status = trynextip(data, conn, sockindex, i); if((status != CURLE_COULDNT_CONNECT) || conn->tempsock[other] == CURL_SOCKET_BAD) /* the last attempt failed and no other sockets remain open */ @@ -990,7 +1015,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* if the first address family runs out of addresses to try before the happy eyeball timeout, go ahead and try the next family now */ - result = trynextip(conn, sockindex, 1); + result = trynextip(data, conn, sockindex, 1); if(!result) return result; @@ -1010,8 +1035,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, hostname, conn->port, Curl_strerror(error, buffer, sizeof(buffer))); - Curl_quic_disconnect(conn, 0); - Curl_quic_disconnect(conn, 1); + Curl_quic_disconnect(data, conn, 0); + Curl_quic_disconnect(data, conn, 1); #ifdef WSAETIMEDOUT if(WSAETIMEDOUT == data->state.os_errno) @@ -1027,16 +1052,15 @@ CURLcode Curl_is_connected(struct connectdata *conn, return result; } -static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) +static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd) { #if defined(TCP_NODELAY) curl_socklen_t onoff = (curl_socklen_t) 1; int level = IPPROTO_TCP; #if !defined(CURL_DISABLE_VERBOSE_STRINGS) - struct Curl_easy *data = conn->data; char buffer[STRERROR_LEN]; #else - (void) conn; + (void) data; #endif if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, @@ -1044,7 +1068,7 @@ static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) infof(data, "Could not set TCP_NODELAY: %s\n", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); #else - (void)conn; + (void)data; (void)sockfd; #endif } @@ -1054,10 +1078,9 @@ static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) sending data to a dead peer (instead of relying on the 4th argument to send being MSG_NOSIGNAL). Possibly also existing and in use on other BSD systems? */ -static void nosigpipe(struct connectdata *conn, +static void nosigpipe(struct Curl_easy *data, curl_socket_t sockfd) { - struct Curl_easy *data = conn->data; int onoff = 1; if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, sizeof(onoff)) < 0) { @@ -1123,7 +1146,8 @@ void Curl_sndbufset(curl_socket_t sockfd) * singleipconnect() connects to the given IP only, and it may return without * having connected. */ -static CURLcode singleipconnect(struct connectdata *conn, +static CURLcode singleipconnect(struct Curl_easy *data, + struct connectdata *conn, const struct Curl_addrinfo *ai, int tempindex) { @@ -1131,7 +1155,6 @@ static CURLcode singleipconnect(struct connectdata *conn, int rc = -1; int error = 0; bool isconnected = FALSE; - struct Curl_easy *data = conn->data; curl_socket_t sockfd; CURLcode result; char ipaddress[MAX_IPADR_LEN]; @@ -1144,7 +1167,7 @@ static CURLcode singleipconnect(struct connectdata *conn, curl_socket_t *sockp = &conn->tempsock[tempindex]; *sockp = CURL_SOCKET_BAD; - result = Curl_socket(conn, ai, &addr, &sockfd); + result = Curl_socket(data, ai, &addr, &sockfd); if(result) return result; @@ -1154,7 +1177,7 @@ static CURLcode singleipconnect(struct connectdata *conn, /* malformed address or bug in inet_ntop, try next address */ failf(data, "sa_addr inet_ntop() failed with errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); - Curl_closesocket(conn, sockfd); + Curl_closesocket(data, conn, sockfd); return CURLE_OK; } infof(data, " Trying %s:%ld...\n", ipaddress, port); @@ -1166,9 +1189,9 @@ static CURLcode singleipconnect(struct connectdata *conn, is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM; #endif if(is_tcp && data->set.tcp_nodelay) - tcpnodelay(conn, sockfd); + tcpnodelay(data, sockfd); - nosigpipe(conn, sockfd); + nosigpipe(data, sockfd); Curl_sndbufset(sockfd); @@ -1186,7 +1209,7 @@ static CURLcode singleipconnect(struct connectdata *conn, if(error == CURL_SOCKOPT_ALREADY_CONNECTED) isconnected = TRUE; else if(error) { - Curl_closesocket(conn, sockfd); /* close the socket and bail out */ + Curl_closesocket(data, conn, sockfd); /* close the socket and bail out */ return CURLE_ABORTED_BY_CALLBACK; } } @@ -1197,10 +1220,10 @@ static CURLcode singleipconnect(struct connectdata *conn, || addr.family == AF_INET6 #endif ) { - result = bindlocal(conn, sockfd, addr.family, + result = bindlocal(data, sockfd, addr.family, Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr)); if(result) { - Curl_closesocket(conn, sockfd); /* close socket and bail out */ + Curl_closesocket(data, conn, sockfd); /* close socket and bail out */ if(result == CURLE_UNSUPPORTED_PROTOCOL) { /* The address family is not supported on this interface. We can continue trying addresses */ @@ -1268,7 +1291,7 @@ static CURLcode singleipconnect(struct connectdata *conn, else if(conn->transport == TRNSPRT_QUIC) { /* pass in 'sockfd' separately since it hasn't been put into the tempsock array at this point */ - result = Curl_quic_connect(conn, sockfd, tempindex, + result = Curl_quic_connect(data, conn, sockfd, tempindex, &addr.sa_addr, addr.addrlen); if(result) error = SOCKERRNO; @@ -1303,7 +1326,7 @@ static CURLcode singleipconnect(struct connectdata *conn, data->state.os_errno = error; /* connect failed */ - Curl_closesocket(conn, sockfd); + Curl_closesocket(data, conn, sockfd); result = CURLE_COULDNT_CONNECT; } } @@ -1320,10 +1343,10 @@ static CURLcode singleipconnect(struct connectdata *conn, * pointer with the connected socket. */ -CURLcode Curl_connecthost(struct connectdata *conn, /* context */ +CURLcode Curl_connecthost(struct Curl_easy *data, + struct connectdata *conn, /* context */ const struct Curl_dns_entry *remotehost) { - struct Curl_easy *data = conn->data; CURLcode result = CURLE_COULDNT_CONNECT; int i; timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); @@ -1361,7 +1384,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* get through the list in family order in case of quick failures */ for(i = 0; (i < 2) && result; i++) { while(conn->tempaddr[i]) { - result = singleipconnect(conn, conn->tempaddr[i], i); + result = singleipconnect(data, conn, conn->tempaddr[i], i); if(!result) break; ainext(conn, i, TRUE); @@ -1370,7 +1393,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(result) return result; - Curl_expire(conn->data, data->set.happy_eyeballs_timeout, + Curl_expire(data, data->set.happy_eyeballs_timeout, EXPIRE_HAPPY_EYEBALLS); return CURLE_OK; @@ -1381,9 +1404,11 @@ struct connfind { struct connectdata *found; }; -static int conn_is_conn(struct connectdata *conn, void *param) +static int conn_is_conn(struct Curl_easy *data, + struct connectdata *conn, void *param) { struct connfind *f = (struct connfind *)param; + (void)data; if(conn->connection_id == f->id_tofind) { f->found = conn; return 1; @@ -1465,8 +1490,8 @@ bool Curl_connalive(struct connectdata *conn) * * 'conn' can be NULL, beware! */ -int Curl_closesocket(struct connectdata *conn, - curl_socket_t sock) +int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t sock) { if(conn && conn->fclosesocket) { if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted) @@ -1476,17 +1501,17 @@ int Curl_closesocket(struct connectdata *conn, conn->bits.sock_accepted = FALSE; else { int rc; - Curl_multi_closed(conn->data, sock); - Curl_set_in_callback(conn->data, true); + Curl_multi_closed(data, sock); + Curl_set_in_callback(data, true); rc = conn->fclosesocket(conn->closesocket_client, sock); - Curl_set_in_callback(conn->data, false); + Curl_set_in_callback(data, false); return rc; } } if(conn) /* tell the multi-socket code about this */ - Curl_multi_closed(conn->data, sock); + Curl_multi_closed(data, sock); sclose(sock); @@ -1502,12 +1527,12 @@ int Curl_closesocket(struct connectdata *conn, * If the open socket callback is set, used that! * */ -CURLcode Curl_socket(struct connectdata *conn, +CURLcode Curl_socket(struct Curl_easy *data, const struct Curl_addrinfo *ai, struct Curl_sockaddr_ex *addr, curl_socket_t *sockfd) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct Curl_sockaddr_ex dummy; if(!addr) @@ -1568,8 +1593,21 @@ CURLcode Curl_socket(struct connectdata *conn, } #endif - return CURLE_OK; +#if defined(__linux__) && defined(IP_RECVERR) + if(addr->socktype == SOCK_DGRAM) { + int one = 1; + switch(addr->family) { + case AF_INET: + (void)setsockopt(*sockfd, SOL_IP, IP_RECVERR, &one, sizeof(one)); + break; + case AF_INET6: + (void)setsockopt(*sockfd, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one)); + break; + } + } +#endif + return CURLE_OK; } /* @@ -1582,16 +1620,20 @@ void Curl_conncontrol(struct connectdata *conn, #endif ) { - /* close if a connection, or a stream that isn't multiplexed */ - bool closeit = (ctrl == CONNCTRL_CONNECTION) || - ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM)); + /* close if a connection, or a stream that isn't multiplexed. */ + /* This function will be called both before and after this connection is + associated with a transfer. */ + bool closeit; DEBUGASSERT(conn); +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + (void)reason; /* useful for debugging */ +#endif + closeit = (ctrl == CONNCTRL_CONNECTION) || + ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM)); if((ctrl == CONNCTRL_STREAM) && (conn->handler->flags & PROTOPT_STREAM)) - DEBUGF(infof(conn->data, "Kill stream: %s\n", reason)); + ; else if((bit)closeit != conn->bits.close) { - DEBUGF(infof(conn->data, "Marked for [%s]: %s\n", - closeit?"closure":"keep alive", reason)); conn->bits.close = closeit; /* the only place in the source code that should assign this bit */ } diff --git a/libs/libcurl/src/connect.h b/libs/libcurl/src/connect.h index 9b1faf8fb7..566b3531d7 100644 --- a/libs/libcurl/src/connect.h +++ b/libs/libcurl/src/connect.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,11 +27,13 @@ #include "sockaddr.h" #include "timeval.h" -CURLcode Curl_is_connected(struct connectdata *conn, +CURLcode Curl_is_connected(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool *connected); -CURLcode Curl_connecthost(struct connectdata *conn, +CURLcode Curl_connecthost(struct Curl_easy *data, + struct connectdata *conn, const struct Curl_dns_entry *host); /* generic function that returns how much time there's left to run, according @@ -74,11 +76,16 @@ void Curl_sndbufset(curl_socket_t sockfd); #define Curl_sndbufset(y) Curl_nop_stmt #endif -void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd); -void Curl_conninfo_remote(struct connectdata *conn, curl_socket_t sockfd); -void Curl_conninfo_local(struct connectdata *conn, curl_socket_t sockfd); -void Curl_persistconninfo(struct connectdata *conn); -int Curl_closesocket(struct connectdata *conn, curl_socket_t sock); +void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t sockfd); +void Curl_conninfo_remote(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t sockfd); +void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd, + char *local_ip, long *local_port); +void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn, + char *local_ip, long local_port); +int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t sock); /* * The Curl_sockaddr_ex structure is basically libcurl's external API @@ -106,7 +113,7 @@ struct Curl_sockaddr_ex { * socket callback is set, used that! * */ -CURLcode Curl_socket(struct connectdata *conn, +CURLcode Curl_socket(struct Curl_easy *data, const struct Curl_addrinfo *ai, struct Curl_sockaddr_ex *addr, curl_socket_t *sockfd); diff --git a/libs/libcurl/src/content_encoding.c b/libs/libcurl/src/content_encoding.c index 82fcc2b83f..f179b81796 100644 --- a/libs/libcurl/src/content_encoding.c +++ b/libs/libcurl/src/content_encoding.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -104,9 +104,8 @@ zfree_cb(voidpf opaque, voidpf ptr) } static CURLcode -process_zlib_error(struct connectdata *conn, z_stream *z) +process_zlib_error(struct Curl_easy *data, z_stream *z) { - struct Curl_easy *data = conn->data; if(z->msg) failf(data, "Error while processing content unencoding: %s", z->msg); @@ -118,7 +117,7 @@ process_zlib_error(struct connectdata *conn, z_stream *z) } static CURLcode -exit_zlib(struct connectdata *conn, +exit_zlib(struct Curl_easy *data, z_stream *z, zlibInitState *zlib_init, CURLcode result) { if(*zlib_init == ZLIB_GZIP_HEADER) @@ -126,14 +125,14 @@ exit_zlib(struct connectdata *conn, if(*zlib_init != ZLIB_UNINIT) { if(inflateEnd(z) != Z_OK && result == CURLE_OK) - result = process_zlib_error(conn, z); + result = process_zlib_error(data, z); *zlib_init = ZLIB_UNINIT; } return result; } -static CURLcode process_trailer(struct connectdata *conn, +static CURLcode process_trailer(struct Curl_easy *data, struct zlib_params *zp) { z_stream *z = &zp->z; @@ -149,7 +148,7 @@ static CURLcode process_trailer(struct connectdata *conn, if(z->avail_in) result = CURLE_WRITE_ERROR; if(result || !zp->trailerlen) - result = exit_zlib(conn, z, &zp->zlib_init, result); + result = exit_zlib(data, z, &zp->zlib_init, result); else { /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */ zp->zlib_init = ZLIB_EXTERNAL_TRAILER; @@ -157,7 +156,7 @@ static CURLcode process_trailer(struct connectdata *conn, return result; } -static CURLcode inflate_stream(struct connectdata *conn, +static CURLcode inflate_stream(struct Curl_easy *data, struct contenc_writer *writer, zlibInitState started) { @@ -174,13 +173,13 @@ static CURLcode inflate_stream(struct connectdata *conn, zp->zlib_init != ZLIB_INFLATING && zp->zlib_init != ZLIB_INIT_GZIP && zp->zlib_init != ZLIB_GZIP_INFLATING) - return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR); + return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR); /* Dynamically allocate a buffer for decompression because it's uncommonly large to hold on the stack */ decomp = malloc(DSIZ); if(decomp == NULL) - return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); + return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); /* because the buffer size is fixed, iteratively decompress and transfer to the client via downstream_write function. */ @@ -204,10 +203,10 @@ static CURLcode inflate_stream(struct connectdata *conn, if(z->avail_out != DSIZ) { if(status == Z_OK || status == Z_STREAM_END) { zp->zlib_init = started; /* Data started. */ - result = Curl_unencode_write(conn, writer->downstream, decomp, + result = Curl_unencode_write(data, writer->downstream, decomp, DSIZ - z->avail_out); if(result) { - exit_zlib(conn, z, &zp->zlib_init, result); + exit_zlib(data, z, &zp->zlib_init, result); break; } } @@ -223,7 +222,7 @@ static CURLcode inflate_stream(struct connectdata *conn, /* No more data to flush: just exit loop. */ break; case Z_STREAM_END: - result = process_trailer(conn, zp); + result = process_trailer(data, zp); break; case Z_DATA_ERROR: /* some servers seem to not generate zlib headers, so this is an attempt @@ -243,7 +242,7 @@ static CURLcode inflate_stream(struct connectdata *conn, } /* FALLTHROUGH */ default: - result = exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); + result = exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z)); break; } } @@ -260,7 +259,7 @@ static CURLcode inflate_stream(struct connectdata *conn, /* Deflate handler. */ -static CURLcode deflate_init_writer(struct connectdata *conn, +static CURLcode deflate_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { struct zlib_params *zp = (struct zlib_params *) &writer->params; @@ -274,12 +273,12 @@ static CURLcode deflate_init_writer(struct connectdata *conn, z->zfree = (free_func) zfree_cb; if(inflateInit(z) != Z_OK) - return process_zlib_error(conn, z); + return process_zlib_error(data, z); zp->zlib_init = ZLIB_INIT; return CURLE_OK; } -static CURLcode deflate_unencode_write(struct connectdata *conn, +static CURLcode deflate_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { @@ -291,19 +290,19 @@ static CURLcode deflate_unencode_write(struct connectdata *conn, z->avail_in = (uInt) nbytes; if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER) - return process_trailer(conn, zp); + return process_trailer(data, zp); /* Now uncompress the data */ - return inflate_stream(conn, writer, ZLIB_INFLATING); + return inflate_stream(data, writer, ZLIB_INFLATING); } -static void deflate_close_writer(struct connectdata *conn, +static void deflate_close_writer(struct Curl_easy *data, struct contenc_writer *writer) { struct zlib_params *zp = (struct zlib_params *) &writer->params; z_stream *z = &zp->z; /* zlib state structure */ - exit_zlib(conn, z, &zp->zlib_init, CURLE_OK); + exit_zlib(data, z, &zp->zlib_init, CURLE_OK); } static const struct content_encoding deflate_encoding = { @@ -317,7 +316,7 @@ static const struct content_encoding deflate_encoding = { /* Gzip handler. */ -static CURLcode gzip_init_writer(struct connectdata *conn, +static CURLcode gzip_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { struct zlib_params *zp = (struct zlib_params *) &writer->params; @@ -333,14 +332,14 @@ static CURLcode gzip_init_writer(struct connectdata *conn, if(strcmp(zlibVersion(), "1.2.0.4") >= 0) { /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) { - return process_zlib_error(conn, z); + return process_zlib_error(data, z); } zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ } else { /* we must parse the gzip header and trailer ourselves */ if(inflateInit2(z, -MAX_WBITS) != Z_OK) { - return process_zlib_error(conn, z); + return process_zlib_error(data, z); } zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */ zp->zlib_init = ZLIB_INIT; /* Initial call state */ @@ -433,7 +432,7 @@ static enum { } #endif -static CURLcode gzip_unencode_write(struct connectdata *conn, +static CURLcode gzip_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { @@ -445,13 +444,13 @@ static CURLcode gzip_unencode_write(struct connectdata *conn, z->next_in = (Bytef *) buf; z->avail_in = (uInt) nbytes; /* Now uncompress the data */ - return inflate_stream(conn, writer, ZLIB_INIT_GZIP); + return inflate_stream(data, writer, ZLIB_INIT_GZIP); } #ifndef OLD_ZLIB_SUPPORT /* Support for old zlib versions is compiled away and we are running with an old version, so return an error. */ - return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR); + return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR); #else /* This next mess is to get around the potential case where there isn't @@ -489,7 +488,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn, z->avail_in = (uInt) nbytes; z->next_in = malloc(z->avail_in); if(z->next_in == NULL) { - return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); + return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); } memcpy(z->next_in, buf, z->avail_in); zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */ @@ -498,7 +497,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn, case GZIP_BAD: default: - return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); + return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z)); } } @@ -511,7 +510,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn, z->avail_in += (uInt) nbytes; z->next_in = Curl_saferealloc(z->next_in, z->avail_in); if(z->next_in == NULL) { - return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); + return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); } /* Append the new block of data to the previous one */ memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes); @@ -532,7 +531,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn, case GZIP_BAD: default: - return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); + return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z)); } } @@ -541,7 +540,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn, case ZLIB_EXTERNAL_TRAILER: z->next_in = (Bytef *) buf; z->avail_in = (uInt) nbytes; - return process_trailer(conn, zp); + return process_trailer(data, zp); case ZLIB_GZIP_INFLATING: default: @@ -557,17 +556,17 @@ static CURLcode gzip_unencode_write(struct connectdata *conn, } /* We've parsed the header, now uncompress the data */ - return inflate_stream(conn, writer, ZLIB_GZIP_INFLATING); + return inflate_stream(data, writer, ZLIB_GZIP_INFLATING); #endif } -static void gzip_close_writer(struct connectdata *conn, +static void gzip_close_writer(struct Curl_easy *data, struct contenc_writer *writer) { struct zlib_params *zp = (struct zlib_params *) &writer->params; z_stream *z = &zp->z; /* zlib state structure */ - exit_zlib(conn, z, &zp->zlib_init, CURLE_OK); + exit_zlib(data, z, &zp->zlib_init, CURLE_OK); } static const struct content_encoding gzip_encoding = { @@ -626,11 +625,11 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be) return CURLE_WRITE_ERROR; } -static CURLcode brotli_init_writer(struct connectdata *conn, +static CURLcode brotli_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { struct brotli_params *bp = (struct brotli_params *) &writer->params; - (void) conn; + (void) data; if(!writer->downstream) return CURLE_WRITE_ERROR; @@ -639,7 +638,7 @@ static CURLcode brotli_init_writer(struct connectdata *conn, return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY; } -static CURLcode brotli_unencode_write(struct connectdata *conn, +static CURLcode brotli_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { @@ -664,7 +663,7 @@ static CURLcode brotli_unencode_write(struct connectdata *conn, dstleft = DSIZ; r = BrotliDecoderDecompressStream(bp->br, &nbytes, &src, &dstleft, &dst, NULL); - result = Curl_unencode_write(conn, writer->downstream, + result = Curl_unencode_write(data, writer->downstream, decomp, DSIZ - dstleft); if(result) break; @@ -687,11 +686,11 @@ static CURLcode brotli_unencode_write(struct connectdata *conn, return result; } -static void brotli_close_writer(struct connectdata *conn, +static void brotli_close_writer(struct Curl_easy *data, struct contenc_writer *writer) { struct brotli_params *bp = (struct brotli_params *) &writer->params; - (void) conn; + (void) data; if(bp->br) { BrotliDecoderDestroyInstance(bp->br); @@ -717,11 +716,11 @@ struct zstd_params { void *decomp; }; -static CURLcode zstd_init_writer(struct connectdata *conn, +static CURLcode zstd_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { struct zstd_params *zp = (struct zstd_params *)&writer->params; - (void)conn; + (void)data; if(!writer->downstream) return CURLE_WRITE_ERROR; @@ -731,9 +730,9 @@ static CURLcode zstd_init_writer(struct connectdata *conn, return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY; } -static CURLcode zstd_unencode_write(struct connectdata *conn, - struct contenc_writer *writer, - const char *buf, size_t nbytes) +static CURLcode zstd_unencode_write(struct Curl_easy *data, + struct contenc_writer *writer, + const char *buf, size_t nbytes) { CURLcode result = CURLE_OK; struct zstd_params *zp = (struct zstd_params *)&writer->params; @@ -760,7 +759,7 @@ static CURLcode zstd_unencode_write(struct connectdata *conn, return CURLE_BAD_CONTENT_ENCODING; } if(out.pos > 0) { - result = Curl_unencode_write(conn, writer->downstream, + result = Curl_unencode_write(data, writer->downstream, zp->decomp, out.pos); if(result) break; @@ -772,11 +771,11 @@ static CURLcode zstd_unencode_write(struct connectdata *conn, return result; } -static void zstd_close_writer(struct connectdata *conn, - struct contenc_writer *writer) +static void zstd_close_writer(struct Curl_easy *data, + struct contenc_writer *writer) { struct zstd_params *zp = (struct zstd_params *)&writer->params; - (void)conn; + (void)data; if(zp->decomp) { free(zp->decomp); @@ -800,24 +799,24 @@ static const struct content_encoding zstd_encoding = { /* Identity handler. */ -static CURLcode identity_init_writer(struct connectdata *conn, +static CURLcode identity_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { - (void) conn; + (void) data; return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR; } -static CURLcode identity_unencode_write(struct connectdata *conn, +static CURLcode identity_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { - return Curl_unencode_write(conn, writer->downstream, buf, nbytes); + return Curl_unencode_write(data, writer->downstream, buf, nbytes); } -static void identity_close_writer(struct connectdata *conn, +static void identity_close_writer(struct Curl_easy *data, struct contenc_writer *writer) { - (void) conn; + (void) data; (void) writer; } @@ -885,18 +884,17 @@ char *Curl_all_content_encodings(void) /* Real client writer: no downstream. */ -static CURLcode client_init_writer(struct connectdata *conn, +static CURLcode client_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { - (void) conn; + (void) data; return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK; } -static CURLcode client_unencode_write(struct connectdata *conn, +static CURLcode client_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { - struct Curl_easy *data = conn->data; struct SingleRequest *k = &data->req; (void) writer; @@ -904,13 +902,13 @@ static CURLcode client_unencode_write(struct connectdata *conn, if(!nbytes || k->ignorebody) return CURLE_OK; - return Curl_client_write(conn, CLIENTWRITE_BODY, (char *) buf, nbytes); + return Curl_client_write(data, CLIENTWRITE_BODY, (char *) buf, nbytes); } -static void client_close_writer(struct connectdata *conn, +static void client_close_writer(struct Curl_easy *data, struct contenc_writer *writer) { - (void) conn; + (void) data; (void) writer; } @@ -925,14 +923,14 @@ static const struct content_encoding client_encoding = { /* Deferred error dummy writer. */ -static CURLcode error_init_writer(struct connectdata *conn, +static CURLcode error_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { - (void) conn; + (void) data; return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR; } -static CURLcode error_unencode_write(struct connectdata *conn, +static CURLcode error_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { @@ -944,16 +942,16 @@ static CURLcode error_unencode_write(struct connectdata *conn, if(!all) return CURLE_OUT_OF_MEMORY; - failf(conn->data, "Unrecognized content encoding type. " - "libcurl understands %s content encodings.", all); + failf(data, "Unrecognized content encoding type. " + "libcurl understands %s content encodings.", all); free(all); return CURLE_BAD_CONTENT_ENCODING; } -static void error_close_writer(struct connectdata *conn, +static void error_close_writer(struct Curl_easy *data, struct contenc_writer *writer) { - (void) conn; + (void) data; (void) writer; } @@ -968,7 +966,7 @@ static const struct content_encoding error_encoding = { /* Create an unencoding writer stage using the given handler. */ static struct contenc_writer * -new_unencoding_writer(struct connectdata *conn, +new_unencoding_writer(struct Curl_easy *data, const struct content_encoding *handler, struct contenc_writer *downstream) { @@ -978,7 +976,7 @@ new_unencoding_writer(struct connectdata *conn, if(writer) { writer->handler = handler; writer->downstream = downstream; - if(handler->init_writer(conn, writer)) { + if(handler->init_writer(data, writer)) { free(writer); writer = NULL; } @@ -988,25 +986,24 @@ new_unencoding_writer(struct connectdata *conn, } /* Write data using an unencoding writer stack. */ -CURLcode Curl_unencode_write(struct connectdata *conn, +CURLcode Curl_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { if(!nbytes) return CURLE_OK; - return writer->handler->unencode_write(conn, writer, buf, nbytes); + return writer->handler->unencode_write(data, writer, buf, nbytes); } /* Close and clean-up the connection's writer stack. */ -void Curl_unencode_cleanup(struct connectdata *conn) +void Curl_unencode_cleanup(struct Curl_easy *data) { - struct Curl_easy *data = conn->data; struct SingleRequest *k = &data->req; struct contenc_writer *writer = k->writer_stack; while(writer) { k->writer_stack = writer->downstream; - writer->handler->close_writer(conn, writer); + writer->handler->close_writer(data, writer); free(writer); writer = k->writer_stack; } @@ -1029,10 +1026,9 @@ static const struct content_encoding *find_encoding(const char *name, /* Set-up the unencoding stack from the Content-Encoding header value. * See RFC 7231 section 3.1.2.2. */ -CURLcode Curl_build_unencoding_stack(struct connectdata *conn, +CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, const char *enclist, int maybechunked) { - struct Curl_easy *data = conn->data; struct SingleRequest *k = &data->req; do { @@ -1052,14 +1048,14 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn, /* Special case: chunked encoding is handled at the reader level. */ if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) { k->chunk = TRUE; /* chunks coming our way. */ - Curl_httpchunk_init(conn); /* init our chunky engine. */ + Curl_httpchunk_init(data); /* init our chunky engine. */ } else if(namelen) { const struct content_encoding *encoding = find_encoding(name, namelen); struct contenc_writer *writer; if(!k->writer_stack) { - k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL); + k->writer_stack = new_unencoding_writer(data, &client_encoding, NULL); if(!k->writer_stack) return CURLE_OUT_OF_MEMORY; @@ -1069,7 +1065,7 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn, encoding = &error_encoding; /* Defer error at stack use. */ /* Stack the unencoding stage. */ - writer = new_unencoding_writer(conn, encoding, k->writer_stack); + writer = new_unencoding_writer(data, encoding, k->writer_stack); if(!writer) return CURLE_OUT_OF_MEMORY; k->writer_stack = writer; @@ -1081,29 +1077,29 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn, #else /* Stubs for builds without HTTP. */ -CURLcode Curl_build_unencoding_stack(struct connectdata *conn, +CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, const char *enclist, int maybechunked) { - (void) conn; + (void) data; (void) enclist; (void) maybechunked; return CURLE_NOT_BUILT_IN; } -CURLcode Curl_unencode_write(struct connectdata *conn, +CURLcode Curl_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { - (void) conn; + (void) data; (void) writer; (void) buf; (void) nbytes; return CURLE_NOT_BUILT_IN; } -void Curl_unencode_cleanup(struct connectdata *conn) +void Curl_unencode_cleanup(struct Curl_easy *data) { - (void) conn; + (void) data; } char *Curl_all_content_encodings(void) diff --git a/libs/libcurl/src/content_encoding.h b/libs/libcurl/src/content_encoding.h index 70310875a0..acfd0c27b0 100644 --- a/libs/libcurl/src/content_encoding.h +++ b/libs/libcurl/src/content_encoding.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -33,23 +33,23 @@ struct contenc_writer { struct content_encoding { const char *name; /* Encoding name. */ const char *alias; /* Encoding name alias. */ - CURLcode (*init_writer)(struct connectdata *conn, + CURLcode (*init_writer)(struct Curl_easy *data, struct contenc_writer *writer); - CURLcode (*unencode_write)(struct connectdata *conn, + CURLcode (*unencode_write)(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes); - void (*close_writer)(struct connectdata *conn, + void (*close_writer)(struct Curl_easy *data, struct contenc_writer *writer); size_t paramsize; }; -CURLcode Curl_build_unencoding_stack(struct connectdata *conn, +CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, const char *enclist, int maybechunked); -CURLcode Curl_unencode_write(struct connectdata *conn, +CURLcode Curl_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes); -void Curl_unencode_cleanup(struct connectdata *conn); +void Curl_unencode_cleanup(struct Curl_easy *data); char *Curl_all_content_encodings(void); #endif /* HEADER_CURL_CONTENT_ENCODING_H */ diff --git a/libs/libcurl/src/cookie.c b/libs/libcurl/src/cookie.c index e88678c219..09fd092ac3 100644 --- a/libs/libcurl/src/cookie.c +++ b/libs/libcurl/src/cookie.c @@ -264,6 +264,11 @@ static const char *get_top_domain(const char * const domain, size_t *outlen) return first? first: domain; } +/* Avoid C1001, an "internal error" with MSVC14 */ +#if defined(_MSC_VER) && (_MSC_VER == 1900) +#pragma optimize("", off) +#endif + /* * A case-insensitive hash for the cookie domains. */ @@ -280,6 +285,10 @@ static size_t cookie_hash_domain(const char *domain, const size_t len) return (h % COOKIE_HASH_SIZE); } +#if defined(_MSC_VER) && (_MSC_VER == 1900) +#pragma optimize("", on) +#endif + /* * Hash this domain. */ diff --git a/libs/libcurl/src/cookie.h b/libs/libcurl/src/cookie.h index 066396f0d5..e0aa383bec 100644 --- a/libs/libcurl/src/cookie.h +++ b/libs/libcurl/src/cookie.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -34,12 +34,12 @@ struct Cookie { char *domain; /* domain = */ curl_off_t expires; /* expires = */ char *expirestr; /* the plain text version */ - bool tailmatch; /* whether we do tail-matching of the domain name */ /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ char *version; /* Version = */ char *maxage; /* Max-Age = */ + bool tailmatch; /* whether we do tail-matching of the domain name */ bool secure; /* whether the 'secure' keyword was used */ bool livecookie; /* updated from a server, not a stored file */ bool httponly; /* true if the httponly directive is present */ @@ -61,8 +61,8 @@ struct CookieInfo { struct Cookie *cookies[COOKIE_HASH_SIZE]; char *filename; /* file we read from/write to */ - bool running; /* state info, for cookie adding information */ long numcookies; /* number of cookies in the "jar" */ + bool running; /* state info, for cookie adding information */ bool newsession; /* new session, discard session cookies on load */ int lastct; /* last creation-time used in the jar */ }; diff --git a/libs/libcurl/src/curl_addrinfo.c b/libs/libcurl/src/curl_addrinfo.c index 872395b05a..06537b275f 100644 --- a/libs/libcurl/src/curl_addrinfo.c +++ b/libs/libcurl/src/curl_addrinfo.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -285,7 +285,7 @@ Curl_he2ai(const struct hostent *he, int port) #endif ss_size = sizeof(struct sockaddr_in); - /* allocate memory to told the struct, the address and the name */ + /* allocate memory to hold the struct, the address and the name */ ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen); if(!ai) { result = CURLE_OUT_OF_MEMORY; diff --git a/libs/libcurl/src/curl_config.h.cmake b/libs/libcurl/src/curl_config.h.cmake index 082d76b371..4c61a02c6e 100644 --- a/libs/libcurl/src/curl_config.h.cmake +++ b/libs/libcurl/src/curl_config.h.cmake @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1002,6 +1002,10 @@ ${SIZEOF_TIME_T_CODE} /* if OpenSSL is in use */ #cmakedefine USE_OPENSSL 1 +/* Define to 1 if you don't want the OpenSSL configuration to be loaded + automatically */ +#cmakedefine CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1 + /* to enable NGHTTP2 */ #cmakedefine USE_NGHTTP2 1 diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in index bd22a5e82a..fa5cf8de78 100644 --- a/libs/libcurl/src/curl_config.h.in +++ b/libs/libcurl/src/curl_config.h.in @@ -334,6 +334,9 @@ /* if you have MIT Kerberos */ #undef HAVE_GSSMIT +/* Define to 1 if you have the header file. */ +#undef HAVE_HYPER_H + /* Define to 1 if you have the header file. */ #undef HAVE_IDN2_H @@ -996,6 +999,9 @@ /* to enable HSTS */ #undef USE_HSTS +/* if hyper is in use */ +#undef USE_HYPER + /* PSL support enabled */ #undef USE_LIBPSL diff --git a/libs/libcurl/src/curl_gssapi.c b/libs/libcurl/src/curl_gssapi.c index f72430b26f..6445fbad09 100644 --- a/libs/libcurl/src/curl_gssapi.c +++ b/libs/libcurl/src/curl_gssapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2011 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2011 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -131,6 +131,10 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, display_gss_error(minor, GSS_C_MECH_CODE, buf, len); infof(data, "%s%s\n", prefix, buf); +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)data; + (void)prefix; +#endif } #endif /* HAVE_GSSAPI */ diff --git a/libs/libcurl/src/curl_krb5.h b/libs/libcurl/src/curl_krb5.h index f0a6fa69be..3f40f9a6ca 100644 --- a/libs/libcurl/src/curl_krb5.h +++ b/libs/libcurl/src/curl_krb5.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , 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,7 +26,7 @@ struct Curl_sec_client_mech { const char *name; size_t size; int (*init)(void *); - int (*auth)(void *, struct connectdata *); + int (*auth)(void *, struct Curl_easy *data, struct connectdata *); void (*end)(void *); int (*check_prot)(void *, int); int (*overhead)(void *, int, int); @@ -39,10 +39,10 @@ struct Curl_sec_client_mech { #define AUTH_ERROR 2 #ifdef HAVE_GSSAPI -int Curl_sec_read_msg(struct connectdata *conn, char *, +int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, char *, enum protection_level); void Curl_sec_end(struct connectdata *); -CURLcode Curl_sec_login(struct connectdata *); +CURLcode Curl_sec_login(struct Curl_easy *, struct connectdata *); int Curl_sec_request_prot(struct connectdata *conn, const char *level); #else #define Curl_sec_end(x) diff --git a/libs/libcurl/src/curl_ntlm_wb.c b/libs/libcurl/src/curl_ntlm_wb.c index c11757f557..9af79fd66a 100644 --- a/libs/libcurl/src/curl_ntlm_wb.c +++ b/libs/libcurl/src/curl_ntlm_wb.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -329,13 +329,16 @@ done: return CURLE_REMOTE_ACCESS_DENIED; } -CURLcode Curl_input_ntlm_wb(struct connectdata *conn, +CURLcode Curl_input_ntlm_wb(struct Curl_easy *data, + struct connectdata *conn, bool proxy, const char *header) { struct ntlmdata *ntlm = proxy ? &conn->proxyntlm : &conn->ntlm; curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state; + (void) data; /* In case it gets unused by nop log macros. */ + if(!checkprefix("NTLM", header)) return CURLE_BAD_CONTENT_ENCODING; @@ -352,17 +355,17 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn, } else { if(*state == NTLMSTATE_LAST) { - infof(conn->data, "NTLM auth restarted\n"); + infof(data, "NTLM auth restarted\n"); Curl_http_auth_cleanup_ntlm_wb(conn); } else if(*state == NTLMSTATE_TYPE3) { - infof(conn->data, "NTLM handshake rejected\n"); + infof(data, "NTLM handshake rejected\n"); Curl_http_auth_cleanup_ntlm_wb(conn); *state = NTLMSTATE_NONE; return CURLE_REMOTE_ACCESS_DENIED; } else if(*state >= NTLMSTATE_TYPE1) { - infof(conn->data, "NTLM handshake failure (internal error)\n"); + infof(data, "NTLM handshake failure (internal error)\n"); return CURLE_REMOTE_ACCESS_DENIED; } @@ -376,7 +379,8 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn, * This is for creating ntlm header output by delegating challenge/response * to Samba's winbind daemon helper ntlm_auth. */ -CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy) +CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn, + bool proxy) { /* point to the address of the pointer that holds the string to send to the server, which is for a plain host or for a HTTP proxy */ @@ -386,12 +390,11 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy) struct ntlmdata *ntlm; curlntlm *state; struct auth *authp; - struct Curl_easy *data = conn->data; CURLcode res = CURLE_OK; DEBUGASSERT(conn); - DEBUGASSERT(conn->data); + DEBUGASSERT(data); if(proxy) { #ifndef CURL_DISABLE_PROXY @@ -399,7 +402,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy) userp = conn->http_proxy.user; ntlm = &conn->proxyntlm; state = &conn->proxy_ntlm_state; - authp = &conn->data->state.authproxy; + authp = &data->state.authproxy; #else return CURLE_NOT_BUILT_IN; #endif @@ -409,7 +412,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy) userp = conn->user; ntlm = &conn->ntlm; state = &conn->http_ntlm_state; - authp = &conn->data->state.authhost; + authp = &data->state.authhost; } authp->done = FALSE; @@ -433,10 +436,10 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy) * request handling process. */ /* Create communication with ntlm_auth */ - res = ntlm_wb_init(conn->data, ntlm, userp); + res = ntlm_wb_init(data, ntlm, userp); if(res) return res; - res = ntlm_wb_response(conn->data, ntlm, "YR\n", *state); + res = ntlm_wb_response(data, ntlm, "YR\n", *state); if(res) return res; @@ -454,7 +457,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy) char *input = aprintf("TT %s\n", ntlm->challenge); if(!input) return CURLE_OUT_OF_MEMORY; - res = ntlm_wb_response(conn->data, ntlm, input, *state); + res = ntlm_wb_response(data, ntlm, input, *state); free(input); if(res) return res; diff --git a/libs/libcurl/src/curl_ntlm_wb.h b/libs/libcurl/src/curl_ntlm_wb.h index 4f847d22ca..961b568733 100644 --- a/libs/libcurl/src/curl_ntlm_wb.h +++ b/libs/libcurl/src/curl_ntlm_wb.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , 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,11 +28,13 @@ defined(NTLM_WB_ENABLED) /* this is for ntlm header input */ -CURLcode Curl_input_ntlm_wb(struct connectdata *conn, bool proxy, +CURLcode Curl_input_ntlm_wb(struct Curl_easy *data, + struct connectdata *conn, bool proxy, const char *header); /* this is for creating ntlm header output */ -CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy); +CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn, + bool proxy); void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn); diff --git a/libs/libcurl/src/curl_path.c b/libs/libcurl/src/curl_path.c index 8c8cbc2468..6100d77bd9 100644 --- a/libs/libcurl/src/curl_path.c +++ b/libs/libcurl/src/curl_path.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -31,12 +31,11 @@ #include "memdebug.h" /* figure out the path to work with in this particular request */ -CURLcode Curl_getworkingpath(struct connectdata *conn, +CURLcode Curl_getworkingpath(struct Curl_easy *data, char *homedir, /* when SFTP is used */ char **path) /* returns the allocated real path to work with */ { - struct Curl_easy *data = conn->data; char *real_path = NULL; char *working_path; size_t working_path_len; @@ -47,7 +46,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn, return result; /* Check for /~/, indicating relative to the user's home directory */ - if(conn->handler->protocol & CURLPROTO_SCP) { + if(data->conn->handler->protocol & CURLPROTO_SCP) { real_path = malloc(working_path_len + 1); if(real_path == NULL) { free(working_path); @@ -59,7 +58,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn, else memcpy(real_path, working_path, 1 + working_path_len); } - else if(conn->handler->protocol & CURLPROTO_SFTP) { + else if(data->conn->handler->protocol & CURLPROTO_SFTP) { if((working_path_len > 1) && (working_path[1] == '~')) { size_t homelen = strlen(homedir); real_path = malloc(homelen + working_path_len + 1); diff --git a/libs/libcurl/src/curl_path.h b/libs/libcurl/src/curl_path.h index b601b48dfc..a376bd1d2a 100644 --- a/libs/libcurl/src/curl_path.h +++ b/libs/libcurl/src/curl_path.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -39,7 +39,7 @@ have their definition hidden well */ #endif -CURLcode Curl_getworkingpath(struct connectdata *conn, +CURLcode Curl_getworkingpath(struct Curl_easy *data, char *homedir, char **path); diff --git a/libs/libcurl/src/curl_range.c b/libs/libcurl/src/curl_range.c index 0a87b1ca52..f7fb7c0824 100644 --- a/libs/libcurl/src/curl_range.c +++ b/libs/libcurl/src/curl_range.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -33,12 +33,11 @@ Check if this is a range download, and if so, set the internal variables properly. */ -CURLcode Curl_range(struct connectdata *conn) +CURLcode Curl_range(struct Curl_easy *data) { curl_off_t from, to; char *ptr; char *ptr2; - struct Curl_easy *data = conn->data; if(data->state.use_range && data->state.range) { CURLofft from_t; diff --git a/libs/libcurl/src/curl_range.h b/libs/libcurl/src/curl_range.h index d1f2c6d55f..0a07baf146 100644 --- a/libs/libcurl/src/curl_range.h +++ b/libs/libcurl/src/curl_range.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , 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,6 +25,5 @@ #include "curl_setup.h" #include "urldata.h" -CURLcode Curl_range(struct connectdata *conn); - +CURLcode Curl_range(struct Curl_easy *data); #endif /* HEADER_CURL_RANGE_H */ diff --git a/libs/libcurl/src/curl_rtmp.c b/libs/libcurl/src/curl_rtmp.c index ba471a2a19..fabdc88484 100644 --- a/libs/libcurl/src/curl_rtmp.c +++ b/libs/libcurl/src/curl_rtmp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * Copyright (C) 2010, Howard Chu, * * This software is licensed as described in the file COPYING, which @@ -48,11 +48,13 @@ #define DEF_BUFTIME (2*60*60*1000) /* 2 hours */ -static CURLcode rtmp_setup_connection(struct connectdata *conn); -static CURLcode rtmp_do(struct connectdata *conn, bool *done); -static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature); -static CURLcode rtmp_connect(struct connectdata *conn, bool *done); -static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead); +static CURLcode rtmp_setup_connection(struct Curl_easy *data, + struct connectdata *conn); +static CURLcode rtmp_do(struct Curl_easy *data, bool *done); +static CURLcode rtmp_done(struct Curl_easy *data, CURLcode, bool premature); +static CURLcode rtmp_connect(struct Curl_easy *data, bool *done); +static CURLcode rtmp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); static Curl_recv rtmp_recv; static Curl_send rtmp_send; @@ -193,7 +195,8 @@ const struct Curl_handler Curl_handler_rtmpts = { PROTOPT_NONE /* flags*/ }; -static CURLcode rtmp_setup_connection(struct connectdata *conn) +static CURLcode rtmp_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { RTMP *r = RTMP_Alloc(); if(!r) @@ -201,7 +204,7 @@ static CURLcode rtmp_setup_connection(struct connectdata *conn) RTMP_Init(r); RTMP_SetBufferMS(r, DEF_BUFTIME); - if(!RTMP_SetupURL(r, conn->data->change.url)) { + if(!RTMP_SetupURL(r, data->change.url)) { RTMP_Free(r); return CURLE_URL_MALFORMAT; } @@ -209,8 +212,9 @@ static CURLcode rtmp_setup_connection(struct connectdata *conn) return CURLE_OK; } -static CURLcode rtmp_connect(struct connectdata *conn, bool *done) +static CURLcode rtmp_connect(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; RTMP *r = conn->proto.rtmp; SET_RCVTIMEO(tv, 10); @@ -219,7 +223,7 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done) /* We have to know if it's a write before we send the * connect request packet */ - if(conn->data->set.upload) + if(data->set.upload) r->Link.protocol |= RTMP_FEATURE_WRITE; /* For plain streams, use the buffer toggle trick to keep data flowing */ @@ -243,15 +247,15 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done) return CURLE_OK; } -static CURLcode rtmp_do(struct connectdata *conn, bool *done) +static CURLcode rtmp_do(struct Curl_easy *data, bool *done) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; RTMP *r = conn->proto.rtmp; if(!RTMP_ConnectStream(r, 0)) return CURLE_FAILED_INIT; - if(conn->data->set.upload) { + if(data->set.upload) { Curl_pgrsSetUploadSize(data, data->state.infilesize); Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); } @@ -261,20 +265,22 @@ static CURLcode rtmp_do(struct connectdata *conn, bool *done) return CURLE_OK; } -static CURLcode rtmp_done(struct connectdata *conn, CURLcode status, +static CURLcode rtmp_done(struct Curl_easy *data, CURLcode status, bool premature) { - (void)conn; /* unused */ + (void)data; /* unused */ (void)status; /* unused */ (void)premature; /* unused */ return CURLE_OK; } -static CURLcode rtmp_disconnect(struct connectdata *conn, +static CURLcode rtmp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { RTMP *r = conn->proto.rtmp; + (void)data; (void)dead_connection; if(r) { conn->proto.rtmp = NULL; @@ -284,9 +290,10 @@ static CURLcode rtmp_disconnect(struct connectdata *conn, return CURLE_OK; } -static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf, +static ssize_t rtmp_recv(struct Curl_easy *data, int sockindex, char *buf, size_t len, CURLcode *err) { + struct connectdata *conn = data->conn; RTMP *r = conn->proto.rtmp; ssize_t nread; @@ -295,8 +302,8 @@ static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf, nread = RTMP_Read(r, buf, curlx_uztosi(len)); if(nread < 0) { if(r->m_read.status == RTMP_READ_COMPLETE || - r->m_read.status == RTMP_READ_EOF) { - conn->data->req.size = conn->data->req.bytecount; + r->m_read.status == RTMP_READ_EOF) { + data->req.size = data->req.bytecount; nread = 0; } else @@ -305,9 +312,10 @@ static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf, return nread; } -static ssize_t rtmp_send(struct connectdata *conn, int sockindex, +static ssize_t rtmp_send(struct Curl_easy *data, int sockindex, const void *buf, size_t len, CURLcode *err) { + struct connectdata *conn = data->conn; RTMP *r = conn->proto.rtmp; ssize_t num; diff --git a/libs/libcurl/src/curl_sasl.c b/libs/libcurl/src/curl_sasl.c index 94b17a1d86..ffeb75164d 100644 --- a/libs/libcurl/src/curl_sasl.c +++ b/libs/libcurl/src/curl_sasl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -194,7 +194,7 @@ void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params) * * This is the ONLY way to change SASL state! */ -static void state(struct SASL *sasl, struct connectdata *conn, +static void state(struct SASL *sasl, struct Curl_easy *data, saslstate newstate) { #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) @@ -221,10 +221,10 @@ static void state(struct SASL *sasl, struct connectdata *conn, }; if(sasl->state != newstate) - infof(conn->data, "SASL %p state change from %s to %s\n", + infof(data, "SASL %p state change from %s to %s\n", (void *)sasl, names[sasl->state], names[newstate]); #else - (void) conn; + (void) data; #endif sasl->state = newstate; @@ -253,11 +253,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 connectdata *conn, +CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, + struct connectdata *conn, bool force_ir, saslprogress *progress) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; unsigned int enabledmechs; const char *mech = NULL; char *resp = NULL; @@ -398,10 +398,10 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, resp = NULL; } - result = sasl->params->sendauth(conn, mech, resp); + result = sasl->params->sendauth(data, conn, mech, resp); if(!result) { *progress = SASL_INPROGRESS; - state(sasl, conn, resp ? state2 : state1); + state(sasl, data, resp ? state2 : state1); } } @@ -415,11 +415,11 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, * * Continue the authentication. */ -CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, +CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, + struct connectdata *conn, int code, saslprogress *progress) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; saslstate newstate = SASL_FINAL; char *resp = NULL; #ifndef CURL_DISABLE_PROXY @@ -450,14 +450,14 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, if(code != sasl->params->finalcode) result = CURLE_LOGIN_DENIED; *progress = SASL_DONE; - state(sasl, conn, SASL_STOP); + state(sasl, data, SASL_STOP); return result; } if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP && code != sasl->params->contcode) { *progress = SASL_DONE; - state(sasl, conn, SASL_STOP); + state(sasl, data, SASL_STOP); return CURLE_LOGIN_DENIED; } @@ -587,7 +587,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, if(code == sasl->params->finalcode) { /* Final response was received so we are done */ *progress = SASL_DONE; - state(sasl, conn, SASL_STOP); + state(sasl, data, SASL_STOP); return result; } else if(code == sasl->params->contcode) { @@ -600,7 +600,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, } else { *progress = SASL_DONE; - state(sasl, conn, SASL_STOP); + state(sasl, data, SASL_STOP); return CURLE_LOGIN_DENIED; } @@ -609,7 +609,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, sasl->authmechs ^= sasl->authused; /* Start an alternative SASL authentication */ - result = Curl_sasl_start(sasl, conn, sasl->force_ir, progress); + result = Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress); newstate = sasl->state; /* Use state from Curl_sasl_start() */ break; default: @@ -621,12 +621,12 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, switch(result) { case CURLE_BAD_CONTENT_ENCODING: /* Cancel dialog */ - result = sasl->params->sendcont(conn, "*"); + result = sasl->params->sendcont(data, conn, "*"); newstate = SASL_CANCEL; break; case CURLE_OK: if(resp) - result = sasl->params->sendcont(conn, resp); + result = sasl->params->sendcont(data, conn, resp); break; default: newstate = SASL_STOP; /* Stop on error */ @@ -636,7 +636,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, free(resp); - state(sasl, conn, newstate); + state(sasl, data, newstate); return result; } diff --git a/libs/libcurl/src/curl_sasl.h b/libs/libcurl/src/curl_sasl.h index ba40ec461a..75a957583a 100644 --- a/libs/libcurl/src/curl_sasl.h +++ b/libs/libcurl/src/curl_sasl.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -88,10 +88,12 @@ struct SASLproto { 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 connectdata *conn, + CURLcode (*sendauth)(struct Curl_easy *data, + struct connectdata *conn, const char *mech, const char *ir); /* Send authentication command */ - CURLcode (*sendcont)(struct connectdata *conn, const char *contauth); + CURLcode (*sendcont)(struct Curl_easy *data, + struct connectdata *conn, const char *contauth); /* Send authentication continuation */ void (*getmessage)(char *buffer, char **outptr); /* Get SASL response message */ @@ -133,11 +135,13 @@ void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params); 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 connectdata *conn, +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 connectdata *conn, +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_sha256.h b/libs/libcurl/src/curl_sha256.h index 0fceb6329a..b4579d7692 100644 --- a/libs/libcurl/src/curl_sha256.h +++ b/libs/libcurl/src/curl_sha256.h @@ -24,6 +24,9 @@ ***************************************************************************/ #ifndef CURL_DISABLE_CRYPTO_AUTH +#include "curl_hmac.h" + +extern const struct HMAC_params Curl_HMAC_SHA256[1]; #define SHA256_DIGEST_LENGTH 32 diff --git a/libs/libcurl/src/dict.c b/libs/libcurl/src/dict.c index 15d3954aa3..4319dadba5 100644 --- a/libs/libcurl/src/dict.c +++ b/libs/libcurl/src/dict.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -67,7 +67,7 @@ * Forward declarations. */ -static CURLcode dict_do(struct connectdata *conn, bool *done); +static CURLcode dict_do(struct Curl_easy *data, bool *done); /* * DICT protocol handler. @@ -129,10 +129,9 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff) } /* sendf() sends formatted data to the server */ -static CURLcode sendf(curl_socket_t sockfd, struct connectdata *conn, +static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data, const char *fmt, ...) { - struct Curl_easy *data = conn->data; ssize_t bytes_written; size_t write_len; CURLcode result = CURLE_OK; @@ -151,7 +150,7 @@ static CURLcode sendf(curl_socket_t sockfd, struct connectdata *conn, for(;;) { /* Write the buffer to the socket */ - result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written); + result = Curl_write(data, sockfd, sptr, write_len, &bytes_written); if(result) break; @@ -173,7 +172,7 @@ static CURLcode sendf(curl_socket_t sockfd, struct connectdata *conn, return result; } -static CURLcode dict_do(struct connectdata *conn, bool *done) +static CURLcode dict_do(struct Curl_easy *data, bool *done) { char *word; char *eword; @@ -183,7 +182,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) char *nthdef = NULL; /* This is not part of the protocol, but required by RFC 2229 */ CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; char *path = data->state.up.path; @@ -230,7 +229,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) if(!eword) return CURLE_OUT_OF_MEMORY; - result = sendf(sockfd, conn, + result = sendf(sockfd, data, "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" "MATCH " "%s " /* database */ @@ -278,7 +277,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) if(!eword) return CURLE_OUT_OF_MEMORY; - result = sendf(sockfd, conn, + result = sendf(sockfd, data, "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" "DEFINE " "%s " /* database */ @@ -306,7 +305,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) if(ppath[i] == ':') ppath[i] = ' '; } - result = sendf(sockfd, conn, + result = sendf(sockfd, data, "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" "%s\r\n" "QUIT\r\n", ppath); diff --git a/libs/libcurl/src/doh.c b/libs/libcurl/src/doh.c index c2b76de53a..004244c8d2 100644 --- a/libs/libcurl/src/doh.c +++ b/libs/libcurl/src/doh.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2018 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2018 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -187,19 +187,20 @@ doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp) } /* called from multi.c when this DOH transfer is complete */ -static int Curl_doh_done(struct Curl_easy *doh, CURLcode result) +static int doh_done(struct Curl_easy *doh, CURLcode result) { struct Curl_easy *data = doh->set.dohfor; + struct dohdata *dohp = data->req.doh; /* so one of the DOH request done for the 'data' transfer is now complete! */ - data->req.doh.pending--; - infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending); + dohp->pending--; + infof(data, "a DOH request is completed, %u to go\n", dohp->pending); if(result) infof(data, "DOH request %s\n", curl_easy_strerror(result)); - if(!data->req.doh.pending) { + if(!dohp->pending) { /* DOH completed */ - curl_slist_free_all(data->req.doh.headers); - data->req.doh.headers = NULL; + curl_slist_free_all(dohp->headers); + dohp->headers = NULL; Curl_expire(data, 0, EXPIRE_RUN_NOW); } return 0; @@ -225,7 +226,7 @@ static CURLcode dohprobe(struct Curl_easy *data, DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer), &p->dohlen); if(d) { - failf(data, "Failed to encode DOH packet [%d]\n", d); + failf(data, "Failed to encode DOH packet [%d]", d); return CURLE_OUT_OF_MEMORY; } @@ -354,7 +355,7 @@ static CURLcode dohprobe(struct Curl_easy *data, data->set.str[STRING_SSL_EC_CURVES]); } - doh->set.fmultidone = Curl_doh_done; + doh->set.fmultidone = doh_done; doh->set.dohfor = data; /* identify for which transfer this is done */ p->easy = doh; @@ -378,58 +379,64 @@ static CURLcode dohprobe(struct Curl_easy *data, * 'Curl_addrinfo *' with the address information. */ -struct Curl_addrinfo *Curl_doh(struct connectdata *conn, +struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, const char *hostname, int port, int *waitp) { - struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; int slot; + struct dohdata *dohp; + struct connectdata *conn = data->conn; *waitp = TRUE; /* this never returns synchronously */ - (void)conn; (void)hostname; (void)port; + DEBUGASSERT(!data->req.doh); + DEBUGASSERT(conn); + /* start clean, consider allocating this struct on demand */ - memset(&data->req.doh, 0, sizeof(struct dohdata)); + dohp = data->req.doh = calloc(sizeof(struct dohdata), 1); + if(!dohp) + return NULL; conn->bits.doh = TRUE; - data->req.doh.host = hostname; - data->req.doh.port = port; - data->req.doh.headers = + dohp->host = hostname; + dohp->port = port; + dohp->headers = curl_slist_append(NULL, "Content-Type: application/dns-message"); - if(!data->req.doh.headers) + if(!dohp->headers) goto error; if(conn->ip_version != CURL_IPRESOLVE_V6) { /* create IPv4 DOH request */ - result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4], + result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4], DNS_TYPE_A, hostname, data->set.str[STRING_DOH], - data->multi, data->req.doh.headers); + data->multi, dohp->headers); if(result) goto error; - data->req.doh.pending++; + dohp->pending++; } if(conn->ip_version != CURL_IPRESOLVE_V4) { /* create IPv6 DOH request */ - result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6], + result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6], DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH], - data->multi, data->req.doh.headers); + data->multi, dohp->headers); if(result) goto error; - data->req.doh.pending++; + dohp->pending++; } return NULL; error: - curl_slist_free_all(data->req.doh.headers); - data->req.doh.headers = NULL; + curl_slist_free_all(dohp->headers); + data->req.doh->headers = NULL; for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { - Curl_close(&data->req.doh.probe[slot].easy); + Curl_close(&dohp->probe[slot].easy); } + Curl_safefree(data->req.doh); return NULL; } @@ -468,7 +475,7 @@ static unsigned int get32bit(const unsigned char *doh, int index) the pointer first. */ doh += index; - /* avoid undefined behaviour by casting to unsigned before shifting + /* avoid undefined behavior by casting to unsigned before shifting 24 bits, possibly into the sign bit. codegen is same, but ub sanitizer won't be upset */ return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3]; @@ -904,20 +911,22 @@ UNITTEST void de_cleanup(struct dohentry *d) } } -CURLcode Curl_doh_is_resolved(struct connectdata *conn, +CURLcode Curl_doh_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dnsp) { CURLcode result; - struct Curl_easy *data = conn->data; + struct dohdata *dohp = data->req.doh; *dnsp = NULL; /* defaults to no response */ + if(!dohp) + return CURLE_OUT_OF_MEMORY; - if(!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4].easy && - !data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6].easy) { - failf(data, "Could not DOH-resolve: %s", conn->async.hostname); - return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: + if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy && + !dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) { + failf(data, "Could not DOH-resolve: %s", data->state.async.hostname); + return data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: CURLE_COULDNT_RESOLVE_HOST; } - else if(!data->req.doh.pending) { + else if(!dohp->pending) { DOHcode rc[DOH_PROBE_SLOTS] = { DOH_OK, DOH_OK }; @@ -925,13 +934,13 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, int slot; /* remove DOH handles from multi handle and close them */ for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { - curl_multi_remove_handle(data->multi, data->req.doh.probe[slot].easy); - Curl_close(&data->req.doh.probe[slot].easy); + curl_multi_remove_handle(data->multi, dohp->probe[slot].easy); + Curl_close(&dohp->probe[slot].easy); } /* parse the responses, create the struct and return it! */ de_init(&de); for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { - struct dnsprobe *p = &data->req.doh.probe[slot]; + struct dnsprobe *p = &dohp->probe[slot]; if(!p->dnstype) continue; rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh), @@ -941,7 +950,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, Curl_dyn_free(&p->serverdoh); if(rc[slot]) { infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]), - type2name(p->dnstype), data->req.doh.host); + type2name(p->dnstype), dohp->host); } } /* next slot */ @@ -951,10 +960,10 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, struct Curl_dns_entry *dns; struct Curl_addrinfo *ai; - infof(data, "DOH Host name: %s\n", data->req.doh.host); + infof(data, "DOH Host name: %s\n", dohp->host); showdoh(data, &de); - ai = doh2ai(&de, data->req.doh.host, data->req.doh.port); + ai = doh2ai(&de, dohp->host, dohp->port); if(!ai) { de_cleanup(&de); return CURLE_OUT_OF_MEMORY; @@ -964,7 +973,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* we got a response, store it in the cache */ - dns = Curl_cache_addr(data, ai, data->req.doh.host, data->req.doh.port); + dns = Curl_cache_addr(data, ai, dohp->host, dohp->port); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); @@ -974,7 +983,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, Curl_freeaddrinfo(ai); } else { - conn->async.dns = dns; + data->state.async.dns = dns; *dnsp = dns; result = CURLE_OK; /* address resolution OK */ } @@ -984,9 +993,10 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, /* All done */ de_cleanup(&de); + Curl_safefree(data->req.doh); return result; - } /* !data->req.doh.pending */ + } /* !dohp->pending */ /* else wait for pending DOH transactions to complete */ return CURLE_OK; diff --git a/libs/libcurl/src/doh.h b/libs/libcurl/src/doh.h index 0867584ced..b3584d1b27 100644 --- a/libs/libcurl/src/doh.h +++ b/libs/libcurl/src/doh.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2018 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2018 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,12 +32,12 @@ * and returns a 'Curl_addrinfo *' with the address information. */ -struct Curl_addrinfo *Curl_doh(struct connectdata *conn, +struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, const char *hostname, int port, int *waitp); -CURLcode Curl_doh_is_resolved(struct connectdata *conn, +CURLcode Curl_doh_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dns); int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks); diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c index dc790b01df..0fb255af49 100644 --- a/libs/libcurl/src/easy.c +++ b/libs/libcurl/src/easy.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -124,6 +124,10 @@ curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; # pragma warning(default:4232) /* MSVC extension, dllimport identity */ #endif +#ifdef DEBUGBUILD +static char *leakpointer; +#endif + /** * curl_global_init() globally initializes curl given a bitwise set of the * different features of what to initialize. @@ -190,6 +194,12 @@ static CURLcode global_init(long flags, bool memoryfuncs) init_flags = flags; +#ifdef DEBUGBUILD + if(getenv("CURL_GLOBAL_INIT")) + /* alloc data that will leak if *cleanup() is not called! */ + leakpointer = malloc(1); +#endif + return CURLE_OK; fail: @@ -265,6 +275,9 @@ void curl_global_cleanup(void) #ifdef USE_WOLFSSH (void)wolfSSH_Cleanup(); #endif +#ifdef DEBUGBUILD + free(leakpointer); +#endif init_flags = 0; } @@ -895,8 +908,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) #endif /* Clone the resolver handle, if present, for the new handle */ if(Curl_resolver_duphandle(outcurl, - &outcurl->state.resolver, - data->state.resolver)) + &outcurl->state.async.resolver, + data->state.async.resolver)) goto fail; #ifdef USE_ARES @@ -1059,7 +1072,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) /* even if one function returns error, this loops through and frees all buffers */ if(!result) - result = Curl_client_write(conn, writebuf[i].type, + result = Curl_client_write(data, writebuf[i].type, Curl_dyn_ptr(&writebuf[i].b), Curl_dyn_len(&writebuf[i].b)); Curl_dyn_free(&writebuf[i].b); @@ -1080,6 +1093,9 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) { Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */ + /* reset the too-slow time keeper */ + data->state.keeps_speed.tv_sec = 0; + if(!data->state.tempcount) /* if not pausing again, force a recv/send check of this connection as the data might've been read off the socket already */ @@ -1140,8 +1156,13 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen, if(result) return result; + if(!data->conn) + /* on first invoke, the transfer has been detached from the connection and + needs to be reattached */ + Curl_attach_connnection(data, c); + *n = 0; - result = Curl_read(c, sfd, buffer, buflen, &n1); + result = Curl_read(data, sfd, buffer, buflen, &n1); if(result) return result; @@ -1170,8 +1191,13 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, if(result) return result; + if(!data->conn) + /* on first invoke, the transfer has been detached from the connection and + needs to be reattached */ + Curl_attach_connnection(data, c); + *n = 0; - result = Curl_write(c, sfd, buffer, buflen, &n1); + result = Curl_write(data, sfd, buffer, buflen, &n1); if(n1 == -1) return CURLE_SEND_ERROR; @@ -1190,16 +1216,16 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, * * Returns always 0. */ -static int conn_upkeep(struct connectdata *conn, +static int conn_upkeep(struct Curl_easy *data, + struct connectdata *conn, void *param) { /* Param is unused. */ (void)param; - if(conn->handler->connection_check) { + if(conn->handler->connection_check) /* Do a protocol-specific keepalive check on the connection. */ - conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE); - } + conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE); return 0; /* continue iteration */ } diff --git a/libs/libcurl/src/easyoptions.c b/libs/libcurl/src/easyoptions.c index f236da23ab..b54829ba38 100644 --- a/libs/libcurl/src/easyoptions.c +++ b/libs/libcurl/src/easyoptions.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * ___|___/|_| ______| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,6 +35,7 @@ struct curl_easyoption Curl_easyopts[] = { {"ALTSVC_CTRL", CURLOPT_ALTSVC_CTRL, CURLOT_LONG, 0}, {"APPEND", CURLOPT_APPEND, CURLOT_LONG, 0}, {"AUTOREFERER", CURLOPT_AUTOREFERER, CURLOT_LONG, 0}, + {"AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0}, {"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0}, {"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0}, {"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0}, @@ -348,6 +349,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return (CURLOPT_LASTENTRY != (304 + 1)); + return ((CURLOPT_LASTENTRY%10000) != (305 + 1)); } #endif diff --git a/libs/libcurl/src/file.c b/libs/libcurl/src/file.c index a65eb7798d..dd8a1fd12a 100644 --- a/libs/libcurl/src/file.c +++ b/libs/libcurl/src/file.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -81,13 +81,15 @@ * Forward declarations. */ -static CURLcode file_do(struct connectdata *, bool *done); -static CURLcode file_done(struct connectdata *conn, +static CURLcode file_do(struct Curl_easy *data, bool *done); +static CURLcode file_done(struct Curl_easy *data, CURLcode status, bool premature); -static CURLcode file_connect(struct connectdata *conn, bool *done); -static CURLcode file_disconnect(struct connectdata *conn, +static CURLcode file_connect(struct Curl_easy *data, bool *done); +static CURLcode file_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection); -static CURLcode file_setup_connection(struct connectdata *conn); +static CURLcode file_setup_connection(struct Curl_easy *data, + struct connectdata *conn); /* * FILE scheme handler. @@ -116,11 +118,13 @@ const struct Curl_handler Curl_handler_file = { }; -static CURLcode file_setup_connection(struct connectdata *conn) +static CURLcode file_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { + (void)conn; /* allocate the FILE specific struct */ - conn->data->req.p.file = calloc(1, sizeof(struct FILEPROTO)); - if(!conn->data->req.p.file) + data->req.p.file = calloc(1, sizeof(struct FILEPROTO)); + if(!data->req.p.file) return CURLE_OUT_OF_MEMORY; return CURLE_OK; @@ -131,9 +135,8 @@ static CURLcode file_setup_connection(struct connectdata *conn) * do protocol-specific actions at connect-time. We emulate a * connect-then-transfer protocol and "connect" to the file here */ -static CURLcode file_connect(struct connectdata *conn, bool *done) +static CURLcode file_connect(struct Curl_easy *data, bool *done) { - struct Curl_easy *data = conn->data; char *real_path; struct FILEPROTO *file = data->req.p.file; int fd; @@ -198,7 +201,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done) file->fd = fd; if(!data->set.upload && (fd == -1)) { failf(data, "Couldn't open file %s", data->state.up.path); - file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); + file_done(data, CURLE_FILE_COULDNT_READ_FILE, FALSE); return CURLE_FILE_COULDNT_READ_FILE; } *done = TRUE; @@ -206,10 +209,10 @@ static CURLcode file_connect(struct connectdata *conn, bool *done) return CURLE_OK; } -static CURLcode file_done(struct connectdata *conn, - CURLcode status, bool premature) +static CURLcode file_done(struct Curl_easy *data, + CURLcode status, bool premature) { - struct FILEPROTO *file = conn->data->req.p.file; + struct FILEPROTO *file = data->req.p.file; (void)status; /* not used */ (void)premature; /* not used */ @@ -224,11 +227,13 @@ static CURLcode file_done(struct connectdata *conn, return CURLE_OK; } -static CURLcode file_disconnect(struct connectdata *conn, +static CURLcode file_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { (void)dead_connection; /* not used */ - return file_done(conn, 0, 0); + (void)conn; + return file_done(data, 0, 0); } #ifdef DOS_FILESYSTEM @@ -237,14 +242,13 @@ static CURLcode file_disconnect(struct connectdata *conn, #define DIRSEP '/' #endif -static CURLcode file_upload(struct connectdata *conn) +static CURLcode file_upload(struct Curl_easy *data) { - struct FILEPROTO *file = conn->data->req.p.file; + struct FILEPROTO *file = data->req.p.file; const char *dir = strchr(file->path, DIRSEP); int fd; int mode; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; char *buf = data->state.buffer; curl_off_t bytecount = 0; struct_stat file_stat; @@ -254,7 +258,7 @@ static CURLcode file_upload(struct connectdata *conn) * Since FILE: doesn't do the full init, we need to provide some extra * assignments here. */ - conn->data->req.upload_fromhere = buf; + data->req.upload_fromhere = buf; if(!dir) return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ @@ -273,7 +277,7 @@ static CURLcode file_upload(struct connectdata *conn) else mode = MODE_DEFAULT|O_TRUNC; - fd = open(file->path, mode, conn->data->set.new_file_perms); + fd = open(file->path, mode, data->set.new_file_perms); if(fd < 0) { failf(data, "Can't open %s for writing", file->path); return CURLE_WRITE_ERROR; @@ -297,7 +301,7 @@ static CURLcode file_upload(struct connectdata *conn) size_t nread; size_t nwrite; size_t readcount; - result = Curl_fillreadbuffer(conn, data->set.buffer_size, &readcount); + result = Curl_fillreadbuffer(data, data->set.buffer_size, &readcount); if(result) break; @@ -333,12 +337,12 @@ static CURLcode file_upload(struct connectdata *conn) Curl_pgrsSetUploadCounter(data, bytecount); - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; else result = Curl_speedcheck(data, Curl_now()); } - if(!result && Curl_pgrsUpdate(conn)) + if(!result && Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; close(fd); @@ -354,7 +358,7 @@ static CURLcode file_upload(struct connectdata *conn) * opposed to sockets) we instead perform the whole do-operation in this * function. */ -static CURLcode file_do(struct connectdata *conn, bool *done) +static CURLcode file_do(struct Curl_easy *data, bool *done) { /* This implementation ignores the host name in conformance with RFC 1738. Only local files (reachable via the standard file system) @@ -365,10 +369,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done) struct_stat statbuf; /* struct_stat instead of struct stat just to allow the Windows version to have a different struct without having to redefine the simple word 'stat' */ - curl_off_t expected_size = 0; + curl_off_t expected_size = -1; bool size_known; bool fstated = FALSE; - struct Curl_easy *data = conn->data; char *buf = data->state.buffer; curl_off_t bytecount = 0; int fd; @@ -379,17 +382,17 @@ static CURLcode file_do(struct connectdata *conn, bool *done) Curl_pgrsStartNow(data); if(data->set.upload) - return file_upload(conn); + return file_upload(data); - file = conn->data->req.p.file; + file = data->req.p.file; /* get the fd from the connection phase */ fd = file->fd; /* VMS: This only works reliable for STREAMLF files */ if(-1 != fstat(fd, &statbuf)) { - /* we could stat it, then read out the size */ - expected_size = statbuf.st_size; + if(!S_ISDIR(statbuf.st_mode)) + expected_size = statbuf.st_size; /* and store the modification time */ data->info.filetime = statbuf.st_mtime; fstated = TRUE; @@ -407,14 +410,16 @@ static CURLcode file_do(struct connectdata *conn, bool *done) struct tm buffer; const struct tm *tm = &buffer; char header[80]; - msnprintf(header, sizeof(header), - "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", - expected_size); - result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0); - if(result) - return result; + if(expected_size >= 0) { + msnprintf(header, sizeof(header), + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", + expected_size); + result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0); + if(result) + return result; + } - result = Curl_client_write(conn, CLIENTWRITE_HEADER, + result = Curl_client_write(data, CLIENTWRITE_HEADER, (char *)"Accept-ranges: bytes\r\n", 0); if(result) return result; @@ -435,7 +440,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done) tm->tm_min, tm->tm_sec, data->set.opt_no_body ? "": "\r\n"); - result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0); + result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0); if(result) return result; /* set the file size to make it available post transfer */ @@ -445,7 +450,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done) } /* Check whether file range has been specified */ - result = Curl_range(conn); + result = Curl_range(data); if(result) return result; @@ -514,18 +519,18 @@ static CURLcode file_do(struct connectdata *conn, bool *done) if(size_known) expected_size -= nread; - result = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread); + result = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread); if(result) return result; Curl_pgrsSetDownloadCounter(data, bytecount); - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; else result = Curl_speedcheck(data, Curl_now()); } - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; return result; diff --git a/libs/libcurl/src/formdata.h b/libs/libcurl/src/formdata.h index 5a021ceb92..09c6e9c28a 100644 --- a/libs/libcurl/src/formdata.h +++ b/libs/libcurl/src/formdata.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -29,22 +29,22 @@ /* used by FormAdd for temporary storage */ struct FormInfo { char *name; - bool name_alloc; size_t namelength; char *value; - bool value_alloc; curl_off_t contentslength; char *contenttype; - bool contenttype_alloc; long flags; char *buffer; /* pointer to existing buffer used for file upload */ size_t bufferlength; char *showfilename; /* The file name to show. If not set, the actual file name will be used */ - bool showfilename_alloc; char *userp; /* pointer for the read callback */ struct curl_slist *contentheader; struct FormInfo *more; + bool name_alloc; + bool value_alloc; + bool contenttype_alloc; + bool showfilename_alloc; }; CURLcode Curl_getformdata(struct Curl_easy *data, diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c index bc35574217..3818a9ea46 100644 --- a/libs/libcurl/src/ftp.c +++ b/libs/libcurl/src/ftp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -96,56 +96,63 @@ /* Local API functions */ #ifndef DEBUGBUILD -static void _state(struct connectdata *conn, +static void _state(struct Curl_easy *data, ftpstate newstate); #define state(x,y) _state(x,y) #else -static void _state(struct connectdata *conn, +static void _state(struct Curl_easy *data, ftpstate newstate, int lineno); #define state(x,y) _state(x,y,__LINE__) #endif -static CURLcode ftp_sendquote(struct connectdata *conn, +static CURLcode ftp_sendquote(struct Curl_easy *data, + struct connectdata *conn, struct curl_slist *quote); -static CURLcode ftp_quit(struct connectdata *conn); -static CURLcode ftp_parse_url_path(struct connectdata *conn); -static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done); +static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn); +static CURLcode ftp_parse_url_path(struct Curl_easy *data); +static CURLcode ftp_regular_transfer(struct Curl_easy *data, bool *done); #ifndef CURL_DISABLE_VERBOSE_STRINGS -static void ftp_pasv_verbose(struct connectdata *conn, +static void ftp_pasv_verbose(struct Curl_easy *data, struct Curl_addrinfo *ai, char *newhost, /* ascii version */ int port); #endif -static CURLcode ftp_state_prepare_transfer(struct connectdata *conn); -static CURLcode ftp_state_mdtm(struct connectdata *conn); -static CURLcode ftp_state_quote(struct connectdata *conn, +static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data); +static CURLcode ftp_state_mdtm(struct Curl_easy *data); +static CURLcode ftp_state_quote(struct Curl_easy *data, bool init, ftpstate instate); -static CURLcode ftp_nb_type(struct connectdata *conn, +static CURLcode ftp_nb_type(struct Curl_easy *data, + struct connectdata *conn, bool ascii, ftpstate newstate); static int ftp_need_type(struct connectdata *conn, bool ascii); -static CURLcode ftp_do(struct connectdata *conn, bool *done); -static CURLcode ftp_done(struct connectdata *conn, +static CURLcode ftp_do(struct Curl_easy *data, bool *done); +static CURLcode ftp_done(struct Curl_easy *data, CURLcode, bool premature); -static CURLcode ftp_connect(struct connectdata *conn, bool *done); -static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection); -static CURLcode ftp_do_more(struct connectdata *conn, int *completed); -static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done); -static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks); -static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks); -static CURLcode ftp_doing(struct connectdata *conn, +static CURLcode ftp_connect(struct Curl_easy *data, bool *done); +static CURLcode ftp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection); +static CURLcode ftp_do_more(struct Curl_easy *data, int *completed); +static CURLcode ftp_multi_statemach(struct Curl_easy *data, bool *done); +static int ftp_getsock(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t *socks); +static int ftp_domore_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); +static CURLcode ftp_doing(struct Curl_easy *data, bool *dophase_done); -static CURLcode ftp_setup_connection(struct connectdata *conn); -static CURLcode init_wc_data(struct connectdata *conn); -static CURLcode wc_statemach(struct connectdata *conn); +static CURLcode ftp_setup_connection(struct Curl_easy *data, + struct connectdata *conn); +static CURLcode init_wc_data(struct Curl_easy *data); +static CURLcode wc_statemach(struct Curl_easy *data); static void wc_data_dtor(void *ptr); -static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize); -static CURLcode ftp_readresp(curl_socket_t sockfd, +static CURLcode ftp_state_retr(struct Curl_easy *data, curl_off_t filesize); +static CURLcode ftp_readresp(struct Curl_easy *data, + curl_socket_t sockfd, struct pingpong *pp, int *ftpcode, size_t *size); -static CURLcode ftp_dophase_done(struct connectdata *conn, +static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected); /* @@ -206,10 +213,11 @@ const struct Curl_handler Curl_handler_ftps = { }; #endif -static void close_secondarysocket(struct connectdata *conn) +static void close_secondarysocket(struct Curl_easy *data, + struct connectdata *conn) { if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) { - Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]); conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; } conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; @@ -256,9 +264,9 @@ static void freedirs(struct ftp_conn *ftpc) * called to accept the connection and close the listening socket * */ -static CURLcode AcceptServerConnect(struct connectdata *conn) +static CURLcode AcceptServerConnect(struct Curl_easy *data) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; curl_socket_t sock = conn->sock[SECONDARYSOCKET]; curl_socket_t s = CURL_SOCKET_BAD; #ifdef ENABLE_IPV6 @@ -273,7 +281,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn) s = accept(sock, (struct sockaddr *) &add, &size); } - Curl_closesocket(conn, sock); /* close the first socket */ + Curl_closesocket(data, conn, sock); /* close the first socket */ if(CURL_SOCKET_BAD == s) { failf(data, "Error accept()ing server connect"); @@ -299,7 +307,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn) Curl_set_in_callback(data, false); if(error) { - close_secondarysocket(conn); + close_secondarysocket(data, conn); return CURLE_ABORTED_BY_CALLBACK; } } @@ -355,9 +363,9 @@ static timediff_t ftp_timeleft_accept(struct Curl_easy *data) * connection for a negative response regarding a failure in connecting * */ -static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) +static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET]; curl_socket_t data_sock = conn->sock[SECONDARYSOCKET]; struct ftp_conn *ftpc = &conn->proto.ftpc; @@ -381,7 +389,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) if(pp->cache_size && pp->cache && pp->cache[0] > '3') { /* Data connection could not be established, let's return */ infof(data, "There is negative response in cache while serv connect\n"); - (void)Curl_GetFTPResponse(&nread, conn, &ftpcode); + (void)Curl_GetFTPResponse(data, &nread, &ftpcode); return CURLE_FTP_ACCEPT_FAILED; } @@ -403,7 +411,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) } else if(result & CURL_CSELECT_IN) { infof(data, "Ctrl conn has data while waiting for data conn\n"); - (void)Curl_GetFTPResponse(&nread, conn, &ftpcode); + (void)Curl_GetFTPResponse(data, &nread, &ftpcode); if(ftpcode/100 > 3) return CURLE_FTP_ACCEPT_FAILED; @@ -426,16 +434,16 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) * setup transfer parameters and initiate the data transfer. * */ -static CURLcode InitiateTransfer(struct connectdata *conn) +static CURLcode InitiateTransfer(struct Curl_easy *data) { - struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; if(conn->bits.ftp_use_data_ssl) { /* since we only have a plaintext TCP connection here, we must now * do the TLS stuff */ infof(data, "Doing the SSL/TLS handshake on the data stream\n"); - result = Curl_ssl_connect(conn, SECONDARYSOCKET); + result = Curl_ssl_connect(data, conn, SECONDARYSOCKET); if(result) return result; } @@ -457,7 +465,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn) } conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */ - state(conn, FTP_STOP); + state(data, FTP_STOP); return CURLE_OK; } @@ -471,9 +479,8 @@ static CURLcode InitiateTransfer(struct connectdata *conn) * accepted. * */ -static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) +static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected) { - struct Curl_easy *data = conn->data; timediff_t timeout_ms; CURLcode result = CURLE_OK; @@ -491,16 +498,16 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) } /* see if the connection request is already here */ - result = ReceivedServerConnect(conn, connected); + result = ReceivedServerConnect(data, connected); if(result) return result; if(*connected) { - result = AcceptServerConnect(conn); + result = AcceptServerConnect(data); if(result) return result; - result = InitiateTransfer(conn); + result = InitiateTransfer(data); if(result) return result; } @@ -523,9 +530,10 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) /* macro to check for the last line in an FTP server response */ #define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3])) -static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len, - int *code) +static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn, + char *line, size_t len, int *code) { + (void)data; (void)conn; if((len > 3) && LASTLINE(line)) { @@ -536,34 +544,35 @@ static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len, return FALSE; } -static CURLcode ftp_readresp(curl_socket_t sockfd, +static CURLcode ftp_readresp(struct Curl_easy *data, + curl_socket_t sockfd, struct pingpong *pp, int *ftpcode, /* return the ftp-code if done */ size_t *size) /* size of the response */ { - struct connectdata *conn = pp->conn; - struct Curl_easy *data = conn->data; -#ifdef HAVE_GSSAPI - char * const buf = data->state.buffer; -#endif int code; - CURLcode result = Curl_pp_readresp(sockfd, pp, &code, size); + CURLcode result = Curl_pp_readresp(data, sockfd, pp, &code, size); -#if defined(HAVE_GSSAPI) - /* handle the security-oriented responses 6xx ***/ - switch(code) { - case 631: - code = Curl_sec_read_msg(conn, buf, PROT_SAFE); - break; - case 632: - code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE); - break; - case 633: - code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL); - break; - default: - /* normal ftp stuff we pass through! */ - break; +#ifdef HAVE_GSSAPI + { + struct connectdata *conn = data->conn; + char * const buf = data->state.buffer; + + /* handle the security-oriented responses 6xx ***/ + switch(code) { + case 631: + code = Curl_sec_read_msg(data, conn, buf, PROT_SAFE); + break; + case 632: + code = Curl_sec_read_msg(data, conn, buf, PROT_PRIVATE); + break; + case 633: + code = Curl_sec_read_msg(data, conn, buf, PROT_CONFIDENTIAL); + break; + default: + /* normal ftp stuff we pass through! */ + break; + } } #endif @@ -582,7 +591,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd, * generically is a good idea. */ infof(data, "We got a 421 - timeout!\n"); - state(conn, FTP_STOP); + state(data, FTP_STOP); return CURLE_OPERATION_TIMEDOUT; } @@ -597,8 +606,8 @@ static CURLcode ftp_readresp(curl_socket_t sockfd, * */ -CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ - struct connectdata *conn, +CURLcode Curl_GetFTPResponse(struct Curl_easy *data, + ssize_t *nreadp, /* return number of bytes read */ int *ftpcode) /* return the ftp-code */ { /* @@ -608,8 +617,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ * Alas, read as much as possible, split up into lines, use the ending * line in a response or continue reading. */ + struct connectdata *conn = data->conn; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; @@ -627,7 +636,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ while(!*ftpcode && !result) { /* check and reset timeout value every lap */ - timediff_t timeout = Curl_pp_state_timeout(pp, FALSE); + timediff_t timeout = Curl_pp_state_timeout(data, pp, FALSE); timediff_t interval_ms; if(timeout <= 0) { @@ -669,7 +678,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ return CURLE_RECV_ERROR; case 0: /* timeout */ - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) return CURLE_ABORTED_BY_CALLBACK; continue; /* just continue in our loop for the timeout duration */ @@ -677,7 +686,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ break; } } - result = ftp_readresp(sockfd, pp, ftpcode, &nread); + result = ftp_readresp(data, sockfd, pp, ftpcode, &nread); if(result) break; @@ -741,13 +750,14 @@ static const char * const ftp_state_names[]={ #endif /* This is the ONLY way to change FTP state! */ -static void _state(struct connectdata *conn, +static void _state(struct Curl_easy *data, ftpstate newstate #ifdef DEBUGBUILD , int lineno #endif ) { + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; #if defined(DEBUGBUILD) @@ -756,7 +766,7 @@ static void _state(struct connectdata *conn, (void) lineno; #else if(ftpc->state != newstate) - infof(conn->data, "FTP %p (line %d) state change from %s to %s\n", + infof(data, "FTP %p (line %d) state change from %s to %s\n", (void *)ftpc, lineno, ftp_state_names[ftpc->state], ftp_state_names[newstate]); #endif @@ -765,37 +775,43 @@ static void _state(struct connectdata *conn, ftpc->state = newstate; } -static CURLcode ftp_state_user(struct connectdata *conn) +static CURLcode ftp_state_user(struct Curl_easy *data, + struct connectdata *conn) { - CURLcode result = Curl_pp_sendf(&conn->proto.ftpc.pp, "USER %s", + CURLcode result = Curl_pp_sendf(data, + &conn->proto.ftpc.pp, "USER %s", conn->user?conn->user:""); if(!result) { - state(conn, FTP_USER); - conn->data->state.ftp_trying_alternative = FALSE; + state(data, FTP_USER); + data->state.ftp_trying_alternative = FALSE; } return result; } -static CURLcode ftp_state_pwd(struct connectdata *conn) +static CURLcode ftp_state_pwd(struct Curl_easy *data, + struct connectdata *conn) { - CURLcode result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "PWD"); + CURLcode result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PWD"); if(!result) - state(conn, FTP_PWD); + state(data, FTP_PWD); return result; } /* For the FTP "protocol connect" and "doing" phases only */ -static int ftp_getsock(struct connectdata *conn, +static int ftp_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { - return Curl_pp_getsock(&conn->proto.ftpc.pp, socks); + return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks); } /* For the FTP "DO_MORE" phase only */ -static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks) +static int ftp_domore_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { struct ftp_conn *ftpc = &conn->proto.ftpc; + (void)data; /* When in DO_MORE state, we could be either waiting for us to connect to a * remote site, or we could wait for that site to connect to us. Or just @@ -813,7 +829,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks) connect on the secondary connection */ socks[0] = conn->sock[FIRSTSOCKET]; - if(!conn->data->set.ftp_use_port) { + if(!data->set.ftp_use_port) { int s; int i; /* PORT is used to tell the server to connect to us, and during that we @@ -833,7 +849,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks) return bits; } - return Curl_pp_getsock(&conn->proto.ftpc.pp, socks); + return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks); } /* This is called after the FTP_QUOTE state is passed. @@ -842,17 +858,18 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks) the correct directory. It may also need to send MKD commands to create missing ones, if that option is enabled. */ -static CURLcode ftp_state_cwd(struct connectdata *conn) +static CURLcode ftp_state_cwd(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; struct ftp_conn *ftpc = &conn->proto.ftpc; if(ftpc->cwddone) /* already done and fine */ - result = ftp_state_mdtm(conn); + result = ftp_state_mdtm(data); else { /* FTPFILE_NOCWD with full path: expect ftpc->cwddone! */ - DEBUGASSERT((conn->data->set.ftp_filemethod != FTPFILE_NOCWD) || + DEBUGASSERT((data->set.ftp_filemethod != FTPFILE_NOCWD) || !(ftpc->dirdepth && ftpc->dirs[0][0] == '/')); ftpc->count2 = 0; /* count2 counts failed CWDs */ @@ -860,7 +877,7 @@ static CURLcode ftp_state_cwd(struct connectdata *conn) /* 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 = (conn->data->set.ftp_create_missing_dirs == 2)?1:0; + 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 */ @@ -870,23 +887,23 @@ static CURLcode ftp_state_cwd(struct connectdata *conn) where we ended up after login: */ ftpc->cwdcount = 0; /* we count this as the first path, then we add one for all upcoming ones in the ftp->dirs[] array */ - result = Curl_pp_sendf(&ftpc->pp, "CWD %s", ftpc->entrypath); + result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->entrypath); if(!result) - state(conn, FTP_CWD); + state(data, FTP_CWD); } else { if(ftpc->dirdepth) { ftpc->cwdcount = 1; /* issue the first CWD, the rest is sent when the CWD responses are received... */ - result = Curl_pp_sendf(&ftpc->pp, "CWD %s", + result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount -1]); if(!result) - state(conn, FTP_CWD); + state(data, FTP_CWD); } else { /* No CWD necessary */ - result = ftp_state_mdtm(conn); + result = ftp_state_mdtm(data); } } } @@ -899,12 +916,12 @@ typedef enum { DONE } ftpport; -static CURLcode ftp_state_use_port(struct connectdata *conn, +static CURLcode ftp_state_use_port(struct Curl_easy *data, ftpport fcmd) /* start with this */ { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; - struct Curl_easy *data = conn->data; curl_socket_t portsock = CURL_SOCKET_BAD; char myhost[MAX_IPADR_LEN + 1] = ""; @@ -1061,9 +1078,9 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, } /* resolv ip/host to ip */ - rc = Curl_resolv(conn, host, 0, FALSE, &h); + rc = Curl_resolv(data, host, 0, FALSE, &h); if(rc == CURLRESOLV_PENDING) - (void)Curl_resolver_wait_resolv(conn, &h); + (void)Curl_resolver_wait_resolv(data, &h); if(h) { res = h->addr; /* when we return from this function, we can forget about this entry @@ -1087,7 +1104,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, portsock = CURL_SOCKET_BAD; error = 0; for(ai = res; ai; ai = ai->ai_next) { - result = Curl_socket(conn, ai, NULL, &portsock); + result = Curl_socket(data, ai, NULL, &portsock); if(result) { error = SOCKERRNO; continue; @@ -1127,7 +1144,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { failf(data, "getsockname() failed: %s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); - Curl_closesocket(conn, portsock); + Curl_closesocket(data, conn, portsock); return CURLE_FTP_PORT_FAILED; } port = port_min; @@ -1137,7 +1154,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(error != EADDRINUSE && error != EACCES) { failf(data, "bind(port=%hu) failed: %s", port, Curl_strerror(error, buffer, sizeof(buffer))); - Curl_closesocket(conn, portsock); + Curl_closesocket(data, conn, portsock); return CURLE_FTP_PORT_FAILED; } } @@ -1150,7 +1167,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, /* maybe all ports were in use already*/ if(port > port_max) { failf(data, "bind() failed, we ran out of ports!"); - Curl_closesocket(conn, portsock); + Curl_closesocket(data, conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1160,7 +1177,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) { failf(data, "getsockname() failed: %s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); - Curl_closesocket(conn, portsock); + Curl_closesocket(data, conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1169,7 +1186,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(listen(portsock, 1)) { failf(data, "socket failure: %s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); - Curl_closesocket(conn, portsock); + Curl_closesocket(data, conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1218,17 +1235,17 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, * EPRT |2|1080::8:800:200C:417A|5282| */ - result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd], + result = Curl_pp_sendf(data, &ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd], sa->sa_family == AF_INET?1:2, myhost, port); if(result) { failf(data, "Failure sending EPRT command: %s", curl_easy_strerror(result)); - Curl_closesocket(conn, portsock); + Curl_closesocket(data, conn, portsock); /* don't retry using PORT */ ftpc->count1 = PORT; /* bail out */ - state(conn, FTP_STOP); + state(data, FTP_STOP); return result; } break; @@ -1251,13 +1268,13 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, *dest = 0; msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff)); - result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], target); + result = Curl_pp_sendf(data, &ftpc->pp, "%s %s", mode[fcmd], target); if(result) { failf(data, "Failure sending PORT command: %s", curl_easy_strerror(result)); - Curl_closesocket(conn, portsock); + Curl_closesocket(data, conn, portsock); /* bail out */ - state(conn, FTP_STOP); + state(data, FTP_STOP); return result; } break; @@ -1267,7 +1284,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, /* store which command was sent */ ftpc->count1 = fcmd; - close_secondarysocket(conn); + close_secondarysocket(data, conn); /* we set the secondary socket variable to this for now, it is only so that the cleanup function will close it in case we fail before the true @@ -1283,11 +1300,12 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, */ conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE; - state(conn, FTP_PORT); + state(data, FTP_PORT); return result; } -static CURLcode ftp_state_use_pasv(struct connectdata *conn) +static CURLcode ftp_state_use_pasv(struct Curl_easy *data, + struct connectdata *conn) { struct ftp_conn *ftpc = &conn->proto.ftpc; CURLcode result = CURLE_OK; @@ -1317,11 +1335,11 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn) modeoff = conn->bits.ftp_use_epsv?0:1; - result = Curl_pp_sendf(&ftpc->pp, "%s", mode[modeoff]); + result = Curl_pp_sendf(data, &ftpc->pp, "%s", mode[modeoff]); if(!result) { ftpc->count1 = modeoff; - state(conn, FTP_PASV); - infof(conn->data, "Connect data stream passively\n"); + state(data, FTP_PASV); + infof(data, "Connect data stream passively\n"); } return result; } @@ -1333,22 +1351,22 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn) * request is made. Thus, if an actual transfer is to be made this is where we * take off for real. */ -static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) +static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->req.p.ftp; - struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.p.ftp; + struct connectdata *conn = data->conn; if(ftp->transfer != FTPTRANSFER_BODY) { /* doesn't transfer any data */ /* still possibly do PRE QUOTE jobs */ - state(conn, FTP_RETR_PREQUOTE); - result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); + state(data, FTP_RETR_PREQUOTE); + result = ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE); } else if(data->set.ftp_use_port) { /* We have chosen to use the PORT (or similar) command */ - result = ftp_state_use_port(conn, EPRT); + result = ftp_state_use_port(data, EPRT); } else { /* We have chosen (this is default) to use the PASV (or similar) command */ @@ -1357,29 +1375,30 @@ static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) to prepare the server for the upcoming PASV */ struct ftp_conn *ftpc = &conn->proto.ftpc; if(!conn->proto.ftpc.file) - result = Curl_pp_sendf(&ftpc->pp, "PRET %s", + result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s", data->set.str[STRING_CUSTOMREQUEST]? data->set.str[STRING_CUSTOMREQUEST]: (data->set.ftp_list_only?"NLST":"LIST")); else if(data->set.upload) - result = Curl_pp_sendf(&ftpc->pp, "PRET STOR %s", + result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s", conn->proto.ftpc.file); else - result = Curl_pp_sendf(&ftpc->pp, "PRET RETR %s", + result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s", conn->proto.ftpc.file); if(!result) - state(conn, FTP_PRET); + state(data, FTP_PRET); } else - result = ftp_state_use_pasv(conn); + result = ftp_state_use_pasv(data, conn); } return result; } -static CURLcode ftp_state_rest(struct connectdata *conn) +static CURLcode ftp_state_rest(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->req.p.ftp; + struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) { @@ -1387,41 +1406,42 @@ static CURLcode ftp_state_rest(struct connectdata *conn) /* Determine if server can respond to REST command and therefore whether it supports range */ - result = Curl_pp_sendf(&ftpc->pp, "REST %d", 0); + result = Curl_pp_sendf(data, &ftpc->pp, "REST %d", 0); if(!result) - state(conn, FTP_REST); + state(data, FTP_REST); } else - result = ftp_state_prepare_transfer(conn); + result = ftp_state_prepare_transfer(data); return result; } -static CURLcode ftp_state_size(struct connectdata *conn) +static CURLcode ftp_state_size(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->req.p.ftp; + struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) { /* if a "head"-like request is being made (on a file) */ /* we know ftpc->file is a valid pointer to a file name */ - result = Curl_pp_sendf(&ftpc->pp, "SIZE %s", ftpc->file); + result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file); if(!result) - state(conn, FTP_SIZE); + state(data, FTP_SIZE); } else - result = ftp_state_rest(conn); + result = ftp_state_rest(data, conn); return result; } -static CURLcode ftp_state_list(struct connectdata *conn) +static CURLcode ftp_state_list(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct FTP *ftp = data->req.p.ftp; + struct connectdata *conn = data->conn; /* If this output is to be machine-parsed, the NLST command might be better to use, since the LIST command output is not specified or standard in any @@ -1473,32 +1493,32 @@ static CURLcode ftp_state_list(struct connectdata *conn) if(!cmd) return CURLE_OUT_OF_MEMORY; - result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd); + result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", cmd); free(cmd); if(!result) - state(conn, FTP_LIST); + state(data, FTP_LIST); return result; } -static CURLcode ftp_state_retr_prequote(struct connectdata *conn) +static CURLcode ftp_state_retr_prequote(struct Curl_easy *data) { /* We've sent the TYPE, now we must send the list of prequote strings */ - return ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); + return ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE); } -static CURLcode ftp_state_stor_prequote(struct connectdata *conn) +static CURLcode ftp_state_stor_prequote(struct Curl_easy *data) { /* We've sent the TYPE, now we must send the list of prequote strings */ - return ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE); + return ftp_state_quote(data, TRUE, FTP_STOR_PREQUOTE); } -static CURLcode ftp_state_type(struct connectdata *conn) +static CURLcode ftp_state_type(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->req.p.ftp; - struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.p.ftp; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; /* If we have selected NOBODY and HEADER, it means that we only want file @@ -1515,22 +1535,22 @@ static CURLcode ftp_state_type(struct connectdata *conn) /* Some servers return different sizes for different modes, and thus we must set the proper type before we check the size */ - result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE); + result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_TYPE); if(result) return result; } else - result = ftp_state_size(conn); + result = ftp_state_size(data, conn); return result; } /* This is called after the CWD commands have been done in the beginning of the DO phase */ -static CURLcode ftp_state_mdtm(struct connectdata *conn) +static CURLcode ftp_state_mdtm(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; /* Requested time of file or time-depended transfer? */ @@ -1538,25 +1558,25 @@ static CURLcode ftp_state_mdtm(struct connectdata *conn) /* we have requested to get the modified-time of the file, this is a white spot as the MDTM is not mentioned in RFC959 */ - result = Curl_pp_sendf(&ftpc->pp, "MDTM %s", ftpc->file); + result = Curl_pp_sendf(data, &ftpc->pp, "MDTM %s", ftpc->file); if(!result) - state(conn, FTP_MDTM); + state(data, FTP_MDTM); } else - result = ftp_state_type(conn); + result = ftp_state_type(data); return result; } /* This is called after the TYPE and possible quote commands have been sent */ -static CURLcode ftp_state_ul_setup(struct connectdata *conn, +static CURLcode ftp_state_ul_setup(struct Curl_easy *data, bool sizechecked) { CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->req.p.ftp; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; + struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; if((data->state.resume_from && !sizechecked) || @@ -1577,9 +1597,9 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, if(data->state.resume_from < 0) { /* Got no given size to start from, figure it out */ - result = Curl_pp_sendf(&ftpc->pp, "SIZE %s", ftpc->file); + result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file); if(!result) - state(conn, FTP_STOR_SIZE); + state(data, FTP_STOR_SIZE); return result; } @@ -1634,28 +1654,29 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, * ftp_done() because we didn't transfer anything! */ ftp->transfer = FTPTRANSFER_NONE; - state(conn, FTP_STOP); + state(data, FTP_STOP); return CURLE_OK; } } /* we've passed, proceed as normal */ } /* resume_from */ - result = Curl_pp_sendf(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s", + result = Curl_pp_sendf(data, &ftpc->pp, + data->set.ftp_append?"APPE %s":"STOR %s", ftpc->file); if(!result) - state(conn, FTP_STOR); + state(data, FTP_STOR); return result; } -static CURLcode ftp_state_quote(struct connectdata *conn, +static CURLcode ftp_state_quote(struct Curl_easy *data, bool init, ftpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct FTP *ftp = data->req.p.ftp; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; bool quote = FALSE; struct curl_slist *item; @@ -1702,10 +1723,10 @@ static CURLcode ftp_state_quote(struct connectdata *conn, else ftpc->count2 = 0; /* failure means cancel operation */ - result = Curl_pp_sendf(&ftpc->pp, "%s", cmd); + result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd); if(result) return result; - state(conn, instate); + state(data, instate); quote = TRUE; } } @@ -1715,15 +1736,15 @@ static CURLcode ftp_state_quote(struct connectdata *conn, switch(instate) { case FTP_QUOTE: default: - result = ftp_state_cwd(conn); + result = ftp_state_cwd(data, conn); break; case FTP_RETR_PREQUOTE: if(ftp->transfer != FTPTRANSFER_BODY) - state(conn, FTP_STOP); + state(data, FTP_STOP); else { if(ftpc->known_filesize != -1) { Curl_pgrsSetDownloadSize(data, ftpc->known_filesize); - result = ftp_state_retr(conn, ftpc->known_filesize); + result = ftp_state_retr(data, ftpc->known_filesize); } else { if(data->set.ignorecl) { @@ -1733,20 +1754,20 @@ static CURLcode ftp_state_quote(struct connectdata *conn, the server terminates it, otherwise the client stops if the received byte count exceeds the reported file size. Set option CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/ - result = Curl_pp_sendf(&ftpc->pp, "RETR %s", ftpc->file); + result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file); if(!result) - state(conn, FTP_RETR); + state(data, FTP_RETR); } else { - result = Curl_pp_sendf(&ftpc->pp, "SIZE %s", ftpc->file); + result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file); if(!result) - state(conn, FTP_RETR_SIZE); + state(data, FTP_RETR_SIZE); } } } break; case FTP_STOR_PREQUOTE: - result = ftp_state_ul_setup(conn, FALSE); + result = ftp_state_ul_setup(data, FALSE); break; case FTP_POSTQUOTE: break; @@ -1758,7 +1779,8 @@ static CURLcode ftp_state_quote(struct connectdata *conn, /* called from ftp_state_pasv_resp to switch to PASV in case of EPSV problems */ -static CURLcode ftp_epsv_disable(struct connectdata *conn) +static CURLcode ftp_epsv_disable(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; @@ -1768,20 +1790,20 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn) #endif ) { /* We can't disable EPSV when doing IPv6, so this is instead a fail */ - failf(conn->data, "Failed EPSV attempt, exiting\n"); + failf(data, "Failed EPSV attempt, exiting"); return CURLE_WEIRD_SERVER_REPLY; } - infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n"); + infof(data, "Failed EPSV attempt. Disabling EPSV\n"); /* disable it for next transfer */ conn->bits.ftp_use_epsv = FALSE; - conn->data->state.errorbuf = FALSE; /* allow error message to get + data->state.errorbuf = FALSE; /* allow error message to get rewritten */ - result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "PASV"); + result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PASV"); if(!result) { conn->proto.ftpc.count1++; /* remain in/go to the FTP_PASV state */ - state(conn, FTP_PASV); + state(data, FTP_PASV); } return result; } @@ -1797,15 +1819,15 @@ static char *control_address(struct connectdata *conn) if(conn->bits.tunnel_proxy || conn->bits.socksproxy) return conn->host.name; #endif - return conn->ip_addr_str; + return conn->primary_ip; } -static CURLcode ftp_state_pasv_resp(struct connectdata *conn, +static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, int ftpcode) { + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; CURLcode result; - struct Curl_easy *data = conn->data; struct Curl_dns_entry *addr = NULL; enum resolve_t rc; unsigned short connectport; /* the local port connect() should use! */ @@ -1906,7 +1928,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, } else if(ftpc->count1 == 0) { /* EPSV failed, move on to PASV */ - return ftp_epsv_disable(conn); + return ftp_epsv_disable(data, conn); } else { failf(data, "Bad PASV/EPSV response: %03d", ftpcode); @@ -1922,11 +1944,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, */ const char * const host_name = conn->bits.socksproxy ? conn->socks_proxy.host.name : conn->http_proxy.host.name; - rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &addr); + rc = Curl_resolv(data, host_name, (int)conn->port, FALSE, &addr); if(rc == CURLRESOLV_PENDING) /* BLOCKING, ignores the return code but 'addr' will be NULL in case of failure */ - (void)Curl_resolver_wait_resolv(conn, &addr); + (void)Curl_resolver_wait_resolv(data, &addr); connectport = (unsigned short)conn->port; /* we connect to the proxy's port */ @@ -1944,17 +1966,17 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, /* postponed address resolution in case of tcp fastopen */ if(conn->bits.tcp_fastopen && !conn->bits.reuse && !ftpc->newhost[0]) { - Curl_conninfo_remote(conn, conn->sock[FIRSTSOCKET]); + Curl_conninfo_remote(data, conn, conn->sock[FIRSTSOCKET]); Curl_safefree(ftpc->newhost); ftpc->newhost = strdup(control_address(conn)); if(!ftpc->newhost) return CURLE_OUT_OF_MEMORY; } - rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr); + rc = Curl_resolv(data, ftpc->newhost, ftpc->newport, FALSE, &addr); if(rc == CURLRESOLV_PENDING) /* BLOCKING */ - (void)Curl_resolver_wait_resolv(conn, &addr); + (void)Curl_resolver_wait_resolv(data, &addr); connectport = ftpc->newport; /* we connect to the remote port */ @@ -1965,12 +1987,12 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, } conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; - result = Curl_connecthost(conn, addr); + result = Curl_connecthost(data, conn, addr); if(result) { Curl_resolv_unlock(data, addr); /* we're done using this address */ if(ftpc->count1 == 0 && ftpcode == 229) - return ftp_epsv_disable(conn); + return ftp_epsv_disable(data, conn); return result; } @@ -1984,7 +2006,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, if(data->set.verbose) /* this just dumps information about this second connection */ - ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport); + ftp_pasv_verbose(data, addr->addr, ftpc->newhost, connectport); Curl_resolv_unlock(data, addr); /* we're done using this address */ @@ -1995,15 +2017,15 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; conn->bits.do_more = TRUE; - state(conn, FTP_STOP); /* this phase is completed */ + state(data, FTP_STOP); /* this phase is completed */ return result; } -static CURLcode ftp_state_port_resp(struct connectdata *conn, +static CURLcode ftp_state_port_resp(struct Curl_easy *data, int ftpcode) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; ftpport fcmd = (ftpport)ftpc->count1; CURLcode result = CURLE_OK; @@ -2025,23 +2047,23 @@ static CURLcode ftp_state_port_resp(struct connectdata *conn, } else /* try next */ - result = ftp_state_use_port(conn, fcmd); + result = ftp_state_use_port(data, fcmd); } else { infof(data, "Connect data stream actively\n"); - state(conn, FTP_STOP); /* end of DO phase */ - result = ftp_dophase_done(conn, FALSE); + state(data, FTP_STOP); /* end of DO phase */ + result = ftp_dophase_done(data, FALSE); } return result; } -static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, +static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, int ftpcode) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct FTP *ftp = data->req.p.ftp; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; switch(ftpcode) { @@ -2088,7 +2110,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, tm->tm_hour, tm->tm_min, tm->tm_sec); - result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0); + result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf, 0); if(result) return result; } /* end of a ridiculous amount of conditionals */ @@ -2113,7 +2135,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, infof(data, "The requested document is not new enough\n"); ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ data->info.timecond = TRUE; - state(conn, FTP_STOP); + state(data, FTP_STOP); return CURLE_OK; } break; @@ -2122,7 +2144,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, infof(data, "The requested document is not old enough\n"); ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ data->info.timecond = TRUE; - state(conn, FTP_STOP); + state(data, FTP_STOP); return CURLE_OK; } break; @@ -2134,17 +2156,17 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, } if(!result) - result = ftp_state_type(conn); + result = ftp_state_type(data); return result; } -static CURLcode ftp_state_type_resp(struct connectdata *conn, +static CURLcode ftp_state_type_resp(struct Curl_easy *data, int ftpcode, ftpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; if(ftpcode/100 != 2) { /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a @@ -2158,23 +2180,23 @@ static CURLcode ftp_state_type_resp(struct connectdata *conn, ftpcode); if(instate == FTP_TYPE) - result = ftp_state_size(conn); + result = ftp_state_size(data, conn); else if(instate == FTP_LIST_TYPE) - result = ftp_state_list(conn); + result = ftp_state_list(data); else if(instate == FTP_RETR_TYPE) - result = ftp_state_retr_prequote(conn); + result = ftp_state_retr_prequote(data); else if(instate == FTP_STOR_TYPE) - result = ftp_state_stor_prequote(conn); + result = ftp_state_stor_prequote(data); return result; } -static CURLcode ftp_state_retr(struct connectdata *conn, - curl_off_t filesize) +static CURLcode ftp_state_retr(struct Curl_easy *data, + curl_off_t filesize) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct FTP *ftp = data->req.p.ftp; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; if(data->set.max_filesize && (filesize > data->set.max_filesize)) { @@ -2229,7 +2251,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn, /* Set ->transfer so that we won't get any error in ftp_done() * because we didn't transfer the any file */ ftp->transfer = FTPTRANSFER_NONE; - state(conn, FTP_STOP); + state(data, FTP_STOP); return CURLE_OK; } @@ -2237,27 +2259,26 @@ static CURLcode ftp_state_retr(struct connectdata *conn, infof(data, "Instructs server to resume from offset %" CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from); - result = Curl_pp_sendf(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T, + result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T, data->state.resume_from); if(!result) - state(conn, FTP_RETR_REST); + state(data, FTP_RETR_REST); } else { /* no resume */ - result = Curl_pp_sendf(&ftpc->pp, "RETR %s", ftpc->file); + result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file); if(!result) - state(conn, FTP_RETR); + state(data, FTP_RETR); } return result; } -static CURLcode ftp_state_size_resp(struct connectdata *conn, +static CURLcode ftp_state_size_resp(struct Curl_easy *data, int ftpcode, ftpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; curl_off_t filesize = -1; char *buf = data->state.buffer; @@ -2292,27 +2313,28 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn, char clbuf[128]; msnprintf(clbuf, sizeof(clbuf), "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize); - result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0); + result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, 0); if(result) return result; } #endif Curl_pgrsSetDownloadSize(data, filesize); - result = ftp_state_rest(conn); + result = ftp_state_rest(data, data->conn); } else if(instate == FTP_RETR_SIZE) { Curl_pgrsSetDownloadSize(data, filesize); - result = ftp_state_retr(conn, filesize); + result = ftp_state_retr(data, filesize); } else if(instate == FTP_STOR_SIZE) { data->state.resume_from = filesize; - result = ftp_state_ul_setup(conn, TRUE); + result = ftp_state_ul_setup(data, TRUE); } return result; } -static CURLcode ftp_state_rest_resp(struct connectdata *conn, +static CURLcode ftp_state_rest_resp(struct Curl_easy *data, + struct connectdata *conn, int ftpcode, ftpstate instate) { @@ -2325,23 +2347,23 @@ static CURLcode ftp_state_rest_resp(struct connectdata *conn, #ifdef CURL_FTP_HTTPSTYLE_HEAD if(ftpcode == 350) { char buffer[24]= { "Accept-ranges: bytes\r\n" }; - result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0); + result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer, 0); if(result) return result; } #endif - result = ftp_state_prepare_transfer(conn); + result = ftp_state_prepare_transfer(data); break; case FTP_RETR_REST: if(ftpcode != 350) { - failf(conn->data, "Couldn't use REST"); + failf(data, "Couldn't use REST"); result = CURLE_FTP_COULDNT_USE_REST; } else { - result = Curl_pp_sendf(&ftpc->pp, "RETR %s", ftpc->file); + result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file); if(!result) - state(conn, FTP_RETR); + state(data, FTP_RETR); } break; } @@ -2349,15 +2371,15 @@ static CURLcode ftp_state_rest_resp(struct connectdata *conn, return result; } -static CURLcode ftp_state_stor_resp(struct connectdata *conn, +static CURLcode ftp_state_stor_resp(struct Curl_easy *data, int ftpcode, ftpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; if(ftpcode >= 400) { failf(data, "Failed FTP upload: %0d", ftpcode); - state(conn, FTP_STOP); + state(data, FTP_STOP); /* oops, we never close the sockets! */ return CURLE_UPLOAD_FAILED; } @@ -2368,9 +2390,9 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn, if(data->set.ftp_use_port) { bool connected; - state(conn, FTP_STOP); /* no longer in STOR state */ + state(data, FTP_STOP); /* no longer in STOR state */ - result = AllowServerConnect(conn, &connected); + result = AllowServerConnect(data, &connected); if(result) return result; @@ -2382,17 +2404,17 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn, return CURLE_OK; } - return InitiateTransfer(conn); + return InitiateTransfer(data); } /* for LIST and RETR responses */ -static CURLcode ftp_state_get_resp(struct connectdata *conn, - int ftpcode, - ftpstate instate) +static CURLcode ftp_state_get_resp(struct Curl_easy *data, + int ftpcode, + ftpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct FTP *ftp = data->req.p.ftp; + struct connectdata *conn = data->conn; if((ftpcode == 150) || (ftpcode == 125)) { @@ -2482,25 +2504,25 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn, if(data->set.ftp_use_port) { bool connected; - result = AllowServerConnect(conn, &connected); + result = AllowServerConnect(data, &connected); if(result) return result; if(!connected) { struct ftp_conn *ftpc = &conn->proto.ftpc; infof(data, "Data conn was not available immediately\n"); - state(conn, FTP_STOP); + state(data, FTP_STOP); ftpc->wait_data_conn = TRUE; } } else - return InitiateTransfer(conn); + return InitiateTransfer(data); } else { if((instate == FTP_LIST) && (ftpcode == 450)) { /* simply no matching files in the dir listing */ ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */ - state(conn, FTP_STOP); /* this phase is over */ + state(data, FTP_STOP); /* this phase is over */ } else { failf(data, "RETR response: %03d", ftpcode); @@ -2514,9 +2536,10 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn, } /* after USER, PASS and ACCT */ -static CURLcode ftp_state_loggedin(struct connectdata *conn) +static CURLcode ftp_state_loggedin(struct Curl_easy *data) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; if(conn->bits.ftp_use_control_ssl) { /* PBSZ = PROTECTION BUFFER SIZE. @@ -2533,23 +2556,23 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn) parameter of '0' to indicate that no buffering is taking place and the data connection should not be encapsulated. */ - result = Curl_pp_sendf(&conn->proto.ftpc.pp, "PBSZ %d", 0); + result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "PBSZ %d", 0); if(!result) - state(conn, FTP_PBSZ); + state(data, FTP_PBSZ); } else { - result = ftp_state_pwd(conn); + result = ftp_state_pwd(data, conn); } return result; } /* for USER and PASS responses */ -static CURLcode ftp_state_user_resp(struct connectdata *conn, +static CURLcode ftp_state_user_resp(struct Curl_easy *data, int ftpcode, ftpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; (void)instate; /* no use for this yet */ @@ -2557,21 +2580,22 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn, if((ftpcode == 331) && (ftpc->state == FTP_USER)) { /* 331 Password required for ... (the server requires to send the user's password too) */ - result = Curl_pp_sendf(&ftpc->pp, "PASS %s", conn->passwd?conn->passwd:""); + result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s", + conn->passwd?conn->passwd:""); if(!result) - state(conn, FTP_PASS); + state(data, FTP_PASS); } else if(ftpcode/100 == 2) { /* 230 User ... logged in. (the user logged in with or without password) */ - result = ftp_state_loggedin(conn); + result = ftp_state_loggedin(data); } else if(ftpcode == 332) { if(data->set.str[STRING_FTP_ACCOUNT]) { - result = Curl_pp_sendf(&ftpc->pp, "ACCT %s", + result = Curl_pp_sendf(data, &ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]); if(!result) - state(conn, FTP_ACCT); + state(data, FTP_ACCT); } else { failf(data, "ACCT requested but none available"); @@ -2584,15 +2608,15 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn, 530 User ... access denied (the server denies to log the specified user) */ - if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] && - !conn->data->state.ftp_trying_alternative) { + if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] && + !data->state.ftp_trying_alternative) { /* Ok, USER failed. Let's try the supplied command. */ result = - Curl_pp_sendf(&ftpc->pp, "%s", - conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); + Curl_pp_sendf(data, &ftpc->pp, "%s", + data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); if(!result) { - conn->data->state.ftp_trying_alternative = TRUE; - state(conn, FTP_USER); + data->state.ftp_trying_alternative = TRUE; + state(data, FTP_USER); } } else { @@ -2604,27 +2628,26 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn, } /* for ACCT response */ -static CURLcode ftp_state_acct_resp(struct connectdata *conn, +static CURLcode ftp_state_acct_resp(struct Curl_easy *data, int ftpcode) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; if(ftpcode != 230) { failf(data, "ACCT rejected by server: %03d", ftpcode); result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */ } else - result = ftp_state_loggedin(conn); + result = ftp_state_loggedin(data); return result; } -static CURLcode ftp_statemach_act(struct connectdata *conn) +static CURLcode ftp_statemachine(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result; curl_socket_t sock = conn->sock[FIRSTSOCKET]; - struct Curl_easy *data = conn->data; int ftpcode; struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; @@ -2632,9 +2655,9 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) size_t nread = 0; if(pp->sendleft) - return Curl_pp_flushsend(pp); + return Curl_pp_flushsend(data, pp); - result = ftp_readresp(sock, pp, &ftpcode, &nread); + result = ftp_readresp(data, sock, pp, &ftpcode, &nread); if(result) return result; @@ -2644,7 +2667,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) case FTP_WAIT220: if(ftpcode == 230) /* 230 User logged in - already! */ - return ftp_state_user_resp(conn, ftpcode, ftpc->state); + 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); @@ -2662,7 +2685,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) set a valid level */ Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]); - if(Curl_sec_login(conn)) + if(Curl_sec_login(data, conn)) infof(data, "Logging in with password in cleartext!\n"); else infof(data, "Authentication successful\n"); @@ -2689,12 +2712,13 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) (int)data->set.ftpsslauth); return CURLE_UNKNOWN_OPTION; /* we don't know what to do */ } - result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); + result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s", + ftpauth[ftpc->count1]); if(!result) - state(conn, FTP_AUTH); + state(data, FTP_AUTH); } else - result = ftp_state_user(conn); + result = ftp_state_user(data, conn); break; case FTP_AUTH: @@ -2709,17 +2733,18 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) if((ftpcode == 234) || (ftpcode == 334)) { /* Curl_ssl_connect is BLOCKING */ - result = Curl_ssl_connect(conn, FIRSTSOCKET); + result = Curl_ssl_connect(data, conn, FIRSTSOCKET); if(!result) { conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */ conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */ - result = ftp_state_user(conn); + result = ftp_state_user(data, conn); } } else if(ftpc->count3 < 1) { ftpc->count3++; ftpc->count1 += ftpc->count2; /* get next attempt */ - result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); + result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s", + ftpauth[ftpc->count1]); /* remain in this same state */ } else { @@ -2728,25 +2753,25 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) result = CURLE_USE_SSL_FAILED; else /* ignore the failure and continue */ - result = ftp_state_user(conn); + result = ftp_state_user(data, conn); } break; case FTP_USER: case FTP_PASS: - result = ftp_state_user_resp(conn, ftpcode, ftpc->state); + result = ftp_state_user_resp(data, ftpcode, ftpc->state); break; case FTP_ACCT: - result = ftp_state_acct_resp(conn, ftpcode); + result = ftp_state_acct_resp(data, ftpcode); break; case FTP_PBSZ: result = - Curl_pp_sendf(&ftpc->pp, "PROT %c", + Curl_pp_sendf(data, &ftpc->pp, "PROT %c", data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P'); if(!result) - state(conn, FTP_PROT); + state(data, FTP_PROT); break; case FTP_PROT: @@ -2763,25 +2788,25 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) if(data->set.ftp_ccc) { /* CCC - Clear Command Channel */ - result = Curl_pp_sendf(&ftpc->pp, "%s", "CCC"); + result = Curl_pp_sendf(data, &ftpc->pp, "%s", "CCC"); if(!result) - state(conn, FTP_CCC); + state(data, FTP_CCC); } else - result = ftp_state_pwd(conn); + result = ftp_state_pwd(data, conn); break; case FTP_CCC: if(ftpcode < 500) { /* First shut down the SSL layer (note: this call will block) */ - result = Curl_ssl_shutdown(conn, FIRSTSOCKET); + result = Curl_ssl_shutdown(data, conn, FIRSTSOCKET); if(result) - failf(conn->data, "Failed to clear the command channel (CCC)"); + failf(data, "Failed to clear the command channel (CCC)"); } if(!result) /* Then continue as normal */ - result = ftp_state_pwd(conn); + result = ftp_state_pwd(data, conn); break; case FTP_PWD: @@ -2847,7 +2872,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) systems. */ if(!ftpc->server_os && dir[0] != '/') { - result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST"); + result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SYST"); if(result) { free(dir); return result; @@ -2857,7 +2882,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) infof(data, "Entry path is '%s'\n", ftpc->entrypath); /* also save it where getinfo can access it: */ data->state.most_recent_ftp_entrypath = ftpc->entrypath; - state(conn, FTP_SYST); + state(data, FTP_SYST); break; } @@ -2873,7 +2898,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) infof(data, "Failed to figure out path\n"); } } - state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + state(data, FTP_STOP); /* we are done with the CONNECT phase! */ DEBUGF(infof(data, "protocol connect phase DONE\n")); break; @@ -2900,7 +2925,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) if(strcasecompare(os, "OS/400")) { /* Force OS400 name format 1. */ - result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1"); + result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SITE NAMEFMT 1"); if(result) { free(os); return result; @@ -2908,7 +2933,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) /* remember target server OS */ Curl_safefree(ftpc->server_os); ftpc->server_os = os; - state(conn, FTP_NAMEFMT); + state(data, FTP_NAMEFMT); break; } /* Nothing special for the target server. */ @@ -2920,18 +2945,18 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) /* Cannot identify server OS. Continue anyway and cross fingers. */ } - state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + state(data, FTP_STOP); /* we are done with the CONNECT phase! */ DEBUGF(infof(data, "protocol connect phase DONE\n")); break; case FTP_NAMEFMT: if(ftpcode == 250) { /* Name format change successful: reload initial path. */ - ftp_state_pwd(conn); + ftp_state_pwd(data, conn); break; } - state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + state(data, FTP_STOP); /* we are done with the CONNECT phase! */ DEBUGF(infof(data, "protocol connect phase DONE\n")); break; @@ -2941,24 +2966,24 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) case FTP_STOR_PREQUOTE: if((ftpcode >= 400) && !ftpc->count2) { /* failure response code, and not allowed to fail */ - failf(conn->data, "QUOT command failed with %03d", ftpcode); + failf(data, "QUOT command failed with %03d", ftpcode); result = CURLE_QUOTE_ERROR; } else - result = ftp_state_quote(conn, FALSE, ftpc->state); + result = ftp_state_quote(data, FALSE, ftpc->state); break; case FTP_CWD: if(ftpcode/100 != 2) { /* failure to CWD there */ - if(conn->data->set.ftp_create_missing_dirs && + if(data->set.ftp_create_missing_dirs && ftpc->cwdcount && !ftpc->count2) { /* try making it */ ftpc->count2++; /* counter to prevent CWD-MKD loops */ - result = Curl_pp_sendf(&ftpc->pp, "MKD %s", + result = Curl_pp_sendf(data, &ftpc->pp, "MKD %s", ftpc->dirs[ftpc->cwdcount - 1]); if(!result) - state(conn, FTP_MKD); + state(data, FTP_MKD); } else { /* return failure */ @@ -2973,10 +2998,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) ftpc->count2 = 0; if(++ftpc->cwdcount <= ftpc->dirdepth) /* send next CWD */ - result = Curl_pp_sendf(&ftpc->pp, "CWD %s", + result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]); else - result = ftp_state_mdtm(conn); + result = ftp_state_mdtm(data); } break; @@ -2987,33 +3012,33 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) result = CURLE_REMOTE_ACCESS_DENIED; } else { - state(conn, FTP_CWD); + state(data, FTP_CWD); /* send CWD */ - result = Curl_pp_sendf(&ftpc->pp, "CWD %s", + result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]); } break; case FTP_MDTM: - result = ftp_state_mdtm_resp(conn, ftpcode); + result = ftp_state_mdtm_resp(data, ftpcode); break; case FTP_TYPE: case FTP_LIST_TYPE: case FTP_RETR_TYPE: case FTP_STOR_TYPE: - result = ftp_state_type_resp(conn, ftpcode, ftpc->state); + result = ftp_state_type_resp(data, ftpcode, ftpc->state); break; case FTP_SIZE: case FTP_RETR_SIZE: case FTP_STOR_SIZE: - result = ftp_state_size_resp(conn, ftpcode, ftpc->state); + result = ftp_state_size_resp(data, ftpcode, ftpc->state); break; case FTP_REST: case FTP_RETR_REST: - result = ftp_state_rest_resp(conn, ftpcode, ftpc->state); + result = ftp_state_rest_resp(data, conn, ftpcode, ftpc->state); break; case FTP_PRET: @@ -3022,31 +3047,31 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) failf(data, "PRET command not accepted: %03d", ftpcode); return CURLE_FTP_PRET_FAILED; } - result = ftp_state_use_pasv(conn); + result = ftp_state_use_pasv(data, conn); break; case FTP_PASV: - result = ftp_state_pasv_resp(conn, ftpcode); + result = ftp_state_pasv_resp(data, ftpcode); break; case FTP_PORT: - result = ftp_state_port_resp(conn, ftpcode); + result = ftp_state_port_resp(data, ftpcode); break; case FTP_LIST: case FTP_RETR: - result = ftp_state_get_resp(conn, ftpcode, ftpc->state); + result = ftp_state_get_resp(data, ftpcode, ftpc->state); break; case FTP_STOR: - result = ftp_state_stor_resp(conn, ftpcode, ftpc->state); + result = ftp_state_stor_resp(data, ftpcode, ftpc->state); break; case FTP_QUIT: /* fallthrough, just stop! */ default: /* internal error */ - state(conn, FTP_STOP); + state(data, FTP_STOP); break; } } /* if(ftpcode) */ @@ -3056,11 +3081,12 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) /* called repeatedly until done from multi.c */ -static CURLcode ftp_multi_statemach(struct connectdata *conn, +static CURLcode ftp_multi_statemach(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; - CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE); + CURLcode result = Curl_pp_statemach(data, &ftpc->pp, FALSE, FALSE); /* Check for the state outside of the Curl_socket_check() return code checks since at times we are in fact already in this state when this function @@ -3070,14 +3096,15 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn, return result; } -static CURLcode ftp_block_statemach(struct connectdata *conn) +static CURLcode ftp_block_statemach(struct Curl_easy *data, + struct connectdata *conn) { struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; CURLcode result = CURLE_OK; while(ftpc->state != FTP_STOP) { - result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */); + result = Curl_pp_statemach(data, pp, TRUE, TRUE /* disconnecting */); if(result) break; } @@ -3093,10 +3120,11 @@ static CURLcode ftp_block_statemach(struct connectdata *conn) * phase is done when this function returns, or FALSE if not. * */ -static CURLcode ftp_connect(struct connectdata *conn, +static CURLcode ftp_connect(struct Curl_easy *data, bool *done) /* see description above */ { CURLcode result; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; @@ -3105,27 +3133,24 @@ static CURLcode ftp_connect(struct connectdata *conn, /* We always support persistent connections on ftp */ connkeep(conn, "FTP default"); - pp->response_time = RESP_TIMEOUT; /* set default response time-out */ - pp->statemach_act = ftp_statemach_act; - pp->endofresp = ftp_endofresp; - pp->conn = conn; + PINGPONG_SETUP(pp, ftp_statemachine, ftp_endofresp); if(conn->handler->flags & PROTOPT_SSL) { /* BLOCKING */ - result = Curl_ssl_connect(conn, FIRSTSOCKET); + result = Curl_ssl_connect(data, conn, FIRSTSOCKET); if(result) return result; conn->bits.ftp_use_control_ssl = TRUE; } Curl_pp_setup(pp); /* once per transfer */ - Curl_pp_init(pp); /* init the generic pingpong data */ + Curl_pp_init(data, pp); /* init the generic pingpong data */ /* When we connect, we start in the state where we await the 220 response */ - state(conn, FTP_WAIT220); + state(data, FTP_WAIT220); - result = ftp_multi_statemach(conn, done); + result = ftp_multi_statemach(data, done); return result; } @@ -3139,10 +3164,10 @@ static CURLcode ftp_connect(struct connectdata *conn, * * Input argument is already checked for validity. */ -static CURLcode ftp_done(struct connectdata *conn, CURLcode status, +static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, bool premature) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; @@ -3246,7 +3271,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) { if(!result && ftpc->dont_check && data->req.maxdownload > 0) { /* partial download completed */ - result = Curl_pp_sendf(pp, "%s", "ABOR"); + result = Curl_pp_sendf(data, pp, "%s", "ABOR"); if(result) { failf(data, "Failure sending ABOR command: %s", curl_easy_strerror(result)); @@ -3258,12 +3283,12 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, if(conn->ssl[SECONDARYSOCKET].use) { /* The secondary socket is using SSL so we must close down that part first before we close the socket for real */ - Curl_ssl_close(conn, SECONDARYSOCKET); + Curl_ssl_close(data, conn, SECONDARYSOCKET); /* Note that we keep "use" set to TRUE since that (next) connection is still requested to use SSL */ } - close_secondarysocket(conn); + close_secondarysocket(data, conn); } if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid && @@ -3279,7 +3304,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, pp->response_time = 60*1000; /* give it only a minute for now */ pp->response = Curl_now(); /* timeout relative now */ - result = Curl_GetFTPResponse(&nread, conn, &ftpcode); + result = Curl_GetFTPResponse(data, &nread, &ftpcode); pp->response_time = old_time; /* set this back to previous value */ @@ -3363,7 +3388,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, /* Send any post-transfer QUOTE strings? */ if(!status && !result && !premature && data->set.postquote) - result = ftp_sendquote(conn, data->set.postquote); + result = ftp_sendquote(data, conn, data->set.postquote); Curl_safefree(ftp->pathalloc); return result; } @@ -3379,7 +3404,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, */ static -CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote) +CURLcode ftp_sendquote(struct Curl_easy *data, + struct connectdata *conn, struct curl_slist *quote) { struct curl_slist *item; struct ftp_conn *ftpc = &conn->proto.ftpc; @@ -3404,16 +3430,16 @@ CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote) acceptfail = TRUE; } - result = Curl_pp_sendf(&ftpc->pp, "%s", cmd); + result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd); if(!result) { pp->response = Curl_now(); /* timeout relative now */ - result = Curl_GetFTPResponse(&nread, conn, &ftpcode); + result = Curl_GetFTPResponse(data, &nread, &ftpcode); } if(result) return result; if(!acceptfail && (ftpcode >= 400)) { - failf(conn->data, "QUOT string not accepted: %s", cmd); + failf(data, "QUOT string not accepted: %s", cmd); return CURLE_QUOTE_ERROR; } } @@ -3444,7 +3470,8 @@ static int ftp_need_type(struct connectdata *conn, * sets one of them. * If the transfer type is not sent, simulate on OK response in newstate */ -static CURLcode ftp_nb_type(struct connectdata *conn, +static CURLcode ftp_nb_type(struct Curl_easy *data, + struct connectdata *conn, bool ascii, ftpstate newstate) { struct ftp_conn *ftpc = &conn->proto.ftpc; @@ -3452,13 +3479,13 @@ static CURLcode ftp_nb_type(struct connectdata *conn, char want = (char)(ascii?'A':'I'); if(ftpc->transfertype == want) { - state(conn, newstate); - return ftp_state_type_resp(conn, 200, newstate); + state(data, newstate); + return ftp_state_type_resp(data, 200, newstate); } - result = Curl_pp_sendf(&ftpc->pp, "TYPE %c", want); + result = Curl_pp_sendf(data, &ftpc->pp, "TYPE %c", want); if(!result) { - state(conn, newstate); + state(data, newstate); /* keep track of our current transfer type */ ftpc->transfertype = want; @@ -3477,14 +3504,14 @@ static CURLcode ftp_nb_type(struct connectdata *conn, */ #ifndef CURL_DISABLE_VERBOSE_STRINGS static void -ftp_pasv_verbose(struct connectdata *conn, +ftp_pasv_verbose(struct Curl_easy *data, struct Curl_addrinfo *ai, char *newhost, /* ascii version */ int port) { char buf[256]; Curl_printable_address(ai, buf, sizeof(buf)); - infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port); + infof(data, "Connecting to %s (%s) port %d\n", newhost, buf, port); } #endif @@ -3499,9 +3526,9 @@ ftp_pasv_verbose(struct connectdata *conn, * EPSV). */ -static CURLcode ftp_do_more(struct connectdata *conn, int *completep) +static CURLcode ftp_do_more(struct Curl_easy *data, int *completep) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; CURLcode result = CURLE_OK; bool connected = FALSE; @@ -3515,12 +3542,12 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) if(Curl_connect_ongoing(conn)) { /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port aren't used so we blank their arguments. */ - result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0); + result = Curl_proxyCONNECT(data, SECONDARYSOCKET, NULL, 0); return result; } - result = Curl_is_connected(conn, SECONDARYSOCKET, &connected); + result = Curl_is_connected(data, conn, SECONDARYSOCKET, &connected); /* Ready to do more? */ if(connected) { @@ -3530,14 +3557,14 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) if(result && (ftpc->count1 == 0)) { *completep = -1; /* go back to DOING please */ /* this is a EPSV connect failing, try PASV instead */ - return ftp_epsv_disable(conn); + return ftp_epsv_disable(data, conn); } return result; } } #ifndef CURL_DISABLE_PROXY - result = Curl_proxy_connect(conn, SECONDARYSOCKET); + result = Curl_proxy_connect(data, SECONDARYSOCKET); if(result) return result; @@ -3552,7 +3579,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) if(ftpc->state) { /* already in a state so skip the initial commands. They are only done to kickstart the do_more state */ - result = ftp_multi_statemach(conn, &complete); + result = ftp_multi_statemach(data, &complete); *completep = (int)complete; @@ -3574,16 +3601,16 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) if(ftpc->wait_data_conn == TRUE) { bool serv_conned; - result = ReceivedServerConnect(conn, &serv_conned); + result = ReceivedServerConnect(data, &serv_conned); if(result) return result; /* Failed to accept data connection */ if(serv_conned) { /* It looks data connection is established */ - result = AcceptServerConnect(conn); + result = AcceptServerConnect(data); ftpc->wait_data_conn = FALSE; if(!result) - result = InitiateTransfer(conn); + result = InitiateTransfer(data); if(result) return result; @@ -3593,11 +3620,11 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) } } else if(data->set.upload) { - result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE); + result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_STOR_TYPE); if(result) return result; - result = ftp_multi_statemach(conn, &complete); + result = ftp_multi_statemach(data, &complete); /* ftpc->wait_data_conn is always false here */ *completep = (int)complete; } @@ -3605,7 +3632,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) /* download */ ftp->downloadsize = -1; /* unknown as of yet */ - result = Curl_range(conn); + result = Curl_range(data); if(result == CURLE_OK && data->req.maxdownload >= 0) { /* Don't check for successful transfer */ @@ -3621,19 +3648,20 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) /* But only if a body transfer was requested. */ if(ftp->transfer == FTPTRANSFER_BODY) { - result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE); + result = ftp_nb_type(data, conn, TRUE, FTP_LIST_TYPE); if(result) return result; } /* otherwise just fall through */ } else { - result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE); + result = ftp_nb_type(data, conn, data->set.prefer_ascii, + FTP_RETR_TYPE); if(result) return result; } - result = ftp_multi_statemach(conn, &complete); + result = ftp_multi_statemach(data, &complete); *completep = (int)complete; } return result; @@ -3662,37 +3690,38 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) */ static -CURLcode ftp_perform(struct connectdata *conn, +CURLcode ftp_perform(struct Curl_easy *data, bool *connected, /* connect status after PASV / PORT */ bool *dophase_done) { /* this is FTP and no proxy */ CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; - DEBUGF(infof(conn->data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts\n")); - if(conn->data->set.opt_no_body) { + if(data->set.opt_no_body) { /* requested no body means no transfer... */ - struct FTP *ftp = conn->data->req.p.ftp; + struct FTP *ftp = data->req.p.ftp; ftp->transfer = FTPTRANSFER_INFO; } *dophase_done = FALSE; /* not done yet */ /* start the first command in the DO phase */ - result = ftp_state_quote(conn, TRUE, FTP_QUOTE); + result = ftp_state_quote(data, TRUE, FTP_QUOTE); if(result) return result; /* run the state-machine */ - result = ftp_multi_statemach(conn, dophase_done); + result = ftp_multi_statemach(data, dophase_done); *connected = conn->bits.tcpconnect[SECONDARYSOCKET]; - infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected); + infof(data, "ftp_perform ends with SECONDARY: %d\n", *connected); if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete1\n")); + DEBUGF(infof(data, "DO phase is complete1\n")); return result; } @@ -3705,12 +3734,12 @@ static void wc_data_dtor(void *ptr) free(ftpwc); } -static CURLcode init_wc_data(struct connectdata *conn) +static CURLcode init_wc_data(struct Curl_easy *data) { char *last_slash; - struct FTP *ftp = conn->data->req.p.ftp; + struct FTP *ftp = data->req.p.ftp; char *path = ftp->path; - struct WildcardData *wildcard = &(conn->data->wildcard); + struct WildcardData *wildcard = &(data->wildcard); CURLcode result = CURLE_OK; struct ftp_wc *ftpwc = NULL; @@ -3719,7 +3748,7 @@ static CURLcode init_wc_data(struct connectdata *conn) last_slash++; if(last_slash[0] == '\0') { wildcard->state = CURLWC_CLEAN; - result = ftp_parse_url_path(conn); + result = ftp_parse_url_path(data); return result; } wildcard->pattern = strdup(last_slash); @@ -3736,7 +3765,7 @@ static CURLcode init_wc_data(struct connectdata *conn) } else { /* only list */ wildcard->state = CURLWC_CLEAN; - result = ftp_parse_url_path(conn); + result = ftp_parse_url_path(data); return result; } } @@ -3762,11 +3791,11 @@ static CURLcode init_wc_data(struct connectdata *conn) wildcard->dtor = wc_data_dtor; /* wildcard does not support NOCWD option (assert it?) */ - if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD) - conn->data->set.ftp_filemethod = FTPFILE_MULTICWD; + if(data->set.ftp_filemethod == FTPFILE_NOCWD) + data->set.ftp_filemethod = FTPFILE_MULTICWD; /* try to parse ftp url */ - result = ftp_parse_url_path(conn); + result = ftp_parse_url_path(data); if(result) { goto fail; } @@ -3778,15 +3807,15 @@ static CURLcode init_wc_data(struct connectdata *conn) } /* backup old write_function */ - ftpwc->backup.write_function = conn->data->set.fwrite_func; + ftpwc->backup.write_function = data->set.fwrite_func; /* parsing write function */ - conn->data->set.fwrite_func = Curl_ftp_parselist; + data->set.fwrite_func = Curl_ftp_parselist; /* backup old file descriptor */ - ftpwc->backup.file_descriptor = conn->data->set.out; - /* let the writefunc callback know what curl pointer is working with */ - conn->data->set.out = conn; + ftpwc->backup.file_descriptor = data->set.out; + /* let the writefunc callback know the transfer */ + data->set.out = data; - infof(conn->data, "Wildcard - Parsing started\n"); + infof(data, "Wildcard - Parsing started\n"); return CURLE_OK; fail: @@ -3800,15 +3829,16 @@ static CURLcode init_wc_data(struct connectdata *conn) return result; } -static CURLcode wc_statemach(struct connectdata *conn) +static CURLcode wc_statemach(struct Curl_easy *data) { - struct WildcardData * const wildcard = &(conn->data->wildcard); + struct WildcardData * const wildcard = &(data->wildcard); + struct connectdata *conn = data->conn; CURLcode result = CURLE_OK; for(;;) { switch(wildcard->state) { case CURLWC_INIT: - result = init_wc_data(conn); + result = init_wc_data(data); if(wildcard->state == CURLWC_CLEAN) /* only listing! */ return result; @@ -3819,8 +3849,8 @@ static CURLcode wc_statemach(struct connectdata *conn) /* In this state is LIST response successfully parsed, so lets restore previous WRITEFUNCTION callback and WRITEDATA pointer */ struct ftp_wc *ftpwc = wildcard->protdata; - conn->data->set.fwrite_func = ftpwc->backup.write_function; - conn->data->set.out = ftpwc->backup.file_descriptor; + data->set.fwrite_func = ftpwc->backup.write_function; + data->set.out = ftpwc->backup.file_descriptor; ftpwc->backup.write_function = ZERO_NULL; ftpwc->backup.file_descriptor = NULL; wildcard->state = CURLWC_DOWNLOADING; @@ -3842,7 +3872,7 @@ static CURLcode wc_statemach(struct connectdata *conn) /* filelist has at least one file, lets get first one */ struct ftp_conn *ftpc = &conn->proto.ftpc; struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; - struct FTP *ftp = conn->data->req.p.ftp; + struct FTP *ftp = data->req.p.ftp; char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); if(!tmp_path) @@ -3852,16 +3882,16 @@ static CURLcode wc_statemach(struct connectdata *conn) free(ftp->pathalloc); ftp->pathalloc = ftp->path = tmp_path; - infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); - if(conn->data->set.chunk_bgn) { + infof(data, "Wildcard - START of \"%s\"\n", finfo->filename); + if(data->set.chunk_bgn) { long userresponse; - Curl_set_in_callback(conn->data, true); - userresponse = conn->data->set.chunk_bgn( + Curl_set_in_callback(data, true); + userresponse = data->set.chunk_bgn( finfo, wildcard->customptr, (int)wildcard->filelist.size); - Curl_set_in_callback(conn->data, false); + Curl_set_in_callback(data, false); switch(userresponse) { case CURL_CHUNK_BGN_FUNC_SKIP: - infof(conn->data, "Wildcard - \"%s\" skipped by user\n", + infof(data, "Wildcard - \"%s\" skipped by user\n", finfo->filename); wildcard->state = CURLWC_SKIP; continue; @@ -3878,7 +3908,7 @@ static CURLcode wc_statemach(struct connectdata *conn) if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) ftpc->known_filesize = finfo->size; - result = ftp_parse_url_path(conn); + result = ftp_parse_url_path(data); if(result) return result; @@ -3895,10 +3925,10 @@ static CURLcode wc_statemach(struct connectdata *conn) } case CURLWC_SKIP: { - if(conn->data->set.chunk_end) { - Curl_set_in_callback(conn->data, true); - conn->data->set.chunk_end(conn->data->wildcard.customptr); - Curl_set_in_callback(conn->data, false); + if(data->set.chunk_end) { + Curl_set_in_callback(data, true); + data->set.chunk_end(data->wildcard.customptr); + Curl_set_in_callback(data, false); } Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); wildcard->state = (wildcard->filelist.size == 0) ? @@ -3936,18 +3966,19 @@ static CURLcode wc_statemach(struct connectdata *conn) * * The input argument is already checked for validity. */ -static CURLcode ftp_do(struct connectdata *conn, bool *done) +static CURLcode ftp_do(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; *done = FALSE; /* default to false */ ftpc->wait_data_conn = FALSE; /* default to no such wait */ - if(conn->data->state.wildcardmatch) { - result = wc_statemach(conn); - if(conn->data->wildcard.state == CURLWC_SKIP || - conn->data->wildcard.state == CURLWC_DONE) { + if(data->state.wildcardmatch) { + result = wc_statemach(data); + if(data->wildcard.state == CURLWC_SKIP || + data->wildcard.state == CURLWC_DONE) { /* do not call ftp_regular_transfer */ return CURLE_OK; } @@ -3955,12 +3986,12 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done) return result; } else { /* no wildcard FSM needed */ - result = ftp_parse_url_path(conn); + result = ftp_parse_url_path(data); if(result) return result; } - result = ftp_regular_transfer(conn, done); + result = ftp_regular_transfer(data, done); return result; } @@ -3975,24 +4006,24 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done) * connection. * */ -static CURLcode ftp_quit(struct connectdata *conn) +static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn) { CURLcode result = CURLE_OK; if(conn->proto.ftpc.ctl_valid) { - result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT"); + result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "QUIT"); if(result) { - failf(conn->data, "Failure sending QUIT command: %s", + failf(data, "Failure sending QUIT command: %s", curl_easy_strerror(result)); conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */ connclose(conn, "QUIT command failed"); /* mark for connection closure */ - state(conn, FTP_STOP); + state(data, FTP_STOP); return result; } - state(conn, FTP_QUIT); + state(data, FTP_QUIT); - result = ftp_block_statemach(conn); + result = ftp_block_statemach(data, conn); } return result; @@ -4005,7 +4036,9 @@ static CURLcode ftp_quit(struct connectdata *conn) * Disconnect from an FTP server. Cleanup protocol-specific per-connection * resources. BLOCKING. */ -static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode ftp_disconnect(struct Curl_easy *data, + struct connectdata *conn, + bool dead_connection) { struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; @@ -4021,10 +4054,9 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) ftpc->ctl_valid = FALSE; /* The FTP session may or may not have been allocated/setup at this point! */ - (void)ftp_quit(conn); /* ignore errors on the QUIT */ + (void)ftp_quit(data, conn); /* ignore errors on the QUIT */ if(ftpc->entrypath) { - struct Curl_easy *data = conn->data; if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) { data->state.most_recent_ftp_entrypath = NULL; } @@ -4047,11 +4079,11 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) * */ static -CURLcode ftp_parse_url_path(struct connectdata *conn) +CURLcode ftp_parse_url_path(struct Curl_easy *data) { - struct Curl_easy *data = conn->data; /* the ftp struct is already inited in ftp_connect() */ struct FTP *ftp = data->req.p.ftp; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; const char *slashPos = NULL; const char *fileName = NULL; @@ -4193,25 +4225,25 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) } /* call this when the DO phase has completed */ -static CURLcode ftp_dophase_done(struct connectdata *conn, - bool connected) +static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected) { - struct FTP *ftp = conn->data->req.p.ftp; + struct connectdata *conn = data->conn; + struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; if(connected) { int completed; - CURLcode result = ftp_do_more(conn, &completed); + CURLcode result = ftp_do_more(data, &completed); if(result) { - close_secondarysocket(conn); + close_secondarysocket(data, conn); return result; } } if(ftp->transfer != FTPTRANSFER_BODY) /* no data to transfer */ - Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); + Curl_setup_transfer(data, -1, -1, FALSE, -1); else if(!connected) /* since we didn't connect now, we want do_more to get called */ conn->bits.do_more = TRUE; @@ -4222,17 +4254,17 @@ static CURLcode ftp_dophase_done(struct connectdata *conn, } /* called from multi.c while DOing */ -static CURLcode ftp_doing(struct connectdata *conn, +static CURLcode ftp_doing(struct Curl_easy *data, bool *dophase_done) { - CURLcode result = ftp_multi_statemach(conn, dophase_done); + CURLcode result = ftp_multi_statemach(data, dophase_done); if(result) - DEBUGF(infof(conn->data, "DO phase failed\n")); + DEBUGF(infof(data, "DO phase failed\n")); else if(*dophase_done) { - result = ftp_dophase_done(conn, FALSE /* not connected */); + result = ftp_dophase_done(data, FALSE /* not connected */); - DEBUGF(infof(conn->data, "DO phase is complete2\n")); + DEBUGF(infof(data, "DO phase is complete2\n")); } return result; } @@ -4250,12 +4282,12 @@ static CURLcode ftp_doing(struct connectdata *conn, * ftp_done() function without finding any major problem. */ static -CURLcode ftp_regular_transfer(struct connectdata *conn, +CURLcode ftp_regular_transfer(struct Curl_easy *data, bool *dophase_done) { CURLcode result = CURLE_OK; bool connected = FALSE; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ftp_conn *ftpc = &conn->proto.ftpc; data->req.size = -1; /* make sure this is unknown at this point */ @@ -4266,7 +4298,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn, ftpc->ctl_valid = TRUE; /* starts good */ - result = ftp_perform(conn, + result = ftp_perform(data, &connected, /* have we connected after PASV/PORT */ dophase_done); /* all commands in the DO-phase done? */ @@ -4276,7 +4308,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn, /* the DO phase has not completed yet */ return CURLE_OK; - result = ftp_dophase_done(conn, connected); + result = ftp_dophase_done(data, connected); if(result) return result; @@ -4287,13 +4319,13 @@ CURLcode ftp_regular_transfer(struct connectdata *conn, return result; } -static CURLcode ftp_setup_connection(struct connectdata *conn) +static CURLcode ftp_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { - struct Curl_easy *data = conn->data; char *type; struct FTP *ftp; - conn->data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1); + data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1); if(NULL == ftp) return CURLE_OUT_OF_MEMORY; diff --git a/libs/libcurl/src/ftp.h b/libs/libcurl/src/ftp.h index 3ca1458ed8..1cfdac0851 100644 --- a/libs/libcurl/src/ftp.h +++ b/libs/libcurl/src/ftp.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -31,7 +31,7 @@ extern const struct Curl_handler Curl_handler_ftp; extern const struct Curl_handler Curl_handler_ftps; #endif -CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn, +CURLcode Curl_GetFTPResponse(struct Curl_easy *data, ssize_t *nread, int *ftpcode); #endif /* CURL_DISABLE_FTP */ @@ -116,9 +116,9 @@ struct FTP { struct ftp_conn { struct pingpong pp; char *entrypath; /* the PWD reply when we logged on */ + char *file; /* url-decoded file name (or path) */ char **dirs; /* realloc()ed array for path components */ int dirdepth; /* number of entries used in the 'dirs' array */ - char *file; /* url-decoded file name (or path) */ bool dont_check; /* Set to TRUE to prevent the final (post-transfer) file size and 226/250 status check. It should still read the line, just ignore the result. */ @@ -131,6 +131,10 @@ struct ftp_conn { bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent caching the current directory */ bool wait_data_conn; /* this is set TRUE if data connection is waited */ + /* newhost is the (allocated) IP addr or host name to connect the data + connection to */ + unsigned short newport; + char *newhost; char *prevpath; /* url-decoded conn->path from the previous transfer */ char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a and others (A/I or zero) */ @@ -145,10 +149,6 @@ struct ftp_conn { curl_off_t known_filesize; /* file size is different from -1, if wildcard LIST parsing was done and wc_statemach set it */ - /* newhost is the (allocated) IP addr or host name to connect the data - connection to */ - char *newhost; /* this is the pair to connect the DATA... */ - unsigned short newport; /* connection to */ }; #define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */ diff --git a/libs/libcurl/src/ftplistparser.c b/libs/libcurl/src/ftplistparser.c index 85b8a78d4f..d3720b1f10 100644 --- a/libs/libcurl/src/ftplistparser.c +++ b/libs/libcurl/src/ftplistparser.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -268,11 +268,11 @@ static int ftp_pl_get_permission(const char *str) return permissions; } -static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, +static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data, struct fileinfo *infop) { curl_fnmatch_callback compare; - struct WildcardData *wc = &conn->data->wildcard; + struct WildcardData *wc = &data->wildcard; struct ftp_wc *ftpwc = wc->protdata; struct Curl_llist *llist = &wc->filelist; struct ftp_parselist_data *parser = ftpwc->parser; @@ -293,13 +293,13 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, str + parser->offsets.user : NULL; /* get correct fnmatch callback */ - compare = conn->data->set.fnmatch; + compare = data->set.fnmatch; if(!compare) compare = Curl_fnmatch; /* filter pattern-corresponding filenames */ - Curl_set_in_callback(conn->data, true); - if(compare(conn->data->set.fnmatch_data, wc->pattern, + Curl_set_in_callback(data, true); + if(compare(data->set.fnmatch_data, wc->pattern, finfo->filename) == 0) { /* discard symlink which is containing multiple " -> " */ if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target && @@ -310,7 +310,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, else { add = FALSE; } - Curl_set_in_callback(conn->data, false); + Curl_set_in_callback(data, false); if(add) { Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list); @@ -327,8 +327,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) { size_t bufflen = size*nmemb; - struct connectdata *conn = (struct connectdata *)connptr; - struct ftp_wc *ftpwc = conn->data->wildcard.protdata; + struct Curl_easy *data = (struct Curl_easy *)connptr; + struct ftp_wc *ftpwc = data->wildcard.protdata; struct ftp_parselist_data *parser = ftpwc->parser; struct fileinfo *infop; struct curl_fileinfo *finfo; @@ -728,7 +728,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; parser->offsets.filename = parser->item_offset; parser->state.UNIX.main = PL_UNIX_FILETYPE; - result = ftp_pl_insert_finfo(conn, infop); + result = ftp_pl_insert_finfo(data, infop); if(result) { parser->error = result; goto fail; @@ -740,7 +740,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; parser->offsets.filename = parser->item_offset; parser->state.UNIX.main = PL_UNIX_FILETYPE; - result = ftp_pl_insert_finfo(conn, infop); + result = ftp_pl_insert_finfo(data, infop); if(result) { parser->error = result; goto fail; @@ -835,7 +835,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, else if(c == '\n') { finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; parser->offsets.symlink_target = parser->item_offset; - result = ftp_pl_insert_finfo(conn, infop); + result = ftp_pl_insert_finfo(data, infop); if(result) { parser->error = result; goto fail; @@ -847,7 +847,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, if(c == '\n') { finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; parser->offsets.symlink_target = parser->item_offset; - result = ftp_pl_insert_finfo(conn, infop); + result = ftp_pl_insert_finfo(data, infop); if(result) { parser->error = result; goto fail; @@ -967,7 +967,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, parser->offsets.filename = parser->item_offset; finfo->b_data[finfo->b_used - 1] = 0; parser->offsets.filename = parser->item_offset; - result = ftp_pl_insert_finfo(conn, infop); + result = ftp_pl_insert_finfo(data, infop); if(result) { parser->error = result; goto fail; @@ -979,7 +979,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, case PL_WINNT_FILENAME_WINEOL: if(c == '\n') { parser->offsets.filename = parser->item_offset; - result = ftp_pl_insert_finfo(conn, infop); + result = ftp_pl_insert_finfo(data, infop); if(result) { parser->error = result; goto fail; diff --git a/libs/libcurl/src/getinfo.c b/libs/libcurl/src/getinfo.c index fd8f4e8430..67ea07d2ee 100644 --- a/libs/libcurl/src/getinfo.c +++ b/libs/libcurl/src/getinfo.c @@ -101,6 +101,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, if(!m) { if(data->set.opt_no_body) m = "HEAD"; +#ifndef CURL_DISABLE_HTTP else { switch(data->state.httpreq) { case HTTPREQ_POST: @@ -120,6 +121,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, break; } } +#endif } *param_charp = m; } diff --git a/libs/libcurl/src/gopher.c b/libs/libcurl/src/gopher.c index b101c0ab68..a39cc7e6b4 100644 --- a/libs/libcurl/src/gopher.c +++ b/libs/libcurl/src/gopher.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -33,6 +33,7 @@ #include "gopher.h" #include "select.h" #include "strdup.h" +#include "vtls/vtls.h" #include "url.h" #include "escape.h" #include "warnless.h" @@ -45,7 +46,11 @@ * Forward declarations. */ -static CURLcode gopher_do(struct connectdata *conn, bool *done); +static CURLcode gopher_do(struct Curl_easy *data, bool *done); +#ifdef USE_SSL +static CURLcode gopher_connect(struct Curl_easy *data, bool *done); +static CURLcode gopher_connecting(struct Curl_easy *data, bool *done); +#endif /* * Gopher protocol handler. @@ -75,10 +80,51 @@ const struct Curl_handler Curl_handler_gopher = { PROTOPT_NONE /* flags */ }; -static CURLcode gopher_do(struct connectdata *conn, bool *done) +#ifdef USE_SSL +const struct Curl_handler Curl_handler_gophers = { + "GOPHERS", /* scheme */ + ZERO_NULL, /* setup_connection */ + gopher_do, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + gopher_connect, /* connect_it */ + gopher_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_GOPHER, /* defport */ + CURLPROTO_GOPHERS, /* protocol */ + CURLPROTO_GOPHER, /* family */ + PROTOPT_SSL /* flags */ +}; + +static CURLcode gopher_connect(struct Curl_easy *data, bool *done) +{ + (void)data; + (void)done; + return CURLE_OK; +} + +static CURLcode gopher_connecting(struct Curl_easy *data, bool *done) +{ + struct connectdata *conn = data->conn; + CURLcode result = Curl_ssl_connect(data, conn, FIRSTSOCKET); + if(result) + connclose(conn, "Failed TLS connection"); + *done = TRUE; + return result; +} +#endif + +static CURLcode gopher_do(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; char *gopherpath; char *path = data->state.up.path; @@ -127,9 +173,14 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) k = curlx_uztosz(len); for(;;) { - result = Curl_write(conn, sockfd, sel, k, &amount); + /* Break out of the loop if the selector is empty because OpenSSL and/or + LibreSSL fail with errno 0 if this is the case. */ + if(strlen(sel) < 1) + break; + + result = Curl_write(data, sockfd, sel, k, &amount); if(!result) { /* Which may not have written it all! */ - result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount); + result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount); if(result) break; @@ -141,7 +192,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) else break; - timeout_ms = Curl_timeleft(conn->data, NULL, FALSE); + timeout_ms = Curl_timeleft(data, NULL, FALSE); if(timeout_ms < 0) { result = CURLE_OPERATION_TIMEDOUT; break; @@ -169,12 +220,12 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) free(sel_org); if(!result) - result = Curl_write(conn, sockfd, "\r\n", 2, &amount); + result = Curl_write(data, sockfd, "\r\n", 2, &amount); if(result) { failf(data, "Failed sending Gopher request"); return result; } - result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2); + result = Curl_client_write(data, CLIENTWRITE_HEADER, (char *)"\r\n", 2); if(result) return result; diff --git a/libs/libcurl/src/gopher.h b/libs/libcurl/src/gopher.h index b35fa45096..6b8bd554a6 100644 --- a/libs/libcurl/src/gopher.h +++ b/libs/libcurl/src/gopher.h @@ -24,6 +24,9 @@ #ifndef CURL_DISABLE_GOPHER extern const struct Curl_handler Curl_handler_gopher; +#ifdef USE_SSL +extern const struct Curl_handler Curl_handler_gophers; +#endif #endif #endif /* HEADER_CURL_GOPHER_H */ diff --git a/libs/libcurl/src/hash.c b/libs/libcurl/src/hash.c index 051c176269..5d433ad1fb 100644 --- a/libs/libcurl/src/hash.c +++ b/libs/libcurl/src/hash.c @@ -175,7 +175,7 @@ Curl_hash_pick(struct Curl_hash *h, void *key, size_t key_len) return NULL; } -#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST) +#if defined(DEBUGBUILD) && defined(AGGRESSIVE_TEST) void Curl_hash_apply(Curl_hash *h, void *user, void (*cb)(void *user, void *ptr)) diff --git a/libs/libcurl/src/hostasyn.c b/libs/libcurl/src/hostasyn.c index 56a6fc2b72..b25de1d417 100644 --- a/libs/libcurl/src/hostasyn.c +++ b/libs/libcurl/src/hostasyn.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -66,25 +66,23 @@ * * The storage operation locks and unlocks the DNS cache. */ -CURLcode Curl_addrinfo_callback(struct connectdata *conn, +CURLcode Curl_addrinfo_callback(struct Curl_easy *data, int status, struct Curl_addrinfo *ai) { struct Curl_dns_entry *dns = NULL; CURLcode result = CURLE_OK; - conn->async.status = status; + data->state.async.status = status; if(CURL_ASYNC_SUCCESS == status) { if(ai) { - struct Curl_easy *data = conn->data; - if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); dns = Curl_cache_addr(data, ai, - conn->async.hostname, - conn->async.port); + data->state.async.hostname, + data->state.async.port); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); @@ -99,12 +97,12 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn, } } - conn->async.dns = dns; + data->state.async.dns = dns; /* Set async.done TRUE last in this function since it may be used multi- threaded and once this is TRUE the other thread may read fields from the async struct */ - conn->async.done = TRUE; + data->state.async.done = TRUE; /* IPv4: The input hostent struct will be freed by ares when we return from this function */ @@ -117,12 +115,12 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn, * name resolve layers (selected at build-time). They all take this same set * of arguments */ -struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, +struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, const char *hostname, int port, int *waitp) { - return Curl_resolver_getaddrinfo(conn, hostname, port, waitp); + return Curl_resolver_getaddrinfo(data, hostname, port, waitp); } #endif /* CURLRES_ASYNCH */ diff --git a/libs/libcurl/src/hostip.c b/libs/libcurl/src/hostip.c index ab1f6df051..8ba3fe81ce 100644 --- a/libs/libcurl/src/hostip.c +++ b/libs/libcurl/src/hostip.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -253,14 +253,12 @@ sigjmp_buf curl_jmpenv; #endif /* lookup address, returns entry if found and not stale */ -static struct Curl_dns_entry * -fetch_addr(struct connectdata *conn, - const char *hostname, - int port) +static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data, + const char *hostname, + int port) { struct Curl_dns_entry *dns = NULL; size_t entry_len; - struct Curl_easy *data = conn->data; char entry_id[MAX_HOSTCACHE_LEN]; /* Create an entry id, based upon the hostname and port */ @@ -311,17 +309,16 @@ fetch_addr(struct connectdata *conn, * use, or we'll leak memory! */ struct Curl_dns_entry * -Curl_fetch_addr(struct connectdata *conn, +Curl_fetch_addr(struct Curl_easy *data, const char *hostname, int port) { - struct Curl_easy *data = conn->data; struct Curl_dns_entry *dns = NULL; if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - dns = fetch_addr(conn, hostname, port); + dns = fetch_addr(data, hostname, port); if(dns) dns->inuse++; /* we use it! */ @@ -444,7 +441,7 @@ Curl_cache_addr(struct Curl_easy *data, dns->addr = addr; /* this is the address(es) */ time(&dns->timestamp); if(dns->timestamp == 0) - dns->timestamp = 1; /* zero indicates CURLOPT_RESOLVE entry */ + dns->timestamp = 1; /* zero indicates permanent CURLOPT_RESOLVE entry */ /* Store the resolved data in our DNS cache. */ dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1, @@ -480,16 +477,16 @@ Curl_cache_addr(struct Curl_easy *data, * CURLRESOLV_PENDING (1) = waiting for response, no pointer */ -enum resolve_t Curl_resolv(struct connectdata *conn, +enum resolve_t Curl_resolv(struct Curl_easy *data, const char *hostname, int port, bool allowDOH, struct Curl_dns_entry **entry) { struct Curl_dns_entry *dns = NULL; - struct Curl_easy *data = conn->data; CURLcode result; enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */ + struct connectdata *conn = data->conn; *entry = NULL; conn->bits.doh = FALSE; /* default is not */ @@ -497,7 +494,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn, if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - dns = fetch_addr(conn, hostname, port); + dns = fetch_addr(data, hostname, port); if(dns) { infof(data, "Hostname %s was found in DNS cache\n", hostname); @@ -523,7 +520,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn, if(data->set.resolver_start) { int st; Curl_set_in_callback(data, true); - st = data->set.resolver_start(data->state.resolver, NULL, + st = data->set.resolver_start(data->state.async.resolver, NULL, data->set.resolver_start_client); Curl_set_in_callback(data, false); if(st) @@ -565,17 +562,17 @@ enum resolve_t Curl_resolv(struct connectdata *conn, if(!addr) { /* Check what IP specifics the app has requested and if we can provide * it. If not, bail out. */ - if(!Curl_ipvalid(conn)) + if(!Curl_ipvalid(data, conn)) return CURLRESOLV_ERROR; if(allowDOH && data->set.doh && !ipnum) { - addr = Curl_doh(conn, hostname, port, &respwait); + addr = Curl_doh(data, hostname, port, &respwait); } else { /* 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 */ - addr = Curl_getaddrinfo(conn, + addr = Curl_getaddrinfo(data, #ifdef DEBUGBUILD (data->set.str[STRING_DEVICE] && !strcmp(data->set.str[STRING_DEVICE], @@ -589,7 +586,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn, /* the response to our resolve call will come asynchronously at a later time, good or bad */ /* First, check that we haven't received the info by now */ - result = Curl_resolv_check(conn, &dns); + result = Curl_resolv_check(data, &dns); if(result) /* error detected */ return CURLRESOLV_ERROR; if(dns) @@ -658,7 +655,7 @@ RETSIGTYPE alarmfunc(int sig) * CURLRESOLV_PENDING (1) = waiting for response, no pointer */ -enum resolve_t Curl_resolv_timeout(struct connectdata *conn, +enum resolve_t Curl_resolv_timeout(struct Curl_easy *data, const char *hostname, int port, struct Curl_dns_entry **entry, @@ -676,7 +673,6 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn, #endif /* HAVE_SIGACTION */ volatile long timeout; volatile unsigned int prev_alarm = 0; - struct Curl_easy *data = conn->data; #endif /* USE_ALARM_TIMEOUT */ enum resolve_t rc; @@ -695,7 +691,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn, if(!timeout) /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */ - return Curl_resolv(conn, hostname, port, TRUE, entry); + return Curl_resolv(data, hostname, port, TRUE, entry); if(timeout < 1000) { /* The alarm() function only provides integer second resolution, so if @@ -728,7 +724,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn, keep_copysig = TRUE; /* yes, we have a copy */ sigact.sa_handler = alarmfunc; #ifdef SA_RESTART - /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */ + /* HPUX doesn't have SA_RESTART but defaults to that behavior! */ sigact.sa_flags &= ~SA_RESTART; #endif /* now set the new struct */ @@ -748,7 +744,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn, #else #ifndef CURLRES_ASYNCH if(timeoutms) - infof(conn->data, "timeout on name lookup is not supported\n"); + infof(data, "timeout on name lookup is not supported\n"); #else (void)timeoutms; /* timeoutms not used with an async resolver */ #endif @@ -757,7 +753,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn, /* Perform the actual name resolution. This might be interrupted by an * alarm if it takes too long. */ - rc = Curl_resolv(conn, hostname, port, TRUE, entry); + rc = Curl_resolv(data, hostname, port, TRUE, entry); #ifdef USE_ALARM_TIMEOUT clean_up: @@ -784,7 +780,7 @@ clean_up: if(prev_alarm) { /* there was an alarm() set before us, now put it back */ timediff_t elapsed_secs = Curl_timediff(Curl_now(), - conn->created) / 1000; + data->conn->created) / 1000; /* the alarm period is counted in even number of seconds */ unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs); @@ -916,17 +912,24 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) char *addr_end; char *port_ptr; char *end_ptr; + bool permanent = TRUE; + char *host_begin; char *host_end; unsigned long tmp_port; bool error = true; - host_end = strchr(hostp->data, ':'); + host_begin = hostp->data; + if(host_begin[0] == '+') { + host_begin++; + permanent = FALSE; + } + host_end = strchr(host_begin, ':'); if(!host_end || - ((host_end - hostp->data) >= (ptrdiff_t)sizeof(hostname))) + ((host_end - host_begin) >= (ptrdiff_t)sizeof(hostname))) goto err; - memcpy(hostname, hostp->data, host_end - hostp->data); - hostname[host_end - hostp->data] = '\0'; + memcpy(hostname, host_begin, host_end - host_begin); + hostname[host_end - host_begin] = '\0'; port_ptr = host_end + 1; tmp_port = strtoul(port_ptr, &end_ptr, 10); @@ -1008,18 +1011,22 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - /* See if its already in our dns cache */ + /* See if it's already in our dns cache */ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); if(dns) { infof(data, "RESOLVE %s:%d is - old addresses discarded!\n", hostname, port); - /* delete old entry entry, there are two reasons for this + /* delete old entry, there are two reasons for this 1. old entry may have different addresses. 2. even if entry with correct addresses is already in the cache, but if it is close to expire, then by the time next http request is made, it can get expired and pruned because old - entry is not necessarily marked as added by CURLOPT_RESOLVE. */ + entry is not necessarily marked as permanent. + 3. when adding a non-permanent entry, we want it to remove and + replace an existing permanent entry. + 4. when adding a non-permanent entry, we want it to get a "fresh" + timeout that starts _now_. */ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); } @@ -1027,10 +1034,11 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) /* put this new host in the cache */ dns = Curl_cache_addr(data, head, hostname, port); if(dns) { - dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */ + if(permanent) + dns->timestamp = 0; /* mark as permanent */ /* release the returned reference; the cache itself will keep the * entry alive: */ - dns->inuse--; + dns->inuse--; } if(data->share) @@ -1040,8 +1048,8 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) Curl_freeaddrinfo(head); return CURLE_OUT_OF_MEMORY; } - infof(data, "Added %s:%d:%s to DNS cache\n", - hostname, port, addresses); + infof(data, "Added %s:%d:%s to DNS cache%s\n", + hostname, port, addresses, permanent ? "" : " (non-permanent)"); /* Wildcard hostname */ if(hostname[0] == '*' && hostname[1] == '\0') { @@ -1056,29 +1064,29 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) return CURLE_OK; } -CURLcode Curl_resolv_check(struct connectdata *conn, +CURLcode Curl_resolv_check(struct Curl_easy *data, struct Curl_dns_entry **dns) { #if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH) (void)dns; #endif - if(conn->bits.doh) - return Curl_doh_is_resolved(conn, dns); - return Curl_resolver_is_resolved(conn, dns); + if(data->conn->bits.doh) + return Curl_doh_is_resolved(data, dns); + return Curl_resolver_is_resolved(data, dns); } -int Curl_resolv_getsock(struct connectdata *conn, +int Curl_resolv_getsock(struct Curl_easy *data, curl_socket_t *socks) { #ifdef CURLRES_ASYNCH - if(conn->bits.doh) + if(data->conn->bits.doh) /* nothing to wait for during DOH resolve, those handles have their own sockets */ return GETSOCK_BLANK; - return Curl_resolver_getsock(conn, socks); + return Curl_resolver_getsock(data, socks); #else - (void)conn; + (void)data; (void)socks; return GETSOCK_BLANK; #endif @@ -1089,21 +1097,19 @@ int Curl_resolv_getsock(struct connectdata *conn, Note: this function disconnects and frees the conn data in case of resolve failure */ -CURLcode Curl_once_resolved(struct connectdata *conn, - bool *protocol_done) +CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done) { CURLcode result; + struct connectdata *conn = data->conn; - if(conn->async.dns) { - conn->dns_entry = conn->async.dns; - conn->async.dns = NULL; + if(data->state.async.dns) { + conn->dns_entry = data->state.async.dns; + data->state.async.dns = NULL; } - result = Curl_setup_conn(conn, protocol_done); + result = Curl_setup_conn(data, protocol_done); if(result) { - struct Curl_easy *data = conn->data; - DEBUGASSERT(data); Curl_detach_connnection(data); Curl_conncache_remove_conn(data, conn, TRUE); Curl_disconnect(data, conn, TRUE); diff --git a/libs/libcurl/src/hostip.h b/libs/libcurl/src/hostip.h index 724a03d7fb..c495c21e02 100644 --- a/libs/libcurl/src/hostip.h +++ b/libs/libcurl/src/hostip.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -65,7 +65,7 @@ struct Curl_hash *Curl_global_host_cache_init(void); struct Curl_dns_entry { struct Curl_addrinfo *addr; - /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */ + /* timestamp == 0 -- permanent CURLOPT_RESOLVE entry (doesn't time out) */ time_t timestamp; /* use-counter, use Curl_resolv_unlock to release reference */ long inuse; @@ -85,12 +85,12 @@ enum resolve_t { CURLRESOLV_RESOLVED = 0, CURLRESOLV_PENDING = 1 }; -enum resolve_t Curl_resolv(struct connectdata *conn, +enum resolve_t Curl_resolv(struct Curl_easy *data, const char *hostname, int port, bool allowDOH, struct Curl_dns_entry **dnsentry); -enum resolve_t Curl_resolv_timeout(struct connectdata *conn, +enum resolve_t Curl_resolv_timeout(struct Curl_easy *data, const char *hostname, int port, struct Curl_dns_entry **dnsentry, timediff_t timeoutms); @@ -99,7 +99,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn, /* * Curl_ipv6works() returns TRUE if IPv6 seems to work. */ -bool Curl_ipv6works(struct connectdata *conn); +bool Curl_ipv6works(struct Curl_easy *data); #else #define Curl_ipv6works(x) FALSE #endif @@ -108,7 +108,7 @@ bool Curl_ipv6works(struct connectdata *conn); * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've * been set and returns TRUE if they are OK. */ -bool Curl_ipvalid(struct connectdata *conn); +bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn); /* @@ -117,7 +117,7 @@ bool Curl_ipvalid(struct connectdata *conn); * name resolve layers (selected at build-time). They all take this same set * of arguments */ -struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, +struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, const char *hostname, int port, int *waitp); @@ -148,7 +148,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, /* IPv4 threadsafe resolve function used for synch and asynch builds */ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); -CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect); +CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_connect); /* * Curl_addrinfo_callback() is used when we build with any asynch specialty. @@ -156,7 +156,7 @@ CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect); * status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async * request completed whether successful or failed. */ -CURLcode Curl_addrinfo_callback(struct connectdata *conn, +CURLcode Curl_addrinfo_callback(struct Curl_easy *data, int status, struct Curl_addrinfo *ai); @@ -177,7 +177,7 @@ void Curl_printable_address(const struct Curl_addrinfo *ip, * use, or we'll leak memory! */ struct Curl_dns_entry * -Curl_fetch_addr(struct connectdata *conn, +Curl_fetch_addr(struct Curl_easy *data, const char *hostname, int port); @@ -240,10 +240,9 @@ void Curl_hostcache_clean(struct Curl_easy *data, struct Curl_hash *hash); * Populate the cache with specified entries from CURLOPT_RESOLVE. */ CURLcode Curl_loadhostpairs(struct Curl_easy *data); - -CURLcode Curl_resolv_check(struct connectdata *conn, +CURLcode Curl_resolv_check(struct Curl_easy *data, struct Curl_dns_entry **dns); -int Curl_resolv_getsock(struct connectdata *conn, +int Curl_resolv_getsock(struct Curl_easy *data, curl_socket_t *socks); #endif /* HEADER_CURL_HOSTIP_H */ diff --git a/libs/libcurl/src/hostip4.c b/libs/libcurl/src/hostip4.c index df83a2f12b..d0754af223 100644 --- a/libs/libcurl/src/hostip4.c +++ b/libs/libcurl/src/hostip4.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -61,8 +61,9 @@ * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've * been set and returns TRUE if they are OK. */ -bool Curl_ipvalid(struct connectdata *conn) +bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn) { + (void)data; if(conn->ip_version == CURL_IPRESOLVE_V6) /* An IPv6 address was requested and we can't get/use one */ return FALSE; @@ -88,7 +89,7 @@ bool Curl_ipvalid(struct connectdata *conn) * flavours have thread-safe versions of the plain gethostbyname() etc. * */ -struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, +struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, const char *hostname, int port, int *waitp) @@ -96,14 +97,14 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *ai = NULL; #ifdef CURL_DISABLE_VERBOSE_STRINGS - (void)conn; + (void)data; #endif *waitp = 0; /* synchronous response only */ ai = Curl_ipv4_resolve_r(hostname, port); if(!ai) - infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname); + infof(data, "Curl_ipv4_resolve_r failed for %s\n", hostname); return ai; } diff --git a/libs/libcurl/src/hostip6.c b/libs/libcurl/src/hostip6.c index 02b0ca298b..53b3c67223 100644 --- a/libs/libcurl/src/hostip6.c +++ b/libs/libcurl/src/hostip6.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -62,16 +62,15 @@ /* * Curl_ipv6works() returns TRUE if IPv6 seems to work. */ -bool Curl_ipv6works(struct connectdata *conn) +bool Curl_ipv6works(struct Curl_easy *data) { - if(conn) { + 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(conn); - DEBUGASSERT(conn->data); - DEBUGASSERT(conn->data->multi); - return conn->data->multi->ipv6_works; + DEBUGASSERT(data); + DEBUGASSERT(data->multi); + return data->multi->ipv6_works; } else { int ipv6_works = -1; @@ -82,7 +81,7 @@ bool Curl_ipv6works(struct connectdata *conn) ipv6_works = 0; else { ipv6_works = 1; - Curl_closesocket(NULL, s); + sclose(s); } return (ipv6_works>0)?TRUE:FALSE; } @@ -92,10 +91,10 @@ bool Curl_ipv6works(struct connectdata *conn) * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've * been set and returns TRUE if they are OK. */ -bool Curl_ipvalid(struct connectdata *conn) +bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn) { if(conn->ip_version == CURL_IPRESOLVE_V6) - return Curl_ipv6works(conn); + return Curl_ipv6works(data); return TRUE; } @@ -128,7 +127,7 @@ static void dump_addrinfo(struct connectdata *conn, * memory we need to free after use. That memory *MUST* be freed with * Curl_freeaddrinfo(), nothing else. */ -struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, +struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, const char *hostname, int port, int *waitp) @@ -142,14 +141,11 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, char addrbuf[128]; #endif int pf; -#if !defined(CURL_DISABLE_VERBOSE_STRINGS) - struct Curl_easy *data = conn->data; -#endif *waitp = 0; /* synchronous response only */ /* Check if a limited name resolve has been requested */ - switch(conn->ip_version) { + switch(data->set.ipver) { case CURL_IPRESOLVE_V4: pf = PF_INET; break; @@ -161,13 +157,13 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, break; } - if((pf != PF_INET) && !Curl_ipv6works(conn)) + if((pf != PF_INET) && !Curl_ipv6works(data)) /* The stack seems to be a non-IPv6 one */ pf = PF_INET; memset(&hints, 0, sizeof(hints)); hints.ai_family = pf; - hints.ai_socktype = (conn->transport == TRNSPRT_TCP) ? + hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ? SOCK_STREAM : SOCK_DGRAM; #ifndef USE_RESOLVE_ON_IPS diff --git a/libs/libcurl/src/hsts.c b/libs/libcurl/src/hsts.c index 6f771284ff..0e7c19cfbd 100644 --- a/libs/libcurl/src/hsts.c +++ b/libs/libcurl/src/hsts.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2020, Daniel Stenberg, , et al. + * Copyright (C) 2020 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -325,7 +325,7 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h, /* no cache activated */ return CURLE_OK; - /* if not new name is given, use the one we stored from the load */ + /* if no new name is given, use the one we stored from the load */ if(!file && h->filename) file = h->filename; @@ -457,7 +457,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h) * format is documented here: * https://github.com/curl/curl/wiki/HSTS * - * This function only returns error on major problems that prevents hsts + * This function only returns error on major problems that prevent hsts * handling to work completely. It will ignore individual syntactical errors * etc. */ diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c index c232ed4134..6f7f55d078 100644 --- a/libs/libcurl/src/http.c +++ b/libs/libcurl/src/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -45,6 +45,10 @@ #include #endif +#ifdef USE_HYPER +#include +#endif + #include "urldata.h" #include #include "transfer.h" @@ -60,6 +64,7 @@ #include "http_ntlm.h" #include "curl_ntlm_wb.h" #include "http_negotiate.h" +#include "http_aws_sigv4.h" #include "url.h" #include "share.h" #include "hostip.h" @@ -78,6 +83,7 @@ #include "strdup.h" #include "altsvc.h" #include "hsts.h" +#include "c-hyper.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -88,22 +94,25 @@ * Forward declarations. */ -static int http_getsock_do(struct connectdata *conn, +static int http_getsock_do(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); -static int http_should_fail(struct connectdata *conn); +static bool http_should_fail(struct Curl_easy *data); #ifndef CURL_DISABLE_PROXY -static CURLcode add_haproxy_protocol_header(struct connectdata *conn); +static CURLcode add_haproxy_protocol_header(struct Curl_easy *data); #endif #ifdef USE_SSL -static CURLcode https_connecting(struct connectdata *conn, bool *done); -static int https_getsock(struct connectdata *conn, +static CURLcode https_connecting(struct Curl_easy *data, bool *done); +static int https_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); #else #define https_connecting(x,y) CURLE_COULDNT_CONNECT #endif -static CURLcode http_setup_conn(struct connectdata *conn); +static CURLcode http_setup_conn(struct Curl_easy *data, + struct connectdata *conn); /* * HTTP handler interface. @@ -159,19 +168,19 @@ const struct Curl_handler Curl_handler_https = { }; #endif -static CURLcode http_setup_conn(struct connectdata *conn) +static CURLcode http_setup_conn(struct Curl_easy *data, + struct connectdata *conn) { /* allocate the HTTP-specific struct for the Curl_easy, only to survive during this request */ struct HTTP *http; - struct Curl_easy *data = conn->data; DEBUGASSERT(data->req.p.http == NULL); http = calloc(1, sizeof(struct HTTP)); if(!http) return CURLE_OUT_OF_MEMORY; - Curl_mime_initpart(&http->form, conn->data); + Curl_mime_initpart(&http->form, data); data->req.p.http = http; if(data->set.httpversion == CURL_HTTP_VERSION_3) { @@ -199,16 +208,16 @@ static CURLcode http_setup_conn(struct connectdata *conn) * if proxy headers are not available, then it will lookup into http header * link list * - * It takes a connectdata struct as input instead of the Curl_easy simply to - * know if this is a proxy request or not, as it then might check a different - * header list. Provide the header prefix without colon!. + * It takes a connectdata struct as input to see if this is a proxy request or + * not, as it then might check a different header list. Provide the header + * prefix without colon! */ -char *Curl_checkProxyheaders(const struct connectdata *conn, +char *Curl_checkProxyheaders(struct Curl_easy *data, + const struct connectdata *conn, const char *thisheader) { struct curl_slist *head; size_t thislen = strlen(thisheader); - struct Curl_easy *data = conn->data; for(head = (conn->bits.proxy && data->set.sep_headers) ? data->set.proxyheaders : data->set.headers; @@ -222,7 +231,7 @@ char *Curl_checkProxyheaders(const struct connectdata *conn, } #else /* disabled */ -#define Curl_checkProxyheaders(x,y) NULL +#define Curl_checkProxyheaders(x,y,z) NULL #endif /* @@ -285,11 +294,11 @@ char *Curl_copy_header_value(const char *header) * * Returns CURLcode. */ -static CURLcode http_output_basic(struct connectdata *conn, bool proxy) +static CURLcode http_output_basic(struct Curl_easy *data, bool proxy) { size_t size = 0; char *authorization = NULL; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; char **userp; const char *user; const char *pwd; @@ -345,16 +354,15 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) * * Returns CURLcode. */ -static CURLcode http_output_bearer(struct connectdata *conn) +static CURLcode http_output_bearer(struct Curl_easy *data) { char **userp; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; userp = &data->state.aptr.userpwd; free(*userp); *userp = aprintf("Authorization: Bearer %s\r\n", - conn->data->set.str[STRING_BEARER]); + data->set.str[STRING_BEARER]); if(!*userp) { result = CURLE_OUT_OF_MEMORY; @@ -393,6 +401,8 @@ static bool pickoneauth(struct auth *pick, unsigned long mask) pick->picked = CURLAUTH_NTLM_WB; else if(avail & CURLAUTH_BASIC) pick->picked = CURLAUTH_BASIC; + else if(avail & CURLAUTH_AWS_SIGV4) + pick->picked = CURLAUTH_AWS_SIGV4; else { pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */ picked = FALSE; @@ -425,9 +435,9 @@ static bool pickoneauth(struct auth *pick, unsigned long mask) * } * } */ -static CURLcode http_perhapsrewind(struct connectdata *conn) +static CURLcode http_perhapsrewind(struct Curl_easy *data, + struct connectdata *conn) { - struct Curl_easy *data = conn->data; struct HTTP *http = data->req.p.http; curl_off_t bytessent; curl_off_t expectsend = -1; /* default is unknown */ @@ -545,7 +555,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) if(bytessent) /* we rewind now at once since if we already sent something */ - return Curl_readrewind(conn); + return Curl_readrewind(data); return CURLE_OK; } @@ -557,9 +567,9 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) * picked. */ -CURLcode Curl_http_auth_act(struct connectdata *conn) +CURLcode Curl_http_auth_act(struct Curl_easy *data) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; bool pickhost = FALSE; bool pickproxy = FALSE; CURLcode result = CURLE_OK; @@ -585,7 +595,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) conn->httpversion > 11) { infof(data, "Forcing HTTP/1.1 for NTLM"); connclose(conn, "Force HTTP/1.1 connection"); - conn->data->set.httpversion = CURL_HTTP_VERSION_1_1; + data->set.httpversion = CURL_HTTP_VERSION_1_1; } } #ifndef CURL_DISABLE_PROXY @@ -603,7 +613,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if((data->state.httpreq != HTTPREQ_GET) && (data->state.httpreq != HTTPREQ_HEAD) && !conn->bits.rewindaftersend) { - result = http_perhapsrewind(conn); + result = http_perhapsrewind(data, conn); if(result) return result; } @@ -630,7 +640,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) data->state.authhost.done = TRUE; } } - if(http_should_fail(conn)) { + if(http_should_fail(data)) { failf(data, "The requested URL returned error: %d", data->req.httpcode); result = CURLE_HTTP_RETURNED_ERROR; @@ -645,7 +655,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) * and whether or not it is to a proxy. */ static CURLcode -output_auth_headers(struct connectdata *conn, +output_auth_headers(struct Curl_easy *data, + struct connectdata *conn, struct auth *authstatus, const char *request, const char *path, @@ -653,17 +664,24 @@ output_auth_headers(struct connectdata *conn, { const char *auth = NULL; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; #ifdef CURL_DISABLE_CRYPTO_AUTH (void)request; (void)path; #endif - +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(authstatus->picked == CURLAUTH_AWS_SIGV4) { + auth = "AWS_SIGV4"; + result = Curl_output_aws_sigv4(data, proxy); + if(result) + return result; + } + else +#endif #ifdef USE_SPNEGO if(authstatus->picked == CURLAUTH_NEGOTIATE) { auth = "Negotiate"; - result = Curl_output_negotiate(conn, proxy); + result = Curl_output_negotiate(data, conn, proxy); if(result) return result; } @@ -672,7 +690,7 @@ output_auth_headers(struct connectdata *conn, #ifdef USE_NTLM if(authstatus->picked == CURLAUTH_NTLM) { auth = "NTLM"; - result = Curl_output_ntlm(conn, proxy); + result = Curl_output_ntlm(data, proxy); if(result) return result; } @@ -681,7 +699,7 @@ output_auth_headers(struct connectdata *conn, #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) if(authstatus->picked == CURLAUTH_NTLM_WB) { auth = "NTLM_WB"; - result = Curl_output_ntlm_wb(conn, proxy); + result = Curl_output_ntlm_wb(data, conn, proxy); if(result) return result; } @@ -690,7 +708,8 @@ output_auth_headers(struct connectdata *conn, #ifndef CURL_DISABLE_CRYPTO_AUTH if(authstatus->picked == CURLAUTH_DIGEST) { auth = "Digest"; - result = Curl_output_digest(conn, + result = Curl_output_digest(data, + conn, proxy, (const unsigned char *)request, (const unsigned char *)path); @@ -704,12 +723,12 @@ output_auth_headers(struct connectdata *conn, if( #ifndef CURL_DISABLE_PROXY (proxy && conn->bits.proxy_user_passwd && - !Curl_checkProxyheaders(conn, "Proxy-authorization")) || + !Curl_checkProxyheaders(data, conn, "Proxy-authorization")) || #endif (!proxy && conn->bits.user_passwd && - !Curl_checkheaders(conn, "Authorization"))) { + !Curl_checkheaders(data, "Authorization"))) { auth = "Basic"; - result = http_output_basic(conn, proxy); + result = http_output_basic(data, proxy); if(result) return result; } @@ -721,9 +740,9 @@ output_auth_headers(struct connectdata *conn, if(authstatus->picked == CURLAUTH_BEARER) { /* Bearer */ if((!proxy && data->set.str[STRING_BEARER] && - !Curl_checkheaders(conn, "Authorization:"))) { + !Curl_checkheaders(data, "Authorization:"))) { auth = "Bearer"; - result = http_output_bearer(conn); + result = http_output_bearer(data); if(result) return result; } @@ -754,7 +773,7 @@ output_auth_headers(struct connectdata *conn, /** * Curl_http_output_auth() setups the authentication headers for the * host/proxy and the correct authentication - * method. conn->data->state.authdone is set to TRUE when authentication is + * method. data->state.authdone is set to TRUE when authentication is * done. * * @param conn all information about the current connection @@ -766,14 +785,15 @@ output_auth_headers(struct connectdata *conn, * @returns CURLcode */ CURLcode -Curl_http_output_auth(struct connectdata *conn, +Curl_http_output_auth(struct Curl_easy *data, + struct connectdata *conn, const char *request, + Curl_HttpReq httpreq, const char *path, bool proxytunnel) /* TRUE if this is the request setting up the proxy tunnel */ { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct auth *authhost; struct auth *authproxy; @@ -810,7 +830,7 @@ Curl_http_output_auth(struct connectdata *conn, /* Send proxy authentication header if needed */ if(conn->bits.httpproxy && (conn->bits.tunnel_proxy == (bit)proxytunnel)) { - result = output_auth_headers(conn, authproxy, request, path, TRUE); + result = output_auth_headers(data, conn, authproxy, request, path, TRUE); if(result) return result; } @@ -829,11 +849,22 @@ Curl_http_output_auth(struct connectdata *conn, !data->state.first_host || data->set.allow_auth_to_other_hosts || strcasecompare(data->state.first_host, conn->host.name)) { - result = output_auth_headers(conn, authhost, request, path, FALSE); + result = output_auth_headers(data, conn, authhost, request, path, FALSE); } else authhost->done = TRUE; + if(((authhost->multipass && !authhost->done) || + (authproxy->multipass && !authproxy->done)) && + (httpreq != HTTPREQ_GET) && + (httpreq != HTTPREQ_HEAD)) { + /* Auth is required and we are not authenticated yet. Make a PUT or POST + with content-length zero as a "probe". */ + conn->bits.authneg = TRUE; + } + else + conn->bits.authneg = FALSE; + return result; } @@ -859,14 +890,13 @@ Curl_http_output_auth(struct connectdata *conn, * proxy CONNECT loop. */ -CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, +CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, const char *auth) /* the first non-space */ { /* * This resource requires authentication */ - struct Curl_easy *data = conn->data; - + struct connectdata *conn = data->conn; #ifdef USE_SPNEGO curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state : &conn->http_negotiate_state; @@ -874,6 +904,8 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, unsigned long *availp; struct auth *authp; + (void) conn; /* In case conditionals make it unused. */ + if(proxy) { availp = &data->info.proxyauthavail; authp = &data->state.authproxy; @@ -908,7 +940,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, authp->avail |= CURLAUTH_NEGOTIATE; if(authp->picked == CURLAUTH_NEGOTIATE) { - CURLcode result = Curl_input_negotiate(conn, proxy, auth); + CURLcode result = Curl_input_negotiate(data, conn, proxy, auth); if(!result) { DEBUGASSERT(!data->req.newurl); data->req.newurl = strdup(data->change.url); @@ -937,7 +969,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, if(authp->picked == CURLAUTH_NTLM || authp->picked == CURLAUTH_NTLM_WB) { /* NTLM authentication is picked and activated */ - CURLcode result = Curl_input_ntlm(conn, proxy, auth); + CURLcode result = Curl_input_ntlm(data, proxy, auth); if(!result) { data->state.authproblem = FALSE; #ifdef NTLM_WB_ENABLED @@ -947,7 +979,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, *availp |= CURLAUTH_NTLM_WB; authp->avail |= CURLAUTH_NTLM_WB; - result = Curl_input_ntlm_wb(conn, proxy, auth); + result = Curl_input_ntlm_wb(data, conn, proxy, auth); if(result) { infof(data, "Authentication problem. Ignoring this.\n"); data->state.authproblem = TRUE; @@ -978,7 +1010,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, * authentication isn't activated yet, as we need to store the * incoming data from this header in case we are going to use * Digest */ - result = Curl_input_digest(conn, proxy, auth); + result = Curl_input_digest(data, proxy, auth); if(result) { infof(data, "Authentication problem. Ignoring this.\n"); data->state.authproblem = TRUE; @@ -1030,18 +1062,15 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, * * @param conn all information about the current connection * - * @retval 0 communications should continue + * @retval FALSE communications should continue * - * @retval 1 communications should not continue + * @retval TRUE communications should not continue */ -static int http_should_fail(struct connectdata *conn) +static bool http_should_fail(struct Curl_easy *data) { - struct Curl_easy *data; int httpcode; - - DEBUGASSERT(conn); - data = conn->data; DEBUGASSERT(data); + DEBUGASSERT(data->conn); httpcode = data->req.httpcode; @@ -1050,20 +1079,20 @@ static int http_should_fail(struct connectdata *conn) ** don't fail. */ if(!data->set.http_fail_on_error) - return 0; + return FALSE; /* ** Any code < 400 is never terminal. */ if(httpcode < 400) - return 0; + return FALSE; /* ** Any code >= 400 that's not 401 or 407 is always ** a terminal error */ if((httpcode != 401) && (httpcode != 407)) - return 1; + return TRUE; /* ** All we have left to deal with is 401 and 407 @@ -1088,16 +1117,17 @@ static int http_should_fail(struct connectdata *conn) ** Either we're not authenticating, or we're supposed to ** be authenticating something else. This is an error. */ - if((httpcode == 401) && !conn->bits.user_passwd) + if((httpcode == 401) && !data->conn->bits.user_passwd) return TRUE; #ifndef CURL_DISABLE_PROXY - if((httpcode == 407) && !conn->bits.proxy_user_passwd) + if((httpcode == 407) && !data->conn->bits.proxy_user_passwd) return TRUE; #endif return data->state.authproblem; } +#ifndef USE_HYPER /* * readmoredata() is a "fread() emulation" to provide POST and/or request * data. It is used when a huge POST is to be made and the entire chunk wasn't @@ -1111,8 +1141,8 @@ static size_t readmoredata(char *buffer, size_t nitems, void *userp) { - struct connectdata *conn = (struct connectdata *)userp; - struct HTTP *http = conn->data->req.p.http; + struct Curl_easy *data = (struct Curl_easy *)userp; + struct HTTP *http = data->req.p.http; size_t fullsize = size * nitems; if(!http->postsize) @@ -1120,7 +1150,7 @@ static size_t readmoredata(char *buffer, return 0; /* make sure that a HTTP request is never sent away chunked! */ - conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; + data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; if(http->postsize <= (curl_off_t)fullsize) { memcpy(buffer, http->postdata, (size_t)http->postsize); @@ -1130,8 +1160,8 @@ static size_t readmoredata(char *buffer, /* move backup data into focus and continue on that */ http->postdata = http->backup.postdata; http->postsize = http->backup.postsize; - conn->data->state.fread_func = http->backup.fread_func; - conn->data->state.in = http->backup.fread_in; + data->state.fread_func = http->backup.fread_func; + data->state.in = http->backup.fread_in; http->sending++; /* move one step up */ @@ -1157,7 +1187,7 @@ static size_t readmoredata(char *buffer, * Returns CURLcode */ CURLcode Curl_buffer_send(struct dynbuf *in, - struct connectdata *conn, + struct Curl_easy *data, /* add the number of sent bytes to this counter */ curl_off_t *bytes_written, @@ -1169,7 +1199,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in, CURLcode result; char *ptr; size_t size; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct HTTP *http = data->req.p.http; size_t sendsize; curl_socket_t sockfd; @@ -1229,7 +1259,9 @@ CURLcode Curl_buffer_send(struct dynbuf *in, } else { #ifdef CURLDEBUG - /* Allow debug builds override this logic to force short initial sends */ + /* Allow debug builds to override this logic to force short initial + sends + */ char *p = getenv("CURL_SMALLREQSEND"); if(p) { size_t altsize = (size_t)strtoul(p, NULL, 10); @@ -1243,7 +1275,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in, sendsize = size; } - result = Curl_write(conn, sockfd, ptr, sendsize, &amount); + result = Curl_write(data, sockfd, ptr, sendsize, &amount); if(!result) { /* @@ -1290,10 +1322,13 @@ CURLcode Curl_buffer_send(struct dynbuf *in, /* set the new pointers for the request-sending */ data->state.fread_func = (curl_read_callback)readmoredata; - data->state.in = (void *)conn; + data->state.in = (void *)data; http->postdata = ptr; http->postsize = (curl_off_t)size; + /* this much data is remaining header: */ + data->req.pendingheader = headersize - headlen; + http->send_buffer = *in; /* copy the whole struct */ http->sending = HTTPSEND_REQUEST; @@ -1316,9 +1351,13 @@ CURLcode Curl_buffer_send(struct dynbuf *in, } Curl_dyn_free(in); + /* no remaining header data */ + data->req.pendingheader = 0; return result; } +#endif + /* end of the add_buffer functions */ /* ------------------------------------------------------------------------- */ @@ -1383,9 +1422,10 @@ Curl_compareheader(const char *headerline, /* line to check */ * Curl_http_connect() performs HTTP stuff to do at connect-time, called from * the generic Curl_connect(). */ -CURLcode Curl_http_connect(struct connectdata *conn, bool *done) +CURLcode Curl_http_connect(struct Curl_easy *data, bool *done) { CURLcode result; + struct connectdata *conn = data->conn; /* We default to persistent connections. We set this already in this connect function to make the re-use checks properly be able to check this bit. */ @@ -1393,7 +1433,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) #ifndef CURL_DISABLE_PROXY /* the CONNECT procedure might not have been completed */ - result = Curl_proxy_connect(conn, FIRSTSOCKET); + result = Curl_proxy_connect(data, FIRSTSOCKET); if(result) return result; @@ -1408,9 +1448,9 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) /* nothing else to do except wait right now - we're not done here. */ return CURLE_OK; - if(conn->data->set.haproxyprotocol) { + if(data->set.haproxyprotocol) { /* add HAProxy PROXY protocol header */ - result = add_haproxy_protocol_header(conn); + result = add_haproxy_protocol_header(data); if(result) return result; } @@ -1418,7 +1458,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) if(conn->given->protocol & CURLPROTO_HTTPS) { /* perform SSL initialization */ - result = https_connecting(conn, done); + result = https_connecting(data, done); if(result) return result; } @@ -1431,24 +1471,27 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) /* this returns the socket to wait for in the DO and DOING state for the multi interface and then we're always _sending_ a request and thus we wait for the single socket to become writable only */ -static int http_getsock_do(struct connectdata *conn, +static int http_getsock_do(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { /* write mode */ + (void)data; socks[0] = conn->sock[FIRSTSOCKET]; return GETSOCK_WRITESOCK(0); } #ifndef CURL_DISABLE_PROXY -static CURLcode add_haproxy_protocol_header(struct connectdata *conn) +static CURLcode add_haproxy_protocol_header(struct Curl_easy *data) { char proxy_header[128]; struct dynbuf req; CURLcode result; char tcp_version[5]; + DEBUGASSERT(data->conn); /* Emit the correct prefix for IPv6 */ - if(conn->bits.ipv6) { + if(data->conn->bits.ipv6) { strcpy(tcp_version, "TCP6"); } else { @@ -1459,10 +1502,10 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn) sizeof(proxy_header), "PROXY %s %s %s %li %li\r\n", tcp_version, - conn->data->info.conn_local_ip, - conn->data->info.conn_primary_ip, - conn->data->info.conn_local_port, - conn->data->info.conn_primary_port); + data->info.conn_local_ip, + data->info.conn_primary_ip, + data->info.conn_local_port, + data->info.conn_primary_port); Curl_dyn_init(&req, DYN_HAXPROXY); @@ -1470,7 +1513,7 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn) if(result) return result; - result = Curl_buffer_send(&req, conn, &conn->data->info.request_size, + result = Curl_buffer_send(&req, data, &data->info.request_size, 0, FIRSTSOCKET); return result; @@ -1478,10 +1521,11 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn) #endif #ifdef USE_SSL -static CURLcode https_connecting(struct connectdata *conn, bool *done) +static CURLcode https_connecting(struct Curl_easy *data, bool *done) { CURLcode result; - DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL)); + struct connectdata *conn = data->conn; + DEBUGASSERT((data) && (data->conn->handler->flags & PROTOPT_SSL)); #ifdef ENABLE_QUIC if(conn->transport == TRNSPRT_QUIC) { @@ -1491,16 +1535,18 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) #endif /* perform SSL initialization for this socket */ - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); + result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, done); if(result) connclose(conn, "Failed HTTPS connection"); return result; } -static int https_getsock(struct connectdata *conn, +static int https_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { + (void)data; if(conn->handler->flags & PROTOPT_SSL) return Curl_ssl_getsock(conn, socks); return GETSOCK_BLANK; @@ -1512,10 +1558,10 @@ static int https_getsock(struct connectdata *conn, * performed. */ -CURLcode Curl_http_done(struct connectdata *conn, +CURLcode Curl_http_done(struct Curl_easy *data, CURLcode status, bool premature) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct HTTP *http = data->req.p.http; /* Clear multipass flag. If authentication isn't done yet, then it will get @@ -1523,7 +1569,7 @@ CURLcode Curl_http_done(struct connectdata *conn, data->state.authhost.multipass = FALSE; data->state.authproxy.multipass = FALSE; - Curl_unencode_cleanup(conn); + Curl_unencode_cleanup(data); /* set the proper values (possibly modified on POST) */ conn->seek_func = data->set.seek_func; /* restore */ @@ -1537,6 +1583,7 @@ CURLcode Curl_http_done(struct connectdata *conn, Curl_quic_done(data, premature); Curl_mime_cleanpart(&http->form); Curl_dyn_reset(&data->state.headerb); + Curl_hyper_done(data); if(status) return status; @@ -1552,6 +1599,8 @@ CURLcode Curl_http_done(struct connectdata *conn, read from the HTTP server (that counts), this can't be right so we return an error here */ failf(data, "Empty reply from server"); + /* Mark it as closed to avoid the "left intact" message */ + streamclose(conn, "Empty reply from server"); return CURLE_GOT_NOTHING; } @@ -1579,6 +1628,7 @@ static bool use_http_1_1plus(const struct Curl_easy *data, (data->set.httpversion >= CURL_HTTP_VERSION_1_1)); } +#ifndef USE_HYPER static const char *get_http_string(const struct Curl_easy *data, const struct connectdata *conn) { @@ -1598,6 +1648,7 @@ static const char *get_http_string(const struct Curl_easy *data, return "1.0"; } +#endif /* check and possibly add an Expect: header */ static CURLcode expect100(struct Curl_easy *data, @@ -1612,7 +1663,7 @@ static CURLcode expect100(struct Curl_easy *data, /* 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 operations (as there is one packet coming back from the web server) */ - const char *ptr = Curl_checkheaders(conn, "Expect"); + const char *ptr = Curl_checkheaders(data, "Expect"); if(ptr) { data->state.expect100header = Curl_compareheader(ptr, "Expect:", "100-continue"); @@ -1678,15 +1729,20 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers, return result; } -CURLcode Curl_add_custom_headers(struct connectdata *conn, +CURLcode Curl_add_custom_headers(struct Curl_easy *data, bool is_connect, - struct dynbuf *req) +#ifndef USE_HYPER + struct dynbuf *req +#else + void *req +#endif + ) { + struct connectdata *conn = data->conn; char *ptr; struct curl_slist *h[2]; struct curl_slist *headers; int numlists = 1; /* by default */ - struct Curl_easy *data = conn->data; int i; #ifndef CURL_DISABLE_PROXY @@ -1747,7 +1803,9 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, /* copy the source */ semicolonp = strdup(headers->data); if(!semicolonp) { +#ifndef USE_HYPER Curl_dyn_free(req); +#endif return CURLE_OUT_OF_MEMORY; } /* put a colon where the semicolon is */ @@ -1808,7 +1866,11 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, !strcasecompare(data->state.first_host, conn->host.name))) ; else { +#ifdef USE_HYPER + result = Curl_hyper_header(data, req, compare); +#else result = Curl_dyn_addf(req, "%s\r\n", compare); +#endif } if(semicolonp) free(semicolonp); @@ -1824,10 +1886,14 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, } #ifndef CURL_DISABLE_PARSEDATE -CURLcode Curl_add_timecondition(const struct connectdata *conn, - struct dynbuf *req) +CURLcode Curl_add_timecondition(struct Curl_easy *data, +#ifndef USE_HYPER + struct dynbuf *req +#else + void *req +#endif + ) { - struct Curl_easy *data = conn->data; const struct tm *tm; struct tm keeptime; CURLcode result; @@ -1860,7 +1926,7 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn, break; } - if(Curl_checkheaders(conn, condp)) { + if(Curl_checkheaders(data, condp)) { /* A custom header was specified; it will be sent instead. */ return CURLE_OK; } @@ -1884,7 +1950,11 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn, tm->tm_min, tm->tm_sec); +#ifndef USE_HYPER result = Curl_dyn_add(req, datestr); +#else + result = Curl_hyper_header(data, req, datestr); +#endif return result; } @@ -1899,102 +1969,14 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn, } #endif -/* - * 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 - * HTTP request. - */ -CURLcode Curl_http(struct connectdata *conn, bool *done) +void Curl_http_method(struct Curl_easy *data, struct connectdata *conn, + const char **method, Curl_HttpReq *reqp) { - struct Curl_easy *data = conn->data; - CURLcode result = CURLE_OK; - struct HTTP *http; - const char *path = data->state.up.path; - const char *query = data->state.up.query; - bool paste_ftp_userpwd = FALSE; - char ftp_typecode[sizeof("/;type=?")] = ""; - const char *host = conn->host.name; - const char *te = ""; /* transfer-encoding */ - const char *ptr; - const char *request; Curl_HttpReq httpreq = data->state.httpreq; -#if !defined(CURL_DISABLE_COOKIES) - char *addcookies = NULL; -#endif - curl_off_t included_body = 0; - const char *httpstring; - struct dynbuf req; - curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */ - char *altused = NULL; - - /* 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 - the rest of the request in the PERFORM phase. */ - *done = TRUE; - - if(conn->transport != TRNSPRT_QUIC) { - if(conn->httpversion < 20) { /* unless the connection is re-used and - already http2 */ - switch(conn->negnpn) { - case CURL_HTTP_VERSION_2: - conn->httpversion = 20; /* we know we're on HTTP/2 now */ - - result = Curl_http2_switched(conn, NULL, 0); - if(result) - return result; - break; - case CURL_HTTP_VERSION_1_1: - /* continue with HTTP/1.1 when explicitly requested */ - break; - default: - /* Check if user wants to use HTTP/2 with clear TCP*/ -#ifdef USE_NGHTTP2 - if(conn->data->set.httpversion == - CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) { -#ifndef CURL_DISABLE_PROXY - if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { - /* We don't support HTTP/2 proxies yet. Also it's debatable - whether or not this setting should apply to HTTP/2 proxies. */ - infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n"); - break; - } -#endif - DEBUGF(infof(data, "HTTP/2 over clean TCP\n")); - conn->httpversion = 20; - - result = Curl_http2_switched(conn, NULL, 0); - if(result) - return result; - } -#endif - break; - } - } - else { - /* prepare for a http2 request */ - result = Curl_http2_setup(conn); - if(result) - return result; - } - } - http = data->req.p.http; - DEBUGASSERT(http); - - if(!data->state.this_is_a_follow) { - /* Free to avoid leaking memory on multiple requests*/ - free(data->state.first_host); - - data->state.first_host = strdup(conn->host.name); - if(!data->state.first_host) - return CURLE_OUT_OF_MEMORY; - - data->state.first_remote_port = conn->remote_port; - } - + const char *request; if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) && - data->set.upload) { + data->set.upload) httpreq = HTTPREQ_PUT; - } /* Now set the 'request' pointer to the proper request string */ if(data->set.str[STRING_CUSTOMREQUEST]) @@ -2003,7 +1985,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(data->set.opt_no_body) request = "HEAD"; else { - DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); + DEBUGASSERT((httpreq >= HTTPREQ_GET) && (httpreq <= HTTPREQ_HEAD)); switch(httpreq) { case HTTPREQ_POST: case HTTPREQ_POST_FORM: @@ -2023,98 +2005,236 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } } + *method = request; + *reqp = httpreq; +} +CURLcode Curl_http_useragent(struct Curl_easy *data) +{ /* The User-Agent string might have been allocated in url.c already, because it might have been used in the proxy connect, but if we have got a header with the user-agent string specified, we erase the previously made string here. */ - if(Curl_checkheaders(conn, "User-Agent")) { + if(Curl_checkheaders(data, "User-Agent")) { free(data->state.aptr.uagent); data->state.aptr.uagent = NULL; } + return CURLE_OK; +} - /* setup the authentication headers */ - { - char *pq = NULL; - if(query && *query) { - pq = aprintf("%s?%s", path, query); - if(!pq) - return CURLE_OUT_OF_MEMORY; - } - result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE); - free(pq); - if(result) - return result; - } - if(((data->state.authhost.multipass && !data->state.authhost.done) - || (data->state.authproxy.multipass && !data->state.authproxy.done)) && - (httpreq != HTTPREQ_GET) && - (httpreq != HTTPREQ_HEAD)) { - /* Auth is required and we are not authenticated yet. Make a PUT or POST - with content-length zero as a "probe". */ - conn->bits.authneg = TRUE; - } - else - conn->bits.authneg = FALSE; +CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn) +{ + const char *ptr; + if(!data->state.this_is_a_follow) { + /* Free to avoid leaking memory on multiple requests*/ + free(data->state.first_host); - Curl_safefree(data->state.aptr.ref); - if(data->change.referer && !Curl_checkheaders(conn, "Referer")) { - data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer); - if(!data->state.aptr.ref) + data->state.first_host = strdup(conn->host.name); + if(!data->state.first_host) return CURLE_OUT_OF_MEMORY; + + data->state.first_remote_port = conn->remote_port; } - else - data->state.aptr.ref = NULL; + Curl_safefree(data->state.aptr.host); + ptr = Curl_checkheaders(data, "Host"); + if(ptr && (!data->state.this_is_a_follow || + strcasecompare(data->state.first_host, conn->host.name))) { #if !defined(CURL_DISABLE_COOKIES) - if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie")) - addcookies = data->set.str[STRING_COOKIE]; -#endif - - if(!Curl_checkheaders(conn, "Accept-Encoding") && - data->set.str[STRING_ENCODING]) { - Curl_safefree(data->state.aptr.accept_encoding); - data->state.aptr.accept_encoding = - aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); - if(!data->state.aptr.accept_encoding) + /* If we have a given custom Host: header, we extract the host name in + order to possibly use it for cookie reasons later on. We only allow the + custom Host: header if this is NOT a redirect, as setting Host: in the + redirected request is being out on thin ice. Except if the host name + is the same as the first one! */ + char *cookiehost = Curl_copy_header_value(ptr); + if(!cookiehost) return CURLE_OUT_OF_MEMORY; - } - else { - Curl_safefree(data->state.aptr.accept_encoding); - data->state.aptr.accept_encoding = NULL; - } - -#ifdef HAVE_LIBZ - /* we only consider transfer-encoding magic if libz support is built-in */ - - if(!Curl_checkheaders(conn, "TE") && - data->set.http_transfer_encoding) { - /* When we are to insert a TE: header in the request, we must also insert - TE in a Connection: header, so we need to merge the custom provided - Connection: header and prevent the original to get sent. Note that if - the user has inserted his/hers own TE: header we don't do this magic - but then assume that the user will handle it all! */ - char *cptr = Curl_checkheaders(conn, "Connection"); -#define TE_HEADER "TE: gzip\r\n" - - Curl_safefree(data->state.aptr.te); + if(!*cookiehost) + /* ignore empty data */ + free(cookiehost); + else { + /* If the host begins with '[', we start searching for the port after + the bracket has been closed */ + if(*cookiehost == '[') { + char *closingbracket; + /* since the 'cookiehost' is an allocated memory area that will be + freed later we cannot simply increment the pointer */ + memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1); + closingbracket = strchr(cookiehost, ']'); + if(closingbracket) + *closingbracket = 0; + } + else { + int startsearch = 0; + char *colon = strchr(cookiehost + startsearch, ':'); + if(colon) + *colon = 0; /* The host must not include an embedded port number */ + } + Curl_safefree(data->state.aptr.cookiehost); + data->state.aptr.cookiehost = cookiehost; + } +#endif - if(cptr) { - cptr = Curl_copy_header_value(cptr); - if(!cptr) + if(strcmp("Host:", ptr)) { + data->state.aptr.host = aprintf("Host:%s\r\n", &ptr[5]); + if(!data->state.aptr.host) return CURLE_OUT_OF_MEMORY; } + else + /* when clearing the header */ + data->state.aptr.host = NULL; + } + else { + /* When building Host: headers, we must put the host name within + [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ + const char *host = conn->host.name; - /* Create the (updated) Connection: header */ - data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER, - cptr ? cptr : "", (cptr && *cptr) ? ", ":""); + if(((conn->given->protocol&CURLPROTO_HTTPS) && + (conn->remote_port == PORT_HTTPS)) || + ((conn->given->protocol&CURLPROTO_HTTP) && + (conn->remote_port == PORT_HTTP)) ) + /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include + the port number in the host string */ + data->state.aptr.host = aprintf("Host: %s%s%s\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":""); + else + data->state.aptr.host = aprintf("Host: %s%s%s:%d\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":"", + conn->remote_port); - free(cptr); - if(!data->state.aptr.te) + if(!data->state.aptr.host) + /* without Host: we can't make a nice request */ return CURLE_OUT_OF_MEMORY; } + return CURLE_OK; +} + +/* + * Append the request-target to the HTTP request + */ +CURLcode Curl_http_target(struct Curl_easy *data, + struct connectdata *conn, + struct dynbuf *r) +{ + CURLcode result = CURLE_OK; + const char *path = data->state.up.path; + const char *query = data->state.up.query; + + if(data->set.str[STRING_TARGET]) { + path = data->set.str[STRING_TARGET]; + query = NULL; + } + +#ifndef CURL_DISABLE_PROXY + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + /* Using a proxy but does not tunnel through it */ + + /* The path sent to the proxy is in fact the entire URL. But if the remote + host is a IDN-name, we must make sure that the request we produce only + uses the encoded host name! */ + + /* and no fragment part */ + CURLUcode uc; + char *url; + CURLU *h = curl_url_dup(data->state.uh); + if(!h) + return CURLE_OUT_OF_MEMORY; + + if(conn->host.dispname != conn->host.name) { + uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + } + uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + + if(strcasecompare("http", data->state.up.scheme)) { + /* when getting HTTP, we don't want the userinfo the URL */ + uc = curl_url_set(h, CURLUPART_USER, NULL, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + } + /* Extract the URL to use in the request. Store in STRING_TEMP_URL for + clean-up reasons if the function returns before the free() further + down. */ + uc = curl_url_get(h, CURLUPART_URL, &url, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + + curl_url_cleanup(h); + + /* target or url */ + result = Curl_dyn_add(r, data->set.str[STRING_TARGET]? + data->set.str[STRING_TARGET]:url); + free(url); + if(result) + return (result); + + if(strcasecompare("ftp", data->state.up.scheme)) { + if(data->set.proxy_transfer_mode) { + /* when doing ftp, append ;type= if not present */ + char *type = strstr(path, ";type="); + if(type && type[6] && type[7] == 0) { + switch(Curl_raw_toupper(type[6])) { + case 'A': + case 'D': + case 'I': + break; + default: + type = NULL; + } + } + if(!type) { + result = Curl_dyn_addf(r, ";type=%c", + data->set.prefer_ascii ? 'a' : 'i'); + if(result) + return result; + } + } + } + } + + else +#else + (void)conn; /* not used in disabled-proxy builds */ #endif + { + result = Curl_dyn_add(r, path); + if(result) + return result; + if(query) + result = Curl_dyn_addf(r, "?%s", query); + } + + return result; +} + +CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, + Curl_HttpReq httpreq, const char **tep) +{ + CURLcode result = CURLE_OK; + const char *ptr; + struct HTTP *http = data->req.p.http; + http->postsize = 0; switch(httpreq) { case HTTPREQ_POST_MIME: @@ -2135,7 +2255,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) #ifndef CURL_DISABLE_MIME if(http->sendit) { - const char *cthdr = Curl_checkheaders(conn, "Content-Type"); + const char *cthdr = Curl_checkheaders(data, "Content-Type"); /* Read and seek body only. */ http->sendit->flags |= MIME_BODY_ONLY; @@ -2160,7 +2280,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } #endif - ptr = Curl_checkheaders(conn, "Transfer-Encoding"); + ptr = Curl_checkheaders(data, "Transfer-Encoding"); if(ptr) { /* Some kind of TE is requested, check if 'chunked' is chosen */ data->req.upload_chunky = @@ -2191,409 +2311,348 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } if(data->req.upload_chunky) - te = "Transfer-Encoding: chunked\r\n"; + *tep = "Transfer-Encoding: chunked\r\n"; } + return result; +} - Curl_safefree(data->state.aptr.host); - - ptr = Curl_checkheaders(conn, "Host"); - if(ptr && (!data->state.this_is_a_follow || - strcasecompare(data->state.first_host, conn->host.name))) { -#if !defined(CURL_DISABLE_COOKIES) - /* If we have a given custom Host: header, we extract the host name in - order to possibly use it for cookie reasons later on. We only allow the - custom Host: header if this is NOT a redirect, as setting Host: in the - redirected request is being out on thin ice. Except if the host name - is the same as the first one! */ - char *cookiehost = Curl_copy_header_value(ptr); - if(!cookiehost) - return CURLE_OUT_OF_MEMORY; - if(!*cookiehost) - /* ignore empty data */ - free(cookiehost); - else { - /* If the host begins with '[', we start searching for the port after - the bracket has been closed */ - if(*cookiehost == '[') { - char *closingbracket; - /* since the 'cookiehost' is an allocated memory area that will be - freed later we cannot simply increment the pointer */ - memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1); - closingbracket = strchr(cookiehost, ']'); - if(closingbracket) - *closingbracket = 0; - } - else { - int startsearch = 0; - char *colon = strchr(cookiehost + startsearch, ':'); - if(colon) - *colon = 0; /* The host must not include an embedded port number */ - } - Curl_safefree(data->state.aptr.cookiehost); - data->state.aptr.cookiehost = cookiehost; - } +CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, + struct dynbuf *r, Curl_HttpReq httpreq) +{ +#ifndef USE_HYPER + /* Hyper always handles the body separately */ + curl_off_t included_body = 0; #endif + CURLcode result = CURLE_OK; + struct HTTP *http = data->req.p.http; + const char *ptr; - if(strcmp("Host:", ptr)) { - data->state.aptr.host = aprintf("Host:%s\r\n", &ptr[5]); - if(!data->state.aptr.host) - return CURLE_OUT_OF_MEMORY; - } - else - /* when clearing the header */ - data->state.aptr.host = NULL; - } - else { - /* When building Host: headers, we must put the host name within - [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ - - if(((conn->given->protocol&CURLPROTO_HTTPS) && - (conn->remote_port == PORT_HTTPS)) || - ((conn->given->protocol&CURLPROTO_HTTP) && - (conn->remote_port == PORT_HTTP)) ) - /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include - the port number in the host string */ - data->state.aptr.host = aprintf("Host: %s%s%s\r\n", - conn->bits.ipv6_ip?"[":"", - host, - conn->bits.ipv6_ip?"]":""); - else - data->state.aptr.host = aprintf("Host: %s%s%s:%d\r\n", - conn->bits.ipv6_ip?"[":"", - host, - conn->bits.ipv6_ip?"]":"", - conn->remote_port); - - if(!data->state.aptr.host) - /* without Host: we can't make a nice request */ - return CURLE_OUT_OF_MEMORY; - } + /* If 'authdone' is FALSE, we must not set the write socket index to the + Curl_transfer() call below, as we're not ready to actually upload any + data yet. */ -#ifndef CURL_DISABLE_PROXY - if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { - /* Using a proxy but does not tunnel through it */ + switch(httpreq) { - /* The path sent to the proxy is in fact the entire URL. But if the remote - host is a IDN-name, we must make sure that the request we produce only - uses the encoded host name! */ + case HTTPREQ_PUT: /* Let's PUT the data to the server! */ - /* and no fragment part */ - CURLUcode uc; - CURLU *h = curl_url_dup(data->state.uh); - if(!h) - return CURLE_OUT_OF_MEMORY; + if(conn->bits.authneg) + http->postsize = 0; + else + http->postsize = data->state.infilesize; - if(conn->host.dispname != conn->host.name) { - uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0); - if(uc) { - curl_url_cleanup(h); - return CURLE_OUT_OF_MEMORY; - } - } - uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0); - if(uc) { - curl_url_cleanup(h); - return CURLE_OUT_OF_MEMORY; + if((http->postsize != -1) && !data->req.upload_chunky && + (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) { + /* only add Content-Length if not uploading chunked */ + result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", http->postsize); + if(result) + return result; } - if(strcasecompare("http", data->state.up.scheme)) { - /* when getting HTTP, we don't want the userinfo the URL */ - uc = curl_url_set(h, CURLUPART_USER, NULL, 0); - if(uc) { - curl_url_cleanup(h); - return CURLE_OUT_OF_MEMORY; - } - uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0); - if(uc) { - curl_url_cleanup(h); - return CURLE_OUT_OF_MEMORY; - } - } - /* Extract the URL to use in the request. Store in STRING_TEMP_URL for - clean-up reasons if the function returns before the free() further - down. */ - uc = curl_url_get(h, CURLUPART_URL, &data->set.str[STRING_TEMP_URL], 0); - if(uc) { - curl_url_cleanup(h); - return CURLE_OUT_OF_MEMORY; + if(http->postsize) { + result = expect100(data, conn, r); + if(result) + return result; } - curl_url_cleanup(h); + /* end of headers */ + result = Curl_dyn_add(r, "\r\n"); + if(result) + return result; - if(strcasecompare("ftp", data->state.up.scheme)) { - if(data->set.proxy_transfer_mode) { - /* when doing ftp, append ;type= if not present */ - char *type = strstr(path, ";type="); - if(type && type[6] && type[7] == 0) { - switch(Curl_raw_toupper(type[6])) { - case 'A': - case 'D': - case 'I': - break; - default: - type = NULL; - } - } - if(!type) { - char *p = ftp_typecode; - /* avoid sending invalid URLs like ftp://example.com;type=i if the - * user specified ftp://example.com without the slash */ - if(!*data->state.up.path && path[strlen(path) - 1] != '/') { - *p++ = '/'; - } - msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c", - data->set.prefer_ascii ? 'a' : 'i'); - } - } - if(conn->bits.user_passwd) - paste_ftp_userpwd = TRUE; - } - } -#endif /* CURL_DISABLE_PROXY */ + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); - http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n"; + /* this sends the buffer and frees all the buffer resources */ + result = Curl_buffer_send(r, data, &data->info.request_size, 0, + FIRSTSOCKET); + if(result) + failf(data, "Failed sending PUT request"); + else + /* prepare for transfer */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postsize?FIRSTSOCKET:-1); + if(result) + return result; + break; - if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) && - data->state.resume_from) { - /********************************************************************** - * Resuming upload in HTTP means that we PUT or POST and that we have - * got a resume_from value set. The resume value has already created - * a Range: header that will be passed along. We need to "fast forward" - * the file the given number of bytes and decrease the assume upload - * file size before we continue this venture in the dark lands of HTTP. - * Resuming mime/form posting at an offset > 0 has no sense and is ignored. - *********************************************************************/ + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + /* This is form posting using mime data. */ + if(conn->bits.authneg) { + /* nothing to post! */ + result = Curl_dyn_add(r, "Content-Length: 0\r\n\r\n"); + if(result) + return result; - if(data->state.resume_from < 0) { - /* - * This is meant to get the size of the present remote-file by itself. - * We don't support this now. Bail out! - */ - data->state.resume_from = 0; + result = Curl_buffer_send(r, data, &data->info.request_size, 0, + FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); + else + /* setup variables for the upcoming transfer */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); + break; } - if(data->state.resume_from && !data->state.this_is_a_follow) { - /* do we still game? */ + data->state.infilesize = http->postsize; - /* Now, let's read off the proper amount of bytes from the - input. */ - int seekerr = CURL_SEEKFUNC_CANTSEEK; - if(conn->seek_func) { - Curl_set_in_callback(data, true); - seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, - SEEK_SET); - Curl_set_in_callback(data, false); + /* We only set Content-Length and allow a custom Content-Length if + we don't upload data chunked, as RFC2616 forbids us to set both + kinds of headers (Transfer-Encoding: chunked and Content-Length) */ + if(http->postsize != -1 && !data->req.upload_chunky && + (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) { + /* we allow replacing this header if not during auth negotiation, + although it isn't very wise to actually set your own */ + result = Curl_dyn_addf(r, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", http->postsize); + if(result) + return result; + } + +#ifndef CURL_DISABLE_MIME + /* Output mime-generated headers. */ + { + struct curl_slist *hdr; + + for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) { + result = Curl_dyn_addf(r, "%s\r\n", hdr->data); + if(result) + return result; } + } +#endif - if(seekerr != CURL_SEEKFUNC_OK) { - curl_off_t passed = 0; + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + ptr = Curl_checkheaders(data, "Expect"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) { + result = expect100(data, conn, r); + if(result) + return result; + } + else + data->state.expect100header = FALSE; - if(seekerr != CURL_SEEKFUNC_CANTSEEK) { - failf(data, "Could not seek stream"); - return CURLE_READ_ERROR; - } - /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ - do { - size_t readthisamountnow = - (data->state.resume_from - passed > data->set.buffer_size) ? - (size_t)data->set.buffer_size : - curlx_sotouz(data->state.resume_from - passed); + /* make the request end in a true CRLF */ + result = Curl_dyn_add(r, "\r\n"); + if(result) + return result; - size_t actuallyread = - data->state.fread_func(data->state.buffer, 1, readthisamountnow, - data->state.in); + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); - passed += actuallyread; - if((actuallyread == 0) || (actuallyread > readthisamountnow)) { - /* this checks for greater-than only to make sure that the - CURL_READFUNC_ABORT return code still aborts */ - failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T - " bytes from the input", passed); - return CURLE_READ_ERROR; - } - } while(passed < data->state.resume_from); - } + /* Read from mime structure. */ + data->state.fread_func = (curl_read_callback) Curl_mime_read; + data->state.in = (void *) http->sendit; + http->sending = HTTPSEND_BODY; - /* now, decrease the size of the read */ - if(data->state.infilesize>0) { - data->state.infilesize -= data->state.resume_from; + /* this sends the buffer and frees all the buffer resources */ + result = Curl_buffer_send(r, data, &data->info.request_size, 0, + FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); + else + /* prepare for transfer */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postsize?FIRSTSOCKET:-1); + if(result) + return result; - if(data->state.infilesize <= 0) { - failf(data, "File already completely uploaded"); - return CURLE_PARTIAL_FILE; - } - } - /* we've passed, proceed as normal */ + break; + + case HTTPREQ_POST: + /* this is the simple POST, using x-www-form-urlencoded style */ + + if(conn->bits.authneg) + http->postsize = 0; + else + /* the size of the post body */ + http->postsize = data->state.infilesize; + + /* We only set Content-Length and allow a custom Content-Length if + we don't upload data chunked, as RFC2616 forbids us to set both + kinds of headers (Transfer-Encoding: chunked and Content-Length) */ + if((http->postsize != -1) && !data->req.upload_chunky && + (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) { + /* we allow replacing this header if not during auth negotiation, + although it isn't very wise to actually set your own */ + result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", http->postsize); + if(result) + return result; } - } - if(data->state.use_range) { - /* - * A range is selected. We use different headers whether we're downloading - * or uploading and we always let customized headers override our internal - * ones if any such are specified. - */ - if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && - !Curl_checkheaders(conn, "Range")) { - /* if a line like this was already allocated, free the previous one */ - free(data->state.aptr.rangeline); - data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n", - data->state.range); + + if(!Curl_checkheaders(data, "Content-Type")) { + result = Curl_dyn_add(r, "Content-Type: application/" + "x-www-form-urlencoded\r\n"); + if(result) + return result; } - else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) && - !Curl_checkheaders(conn, "Content-Range")) { - /* if a line like this was already allocated, free the previous one */ - free(data->state.aptr.rangeline); + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + ptr = Curl_checkheaders(data, "Expect"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) { + result = expect100(data, conn, r); + if(result) + return result; + } + else + data->state.expect100header = FALSE; - if(data->set.set_resume_from < 0) { - /* Upload resume was asked for, but we don't know the size of the - remote part so we tell the server (and act accordingly) that we - upload the whole file (again) */ - data->state.aptr.rangeline = - aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T - "/%" CURL_FORMAT_CURL_OFF_T "\r\n", - data->state.infilesize - 1, data->state.infilesize); +#ifndef USE_HYPER + /* With Hyper the body is always passed on separately */ + if(data->set.postfields) { - } - else if(data->state.resume_from) { - /* This is because "resume" was selected */ - curl_off_t total_expected_size = - data->state.resume_from + data->state.infilesize; - data->state.aptr.rangeline = - aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T - "/%" CURL_FORMAT_CURL_OFF_T "\r\n", - data->state.range, total_expected_size-1, - total_expected_size); - } - else { - /* Range was selected and then we just pass the incoming range and - append total size */ - data->state.aptr.rangeline = - aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n", - data->state.range, data->state.infilesize); - } - if(!data->state.aptr.rangeline) - return CURLE_OUT_OF_MEMORY; - } - } + /* In HTTP2, we send request body in DATA frame regardless of + its size. */ + if(conn->httpversion != 20 && + !data->state.expect100header && + (http->postsize < MAX_INITIAL_POST_SIZE)) { + /* if we don't use expect: 100 AND + postsize is less than MAX_INITIAL_POST_SIZE - httpstring = get_http_string(data, conn); + then append the post data to the HTTP request header. This limit + is no magic limit but only set to prevent really huge POSTs to + get the data duplicated with malloc() and family. */ - /* initialize a dynamic send-buffer */ - Curl_dyn_init(&req, DYN_HTTP_REQUEST); + /* end of headers! */ + result = Curl_dyn_add(r, "\r\n"); + if(result) + return result; - /* add the main request stuff */ - /* GET/HEAD/POST/PUT */ - result = Curl_dyn_addf(&req, "%s ", request); - if(result) - return result; + if(!data->req.upload_chunky) { + /* We're not sending it 'chunked', append it to the request + already now to reduce the number if send() calls */ + result = Curl_dyn_addn(r, data->set.postfields, + (size_t)http->postsize); + included_body = http->postsize; + } + else { + if(http->postsize) { + char chunk[16]; + /* Append the POST data chunky-style */ + msnprintf(chunk, sizeof(chunk), "%x\r\n", (int)http->postsize); + result = Curl_dyn_add(r, chunk); + if(!result) { + included_body = http->postsize + strlen(chunk); + result = Curl_dyn_addn(r, data->set.postfields, + (size_t)http->postsize); + if(!result) + result = Curl_dyn_add(r, "\r\n"); + included_body += 2; + } + } + if(!result) { + result = Curl_dyn_add(r, "\x30\x0d\x0a\x0d\x0a"); + /* 0 CR LF CR LF */ + included_body += 5; + } + } + if(result) + return result; + /* Make sure the progress information is accurate */ + Curl_pgrsSetUploadSize(data, http->postsize); + } + else { + /* A huge POST coming up, do data separate from the request */ + http->postdata = data->set.postfields; - if(data->set.str[STRING_TARGET]) { - path = data->set.str[STRING_TARGET]; - query = NULL; - } + http->sending = HTTPSEND_BODY; -#ifndef CURL_DISABLE_PROXY - /* url */ - if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { - char *url = data->set.str[STRING_TEMP_URL]; - result = Curl_dyn_add(&req, url); - Curl_safefree(data->set.str[STRING_TEMP_URL]); - } - else -#endif - if(paste_ftp_userpwd) - result = Curl_dyn_addf(&req, "ftp://%s:%s@%s", conn->user, conn->passwd, - path + sizeof("ftp://") - 1); - else { - result = Curl_dyn_add(&req, path); - if(result) - return result; - if(query) - result = Curl_dyn_addf(&req, "?%s", query); - } - if(result) - return result; + data->state.fread_func = (curl_read_callback)readmoredata; + data->state.in = (void *)data; -#ifndef CURL_DISABLE_ALTSVC - if(conn->bits.altused && !Curl_checkheaders(conn, "Alt-Used")) { - altused = aprintf("Alt-Used: %s:%d\r\n", - conn->conn_to_host.name, conn->conn_to_port); - if(!altused) { - Curl_dyn_free(&req); - return CURLE_OUT_OF_MEMORY; + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); + + /* end of headers! */ + result = Curl_dyn_add(r, "\r\n"); + if(result) + return result; + } } - } + else #endif - result = - Curl_dyn_addf(&req, - "%s" /* ftp typecode (;type=x) */ - " HTTP/%s\r\n" /* HTTP version */ - "%s" /* host */ - "%s" /* proxyuserpwd */ - "%s" /* userpwd */ - "%s" /* range */ - "%s" /* user agent */ - "%s" /* accept */ - "%s" /* TE: */ - "%s" /* accept-encoding */ - "%s" /* referer */ - "%s" /* Proxy-Connection */ - "%s" /* transfer-encoding */ - "%s",/* Alt-Used */ + { + /* end of headers! */ + result = Curl_dyn_add(r, "\r\n"); + if(result) + return result; - ftp_typecode, - httpstring, - (data->state.aptr.host?data->state.aptr.host:""), - data->state.aptr.proxyuserpwd? - data->state.aptr.proxyuserpwd:"", - data->state.aptr.userpwd?data->state.aptr.userpwd:"", - (data->state.use_range && data->state.aptr.rangeline)? - data->state.aptr.rangeline:"", - (data->set.str[STRING_USERAGENT] && - *data->set.str[STRING_USERAGENT] && - data->state.aptr.uagent)? - data->state.aptr.uagent:"", - http->p_accept?http->p_accept:"", - data->state.aptr.te?data->state.aptr.te:"", - (data->set.str[STRING_ENCODING] && - *data->set.str[STRING_ENCODING] && - data->state.aptr.accept_encoding)? - data->state.aptr.accept_encoding:"", - (data->change.referer && data->state.aptr.ref)? - data->state.aptr.ref:"" /* Referer: */, -#ifndef CURL_DISABLE_PROXY - (conn->bits.httpproxy && - !conn->bits.tunnel_proxy && - !Curl_checkProxyheaders(conn, "Proxy-Connection"))? - "Proxy-Connection: Keep-Alive\r\n":"", -#else - "", -#endif - te, - altused ? altused : "" - ); + if(data->req.upload_chunky && conn->bits.authneg) { + /* Chunky upload is selected and we're negotiating auth still, send + end-of-data only */ + result = Curl_dyn_add(r, (char *)"\x30\x0d\x0a\x0d\x0a"); + /* 0 CR LF CR LF */ + if(result) + return result; + } - /* clear userpwd and proxyuserpwd to avoid re-using old credentials - * from re-used connections */ - Curl_safefree(data->state.aptr.userpwd); - Curl_safefree(data->state.aptr.proxyuserpwd); - free(altused); + else if(data->state.infilesize) { + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize?http->postsize:-1); - if(result) - return result; + /* set the pointer to mark that we will send the post body using the + read callback, but only if we're not in authenticate negotiation */ + if(!conn->bits.authneg) + http->postdata = (char *)&http->postdata; + } + } + /* issue the request */ + result = Curl_buffer_send(r, data, &data->info.request_size, + (size_t)included_body, FIRSTSOCKET); - if(!(conn->handler->flags&PROTOPT_SSL) && - conn->httpversion != 20 && - (data->set.httpversion == CURL_HTTP_VERSION_2)) { - /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done - over SSL */ - result = Curl_http2_request_upgrade(&req, conn); + if(result) + failf(data, "Failed sending HTTP POST request"); + else + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postdata?FIRSTSOCKET:-1); + break; + + default: + result = Curl_dyn_add(r, "\r\n"); if(result) return result; + + /* issue the request */ + result = Curl_buffer_send(r, data, &data->info.request_size, 0, + FIRSTSOCKET); + + if(result) + failf(data, "Failed sending HTTP request"); + else + /* HTTP GET/HEAD download: */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); } + return result; +} + #if !defined(CURL_DISABLE_COOKIES) +CURLcode Curl_http_cookies(struct Curl_easy *data, + struct connectdata *conn, + struct dynbuf *r) +{ + CURLcode result = CURLE_OK; + char *addcookies = NULL; + if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie")) + addcookies = data->set.str[STRING_COOKIE]; + if(data->cookies || addcookies) { struct Cookie *co = NULL; /* no cookies from start */ int count = 0; @@ -2602,7 +2661,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) 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:host, + data->state.aptr.cookiehost: + conn->host.name, data->state.up.path, (conn->handler->protocol&CURLPROTO_HTTPS)? TRUE:FALSE); @@ -2614,11 +2674,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) while(co) { if(co->value) { if(0 == count) { - result = Curl_dyn_add(&req, "Cookie: "); + result = Curl_dyn_add(r, "Cookie: "); if(result) break; } - result = Curl_dyn_addf(&req, "%s%s=%s", count?"; ":"", + result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"", co->name, co->value); if(result) break; @@ -2630,361 +2690,516 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } if(addcookies && !result) { if(!count) - result = Curl_dyn_add(&req, "Cookie: "); + result = Curl_dyn_add(r, "Cookie: "); if(!result) { - result = Curl_dyn_addf(&req, "%s%s", count?"; ":"", addcookies); + result = Curl_dyn_addf(r, "%s%s", count?"; ":"", addcookies); count++; } } if(count && !result) - result = Curl_dyn_add(&req, "\r\n"); + result = Curl_dyn_add(r, "\r\n"); if(result) return result; } + return result; +} #endif - result = Curl_add_timecondition(conn, &req); - if(result) - return result; +CURLcode Curl_http_range(struct Curl_easy *data, + Curl_HttpReq httpreq) +{ + if(data->state.use_range) { + /* + * A range is selected. We use different headers whether we're downloading + * or uploading and we always let customized headers override our internal + * ones if any such are specified. + */ + if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && + !Curl_checkheaders(data, "Range")) { + /* if a line like this was already allocated, free the previous one */ + free(data->state.aptr.rangeline); + data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n", + data->state.range); + } + else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) && + !Curl_checkheaders(data, "Content-Range")) { - result = Curl_add_custom_headers(conn, FALSE, &req); - if(result) - return result; + /* if a line like this was already allocated, free the previous one */ + free(data->state.aptr.rangeline); - http->postdata = NULL; /* nothing to post at this point */ - Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */ + if(data->set.set_resume_from < 0) { + /* Upload resume was asked for, but we don't know the size of the + remote part so we tell the server (and act accordingly) that we + upload the whole file (again) */ + data->state.aptr.rangeline = + aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T + "/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.infilesize - 1, data->state.infilesize); - /* If 'authdone' is FALSE, we must not set the write socket index to the - Curl_transfer() call below, as we're not ready to actually upload any - data yet. */ + } + else if(data->state.resume_from) { + /* This is because "resume" was selected */ + curl_off_t total_expected_size = + data->state.resume_from + data->state.infilesize; + data->state.aptr.rangeline = + aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T + "/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.range, total_expected_size-1, + total_expected_size); + } + else { + /* Range was selected and then we just pass the incoming range and + append total size */ + data->state.aptr.rangeline = + aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.range, data->state.infilesize); + } + if(!data->state.aptr.rangeline) + return CURLE_OUT_OF_MEMORY; + } + } + return CURLE_OK; +} - switch(httpreq) { +CURLcode Curl_http_resume(struct Curl_easy *data, + struct connectdata *conn, + Curl_HttpReq httpreq) +{ + if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) && + data->state.resume_from) { + /********************************************************************** + * Resuming upload in HTTP means that we PUT or POST and that we have + * got a resume_from value set. The resume value has already created + * a Range: header that will be passed along. We need to "fast forward" + * the file the given number of bytes and decrease the assume upload + * file size before we continue this venture in the dark lands of HTTP. + * Resuming mime/form posting at an offset > 0 has no sense and is ignored. + *********************************************************************/ - case HTTPREQ_PUT: /* Let's PUT the data to the server! */ + if(data->state.resume_from < 0) { + /* + * This is meant to get the size of the present remote-file by itself. + * We don't support this now. Bail out! + */ + data->state.resume_from = 0; + } - if(conn->bits.authneg) - postsize = 0; - else - postsize = data->state.infilesize; + if(data->state.resume_from && !data->state.this_is_a_follow) { + /* do we still game? */ - if((postsize != -1) && !data->req.upload_chunky && - (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { - /* only add Content-Length if not uploading chunked */ - result = Curl_dyn_addf(&req, "Content-Length: %" CURL_FORMAT_CURL_OFF_T - "\r\n", postsize); - if(result) - return result; - } + /* Now, let's read off the proper amount of bytes from the + input. */ + int seekerr = CURL_SEEKFUNC_CANTSEEK; + if(conn->seek_func) { + Curl_set_in_callback(data, true); + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + Curl_set_in_callback(data, false); + } - if(postsize != 0) { - result = expect100(data, conn, &req); - if(result) - return result; - } + if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed = 0; - /* end of headers */ - result = Curl_dyn_add(&req, "\r\n"); - if(result) - return result; + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_READ_ERROR; + } + /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + do { + size_t readthisamountnow = + (data->state.resume_from - passed > data->set.buffer_size) ? + (size_t)data->set.buffer_size : + curlx_sotouz(data->state.resume_from - passed); - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, postsize); + size_t actuallyread = + data->state.fread_func(data->state.buffer, 1, readthisamountnow, + data->state.in); - /* this sends the buffer and frees all the buffer resources */ - result = Curl_buffer_send(&req, conn, &data->info.request_size, 0, - FIRSTSOCKET); - if(result) - failf(data, "Failed sending PUT request"); - else - /* prepare for transfer */ - Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, - postsize?FIRSTSOCKET:-1); - if(result) - return result; - break; + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T + " bytes from the input", passed); + return CURLE_READ_ERROR; + } + } while(passed < data->state.resume_from); + } - case HTTPREQ_POST_FORM: - case HTTPREQ_POST_MIME: - /* This is form posting using mime data. */ - if(conn->bits.authneg) { - /* nothing to post! */ - result = Curl_dyn_add(&req, "Content-Length: 0\r\n\r\n"); - if(result) - return result; + /* now, decrease the size of the read */ + if(data->state.infilesize>0) { + data->state.infilesize -= data->state.resume_from; - result = Curl_buffer_send(&req, conn, &data->info.request_size, 0, - FIRSTSOCKET); - if(result) - failf(data, "Failed sending POST request"); - else - /* setup variables for the upcoming transfer */ - Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); - break; + if(data->state.infilesize <= 0) { + failf(data, "File already completely uploaded"); + return CURLE_PARTIAL_FILE; + } + } + /* we've passed, proceed as normal */ } + } + return CURLE_OK; +} - data->state.infilesize = postsize = http->postsize; +CURLcode Curl_http_firstwrite(struct Curl_easy *data, + struct connectdata *conn, + 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 + and we're set to close anyway. */ + k->keepon &= ~KEEP_RECV; + *done = TRUE; + return CURLE_OK; + } + /* We have a new url to load, but since we want to be able to re-use this + connection properly, we read the full response in "ignore more" */ + k->ignorebody = TRUE; + infof(data, "Ignoring the response-body\n"); + } + if(data->state.resume_from && !k->content_range && + (data->state.httpreq == HTTPREQ_GET) && + !k->ignorebody) { + + if(k->size == data->state.resume_from) { + /* The resume point is at the end of file, consider this fine even if it + doesn't allow resume from here. */ + infof(data, "The entire document is already downloaded"); + connclose(conn, "already downloaded"); + /* Abort download */ + k->keepon &= ~KEEP_RECV; + *done = TRUE; + return CURLE_OK; + } - /* We only set Content-Length and allow a custom Content-Length if - we don't upload data chunked, as RFC2616 forbids us to set both - kinds of headers (Transfer-Encoding: chunked and Content-Length) */ - if(postsize != -1 && !data->req.upload_chunky && - (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { - /* we allow replacing this header if not during auth negotiation, - although it isn't very wise to actually set your own */ - result = Curl_dyn_addf(&req, - "Content-Length: %" CURL_FORMAT_CURL_OFF_T - "\r\n", postsize); - if(result) - return result; + /* we wanted to resume a download, although the server doesn't seem to + * support this and we did this with a GET (if it wasn't a GET we did a + * POST or PUT resume) */ + failf(data, "HTTP server doesn't seem to support " + "byte ranges. Cannot resume."); + return CURLE_RANGE_ERROR; + } + + if(data->set.timecondition && !data->state.range) { + /* A time condition has been set AND no ranges have been requested. This + seems to be what chapter 13.3.4 of RFC 2616 defines to be the correct + action for a HTTP/1.1 client */ + + if(!Curl_meets_timecondition(data, k->timeofdoc)) { + *done = TRUE; + /* We're simulating a http 304 from server so we return + what should have been returned from the server */ + data->info.httpcode = 304; + infof(data, "Simulate a HTTP 304 response!\n"); + /* we abort the transfer before it is completed == we ruin the + re-use ability. Close the connection */ + connclose(conn, "Simulated 304 handling"); + return CURLE_OK; } + } /* we have a time condition */ -#ifndef CURL_DISABLE_MIME - /* Output mime-generated headers. */ - { - struct curl_slist *hdr; + return CURLE_OK; +} - for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) { - result = Curl_dyn_addf(&req, "%s\r\n", hdr->data); +#ifndef USE_HYPER +/* + * 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 + * HTTP request. + */ +CURLcode Curl_http(struct Curl_easy *data, bool *done) +{ + struct connectdata *conn = data->conn; + CURLcode result = CURLE_OK; + struct HTTP *http; + Curl_HttpReq httpreq; + const char *te = ""; /* transfer-encoding */ + const char *request; + const char *httpstring; + struct dynbuf req; + char *altused = NULL; + const char *p_accept; /* Accept: string */ + + /* Always consider the DO phase done after this function call, even if there + may be parts of the request that are not yet sent, since we can deal with + the rest of the request in the PERFORM phase. */ + *done = TRUE; + + if(conn->transport != TRNSPRT_QUIC) { + if(conn->httpversion < 20) { /* unless the connection is re-used and + already http2 */ + switch(conn->negnpn) { + case CURL_HTTP_VERSION_2: + conn->httpversion = 20; /* we know we're on HTTP/2 now */ + + result = Curl_http2_switched(data, NULL, 0); if(result) return result; - } - } + break; + case CURL_HTTP_VERSION_1_1: + /* continue with HTTP/1.1 when explicitly requested */ + break; + default: + /* Check if user wants to use HTTP/2 with clear TCP*/ +#ifdef USE_NGHTTP2 + if(data->set.httpversion == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) { +#ifndef CURL_DISABLE_PROXY + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + /* We don't support HTTP/2 proxies yet. Also it's debatable + whether or not this setting should apply to HTTP/2 proxies. */ + infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n"); + break; + } #endif + DEBUGF(infof(data, "HTTP/2 over clean TCP\n")); + conn->httpversion = 20; - /* For really small posts we don't use Expect: headers at all, and for - the somewhat bigger ones we allow the app to disable it. Just make - sure that the expect100header is always set to the preferred value - here. */ - ptr = Curl_checkheaders(conn, "Expect"); - if(ptr) { - data->state.expect100header = - Curl_compareheader(ptr, "Expect:", "100-continue"); + result = Curl_http2_switched(data, NULL, 0); + if(result) + return result; + } +#endif + break; + } } - else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) { - result = expect100(data, conn, &req); + else { + /* prepare for a http2 request */ + result = Curl_http2_setup(data, conn); if(result) return result; } - else - data->state.expect100header = FALSE; + } + http = data->req.p.http; + DEBUGASSERT(http); - /* make the request end in a true CRLF */ - result = Curl_dyn_add(&req, "\r\n"); - if(result) - return result; + result = Curl_http_host(data, conn); + if(result) + return result; - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, postsize); + result = Curl_http_useragent(data); + if(result) + return result; - /* Read from mime structure. */ - data->state.fread_func = (curl_read_callback) Curl_mime_read; - data->state.in = (void *) http->sendit; - http->sending = HTTPSEND_BODY; + Curl_http_method(data, conn, &request, &httpreq); - /* this sends the buffer and frees all the buffer resources */ - result = Curl_buffer_send(&req, conn, &data->info.request_size, 0, - FIRSTSOCKET); - if(result) - failf(data, "Failed sending POST request"); - else - /* prepare for transfer */ - Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, - postsize?FIRSTSOCKET:-1); + /* setup the authentication headers */ + { + char *pq = NULL; + if(data->state.up.query) { + pq = aprintf("%s?%s", data->state.up.path, data->state.up.query); + if(!pq) + return CURLE_OUT_OF_MEMORY; + } + result = Curl_http_output_auth(data, conn, request, httpreq, + (pq ? pq : data->state.up.path), FALSE); + free(pq); if(result) return result; + } - break; + Curl_safefree(data->state.aptr.ref); + if(data->change.referer && !Curl_checkheaders(data, "Referer")) { + data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + if(!data->state.aptr.ref) + return CURLE_OUT_OF_MEMORY; + } - case HTTPREQ_POST: - /* this is the simple POST, using x-www-form-urlencoded style */ + if(!Curl_checkheaders(data, "Accept-Encoding") && + data->set.str[STRING_ENCODING]) { + Curl_safefree(data->state.aptr.accept_encoding); + 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; + } + else { + Curl_safefree(data->state.aptr.accept_encoding); + data->state.aptr.accept_encoding = NULL; + } - if(conn->bits.authneg) - postsize = 0; - else - /* the size of the post body */ - postsize = data->state.infilesize; +#ifdef HAVE_LIBZ + /* we only consider transfer-encoding magic if libz support is built-in */ - /* We only set Content-Length and allow a custom Content-Length if - we don't upload data chunked, as RFC2616 forbids us to set both - kinds of headers (Transfer-Encoding: chunked and Content-Length) */ - if((postsize != -1) && !data->req.upload_chunky && - (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { - /* we allow replacing this header if not during auth negotiation, - although it isn't very wise to actually set your own */ - result = Curl_dyn_addf(&req, "Content-Length: %" CURL_FORMAT_CURL_OFF_T - "\r\n", postsize); - if(result) - return result; - } + if(!Curl_checkheaders(data, "TE") && + data->set.http_transfer_encoding) { + /* When we are to insert a TE: header in the request, we must also insert + TE in a Connection: header, so we need to merge the custom provided + Connection: header and prevent the original to get sent. Note that if + the user has inserted his/her own TE: header we don't do this magic + but then assume that the user will handle it all! */ + char *cptr = Curl_checkheaders(data, "Connection"); +#define TE_HEADER "TE: gzip\r\n" - if(!Curl_checkheaders(conn, "Content-Type")) { - result = Curl_dyn_add(&req, "Content-Type: application/" - "x-www-form-urlencoded\r\n"); - if(result) - return result; - } + Curl_safefree(data->state.aptr.te); - /* For really small posts we don't use Expect: headers at all, and for - the somewhat bigger ones we allow the app to disable it. Just make - sure that the expect100header is always set to the preferred value - here. */ - ptr = Curl_checkheaders(conn, "Expect"); - if(ptr) { - data->state.expect100header = - Curl_compareheader(ptr, "Expect:", "100-continue"); - } - else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) { - result = expect100(data, conn, &req); - if(result) - return result; + if(cptr) { + cptr = Curl_copy_header_value(cptr); + if(!cptr) + return CURLE_OUT_OF_MEMORY; } - else - data->state.expect100header = FALSE; - if(data->set.postfields) { + /* Create the (updated) Connection: header */ + data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER, + cptr ? cptr : "", (cptr && *cptr) ? ", ":""); - /* In HTTP2, we send request body in DATA frame regardless of - its size. */ - if(conn->httpversion != 20 && - !data->state.expect100header && - (postsize < MAX_INITIAL_POST_SIZE)) { - /* if we don't use expect: 100 AND - postsize is less than MAX_INITIAL_POST_SIZE + free(cptr); + if(!data->state.aptr.te) + return CURLE_OUT_OF_MEMORY; + } +#endif - then append the post data to the HTTP request header. This limit - is no magic limit but only set to prevent really huge POSTs to - get the data duplicated with malloc() and family. */ + result = Curl_http_body(data, conn, httpreq, &te); + if(result) + return result; - /* end of headers! */ - result = Curl_dyn_add(&req, "\r\n"); - if(result) - return result; + p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n"; - if(!data->req.upload_chunky) { - /* We're not sending it 'chunked', append it to the request - already now to reduce the number if send() calls */ - result = Curl_dyn_addn(&req, data->set.postfields, - (size_t)postsize); - included_body = postsize; - } - else { - if(postsize) { - char chunk[16]; - /* Append the POST data chunky-style */ - msnprintf(chunk, sizeof(chunk), "%x\r\n", (int)postsize); - result = Curl_dyn_add(&req, chunk); - if(!result) { - included_body = postsize + strlen(chunk); - result = Curl_dyn_addn(&req, data->set.postfields, - (size_t)postsize); - if(!result) - result = Curl_dyn_add(&req, "\r\n"); - included_body += 2; - } - } - if(!result) { - result = Curl_dyn_add(&req, "\x30\x0d\x0a\x0d\x0a"); - /* 0 CR LF CR LF */ - included_body += 5; - } - } - if(result) - return result; - /* Make sure the progress information is accurate */ - Curl_pgrsSetUploadSize(data, postsize); - } - else { - /* A huge POST coming up, do data separate from the request */ - http->postsize = postsize; - http->postdata = data->set.postfields; + result = Curl_http_resume(data, conn, httpreq); + if(result) + return result; - http->sending = HTTPSEND_BODY; + result = Curl_http_range(data, httpreq); + if(result) + return result; - data->state.fread_func = (curl_read_callback)readmoredata; - data->state.in = (void *)conn; + httpstring = get_http_string(data, conn); - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, http->postsize); + /* initialize a dynamic send-buffer */ + Curl_dyn_init(&req, DYN_HTTP_REQUEST); - /* end of headers! */ - result = Curl_dyn_add(&req, "\r\n"); - if(result) - return result; - } - } - else { - /* end of headers! */ - result = Curl_dyn_add(&req, "\r\n"); - if(result) - return result; + /* add the main request stuff */ + /* GET/HEAD/POST/PUT */ + result = Curl_dyn_addf(&req, "%s ", request); + if(!result) + result = Curl_http_target(data, conn, &req); + if(result) { + Curl_dyn_free(&req); + return result; + } - if(data->req.upload_chunky && conn->bits.authneg) { - /* Chunky upload is selected and we're negotiating auth still, send - end-of-data only */ - result = Curl_dyn_add(&req, (char *)"\x30\x0d\x0a\x0d\x0a"); - /* 0 CR LF CR LF */ - if(result) - return result; - } +#ifndef CURL_DISABLE_ALTSVC + if(conn->bits.altused && !Curl_checkheaders(data, "Alt-Used")) { + altused = aprintf("Alt-Used: %s:%d\r\n", + conn->conn_to_host.name, conn->conn_to_port); + if(!altused) { + Curl_dyn_free(&req); + return CURLE_OUT_OF_MEMORY; + } + } +#endif + result = + Curl_dyn_addf(&req, + " HTTP/%s\r\n" /* HTTP version */ + "%s" /* host */ + "%s" /* proxyuserpwd */ + "%s" /* userpwd */ + "%s" /* range */ + "%s" /* user agent */ + "%s" /* accept */ + "%s" /* TE: */ + "%s" /* accept-encoding */ + "%s" /* referer */ + "%s" /* Proxy-Connection */ + "%s" /* transfer-encoding */ + "%s",/* Alt-Used */ - else if(data->state.infilesize) { - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, postsize?postsize:-1); + httpstring, + (data->state.aptr.host?data->state.aptr.host:""), + data->state.aptr.proxyuserpwd? + data->state.aptr.proxyuserpwd:"", + data->state.aptr.userpwd?data->state.aptr.userpwd:"", + (data->state.use_range && data->state.aptr.rangeline)? + data->state.aptr.rangeline:"", + (data->set.str[STRING_USERAGENT] && + *data->set.str[STRING_USERAGENT] && + data->state.aptr.uagent)? + data->state.aptr.uagent:"", + p_accept?p_accept:"", + data->state.aptr.te?data->state.aptr.te:"", + (data->set.str[STRING_ENCODING] && + *data->set.str[STRING_ENCODING] && + data->state.aptr.accept_encoding)? + data->state.aptr.accept_encoding:"", + (data->change.referer && data->state.aptr.ref)? + data->state.aptr.ref:"" /* Referer: */, +#ifndef CURL_DISABLE_PROXY + (conn->bits.httpproxy && + !conn->bits.tunnel_proxy && + !Curl_checkheaders(data, "Proxy-Connection") && + !Curl_checkProxyheaders(data, conn, "Proxy-Connection"))? + "Proxy-Connection: Keep-Alive\r\n":"", +#else + "", +#endif + te, + altused ? altused : "" + ); - /* set the pointer to mark that we will send the post body using the - read callback, but only if we're not in authenticate - negotiation */ - if(!conn->bits.authneg) { - http->postdata = (char *)&http->postdata; - http->postsize = postsize; - } - } - } - /* issue the request */ - result = Curl_buffer_send(&req, conn, &data->info.request_size, - (size_t)included_body, FIRSTSOCKET); + /* clear userpwd and proxyuserpwd to avoid re-using old credentials + * from re-used connections */ + Curl_safefree(data->state.aptr.userpwd); + Curl_safefree(data->state.aptr.proxyuserpwd); + free(altused); - if(result) - failf(data, "Failed sending HTTP POST request"); - else - Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, - http->postdata?FIRSTSOCKET:-1); - break; + if(result) { + Curl_dyn_free(&req); + return result; + } - default: - result = Curl_dyn_add(&req, "\r\n"); - if(result) + if(!(conn->handler->flags&PROTOPT_SSL) && + conn->httpversion != 20 && + (data->set.httpversion == CURL_HTTP_VERSION_2)) { + /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done + over SSL */ + result = Curl_http2_request_upgrade(&req, conn); + if(result) { + Curl_dyn_free(&req); return result; + } + } - /* issue the request */ - result = Curl_buffer_send(&req, conn, &data->info.request_size, 0, - FIRSTSOCKET); + result = Curl_http_cookies(data, conn, &req); + if(!result) + result = Curl_add_timecondition(data, &req); + if(!result) + result = Curl_add_custom_headers(data, FALSE, &req); - if(result) - failf(data, "Failed sending HTTP request"); - else - /* HTTP GET/HEAD download: */ - Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); + if(!result) { + http->postdata = NULL; /* nothing to post at this point */ + if((httpreq == HTTPREQ_GET) || + (httpreq == HTTPREQ_HEAD)) + Curl_pgrsSetUploadSize(data, 0); /* nothing */ + + /* bodysend takes ownership of the 'req' memory on success */ + result = Curl_http_bodysend(data, conn, &req, httpreq); } - if(result) + if(result) { + Curl_dyn_free(&req); return result; - if(!postsize && (http->sending != HTTPSEND_REQUEST)) + } + + if((http->postsize > -1) && + (http->postsize <= data->req.writebytecount) && + (http->sending != HTTPSEND_REQUEST)) data->req.upload_done = TRUE; if(data->req.writebytecount) { /* if a request-body has been sent off, we make sure this progress is noted properly */ Curl_pgrsSetUploadCounter(data, data->req.writebytecount); - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; - if(data->req.writebytecount >= postsize) { + if(!http->postsize) { /* already sent the entire request body, mark the "upload" as complete */ infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n", - data->req.writebytecount, postsize); + data->req.writebytecount, http->postsize); data->req.upload_done = TRUE; data->req.keepon &= ~KEEP_SEND; /* we're done writing */ data->req.exp100 = EXP100_SEND_DATA; /* already sent */ @@ -3000,6 +3215,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } +#endif /* USE_HYPER */ + typedef enum { STATUS_UNKNOWN, /* not enough data to tell yet */ STATUS_DONE, /* a status line was read */ @@ -3104,41 +3321,383 @@ checkprotoprefix(struct Curl_easy *data, struct connectdata *conn, return checkhttpprefix(data, s, len); } -static void print_http_error(struct Curl_easy *data) +/* + * Curl_http_header() parses a single response header. + */ +CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, + char *headp) { + CURLcode result; struct SingleRequest *k = &data->req; - char *beg = Curl_dyn_ptr(&data->state.headerb); - - /* make sure that data->req.p points to the HTTP status line */ - if(!strncmp(beg, "HTTP", 4)) { - - /* skip to HTTP status code */ - beg = strchr(beg, ' '); - if(beg && *++beg) { - - /* find trailing CR */ - char end_char = '\r'; - char *end = strchr(beg, end_char); - if(!end) { - /* try to find LF (workaround for non-compliant HTTP servers) */ - end_char = '\n'; - end = strchr(beg, end_char); + /* Check for Content-Length: header lines to get size */ + if(!k->http_bodyless && + !data->set.ignorecl && checkprefix("Content-Length:", headp)) { + curl_off_t contentlength; + CURLofft offt = curlx_strtoofft(headp + 15, 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 */ + if(data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + streamclose(conn, "overflow content-length"); + infof(data, "Overflow Content-Length: value!\n"); + } + else { + /* negative or just rubbish - bad HTTP */ + failf(data, "Invalid Content-Length: value"); + return CURLE_WEIRD_SERVER_REPLY; + } + } + /* check for Content-Type: header lines to get the MIME-type */ + else if(checkprefix("Content-Type:", headp)) { + char *contenttype = Curl_copy_header_value(headp); + if(!contenttype) + return CURLE_OUT_OF_MEMORY; + if(!*contenttype) + /* ignore empty data */ + free(contenttype); + else { + Curl_safefree(data->info.contenttype); + data->info.contenttype = contenttype; + } + } +#ifndef CURL_DISABLE_PROXY + else if((conn->httpversion == 10) && + conn->bits.httpproxy && + Curl_compareheader(headp, "Proxy-Connection:", "keep-alive")) { + /* + * When a HTTP/1.0 reply comes when using a proxy, the + * 'Proxy-Connection: keep-alive' line tells us the + * connection will be kept alive for our pleasure. + * Default action for 1.0 is to close. + */ + connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */ + infof(data, "HTTP/1.0 proxy connection set to keep alive!\n"); + } + else if((conn->httpversion == 11) && + conn->bits.httpproxy && + Curl_compareheader(headp, "Proxy-Connection:", "close")) { + /* + * We get a HTTP/1.1 response from a proxy and it says it'll + * close down after this transfer. + */ + connclose(conn, "Proxy-Connection: asked to close after done"); + infof(data, "HTTP/1.1 proxy connection set close!\n"); + } +#endif + else if((conn->httpversion == 10) && + Curl_compareheader(headp, "Connection:", "keep-alive")) { + /* + * A HTTP/1.0 reply with the 'Connection: keep-alive' line + * tells us the connection will be kept alive for our + * pleasure. Default action for 1.0 is to close. + * + * [RFC2068, section 19.7.1] */ + connkeep(conn, "Connection keep-alive"); + infof(data, "HTTP/1.0 connection set to keep alive!\n"); + } + else if(Curl_compareheader(headp, "Connection:", "close")) { + /* + * [RFC 2616, section 8.1.2.1] + * "Connection: close" is HTTP/1.1 language and means that + * the connection will close when this request has been + * served. + */ + streamclose(conn, "Connection: close used"); + } + else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) { + /* One or more encodings. We check for chunked and/or a compression + algorithm. */ + /* + * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding + * means that the server will send a series of "chunks". Each + * chunk starts with line with info (including size of the + * coming block) (terminated with CRLF), then a block of data + * with the previously mentioned size. There can be any amount + * of chunks, and a chunk-data set to zero signals the + * end-of-chunks. */ + + result = Curl_build_unencoding_stack(data, headp + 18, TRUE); + if(result) + return result; + } + else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) && + data->set.str[STRING_ENCODING]) { + /* + * Process Content-Encoding. Look for the values: identity, + * gzip, deflate, compress, x-gzip and x-compress. x-gzip and + * x-compress are the same as gzip and compress. (Sec 3.5 RFC + * 2616). zlib cannot handle compress. However, errors are + * handled further down when the response body is processed + */ + result = Curl_build_unencoding_stack(data, headp + 17, FALSE); + if(result) + return result; + } + else if(checkprefix("Retry-After:", headp)) { + /* Retry-After = HTTP-date / delay-seconds */ + curl_off_t retry_after = 0; /* zero for unknown or "now" */ + time_t date = Curl_getdate_capped(&headp[12]); + if(-1 == date) { + /* not a date, try it as a decimal number */ + (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after); + } + else + /* convert date to number of seconds into the future */ + retry_after = date - time(NULL); + data->info.retry_after = retry_after; /* store it */ + } + else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) { + /* Content-Range: bytes [num]- + Content-Range: bytes: [num]- + Content-Range: [num]- + Content-Range: [asterisk]/[total] + + The second format was added since Sun's webserver + JavaWebServer/1.1.1 obviously sends the header this way! + The third added since some servers use that! + The forth means the requested range was unsatisfied. + */ + + char *ptr = headp + 14; + + /* Move forward until first digit or asterisk */ + while(*ptr && !ISDIGIT(*ptr) && *ptr != '*') + ptr++; + + /* if it truly stopped on a digit */ + if(ISDIGIT(*ptr)) { + if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) { + if(data->state.resume_from == k->offset) + /* we asked for a resume and we got it */ + k->content_range = TRUE; } + } + else + data->state.resume_from = 0; /* get everything */ + } +#if !defined(CURL_DISABLE_COOKIES) + else if(data->cookies && data->state.cookie_engine && + checkprefix("Set-Cookie:", headp)) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, + CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_add(data, + data->cookies, TRUE, FALSE, headp + 11, + /* 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_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } +#endif + else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) && + (data->set.timecondition || data->set.get_filetime) ) { + k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:")); + if(data->set.get_filetime) + data->info.filetime = k->timeofdoc; + } + else if((checkprefix("WWW-Authenticate:", headp) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", headp) && + (407 == k->httpcode))) { + + bool proxy = (k->httpcode == 407) ? TRUE : FALSE; + char *auth = Curl_copy_header_value(headp); + if(!auth) + return CURLE_OUT_OF_MEMORY; + + result = Curl_http_input_auth(data, proxy, auth); + + free(auth); + + if(result) + return result; + } +#ifdef USE_SPNEGO + else if(checkprefix("Persistent-Auth", headp)) { + struct negotiatedata *negdata = &conn->negotiate; + struct auth *authp = &data->state.authhost; + if(authp->picked == CURLAUTH_NEGOTIATE) { + char *persistentauth = Curl_copy_header_value(headp); + if(!persistentauth) + return CURLE_OUT_OF_MEMORY; + negdata->noauthpersist = checkprefix("false", persistentauth)? + TRUE:FALSE; + negdata->havenoauthpersist = TRUE; + infof(data, "Negotiate: noauthpersist -> %d, header part: %s", + negdata->noauthpersist, persistentauth); + free(persistentauth); + } + } +#endif + else if((k->httpcode >= 300 && k->httpcode < 400) && + checkprefix("Location:", headp) && + !data->req.location) { + /* this is the URL that the server advises us to use instead */ + char *location = Curl_copy_header_value(headp); + if(!location) + return CURLE_OUT_OF_MEMORY; + if(!*location) + /* ignore empty data */ + free(location); + else { + data->req.location = location; - if(end) { - /* temporarily replace CR or LF by NUL and print the error message */ - *end = '\0'; - failf(data, "The requested URL returned error: %s", beg); + if(data->set.http_follow_location) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->req.location); /* clone */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; - /* restore the previously replaced CR or LF */ - *end = end_char; - return; + /* some cases of POST and PUT etc needs to rewind the data + stream at this point */ + result = http_perhapsrewind(data, conn); + if(result) + return result; } } } - /* fall-back to printing the HTTP status code only */ - failf(data, "The requested URL returned error: %d", k->httpcode); +#ifdef USE_HSTS + /* If enabled, the header is incoming and this is over HTTPS */ + else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) && + (conn->handler->flags & PROTOPT_SSL)) { + CURLcode check = + Curl_hsts_parse(data->hsts, data->state.up.hostname, + &headp[ sizeof("Strict-Transport-Security:") -1 ]); + if(check) + infof(data, "Illegal STS header skipped\n"); +#ifdef DEBUGBUILD + else + infof(data, "Parsed STS header fine (%zu entries)\n", + data->hsts->list.size); +#endif + } +#endif +#ifndef CURL_DISABLE_ALTSVC + /* If enabled, the header is incoming and this is over HTTPS */ + else if(data->asi && checkprefix("Alt-Svc:", headp) && + ((conn->handler->flags & PROTOPT_SSL) || +#ifdef CURLDEBUG + /* allow debug builds to circumvent the HTTPS restriction */ + getenv("CURL_ALTSVC_HTTP") +#else + 0 +#endif + )) { + /* the ALPN of the current request */ + enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1; + result = Curl_altsvc_parse(data, data->asi, + &headp[ strlen("Alt-Svc:") ], + id, conn->host.name, + curlx_uitous(conn->remote_port)); + if(result) + return result; + } +#endif + else if(conn->handler->protocol & CURLPROTO_RTSP) { + result = Curl_rtsp_parseheader(data, headp); + if(result) + return result; + } + return CURLE_OK; +} + +/* + * Called after the first HTTP response line (the status line) has been + * received and parsed. + */ + +CURLcode Curl_http_statusline(struct Curl_easy *data, + struct connectdata *conn) +{ + struct SingleRequest *k = &data->req; + data->info.httpcode = k->httpcode; + + data->info.httpversion = conn->httpversion; + if(!data->state.httpversion || + data->state.httpversion > conn->httpversion) + /* store the lowest server version we encounter */ + data->state.httpversion = conn->httpversion; + + /* + * This code executes as part of processing the header. As a + * result, it's not totally clear how to interpret the + * response code yet as that depends on what other headers may + * be present. 401 and 407 may be errors, but may be OK + * depending on how authentication is working. Other codes + * are definitely errors, so give up here. + */ + if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET && + k->httpcode == 416) { + /* "Requested Range Not Satisfiable", just proceed and + pretend this is no error */ + k->ignorebody = TRUE; /* Avoid appending error msg to good data. */ + } + + if(conn->httpversion == 10) { + /* Default action for HTTP/1.0 must be to close, unless + we get one of those fancy headers that tell us the + server keeps it open for us! */ + infof(data, "HTTP 1.0, assume close after body\n"); + connclose(conn, "HTTP/1.0 close after body"); + } + else if(conn->httpversion == 20 || + (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) { + DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n")); + /* HTTP/2 cannot avoid multiplexing since it is a core functionality + of the protocol */ + conn->bundle->multiuse = BUNDLE_MULTIPLEX; + } + else if(conn->httpversion >= 11 && + !conn->bits.close) { + /* If HTTP version is >= 1.1 and connection is persistent */ + DEBUGF(infof(data, + "HTTP 1.1 or later with persistent connection\n")); + } + + k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200; + switch(k->httpcode) { + case 304: + /* (quote from RFC2616, section 10.3.5): The 304 response + * MUST NOT contain a message-body, and thus is always + * terminated by the first empty line after the header + * fields. */ + if(data->set.timecondition) + data->info.timecond = TRUE; + /* FALLTHROUGH */ + case 204: + /* (quote from RFC2616, section 10.2.5): The server has + * fulfilled the request but does not need to return an + * entity-body ... The 204 response MUST NOT include a + * message-body, and thus is always terminated by the first + * empty line after the header fields. */ + k->size = 0; + k->maxdownload = 0; + k->http_bodyless = TRUE; + break; + default: + break; + } + return CURLE_OK; } /* @@ -3189,7 +3748,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, k->badheader = HEADER_ALLBAD; streamclose(conn, "bad HTTP: No end-of-message indicator"); if(!data->set.http09_allowed) { - failf(data, "Received HTTP/0.9 when not allowed\n"); + failf(data, "Received HTTP/0.9 when not allowed"); return CURLE_UNSUPPORTED_PROTOCOL; } break; @@ -3224,7 +3783,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, streamclose(conn, "bad HTTP: No end-of-message indicator"); /* this is not the beginning of a protocol first header line */ if(!data->set.http09_allowed) { - failf(data, "Received HTTP/0.9 when not allowed\n"); + failf(data, "Received HTTP/0.9 when not allowed"); return CURLE_UNSUPPORTED_PROTOCOL; } k->header = FALSE; @@ -3299,7 +3858,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, /* switch to http2 now. The bytes after response headers are also processed here, otherwise they are lost. */ - result = Curl_http2_switched(conn, k->str, *nread); + result = Curl_http2_switched(data, k->str, *nread); if(result) return result; *nread = 0; @@ -3365,15 +3924,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, conn->proxy_negotiate_state = GSS_AUTHSUCC; } #endif - /* - * When all the headers have been parsed, see if we should give - * up and return an error. - */ - if(http_should_fail(conn)) { - failf(data, "The requested URL returned error: %d", - k->httpcode); - return CURLE_HTTP_RETURNED_ERROR; - } /* now, only output this if the header AND body are requested: */ @@ -3382,7 +3932,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, writetype |= CLIENTWRITE_BODY; headerlen = Curl_dyn_len(&data->state.headerb); - result = Curl_client_write(conn, writetype, + result = Curl_client_write(data, writetype, Curl_dyn_ptr(&data->state.headerb), headerlen); if(result) @@ -3391,13 +3941,23 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, data->info.header_size += (long)headerlen; data->req.headerbytecount += (long)headerlen; + /* + * When all the headers have been parsed, see if we should give + * up and return an error. + */ + if(http_should_fail(data)) { + failf(data, "The requested URL returned error: %d", + k->httpcode); + return CURLE_HTTP_RETURNED_ERROR; + } + data->req.deductheadercount = (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0; /* Curl_http_auth_act() checks what authentication methods * that are available and decides which one (if any) to * use. It will set 'newurl' if an auth method was picked. */ - result = Curl_http_auth_act(conn); + result = Curl_http_auth_act(data); if(result) return result; @@ -3435,8 +3995,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, infof(data, "Got 417 while waiting for a 100\n"); data->state.disableexpect = TRUE; DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(conn->data->change.url); - Curl_done_sending(conn, k); + data->req.newurl = strdup(data->change.url); + Curl_done_sending(data, k); } else if(data->set.http_keep_sending_on_error) { infof(data, "HTTP error before end of send, keep sending\n"); @@ -3448,7 +4008,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, else { infof(data, "HTTP error before end of send, stop sending\n"); streamclose(conn, "Stop sending data before everything sent"); - result = Curl_done_sending(conn, k); + result = Curl_done_sending(data, k); if(result) return result; k->upload_done = TRUE; @@ -3656,83 +4216,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, } if(nc) { - data->info.httpcode = k->httpcode; - - data->info.httpversion = conn->httpversion; - if(!data->state.httpversion || - data->state.httpversion > conn->httpversion) - /* store the lowest server version we encounter */ - data->state.httpversion = conn->httpversion; - - /* - * This code executes as part of processing the header. As a - * result, it's not totally clear how to interpret the - * response code yet as that depends on what other headers may - * be present. 401 and 407 may be errors, but may be OK - * depending on how authentication is working. Other codes - * are definitely errors, so give up here. - */ - if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET && - k->httpcode == 416) { - /* "Requested Range Not Satisfiable", just proceed and - pretend this is no error */ - k->ignorebody = TRUE; /* Avoid appending error msg to good data. */ - } - else if(data->set.http_fail_on_error && (k->httpcode >= 400) && - ((k->httpcode != 401) || !conn->bits.user_passwd) -#ifndef CURL_DISABLE_PROXY - && ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) -#endif - ) { - /* serious error, go home! */ - print_http_error(data); - return CURLE_HTTP_RETURNED_ERROR; - } - - if(conn->httpversion == 10) { - /* Default action for HTTP/1.0 must be to close, unless - we get one of those fancy headers that tell us the - server keeps it open for us! */ - infof(data, "HTTP 1.0, assume close after body\n"); - connclose(conn, "HTTP/1.0 close after body"); - } - else if(conn->httpversion == 20 || - (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) { - DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n")); - /* HTTP/2 cannot avoid multiplexing since it is a core functionality - of the protocol */ - conn->bundle->multiuse = BUNDLE_MULTIPLEX; - } - else if(conn->httpversion >= 11 && - !conn->bits.close) { - /* If HTTP version is >= 1.1 and connection is persistent */ - DEBUGF(infof(data, - "HTTP 1.1 or later with persistent connection\n")); - } - - k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200; - switch(k->httpcode) { - case 304: - /* (quote from RFC2616, section 10.3.5): The 304 response - * MUST NOT contain a message-body, and thus is always - * terminated by the first empty line after the header - * fields. */ - if(data->set.timecondition) - data->info.timecond = TRUE; - /* FALLTHROUGH */ - case 204: - /* (quote from RFC2616, section 10.2.5): The server has - * fulfilled the request but does not need to return an - * entity-body ... The 204 response MUST NOT include a - * message-body, and thus is always terminated by the first - * empty line after the header fields. */ - k->size = 0; - k->maxdownload = 0; - k->http_bodyless = TRUE; - break; - default: - break; - } + result = Curl_http_statusline(data, conn); + if(result) + return result; } else { k->header = FALSE; /* this is not a header line */ @@ -3745,295 +4231,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if(result) return result; - /* Check for Content-Length: header lines to get size */ - if(!k->http_bodyless && - !data->set.ignorecl && checkprefix("Content-Length:", headp)) { - curl_off_t contentlength; - CURLofft offt = curlx_strtoofft(headp + 15, 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 */ - if(data->set.max_filesize) { - failf(data, "Maximum file size exceeded"); - return CURLE_FILESIZE_EXCEEDED; - } - streamclose(conn, "overflow content-length"); - infof(data, "Overflow Content-Length: value!\n"); - } - else { - /* negative or just rubbish - bad HTTP */ - failf(data, "Invalid Content-Length: value"); - return CURLE_WEIRD_SERVER_REPLY; - } - } - /* check for Content-Type: header lines to get the MIME-type */ - else if(checkprefix("Content-Type:", headp)) { - char *contenttype = Curl_copy_header_value(headp); - if(!contenttype) - return CURLE_OUT_OF_MEMORY; - if(!*contenttype) - /* ignore empty data */ - free(contenttype); - else { - Curl_safefree(data->info.contenttype); - data->info.contenttype = contenttype; - } - } -#ifndef CURL_DISABLE_PROXY - else if((conn->httpversion == 10) && - conn->bits.httpproxy && - Curl_compareheader(headp, "Proxy-Connection:", "keep-alive")) { - /* - * When a HTTP/1.0 reply comes when using a proxy, the - * 'Proxy-Connection: keep-alive' line tells us the - * connection will be kept alive for our pleasure. - * Default action for 1.0 is to close. - */ - connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */ - infof(data, "HTTP/1.0 proxy connection set to keep alive!\n"); - } - else if((conn->httpversion == 11) && - conn->bits.httpproxy && - Curl_compareheader(headp, "Proxy-Connection:", "close")) { - /* - * We get a HTTP/1.1 response from a proxy and it says it'll - * close down after this transfer. - */ - connclose(conn, "Proxy-Connection: asked to close after done"); - infof(data, "HTTP/1.1 proxy connection set close!\n"); - } -#endif - else if((conn->httpversion == 10) && - Curl_compareheader(headp, "Connection:", "keep-alive")) { - /* - * A HTTP/1.0 reply with the 'Connection: keep-alive' line - * tells us the connection will be kept alive for our - * pleasure. Default action for 1.0 is to close. - * - * [RFC2068, section 19.7.1] */ - connkeep(conn, "Connection keep-alive"); - infof(data, "HTTP/1.0 connection set to keep alive!\n"); - } - else if(Curl_compareheader(headp, "Connection:", "close")) { - /* - * [RFC 2616, section 8.1.2.1] - * "Connection: close" is HTTP/1.1 language and means that - * the connection will close when this request has been - * served. - */ - streamclose(conn, "Connection: close used"); - } - else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) { - /* One or more encodings. We check for chunked and/or a compression - algorithm. */ - /* - * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding - * means that the server will send a series of "chunks". Each - * chunk starts with line with info (including size of the - * coming block) (terminated with CRLF), then a block of data - * with the previously mentioned size. There can be any amount - * of chunks, and a chunk-data set to zero signals the - * end-of-chunks. */ - - result = Curl_build_unencoding_stack(conn, headp + 18, TRUE); - if(result) - return result; - } - else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) && - data->set.str[STRING_ENCODING]) { - /* - * Process Content-Encoding. Look for the values: identity, - * gzip, deflate, compress, x-gzip and x-compress. x-gzip and - * x-compress are the same as gzip and compress. (Sec 3.5 RFC - * 2616). zlib cannot handle compress. However, errors are - * handled further down when the response body is processed - */ - result = Curl_build_unencoding_stack(conn, headp + 17, FALSE); - if(result) - return result; - } - else if(checkprefix("Retry-After:", headp)) { - /* Retry-After = HTTP-date / delay-seconds */ - curl_off_t retry_after = 0; /* zero for unknown or "now" */ - time_t date = Curl_getdate_capped(&headp[12]); - if(-1 == date) { - /* not a date, try it as a decimal number */ - (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after); - } - else - /* convert date to number of seconds into the future */ - retry_after = date - time(NULL); - data->info.retry_after = retry_after; /* store it */ - } - else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) { - /* Content-Range: bytes [num]- - Content-Range: bytes: [num]- - Content-Range: [num]- - Content-Range: [asterisk]/[total] - - The second format was added since Sun's webserver - JavaWebServer/1.1.1 obviously sends the header this way! - The third added since some servers use that! - The forth means the requested range was unsatisfied. - */ - - char *ptr = headp + 14; - - /* Move forward until first digit or asterisk */ - while(*ptr && !ISDIGIT(*ptr) && *ptr != '*') - ptr++; - - /* if it truly stopped on a digit */ - if(ISDIGIT(*ptr)) { - if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) { - if(data->state.resume_from == k->offset) - /* we asked for a resume and we got it */ - k->content_range = TRUE; - } - } - else - data->state.resume_from = 0; /* get everything */ - } -#if !defined(CURL_DISABLE_COOKIES) - else if(data->cookies && data->state.cookie_engine && - checkprefix("Set-Cookie:", headp)) { - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, - CURL_LOCK_ACCESS_SINGLE); - Curl_cookie_add(data, - data->cookies, TRUE, FALSE, headp + 11, - /* 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_share_unlock(data, CURL_LOCK_DATA_COOKIE); - } -#endif - else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) && - (data->set.timecondition || data->set.get_filetime) ) { - k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:")); - if(data->set.get_filetime) - data->info.filetime = k->timeofdoc; - } - else if((checkprefix("WWW-Authenticate:", headp) && - (401 == k->httpcode)) || - (checkprefix("Proxy-authenticate:", headp) && - (407 == k->httpcode))) { - - bool proxy = (k->httpcode == 407) ? TRUE : FALSE; - char *auth = Curl_copy_header_value(headp); - if(!auth) - return CURLE_OUT_OF_MEMORY; - - result = Curl_http_input_auth(conn, proxy, auth); - - free(auth); - - if(result) - return result; - } -#ifdef USE_SPNEGO - else if(checkprefix("Persistent-Auth", headp)) { - struct negotiatedata *negdata = &conn->negotiate; - struct auth *authp = &data->state.authhost; - if(authp->picked == CURLAUTH_NEGOTIATE) { - char *persistentauth = Curl_copy_header_value(headp); - if(!persistentauth) - return CURLE_OUT_OF_MEMORY; - negdata->noauthpersist = checkprefix("false", persistentauth)? - TRUE:FALSE; - negdata->havenoauthpersist = TRUE; - infof(data, "Negotiate: noauthpersist -> %d, header part: %s", - negdata->noauthpersist, persistentauth); - free(persistentauth); - } - } -#endif - else if((k->httpcode >= 300 && k->httpcode < 400) && - checkprefix("Location:", headp) && - !data->req.location) { - /* this is the URL that the server advises us to use instead */ - char *location = Curl_copy_header_value(headp); - if(!location) - return CURLE_OUT_OF_MEMORY; - if(!*location) - /* ignore empty data */ - free(location); - else { - data->req.location = location; - - if(data->set.http_follow_location) { - DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->req.location); /* clone */ - if(!data->req.newurl) - return CURLE_OUT_OF_MEMORY; - - /* some cases of POST and PUT etc needs to rewind the data - stream at this point */ - result = http_perhapsrewind(conn); - if(result) - return result; - } - } - } - -#ifdef USE_HSTS - /* If enabled, the header is incoming and this is over HTTPS */ - else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) && - (conn->handler->flags & PROTOPT_SSL)) { - CURLcode check = - Curl_hsts_parse(data->hsts, data->state.up.hostname, - &headp[ sizeof("Strict-Transport-Security:") -1 ]); - if(check) - infof(data, "Illegal STS header skipped\n"); -#ifdef DEBUGBUILD - else - infof(data, "Parsed STS header fine (%zu entries)\n", - data->hsts->list.size); -#endif - } -#endif -#ifndef CURL_DISABLE_ALTSVC - /* If enabled, the header is incoming and this is over HTTPS */ - else if(data->asi && checkprefix("Alt-Svc:", headp) && - ((conn->handler->flags & PROTOPT_SSL) || -#ifdef CURLDEBUG - /* allow debug builds to circumvent the HTTPS restriction */ - getenv("CURL_ALTSVC_HTTP") -#else - 0 -#endif - )) { - /* the ALPN of the current request */ - enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1; - result = Curl_altsvc_parse(data, data->asi, - &headp[ strlen("Alt-Svc:") ], - id, conn->host.name, - curlx_uitous(conn->remote_port)); - if(result) - return result; - } -#endif - else if(conn->handler->protocol & CURLPROTO_RTSP) { - result = Curl_rtsp_parseheader(conn, headp); - if(result) - return result; - } + result = Curl_http_header(data, conn, headp); + if(result) + return result; /* * End of header-checks. Write them to the client. @@ -4046,7 +4246,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, Curl_debug(data, CURLINFO_HEADER_IN, headp, Curl_dyn_len(&data->state.headerb)); - result = Curl_client_write(conn, writetype, headp, + result = Curl_client_write(data, writetype, headp, Curl_dyn_len(&data->state.headerb)); if(result) return result; diff --git a/libs/libcurl/src/http.h b/libs/libcurl/src/http.h index 1aaec225e2..28f9341f67 100644 --- a/libs/libcurl/src/http.h +++ b/libs/libcurl/src/http.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,6 +23,15 @@ ***************************************************************************/ #include "curl_setup.h" +typedef enum { + HTTPREQ_GET, + HTTPREQ_POST, + HTTPREQ_POST_FORM, /* we make a difference internally */ + HTTPREQ_POST_MIME, /* we make a difference internally */ + HTTPREQ_PUT, + HTTPREQ_HEAD +} Curl_HttpReq; + #ifndef CURL_DISABLE_HTTP #ifdef USE_NGHTTP2 @@ -42,32 +51,78 @@ bool Curl_compareheader(const char *headerline, /* line to check */ char *Curl_copy_header_value(const char *header); -char *Curl_checkProxyheaders(const struct connectdata *conn, +char *Curl_checkProxyheaders(struct Curl_easy *data, + const struct connectdata *conn, const char *thisheader); +#ifndef USE_HYPER CURLcode Curl_buffer_send(struct dynbuf *in, - struct connectdata *conn, + struct Curl_easy *data, curl_off_t *bytes_written, size_t included_body_bytes, int socketindex); +#else +#define Curl_buffer_send(a,b,c,d,e) CURLE_OK +#endif -CURLcode Curl_add_timecondition(const struct connectdata *conn, - struct dynbuf *buf); -CURLcode Curl_add_custom_headers(struct connectdata *conn, +CURLcode Curl_add_timecondition(struct Curl_easy *data, +#ifndef USE_HYPER + struct dynbuf *req +#else + void *headers +#endif + ); +CURLcode Curl_add_custom_headers(struct Curl_easy *data, bool is_connect, - struct dynbuf *req_buffer); +#ifndef USE_HYPER + struct dynbuf *req +#else + void *headers +#endif + ); CURLcode Curl_http_compile_trailers(struct curl_slist *trailers, struct dynbuf *buf, struct Curl_easy *handle); +void Curl_http_method(struct Curl_easy *data, struct connectdata *conn, + const char **method, Curl_HttpReq *); +CURLcode Curl_http_useragent(struct Curl_easy *data); +CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn); +CURLcode Curl_http_target(struct Curl_easy *data, struct connectdata *conn, + struct dynbuf *req); +CURLcode Curl_http_statusline(struct Curl_easy *data, + struct connectdata *conn); +CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, + char *headp); +CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, + Curl_HttpReq httpreq, + const char **teep); +CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, + struct dynbuf *r, Curl_HttpReq httpreq); +#ifndef CURL_DISABLE_COOKIES +CURLcode Curl_http_cookies(struct Curl_easy *data, + struct connectdata *conn, + struct dynbuf *r); +#else +#define Curl_http_cookies(a,b,c) CURLE_OK +#endif +CURLcode Curl_http_resume(struct Curl_easy *data, + struct connectdata *conn, + Curl_HttpReq httpreq); +CURLcode Curl_http_range(struct Curl_easy *data, + Curl_HttpReq httpreq); +CURLcode Curl_http_firstwrite(struct Curl_easy *data, + struct connectdata *conn, + bool *done); + /* protocol-specific functions set up to be called by the main engine */ -CURLcode Curl_http(struct connectdata *conn, bool *done); -CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); -CURLcode Curl_http_connect(struct connectdata *conn, bool *done); +CURLcode Curl_http(struct Curl_easy *data, bool *done); +CURLcode Curl_http_done(struct Curl_easy *data, CURLcode, bool premature); +CURLcode Curl_http_connect(struct Curl_easy *data, bool *done); /* These functions are in http.c */ -CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, +CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, const char *auth); -CURLcode Curl_http_auth_act(struct connectdata *conn); +CURLcode Curl_http_auth_act(struct Curl_easy *data); /* If only the PICKNONE bit is set, there has been a round-trip and we selected to use no auth at all. Ie, we actively select no auth, as opposed @@ -115,7 +170,6 @@ struct HTTP { const char *postdata; const char *p_pragma; /* Pragma: string */ - const char *p_accept; /* Accept: string */ /* For FORM posting */ curl_mimepart form; @@ -234,11 +288,13 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, /** * Curl_http_output_auth() setups the authentication headers for the * host/proxy and the correct authentication - * method. conn->data->state.authdone is set to TRUE when authentication is + * method. data->state.authdone is set to TRUE when authentication is * done. * + * @param data all information about the current transfer * @param conn all information about the current connection * @param request pointer to the request keyword + * @param httpreq is the request type * @param path pointer to the requested path * @param proxytunnel boolean if this is the request setting up a "proxy * tunnel" @@ -246,8 +302,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * @returns CURLcode */ CURLcode -Curl_http_output_auth(struct connectdata *conn, +Curl_http_output_auth(struct Curl_easy *data, + struct connectdata *conn, const char *request, + Curl_HttpReq httpreq, const char *path, bool proxytunnel); /* TRUE if this is the request setting up the proxy tunnel */ diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c index b138fb4b0f..be4c712420 100644 --- a/libs/libcurl/src/http2.c +++ b/libs/libcurl/src/http2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -65,12 +65,13 @@ #endif -static ssize_t http2_recv(struct connectdata *conn, int sockindex, +static ssize_t http2_recv(struct Curl_easy *data, int sockindex, char *mem, size_t len, CURLcode *err); -static bool http2_connisdead(struct connectdata *conn); +static bool http2_connisdead(struct Curl_easy *data, + struct connectdata *conn); static int h2_session_send(struct Curl_easy *data, nghttp2_session *h2); -static int h2_process_pending_input(struct connectdata *conn, +static int h2_process_pending_input(struct Curl_easy *data, struct http_conn *httpc, CURLcode *err); @@ -92,18 +93,20 @@ void Curl_http2_init_userset(struct UserDefined *set) set->stream_weight = NGHTTP2_DEFAULT_WEIGHT; } -static int http2_perform_getsock(const struct connectdata *conn, - curl_socket_t *sock) +static int http2_getsock(struct Curl_easy *data, + struct connectdata *conn, + curl_socket_t *sock) { const struct http_conn *c = &conn->proto.httpc; - struct SingleRequest *k = &conn->data->req; + struct SingleRequest *k = &data->req; int bitmap = GETSOCK_BLANK; sock[0] = conn->sock[FIRSTSOCKET]; - /* in a HTTP/2 connection we can basically always get a frame so we should - always be ready for one */ - bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); + if(!(k->keepon & KEEP_RECV_PAUSE)) + /* Unless paused - in a HTTP/2 connection we can basically always get a + 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) || @@ -113,12 +116,6 @@ static int http2_perform_getsock(const struct connectdata *conn, return bitmap; } -static int http2_getsock(struct connectdata *conn, - curl_socket_t *socks) -{ - return http2_perform_getsock(conn, socks); -} - /* * http2_stream_free() free HTTP2 stream related data */ @@ -139,18 +136,22 @@ static void http2_stream_free(struct HTTP *http) * connection cache and not the "main" one. Don't touch the easy handle! */ -static CURLcode http2_disconnect(struct connectdata *conn, +static CURLcode http2_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { struct http_conn *c = &conn->proto.httpc; (void)dead_connection; +#ifndef DEBUG_HTTP2 + (void)data; +#endif - H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n")); + H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now\n")); nghttp2_session_del(c->h2); Curl_safefree(c->inbuf); - H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n")); + H2BUGF(infof(data, "HTTP/2 DISCONNECT done\n")); return CURLE_OK; } @@ -162,7 +163,7 @@ static CURLcode http2_disconnect(struct connectdata *conn, * Instead, if it is readable, run Curl_connalive() to peek at the socket * and distinguish between closed and data. */ -static bool http2_connisdead(struct connectdata *conn) +static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn) { int sval; bool dead = TRUE; @@ -192,14 +193,14 @@ static bool http2_connisdead(struct connectdata *conn) if(httpc->recv_underlying) /* if called "too early", this pointer isn't setup yet! */ nread = ((Curl_recv *)httpc->recv_underlying)( - conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); + data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); if(nread != -1) { - infof(conn->data, + infof(data, "%d bytes stray data read before trying h2 connection\n", (int)nread); httpc->nread_inbuf = 0; httpc->inbuflen = nread; - (void)h2_process_pending_input(conn, httpc, &result); + (void)h2_process_pending_input(data, httpc, &result); } else /* the read failed so let's say this is dead anyway */ @@ -210,24 +211,25 @@ static bool http2_connisdead(struct connectdata *conn) return dead; } -static unsigned int http2_conncheck(struct connectdata *check, +static unsigned int http2_conncheck(struct Curl_easy *data, + struct connectdata *conn, unsigned int checks_to_perform) { unsigned int ret_val = CONNRESULT_NONE; - struct http_conn *c = &check->proto.httpc; + struct http_conn *c = &conn->proto.httpc; int rc; bool send_frames = false; if(checks_to_perform & CONNCHECK_ISDEAD) { - if(http2_connisdead(check)) + if(http2_connisdead(data, conn)) ret_val |= CONNRESULT_DEAD; } if(checks_to_perform & CONNCHECK_KEEPALIVE) { struct curltime now = Curl_now(); - timediff_t elapsed = Curl_timediff(now, check->keepalive); + timediff_t elapsed = Curl_timediff(now, conn->keepalive); - if(elapsed > check->upkeep_interval_ms) { + if(elapsed > data->set.upkeep_interval_ms) { /* Perform an HTTP/2 PING */ rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL); if(!rc) { @@ -236,18 +238,18 @@ static unsigned int http2_conncheck(struct connectdata *check, send_frames = true; } else { - failf(check->data, "nghttp2_submit_ping() failed: %s(%d)", + failf(data, "nghttp2_submit_ping() failed: %s(%d)", nghttp2_strerror(rc), rc); } - check->keepalive = now; + conn->keepalive = now; } } if(send_frames) { rc = nghttp2_session_send(c->h2); if(rc) - failf(check->data, "nghttp2_session_send() failed: %s(%d)", + failf(data, "nghttp2_session_send() failed: %s(%d)", nghttp2_strerror(rc), rc); } @@ -294,7 +296,7 @@ static const struct Curl_handler Curl_handler_http2 = { http2_getsock, /* proto_getsock */ http2_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - http2_perform_getsock, /* perform_getsock */ + http2_getsock, /* perform_getsock */ http2_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ http2_conncheck, /* connection_check */ @@ -316,7 +318,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = { http2_getsock, /* proto_getsock */ http2_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - http2_perform_getsock, /* perform_getsock */ + http2_getsock, /* perform_getsock */ http2_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ http2_conncheck, /* connection_check */ @@ -342,7 +344,7 @@ int Curl_http2_ver(char *p, size_t len) * written. See the documentation of nghttp2_send_callback for the details. */ static ssize_t send_callback(nghttp2_session *h2, - const uint8_t *data, size_t length, int flags, + const uint8_t *mem, size_t length, int flags, void *userp) { struct connectdata *conn = (struct connectdata *)userp; @@ -357,8 +359,8 @@ static ssize_t send_callback(nghttp2_session *h2, /* called before setup properly! */ return NGHTTP2_ERR_CALLBACK_FAILURE; - written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET, - data, length, &result); + written = ((Curl_send*)c->send_underlying)(conn->data, FIRSTSOCKET, + mem, length, &result); if(result == CURLE_AGAIN) { return NGHTTP2_ERR_WOULDBLOCK; @@ -541,7 +543,7 @@ static int push_promise(struct Curl_easy *data, stream = data->req.p.http; if(!stream) { - failf(data, "Internal NULL stream!\n"); + failf(data, "Internal NULL stream!"); (void)Curl_close(&newhandle); rv = CURL_PUSH_DENY; goto fail; @@ -956,7 +958,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, stream = data_s->req.p.http; if(!stream) { - failf(data_s, "Internal NULL stream! 5\n"); + failf(data_s, "Internal NULL stream!"); return NGHTTP2_ERR_CALLBACK_FAILURE; } @@ -1214,7 +1216,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) /* * Initialize nghttp2 for a Curl connection */ -static CURLcode http2_init(struct connectdata *conn) +static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn) { if(!conn->proto.httpc.h2) { int rc; @@ -1227,7 +1229,7 @@ static CURLcode http2_init(struct connectdata *conn) rc = nghttp2_session_callbacks_new(&callbacks); if(rc) { - failf(conn->data, "Couldn't initialize nghttp2 callbacks!"); + failf(data, "Couldn't initialize nghttp2 callbacks!"); return CURLE_OUT_OF_MEMORY; /* most likely at least */ } @@ -1256,7 +1258,7 @@ static CURLcode http2_init(struct connectdata *conn) nghttp2_session_callbacks_del(callbacks); if(rc) { - failf(conn->data, "Couldn't initialize nghttp2!"); + failf(data, "Couldn't initialize nghttp2!"); return CURLE_OUT_OF_MEMORY; /* most likely at least */ } } @@ -1273,7 +1275,8 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req, ssize_t binlen; char *base64; size_t blen; - struct SingleRequest *k = &conn->data->req; + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; uint8_t *binsettings = conn->proto.httpc.binsettings; struct http_conn *httpc = &conn->proto.httpc; @@ -1284,13 +1287,13 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req, httpc->local_settings, httpc->local_settings_num); if(binlen <= 0) { - failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload"); + failf(data, "nghttp2 unexpectedly failed on pack_settings_payload"); Curl_dyn_free(req); return CURLE_FAILED_INIT; } conn->proto.httpc.binlen = binlen; - result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen, + result = Curl_base64url_encode(data, (const char *)binsettings, binlen, &base64, &blen); if(result) { Curl_dyn_free(req); @@ -1324,14 +1327,13 @@ static int should_close_session(struct http_conn *httpc) * This function returns 0 if it succeeds, or -1 and error code will * be assigned to *err. */ -static int h2_process_pending_input(struct connectdata *conn, +static int h2_process_pending_input(struct Curl_easy *data, struct http_conn *httpc, CURLcode *err) { ssize_t nread; char *inbuf; ssize_t rv; - struct Curl_easy *data = conn->data; nread = httpc->inbuflen - httpc->nread_inbuf; inbuf = httpc->inbuf + httpc->nread_inbuf; @@ -1340,7 +1342,7 @@ static int h2_process_pending_input(struct connectdata *conn, if(rv < 0) { failf(data, "h2_process_pending_input: nghttp2_session_mem_recv() returned " - "%zd:%s\n", rv, nghttp2_strerror((int)rv)); + "%zd:%s", rv, nghttp2_strerror((int)rv)); *err = CURLE_RECV_ERROR; return -1; } @@ -1371,7 +1373,7 @@ static int h2_process_pending_input(struct connectdata *conn, the connection may not be reused. This is set when a GOAWAY frame has been received or when the limit of stream identifiers has been reached. */ - connclose(conn, "http/2: No new requests allowed"); + connclose(data->conn, "http/2: No new requests allowed"); } if(should_close_session(httpc)) { @@ -1381,7 +1383,7 @@ static int h2_process_pending_input(struct connectdata *conn, *err = CURLE_HTTP2; else { /* not an error per se, but should still close the connection */ - connclose(conn, "GOAWAY received"); + connclose(data->conn, "GOAWAY received"); *err = CURLE_OK; } return -1; @@ -1392,7 +1394,8 @@ static int h2_process_pending_input(struct connectdata *conn, /* * Called from transfer.c:done_sending when we stop uploading. */ -CURLcode Curl_http2_done_sending(struct connectdata *conn) +CURLcode Curl_http2_done_sending(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; @@ -1400,7 +1403,7 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn) (conn->handler == &Curl_handler_http2)) { /* make sure this is only attempted for HTTP/2 transfers */ - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; struct http_conn *httpc = &conn->proto.httpc; nghttp2_session *h2 = httpc->h2; @@ -1413,13 +1416,11 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn) /* resume sending here to trigger the callback to get called again so that it can signal EOF to nghttp2 */ (void)nghttp2_session_resume_data(h2, stream->stream_id); - - (void)h2_process_pending_input(conn, httpc, &result); + (void)h2_process_pending_input(data, httpc, &result); } /* If nghttp2 still has pending frames unsent */ if(nghttp2_session_want_write(h2)) { - struct Curl_easy *data = conn->data; struct SingleRequest *k = &data->req; int rv; @@ -1450,7 +1451,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, drained_transfer(data, httpc); if(httpc->pause_stream_id == 0) { - if(h2_process_pending_input(conn, httpc, err) != 0) { + if(h2_process_pending_input(data, httpc, err) != 0) { return -1; } } @@ -1498,7 +1499,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, Curl_debug(data, CURLINFO_HEADER_IN, trailp, len); /* pass the trailers one by one to the callback */ - result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailp, len); + result = Curl_client_write(data, CLIENTWRITE_HEADER, trailp, len); if(result) { *err = result; return -1; @@ -1562,12 +1563,12 @@ static int h2_session_send(struct Curl_easy *data, return nghttp2_session_send(h2); } -static ssize_t http2_recv(struct connectdata *conn, int sockindex, +static ssize_t http2_recv(struct Curl_easy *data, int sockindex, char *mem, size_t len, CURLcode *err) { ssize_t nread; + struct connectdata *conn = data->conn; struct http_conn *httpc = &conn->proto.httpc; - struct Curl_easy *data = conn->data; struct HTTP *stream = data->req.p.http; (void)sockindex; /* we always do HTTP2 on sockindex 0 */ @@ -1631,7 +1632,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, /* We have paused nghttp2, but we have no pause data (see on_data_chunk_recv). */ httpc->pause_stream_id = 0; - if(h2_process_pending_input(conn, httpc, err) != 0) { + if(h2_process_pending_input(data, httpc, err) != 0) { return -1; } } @@ -1659,7 +1660,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, frames, then we have to call it again with 0-length data. Without this, on_stream_close callback will not be called, and stream could be hanged. */ - if(h2_process_pending_input(conn, httpc, err) != 0) { + if(h2_process_pending_input(data, httpc, err) != 0) { return -1; } } @@ -1693,7 +1694,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, if(httpc->inbuflen == 0) { nread = ((Curl_recv *)httpc->recv_underlying)( - conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err); + data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err); if(nread == -1) { if(*err != CURLE_AGAIN) @@ -1724,7 +1725,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, nread)); } - if(h2_process_pending_input(conn, httpc, err) != 0) + if(h2_process_pending_input(data, httpc, err) != 0) return -1; } if(stream->memlen) { @@ -1830,7 +1831,7 @@ static header_instruction inspect_header(const char *name, size_t namelen, } } -static ssize_t http2_send(struct connectdata *conn, int sockindex, +static ssize_t http2_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *err) { /* @@ -1839,8 +1840,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, * request. */ int rv; + struct connectdata *conn = data->conn; struct http_conn *httpc = &conn->proto.httpc; - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; nghttp2_nv *nva = NULL; size_t nheader; size_t i; @@ -1854,16 +1856,16 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, (void)sockindex; - H2BUGF(infof(conn->data, "http2_send len=%zu\n", len)); + H2BUGF(infof(data, "http2_send len=%zu\n", len)); if(stream->stream_id != -1) { if(stream->close_handled) { - infof(conn->data, "stream %d closed\n", stream->stream_id); + infof(data, "stream %d closed\n", stream->stream_id); *err = CURLE_HTTP2_STREAM; return -1; } else if(stream->closed) { - return http2_handle_stream_close(conn, conn->data, stream, err); + return http2_handle_stream_close(conn, data, stream, err); } /* If stream_id != -1, we have dispatched request HEADERS, and now are going to send or sending request body in DATA frame */ @@ -1874,7 +1876,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, *err = CURLE_SEND_ERROR; return -1; } - rv = h2_session_send(conn->data, h2); + rv = h2_session_send(data, h2); if(nghttp2_is_fatal(rv)) { *err = CURLE_SEND_ERROR; return -1; @@ -1887,7 +1889,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, stream->upload_len = 0; if(should_close_session(httpc)) { - H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n")); + H2BUGF(infof(data, "http2_send: nothing to do in this session\n")); *err = CURLE_HTTP2; return -1; } @@ -1900,7 +1902,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, nghttp2_session_resume_data(h2, stream->stream_id); } - H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len, + H2BUGF(infof(data, "http2_send returns %zu for stream %u\n", len, stream->stream_id)); return len; } @@ -1944,7 +1946,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, nva[0].valuelen = (size_t)(end - hdbuf); nva[0].flags = NGHTTP2_NV_FLAG_NONE; if(HEADER_OVERFLOW(nva[0])) { - failf(conn->data, "Failed sending HTTP request: Header overflow"); + failf(data, "Failed sending HTTP request: Header overflow"); goto fail; } @@ -1966,7 +1968,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, nva[1].valuelen = (size_t)(end - hdbuf); nva[1].flags = NGHTTP2_NV_FLAG_NONE; if(HEADER_OVERFLOW(nva[1])) { - failf(conn->data, "Failed sending HTTP request: Header overflow"); + failf(data, "Failed sending HTTP request: Header overflow"); goto fail; } @@ -1979,7 +1981,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, nva[2].valuelen = strlen((char *)nva[2].value); nva[2].flags = NGHTTP2_NV_FLAG_NONE; if(HEADER_OVERFLOW(nva[2])) { - failf(conn->data, "Failed sending HTTP request: Header overflow"); + failf(data, "Failed sending HTTP request: Header overflow"); goto fail; } @@ -2039,7 +2041,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, nva[i].flags = NGHTTP2_NV_FLAG_NONE; if(HEADER_OVERFLOW(nva[i])) { - failf(conn->data, "Failed sending HTTP request: Header overflow"); + failf(data, "Failed sending HTTP request: Header overflow"); goto fail; } ++i; @@ -2063,30 +2065,30 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, for(i = 0; i < nheader; ++i) { acc += nva[i].namelen + nva[i].valuelen; - H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n", + H2BUGF(infof(data, "h2 header: %.*s:%.*s\n", nva[i].namelen, nva[i].name, nva[i].valuelen, nva[i].value)); } if(acc > MAX_ACC) { - infof(conn->data, "http2_send: Warning: The cumulative length of all " + infof(data, "http2_send: Warning: The cumulative length of all " "headers exceeds %d bytes and that could cause the " "stream to be rejected.\n", MAX_ACC); } } - h2_pri_spec(conn->data, &pri_spec); + h2_pri_spec(data, &pri_spec); - H2BUGF(infof(conn->data, "http2_send request allowed %d (easy handle %p)\n", - nghttp2_session_check_request_allowed(h2), (void *)conn->data)); + H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)\n", + nghttp2_session_check_request_allowed(h2), (void *)data)); - switch(conn->data->state.httpreq) { + switch(data->state.httpreq) { case HTTPREQ_POST: case HTTPREQ_POST_FORM: case HTTPREQ_POST_MIME: case HTTPREQ_PUT: - if(conn->data->state.infilesize != -1) - stream->upload_left = conn->data->state.infilesize; + if(data->state.infilesize != -1) + stream->upload_left = data->state.infilesize; else /* data sending without specifying the data amount up front */ stream->upload_left = -1; /* unknown, but not zero */ @@ -2094,32 +2096,32 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, data_prd.read_callback = data_source_read_callback; data_prd.source.ptr = NULL; stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader, - &data_prd, conn->data); + &data_prd, data); break; default: stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader, - NULL, conn->data); + NULL, data); } Curl_safefree(nva); if(stream_id < 0) { - H2BUGF(infof(conn->data, + H2BUGF(infof(data, "http2_send() nghttp2_submit_request error (%s)%d\n", nghttp2_strerror(stream_id), stream_id)); *err = CURLE_SEND_ERROR; return -1; } - infof(conn->data, "Using Stream ID: %x (easy handle %p)\n", - stream_id, (void *)conn->data); + infof(data, "Using Stream ID: %x (easy handle %p)\n", + stream_id, (void *)data); stream->stream_id = stream_id; /* this does not call h2_session_send() since there can not have been any * priority update since the nghttp2_submit_request() call above */ rv = nghttp2_session_send(h2); if(rv != 0) { - H2BUGF(infof(conn->data, + H2BUGF(infof(data, "http2_send() nghttp2_session_send error (%s)%d\n", nghttp2_strerror(rv), rv)); @@ -2128,7 +2130,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, } if(should_close_session(httpc)) { - H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n")); + H2BUGF(infof(data, "http2_send: nothing to do in this session\n")); *err = CURLE_HTTP2; return -1; } @@ -2150,13 +2152,14 @@ fail: return -1; } -CURLcode Curl_http2_setup(struct connectdata *conn) +CURLcode Curl_http2_setup(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result; struct http_conn *httpc = &conn->proto.httpc; - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; - DEBUGASSERT(conn->data->state.buffer); + DEBUGASSERT(data->state.buffer); stream->stream_id = -1; @@ -2172,18 +2175,18 @@ CURLcode Curl_http2_setup(struct connectdata *conn) else conn->handler = &Curl_handler_http2; - result = http2_init(conn); + result = http2_init(data, conn); if(result) { Curl_dyn_free(&stream->header_recvbuf); return result; } - infof(conn->data, "Using HTTP2, server supports multi-use\n"); + infof(data, "Using HTTP2, server supports multi-use\n"); stream->upload_left = 0; stream->upload_mem = NULL; stream->upload_len = 0; - stream->mem = conn->data->state.buffer; - stream->len = conn->data->set.buffer_size; + stream->mem = data->state.buffer; + stream->len = data->set.buffer_size; httpc->inbuflen = 0; httpc->nread_inbuf = 0; @@ -2195,22 +2198,22 @@ CURLcode Curl_http2_setup(struct connectdata *conn) conn->httpversion = 20; conn->bundle->multiuse = BUNDLE_MULTIPLEX; - infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n"); - multi_connchanged(conn->data->multi); + infof(data, "Connection state changed (HTTP/2 confirmed)\n"); + multi_connchanged(data->multi); return CURLE_OK; } -CURLcode Curl_http2_switched(struct connectdata *conn, +CURLcode Curl_http2_switched(struct Curl_easy *data, const char *mem, size_t nread) { CURLcode result; + struct connectdata *conn = data->conn; struct http_conn *httpc = &conn->proto.httpc; int rv; - struct Curl_easy *data = conn->data; - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; - result = Curl_http2_setup(conn); + result = Curl_http2_setup(data, conn); if(result) return result; @@ -2219,7 +2222,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn, conn->recv[FIRSTSOCKET] = http2_recv; conn->send[FIRSTSOCKET] = http2_send; - if(conn->data->req.upgr101 == UPGR101_RECEIVED) { + if(data->req.upgr101 == UPGR101_RECEIVED) { /* stream 1 is opened implicitly on upgrade */ stream->stream_id = 1; /* queue SETTINGS frame (again) */ @@ -2269,13 +2272,13 @@ CURLcode Curl_http2_switched(struct connectdata *conn, data into stream->mem, overwriting data already there. */ if(H2_BUFSIZE < nread) { failf(data, "connection buffer size is too small to store data following " - "HTTP Upgrade response header: buflen=%d, datalen=%zu", + "HTTP Upgrade response header: buflen=%d, datalen=%zu", H2_BUFSIZE, nread); return CURLE_HTTP2; } - infof(conn->data, "Copying HTTP/2 data in stream buffer to connection buffer" - " after upgrade: len=%zu\n", + infof(data, "Copying HTTP/2 data in stream buffer to connection buffer" + " after upgrade: len=%zu\n", nread); if(nread) @@ -2285,7 +2288,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn, DEBUGASSERT(httpc->nread_inbuf == 0); - if(-1 == h2_process_pending_input(conn, httpc, &result)) + if(-1 == h2_process_pending_input(data, httpc, &result)) return CURLE_HTTP2; return CURLE_OK; diff --git a/libs/libcurl/src/http2.h b/libs/libcurl/src/http2.h index 43a6863abe..119e584a8b 100644 --- a/libs/libcurl/src/http2.h +++ b/libs/libcurl/src/http2.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -44,14 +44,15 @@ void Curl_http2_init_state(struct UrlState *state); void Curl_http2_init_userset(struct UserDefined *set); CURLcode Curl_http2_request_upgrade(struct dynbuf *req, struct connectdata *conn); -CURLcode Curl_http2_setup(struct connectdata *conn); -CURLcode Curl_http2_switched(struct connectdata *conn, - const char *data, size_t nread); +CURLcode Curl_http2_setup(struct Curl_easy *data, struct connectdata *conn); +CURLcode Curl_http2_switched(struct Curl_easy *data, + const char *ptr, size_t nread); /* called from http_setup_conn */ void Curl_http2_setup_conn(struct connectdata *conn); void Curl_http2_setup_req(struct Curl_easy *data); void Curl_http2_done(struct Curl_easy *data, bool premature); -CURLcode Curl_http2_done_sending(struct connectdata *conn); +CURLcode Curl_http2_done_sending(struct Curl_easy *data, + struct connectdata *conn); CURLcode Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child, bool exclusive); @@ -64,14 +65,14 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause); bool Curl_h2_http_1_1_error(struct connectdata *conn); #else /* USE_NGHTTP2 */ #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL -#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_setup(x,y) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_setup_conn(x) Curl_nop_stmt #define Curl_http2_setup_req(x) #define Curl_http2_init_state(x) #define Curl_http2_init_userset(x) #define Curl_http2_done(x,y) -#define Curl_http2_done_sending(x) +#define Curl_http2_done_sending(x,y) #define Curl_http2_add_child(x, y, z) #define Curl_http2_remove_child(x, y) #define Curl_http2_cleanup_dependencies(x) diff --git a/libs/libcurl/src/http_aws_sigv4.c b/libs/libcurl/src/http_aws_sigv4.c new file mode 100644 index 0000000000..8fd1c77e60 --- /dev/null +++ b/libs/libcurl/src/http_aws_sigv4.c @@ -0,0 +1,394 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + +#include "urldata.h" +#include "strcase.h" +#include "strdup.h" +#include "vauth/vauth.h" +#include "vauth/digest.h" +#include "http_aws_sigv4.h" +#include "curl_sha256.h" +#include "transfer.h" + +#include "strcase.h" +#include "parsedate.h" +#include "sendf.h" + +#include + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define HMAC_SHA256(k, kl, d, dl, o) \ + do { \ + ret = Curl_hmacit(Curl_HMAC_SHA256, \ + (unsigned char *)k, \ + (unsigned int)kl, \ + (unsigned char *)d, \ + (unsigned int)dl, o); \ + if(ret != CURLE_OK) { \ + goto fail; \ + } \ + } while(0) + +static void sha256_to_hex(char *dst, unsigned char *sha, size_t dst_l) +{ + int i; + + DEBUGASSERT(dst_l >= 65); + for(i = 0; i < 32; ++i) { + curl_msnprintf(dst + (i * 2), dst_l - (i * 2), "%02x", sha[i]); + } +} + +CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) +{ + CURLcode ret = CURLE_OUT_OF_MEMORY; + struct connectdata *conn = data->conn; + size_t len; + const char *tmp0; + const char *tmp1; + char *provider0_low = NULL; + char *provider0_up = NULL; + char *provider1_low = NULL; + char *provider1_mid = NULL; + char *region = NULL; + char *service = NULL; + const char *hostname = conn->host.name; +#ifdef DEBUGBUILD + char *force_timestamp; +#endif + time_t clock; + struct tm tm; + char timestamp[17]; + char date[9]; + const char *content_type = Curl_checkheaders(data, "Content-Type"); + char *canonical_headers = NULL; + char *signed_headers = NULL; + Curl_HttpReq httpreq; + const char *method; + const char *post_data = data->set.postfields ? data->set.postfields : ""; + unsigned char sha_hash[32]; + char sha_hex[65]; + char *canonical_request = NULL; + char *request_type = NULL; + char *credential_scope = NULL; + char *str_to_sign = NULL; + const char *user = conn->user ? conn->user : ""; + const char *passwd = conn->passwd ? conn->passwd : ""; + char *secret = NULL; + unsigned char tmp_sign0[32] = {0}; + unsigned char tmp_sign1[32] = {0}; + char *auth_headers = NULL; + + DEBUGASSERT(!proxy); + (void)proxy; + + if(Curl_checkheaders(data, "Authorization")) { + /* Authorization already present, Bailing out */ + return CURLE_OK; + } + + /* + * Parameters parsing + * Google and Outscale use the same OSC or GOOG, + * but Amazon uses AWS and AMZ for header arguments. + * AWS is the default because most of non-amazon providers + * are still using aws:amz as a prefix. + */ + tmp0 = data->set.str[STRING_AWS_SIGV4] ? + data->set.str[STRING_AWS_SIGV4] : "aws:amz"; + tmp1 = strchr(tmp0, ':'); + len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0); + if(len < 1) { + infof(data, "first provider can't be empty\n"); + ret = CURLE_BAD_FUNCTION_ARGUMENT; + goto fail; + } + provider0_low = malloc(len + 1); + provider0_up = malloc(len + 1); + if(!provider0_low || !provider0_up) { + goto fail; + } + Curl_strntolower(provider0_low, tmp0, len); + provider0_low[len] = '\0'; + Curl_strntoupper(provider0_up, tmp0, len); + provider0_up[len] = '\0'; + + if(tmp1) { + tmp0 = tmp1 + 1; + tmp1 = strchr(tmp0, ':'); + len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0); + if(len < 1) { + infof(data, "second provider can't be empty\n"); + ret = CURLE_BAD_FUNCTION_ARGUMENT; + goto fail; + } + provider1_low = malloc(len + 1); + provider1_mid = malloc(len + 1); + if(!provider1_low || !provider1_mid) { + goto fail; + } + Curl_strntolower(provider1_low, tmp0, len); + provider1_low[len] = '\0'; + Curl_strntolower(provider1_mid, tmp0, len); + provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]); + provider1_mid[len] = '\0'; + + if(tmp1) { + tmp0 = tmp1 + 1; + tmp1 = strchr(tmp0, ':'); + len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0); + if(len < 1) { + infof(data, "region can't be empty\n"); + ret = CURLE_BAD_FUNCTION_ARGUMENT; + goto fail; + } + region = Curl_memdup(tmp0, len + 1); + if(!region) { + goto fail; + } + region[len] = '\0'; + + if(tmp1) { + tmp0 = tmp1 + 1; + service = strdup(tmp0); + if(!service) { + goto fail; + } + if(strlen(service) < 1) { + infof(data, "service can't be empty\n"); + ret = CURLE_BAD_FUNCTION_ARGUMENT; + goto fail; + } + } + } + } + else { + provider1_low = Curl_memdup(provider0_low, len + 1); + provider1_mid = Curl_memdup(provider0_low, len + 1); + if(!provider1_low || !provider1_mid) { + goto fail; + } + provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]); + } + + if(!service) { + tmp0 = hostname; + tmp1 = strchr(tmp0, '.'); + len = tmp1 - tmp0; + if(!tmp1 || len < 1) { + infof(data, "service missing in parameters or hostname\n"); + ret = CURLE_URL_MALFORMAT; + goto fail; + } + service = Curl_memdup(tmp0, len + 1); + if(!service) { + goto fail; + } + service[len] = '\0'; + + if(!region) { + tmp0 = tmp1 + 1; + tmp1 = strchr(tmp0, '.'); + len = tmp1 - tmp0; + if(!tmp1 || len < 1) { + infof(data, "region missing in parameters or hostname\n"); + ret = CURLE_URL_MALFORMAT; + goto fail; + } + region = Curl_memdup(tmp0, len + 1); + if(!region) { + goto fail; + } + region[len] = '\0'; + } + } + +#ifdef DEBUGBUILD + force_timestamp = getenv("CURL_FORCETIME"); + if(force_timestamp) + clock = 0; + else + time(&clock); +#else + time(&clock); +#endif + ret = Curl_gmtime(clock, &tm); + if(ret != CURLE_OK) { + goto fail; + } + if(!strftime(timestamp, sizeof(timestamp), "%Y%m%dT%H%M%SZ", &tm)) { + goto fail; + } + memcpy(date, timestamp, sizeof(date)); + date[sizeof(date) - 1] = 0; + + if(content_type) { + content_type = strchr(content_type, ':'); + if(!content_type) { + ret = CURLE_FAILED_INIT; + goto fail; + } + content_type++; + /* Skip whitespace now */ + while(*content_type == ' ' || *content_type == '\t') + ++content_type; + + canonical_headers = curl_maprintf("content-type:%s\n" + "host:%s\n" + "x-%s-date:%s\n", + content_type, + hostname, + provider1_low, timestamp); + signed_headers = curl_maprintf("content-type;host;x-%s-date", + provider1_low); + } + else { + canonical_headers = curl_maprintf("host:%s\n" + "x-%s-date:%s\n", + hostname, + provider1_low, timestamp); + signed_headers = curl_maprintf("host;x-%s-date", provider1_low); + } + + if(!canonical_headers || !signed_headers) { + goto fail; + } + + Curl_sha256it(sha_hash, + (const unsigned char *) post_data, strlen(post_data)); + sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex)); + + Curl_http_method(data, conn, &method, &httpreq); + + canonical_request = + curl_maprintf("%s\n" /* HTTPRequestMethod */ + "%s\n" /* CanonicalURI */ + "%s\n" /* CanonicalQueryString */ + "%s\n" /* CanonicalHeaders */ + "%s\n" /* SignedHeaders */ + "%s", /* HashedRequestPayload in hex */ + method, + data->state.up.path, + data->state.up.query ? data->state.up.query : "", + canonical_headers, + signed_headers, + sha_hex); + if(!canonical_request) { + goto fail; + } + + request_type = curl_maprintf("%s4_request", provider0_low); + if(!request_type) { + goto fail; + } + + credential_scope = curl_maprintf("%s/%s/%s/%s", + date, region, service, request_type); + if(!credential_scope) { + goto fail; + } + + Curl_sha256it(sha_hash, (unsigned char *) canonical_request, + strlen(canonical_request)); + sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex)); + + /* + * 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 + */ + str_to_sign = curl_maprintf("%s4-HMAC-SHA256\n" /* Algorithm */ + "%s\n" /* RequestDateTime */ + "%s\n" /* CredentialScope */ + "%s", /* HashedCanonicalRequest in hex */ + provider0_up, + timestamp, + credential_scope, + sha_hex); + if(!str_to_sign) { + goto fail; + } + + secret = curl_maprintf("%s4%s", provider0_up, passwd); + if(!secret) { + goto fail; + } + + HMAC_SHA256(secret, strlen(secret), + date, strlen(date), tmp_sign0); + HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0), + region, strlen(region), tmp_sign1); + HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1), + service, strlen(service), tmp_sign0); + HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0), + request_type, strlen(request_type), tmp_sign1); + HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1), + str_to_sign, strlen(str_to_sign), tmp_sign0); + + sha256_to_hex(sha_hex, tmp_sign0, sizeof(sha_hex)); + + auth_headers = curl_maprintf("Authorization: %s4-HMAC-SHA256 " + "Credential=%s/%s, " + "SignedHeaders=%s, " + "Signature=%s\r\n" + "X-%s-Date: %s\r\n", + provider0_up, + user, + credential_scope, + signed_headers, + sha_hex, + provider1_mid, + timestamp); + if(!auth_headers) { + goto fail; + } + + Curl_safefree(data->state.aptr.userpwd); + data->state.aptr.userpwd = auth_headers; + data->state.authhost.done = TRUE; + ret = CURLE_OK; + +fail: + free(provider0_low); + free(provider0_up); + free(provider1_low); + free(provider1_mid); + free(region); + free(service); + free(canonical_headers); + free(signed_headers); + free(canonical_request); + free(request_type); + free(credential_scope); + free(str_to_sign); + free(secret); + return ret; +} + +#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) */ diff --git a/libs/libcurl/src/http_aws_sigv4.h b/libs/libcurl/src/http_aws_sigv4.h new file mode 100644 index 0000000000..886b31440f --- /dev/null +++ b/libs/libcurl/src/http_aws_sigv4.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_HTTP_AWS_SIGV4_H +#define HEADER_CURL_HTTP_AWS_SIGV4_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* this is for creating aws_sigv4 header output */ +CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy); + +#endif /* HEADER_CURL_HTTP_AWS_SIGV4_H */ diff --git a/libs/libcurl/src/http_chunks.c b/libs/libcurl/src/http_chunks.c index 498481475c..beb9695884 100644 --- a/libs/libcurl/src/http_chunks.c +++ b/libs/libcurl/src/http_chunks.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -77,21 +77,21 @@ #ifdef CURL_DOES_CONVERSIONS /* Check for an ASCII hex digit. We avoid the use of ISXDIGIT to accommodate non-ASCII hosts. */ -static bool Curl_isxdigit_ascii(char digit) +static bool isxdigit_ascii(char digit) { return (digit >= 0x30 && digit <= 0x39) /* 0-9 */ - || (digit >= 0x41 && digit <= 0x46) /* A-F */ - || (digit >= 0x61 && digit <= 0x66); /* a-f */ + || (digit >= 0x41 && digit <= 0x46) /* A-F */ + || (digit >= 0x61 && digit <= 0x66); /* a-f */ } #else -#define Curl_isxdigit_ascii(x) Curl_isxdigit(x) +#define isxdigit_ascii(x) Curl_isxdigit(x) #endif -void Curl_httpchunk_init(struct connectdata *conn) +void Curl_httpchunk_init(struct Curl_easy *data) { + struct connectdata *conn = data->conn; struct Curl_chunker *chunk = &conn->chunk; chunk->hexindex = 0; /* start at 0 */ - chunk->dataleft = 0; /* no data left yet! */ chunk->state = CHUNK_HEX; /* we get hex first! */ Curl_dyn_init(&conn->trailer, DYN_H1_TRAILER); } @@ -107,14 +107,14 @@ void Curl_httpchunk_init(struct connectdata *conn) * This function always uses ASCII hex values to accommodate non-ASCII hosts. * For example, 0x0d and 0x0a are used instead of '\r' and '\n'. */ -CHUNKcode Curl_httpchunk_read(struct connectdata *conn, +CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap, ssize_t datalen, ssize_t *wrotep, CURLcode *extrap) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct Curl_chunker *ch = &conn->chunk; struct SingleRequest *k = &data->req; size_t piece; @@ -126,7 +126,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, /* the original data is written to the client, but we go on with the chunk read process, to properly calculate the content length*/ if(data->set.http_te_skip && !k->ignorebody) { - result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen); + result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen); if(result) { *extrap = result; return CHUNKE_PASSTHRU_ERROR; @@ -136,8 +136,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, while(length) { switch(ch->state) { case CHUNK_HEX: - if(Curl_isxdigit_ascii(*datap)) { - if(ch->hexindex < MAXNUM_SIZE) { + if(isxdigit_ascii(*datap)) { + if(ch->hexindex < CHUNK_MAXNUM_LEN) { ch->hexbuffer[ch->hexindex] = *datap; datap++; length--; @@ -158,8 +158,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, ch->hexbuffer[ch->hexindex] = 0; /* convert to host encoding before calling strtoul */ - result = Curl_convert_from_network(conn->data, ch->hexbuffer, - ch->hexindex); + result = Curl_convert_from_network(data, ch->hexbuffer, ch->hexindex); if(result) { /* Curl_convert_from_network calls failf if unsuccessful */ /* Treat it as a bad hex character */ @@ -194,11 +193,11 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize); /* Write the data portion available */ - if(!conn->data->set.http_te_skip && !k->ignorebody) { - if(!conn->data->set.http_ce_skip && k->writer_stack) - result = Curl_unencode_write(conn, k->writer_stack, datap, piece); + if(!data->set.http_te_skip && !k->ignorebody) { + if(!data->set.http_ce_skip && k->writer_stack) + result = Curl_unencode_write(data, k->writer_stack, datap, piece); else - result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece); + result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece); if(result) { *extrap = result; @@ -219,7 +218,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, case CHUNK_POSTLF: if(*datap == 0x0a) { /* The last one before we go back to hex state and start all over. */ - Curl_httpchunk_init(conn); /* sets state back to CHUNK_HEX */ + Curl_httpchunk_init(data); /* sets state back to CHUNK_HEX */ } else if(*datap != 0x0d) return CHUNKE_BAD_CHUNK; @@ -242,14 +241,14 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, tr = Curl_dyn_ptr(&conn->trailer); trlen = Curl_dyn_len(&conn->trailer); /* Convert to host encoding before calling Curl_client_write */ - result = Curl_convert_from_network(conn->data, tr, trlen); + result = Curl_convert_from_network(data, tr, trlen); if(result) /* Curl_convert_from_network calls failf if unsuccessful */ /* Treat it as a bad chunk */ return CHUNKE_BAD_CHUNK; if(!data->set.http_te_skip) { - result = Curl_client_write(conn, CLIENTWRITE_HEADER, tr, trlen); + result = Curl_client_write(data, CLIENTWRITE_HEADER, tr, trlen); if(result) { *extrap = result; return CHUNKE_PASSTHRU_ERROR; @@ -309,7 +308,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, /* Record the length of any data left in the end of the buffer even if there's no more chunks to read */ - ch->dataleft = curlx_sotouz(length); + ch->datasize = curlx_sotouz(length); return CHUNKE_STOP; /* return stop */ } diff --git a/libs/libcurl/src/http_chunks.h b/libs/libcurl/src/http_chunks.h index c8f072a2de..741a9a3bc3 100644 --- a/libs/libcurl/src/http_chunks.h +++ b/libs/libcurl/src/http_chunks.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , 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,10 +26,10 @@ struct connectdata; /* * The longest possible hexadecimal number we support in a chunked transfer. - * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul() - * to convert it, we "only" support 2^32 bytes chunk data. + * Neither RFC2616 nor the later HTTP specs define a maximum chunk size. + * For 64 bit curl_off_t we support 16 digits. For 32 bit, 8 digits. */ -#define MAXNUM_SIZE 16 +#define CHUNK_MAXNUM_LEN (SIZEOF_CURL_OFF_T * 2) typedef enum { /* await and buffer all hexadecimal digits until we get one that isn't a @@ -48,7 +48,7 @@ typedef enum { big deal. */ CHUNK_POSTLF, - /* Used to mark that we're out of the game. NOTE: that there's a 'dataleft' + /* Used to mark that we're out of the game. NOTE: that there's a 'datasize' field in the struct that will tell how many bytes that were not passed to the client in the end of the last buffer! */ CHUNK_STOP, @@ -83,16 +83,15 @@ typedef enum { const char *Curl_chunked_strerror(CHUNKcode code); struct Curl_chunker { - char hexbuffer[ MAXNUM_SIZE + 1]; - int hexindex; - ChunkyState state; curl_off_t datasize; - size_t dataleft; /* untouched data amount at the end of the last buffer */ + ChunkyState state; + unsigned char hexindex; + char hexbuffer[ CHUNK_MAXNUM_LEN + 1]; /* +1 for null-terminator */ }; /* The following functions are defined in http_chunks.c */ -void Curl_httpchunk_init(struct connectdata *conn); -CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, +void Curl_httpchunk_init(struct Curl_easy *data); +CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap, ssize_t length, ssize_t *wrote, CURLcode *passthru); diff --git a/libs/libcurl/src/http_digest.c b/libs/libcurl/src/http_digest.c index dfa40dcb61..596b215db6 100644 --- a/libs/libcurl/src/http_digest.c +++ b/libs/libcurl/src/http_digest.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -41,13 +41,11 @@ Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598" */ -CURLcode Curl_input_digest(struct connectdata *conn, +CURLcode Curl_input_digest(struct Curl_easy *data, bool proxy, const char *header) /* rest of the *-authenticate: header */ { - struct Curl_easy *data = conn->data; - /* Point to the correct struct with this */ struct digestdata *digest; @@ -68,13 +66,13 @@ CURLcode Curl_input_digest(struct connectdata *conn, return Curl_auth_decode_digest_http_message(header, digest); } -CURLcode Curl_output_digest(struct connectdata *conn, +CURLcode Curl_output_digest(struct Curl_easy *data, + struct connectdata *conn, bool proxy, const unsigned char *request, const unsigned char *uripath) { CURLcode result; - struct Curl_easy *data = conn->data; unsigned char *path = NULL; char *tmp = NULL; char *response; diff --git a/libs/libcurl/src/http_digest.h b/libs/libcurl/src/http_digest.h index f7001edec1..106caa7c4f 100644 --- a/libs/libcurl/src/http_digest.h +++ b/libs/libcurl/src/http_digest.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , 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,11 +26,12 @@ #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) /* this is for digest header input */ -CURLcode Curl_input_digest(struct connectdata *conn, +CURLcode Curl_input_digest(struct Curl_easy *data, bool proxy, const char *header); /* this is for creating digest header output */ -CURLcode Curl_output_digest(struct connectdata *conn, +CURLcode Curl_output_digest(struct Curl_easy *data, + struct connectdata *conn, bool proxy, const unsigned char *request, const unsigned char *uripath); diff --git a/libs/libcurl/src/http_negotiate.c b/libs/libcurl/src/http_negotiate.c index 872d172fc6..d759748f2e 100644 --- a/libs/libcurl/src/http_negotiate.c +++ b/libs/libcurl/src/http_negotiate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -34,11 +34,10 @@ #include "curl_memory.h" #include "memdebug.h" -CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, - const char *header) +CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn, + bool proxy, const char *header) { CURLcode result; - struct Curl_easy *data = conn->data; size_t len; /* Point to the username, password, service and host */ @@ -90,7 +89,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, neg_ctx->havenegdata = len != 0; if(!len) { if(state == GSS_AUTHSUCC) { - infof(conn->data, "Negotiate auth restarted\n"); + infof(data, "Negotiate auth restarted\n"); Curl_http_auth_cleanup_negotiate(conn); } else if(state != GSS_AUTHNONE) { @@ -116,15 +115,14 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, return result; } -CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) +CURLcode Curl_output_negotiate(struct Curl_easy *data, + struct connectdata *conn, bool proxy) { struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg : &conn->negotiate; - struct auth *authp = proxy ? &conn->data->state.authproxy : - &conn->data->state.authhost; + struct auth *authp = proxy ? &data->state.authproxy : &data->state.authhost; curlnegotiate *state = proxy ? &conn->proxy_negotiate_state : &conn->http_negotiate_state; - struct Curl_easy *data = conn->data; char *base64 = NULL; size_t len = 0; char *userp; @@ -147,12 +145,12 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) { if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) { - infof(conn->data, "Curl_output_negotiate, " + infof(data, "Curl_output_negotiate, " "no persistent authentication: cleanup existing context"); Curl_http_auth_cleanup_negotiate(conn); } if(!neg_ctx->context) { - result = Curl_input_negotiate(conn, proxy, "Negotiate"); + result = Curl_input_negotiate(data, conn, proxy, "Negotiate"); if(result == CURLE_AUTH_ERROR) { /* negotiate auth failed, let's continue unauthenticated to stay * compatible with the behavior before curl-7_64_0-158-g6c6035532 */ @@ -163,8 +161,7 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) return result; } - result = Curl_auth_create_spnego_message(conn->data, - neg_ctx, &base64, &len); + result = Curl_auth_create_spnego_message(data, neg_ctx, &base64, &len); if(result) return result; diff --git a/libs/libcurl/src/http_negotiate.h b/libs/libcurl/src/http_negotiate.h index cf1d007dce..2640a3ee01 100644 --- a/libs/libcurl/src/http_negotiate.h +++ b/libs/libcurl/src/http_negotiate.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , 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,12 @@ #if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) /* this is for Negotiate header input */ -CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, - const char *header); +CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn, + bool proxy, const char *header); /* this is for creating Negotiate header output */ -CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy); +CURLcode Curl_output_negotiate(struct Curl_easy *data, + struct connectdata *conn, bool proxy); void Curl_http_auth_cleanup_negotiate(struct connectdata *conn); diff --git a/libs/libcurl/src/http_ntlm.c b/libs/libcurl/src/http_ntlm.c index 91e1d1f714..6cb829edfa 100644 --- a/libs/libcurl/src/http_ntlm.c +++ b/libs/libcurl/src/http_ntlm.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -59,7 +59,7 @@ # define DEBUG_OUT(x) Curl_nop_stmt #endif -CURLcode Curl_input_ntlm(struct connectdata *conn, +CURLcode Curl_input_ntlm(struct Curl_easy *data, bool proxy, /* if proxy or not */ const char *header) /* rest of the www-authenticate: header */ @@ -68,6 +68,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, struct ntlmdata *ntlm; curlntlm *state; CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; ntlm = proxy ? &conn->proxyntlm : &conn->ntlm; state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state; @@ -79,7 +80,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, header++; if(*header) { - result = Curl_auth_decode_ntlm_type2_message(conn->data, header, ntlm); + result = Curl_auth_decode_ntlm_type2_message(data, header, ntlm); if(result) return result; @@ -87,17 +88,17 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, } else { if(*state == NTLMSTATE_LAST) { - infof(conn->data, "NTLM auth restarted\n"); + infof(data, "NTLM auth restarted\n"); Curl_http_auth_cleanup_ntlm(conn); } else if(*state == NTLMSTATE_TYPE3) { - infof(conn->data, "NTLM handshake rejected\n"); + infof(data, "NTLM handshake rejected\n"); Curl_http_auth_cleanup_ntlm(conn); *state = NTLMSTATE_NONE; return CURLE_REMOTE_ACCESS_DENIED; } else if(*state >= NTLMSTATE_TYPE1) { - infof(conn->data, "NTLM handshake failure (internal error)\n"); + infof(data, "NTLM handshake failure (internal error)\n"); return CURLE_REMOTE_ACCESS_DENIED; } @@ -111,7 +112,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, /* * This is for creating ntlm header output */ -CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) +CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) { char *base64 = NULL; size_t len = 0; @@ -131,8 +132,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) struct ntlmdata *ntlm; curlntlm *state; struct auth *authp; - struct Curl_easy *data = conn->data; - + struct connectdata *conn = data->conn; DEBUGASSERT(conn); DEBUGASSERT(data); @@ -142,12 +142,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) allocuserpwd = &data->state.aptr.proxyuserpwd; userp = conn->http_proxy.user; passwdp = conn->http_proxy.passwd; - service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ? - conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; + service = data->set.str[STRING_PROXY_SERVICE_NAME] ? + data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; hostname = conn->http_proxy.host.name; ntlm = &conn->proxyntlm; state = &conn->proxy_ntlm_state; - authp = &conn->data->state.authproxy; + authp = &data->state.authproxy; #else return CURLE_NOT_BUILT_IN; #endif @@ -156,12 +156,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) allocuserpwd = &data->state.aptr.userpwd; userp = conn->user; passwdp = conn->passwd; - service = conn->data->set.str[STRING_SERVICE_NAME] ? - conn->data->set.str[STRING_SERVICE_NAME] : "HTTP"; + service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : "HTTP"; hostname = conn->host.name; ntlm = &conn->ntlm; state = &conn->http_ntlm_state; - authp = &conn->data->state.authhost; + authp = &data->state.authhost; } authp->done = FALSE; @@ -188,7 +188,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) case NTLMSTATE_TYPE1: default: /* for the weird cases we (re)start here */ /* Create a type-1 message */ - result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp, + result = Curl_auth_create_ntlm_type1_message(data, userp, passwdp, service, hostname, ntlm, &base64, &len); @@ -210,7 +210,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) case NTLMSTATE_TYPE2: /* We already received the type-2 message, create a type-3 message */ - result = Curl_auth_create_ntlm_type3_message(conn->data, userp, passwdp, + result = Curl_auth_create_ntlm_type3_message(data, userp, passwdp, ntlm, &base64, &len); if(result) return result; diff --git a/libs/libcurl/src/http_ntlm.h b/libs/libcurl/src/http_ntlm.h index 5ddf538727..5b4fa00baa 100644 --- a/libs/libcurl/src/http_ntlm.h +++ b/libs/libcurl/src/http_ntlm.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,11 +27,11 @@ #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) /* this is for ntlm header input */ -CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy, +CURLcode Curl_input_ntlm(struct Curl_easy *data, bool proxy, const char *header); /* this is for creating ntlm header output */ -CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy); +CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy); void Curl_http_auth_cleanup_ntlm(struct connectdata *conn); diff --git a/libs/libcurl/src/http_proxy.c b/libs/libcurl/src/http_proxy.c index 4242251219..a03a27fdc4 100644 --- a/libs/libcurl/src/http_proxy.c +++ b/libs/libcurl/src/http_proxy.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,6 +27,9 @@ #if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) #include +#ifdef USE_HYPER +#include +#endif #include "sendf.h" #include "http.h" #include "url.h" @@ -47,15 +50,16 @@ * proxy_ssl_connected connection bit when complete. Can be * called multiple times. */ -static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex) +static CURLcode https_proxy_connect(struct Curl_easy *data, int sockindex) { #ifdef USE_SSL + struct connectdata *conn = data->conn; CURLcode result = CURLE_OK; DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS); if(!conn->bits.proxy_ssl_connected[sockindex]) { /* perform SSL initialization for this socket */ result = - Curl_ssl_connect_nonblocking(conn, sockindex, + Curl_ssl_connect_nonblocking(data, conn, sockindex, &conn->bits.proxy_ssl_connected[sockindex]); if(result) /* a failed connection is marked for closure to prevent (bad) re-use or @@ -64,17 +68,17 @@ static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex) } return result; #else - (void) conn; + (void) data; (void) sockindex; return CURLE_NOT_BUILT_IN; #endif } -CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex) +CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) { - const CURLcode result = https_proxy_connect(conn, sockindex); + const CURLcode result = https_proxy_connect(data, sockindex); if(result) return result; if(!conn->bits.proxy_ssl_connected[sockindex]) @@ -102,9 +106,9 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex) * This function might be called several times in the multi interface case * if the proxy's CONNECT response is not instant. */ - prot_save = conn->data->req.p.http; + prot_save = data->req.p.http; memset(&http_proxy, 0, sizeof(http_proxy)); - conn->data->req.p.http = &http_proxy; + data->req.p.http = &http_proxy; connkeep(conn, "HTTP proxy CONNECT"); /* for the secondary socket (FTP), use the "connect to host" @@ -124,8 +128,8 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex) remote_port = conn->conn_to_port; else remote_port = conn->remote_port; - result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port); - conn->data->req.p.http = prot_save; + result = Curl_proxyCONNECT(data, sockindex, hostname, remote_port); + data->req.p.http = prot_save; if(CURLE_OK != result) return result; Curl_safefree(data->state.aptr.proxyuserpwd); @@ -149,15 +153,16 @@ bool Curl_connect_ongoing(struct connectdata *conn) (conn->connect_state->tunnel_state != TUNNEL_COMPLETE); } -static CURLcode connect_init(struct connectdata *conn, bool reinit) +static CURLcode connect_init(struct Curl_easy *data, bool reinit) { struct http_connect_state *s; + struct connectdata *conn = data->conn; if(!reinit) { DEBUGASSERT(!conn->connect_state); s = calloc(1, sizeof(struct http_connect_state)); if(!s) return CURLE_OUT_OF_MEMORY; - infof(conn->data, "allocate connect buffer!\n"); + infof(data, "allocate connect buffer!\n"); conn->connect_state = s; Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS); } @@ -173,23 +178,57 @@ static CURLcode connect_init(struct connectdata *conn, bool reinit) return CURLE_OK; } -static void connect_done(struct connectdata *conn) +static void connect_done(struct Curl_easy *data) { + struct connectdata *conn = data->conn; struct http_connect_state *s = conn->connect_state; s->tunnel_state = TUNNEL_COMPLETE; Curl_dyn_free(&s->rcvbuf); - infof(conn->data, "CONNECT phase completed!\n"); + infof(data, "CONNECT phase completed!\n"); +} + +static CURLcode CONNECT_host(struct Curl_easy *data, + struct connectdata *conn, + const char *hostname, + int remote_port, + char **connecthostp, + char **hostp) +{ + char *hostheader; /* for CONNECT */ + char *host = NULL; /* Host: */ + bool ipv6_ip = conn->bits.ipv6_ip; + + /* the hostname may be different */ + if(hostname != conn->host.name) + ipv6_ip = (strchr(hostname, ':') != NULL); + hostheader = /* host:port with IPv6 support */ + aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"", + remote_port); + if(!hostheader) + return CURLE_OUT_OF_MEMORY; + + if(!Curl_checkProxyheaders(data, conn, "Host")) { + host = aprintf("Host: %s\r\n", hostheader); + if(!host) { + free(hostheader); + return CURLE_OUT_OF_MEMORY; + } + } + *connecthostp = hostheader; + *hostp = host; + return CURLE_OK; } -static CURLcode CONNECT(struct connectdata *conn, +static CURLcode CONNECT(struct Curl_easy *data, int sockindex, const char *hostname, int remote_port) +#ifndef USE_HYPER { int subversion = 0; - struct Curl_easy *data = conn->data; struct SingleRequest *k = &data->req; CURLcode result; + struct connectdata *conn = data->conn; curl_socket_t tunnelsocket = conn->sock[sockindex]; struct http_connect_state *s = conn->connect_state; char *linep; @@ -207,8 +246,9 @@ static CURLcode CONNECT(struct connectdata *conn, timediff_t check; if(TUNNEL_INIT == s->tunnel_state) { /* BEGIN CONNECT PHASE */ - char *host_port; struct dynbuf req; + char *hostheader = NULL; + char *host = NULL; infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); @@ -219,50 +259,28 @@ static CURLcode CONNECT(struct connectdata *conn, free(data->req.newurl); data->req.newurl = NULL; - host_port = aprintf("%s:%d", hostname, remote_port); - if(!host_port) - return CURLE_OUT_OF_MEMORY; - /* initialize a dynamic send-buffer */ Curl_dyn_init(&req, DYN_HTTP_REQUEST); - /* Setup the proxy-authorization header, if any */ - result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE); + result = CONNECT_host(data, conn, + hostname, remote_port, &hostheader, &host); + if(result) + return result; - free(host_port); + /* Setup the proxy-authorization header, if any */ + result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET, + hostheader, TRUE); if(!result) { - char *host = NULL; const char *proxyconn = ""; const char *useragent = ""; const char *httpv = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1"; - bool ipv6_ip = conn->bits.ipv6_ip; - char *hostheader; - - /* the hostname may be different */ - if(hostname != conn->host.name) - ipv6_ip = (strchr(hostname, ':') != NULL); - hostheader = /* host:port with IPv6 support */ - aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"", - remote_port); - if(!hostheader) { - Curl_dyn_free(&req); - return CURLE_OUT_OF_MEMORY; - } - if(!Curl_checkProxyheaders(conn, "Host")) { - host = aprintf("Host: %s\r\n", hostheader); - if(!host) { - free(hostheader); - Curl_dyn_free(&req); - return CURLE_OUT_OF_MEMORY; - } - } - if(!Curl_checkProxyheaders(conn, "Proxy-Connection")) + if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection")) proxyconn = "Proxy-Connection: Keep-Alive\r\n"; - if(!Curl_checkProxyheaders(conn, "User-Agent") && + if(!Curl_checkProxyheaders(data, conn, "User-Agent") && data->set.str[STRING_USERAGENT]) useragent = data->state.aptr.uagent; @@ -281,12 +299,8 @@ static CURLcode CONNECT(struct connectdata *conn, useragent, proxyconn); - if(host) - free(host); - free(hostheader); - if(!result) - result = Curl_add_custom_headers(conn, TRUE, &req); + result = Curl_add_custom_headers(data, TRUE, &req); if(!result) /* CRLF terminate the request */ @@ -295,13 +309,14 @@ static CURLcode CONNECT(struct connectdata *conn, if(!result) { /* Send the connect request to the proxy */ /* BLOCKING */ - result = Curl_buffer_send(&req, conn, &data->info.request_size, 0, + result = Curl_buffer_send(&req, data, &data->info.request_size, 0, sockindex); } if(result) failf(data, "Failed sending CONNECT to proxy"); } - + free(host); + free(hostheader); Curl_dyn_free(&req); if(result) return result; @@ -330,12 +345,12 @@ static CURLcode CONNECT(struct connectdata *conn, /* Read one byte at a time to avoid a race condition. Wait at most one second before looping to ensure continuous pgrsUpdates. */ - result = Curl_read(conn, tunnelsocket, &byte, 1, &gotbytes); + result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes); if(result == CURLE_AGAIN) /* socket buffer drained, return */ return CURLE_OK; - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) return CURLE_ABORTED_BY_CALLBACK; if(result) { @@ -379,7 +394,7 @@ static CURLcode CONNECT(struct connectdata *conn, /* now parse the chunked piece of data so that we can properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, &byte, 1, &tookcareof, &extra); + r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra); if(r == CHUNKE_STOP) { /* we're done reading chunks! */ infof(data, "chunk reading DONE\n"); @@ -418,7 +433,7 @@ static CURLcode CONNECT(struct connectdata *conn, if(data->set.include_header) writetype |= CLIENTWRITE_BODY; - result = Curl_client_write(conn, writetype, linep, perline); + result = Curl_client_write(data, writetype, linep, perline); if(result) return result; } @@ -460,7 +475,7 @@ static CURLcode CONNECT(struct connectdata *conn, /* now parse the chunked piece of data so that we can properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, linep + 1, 1, &gotbytes, + r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes, &extra); if(r == CHUNKE_STOP) { /* we're done reading chunks! */ @@ -479,9 +494,12 @@ static CURLcode CONNECT(struct connectdata *conn, } else s->keepon = KEEPON_DONE; - if(!s->cl) + + if(s->keepon == KEEPON_DONE && !s->cl) /* we did the full CONNECT treatment, go to COMPLETE */ s->tunnel_state = TUNNEL_COMPLETE; + + DEBUGASSERT(s->keepon == KEEPON_IGNORE || s->keepon == KEEPON_DONE); continue; } @@ -495,7 +513,7 @@ static CURLcode CONNECT(struct connectdata *conn, if(!auth) return CURLE_OUT_OF_MEMORY; - result = Curl_http_input_auth(conn, proxy, auth); + result = Curl_http_input_auth(data, proxy, auth); free(auth); @@ -530,7 +548,7 @@ static CURLcode CONNECT(struct connectdata *conn, infof(data, "CONNECT responded chunked\n"); s->chunked_encoding = TRUE; /* init our chunky engine */ - Curl_httpchunk_init(conn); + Curl_httpchunk_init(data); } } else if(Curl_compareheader(linep, "Proxy-Connection:", "close")) @@ -545,7 +563,7 @@ static CURLcode CONNECT(struct connectdata *conn, Curl_dyn_reset(&s->rcvbuf); } /* while there's buffer left and loop is requested */ - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) return CURLE_ABORTED_BY_CALLBACK; if(error) @@ -554,7 +572,7 @@ static CURLcode CONNECT(struct connectdata *conn, if(data->info.httpproxycode/100 != 2) { /* Deal with the possibly already received authenticate headers. 'newurl' is set to a new URL if we must loop. */ - result = Curl_http_auth_act(conn); + result = Curl_http_auth_act(data); if(result) return result; @@ -567,7 +585,7 @@ static CURLcode CONNECT(struct connectdata *conn, if(s->close_connection && data->req.newurl) { /* Connection closed by server. Don't use it anymore */ - Curl_closesocket(conn, conn->sock[sockindex]); + Curl_closesocket(data, conn, conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; break; } @@ -577,7 +595,7 @@ static CURLcode CONNECT(struct connectdata *conn, * 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)) { - connect_init(conn, TRUE); /* reinit */ + connect_init(data, TRUE); /* reinit */ } } while(data->req.newurl); @@ -586,14 +604,14 @@ static CURLcode CONNECT(struct connectdata *conn, if(s->close_connection && data->req.newurl) { conn->bits.proxy_connect_closed = TRUE; infof(data, "Connect me again please\n"); - connect_done(conn); + connect_done(data); } else { free(data->req.newurl); data->req.newurl = NULL; /* failure, close this connection to avoid re-use */ streamclose(conn, "proxy CONNECT failure"); - Curl_closesocket(conn, conn->sock[sockindex]); + Curl_closesocket(data, conn, conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; } @@ -628,6 +646,225 @@ static CURLcode CONNECT(struct connectdata *conn, Curl_dyn_free(&s->rcvbuf); return CURLE_OK; } +#else +/* The Hyper version of CONNECT */ +{ + struct connectdata *conn = data->conn; + struct hyptransfer *h = &data->hyp; + curl_socket_t tunnelsocket = conn->sock[sockindex]; + struct http_connect_state *s = conn->connect_state; + CURLcode result = CURLE_OUT_OF_MEMORY; + hyper_io *io = NULL; + hyper_request *req = NULL; + hyper_headers *headers = NULL; + hyper_clientconn_options *options = NULL; + hyper_task *handshake = NULL; + hyper_task *task = NULL; /* for the handshake */ + hyper_task *sendtask = NULL; /* for the send */ + hyper_clientconn *client = NULL; + hyper_error *hypererr = NULL; + char *hostheader = NULL; /* for CONNECT */ + char *host = NULL; /* Host: */ + + if(Curl_connect_complete(conn)) + return CURLE_OK; /* CONNECT is already completed */ + + conn->bits.proxy_connect_closed = FALSE; + + do { + switch(s->tunnel_state) { + case TUNNEL_INIT: + /* BEGIN CONNECT PHASE */ + io = hyper_io_new(); + if(!io) { + failf(data, "Couldn't create hyper IO"); + goto error; + } + /* tell Hyper how to read/write network data */ + hyper_io_set_userdata(io, data); + hyper_io_set_read(io, Curl_hyper_recv); + hyper_io_set_write(io, Curl_hyper_send); + conn->sockfd = tunnelsocket; + + /* create an executor to poll futures */ + if(!h->exec) { + h->exec = hyper_executor_new(); + if(!h->exec) { + failf(data, "Couldn't create hyper executor"); + goto error; + } + } + + options = hyper_clientconn_options_new(); + if(!options) { + failf(data, "Couldn't create hyper client options"); + goto error; + } + + hyper_clientconn_options_exec(options, h->exec); + + /* "Both the `io` and the `options` are consumed in this function + call" */ + handshake = hyper_clientconn_handshake(io, options); + if(!handshake) { + failf(data, "Couldn't create hyper client handshake"); + goto error; + } + io = NULL; + options = NULL; + + if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) { + failf(data, "Couldn't hyper_executor_push the handshake"); + goto error; + } + handshake = NULL; /* ownership passed on */ + + task = hyper_executor_poll(h->exec); + if(!task) { + failf(data, "Couldn't hyper_executor_poll the handshake"); + goto error; + } + + client = hyper_task_value(task); + hyper_task_free(task); + req = hyper_request_new(); + if(!req) { + failf(data, "Couldn't hyper_request_new"); + goto error; + } + if(hyper_request_set_method(req, (uint8_t *)"CONNECT", + strlen("CONNECT"))) { + failf(data, "error setting method"); + goto error; + } + + result = CONNECT_host(data, conn, hostname, remote_port, + &hostheader, &host); + if(result) + goto error; + + if(hyper_request_set_uri(req, (uint8_t *)hostheader, + strlen(hostheader))) { + failf(data, "error setting path"); + result = CURLE_OUT_OF_MEMORY; + } + /* Setup the proxy-authorization header, if any */ + result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET, + hostheader, TRUE); + if(result) + goto error; + Curl_safefree(hostheader); + + /* default is 1.1 */ + if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) && + (HYPERE_OK != hyper_request_set_version(req, + HYPER_HTTP_VERSION_1_0))) { + failf(data, "error settting HTTP version"); + goto error; + } + + headers = hyper_request_headers(req); + if(!headers) { + failf(data, "hyper_request_headers"); + goto error; + } + if(host && Curl_hyper_header(data, headers, host)) + goto error; + Curl_safefree(host); + + if(data->state.aptr.proxyuserpwd && + Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd)) + 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, "Proxy-Connection") && + Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive")) + goto error; + + sendtask = hyper_clientconn_send(client, req); + if(!sendtask) { + failf(data, "hyper_clientconn_send"); + goto error; + } + + if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) { + failf(data, "Couldn't hyper_executor_push the send"); + 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); + s->tunnel_state = TUNNEL_CONNECT; + /* FALLTHROUGH */ + case TUNNEL_CONNECT: { + int didwhat; + bool done = FALSE; + result = Curl_hyper_stream(data, conn, &didwhat, &done, + CURL_CSELECT_IN | CURL_CSELECT_OUT); + if(result) + goto error; + if(!done) + break; + fprintf(stderr, "done\n"); + s->tunnel_state = TUNNEL_COMPLETE; + if(h->exec) { + hyper_executor_free(h->exec); + h->exec = NULL; + } + if(h->read_waker) { + hyper_waker_free(h->read_waker); + h->read_waker = NULL; + } + if(h->write_waker) { + hyper_waker_free(h->write_waker); + h->write_waker = NULL; + } + } + /* FALLTHROUGH */ + default: + break; + } + } while(data->req.newurl); + + result = CURLE_OK; + error: + free(host); + free(hostheader); + if(io) + hyper_io_free(io); + + if(options) + hyper_clientconn_options_free(options); + + if(handshake) + hyper_task_free(handshake); + + if(hypererr) { + uint8_t errbuf[256]; + size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf)); + failf(data, "Hyper: %.*s", (int)errlen, errbuf); + hyper_error_free(hypererr); + } + return result; +} + +#endif void Curl_connect_free(struct Curl_easy *data) { @@ -645,21 +882,22 @@ void Curl_connect_free(struct Curl_easy *data) * this proxy. After that, the socket can be used just as a normal socket. */ -CURLcode Curl_proxyCONNECT(struct connectdata *conn, +CURLcode Curl_proxyCONNECT(struct Curl_easy *data, int sockindex, const char *hostname, int remote_port) { CURLcode result; + struct connectdata *conn = data->conn; if(!conn->connect_state) { - result = connect_init(conn, FALSE); + result = connect_init(data, FALSE); if(result) return result; } - result = CONNECT(conn, sockindex, hostname, remote_port); + result = CONNECT(data, sockindex, hostname, remote_port); if(result || Curl_connect_complete(conn)) - connect_done(conn); + connect_done(data); return result; } diff --git a/libs/libcurl/src/http_proxy.h b/libs/libcurl/src/http_proxy.h index a595e8b553..a78db0d046 100644 --- a/libs/libcurl/src/http_proxy.h +++ b/libs/libcurl/src/http_proxy.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -27,14 +27,14 @@ #if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) /* ftp can use this as well */ -CURLcode Curl_proxyCONNECT(struct connectdata *conn, +CURLcode Curl_proxyCONNECT(struct Curl_easy *data, int tunnelsocket, const char *hostname, int remote_port); /* Default proxy timeout in milliseconds */ #define PROXY_TIMEOUT (3600*1000) -CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex); +CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex); bool Curl_connect_complete(struct connectdata *conn); bool Curl_connect_ongoing(struct connectdata *conn); diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c index c6dd7a2323..2d8069921c 100644 --- a/libs/libcurl/src/imap.c +++ b/libs/libcurl/src/imap.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -88,25 +88,31 @@ #include "memdebug.h" /* Local API functions */ -static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done); -static CURLcode imap_do(struct connectdata *conn, bool *done); -static CURLcode imap_done(struct connectdata *conn, CURLcode status, +static CURLcode imap_regular_transfer(struct Curl_easy *data, bool *done); +static CURLcode imap_do(struct Curl_easy *data, bool *done); +static CURLcode imap_done(struct Curl_easy *data, CURLcode status, bool premature); -static CURLcode imap_connect(struct connectdata *conn, bool *done); -static CURLcode imap_disconnect(struct connectdata *conn, bool dead); -static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done); -static int imap_getsock(struct connectdata *conn, curl_socket_t *socks); -static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done); -static CURLcode imap_setup_connection(struct connectdata *conn); +static CURLcode imap_connect(struct Curl_easy *data, bool *done); +static CURLcode imap_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); +static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done); +static int imap_getsock(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t *socks); +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 connectdata *conn, const char *fmt, ...); +static CURLcode imap_sendf(struct Curl_easy *data, + struct connectdata *conn, const char *fmt, ...); static CURLcode imap_parse_url_options(struct connectdata *conn); -static CURLcode imap_parse_url_path(struct connectdata *conn); -static CURLcode imap_parse_custom_request(struct connectdata *conn); -static CURLcode imap_perform_authenticate(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); -static CURLcode imap_continue_authenticate(struct connectdata *conn, +static CURLcode imap_continue_authenticate(struct Curl_easy *data, + struct connectdata *conn, const char *resp); static void imap_get_message(char *buffer, char **outptr); @@ -243,10 +249,10 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd) * Checks whether the given string is a valid tagged, untagged or continuation * response which can be processed by the response handler. */ -static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, - int *resp) +static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn, + char *line, size_t len, int *resp) { - struct IMAP *imap = conn->data->req.p.imap; + struct IMAP *imap = data->req.p.imap; struct imap_conn *imapc = &conn->proto.imapc; const char *id = imapc->resptag; size_t id_len = strlen(id); @@ -328,7 +334,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, break; default: - failf(conn->data, "Unexpected continuation response"); + failf(data, "Unexpected continuation response"); *resp = -1; break; } @@ -381,9 +387,9 @@ static void imap_get_message(char *buffer, char **outptr) * * This is the ONLY way to change IMAP state! */ -static void state(struct connectdata *conn, imapstate newstate) +static void state(struct Curl_easy *data, imapstate newstate) { - struct imap_conn *imapc = &conn->proto.imapc; + struct imap_conn *imapc = &data->conn->proto.imapc; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* for debug purposes */ static const char * const names[]={ @@ -406,7 +412,7 @@ static void state(struct connectdata *conn, imapstate newstate) }; if(imapc->state != newstate) - infof(conn->data, "IMAP %p state change from %s to %s\n", + infof(data, "IMAP %p state change from %s to %s\n", (void *)imapc, names[imapc->state], names[newstate]); #endif @@ -420,7 +426,8 @@ static void state(struct connectdata *conn, imapstate newstate) * Sends the CAPABILITY command in order to obtain a list of server side * supported capabilities. */ -static CURLcode imap_perform_capability(struct connectdata *conn) +static CURLcode imap_perform_capability(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; @@ -429,10 +436,10 @@ static CURLcode imap_perform_capability(struct connectdata *conn) imapc->tls_supported = FALSE; /* Clear the TLS capability */ /* Send the CAPABILITY command */ - result = imap_sendf(conn, "CAPABILITY"); + result = imap_sendf(data, conn, "CAPABILITY"); if(!result) - state(conn, IMAP_CAPABILITY); + state(data, IMAP_CAPABILITY); return result; } @@ -443,13 +450,14 @@ static CURLcode imap_perform_capability(struct connectdata *conn) * * Sends the STARTTLS command to start the upgrade to TLS. */ -static CURLcode imap_perform_starttls(struct connectdata *conn) +static CURLcode imap_perform_starttls(struct Curl_easy *data, + struct connectdata *conn) { /* Send the STARTTLS command */ - CURLcode result = imap_sendf(conn, "STARTTLS"); + CURLcode result = imap_sendf(data, conn, "STARTTLS"); if(!result) - state(conn, IMAP_STARTTLS); + state(data, IMAP_STARTTLS); return result; } @@ -460,20 +468,21 @@ static CURLcode imap_perform_starttls(struct connectdata *conn) * * Performs the upgrade to TLS. */ -static CURLcode imap_perform_upgrade_tls(struct connectdata *conn) +static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data, + struct connectdata *conn) { /* Start the SSL connection */ struct imap_conn *imapc = &conn->proto.imapc; - CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, &imapc->ssldone); if(!result) { if(imapc->state != IMAP_UPGRADETLS) - state(conn, IMAP_UPGRADETLS); + state(data, IMAP_UPGRADETLS); if(imapc->ssldone) { imap_to_imaps(conn); - result = imap_perform_capability(conn); + result = imap_perform_capability(data, conn); } } @@ -486,7 +495,8 @@ static CURLcode imap_perform_upgrade_tls(struct connectdata *conn) * * Sends a clear text LOGIN command to authenticate with. */ -static CURLcode imap_perform_login(struct connectdata *conn) +static CURLcode imap_perform_login(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; char *user; @@ -495,7 +505,7 @@ static CURLcode imap_perform_login(struct connectdata *conn) /* Check we have a username and password to authenticate with and end the connect phase if we don't */ if(!conn->bits.user_passwd) { - state(conn, IMAP_STOP); + state(data, IMAP_STOP); return result; } @@ -505,14 +515,14 @@ static CURLcode imap_perform_login(struct connectdata *conn) passwd = imap_atom(conn->passwd, false); /* Send the LOGIN command */ - result = imap_sendf(conn, "LOGIN %s %s", user ? user : "", + result = imap_sendf(data, conn, "LOGIN %s %s", user ? user : "", passwd ? passwd : ""); free(user); free(passwd); if(!result) - state(conn, IMAP_LOGIN); + state(data, IMAP_LOGIN); return result; } @@ -524,19 +534,21 @@ static CURLcode imap_perform_login(struct connectdata *conn) * Sends an AUTHENTICATE command allowing the client to login with the given * SASL authentication mechanism. */ -static CURLcode imap_perform_authenticate(struct connectdata *conn, +static CURLcode imap_perform_authenticate(struct Curl_easy *data, + struct connectdata *conn, const char *mech, const char *initresp) { CURLcode result = CURLE_OK; + (void)data; if(initresp) { /* Send the AUTHENTICATE command with the initial response */ - result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp); + result = imap_sendf(data, conn, "AUTHENTICATE %s %s", mech, initresp); } else { /* Send the AUTHENTICATE command */ - result = imap_sendf(conn, "AUTHENTICATE %s", mech); + result = imap_sendf(data, conn, "AUTHENTICATE %s", mech); } return result; @@ -548,12 +560,13 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn, * * Sends SASL continuation data or cancellation. */ -static CURLcode imap_continue_authenticate(struct connectdata *conn, +static CURLcode imap_continue_authenticate(struct Curl_easy *data, + struct connectdata *conn, const char *resp) { struct imap_conn *imapc = &conn->proto.imapc; - return Curl_pp_sendf(&imapc->pp, "%s", resp); + return Curl_pp_sendf(data, &imapc->pp, "%s", resp); } /*********************************************************************** @@ -564,7 +577,8 @@ static CURLcode imap_continue_authenticate(struct connectdata *conn, * authentication mechanism, falling back to clear text should a common * mechanism not be available between the client and server. */ -static CURLcode imap_perform_authentication(struct connectdata *conn) +static CURLcode imap_perform_authentication(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; @@ -574,22 +588,23 @@ static CURLcode imap_perform_authentication(struct connectdata *conn) with and end the connect phase if we don't */ if(imapc->preauth || !Curl_sasl_can_authenticate(&imapc->sasl, conn)) { - state(conn, IMAP_STOP); + state(data, IMAP_STOP); return result; } /* Calculate the SASL login details */ - result = Curl_sasl_start(&imapc->sasl, conn, imapc->ir_supported, &progress); + result = Curl_sasl_start(&imapc->sasl, data, conn, + imapc->ir_supported, &progress); if(!result) { if(progress == SASL_INPROGRESS) - state(conn, IMAP_AUTHENTICATE); + state(data, IMAP_AUTHENTICATE); else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) /* Perform clear text authentication */ - result = imap_perform_login(conn); + result = imap_perform_login(data, conn); else { /* Other mechanisms not supported */ - infof(conn->data, "No known authentication mechanisms supported!\n"); + infof(data, "No known authentication mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; } } @@ -603,15 +618,15 @@ static CURLcode imap_perform_authentication(struct connectdata *conn) * * Sends a LIST command or an alternative custom request. */ -static CURLcode imap_perform_list(struct connectdata *conn) +static CURLcode imap_perform_list(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct IMAP *imap = data->req.p.imap; if(imap->custom) /* Send the custom request */ - result = imap_sendf(conn, "%s%s", imap->custom, + result = imap_sendf(data, conn, "%s%s", imap->custom, imap->custom_params ? imap->custom_params : ""); else { /* Make sure the mailbox is in the correct atom format if necessary */ @@ -621,13 +636,13 @@ static CURLcode imap_perform_list(struct connectdata *conn) return CURLE_OUT_OF_MEMORY; /* Send the LIST command */ - result = imap_sendf(conn, "LIST \"%s\" *", mailbox); + result = imap_sendf(data, conn, "LIST \"%s\" *", mailbox); free(mailbox); } if(!result) - state(conn, IMAP_LIST); + state(data, IMAP_LIST); return result; } @@ -638,10 +653,10 @@ static CURLcode imap_perform_list(struct connectdata *conn) * * Sends a SELECT command to ask the server to change the selected mailbox. */ -static CURLcode imap_perform_select(struct connectdata *conn) +static CURLcode imap_perform_select(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct IMAP *imap = data->req.p.imap; struct imap_conn *imapc = &conn->proto.imapc; char *mailbox; @@ -652,7 +667,7 @@ static CURLcode imap_perform_select(struct connectdata *conn) /* Check we have a mailbox */ if(!imap->mailbox) { - failf(conn->data, "Cannot SELECT without a mailbox."); + failf(data, "Cannot SELECT without a mailbox."); return CURLE_URL_MALFORMAT; } @@ -662,12 +677,12 @@ static CURLcode imap_perform_select(struct connectdata *conn) return CURLE_OUT_OF_MEMORY; /* Send the SELECT command */ - result = imap_sendf(conn, "SELECT %s", mailbox); + result = imap_sendf(data, conn, "SELECT %s", mailbox); free(mailbox); if(!result) - state(conn, IMAP_SELECT); + state(data, IMAP_SELECT); return result; } @@ -678,43 +693,39 @@ static CURLcode imap_perform_select(struct connectdata *conn) * * Sends a FETCH command to initiate the download of a message. */ -static CURLcode imap_perform_fetch(struct connectdata *conn) +static CURLcode imap_perform_fetch(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; - struct IMAP *imap = conn->data->req.p.imap; + struct IMAP *imap = data->req.p.imap; /* Check we have a UID */ if(imap->uid) { /* Send the FETCH command */ if(imap->partial) - result = imap_sendf(conn, "UID FETCH %s BODY[%s]<%s>", - imap->uid, - imap->section ? imap->section : "", - imap->partial); + result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]<%s>", + imap->uid, imap->section ? imap->section : "", + imap->partial); else - result = imap_sendf(conn, "UID FETCH %s BODY[%s]", - imap->uid, - imap->section ? imap->section : ""); + result = imap_sendf(data, conn, "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(conn, "FETCH %s BODY[%s]<%s>", - imap->mindex, - imap->section ? imap->section : "", - imap->partial); + result = imap_sendf(data, conn, "FETCH %s BODY[%s]<%s>", + imap->mindex, imap->section ? imap->section : "", + imap->partial); else - result = imap_sendf(conn, "FETCH %s BODY[%s]", - imap->mindex, - imap->section ? imap->section : ""); + result = imap_sendf(data, conn, "FETCH %s BODY[%s]", + imap->mindex, imap->section ? imap->section : ""); } else { - failf(conn->data, "Cannot FETCH without a UID."); - return CURLE_URL_MALFORMAT; + failf(data, "Cannot FETCH without a UID."); + return CURLE_URL_MALFORMAT; } if(!result) - state(conn, IMAP_FETCH); + state(data, IMAP_FETCH); return result; } @@ -725,10 +736,10 @@ static CURLcode imap_perform_fetch(struct connectdata *conn) * * Sends an APPEND command to initiate the upload of a message. */ -static CURLcode imap_perform_append(struct connectdata *conn) +static CURLcode imap_perform_append(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct IMAP *imap = data->req.p.imap; char *mailbox; @@ -749,7 +760,7 @@ static CURLcode imap_perform_append(struct connectdata *conn) NULL, MIMESTRATEGY_MAIL); if(!result) - if(!Curl_checkheaders(conn, "Mime-Version")) + if(!Curl_checkheaders(data, "Mime-Version")) result = Curl_mime_add_header(&data->set.mimepost.curlheaders, "Mime-Version: 1.0"); @@ -769,7 +780,7 @@ static CURLcode imap_perform_append(struct connectdata *conn) /* Check we know the size of the upload */ if(data->state.infilesize < 0) { - failf(data, "Cannot APPEND with unknown input file size\n"); + failf(data, "Cannot APPEND with unknown input file size"); return CURLE_UPLOAD_FAILED; } @@ -779,13 +790,14 @@ static CURLcode imap_perform_append(struct connectdata *conn) return CURLE_OUT_OF_MEMORY; /* Send the APPEND command */ - result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}", + result = imap_sendf(data, conn, + "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}", mailbox, data->state.infilesize); free(mailbox); if(!result) - state(conn, IMAP_APPEND); + state(data, IMAP_APPEND); return result; } @@ -796,22 +808,23 @@ static CURLcode imap_perform_append(struct connectdata *conn) * * Sends a SEARCH command. */ -static CURLcode imap_perform_search(struct connectdata *conn) +static CURLcode imap_perform_search(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; - struct IMAP *imap = conn->data->req.p.imap; + struct IMAP *imap = data->req.p.imap; /* Check we have a query string */ if(!imap->query) { - failf(conn->data, "Cannot SEARCH without a query string."); + failf(data, "Cannot SEARCH without a query string."); return CURLE_URL_MALFORMAT; } /* Send the SEARCH command */ - result = imap_sendf(conn, "SEARCH %s", imap->query); + result = imap_sendf(data, conn, "SEARCH %s", imap->query); if(!result) - state(conn, IMAP_SEARCH); + state(data, IMAP_SEARCH); return result; } @@ -822,23 +835,24 @@ static CURLcode imap_perform_search(struct connectdata *conn) * * Performs the logout action prior to sclose() being called. */ -static CURLcode imap_perform_logout(struct connectdata *conn) +static CURLcode imap_perform_logout(struct Curl_easy *data, + struct connectdata *conn) { /* Send the LOGOUT command */ - CURLcode result = imap_sendf(conn, "LOGOUT"); + CURLcode result = imap_sendf(data, conn, "LOGOUT"); if(!result) - state(conn, IMAP_LOGOUT); + state(data, IMAP_LOGOUT); return result; } /* For the initial server greeting */ -static CURLcode imap_state_servergreet_resp(struct connectdata *conn, +static CURLcode imap_state_servergreet_resp(struct Curl_easy *data, int imapcode, imapstate instate) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; (void)instate; /* no use for this yet */ if(imapcode == IMAP_RESP_PREAUTH) { @@ -852,16 +866,16 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn, return CURLE_WEIRD_SERVER_REPLY; } - return imap_perform_capability(conn); + return imap_perform_capability(data, conn); } /* For CAPABILITY responses */ -static CURLcode imap_state_capability_resp(struct connectdata *conn, +static CURLcode imap_state_capability_resp(struct Curl_easy *data, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct imap_conn *imapc = &conn->proto.imapc; const char *line = data->state.buffer; @@ -924,31 +938,31 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn, /* 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(conn); + result = imap_perform_starttls(data, conn); else if(data->set.use_ssl == CURLUSESSL_TRY) /* Fallback and carry on with authentication */ - result = imap_perform_authentication(conn); + result = imap_perform_authentication(data, conn); else { failf(data, "STARTTLS not supported."); result = CURLE_USE_SSL_FAILED; } } else - result = imap_perform_authentication(conn); + result = imap_perform_authentication(data, conn); } else - result = imap_perform_authentication(conn); + result = imap_perform_authentication(data, conn); return result; } /* For STARTTLS responses */ -static CURLcode imap_state_starttls_resp(struct connectdata *conn, +static CURLcode imap_state_starttls_resp(struct Curl_easy *data, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; (void)instate; /* no use for this yet */ @@ -958,36 +972,36 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn, result = CURLE_USE_SSL_FAILED; } else - result = imap_perform_authentication(conn); + result = imap_perform_authentication(data, conn); } else - result = imap_perform_upgrade_tls(conn); + result = imap_perform_upgrade_tls(data, conn); return result; } /* For SASL authentication responses */ -static CURLcode imap_state_auth_resp(struct connectdata *conn, +static CURLcode imap_state_auth_resp(struct Curl_easy *data, + struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct imap_conn *imapc = &conn->proto.imapc; saslprogress progress; (void)instate; /* no use for this yet */ - result = Curl_sasl_continue(&imapc->sasl, conn, imapcode, &progress); + result = Curl_sasl_continue(&imapc->sasl, data, conn, imapcode, &progress); if(!result) switch(progress) { case SASL_DONE: - state(conn, IMAP_STOP); /* Authenticated */ + state(data, IMAP_STOP); /* Authenticated */ break; case SASL_IDLE: /* No mechanism left after cancellation */ if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) /* Perform clear text authentication */ - result = imap_perform_login(conn); + result = imap_perform_login(data, conn); else { failf(data, "Authentication cancelled"); result = CURLE_LOGIN_DENIED; @@ -1001,13 +1015,11 @@ static CURLcode imap_state_auth_resp(struct connectdata *conn, } /* For LOGIN responses */ -static CURLcode imap_state_login_resp(struct connectdata *conn, +static CURLcode imap_state_login_resp(struct Curl_easy *data, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(imapcode != IMAP_RESP_OK) { @@ -1016,18 +1028,18 @@ static CURLcode imap_state_login_resp(struct connectdata *conn, } else /* End of connect phase */ - state(conn, IMAP_STOP); + state(data, IMAP_STOP); return result; } /* For LIST and SEARCH responses */ -static CURLcode imap_state_listsearch_resp(struct connectdata *conn, +static CURLcode imap_state_listsearch_resp(struct Curl_easy *data, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - char *line = conn->data->state.buffer; + char *line = data->state.buffer; size_t len = strlen(line); (void)instate; /* No use for this yet */ @@ -1035,25 +1047,25 @@ static CURLcode imap_state_listsearch_resp(struct connectdata *conn, if(imapcode == '*') { /* Temporarily add the LF character back and send as body to the client */ line[len] = '\n'; - result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); + result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1); line[len] = '\0'; } else if(imapcode != IMAP_RESP_OK) result = CURLE_QUOTE_ERROR; else /* End of DO phase */ - state(conn, IMAP_STOP); + state(data, IMAP_STOP); return result; } /* For SELECT responses */ -static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, +static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - struct IMAP *imap = conn->data->req.p.imap; + struct connectdata *conn = data->conn; + struct IMAP *imap = data->req.p.imap; struct imap_conn *imapc = &conn->proto.imapc; const char *line = data->state.buffer; @@ -1071,7 +1083,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, /* Check if the UIDVALIDITY has been specified and matches */ if(imap->uidvalidity && imapc->mailbox_uidvalidity && !strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity)) { - failf(conn->data, "Mailbox UIDVALIDITY has changed"); + failf(data, "Mailbox UIDVALIDITY has changed"); result = CURLE_REMOTE_FILE_NOT_FOUND; } else { @@ -1079,11 +1091,11 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, imapc->mailbox = strdup(imap->mailbox); if(imap->custom) - result = imap_perform_list(conn); + result = imap_perform_list(data); else if(imap->query) - result = imap_perform_search(conn); + result = imap_perform_search(data, conn); else - result = imap_perform_fetch(conn); + result = imap_perform_fetch(data, conn); } } else { @@ -1095,11 +1107,11 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, } /* For the (first line of the) FETCH responses */ -static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, +static CURLcode imap_state_fetch_resp(struct Curl_easy *data, + struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct imap_conn *imapc = &conn->proto.imapc; struct pingpong *pp = &imapc->pp; const char *ptr = data->state.buffer; @@ -1110,7 +1122,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, if(imapcode != '*') { Curl_pgrsSetDownloadSize(data, -1); - state(conn, IMAP_STOP); + state(data, IMAP_STOP); return CURLE_REMOTE_FILE_NOT_FOUND; } @@ -1145,10 +1157,10 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, if(!chunk) { /* no size, we're done with the data */ - state(conn, IMAP_STOP); + state(data, IMAP_STOP); return CURLE_OK; } - result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk); + result = Curl_client_write(data, CLIENTWRITE_BODY, pp->cache, chunk); if(result) return result; @@ -1186,18 +1198,18 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, } else { /* We don't know how to parse this line */ - failf(pp->conn->data, "Failed to parse FETCH response."); + failf(data, "Failed to parse FETCH response."); result = CURLE_WEIRD_SERVER_REPLY; } /* End of DO phase */ - state(conn, IMAP_STOP); + state(data, IMAP_STOP); return result; } /* For final FETCH responses performed after the download */ -static CURLcode imap_state_fetch_final_resp(struct connectdata *conn, +static CURLcode imap_state_fetch_final_resp(struct Curl_easy *data, int imapcode, imapstate instate) { @@ -1209,18 +1221,16 @@ static CURLcode imap_state_fetch_final_resp(struct connectdata *conn, result = CURLE_WEIRD_SERVER_REPLY; else /* End of DONE phase */ - state(conn, IMAP_STOP); + state(data, IMAP_STOP); return result; } /* For APPEND responses */ -static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode, +static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* No use for this yet */ if(imapcode != '+') { @@ -1234,14 +1244,14 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode, Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* End of DO phase */ - state(conn, IMAP_STOP); + state(data, IMAP_STOP); } return result; } /* For final APPEND responses performed after the upload */ -static CURLcode imap_state_append_final_resp(struct connectdata *conn, +static CURLcode imap_state_append_final_resp(struct Curl_easy *data, int imapcode, imapstate instate) { @@ -1253,12 +1263,13 @@ static CURLcode imap_state_append_final_resp(struct connectdata *conn, result = CURLE_UPLOAD_FAILED; else /* End of DONE phase */ - state(conn, IMAP_STOP); + state(data, IMAP_STOP); return result; } -static CURLcode imap_statemach_act(struct connectdata *conn) +static CURLcode imap_statemachine(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; curl_socket_t sock = conn->sock[FIRSTSOCKET]; @@ -1266,18 +1277,19 @@ static CURLcode imap_statemach_act(struct connectdata *conn) struct imap_conn *imapc = &conn->proto.imapc; struct pingpong *pp = &imapc->pp; size_t nread = 0; + (void)data; /* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */ if(imapc->state == IMAP_UPGRADETLS) - return imap_perform_upgrade_tls(conn); + return imap_perform_upgrade_tls(data, conn); /* Flush any data that needs to be sent */ if(pp->sendleft) - return Curl_pp_flushsend(pp); + return Curl_pp_flushsend(data, pp); do { /* Read the response from the server */ - result = Curl_pp_readresp(sock, pp, &imapcode, &nread); + result = Curl_pp_readresp(data, sock, pp, &imapcode, &nread); if(result) return result; @@ -1291,55 +1303,55 @@ static CURLcode imap_statemach_act(struct connectdata *conn) /* We have now received a full IMAP server response */ switch(imapc->state) { case IMAP_SERVERGREET: - result = imap_state_servergreet_resp(conn, imapcode, imapc->state); + result = imap_state_servergreet_resp(data, imapcode, imapc->state); break; case IMAP_CAPABILITY: - result = imap_state_capability_resp(conn, imapcode, imapc->state); + result = imap_state_capability_resp(data, imapcode, imapc->state); break; case IMAP_STARTTLS: - result = imap_state_starttls_resp(conn, imapcode, imapc->state); + result = imap_state_starttls_resp(data, imapcode, imapc->state); break; case IMAP_AUTHENTICATE: - result = imap_state_auth_resp(conn, imapcode, imapc->state); + result = imap_state_auth_resp(data, conn, imapcode, imapc->state); break; case IMAP_LOGIN: - result = imap_state_login_resp(conn, imapcode, imapc->state); + result = imap_state_login_resp(data, imapcode, imapc->state); break; case IMAP_LIST: case IMAP_SEARCH: - result = imap_state_listsearch_resp(conn, imapcode, imapc->state); + result = imap_state_listsearch_resp(data, imapcode, imapc->state); break; case IMAP_SELECT: - result = imap_state_select_resp(conn, imapcode, imapc->state); + result = imap_state_select_resp(data, imapcode, imapc->state); break; case IMAP_FETCH: - result = imap_state_fetch_resp(conn, imapcode, imapc->state); + result = imap_state_fetch_resp(data, conn, imapcode, imapc->state); break; case IMAP_FETCH_FINAL: - result = imap_state_fetch_final_resp(conn, imapcode, imapc->state); + result = imap_state_fetch_final_resp(data, imapcode, imapc->state); break; case IMAP_APPEND: - result = imap_state_append_resp(conn, imapcode, imapc->state); + result = imap_state_append_resp(data, imapcode, imapc->state); break; case IMAP_APPEND_FINAL: - result = imap_state_append_final_resp(conn, imapcode, imapc->state); + result = imap_state_append_final_resp(data, imapcode, imapc->state); break; case IMAP_LOGOUT: /* fallthrough, just stop! */ default: /* internal error */ - state(conn, IMAP_STOP); + state(data, IMAP_STOP); break; } } while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp)); @@ -1348,41 +1360,43 @@ static CURLcode imap_statemach_act(struct connectdata *conn) } /* Called repeatedly until done from multi.c */ -static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done) +static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct imap_conn *imapc = &conn->proto.imapc; if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) { - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); + result = Curl_ssl_connect_nonblocking(data, conn, + FIRSTSOCKET, &imapc->ssldone); if(result || !imapc->ssldone) return result; } - result = Curl_pp_statemach(&imapc->pp, FALSE, FALSE); + result = Curl_pp_statemach(data, &imapc->pp, FALSE, FALSE); *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE; return result; } -static CURLcode imap_block_statemach(struct connectdata *conn, +static CURLcode imap_block_statemach(struct Curl_easy *data, + struct connectdata *conn, bool disconnecting) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; while(imapc->state != IMAP_STOP && !result) - result = Curl_pp_statemach(&imapc->pp, TRUE, disconnecting); + result = Curl_pp_statemach(data, &imapc->pp, TRUE, disconnecting); return result; } /* Allocate and initialize the struct IMAP for the current Curl_easy if required */ -static CURLcode imap_init(struct connectdata *conn) +static CURLcode imap_init(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct IMAP *imap; imap = data->req.p.imap = calloc(sizeof(struct IMAP), 1); @@ -1393,9 +1407,11 @@ static CURLcode imap_init(struct connectdata *conn) } /* For the IMAP "protocol connect" and "doing" phases only */ -static int imap_getsock(struct connectdata *conn, curl_socket_t *socks) +static int imap_getsock(struct Curl_easy *data, + struct connectdata *conn, + curl_socket_t *socks) { - return Curl_pp_getsock(&conn->proto.imapc.pp, socks); + return Curl_pp_getsock(data, &conn->proto.imapc.pp, socks); } /*********************************************************************** @@ -1408,9 +1424,10 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks) * The variable 'done' points to will be TRUE if the protocol-layer connect * phase is done when this function returns, or FALSE if not. */ -static CURLcode imap_connect(struct connectdata *conn, bool *done) +static CURLcode imap_connect(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct imap_conn *imapc = &conn->proto.imapc; struct pingpong *pp = &imapc->pp; @@ -1419,11 +1436,7 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done) /* We always support persistent connections in IMAP */ connkeep(conn, "IMAP default"); - /* Set the default response time-out */ - pp->response_time = RESP_TIMEOUT; - pp->statemach_act = imap_statemach_act; - pp->endofresp = imap_endofresp; - pp->conn = conn; + PINGPONG_SETUP(pp, imap_statemachine, imap_endofresp); /* Set the default preferred authentication type and mechanism */ imapc->preftype = IMAP_TYPE_ANY; @@ -1432,7 +1445,7 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done) Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD); /* Initialise the pingpong layer */ Curl_pp_setup(pp); - Curl_pp_init(pp); + Curl_pp_init(data, pp); /* Parse the URL options */ result = imap_parse_url_options(conn); @@ -1440,12 +1453,12 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done) return result; /* Start off waiting for the server greeting response */ - state(conn, IMAP_SERVERGREET); + state(data, IMAP_SERVERGREET); /* Start off with an response id of '*' */ strcpy(imapc->resptag, "*"); - result = imap_multi_statemach(conn, done); + result = imap_multi_statemach(data, done); return result; } @@ -1459,11 +1472,11 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done) * * Input argument is already checked for validity. */ -static CURLcode imap_done(struct connectdata *conn, CURLcode status, +static CURLcode imap_done(struct Curl_easy *data, CURLcode status, bool premature) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct IMAP *imap = data->req.p.imap; (void)premature; @@ -1481,17 +1494,17 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status, /* Handle responses after FETCH or APPEND transfer has finished */ if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE) - state(conn, IMAP_FETCH_FINAL); + state(data, IMAP_FETCH_FINAL); else { /* End the APPEND command first by sending an empty line */ - result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", ""); + result = Curl_pp_sendf(data, &conn->proto.imapc.pp, "%s", ""); if(!result) - state(conn, IMAP_APPEND_FINAL); + state(data, IMAP_APPEND_FINAL); } /* Run the state-machine */ if(!result) - result = imap_block_statemach(conn, FALSE); + result = imap_block_statemach(data, conn, FALSE); } /* Cleanup our per-request based variables */ @@ -1518,19 +1531,19 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status, * This is the actual DO function for IMAP. Fetch or append a message, or do * other things according to the options previously setup. */ -static CURLcode imap_perform(struct connectdata *conn, bool *connected, +static CURLcode imap_perform(struct Curl_easy *data, bool *connected, bool *dophase_done) { /* This is IMAP and no proxy */ CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct IMAP *imap = data->req.p.imap; struct imap_conn *imapc = &conn->proto.imapc; bool selected = FALSE; - DEBUGF(infof(conn->data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts\n")); - if(conn->data->set.opt_no_body) { + if(data->set.opt_no_body) { /* Requested no body means no transfer */ imap->transfer = FTPTRANSFER_INFO; } @@ -1546,36 +1559,36 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected, selected = TRUE; /* Start the first command in the DO phase */ - if(conn->data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE) + if(data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE) /* APPEND can be executed directly */ - result = imap_perform_append(conn); + result = imap_perform_append(data); else if(imap->custom && (selected || !imap->mailbox)) /* Custom command using the same mailbox or no mailbox */ - result = imap_perform_list(conn); + result = imap_perform_list(data); else if(!imap->custom && selected && (imap->uid || imap->mindex)) /* FETCH from the same mailbox */ - result = imap_perform_fetch(conn); + result = imap_perform_fetch(data, conn); else if(!imap->custom && selected && imap->query) /* SEARCH the current mailbox */ - result = imap_perform_search(conn); + result = imap_perform_search(data, conn); else if(imap->mailbox && !selected && (imap->custom || imap->uid || imap->mindex || imap->query)) /* SELECT the mailbox */ - result = imap_perform_select(conn); + result = imap_perform_select(data); else /* LIST */ - result = imap_perform_list(conn); + result = imap_perform_list(data); if(result) return result; /* Run the state-machine */ - result = imap_multi_statemach(conn, dophase_done); + result = imap_multi_statemach(data, dophase_done); *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); return result; } @@ -1589,23 +1602,22 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected, * * The input argument is already checked for validity. */ -static CURLcode imap_do(struct connectdata *conn, bool *done) +static CURLcode imap_do(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; - *done = FALSE; /* default to false */ /* Parse the URL path */ - result = imap_parse_url_path(conn); + result = imap_parse_url_path(data); if(result) return result; /* Parse the custom request */ - result = imap_parse_custom_request(conn); + result = imap_parse_custom_request(data); if(result) return result; - result = imap_regular_transfer(conn, done); + result = imap_regular_transfer(data, done); return result; } @@ -1617,9 +1629,11 @@ static CURLcode imap_do(struct connectdata *conn, bool *done) * Disconnect from an IMAP server. Cleanup protocol-specific per-connection * resources. BLOCKING. */ -static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode imap_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { struct imap_conn *imapc = &conn->proto.imapc; + (void)data; /* We cannot send quit unconditionally. If this connection is stale or bad in any way, sending quit and waiting around here will make the @@ -1627,9 +1641,10 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) /* The IMAP session may or may not have been allocated/setup at this point! */ - if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart) - if(!imap_perform_logout(conn)) - (void)imap_block_statemach(conn, TRUE); /* ignore errors on LOGOUT */ + if(!dead_connection && conn->bits.protoconnstart) { + if(!imap_perform_logout(data, conn)) + (void)imap_block_statemach(data, conn, TRUE); /* ignore errors */ + } /* Disconnect from the server */ Curl_pp_disconnect(&imapc->pp); @@ -1646,30 +1661,30 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) } /* Call this when the DO phase has completed */ -static CURLcode imap_dophase_done(struct connectdata *conn, bool connected) +static CURLcode imap_dophase_done(struct Curl_easy *data, bool connected) { - struct IMAP *imap = conn->data->req.p.imap; + struct IMAP *imap = data->req.p.imap; (void)connected; if(imap->transfer != FTPTRANSFER_BODY) /* no data to transfer */ - Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); + Curl_setup_transfer(data, -1, -1, FALSE, -1); return CURLE_OK; } /* Called from multi.c while DOing */ -static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done) +static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done) { - CURLcode result = imap_multi_statemach(conn, dophase_done); + CURLcode result = imap_multi_statemach(data, dophase_done); if(result) - DEBUGF(infof(conn->data, "DO phase failed\n")); + DEBUGF(infof(data, "DO phase failed\n")); else if(*dophase_done) { - result = imap_dophase_done(conn, FALSE /* not connected */); + result = imap_dophase_done(data, FALSE /* not connected */); - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; @@ -1684,12 +1699,11 @@ static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done) * Performs all commands done before a regular transfer between a local and a * remote host. */ -static CURLcode imap_regular_transfer(struct connectdata *conn, +static CURLcode imap_regular_transfer(struct Curl_easy *data, bool *dophase_done) { CURLcode result = CURLE_OK; bool connected = FALSE; - struct Curl_easy *data = conn->data; /* Make sure size is unknown at this point */ data->req.size = -1; @@ -1701,19 +1715,20 @@ static CURLcode imap_regular_transfer(struct connectdata *conn, Curl_pgrsSetDownloadSize(data, -1); /* Carry out the perform */ - result = imap_perform(conn, &connected, dophase_done); + result = imap_perform(data, &connected, dophase_done); /* Perform post DO phase operations if necessary */ if(!result && *dophase_done) - result = imap_dophase_done(conn, connected); + result = imap_dophase_done(data, connected); return result; } -static CURLcode imap_setup_connection(struct connectdata *conn) +static CURLcode imap_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { /* Initialise the IMAP layer */ - CURLcode result = imap_init(conn); + CURLcode result = imap_init(data); if(result) return result; @@ -1731,7 +1746,8 @@ static CURLcode imap_setup_connection(struct connectdata *conn) * * Designed to never block. */ -static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...) +static CURLcode imap_sendf(struct Curl_easy *data, + struct connectdata *conn, const char *fmt, ...) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; @@ -1751,7 +1767,7 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...) if(!result) { va_list ap; va_start(ap, fmt); - result = Curl_pp_vsendf(&imapc->pp, Curl_dyn_ptr(&imapc->dyn), ap); + result = Curl_pp_vsendf(data, &imapc->pp, Curl_dyn_ptr(&imapc->dyn), ap); va_end(ap); } return result; @@ -1940,11 +1956,10 @@ static CURLcode imap_parse_url_options(struct connectdata *conn) * Parse the URL path into separate path components. * */ -static CURLcode imap_parse_url_path(struct connectdata *conn) +static CURLcode imap_parse_url_path(struct Curl_easy *data) { /* The imap struct is already initialised in imap_connect() */ CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct IMAP *imap = data->req.p.imap; const char *begin = &data->state.up.path[1]; /* skip leading slash */ const char *ptr = begin; @@ -2000,7 +2015,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn) return result; } - DEBUGF(infof(conn->data, "IMAP URL parameter '%s' = '%s'\n", name, value)); + DEBUGF(infof(data, "IMAP URL parameter '%s' = '%s'\n", name, value)); /* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and PARTIAL) stripping of the trailing slash character if it is present. @@ -2073,10 +2088,9 @@ static CURLcode imap_parse_url_path(struct connectdata *conn) * * Parse the custom request. */ -static CURLcode imap_parse_custom_request(struct connectdata *conn) +static CURLcode imap_parse_custom_request(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct IMAP *imap = data->req.p.imap; const char *custom = data->set.str[STRING_CUSTOMREQUEST]; diff --git a/libs/libcurl/src/krb5.c b/libs/libcurl/src/krb5.c index 66394f4f30..eb83566d6b 100644 --- a/libs/libcurl/src/krb5.c +++ b/libs/libcurl/src/krb5.c @@ -2,7 +2,7 @@ * * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). - * Copyright (c) 2004 - 2020 Daniel Stenberg + * Copyright (c) 2004 - 2021 Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,7 +56,8 @@ #include "curl_memory.h" #include "memdebug.h" -static CURLcode ftpsend(struct connectdata *conn, const char *cmd) +static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn, + const char *cmd) { ssize_t bytes_written; #define SBUF_SIZE 1024 @@ -80,7 +81,7 @@ static CURLcode ftpsend(struct connectdata *conn, const char *cmd) write_len += 2; bytes_written = 0; - result = Curl_convert_to_network(conn->data, s, write_len); + result = Curl_convert_to_network(data, s, write_len); /* Curl_convert_to_network calls failf if unsuccessful */ if(result) return result; @@ -89,7 +90,7 @@ static CURLcode ftpsend(struct connectdata *conn, const char *cmd) #ifdef HAVE_GSSAPI conn->data_prot = PROT_CMD; #endif - result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, + result = Curl_write(data, conn->sock[FIRSTSOCKET], sptr, write_len, &bytes_written); #ifdef HAVE_GSSAPI DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); @@ -99,7 +100,7 @@ static CURLcode ftpsend(struct connectdata *conn, const char *cmd) if(result) break; - Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written); + Curl_debug(data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written); if(bytes_written != (ssize_t)write_len) { write_len -= bytes_written; @@ -202,14 +203,13 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to) } static int -krb5_auth(void *app_data, struct connectdata *conn) +krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn) { int ret = AUTH_OK; char *p; const char *host = conn->host.name; ssize_t nread; curl_socklen_t l = sizeof(conn->local_addr); - struct Curl_easy *data = conn->data; CURLcode result; const char *service = data->set.str[STRING_SERVICE_NAME] ? data->set.str[STRING_SERVICE_NAME] : @@ -242,11 +242,11 @@ krb5_auth(void *app_data, struct connectdata *conn) for(;;) { /* this really shouldn't be repeated here, but can't help it */ if(service == srv_host) { - result = ftpsend(conn, "AUTH GSSAPI"); + result = ftpsend(data, conn, "AUTH GSSAPI"); if(result) return -2; - if(Curl_GetFTPResponse(&nread, conn, NULL)) + if(Curl_GetFTPResponse(data, &nread, NULL)) return -1; if(data->state.buffer[0] != '3') @@ -319,7 +319,7 @@ krb5_auth(void *app_data, struct connectdata *conn) cmd = aprintf("ADAT %s", p); if(cmd) - result = ftpsend(conn, cmd); + result = ftpsend(data, conn, cmd); else result = CURLE_OUT_OF_MEMORY; @@ -331,7 +331,7 @@ krb5_auth(void *app_data, struct connectdata *conn) break; } - if(Curl_GetFTPResponse(&nread, conn, NULL)) { + if(Curl_GetFTPResponse(data, &nread, NULL)) { ret = -1; break; } @@ -443,7 +443,7 @@ static char level_to_char(int level) /* Send an FTP command defined by |message| and the optional arguments. The function returns the ftp_code. If an error occurs, -1 is returned. */ -static int ftp_send_command(struct connectdata *conn, const char *message, ...) +static int ftp_send_command(struct Curl_easy *data, const char *message, ...) { int ftp_code; ssize_t nread = 0; @@ -454,11 +454,11 @@ static int ftp_send_command(struct connectdata *conn, const char *message, ...) mvsnprintf(print_buffer, sizeof(print_buffer), message, args); va_end(args); - if(ftpsend(conn, print_buffer)) { + if(ftpsend(data, data->conn, print_buffer)) { ftp_code = -1; } else { - if(Curl_GetFTPResponse(&nread, conn, &ftp_code)) + if(Curl_GetFTPResponse(data, &nread, &ftp_code)) ftp_code = -1; } @@ -495,7 +495,7 @@ socket_read(curl_socket_t fd, void *to, size_t len) CURLcode saying whether an error occurred or CURLE_OK if |len| was written. */ static CURLcode -socket_write(struct connectdata *conn, curl_socket_t fd, const void *to, +socket_write(struct Curl_easy *data, curl_socket_t fd, const void *to, size_t len) { const char *to_p = to; @@ -503,7 +503,7 @@ socket_write(struct connectdata *conn, curl_socket_t fd, const void *to, ssize_t written; while(len > 0) { - result = Curl_write_plain(conn, fd, to_p, len, &written); + result = Curl_write_plain(data, fd, to_p, len, &written); if(!result) { len -= written; to_p += written; @@ -556,18 +556,19 @@ buffer_read(struct krb5buffer *buf, void *data, size_t len) } /* Matches Curl_recv signature */ -static ssize_t sec_recv(struct connectdata *conn, int sockindex, +static ssize_t sec_recv(struct Curl_easy *data, int sockindex, char *buffer, size_t len, CURLcode *err) { size_t bytes_read; size_t total_read = 0; + struct connectdata *conn = data->conn; curl_socket_t fd = conn->sock[sockindex]; *err = CURLE_OK; /* Handle clear text response. */ if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR) - return sread(fd, buffer, len); + return sread(fd, buffer, len); if(conn->in_buffer.eof_flag) { conn->in_buffer.eof_flag = 0; @@ -597,8 +598,8 @@ static ssize_t sec_recv(struct connectdata *conn, int sockindex, /* Send |length| bytes from |from| to the |fd| socket taking care of encoding and negotiating with the server. |from| can be NULL. */ -static void do_sec_send(struct connectdata *conn, curl_socket_t fd, - const char *from, int length) +static void do_sec_send(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t fd, const char *from, int length) { int bytes, htonl_bytes; /* 32-bit integers for htonl */ char *buffer = NULL; @@ -622,7 +623,7 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd, return; /* error */ if(iscmd) { - error = Curl_base64_encode(conn->data, buffer, curlx_sitouz(bytes), + error = Curl_base64_encode(data, buffer, curlx_sitouz(bytes), &cmd_buffer, &cmd_size); if(error) { free(buffer); @@ -632,27 +633,27 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd, static const char *enc = "ENC "; static const char *mic = "MIC "; if(prot_level == PROT_PRIVATE) - socket_write(conn, fd, enc, 4); + socket_write(data, fd, enc, 4); else - socket_write(conn, fd, mic, 4); + socket_write(data, fd, mic, 4); - socket_write(conn, fd, cmd_buffer, cmd_size); - socket_write(conn, fd, "\r\n", 2); - infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic, + socket_write(data, fd, cmd_buffer, cmd_size); + socket_write(data, fd, "\r\n", 2); + infof(data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic, cmd_buffer); free(cmd_buffer); } } else { htonl_bytes = htonl(bytes); - socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes)); - socket_write(conn, fd, buffer, curlx_sitouz(bytes)); + socket_write(data, fd, &htonl_bytes, sizeof(htonl_bytes)); + socket_write(data, fd, buffer, curlx_sitouz(bytes)); } free(buffer); } -static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd, - const char *buffer, size_t length) +static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t fd, const char *buffer, size_t length) { ssize_t tx = 0, len = conn->buffer_size; @@ -664,7 +665,7 @@ static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd, if(length < (size_t)len) len = length; - do_sec_send(conn, fd, buffer, curlx_sztosi(len)); + do_sec_send(data, conn, fd, buffer, curlx_sztosi(len)); length -= len; buffer += len; tx += len; @@ -673,16 +674,17 @@ static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd, } /* Matches Curl_send signature */ -static ssize_t sec_send(struct connectdata *conn, int sockindex, +static ssize_t sec_send(struct Curl_easy *data, int sockindex, const void *buffer, size_t len, CURLcode *err) { + struct connectdata *conn = data->conn; curl_socket_t fd = conn->sock[sockindex]; *err = CURLE_OK; - return sec_write(conn, fd, buffer, len); + return sec_write(data, conn, fd, buffer, len); } -int Curl_sec_read_msg(struct connectdata *conn, char *buffer, - enum protection_level level) +int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, + char *buffer, enum protection_level level) { /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an int */ @@ -692,6 +694,8 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer, size_t decoded_sz = 0; CURLcode error; + (void) data; + if(!conn->mech) /* not inititalized, return error */ return -1; @@ -717,7 +721,7 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer, { buf[decoded_len] = '\n'; - Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1); + Curl_debug(data, CURLINFO_HEADER_IN, buf, decoded_len + 1); } buf[decoded_len] = '\0'; @@ -736,16 +740,17 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer, return ret_code; } -static int sec_set_protection_level(struct connectdata *conn) +static int sec_set_protection_level(struct Curl_easy *data) { int code; + struct connectdata *conn = data->conn; enum protection_level level = conn->request_data_prot; DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); if(!conn->sec_complete) { - infof(conn->data, "Trying to change the protection level after the" - " completion of the data exchange.\n"); + infof(data, "Trying to change the protection level after the" + " completion of the data exchange.\n"); return -1; } @@ -757,17 +762,17 @@ static int sec_set_protection_level(struct connectdata *conn) char *pbsz; static unsigned int buffer_size = 1 << 20; /* 1048576 */ - code = ftp_send_command(conn, "PBSZ %u", buffer_size); + code = ftp_send_command(data, "PBSZ %u", buffer_size); if(code < 0) return -1; if(code/100 != 2) { - failf(conn->data, "Failed to set the protection's buffer size."); + failf(data, "Failed to set the protection's buffer size."); return -1; } conn->buffer_size = buffer_size; - pbsz = strstr(conn->data->state.buffer, "PBSZ="); + pbsz = strstr(data->state.buffer, "PBSZ="); if(pbsz) { /* ignore return code, use default value if it fails */ (void)sscanf(pbsz, "PBSZ=%u", &buffer_size); @@ -777,13 +782,13 @@ static int sec_set_protection_level(struct connectdata *conn) } /* Now try to negiociate the protection level. */ - code = ftp_send_command(conn, "PROT %c", level_to_char(level)); + code = ftp_send_command(data, "PROT %c", level_to_char(level)); if(code < 0) return -1; if(code/100 != 2) { - failf(conn->data, "Failed to set the protection level."); + failf(data, "Failed to set the protection level."); return -1; } @@ -805,10 +810,9 @@ Curl_sec_request_prot(struct connectdata *conn, const char *level) return 0; } -static CURLcode choose_mech(struct connectdata *conn) +static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn) { int ret; - struct Curl_easy *data = conn->data; void *tmp_allocation; const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech; @@ -830,7 +834,7 @@ static CURLcode choose_mech(struct connectdata *conn) } infof(data, "Trying mechanism %s...\n", mech->name); - ret = ftp_send_command(conn, "AUTH %s", mech->name); + ret = ftp_send_command(data, "AUTH %s", mech->name); if(ret < 0) return CURLE_COULDNT_CONNECT; @@ -855,7 +859,7 @@ static CURLcode choose_mech(struct connectdata *conn) } /* Authenticate */ - ret = mech->auth(conn->app_data, conn); + ret = mech->auth(conn->app_data, data, conn); if(ret != AUTH_CONTINUE) { if(ret != AUTH_OK) { @@ -873,16 +877,16 @@ static CURLcode choose_mech(struct connectdata *conn) conn->command_prot = PROT_SAFE; /* Set the requested protection level */ /* BLOCKING */ - (void)sec_set_protection_level(conn); + (void)sec_set_protection_level(data); } return CURLE_OK; } CURLcode -Curl_sec_login(struct connectdata *conn) +Curl_sec_login(struct Curl_easy *data, struct connectdata *conn) { - return choose_mech(conn); + return choose_mech(data, conn); } diff --git a/libs/libcurl/src/ldap.c b/libs/libcurl/src/ldap.c index 0a1f02d5b4..307ebebafd 100644 --- a/libs/libcurl/src/ldap.c +++ b/libs/libcurl/src/ldap.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -100,7 +100,8 @@ struct ldap_urldesc { #undef LDAPURLDesc #define LDAPURLDesc struct ldap_urldesc -static int _ldap_url_parse(const struct connectdata *conn, +static int _ldap_url_parse(struct Curl_easy *data, + const struct connectdata *conn, LDAPURLDesc **ludp); static void _ldap_free_urldesc(LDAPURLDesc *ludp); @@ -126,7 +127,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp); #endif -static CURLcode Curl_ldap(struct connectdata *conn, bool *done); +static CURLcode ldap_do(struct Curl_easy *data, bool *done); /* * LDAP protocol handler. @@ -135,7 +136,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done); const struct Curl_handler Curl_handler_ldap = { "LDAP", /* scheme */ ZERO_NULL, /* setup_connection */ - Curl_ldap, /* do_it */ + ldap_do, /* do_it */ ZERO_NULL, /* done */ ZERO_NULL, /* do_more */ ZERO_NULL, /* connect_it */ @@ -162,7 +163,7 @@ const struct Curl_handler Curl_handler_ldap = { const struct Curl_handler Curl_handler_ldaps = { "LDAPS", /* scheme */ ZERO_NULL, /* setup_connection */ - Curl_ldap, /* do_it */ + ldap_do, /* do_it */ ZERO_NULL, /* done */ ZERO_NULL, /* do_more */ ZERO_NULL, /* connect_it */ @@ -232,7 +233,7 @@ static int ldap_win_bind_auth(LDAP *server, const char *user, } #endif /* #if defined(USE_WINDOWS_SSPI) */ -static int ldap_win_bind(struct connectdata *conn, LDAP *server, +static int ldap_win_bind(struct Curl_easy *data, LDAP *server, const char *user, const char *passwd) { int rc = LDAP_INVALID_CREDENTIALS; @@ -240,7 +241,7 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server, PTCHAR inuser = NULL; PTCHAR inpass = NULL; - if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) { + if(user && passwd && (data->set.httpauth & CURLAUTH_BASIC)) { inuser = curlx_convert_UTF8_to_tchar((char *) user); inpass = curlx_convert_UTF8_to_tchar((char *) passwd); @@ -251,7 +252,7 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server, } #if defined(USE_WINDOWS_SSPI) else { - rc = ldap_win_bind_auth(server, user, passwd, conn->data->set.httpauth); + rc = ldap_win_bind_auth(server, user, passwd, data->set.httpauth); } #endif @@ -266,7 +267,7 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server, #endif -static CURLcode Curl_ldap(struct connectdata *conn, bool *done) +static CURLcode ldap_do(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; int rc = 0; @@ -275,7 +276,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) LDAPMessage *ldapmsg = NULL; LDAPMessage *entryIterator; int num = 0; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; int ldap_proto = LDAP_VERSION3; int ldap_ssl = 0; char *val_b64 = NULL; @@ -300,7 +301,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) #ifdef HAVE_LDAP_URL_PARSE rc = ldap_url_parse(data->change.url, &ludp); #else - rc = _ldap_url_parse(conn, &ludp); + rc = _ldap_url_parse(data, conn, &ludp); #endif if(rc != 0) { failf(data, "LDAP local: %s", ldap_err2string(rc)); @@ -472,7 +473,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) } #ifdef USE_WIN32_LDAP ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); - rc = ldap_win_bind(conn, server, user, passwd); + rc = ldap_win_bind(data, server, user, passwd); #else rc = ldap_simple_bind_s(server, user, passwd); #endif @@ -480,7 +481,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) ldap_proto = LDAP_VERSION2; ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); #ifdef USE_WIN32_LDAP - rc = ldap_win_bind(conn, server, user, passwd); + rc = ldap_win_bind(data, server, user, passwd); #else rc = ldap_simple_bind_s(server, user, passwd); #endif @@ -536,14 +537,14 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) #endif name_len = strlen(name); - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4); if(result) { FREE_ON_WINLDAP(name); ldap_memfree(dn); goto quit; } - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name, + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) name, name_len); if(result) { FREE_ON_WINLDAP(name); @@ -551,7 +552,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) goto quit; } - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(result) { FREE_ON_WINLDAP(name); ldap_memfree(dn); @@ -589,7 +590,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) vals = ldap_get_values_len(server, entryIterator, attribute); if(vals != NULL) { for(i = 0; (vals[i] != NULL); i++) { - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1); if(result) { ldap_value_free_len(vals); FREE_ON_WINLDAP(attr); @@ -600,7 +601,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) goto quit; } - result = Curl_client_write(conn, CLIENTWRITE_BODY, + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) attr, attr_len); if(result) { ldap_value_free_len(vals); @@ -612,7 +613,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) goto quit; } - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2); if(result) { ldap_value_free_len(vals); FREE_ON_WINLDAP(attr); @@ -644,7 +645,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) } if(val_b64_sz > 0) { - result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, + result = Curl_client_write(data, CLIENTWRITE_BODY, val_b64, val_b64_sz); free(val_b64); if(result) { @@ -661,7 +662,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) } } else { - result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val, + result = Curl_client_write(data, CLIENTWRITE_BODY, vals[i]->bv_val, vals[i]->bv_len); if(result) { ldap_value_free_len(vals); @@ -676,7 +677,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) dlsize += vals[i]->bv_len; } - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(result) { ldap_value_free_len(vals); FREE_ON_WINLDAP(attr); @@ -698,7 +699,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) FREE_ON_WINLDAP(attr); ldap_memfree(attribute); - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(result) goto quit; dlsize++; @@ -812,14 +813,15 @@ static bool split_str(char *str, char ***out, size_t *count) * * already known from 'conn->host.name'. * already known from 'conn->remote_port'. - * extract the rest from 'conn->data->state.path+1'. All fields are optional. + * extract the rest from 'data->state.path+1'. All fields are optional. * e.g. * ldap://:/??? * yields ludp->lud_dn = "". * * Defined in RFC4516 section 2. */ -static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) +static int _ldap_url_parse2(struct Curl_easy *data, + const struct connectdata *conn, LDAPURLDesc *ludp) { int rc = LDAP_SUCCESS; char *p; @@ -828,10 +830,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) char *query = NULL; size_t i; - if(!conn->data || - !conn->data->state.up.path || - conn->data->state.up.path[0] != '/' || - !strncasecompare("LDAP", conn->data->state.up.scheme, 4)) + if(!data || + !data->state.up.path || + data->state.up.path[0] != '/' || + !strncasecompare("LDAP", data->state.up.scheme, 4)) return LDAP_INVALID_SYNTAX; ludp->lud_scope = LDAP_SCOPE_BASE; @@ -839,13 +841,13 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) ludp->lud_host = conn->host.name; /* Duplicate the path */ - p = path = strdup(conn->data->state.up.path + 1); + p = path = strdup(data->state.up.path + 1); if(!path) return LDAP_NO_MEMORY; /* Duplicate the query if present */ - if(conn->data->state.up.query) { - q = query = strdup(conn->data->state.up.query); + if(data->state.up.query) { + q = query = strdup(data->state.up.query); if(!query) { free(path); return LDAP_NO_MEMORY; @@ -861,7 +863,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) LDAP_TRACE(("DN '%s'\n", dn)); /* Unescape the DN */ - result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, REJECT_ZERO); + result = Curl_urldecode(data, dn, 0, &unescaped, NULL, REJECT_ZERO); if(result) { rc = LDAP_NO_MEMORY; @@ -926,7 +928,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) LDAP_TRACE(("attr[%zu] '%s'\n", i, attributes[i])); /* Unescape the attribute */ - result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL, + result = Curl_urldecode(data, attributes[i], 0, &unescaped, NULL, REJECT_ZERO); if(result) { free(attributes); @@ -996,8 +998,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) LDAP_TRACE(("filter '%s'\n", filter)); /* Unescape the filter */ - result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, - REJECT_ZERO); + result = Curl_urldecode(data, filter, 0, &unescaped, NULL, REJECT_ZERO); if(result) { rc = LDAP_NO_MEMORY; @@ -1035,7 +1036,8 @@ quit: return rc; } -static int _ldap_url_parse(const struct connectdata *conn, +static int _ldap_url_parse(struct Curl_easy *data, + const struct connectdata *conn, LDAPURLDesc **ludpp) { LDAPURLDesc *ludp = calloc(1, sizeof(*ludp)); @@ -1045,7 +1047,7 @@ static int _ldap_url_parse(const struct connectdata *conn, if(!ludp) return LDAP_NO_MEMORY; - rc = _ldap_url_parse2(conn, ludp); + rc = _ldap_url_parse2(data, conn, ludp); if(rc != LDAP_SUCCESS) { _ldap_free_urldesc(ludp); ludp = NULL; diff --git a/libs/libcurl/src/libcurl.plist b/libs/libcurl/src/libcurl.plist index cf5efc840a..bc332ad5d3 100644 --- a/libs/libcurl/src/libcurl.plist +++ b/libs/libcurl/src/libcurl.plist @@ -15,7 +15,7 @@ se.curl.libcurl CFBundleVersion - 7.74.0 + 7.75.0 CFBundleName libcurl @@ -27,9 +27,9 @@ ???? CFBundleShortVersionString - libcurl 7.74.0 + libcurl 7.75.0 CFBundleGetInfoString - libcurl.plist 7.74.0 + libcurl.plist 7.75.0 diff --git a/libs/libcurl/src/makefile.dj b/libs/libcurl/src/makefile.dj index 2b18ad6d54..ef1a24a7f5 100644 --- a/libs/libcurl/src/makefile.dj +++ b/libs/libcurl/src/makefile.dj @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 2003 - 2008, Gisle Vanem . +# Copyright (C) 2003 - 2021, Gisle Vanem . # Copyright (C) 2003 - 2020, Daniel Stenberg, , et al. # # This software is licensed as described in the file COPYING, which @@ -26,7 +26,7 @@ # DEPEND_PREREQ = curl_config.h -VPATH = vtls vauth +VPATH = vtls vauth vquic vssh TOPDIR = .. include ../packages/DOS/common.dj diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c index 2ddd9b8b98..abadcb02cb 100644 --- a/libs/libcurl/src/mime.c +++ b/libs/libcurl/src/mime.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1168,6 +1168,7 @@ static void cleanup_part_content(curl_mimepart *part) part->kind = MIMEKIND_NONE; part->flags &= ~MIME_FAST_READ; part->lastreadstatus = 1; /* Successful read status. */ + part->state.state = MIMESTATE_BEGIN; } static void mime_subparts_free(void *ptr) diff --git a/libs/libcurl/src/mime.h b/libs/libcurl/src/mime.h index ab89d52517..56642ae661 100644 --- a/libs/libcurl/src/mime.h +++ b/libs/libcurl/src/mime.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -110,6 +110,7 @@ struct curl_mimepart { curl_mime *parent; /* Parent mime structure. */ curl_mimepart *nextpart; /* Forward linked list. */ enum mimekind kind; /* The part kind. */ + unsigned int flags; /* Flags. */ char *data; /* Memory data or file name. */ curl_read_callback readfunc; /* Read function. */ curl_seek_callback seekfunc; /* Seek function. */ @@ -122,7 +123,6 @@ struct curl_mimepart { char *filename; /* Remote file name. */ char *name; /* Data name. */ curl_off_t datasize; /* Expected data size. */ - unsigned int flags; /* Flags. */ struct mime_state state; /* Current readback state. */ const struct mime_encoder *encoder; /* Content data encoder. */ struct mime_encoder_state encstate; /* Data encoder state. */ diff --git a/libs/libcurl/src/mk-ca-bundle.pl b/libs/libcurl/src/mk-ca-bundle.pl index 5ed53fe0d4..910fedb0ca 100644 --- a/libs/libcurl/src/mk-ca-bundle.pl +++ b/libs/libcurl/src/mk-ca-bundle.pl @@ -6,7 +6,7 @@ # * | (__| |_| | _ <| |___ # * \___|\___/|_| \_\_____| # * -# * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. +# * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. # * # * This software is licensed as described in the file COPYING, which # * you should have received as part of this distribution. The terms @@ -545,7 +545,7 @@ while () { print CRT @precert if($opt_m); my $maxStringLength = length(decode('UTF-8', $caname, Encode::FB_CROAK | Encode::LEAVE_SRC)); if ($opt_t) { - foreach my $key (keys %trust_purposes_by_level) { + foreach my $key (sort keys %trust_purposes_by_level) { my $string = $key . ": " . join(", ", @{$trust_purposes_by_level{$key}}); $maxStringLength = List::Util::max( length($string), $maxStringLength ); print CRT $string . "\n"; diff --git a/libs/libcurl/src/mqtt.c b/libs/libcurl/src/mqtt.c index e324ec3dd7..2134409cda 100644 --- a/libs/libcurl/src/mqtt.c +++ b/libs/libcurl/src/mqtt.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2020, Daniel Stenberg, , et al. + * Copyright (C) 2020 - 2021, Daniel Stenberg, , et al. * Copyright (C) 2019, Björn Stenberg, * * This software is licensed as described in the file COPYING, which @@ -59,10 +59,12 @@ * Forward declarations. */ -static CURLcode mqtt_do(struct connectdata *conn, bool *done); -static CURLcode mqtt_doing(struct connectdata *conn, bool *done); -static int mqtt_getsock(struct connectdata *conn, curl_socket_t *sock); -static CURLcode mqtt_setup_conn(struct connectdata *conn); +static CURLcode mqtt_do(struct Curl_easy *data, bool *done); +static CURLcode mqtt_doing(struct Curl_easy *data, bool *done); +static int mqtt_getsock(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t *sock); +static CURLcode mqtt_setup_conn(struct Curl_easy *data, + struct connectdata *conn); /* * MQTT protocol handler. @@ -90,12 +92,13 @@ const struct Curl_handler Curl_handler_mqtt = { PROTOPT_NONE /* flags */ }; -static CURLcode mqtt_setup_conn(struct connectdata *conn) +static CURLcode mqtt_setup_conn(struct Curl_easy *data, + struct connectdata *conn) { /* allocate the HTTP-specific struct for the Curl_easy, only to survive during this request */ struct MQTT *mq; - struct Curl_easy *data = conn->data; + (void)conn; DEBUGASSERT(data->req.p.mqtt == NULL); mq = calloc(1, sizeof(struct MQTT)); @@ -105,15 +108,15 @@ static CURLcode mqtt_setup_conn(struct connectdata *conn) return CURLE_OK; } -static CURLcode mqtt_send(struct connectdata *conn, +static CURLcode mqtt_send(struct Curl_easy *data, char *buf, size_t len) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - struct Curl_easy *data = conn->data; struct MQTT *mq = data->req.p.mqtt; ssize_t n; - result = Curl_write(conn, sockfd, buf, len, &n); + result = Curl_write(data, sockfd, buf, len, &n); if(!result) Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n); if(len != (size_t)n) { @@ -130,14 +133,16 @@ static CURLcode mqtt_send(struct connectdata *conn, /* Generic function called by the multi interface to figure out what socket(s) to wait for and for what actions during the DOING and PROTOCONNECT states */ -static int mqtt_getsock(struct connectdata *conn, +static int mqtt_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *sock) { + (void)data; sock[0] = conn->sock[FIRSTSOCKET]; return GETSOCK_READSOCK(FIRSTSOCKET); } -static CURLcode mqtt_connect(struct connectdata *conn) +static CURLcode mqtt_connect(struct Curl_easy *data) { CURLcode result = CURLE_OK; const size_t client_id_offset = 14; @@ -157,31 +162,31 @@ static CURLcode mqtt_connect(struct connectdata *conn) packet[1] = (packetlen - 2) & 0x7f; packet[client_id_offset - 1] = MQTT_CLIENTID_LEN; - result = Curl_rand_hex(conn->data, (unsigned char *)&client_id[clen], + result = Curl_rand_hex(data, (unsigned char *)&client_id[clen], MQTT_CLIENTID_LEN - clen + 1); memcpy(&packet[client_id_offset], client_id, MQTT_CLIENTID_LEN); - infof(conn->data, "Using client id '%s'\n", client_id); + infof(data, "Using client id '%s'\n", client_id); if(!result) - result = mqtt_send(conn, packet, packetlen); + result = mqtt_send(data, packet, packetlen); return result; } -static CURLcode mqtt_disconnect(struct connectdata *conn) +static CURLcode mqtt_disconnect(struct Curl_easy *data) { CURLcode result = CURLE_OK; - result = mqtt_send(conn, (char *)"\xe0\x00", 2); + result = mqtt_send(data, (char *)"\xe0\x00", 2); return result; } -static CURLcode mqtt_verify_connack(struct connectdata *conn) +static CURLcode mqtt_verify_connack(struct Curl_easy *data) { CURLcode result; + struct connectdata *conn = data->conn; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; unsigned char readbuf[MQTT_CONNACK_LEN]; ssize_t nread; - struct Curl_easy *data = conn->data; - result = Curl_read(conn, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread); + result = Curl_read(data, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread); if(result) goto fail; @@ -204,18 +209,18 @@ fail: return result; } -static CURLcode mqtt_get_topic(struct connectdata *conn, +static CURLcode mqtt_get_topic(struct Curl_easy *data, char **topic, size_t *topiclen) { CURLcode result = CURLE_OK; - char *path = conn->data->state.up.path; + char *path = data->state.up.path; if(strlen(path) > 1) { - result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen, + result = Curl_urldecode(data, path + 1, 0, topic, topiclen, REJECT_NADA); } else { - failf(conn->data, "Error: No topic specified."); + failf(data, "Error: No topic specified."); result = CURLE_URL_MALFORMAT; } return result; @@ -238,7 +243,7 @@ static int mqtt_encode_len(char *buf, size_t len) return i; } -static CURLcode mqtt_subscribe(struct connectdata *conn) +static CURLcode mqtt_subscribe(struct Curl_easy *data) { CURLcode result = CURLE_OK; char *topic = NULL; @@ -247,8 +252,9 @@ static CURLcode mqtt_subscribe(struct connectdata *conn) size_t packetlen; char encodedsize[4]; size_t n; + struct connectdata *conn = data->conn; - result = mqtt_get_topic(conn, &topic, &topiclen); + result = mqtt_get_topic(data, &topic, &topiclen); if(result) goto fail; @@ -274,7 +280,7 @@ static CURLcode mqtt_subscribe(struct connectdata *conn) memcpy(&packet[5 + n], topic, topiclen); packet[5 + n + topiclen] = 0; /* QoS zero */ - result = mqtt_send(conn, (char *)packet, packetlen); + result = mqtt_send(data, (char *)packet, packetlen); fail: free(topic); @@ -285,19 +291,20 @@ fail: /* * Called when the first byte was already read. */ -static CURLcode mqtt_verify_suback(struct connectdata *conn) +static CURLcode mqtt_verify_suback(struct Curl_easy *data) { CURLcode result; + struct connectdata *conn = data->conn; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; unsigned char readbuf[MQTT_SUBACK_LEN]; ssize_t nread; struct mqtt_conn *mqtt = &conn->proto.mqtt; - result = Curl_read(conn, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread); + result = Curl_read(data, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread); if(result) goto fail; - Curl_debug(conn->data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread); + Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread); /* fixme */ if(nread < MQTT_SUBACK_LEN) { @@ -315,11 +322,11 @@ fail: return result; } -static CURLcode mqtt_publish(struct connectdata *conn) +static CURLcode mqtt_publish(struct Curl_easy *data) { CURLcode result; - char *payload = conn->data->set.postfields; - size_t payloadlen = (size_t)conn->data->set.postfieldsize; + char *payload = data->set.postfields; + size_t payloadlen; char *topic = NULL; size_t topiclen; unsigned char *pkt = NULL; @@ -327,8 +334,16 @@ static CURLcode mqtt_publish(struct connectdata *conn) size_t remaininglength; size_t encodelen; char encodedbytes[4]; + curl_off_t postfieldsize = data->set.postfieldsize; + + if(!payload) + return CURLE_BAD_FUNCTION_ARGUMENT; + if(postfieldsize < 0) + payloadlen = strlen(payload); + else + payloadlen = (size_t)postfieldsize; - result = mqtt_get_topic(conn, &topic, &topiclen); + result = mqtt_get_topic(data, &topic, &topiclen); if(result) goto fail; @@ -352,7 +367,7 @@ static CURLcode mqtt_publish(struct connectdata *conn) i += topiclen; memcpy(&pkt[i], payload, payloadlen); i += payloadlen; - result = mqtt_send(conn, (char *)pkt, i); + result = mqtt_send(data, (char *)pkt, i); fail: free(pkt); @@ -395,13 +410,14 @@ static const char *statenames[]={ #endif /* The only way to change state */ -static void mqstate(struct connectdata *conn, +static void mqstate(struct Curl_easy *data, enum mqttstate state, enum mqttstate nextstate) /* used if state == FIRST */ { + struct connectdata *conn = data->conn; struct mqtt_conn *mqtt = &conn->proto.mqtt; #ifdef CURLDEBUG - infof(conn->data, "%s (from %s) (next is %s)\n", + infof(data, "%s (from %s) (next is %s)\n", statenames[state], statenames[mqtt->state], (state == MQTT_FIRST)? statenames[nextstate] : ""); @@ -415,13 +431,12 @@ static void mqstate(struct connectdata *conn, /* for the publish packet */ #define MQTT_HEADER_LEN 5 /* max 5 bytes */ -static CURLcode mqtt_read_publish(struct connectdata *conn, - bool *done) +static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; ssize_t nread; - struct Curl_easy *data = conn->data; unsigned char *pkt = (unsigned char *)data->state.buffer; size_t remlen; struct mqtt_conn *mqtt = &conn->proto.mqtt; @@ -431,11 +446,11 @@ static CURLcode mqtt_read_publish(struct connectdata *conn, switch(mqtt->state) { MQTT_SUBACK_COMING: case MQTT_SUBACK_COMING: - result = mqtt_verify_suback(conn); + result = mqtt_verify_suback(data); if(result) break; - mqstate(conn, MQTT_FIRST, MQTT_PUBWAIT); + mqstate(data, MQTT_FIRST, MQTT_PUBWAIT); break; case MQTT_SUBACK: @@ -443,9 +458,9 @@ static CURLcode mqtt_read_publish(struct connectdata *conn, /* we are expecting PUBLISH or SUBACK */ packet = mq->firstbyte & 0xf0; if(packet == MQTT_MSG_PUBLISH) - mqstate(conn, MQTT_PUB_REMAIN, MQTT_NOSTATE); + mqstate(data, MQTT_PUB_REMAIN, MQTT_NOSTATE); else if(packet == MQTT_MSG_SUBACK) { - mqstate(conn, MQTT_SUBACK_COMING, MQTT_NOSTATE); + mqstate(data, MQTT_SUBACK_COMING, MQTT_NOSTATE); goto MQTT_SUBACK_COMING; } else if(packet == MQTT_MSG_DISCONNECT) { @@ -472,7 +487,7 @@ static CURLcode mqtt_read_publish(struct connectdata *conn, size_t rest = mq->npacket; if(rest > (size_t)data->set.buffer_size) rest = (size_t)data->set.buffer_size; - result = Curl_read(conn, sockfd, (char *)pkt, rest, &nread); + result = Curl_read(data, sockfd, (char *)pkt, rest, &nread); if(result) { if(CURLE_AGAIN == result) { infof(data, "EEEE AAAAGAIN\n"); @@ -492,13 +507,13 @@ static CURLcode mqtt_read_publish(struct connectdata *conn, /* if QoS is set, message contains packet id */ - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)pkt, nread); + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)pkt, nread); if(result) goto end; if(!mq->npacket) /* no more PUBLISH payload, back to subscribe wait state */ - mqstate(conn, MQTT_FIRST, MQTT_PUBWAIT); + mqstate(data, MQTT_FIRST, MQTT_PUBWAIT); break; } default: @@ -510,27 +525,25 @@ static CURLcode mqtt_read_publish(struct connectdata *conn, return result; } -static CURLcode mqtt_do(struct connectdata *conn, bool *done) +static CURLcode mqtt_do(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - *done = FALSE; /* unconditionally */ - result = mqtt_connect(conn); + result = mqtt_connect(data); if(result) { failf(data, "Error %d sending MQTT CONN request", result); return result; } - mqstate(conn, MQTT_FIRST, MQTT_CONNACK); + mqstate(data, MQTT_FIRST, MQTT_CONNACK); return CURLE_OK; } -static CURLcode mqtt_doing(struct connectdata *conn, bool *done) +static CURLcode mqtt_doing(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct mqtt_conn *mqtt = &conn->proto.mqtt; - struct Curl_easy *data = conn->data; struct MQTT *mq = data->req.p.mqtt; ssize_t nread; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; @@ -542,7 +555,7 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done) if(mq->nsend) { /* send the remainder of an outgoing packet */ char *ptr = mq->sendleftovers; - result = mqtt_send(conn, mq->sendleftovers, mq->nsend); + result = mqtt_send(data, mq->sendleftovers, mq->nsend); free(ptr); if(result) return result; @@ -552,18 +565,18 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done) switch(mqtt->state) { case MQTT_FIRST: /* Read the initial byte only */ - result = Curl_read(conn, sockfd, (char *)&mq->firstbyte, 1, &nread); - if(result) + result = Curl_read(data, sockfd, (char *)&mq->firstbyte, 1, &nread); + if(!nread) break; Curl_debug(data, CURLINFO_HEADER_IN, (char *)&mq->firstbyte, 1); /* remember the first byte */ mq->npacket = 0; - mqstate(conn, MQTT_REMAINING_LENGTH, MQTT_NOSTATE); + mqstate(data, MQTT_REMAINING_LENGTH, MQTT_NOSTATE); /* FALLTHROUGH */ case MQTT_REMAINING_LENGTH: do { - result = Curl_read(conn, sockfd, (char *)&byte, 1, &nread); - if(result) + result = Curl_read(data, sockfd, (char *)&byte, 1, &nread); + if(!nread) break; Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1); pkt[mq->npacket++] = byte; @@ -573,10 +586,10 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done) mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL); mq->npacket = 0; if(mq->remaining_length) { - mqstate(conn, mqtt->nextstate, MQTT_NOSTATE); + mqstate(data, mqtt->nextstate, MQTT_NOSTATE); break; } - mqstate(conn, MQTT_FIRST, MQTT_FIRST); + mqstate(data, MQTT_FIRST, MQTT_FIRST); if(mq->firstbyte == MQTT_MSG_DISCONNECT) { infof(data, "Got DISCONNECT\n"); @@ -584,22 +597,22 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done) } break; case MQTT_CONNACK: - result = mqtt_verify_connack(conn); + result = mqtt_verify_connack(data); if(result) break; - if(conn->data->state.httpreq == HTTPREQ_POST) { - result = mqtt_publish(conn); + if(data->state.httpreq == HTTPREQ_POST) { + result = mqtt_publish(data); if(!result) { - result = mqtt_disconnect(conn); + result = mqtt_disconnect(data); *done = TRUE; } mqtt->nextstate = MQTT_FIRST; } else { - result = mqtt_subscribe(conn); + result = mqtt_subscribe(data); if(!result) { - mqstate(conn, MQTT_FIRST, MQTT_SUBACK); + mqstate(data, MQTT_FIRST, MQTT_SUBACK); } } break; @@ -607,11 +620,11 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done) case MQTT_SUBACK: case MQTT_PUBWAIT: case MQTT_PUB_REMAIN: - result = mqtt_read_publish(conn, done); + result = mqtt_read_publish(data, done); break; default: - failf(conn->data, "State not handled yet"); + failf(data, "State not handled yet"); *done = TRUE; break; } diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c index 86e36be4ac..85707a1af9 100644 --- a/libs/libcurl/src/multi.c +++ b/libs/libcurl/src/multi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -69,7 +69,7 @@ #define CURL_MULTI_HANDLE 0x000bab1e #define GOOD_MULTI_HANDLE(x) \ - ((x) && (x)->type == CURL_MULTI_HANDLE) + ((x) && (x)->magic == CURL_MULTI_HANDLE) static CURLMcode singlesocket(struct Curl_multi *multi, struct Curl_easy *data); @@ -105,7 +105,14 @@ static const char * const statename[]={ /* function pointer called once when switching TO a state */ typedef void (*init_multistate_func)(struct Curl_easy *data); -static void Curl_init_completed(struct Curl_easy *data) +/* called when the PERFORM state starts */ +static void init_perform(struct Curl_easy *data) +{ + data->req.chunk = FALSE; + Curl_pgrsTime(data, TIMER_PRETRANSFER); +} + +static void init_completed(struct Curl_easy *data) { /* this is a completed transfer */ @@ -136,10 +143,10 @@ static void mstate(struct Curl_easy *data, CURLMstate state NULL, /* DOING */ NULL, /* DO_MORE */ NULL, /* DO_DONE */ - NULL, /* PERFORM */ + init_perform, /* PERFORM */ NULL, /* TOOFAST */ NULL, /* DONE */ - Curl_init_completed, /* COMPLETED */ + init_completed, /* COMPLETED */ NULL /* MSGSENT */ }; @@ -193,8 +200,8 @@ struct Curl_sh_entry { struct Curl_hash transfers; /* hash of transfers using this socket */ unsigned int action; /* what combined action READ/WRITE this socket waits for */ - void *socketp; /* settable by users with curl_multi_assign() */ unsigned int users; /* number of transfers using this */ + void *socketp; /* settable by users with curl_multi_assign() */ unsigned int readers; /* this many transfers want to read */ unsigned int writers; /* this many transfers want to write */ }; @@ -353,7 +360,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ if(!multi) return NULL; - multi->type = CURL_MULTI_HANDLE; + multi->magic = CURL_MULTI_HANDLE; if(Curl_mk_dnscache(&multi->hostcache)) goto error; @@ -558,7 +565,7 @@ static CURLcode multi_done(struct Curl_easy *data, conn->data = data; /* ensure the connection uses this transfer now */ /* Stop the resolver and free its own resources (but not dns_entry yet). */ - Curl_resolver_kill(conn); + Curl_resolver_kill(data); /* Cleanup possible redirect junk */ Curl_safefree(data->req.newurl); @@ -579,14 +586,14 @@ static CURLcode multi_done(struct Curl_easy *data, /* this calls the protocol-specific function pointer previously set */ if(conn->handler->done) - result = conn->handler->done(conn, status, premature); + result = conn->handler->done(data, status, premature); else result = status; if(CURLE_ABORTED_BY_CALLBACK != result) { /* avoid this if we already aborted by callback to avoid this calling another callback */ - CURLcode rc = Curl_pgrsDone(conn); + CURLcode rc = Curl_pgrsDone(data); if(!result && rc) result = CURLE_ABORTED_BY_CALLBACK; } @@ -690,17 +697,13 @@ static CURLcode multi_done(struct Curl_easy *data, return result; } -static int close_connect_only(struct connectdata *conn, void *param) +static int close_connect_only(struct Curl_easy *data, + struct connectdata *conn, void *param) { - struct Curl_easy *data = param; - + (void)param; if(data->state.lastconnect_id != conn->connection_id) return 0; - if(conn->data != data) - return 1; - conn->data = NULL; - if(!conn->bits.connect_only) return 1; @@ -809,7 +812,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, if(data->state.lastconnect_id != -1) { /* Mark any connect-only connection for closure */ Curl_conncache_foreach(data, data->state.conn_cache, - data, &close_connect_only); + NULL, close_connect_only); } #ifdef USE_LIBPSL @@ -938,27 +941,30 @@ static int waitproxyconnect_getsock(struct connectdata *conn, return GETSOCK_WRITESOCK(0); } -static int domore_getsock(struct connectdata *conn, +static int domore_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { if(conn && conn->handler->domore_getsock) - return conn->handler->domore_getsock(conn, socks); + return conn->handler->domore_getsock(data, conn, socks); return GETSOCK_BLANK; } -static int doing_getsock(struct connectdata *conn, +static int doing_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { if(conn && conn->handler->doing_getsock) - return conn->handler->doing_getsock(conn, socks); + return conn->handler->doing_getsock(data, conn, socks); return GETSOCK_BLANK; } -static int protocol_getsock(struct connectdata *conn, +static int protocol_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { if(conn->handler->proto_getsock) - return conn->handler->proto_getsock(conn, socks); + return conn->handler->proto_getsock(data, conn, socks); /* Backup getsock logic. Since there is a live socket in use, we must wait for it or it will be removed from watching when the multi_socket API is used. */ @@ -971,10 +977,11 @@ static int protocol_getsock(struct connectdata *conn, static int multi_getsock(struct Curl_easy *data, curl_socket_t *socks) { + struct connectdata *conn = data->conn; /* The no connection case can happen when this is called from curl_multi_remove_handle() => singlesocket() => multi_getsock(). */ - if(!data->conn) + if(!conn) return 0; if(data->mstate > CURLM_STATE_CONNECT && @@ -988,30 +995,30 @@ static int multi_getsock(struct Curl_easy *data, return 0; case CURLM_STATE_WAITRESOLVE: - return Curl_resolv_getsock(data->conn, socks); + return Curl_resolv_getsock(data, socks); case CURLM_STATE_PROTOCONNECT: case CURLM_STATE_SENDPROTOCONNECT: - return protocol_getsock(data->conn, socks); + return protocol_getsock(data, conn, socks); case CURLM_STATE_DO: case CURLM_STATE_DOING: - return doing_getsock(data->conn, socks); + return doing_getsock(data, conn, socks); case CURLM_STATE_WAITPROXYCONNECT: - return waitproxyconnect_getsock(data->conn, socks); + return waitproxyconnect_getsock(conn, socks); case CURLM_STATE_WAITCONNECT: - return waitconnect_getsock(data->conn, socks); + return waitconnect_getsock(conn, socks); case CURLM_STATE_DO_MORE: - return domore_getsock(data->conn, socks); + return domore_getsock(data, conn, socks); case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch to waiting for the same as the *PERFORM states */ case CURLM_STATE_PERFORM: - return Curl_single_getsock(data->conn, socks); + return Curl_single_getsock(data, conn, socks); } } @@ -1067,13 +1074,13 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, #define NUM_POLLS_ON_STACK 10 -static CURLMcode Curl_multi_wait(struct Curl_multi *multi, - struct curl_waitfd extra_fds[], - unsigned int extra_nfds, - int timeout_ms, - int *ret, - bool extrawait, /* when no socket, wait */ - bool use_wakeup) +static CURLMcode multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret, + bool extrawait, /* when no socket, wait */ + bool use_wakeup) { struct Curl_easy *data; curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; @@ -1281,8 +1288,8 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi, int timeout_ms, int *ret) { - return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE, - FALSE); + return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE, + FALSE); } CURLMcode curl_multi_poll(struct Curl_multi *multi, @@ -1291,8 +1298,8 @@ CURLMcode curl_multi_poll(struct Curl_multi *multi, int timeout_ms, int *ret) { - return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE, - TRUE); + return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE, + TRUE); } CURLMcode curl_multi_wakeup(struct Curl_multi *multi) @@ -1319,7 +1326,7 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi) The write socket is set to non-blocking, this way this function cannot block, making it safe to call even from the same thread - that will call Curl_multi_wait(). If swrite() returns that it + that will call curl_multi_wait(). If swrite() returns that it would block, it's considered successful because it means that previous calls to this function will wake up the poll(). */ if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) { @@ -1383,18 +1390,6 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, return rc; } -/* - * do_complete is called when the DO actions are complete. - * - * We init chunking and trailer bits to their default values here immediately - * before receiving any header data for the current request. - */ -static void do_complete(struct connectdata *conn) -{ - conn->data->req.chunk = FALSE; - Curl_pgrsTime(conn->data, TIMER_PRETRANSFER); -} - static CURLcode multi_do(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; @@ -1404,14 +1399,10 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done) DEBUGASSERT(conn->handler); DEBUGASSERT(conn->data == data); - if(conn->handler->do_it) { + if(conn->handler->do_it) /* generic protocol-specific function pointer set in curl_connect() */ - result = conn->handler->do_it(conn, done); + result = conn->handler->do_it(data, done); - if(!result && *done) - /* do_complete must be called after the protocol-specific DO function */ - do_complete(conn); - } return result; } @@ -1424,18 +1415,15 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done) * DOING state there's more work to do! */ -static CURLcode multi_do_more(struct connectdata *conn, int *complete) +static CURLcode multi_do_more(struct Curl_easy *data, int *complete) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; *complete = 0; if(conn->handler->do_more) - result = conn->handler->do_more(conn, complete); - - if(!result && (*complete == 1)) - /* do_complete must be called after the protocol-specific DO function */ - do_complete(conn); + result = conn->handler->do_more(data, complete); return result; } @@ -1446,14 +1434,14 @@ static CURLcode multi_do_more(struct connectdata *conn, int *complete) * protocol layer. */ -static CURLcode protocol_connecting(struct connectdata *conn, - bool *done) +static CURLcode protocol_connecting(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; if(conn && conn->handler->connecting) { *done = FALSE; - result = conn->handler->connecting(conn, done); + result = conn->handler->connecting(data, done); } else *done = TRUE; @@ -1466,13 +1454,14 @@ static CURLcode protocol_connecting(struct connectdata *conn, * until the DOING phase is done on protocol layer. */ -static CURLcode protocol_doing(struct connectdata *conn, bool *done) +static CURLcode protocol_doing(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; if(conn && conn->handler->doing) { *done = FALSE; - result = conn->handler->doing(conn, done); + result = conn->handler->doing(data, done); } else *done = TRUE; @@ -1485,11 +1474,11 @@ static CURLcode protocol_doing(struct connectdata *conn, bool *done) * proceed with some action. * */ -static CURLcode protocol_connect(struct connectdata *conn, +static CURLcode protocol_connect(struct Curl_easy *data, bool *protocol_done) { CURLcode result = CURLE_OK; - + struct connectdata *conn = data->conn; DEBUGASSERT(conn); DEBUGASSERT(protocol_done); @@ -1510,7 +1499,7 @@ static CURLcode protocol_connect(struct connectdata *conn, if(!conn->bits.protoconnstart) { #ifndef CURL_DISABLE_PROXY - result = Curl_proxy_connect(conn, FIRSTSOCKET); + result = Curl_proxy_connect(data, FIRSTSOCKET); if(result) return result; @@ -1528,7 +1517,7 @@ static CURLcode protocol_connect(struct connectdata *conn, /* is there a protocol-specific connect() procedure? */ /* Call the protocol-specific connect function */ - result = conn->handler->connect_it(conn, protocol_done); + result = conn->handler->connect_it(data, protocol_done); } else *protocol_done = TRUE; @@ -1589,9 +1578,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, process_pending_handles(multi); /* multiplexed */ } - if(data->conn && data->mstate > CURLM_STATE_CONNECT && + if(data->mstate > CURLM_STATE_CONNECT && data->mstate < CURLM_STATE_COMPLETED) { /* Make sure we set the connection's current owner */ + DEBUGASSERT(data->conn); + if(!data->conn) + return CURLM_INTERNAL_ERROR; data->conn->data = data; } @@ -1737,19 +1729,19 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, hostname = conn->host.name; /* check if we have the name resolved by now */ - dns = Curl_fetch_addr(conn, hostname, (int)conn->port); + dns = Curl_fetch_addr(data, hostname, (int)conn->port); if(dns) { #ifdef CURLRES_ASYNCH - conn->async.dns = dns; - conn->async.done = TRUE; + data->state.async.dns = dns; + data->state.async.done = TRUE; #endif result = CURLE_OK; infof(data, "Hostname '%s' was found in DNS cache\n", hostname); } if(!dns) - result = Curl_resolv_check(data->conn, &dns); + result = Curl_resolv_check(data, &dns); /* Update sockets here, because the socket(s) may have been closed and the application thus needs to be told, even if it @@ -1762,7 +1754,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(dns) { /* Perform the next step in the connection phase, and then move on to the WAITCONNECT state */ - result = Curl_once_resolved(data->conn, &protocol_connected); + result = Curl_once_resolved(data, &protocol_connected); if(result) /* if Curl_once_resolved() returns failure, the connection struct @@ -1796,7 +1788,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, case CURLM_STATE_WAITPROXYCONNECT: /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */ DEBUGASSERT(data->conn); - result = Curl_http_connect(data->conn, &protocol_connected); + result = Curl_http_connect(data, &protocol_connected); #ifndef CURL_DISABLE_PROXY if(data->conn->bits.proxy_connect_closed) { rc = CURLM_CALL_MULTI_PERFORM; @@ -1827,7 +1819,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, case CURLM_STATE_WAITCONNECT: /* awaiting a completion of an asynch TCP connect */ DEBUGASSERT(data->conn); - result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected); + result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected); if(connected && !result) { #ifndef CURL_DISABLE_HTTP if( @@ -1860,7 +1852,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, break; case CURLM_STATE_SENDPROTOCONNECT: - result = protocol_connect(data->conn, &protocol_connected); + result = protocol_connect(data, &protocol_connected); if(!result && !protocol_connected) /* switch to waiting state */ multistate(data, CURLM_STATE_PROTOCONNECT); @@ -1879,7 +1871,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, case CURLM_STATE_PROTOCONNECT: /* protocol-specific connect phase */ - result = protocol_connecting(data->conn, &protocol_connected); + result = protocol_connecting(data, &protocol_connected); if(!result && protocol_connected) { /* after the connect has completed, go WAITDO or DO */ multistate(data, CURLM_STATE_DO); @@ -1916,7 +1908,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) { /* skip some states if it is important */ multi_done(data, CURLE_OK, FALSE); - multistate(data, CURLM_STATE_DONE); + + /* if there's no connection left, skip the DONE state */ + multistate(data, data->conn ? + CURLM_STATE_DONE : CURLM_STATE_COMPLETED); rc = CURLM_CALL_MULTI_PERFORM; break; } @@ -1952,7 +1947,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, followtype follow = FOLLOW_NONE; CURLcode drc; - drc = Curl_retry_request(data->conn, &newurl); + drc = Curl_retry_request(data, &newurl); if(drc) { /* a failure here pretty much implies an out of memory */ result = drc; @@ -2002,7 +1997,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, case CURLM_STATE_DOING: /* we continue DOING until the DO phase is complete */ DEBUGASSERT(data->conn); - result = protocol_doing(data->conn, &dophase_done); + result = protocol_doing(data, &dophase_done); if(!result) { if(dophase_done) { /* after DO, go DO_DONE or DO_MORE */ @@ -2025,7 +2020,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, * When we are connected, DO MORE and then go DO_DONE */ DEBUGASSERT(data->conn); - result = multi_do_more(data->conn, &control); + result = multi_do_more(data, &control); if(!result) { if(control) { @@ -2074,12 +2069,20 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */ DEBUGASSERT(data->conn); /* if both rates are within spec, resume transfer */ - if(Curl_pgrsUpdate(data->conn)) + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; else result = Curl_speedcheck(data, *nowp); - if(!result) { + if(result) { + if(!(data->conn->handler->flags & PROTOPT_DUAL) && + result != CURLE_HTTP2_STREAM) + streamclose(data->conn, "Transfer returned error"); + + Curl_posttransfer(data); + multi_done(data, result, TRUE); + } + else { send_timeout_ms = 0; if(data->set.max_send_speed > 0) send_timeout_ms = @@ -2151,7 +2154,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, * condition and the server closed the re-used connection exactly when * we wanted to use it, so figure out if that is indeed the case. */ - CURLcode ret = Curl_retry_request(data->conn, &newurl); + CURLcode ret = Curl_retry_request(data, &newurl); if(!ret) retry = (newurl)?TRUE:FALSE; else if(!result) @@ -2166,7 +2169,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } else if((CURLE_HTTP2_STREAM == result) && Curl_h2_http_1_1_error(data->conn)) { - CURLcode ret = Curl_retry_request(data->conn, &newurl); + CURLcode ret = Curl_retry_request(data, &newurl); if(!ret) { infof(data, "Downgrades to HTTP/1.1!\n"); @@ -2203,7 +2206,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, multi_done(data, result, TRUE); } else if(done) { - followtype follow = FOLLOW_NONE; /* call this even if the readwrite function returned error */ Curl_posttransfer(data); @@ -2211,6 +2213,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* When we follow redirects or is set to retry the connection, we must to go back to the CONNECT state */ if(data->req.newurl || retry) { + followtype follow = FOLLOW_NONE; if(!retry) { /* if the URL is a follow-location and not just a retried request then figure out the URL here */ @@ -2280,14 +2283,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* allow a previously set error code take precedence */ if(!result) result = res; - - /* - * If there are other handles on the connection, multi_done won't set - * conn to NULL. In such a case, curl_multi_remove_handle() can - * access free'd data, if the connection is free'd and the handle - * removed before we perform the processing in CURLM_STATE_COMPLETED - */ - Curl_detach_connnection(data); } #ifndef CURL_DISABLE_FTP @@ -2357,7 +2352,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, rc = CURLM_CALL_MULTI_PERFORM; } /* if there's still a connection to use, call the progress function */ - else if(data->conn && Curl_pgrsUpdate(data->conn)) { + else if(data->conn && Curl_pgrsUpdate(data)) { /* aborted due to progress callback return code must close the connection */ result = CURLE_ABORTED_BY_CALLBACK; @@ -2458,7 +2453,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) if(multi->in_callback) return CURLM_RECURSIVE_API_CALL; - multi->type = 0; /* not good anymore */ + multi->magic = 0; /* not good anymore */ /* Firsrt remove all remaining easy handles */ data = multi->easyp; @@ -3329,16 +3324,18 @@ size_t Curl_multi_max_total_connections(struct Curl_multi *multi) * When information about a connection has appeared, call this! */ -void Curl_multiuse_state(struct connectdata *conn, +void Curl_multiuse_state(struct Curl_easy *data, int bundlestate) /* use BUNDLE_* defines */ { + struct connectdata *conn; + DEBUGASSERT(data); + DEBUGASSERT(data->multi); + conn = data->conn; DEBUGASSERT(conn); DEBUGASSERT(conn->bundle); - DEBUGASSERT(conn->data); - DEBUGASSERT(conn->data->multi); conn->bundle->multiuse = bundlestate; - process_pending_handles(conn->data->multi); + process_pending_handles(data->multi); } static void process_pending_handles(struct Curl_multi *multi) diff --git a/libs/libcurl/src/multihandle.h b/libs/libcurl/src/multihandle.h index de4f74069e..f28c5899b6 100644 --- a/libs/libcurl/src/multihandle.h +++ b/libs/libcurl/src/multihandle.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -22,10 +22,14 @@ * ***************************************************************************/ +#include "llist.h" +#include "hash.h" #include "conncache.h" #include "psl.h" #include "socketpair.h" +struct connectdata; + struct Curl_message { struct Curl_llist_element list; /* the 'CURLMsg' is the part that is visible to the external user */ @@ -79,7 +83,7 @@ typedef enum { struct Curl_multi { /* First a simple identifier to easier detect if a user mix up this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */ - long type; + unsigned int magic; /* We have a doubly-linked list with easy handles */ struct Curl_easy *easyp; diff --git a/libs/libcurl/src/multiif.h b/libs/libcurl/src/multiif.h index f0a57d9a6c..2fbef53c48 100644 --- a/libs/libcurl/src/multiif.h +++ b/libs/libcurl/src/multiif.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -69,7 +69,7 @@ size_t Curl_multi_max_host_connections(struct Curl_multi *multi); /* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */ size_t Curl_multi_max_total_connections(struct Curl_multi *multi); -void Curl_multiuse_state(struct connectdata *conn, +void Curl_multiuse_state(struct Curl_easy *data, int bundlestate); /* use BUNDLE_* defines */ /* diff --git a/libs/libcurl/src/openldap.c b/libs/libcurl/src/openldap.c index 24892ff414..4070bbf88b 100644 --- a/libs/libcurl/src/openldap.c +++ b/libs/libcurl/src/openldap.c @@ -5,8 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * + * Copyright (C) 2011 - 2021, Daniel Stenberg, , et al. * Copyright (C) 2010, Howard Chu, - * Copyright (C) 2011 - 2020, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -76,12 +76,14 @@ extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, LDAP **ld); #endif -static CURLcode ldap_setup_connection(struct connectdata *conn); -static CURLcode ldap_do(struct connectdata *conn, bool *done); -static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool); -static CURLcode ldap_connect(struct connectdata *conn, bool *done); -static CURLcode ldap_connecting(struct connectdata *conn, bool *done); -static CURLcode ldap_disconnect(struct connectdata *conn, bool dead); +static CURLcode ldap_setup_connection(struct Curl_easy *data, + struct connectdata *conn); +static CURLcode ldap_do(struct Curl_easy *data, bool *done); +static CURLcode ldap_done(struct Curl_easy *data, CURLcode, bool); +static CURLcode ldap_connect(struct Curl_easy *data, bool *done); +static CURLcode ldap_connecting(struct Curl_easy *data, bool *done); +static CURLcode ldap_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); static Curl_recv ldap_recv; @@ -169,11 +171,11 @@ struct ldapreqinfo { int nument; }; -static CURLcode ldap_setup_connection(struct connectdata *conn) +static CURLcode ldap_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { struct ldapconninfo *li; LDAPURLDesc *lud; - struct Curl_easy *data = conn->data; int rc, proto; CURLcode status; @@ -186,7 +188,7 @@ static CURLcode ldap_setup_connection(struct connectdata *conn) status = CURLE_OUT_OF_MEMORY; msg = url_errs[rc]; } - failf(conn->data, "LDAP local: %s", msg); + failf(data, "LDAP local: %s", msg); return status; } proto = ldap_pvt_url_scheme2proto(lud->lud_scheme); @@ -205,10 +207,10 @@ static CURLcode ldap_setup_connection(struct connectdata *conn) static Sockbuf_IO ldapsb_tls; #endif -static CURLcode ldap_connect(struct connectdata *conn, bool *done) +static CURLcode ldap_connect(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; - struct Curl_easy *data = conn->data; int rc, proto = LDAP_VERSION3; char hosturl[1024]; char *ptr; @@ -243,7 +245,8 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) #ifdef USE_SSL if(conn->handler->flags & PROTOPT_SSL) { CURLcode result; - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); + result = Curl_ssl_connect_nonblocking(data, conn, + FIRSTSOCKET, &li->ssldone); if(result) return result; } @@ -252,10 +255,10 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) return CURLE_OK; } -static CURLcode ldap_connecting(struct connectdata *conn, bool *done) +static CURLcode ldap_connecting(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; - struct Curl_easy *data = conn->data; LDAPMessage *msg = NULL; struct timeval tv = {0, 1}, *tvp; int rc, err; @@ -265,7 +268,7 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done) if(conn->handler->flags & PROTOPT_SSL) { /* Is the SSL handshake complete yet? */ if(!li->ssldone) { - CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, &li->ssldone); if(result || !li->ssldone) return result; @@ -357,10 +360,12 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done) return CURLE_OK; } -static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode ldap_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { struct ldapconninfo *li = conn->proto.ldapc; (void) dead_connection; + (void) data; if(li) { if(li->ld) { @@ -373,15 +378,15 @@ static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection) return CURLE_OK; } -static CURLcode ldap_do(struct connectdata *conn, bool *done) +static CURLcode ldap_do(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; struct ldapreqinfo *lr; CURLcode status = CURLE_OK; int rc = 0; LDAPURLDesc *ludp = NULL; int msgid; - struct Curl_easy *data = conn->data; connkeep(conn, "OpenLDAP do"); @@ -396,7 +401,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done) status = CURLE_OUT_OF_MEMORY; msg = url_errs[rc]; } - failf(conn->data, "LDAP local: %s", msg); + failf(data, "LDAP local: %s", msg); return status; } @@ -418,10 +423,11 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done) return CURLE_OK; } -static CURLcode ldap_done(struct connectdata *conn, CURLcode res, +static CURLcode ldap_done(struct Curl_easy *data, CURLcode res, bool premature) { - struct ldapreqinfo *lr = conn->data->req.p.ldap; + struct connectdata *conn = data->conn; + struct ldapreqinfo *lr = data->req.p.ldap; (void)res; (void)premature; @@ -433,18 +439,18 @@ static CURLcode ldap_done(struct connectdata *conn, CURLcode res, ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL); lr->msgid = 0; } - conn->data->req.p.ldap = NULL; + data->req.p.ldap = NULL; free(lr); } return CURLE_OK; } -static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, +static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, size_t len, CURLcode *err) { + struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; - struct Curl_easy *data = conn->data; struct ldapreqinfo *lr = data->req.p.ldap; int rc, ret; LDAPMessage *msg = NULL; @@ -512,20 +518,20 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, *err = CURLE_RECV_ERROR; return -1; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4); if(writeerr) { *err = writeerr; return -1; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); if(writeerr) { *err = writeerr; return -1; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(writeerr) { *err = writeerr; return -1; @@ -546,18 +552,18 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, binary = 0; if(bvals == NULL) { - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1); if(writeerr) { *err = writeerr; return -1; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); if(writeerr) { *err = writeerr; return -1; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":\n", 2); if(writeerr) { *err = writeerr; return -1; @@ -568,20 +574,20 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, for(i = 0; bvals[i].bv_val != NULL; i++) { int binval = 0; - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1); if(writeerr) { *err = writeerr; return -1; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); if(writeerr) { *err = writeerr; return -1; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":", 1); if(writeerr) { *err = writeerr; return -1; @@ -619,7 +625,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, *err = error; return -1; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2); if(writeerr) { *err = writeerr; @@ -628,7 +634,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, data->req.bytecount += 2; if(val_b64_sz > 0) { - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, val_b64, val_b64_sz); if(writeerr) { *err = writeerr; @@ -639,13 +645,13 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, } } else { - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)" ", 1); if(writeerr) { *err = writeerr; return -1; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val, + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, bvals[i].bv_val, bvals[i].bv_len); if(writeerr) { *err = writeerr; @@ -654,7 +660,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, data->req.bytecount += bvals[i].bv_len + 1; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0); if(writeerr) { *err = writeerr; return -1; @@ -663,14 +669,14 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, data->req.bytecount++; } ber_memfree(bvals); - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0); if(writeerr) { *err = writeerr; return -1; } data->req.bytecount++; } - writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0); if(writeerr) { *err = writeerr; return -1; @@ -724,7 +730,7 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) ber_slen_t ret; CURLcode err = CURLE_RECV_ERROR; - ret = (li->recv)(conn, FIRSTSOCKET, buf, len, &err); + ret = (li->recv)(conn->data, FIRSTSOCKET, buf, len, &err); if(ret < 0 && err == CURLE_AGAIN) { SET_SOCKERRNO(EWOULDBLOCK); } @@ -739,7 +745,7 @@ ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) ber_slen_t ret; CURLcode err = CURLE_SEND_ERROR; - ret = (li->send)(conn, FIRSTSOCKET, buf, len, &err); + ret = (li->send)(conn->data, FIRSTSOCKET, buf, len, &err); if(ret < 0 && err == CURLE_AGAIN) { SET_SOCKERRNO(EWOULDBLOCK); } diff --git a/libs/libcurl/src/pingpong.c b/libs/libcurl/src/pingpong.c index 5d6109a7df..481173995f 100644 --- a/libs/libcurl/src/pingpong.c +++ b/libs/libcurl/src/pingpong.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -44,10 +44,10 @@ /* Returns timeout in ms. 0 or negative number means the timeout has already triggered */ -timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting) +timediff_t Curl_pp_state_timeout(struct Curl_easy *data, + struct pingpong *pp, bool disconnecting) { - struct connectdata *conn = pp->conn; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; timediff_t timeout_ms; /* in milliseconds */ timediff_t response_time = (data->set.server_response_timeout)? data->set.server_response_timeout: pp->response_time; @@ -77,15 +77,15 @@ timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting) /* * Curl_pp_statemach() */ -CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, +CURLcode Curl_pp_statemach(struct Curl_easy *data, + struct pingpong *pp, bool block, bool disconnecting) { - struct connectdata *conn = pp->conn; + struct connectdata *conn = data->conn; curl_socket_t sock = conn->sock[FIRSTSOCKET]; int rc; timediff_t interval_ms; - timediff_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting); - struct Curl_easy *data = conn->data; + timediff_t timeout_ms = Curl_pp_state_timeout(data, pp, disconnecting); CURLcode result = CURLE_OK; if(timeout_ms <= 0) { @@ -117,7 +117,7 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, if(block) { /* if we didn't wait, we don't have to spend time on this now */ - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; else result = Curl_speedcheck(data, Curl_now()); @@ -131,17 +131,17 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, result = CURLE_OUT_OF_MEMORY; } else if(rc) - result = pp->statemach_act(conn); + result = pp->statemachine(data, data->conn); return result; } /* initialize stuff to prepare for reading a fresh new response */ -void Curl_pp_init(struct pingpong *pp) +void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp) { - struct connectdata *conn = pp->conn; + DEBUGASSERT(data); pp->nread_resp = 0; - pp->linestart_resp = conn->data->state.buffer; + pp->linestart_resp = data->state.buffer; pp->pending_resp = TRUE; pp->response = Curl_now(); /* start response time-out now! */ } @@ -162,7 +162,8 @@ void Curl_pp_setup(struct pingpong *pp) * * made to never block */ -CURLcode Curl_pp_vsendf(struct pingpong *pp, +CURLcode Curl_pp_vsendf(struct Curl_easy *data, + struct pingpong *pp, const char *fmt, va_list args) { @@ -170,8 +171,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, size_t write_len; char *s; CURLcode result; - struct connectdata *conn = pp->conn; - struct Curl_easy *data; + struct connectdata *conn = data->conn; #ifdef HAVE_GSSAPI enum protection_level data_sec; @@ -184,7 +184,6 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, if(!conn) /* can't send without a connection! */ return CURLE_SEND_ERROR; - data = conn->data; Curl_dyn_reset(&pp->sendbuf); result = Curl_dyn_vaddf(&pp->sendbuf, fmt, args); @@ -198,7 +197,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, write_len = Curl_dyn_len(&pp->sendbuf); s = Curl_dyn_ptr(&pp->sendbuf); - Curl_pp_init(pp); + Curl_pp_init(data, pp); result = Curl_convert_to_network(data, s, write_len); /* Curl_convert_to_network calls failf if unsuccessful */ @@ -208,7 +207,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, #ifdef HAVE_GSSAPI conn->data_prot = PROT_CMD; #endif - result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len, + result = Curl_write(data, conn->sock[FIRSTSOCKET], s, write_len, &bytes_written); if(result) return result; @@ -246,14 +245,14 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, * * made to never block */ -CURLcode Curl_pp_sendf(struct pingpong *pp, +CURLcode Curl_pp_sendf(struct Curl_easy *data, struct pingpong *pp, const char *fmt, ...) { CURLcode result; va_list ap; va_start(ap, fmt); - result = Curl_pp_vsendf(pp, fmt, ap); + result = Curl_pp_vsendf(data, pp, fmt, ap); va_end(ap); @@ -265,7 +264,8 @@ CURLcode Curl_pp_sendf(struct pingpong *pp, * * Reads a piece of a server response. */ -CURLcode Curl_pp_readresp(curl_socket_t sockfd, +CURLcode Curl_pp_readresp(struct Curl_easy *data, + curl_socket_t sockfd, struct pingpong *pp, int *code, /* return the server code if done */ size_t *size) /* size of the response */ @@ -274,8 +274,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, bool keepon = TRUE; ssize_t gotbytes; char *ptr; - struct connectdata *conn = pp->conn; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; char * const buf = data->state.buffer; CURLcode result = CURLE_OK; @@ -315,7 +314,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, #endif DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <= (buf + data->set.buffer_size + 1)); - result = Curl_read(conn, sockfd, ptr, + result = Curl_read(data, sockfd, ptr, data->set.buffer_size - pp->nread_resp, &gotbytes); #ifdef HAVE_GSSAPI @@ -371,12 +370,12 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, * for "headers". The response lines can be seen as a kind of * headers. */ - result = Curl_client_write(conn, CLIENTWRITE_HEADER, + result = Curl_client_write(data, CLIENTWRITE_HEADER, pp->linestart_resp, perline); if(result) return result; - if(pp->endofresp(conn, pp->linestart_resp, perline, code)) { + if(pp->endofresp(data, conn, pp->linestart_resp, perline, code)) { /* This is the end of the last line, copy the last line to the start of the buffer and null-terminate, for old times sake */ size_t n = ptr - pp->linestart_resp; @@ -456,10 +455,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, return result; } -int Curl_pp_getsock(struct pingpong *pp, - curl_socket_t *socks) +int Curl_pp_getsock(struct Curl_easy *data, + struct pingpong *pp, curl_socket_t *socks) { - struct connectdata *conn = pp->conn; + struct connectdata *conn = data->conn; socks[0] = conn->sock[FIRSTSOCKET]; if(pp->sendleft) { @@ -471,13 +470,14 @@ int Curl_pp_getsock(struct pingpong *pp, return GETSOCK_READSOCK(0); } -CURLcode Curl_pp_flushsend(struct pingpong *pp) +CURLcode Curl_pp_flushsend(struct Curl_easy *data, + struct pingpong *pp) { /* we have a piece of a command still left to send */ - struct connectdata *conn = pp->conn; + struct connectdata *conn = data->conn; ssize_t written; curl_socket_t sock = conn->sock[FIRSTSOCKET]; - CURLcode result = Curl_write(conn, sock, pp->sendthis + pp->sendsize - + CURLcode result = Curl_write(data, sock, pp->sendthis + pp->sendsize - pp->sendleft, pp->sendleft, &written); if(result) return result; diff --git a/libs/libcurl/src/pingpong.h b/libs/libcurl/src/pingpong.h index 0d0c74afa0..4f7d7ea6b9 100644 --- a/libs/libcurl/src/pingpong.h +++ b/libs/libcurl/src/pingpong.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -62,37 +62,42 @@ struct pingpong { off, used to time-out response reading */ timediff_t response_time; /* When no timeout is given, this is the amount of milliseconds we await for a server response. */ - struct connectdata *conn; /* points to the connectdata struct that this - belongs to */ struct dynbuf sendbuf; /* Function pointers the protocols MUST implement and provide for the pingpong layer to function */ - CURLcode (*statemach_act)(struct connectdata *conn); - - bool (*endofresp)(struct connectdata *conn, char *ptr, size_t len, - int *code); + CURLcode (*statemachine)(struct Curl_easy *data, struct connectdata *conn); + bool (*endofresp)(struct Curl_easy *data, struct connectdata *conn, + char *ptr, size_t len, int *code); }; +#define PINGPONG_SETUP(pp,s,e) \ + do { \ + pp->response_time = RESP_TIMEOUT; \ + pp->statemachine = s; \ + pp->endofresp = e; \ + } while(0) + /* * Curl_pp_statemach() * * called repeatedly until done. Set 'wait' to make it wait a while on the * socket if there's no traffic. */ -CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, - bool disconnecting); +CURLcode Curl_pp_statemach(struct Curl_easy *data, struct pingpong *pp, + bool block, bool disconnecting); /* initialize stuff to prepare for reading a fresh new response */ -void Curl_pp_init(struct pingpong *pp); +void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp); /* setup for the transfer */ void Curl_pp_setup(struct pingpong *pp); /* Returns timeout in ms. 0 or negative number means the timeout has already triggered */ -timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting); +timediff_t Curl_pp_state_timeout(struct Curl_easy *data, + struct pingpong *pp, bool disconnecting); /*********************************************************************** @@ -105,7 +110,8 @@ timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting); * * made to never block */ -CURLcode Curl_pp_sendf(struct pingpong *pp, +CURLcode Curl_pp_sendf(struct Curl_easy *data, + struct pingpong *pp, const char *fmt, ...); /*********************************************************************** @@ -118,7 +124,8 @@ CURLcode Curl_pp_sendf(struct pingpong *pp, * * made to never block */ -CURLcode Curl_pp_vsendf(struct pingpong *pp, +CURLcode Curl_pp_vsendf(struct Curl_easy *data, + struct pingpong *pp, const char *fmt, va_list args); @@ -127,18 +134,21 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, * * Reads a piece of a server response. */ -CURLcode Curl_pp_readresp(curl_socket_t sockfd, +CURLcode Curl_pp_readresp(struct Curl_easy *data, + curl_socket_t sockfd, struct pingpong *pp, int *code, /* return the server code if done */ size_t *size); /* size of the response */ -CURLcode Curl_pp_flushsend(struct pingpong *pp); +CURLcode Curl_pp_flushsend(struct Curl_easy *data, + struct pingpong *pp); /* call this when a pingpong connection is disconnected */ CURLcode Curl_pp_disconnect(struct pingpong *pp); -int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks); +int Curl_pp_getsock(struct Curl_easy *data, struct pingpong *pp, + curl_socket_t *socks); /*********************************************************************** diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c index e71860e48a..0ed3d3ee18 100644 --- a/libs/libcurl/src/pop3.c +++ b/libs/libcurl/src/pop3.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -88,22 +88,27 @@ #include "memdebug.h" /* Local API functions */ -static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done); -static CURLcode pop3_do(struct connectdata *conn, bool *done); -static CURLcode pop3_done(struct connectdata *conn, CURLcode status, +static CURLcode pop3_regular_transfer(struct Curl_easy *data, bool *done); +static CURLcode pop3_do(struct Curl_easy *data, bool *done); +static CURLcode pop3_done(struct Curl_easy *data, CURLcode status, bool premature); -static CURLcode pop3_connect(struct connectdata *conn, bool *done); -static CURLcode pop3_disconnect(struct connectdata *conn, bool dead); -static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done); -static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks); -static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done); -static CURLcode pop3_setup_connection(struct connectdata *conn); +static CURLcode pop3_connect(struct Curl_easy *data, bool *done); +static CURLcode pop3_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); +static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done); +static int pop3_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); +static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done); +static CURLcode pop3_setup_connection(struct Curl_easy *data, + struct connectdata *conn); static CURLcode pop3_parse_url_options(struct connectdata *conn); -static CURLcode pop3_parse_url_path(struct connectdata *conn); -static CURLcode pop3_parse_custom_request(struct connectdata *conn); -static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech, +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 connectdata *conn, const char *resp); +static CURLcode pop3_continue_auth(struct Curl_easy *data, + struct connectdata *conn, const char *resp); static void pop3_get_message(char *buffer, char **outptr); /* @@ -195,10 +200,11 @@ static void pop3_to_pop3s(struct connectdata *conn) * capabilities from the CAPA response including the supported authentication * types and allowed SASL mechanisms. */ -static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len, - int *resp) +static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn, + char *line, size_t len, int *resp) { struct pop3_conn *pop3c = &conn->proto.pop3c; + (void)data; /* Do we have an error response? */ if(len >= 4 && !memcmp("-ERR", line, 4)) { @@ -279,9 +285,9 @@ static void pop3_get_message(char *buffer, char **outptr) * * This is the ONLY way to change POP3 state! */ -static void state(struct connectdata *conn, pop3state newstate) +static void state(struct Curl_easy *data, pop3state newstate) { - struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pop3_conn *pop3c = &data->conn->proto.pop3c; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* for debug purposes */ static const char * const names[] = { @@ -300,7 +306,7 @@ static void state(struct connectdata *conn, pop3state newstate) }; if(pop3c->state != newstate) - infof(conn->data, "POP3 %p state change from %s to %s\n", + infof(data, "POP3 %p state change from %s to %s\n", (void *)pop3c, names[pop3c->state], names[newstate]); #endif @@ -314,7 +320,8 @@ static void state(struct connectdata *conn, pop3state newstate) * Sends the CAPA command in order to obtain a list of server side supported * capabilities. */ -static CURLcode pop3_perform_capa(struct connectdata *conn) +static CURLcode pop3_perform_capa(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; @@ -324,10 +331,10 @@ static CURLcode pop3_perform_capa(struct connectdata *conn) pop3c->tls_supported = FALSE; /* Clear the TLS capability */ /* Send the CAPA command */ - result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA"); + result = Curl_pp_sendf(data, &pop3c->pp, "%s", "CAPA"); if(!result) - state(conn, POP3_CAPA); + state(data, POP3_CAPA); return result; } @@ -338,13 +345,14 @@ static CURLcode pop3_perform_capa(struct connectdata *conn) * * Sends the STLS command to start the upgrade to TLS. */ -static CURLcode pop3_perform_starttls(struct connectdata *conn) +static CURLcode pop3_perform_starttls(struct Curl_easy *data, + struct connectdata *conn) { /* Send the STLS command */ - CURLcode result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "STLS"); + CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "STLS"); if(!result) - state(conn, POP3_STARTTLS); + state(data, POP3_STARTTLS); return result; } @@ -355,20 +363,21 @@ static CURLcode pop3_perform_starttls(struct connectdata *conn) * * Performs the upgrade to TLS. */ -static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn) +static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data, + struct connectdata *conn) { /* Start the SSL connection */ struct pop3_conn *pop3c = &conn->proto.pop3c; - CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, &pop3c->ssldone); if(!result) { if(pop3c->state != POP3_UPGRADETLS) - state(conn, POP3_UPGRADETLS); + state(data, POP3_UPGRADETLS); if(pop3c->ssldone) { pop3_to_pop3s(conn); - result = pop3_perform_capa(conn); + result = pop3_perform_capa(data, conn); } } @@ -381,23 +390,24 @@ static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn) * * Sends a clear text USER command to authenticate with. */ -static CURLcode pop3_perform_user(struct connectdata *conn) +static CURLcode pop3_perform_user(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; /* Check we have a username and password to authenticate with and end the connect phase if we don't */ if(!conn->bits.user_passwd) { - state(conn, POP3_STOP); + state(data, POP3_STOP); return result; } /* Send the USER command */ - result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s", + result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "USER %s", conn->user ? conn->user : ""); if(!result) - state(conn, POP3_USER); + state(data, POP3_USER); return result; } @@ -409,7 +419,8 @@ static CURLcode pop3_perform_user(struct connectdata *conn) * * Sends an APOP command to authenticate with. */ -static CURLcode pop3_perform_apop(struct connectdata *conn) +static CURLcode pop3_perform_apop(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; @@ -421,7 +432,7 @@ static CURLcode pop3_perform_apop(struct connectdata *conn) /* Check we have a username and password to authenticate with and end the connect phase if we don't */ if(!conn->bits.user_passwd) { - state(conn, POP3_STOP); + state(data, POP3_STOP); return result; } @@ -444,10 +455,10 @@ static CURLcode pop3_perform_apop(struct connectdata *conn) for(i = 0; i < MD5_DIGEST_LEN; i++) msnprintf(&secret[2 * i], 3, "%02x", digest[i]); - result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret); + result = Curl_pp_sendf(data, &pop3c->pp, "APOP %s %s", conn->user, secret); if(!result) - state(conn, POP3_APOP); + state(data, POP3_APOP); return result; } @@ -460,7 +471,8 @@ static CURLcode pop3_perform_apop(struct connectdata *conn) * Sends an AUTH command allowing the client to login with the given SASL * authentication mechanism. */ -static CURLcode pop3_perform_auth(struct connectdata *conn, +static CURLcode pop3_perform_auth(struct Curl_easy *data, + struct connectdata *conn, const char *mech, const char *initresp) { @@ -469,11 +481,11 @@ static CURLcode pop3_perform_auth(struct connectdata *conn, if(initresp) { /* AUTH ... */ /* Send the AUTH command with the initial response */ - result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp); + result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s %s", mech, initresp); } else { /* Send the AUTH command */ - result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech); + result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s", mech); } return result; @@ -485,12 +497,13 @@ static CURLcode pop3_perform_auth(struct connectdata *conn, * * Sends SASL continuation data or cancellation. */ -static CURLcode pop3_continue_auth(struct connectdata *conn, +static CURLcode pop3_continue_auth(struct Curl_easy *data, + struct connectdata *conn, const char *resp) { struct pop3_conn *pop3c = &conn->proto.pop3c; - return Curl_pp_sendf(&pop3c->pp, "%s", resp); + return Curl_pp_sendf(data, &pop3c->pp, "%s", resp); } /*********************************************************************** @@ -501,7 +514,8 @@ static CURLcode pop3_continue_auth(struct connectdata *conn, * authentication mechanism, falling back to APOP and clear text should a * common mechanism not be available between the client and server. */ -static CURLcode pop3_perform_authentication(struct connectdata *conn) +static CURLcode pop3_perform_authentication(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; @@ -510,32 +524,32 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn) /* Check we have enough data to authenticate with and end the connect phase if we don't */ if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) { - state(conn, POP3_STOP); + state(data, POP3_STOP); return result; } if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) { /* Calculate the SASL login details */ - result = Curl_sasl_start(&pop3c->sasl, conn, FALSE, &progress); + result = Curl_sasl_start(&pop3c->sasl, data, conn, FALSE, &progress); if(!result) if(progress == SASL_INPROGRESS) - state(conn, POP3_AUTH); + state(data, POP3_AUTH); } if(!result && progress == SASL_IDLE) { #ifndef CURL_DISABLE_CRYPTO_AUTH if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) /* Perform APOP authentication */ - result = pop3_perform_apop(conn); + result = pop3_perform_apop(data, conn); else #endif if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) /* Perform clear text authentication */ - result = pop3_perform_user(conn); + result = pop3_perform_user(data, conn); else { /* Other mechanisms not supported */ - infof(conn->data, "No known authentication mechanisms supported!\n"); + infof(data, "No known authentication mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; } } @@ -549,15 +563,15 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn) * * Sends a POP3 based command. */ -static CURLcode pop3_perform_command(struct connectdata *conn) +static CURLcode pop3_perform_command(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct POP3 *pop3 = data->req.p.pop3; const char *command = NULL; /* Calculate the default command */ - if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) { + if(pop3->id[0] == '\0' || data->set.ftp_list_only) { command = "LIST"; if(pop3->id[0] != '\0') @@ -569,16 +583,16 @@ static CURLcode pop3_perform_command(struct connectdata *conn) /* Send the command */ if(pop3->id[0] != '\0') - result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s", + result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s %s", (pop3->custom && pop3->custom[0] != '\0' ? pop3->custom : command), pop3->id); else - result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", + result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", (pop3->custom && pop3->custom[0] != '\0' ? pop3->custom : command)); if(!result) - state(conn, POP3_COMMAND); + state(data, POP3_COMMAND); return result; } @@ -589,24 +603,25 @@ static CURLcode pop3_perform_command(struct connectdata *conn) * * Performs the quit action prior to sclose() be called. */ -static CURLcode pop3_perform_quit(struct connectdata *conn) +static CURLcode pop3_perform_quit(struct Curl_easy *data, + struct connectdata *conn) { /* Send the QUIT command */ - CURLcode result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "QUIT"); + CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "QUIT"); if(!result) - state(conn, POP3_QUIT); + state(data, POP3_QUIT); return result; } /* For the initial server greeting */ -static CURLcode pop3_state_servergreet_resp(struct connectdata *conn, +static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct pop3_conn *pop3c = &conn->proto.pop3c; const char *line = data->state.buffer; size_t len = strlen(line); @@ -654,18 +669,18 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn, } } - result = pop3_perform_capa(conn); + result = pop3_perform_capa(data, conn); } return result; } /* For CAPA responses */ -static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, +static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct pop3_conn *pop3c = &conn->proto.pop3c; const char *line = data->state.buffer; size_t len = strlen(line); @@ -728,36 +743,35 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, /* 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(conn); + result = pop3_perform_starttls(data, conn); else if(data->set.use_ssl == CURLUSESSL_TRY) /* Fallback and carry on with authentication */ - result = pop3_perform_authentication(conn); + result = pop3_perform_authentication(data, conn); else { failf(data, "STLS not supported."); result = CURLE_USE_SSL_FAILED; } } else - result = pop3_perform_authentication(conn); + result = pop3_perform_authentication(data, conn); } else { /* Clear text is supported when CAPA isn't recognised */ pop3c->authtypes |= POP3_TYPE_CLEARTEXT; - result = pop3_perform_authentication(conn); + result = pop3_perform_authentication(data, conn); } return result; } /* For STARTTLS responses */ -static CURLcode pop3_state_starttls_resp(struct connectdata *conn, +static CURLcode pop3_state_starttls_resp(struct Curl_easy *data, + struct connectdata *conn, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(pop3code != '+') { @@ -766,42 +780,42 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn, result = CURLE_USE_SSL_FAILED; } else - result = pop3_perform_authentication(conn); + result = pop3_perform_authentication(data, conn); } else - result = pop3_perform_upgrade_tls(conn); + result = pop3_perform_upgrade_tls(data, conn); return result; } /* For SASL authentication responses */ -static CURLcode pop3_state_auth_resp(struct connectdata *conn, +static CURLcode pop3_state_auth_resp(struct Curl_easy *data, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct pop3_conn *pop3c = &conn->proto.pop3c; saslprogress progress; (void)instate; /* no use for this yet */ - result = Curl_sasl_continue(&pop3c->sasl, conn, pop3code, &progress); + result = Curl_sasl_continue(&pop3c->sasl, data, conn, pop3code, &progress); if(!result) switch(progress) { case SASL_DONE: - state(conn, POP3_STOP); /* Authenticated */ + state(data, POP3_STOP); /* Authenticated */ break; case SASL_IDLE: /* No mechanism left after cancellation */ #ifndef CURL_DISABLE_CRYPTO_AUTH if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) /* Perform APOP authentication */ - result = pop3_perform_apop(conn); + result = pop3_perform_apop(data, conn); else #endif if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) /* Perform clear text authentication */ - result = pop3_perform_user(conn); + result = pop3_perform_user(data, conn); else { failf(data, "Authentication cancelled"); result = CURLE_LOGIN_DENIED; @@ -816,12 +830,10 @@ static CURLcode pop3_state_auth_resp(struct connectdata *conn, #ifndef CURL_DISABLE_CRYPTO_AUTH /* For APOP responses */ -static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code, +static CURLcode pop3_state_apop_resp(struct Curl_easy *data, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(pop3code != '+') { @@ -830,19 +842,18 @@ static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code, } else /* End of connect phase */ - state(conn, POP3_STOP); + state(data, POP3_STOP); return result; } #endif /* For USER responses */ -static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code, +static CURLcode pop3_state_user_resp(struct Curl_easy *data, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - + struct connectdata *conn = data->conn; (void)instate; /* no use for this yet */ if(pop3code != '+') { @@ -851,21 +862,19 @@ static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code, } else /* Send the PASS command */ - result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s", + result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "PASS %s", conn->passwd ? conn->passwd : ""); if(!result) - state(conn, POP3_PASS); + state(data, POP3_PASS); return result; } /* For PASS responses */ -static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code, +static CURLcode pop3_state_pass_resp(struct Curl_easy *data, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(pop3code != '+') { @@ -874,18 +883,18 @@ static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code, } else /* End of connect phase */ - state(conn, POP3_STOP); + state(data, POP3_STOP); return result; } /* For command responses */ -static CURLcode pop3_state_command_resp(struct connectdata *conn, +static CURLcode pop3_state_command_resp(struct Curl_easy *data, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct POP3 *pop3 = data->req.p.pop3; struct pop3_conn *pop3c = &conn->proto.pop3c; struct pingpong *pp = &pop3c->pp; @@ -893,7 +902,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn, (void)instate; /* no use for this yet */ if(pop3code != '+') { - state(conn, POP3_STOP); + state(data, POP3_STOP); return CURLE_RECV_ERROR; } @@ -917,7 +926,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn, "headers" after the body */ if(!data->set.opt_no_body) { - result = Curl_pop3_write(conn, pp->cache, pp->cache_size); + result = Curl_pop3_write(data, pp->cache, pp->cache_size); if(result) return result; } @@ -931,12 +940,13 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn, } /* End of DO phase */ - state(conn, POP3_STOP); + state(data, POP3_STOP); return result; } -static CURLcode pop3_statemach_act(struct connectdata *conn) +static CURLcode pop3_statemachine(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; curl_socket_t sock = conn->sock[FIRSTSOCKET]; @@ -944,20 +954,21 @@ static CURLcode pop3_statemach_act(struct connectdata *conn) struct pop3_conn *pop3c = &conn->proto.pop3c; struct pingpong *pp = &pop3c->pp; size_t nread = 0; + (void)data; /* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */ if(pop3c->state == POP3_UPGRADETLS) - return pop3_perform_upgrade_tls(conn); + return pop3_perform_upgrade_tls(data, conn); /* Flush any data that needs to be sent */ if(pp->sendleft) - return Curl_pp_flushsend(pp); + return Curl_pp_flushsend(data, pp); do { /* Read the response from the server */ - result = Curl_pp_readresp(sock, pp, &pop3code, &nread); - if(result) - return result; + result = Curl_pp_readresp(data, sock, pp, &pop3code, &nread); + if(result) + return result; if(!pop3code) break; @@ -965,44 +976,44 @@ static CURLcode pop3_statemach_act(struct connectdata *conn) /* We have now received a full POP3 server response */ switch(pop3c->state) { case POP3_SERVERGREET: - result = pop3_state_servergreet_resp(conn, pop3code, pop3c->state); + result = pop3_state_servergreet_resp(data, pop3code, pop3c->state); break; case POP3_CAPA: - result = pop3_state_capa_resp(conn, pop3code, pop3c->state); + result = pop3_state_capa_resp(data, pop3code, pop3c->state); break; case POP3_STARTTLS: - result = pop3_state_starttls_resp(conn, pop3code, pop3c->state); + result = pop3_state_starttls_resp(data, conn, pop3code, pop3c->state); break; case POP3_AUTH: - result = pop3_state_auth_resp(conn, pop3code, pop3c->state); + result = pop3_state_auth_resp(data, pop3code, pop3c->state); break; #ifndef CURL_DISABLE_CRYPTO_AUTH case POP3_APOP: - result = pop3_state_apop_resp(conn, pop3code, pop3c->state); + result = pop3_state_apop_resp(data, pop3code, pop3c->state); break; #endif case POP3_USER: - result = pop3_state_user_resp(conn, pop3code, pop3c->state); + result = pop3_state_user_resp(data, pop3code, pop3c->state); break; case POP3_PASS: - result = pop3_state_pass_resp(conn, pop3code, pop3c->state); + result = pop3_state_pass_resp(data, pop3code, pop3c->state); break; case POP3_COMMAND: - result = pop3_state_command_resp(conn, pop3code, pop3c->state); + result = pop3_state_command_resp(data, pop3code, pop3c->state); break; case POP3_QUIT: /* fallthrough, just stop! */ default: /* internal error */ - state(conn, POP3_STOP); + state(data, POP3_STOP); break; } } while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp)); @@ -1011,41 +1022,43 @@ static CURLcode pop3_statemach_act(struct connectdata *conn) } /* Called repeatedly until done from multi.c */ -static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done) +static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct pop3_conn *pop3c = &conn->proto.pop3c; if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) { - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone); + result = Curl_ssl_connect_nonblocking(data, conn, + FIRSTSOCKET, &pop3c->ssldone); if(result || !pop3c->ssldone) return result; } - result = Curl_pp_statemach(&pop3c->pp, FALSE, FALSE); + result = Curl_pp_statemach(data, &pop3c->pp, FALSE, FALSE); *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE; return result; } -static CURLcode pop3_block_statemach(struct connectdata *conn, +static CURLcode pop3_block_statemach(struct Curl_easy *data, + struct connectdata *conn, bool disconnecting) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; while(pop3c->state != POP3_STOP && !result) - result = Curl_pp_statemach(&pop3c->pp, TRUE, disconnecting); + result = Curl_pp_statemach(data, &pop3c->pp, TRUE, disconnecting); return result; } /* Allocate and initialize the POP3 struct for the current Curl_easy if required */ -static CURLcode pop3_init(struct connectdata *conn) +static CURLcode pop3_init(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct POP3 *pop3; pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1); @@ -1056,9 +1069,10 @@ static CURLcode pop3_init(struct connectdata *conn) } /* For the POP3 "protocol connect" and "doing" phases only */ -static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks) +static int pop3_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { - return Curl_pp_getsock(&conn->proto.pop3c.pp, socks); + return Curl_pp_getsock(data, &conn->proto.pop3c.pp, socks); } /*********************************************************************** @@ -1071,9 +1085,10 @@ static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks) * The variable 'done' points to will be TRUE if the protocol-layer connect * phase is done when this function returns, or FALSE if not. */ -static CURLcode pop3_connect(struct connectdata *conn, bool *done) +static CURLcode pop3_connect(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct pop3_conn *pop3c = &conn->proto.pop3c; struct pingpong *pp = &pop3c->pp; @@ -1082,11 +1097,7 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done) /* We always support persistent connections in POP3 */ connkeep(conn, "POP3 default"); - /* Set the default response time-out */ - pp->response_time = RESP_TIMEOUT; - pp->statemach_act = pop3_statemach_act; - pp->endofresp = pop3_endofresp; - pp->conn = conn; + PINGPONG_SETUP(pp, pop3_statemachine, pop3_endofresp); /* Set the default preferred authentication type and mechanism */ pop3c->preftype = POP3_TYPE_ANY; @@ -1094,7 +1105,7 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done) /* Initialise the pingpong layer */ Curl_pp_setup(pp); - Curl_pp_init(pp); + Curl_pp_init(data, pp); /* Parse the URL options */ result = pop3_parse_url_options(conn); @@ -1102,9 +1113,9 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done) return result; /* Start off waiting for the server greeting response */ - state(conn, POP3_SERVERGREET); + state(data, POP3_SERVERGREET); - result = pop3_multi_statemach(conn, done); + result = pop3_multi_statemach(data, done); return result; } @@ -1118,11 +1129,10 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done) * * Input argument is already checked for validity. */ -static CURLcode pop3_done(struct connectdata *conn, CURLcode status, +static CURLcode pop3_done(struct Curl_easy *data, CURLcode status, bool premature) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct POP3 *pop3 = data->req.p.pop3; (void)premature; @@ -1131,7 +1141,7 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status, return CURLE_OK; if(status) { - connclose(conn, "POP3 done with bad status"); + connclose(data->conn, "POP3 done with bad status"); result = status; /* use the already set error code */ } @@ -1152,16 +1162,17 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status, * This is the actual DO function for POP3. Get a message/listing according to * the options previously setup. */ -static CURLcode pop3_perform(struct connectdata *conn, bool *connected, +static CURLcode pop3_perform(struct Curl_easy *data, bool *connected, bool *dophase_done) { /* This is POP3 and no proxy */ CURLcode result = CURLE_OK; - struct POP3 *pop3 = conn->data->req.p.pop3; + struct connectdata *conn = data->conn; + struct POP3 *pop3 = data->req.p.pop3; - DEBUGF(infof(conn->data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts\n")); - if(conn->data->set.opt_no_body) { + if(data->set.opt_no_body) { /* Requested no body means no transfer */ pop3->transfer = FTPTRANSFER_INFO; } @@ -1169,17 +1180,16 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected, *dophase_done = FALSE; /* not done yet */ /* Start the first command in the DO phase */ - result = pop3_perform_command(conn); + result = pop3_perform_command(data); if(result) return result; /* Run the state-machine */ - result = pop3_multi_statemach(conn, dophase_done); - + result = pop3_multi_statemach(data, dophase_done); *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); return result; } @@ -1193,23 +1203,22 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected, * * The input argument is already checked for validity. */ -static CURLcode pop3_do(struct connectdata *conn, bool *done) +static CURLcode pop3_do(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; - *done = FALSE; /* default to false */ /* Parse the URL path */ - result = pop3_parse_url_path(conn); + result = pop3_parse_url_path(data); if(result) return result; /* Parse the custom request */ - result = pop3_parse_custom_request(conn); + result = pop3_parse_custom_request(data); if(result) return result; - result = pop3_regular_transfer(conn, done); + result = pop3_regular_transfer(data, done); return result; } @@ -1221,19 +1230,20 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done) * Disconnect from an POP3 server. Cleanup protocol-specific per-connection * resources. BLOCKING. */ -static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode pop3_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { struct pop3_conn *pop3c = &conn->proto.pop3c; + (void)data; /* We cannot send quit unconditionally. If this connection is stale or bad in any way, sending quit and waiting around here will make the disconnect wait in vain and cause more problems than we need to. */ - /* The POP3 session may or may not have been allocated/setup at this - point! */ - if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart) - if(!pop3_perform_quit(conn)) - (void)pop3_block_statemach(conn, TRUE); /* ignore errors on QUIT */ + if(!dead_connection && conn->bits.protoconnstart) { + if(!pop3_perform_quit(data, conn)) + (void)pop3_block_statemach(data, conn, TRUE); /* ignore errors on QUIT */ + } /* Disconnect from the server */ Curl_pp_disconnect(&pop3c->pp); @@ -1248,25 +1258,25 @@ static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection) } /* Call this when the DO phase has completed */ -static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected) +static CURLcode pop3_dophase_done(struct Curl_easy *data, bool connected) { - (void)conn; + (void)data; (void)connected; return CURLE_OK; } /* Called from multi.c while DOing */ -static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done) +static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done) { - CURLcode result = pop3_multi_statemach(conn, dophase_done); + CURLcode result = pop3_multi_statemach(data, dophase_done); if(result) - DEBUGF(infof(conn->data, "DO phase failed\n")); + DEBUGF(infof(data, "DO phase failed\n")); else if(*dophase_done) { - result = pop3_dophase_done(conn, FALSE /* not connected */); + result = pop3_dophase_done(data, FALSE /* not connected */); - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; @@ -1281,12 +1291,11 @@ static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done) * Performs all commands done before a regular transfer between a local and a * remote host. */ -static CURLcode pop3_regular_transfer(struct connectdata *conn, +static CURLcode pop3_regular_transfer(struct Curl_easy *data, bool *dophase_done) { CURLcode result = CURLE_OK; bool connected = FALSE; - struct Curl_easy *data = conn->data; /* Make sure size is unknown at this point */ data->req.size = -1; @@ -1298,19 +1307,20 @@ static CURLcode pop3_regular_transfer(struct connectdata *conn, Curl_pgrsSetDownloadSize(data, -1); /* Carry out the perform */ - result = pop3_perform(conn, &connected, dophase_done); + result = pop3_perform(data, &connected, dophase_done); /* Perform post DO phase operations if necessary */ if(!result && *dophase_done) - result = pop3_dophase_done(conn, connected); + result = pop3_dophase_done(data, connected); return result; } -static CURLcode pop3_setup_connection(struct connectdata *conn) +static CURLcode pop3_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { /* Initialise the POP3 layer */ - CURLcode result = pop3_init(conn); + CURLcode result = pop3_init(data); if(result) return result; @@ -1385,10 +1395,9 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn) * * Parse the URL path into separate path components. */ -static CURLcode pop3_parse_url_path(struct connectdata *conn) +static CURLcode pop3_parse_url_path(struct Curl_easy *data) { /* The POP3 struct is already initialised in pop3_connect() */ - struct Curl_easy *data = conn->data; struct POP3 *pop3 = data->req.p.pop3; const char *path = &data->state.up.path[1]; /* skip leading path */ @@ -1402,10 +1411,9 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn) * * Parse the custom request. */ -static CURLcode pop3_parse_custom_request(struct connectdata *conn) +static CURLcode pop3_parse_custom_request(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct POP3 *pop3 = data->req.p.pop3; const char *custom = data->set.str[STRING_CUSTOMREQUEST]; @@ -1423,13 +1431,12 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn) * This function scans the body after the end-of-body and writes everything * until the end is found. */ -CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread) +CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread) { /* This code could be made into a special function in the handler struct */ CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct SingleRequest *k = &data->req; - + struct connectdata *conn = data->conn; struct pop3_conn *pop3c = &conn->proto.pop3c; bool strip_dot = FALSE; size_t last = 0; @@ -1450,7 +1457,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread) if(i) { /* Write out the body part that didn't match */ - result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last], + result = Curl_client_write(data, CLIENTWRITE_BODY, &str[last], i - last); if(result) @@ -1508,7 +1515,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread) if(prev) { /* If the partial match was the CRLF and dot then only write the CRLF as the server would have inserted the dot */ - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB, strip_dot ? prev - 1 : prev); if(result) @@ -1524,7 +1531,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread) /* We have a full match so the transfer is done, however we must transfer the CRLF at the start of the EOB as this is considered to be part of the message as per RFC-1939, sect. 3 */ - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, 2); + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB, 2); k->keepon &= ~KEEP_RECV; pop3c->eob = 0; @@ -1537,7 +1544,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread) return CURLE_OK; if(nread - last) { - result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last], + result = Curl_client_write(data, CLIENTWRITE_BODY, &str[last], nread - last); } diff --git a/libs/libcurl/src/pop3.h b/libs/libcurl/src/pop3.h index 6ca3fd511f..17629ee2df 100644 --- a/libs/libcurl/src/pop3.h +++ b/libs/libcurl/src/pop3.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2009 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2009 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -61,6 +61,7 @@ struct pop3_conn { struct pingpong pp; pop3state state; /* Always use pop3.c:state() to change state! */ bool ssldone; /* Is connect() over SSL done? */ + bool tls_supported; /* StartTLS capability supported by server */ size_t eob; /* Number of bytes of the EOB (End Of Body) that have been received so far */ size_t strip; /* Number of bytes from the start to ignore as @@ -69,7 +70,6 @@ struct pop3_conn { unsigned int authtypes; /* Accepted authentication types */ unsigned int preftype; /* Preferred authentication type */ char *apoptimestamp; /* APOP timestamp from the server greeting */ - bool tls_supported; /* StartTLS capability supported by server */ }; extern const struct Curl_handler Curl_handler_pop3; @@ -90,6 +90,6 @@ extern const struct Curl_handler Curl_handler_pop3s; /* This function scans the body after the end-of-body and writes everything * until the end is found */ -CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread); +CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread); #endif /* HEADER_CURL_POP3_H */ diff --git a/libs/libcurl/src/progress.c b/libs/libcurl/src/progress.c index 658d05ab8e..55e8ded04d 100644 --- a/libs/libcurl/src/progress.c +++ b/libs/libcurl/src/progress.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -137,12 +137,11 @@ static char *max5data(curl_off_t bytes, char *max5) */ -int Curl_pgrsDone(struct connectdata *conn) +int Curl_pgrsDone(struct Curl_easy *data) { int rc; - struct Curl_easy *data = conn->data; data->progress.lastshow = 0; - rc = Curl_pgrsUpdate(conn); /* the final (forced) update */ + rc = Curl_pgrsUpdate(data); /* the final (forced) update */ if(rc) return rc; @@ -371,11 +370,10 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size) } /* returns TRUE if it's time to show the progress meter */ -static bool progress_calc(struct connectdata *conn, struct curltime now) +static bool progress_calc(struct Curl_easy *data, struct curltime now) { curl_off_t timespent; curl_off_t timespent_ms; /* milliseconds */ - struct Curl_easy *data = conn->data; curl_off_t dl = data->progress.downloaded; curl_off_t ul = data->progress.uploaded; bool timetoshow = FALSE; @@ -465,9 +463,8 @@ static bool progress_calc(struct connectdata *conn, struct curltime now) } #ifndef CURL_DISABLE_PROGRESS_METER -static void progress_meter(struct connectdata *conn) +static void progress_meter(struct Curl_easy *data) { - struct Curl_easy *data = conn->data; char max5[6][10]; curl_off_t dlpercen = 0; curl_off_t ulpercen = 0; @@ -581,11 +578,10 @@ static void progress_meter(struct connectdata *conn) * Curl_pgrsUpdate() returns 0 for success or the value returned by the * progress callback! */ -int Curl_pgrsUpdate(struct connectdata *conn) +int Curl_pgrsUpdate(struct Curl_easy *data) { - struct Curl_easy *data = conn->data; struct curltime now = Curl_now(); /* what time is it */ - bool showprogress = progress_calc(conn, now); + bool showprogress = progress_calc(data, now); if(!(data->progress.flags & PGRS_HIDE)) { if(data->set.fxferinfo) { int result; @@ -621,7 +617,7 @@ int Curl_pgrsUpdate(struct connectdata *conn) } if(showprogress) - progress_meter(conn); + progress_meter(data); } return 0; diff --git a/libs/libcurl/src/progress.h b/libs/libcurl/src/progress.h index 74680099f0..ac4ebc0980 100644 --- a/libs/libcurl/src/progress.h +++ b/libs/libcurl/src/progress.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -40,14 +40,14 @@ typedef enum { TIMER_LAST /* must be last */ } timerid; -int Curl_pgrsDone(struct connectdata *); +int Curl_pgrsDone(struct Curl_easy *data); void Curl_pgrsStartNow(struct Curl_easy *data); void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size); void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size); void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size); void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size); void Curl_ratelimit(struct Curl_easy *data, struct curltime now); -int Curl_pgrsUpdate(struct connectdata *); +int Curl_pgrsUpdate(struct Curl_easy *data); void Curl_pgrsResetTransferSizes(struct Curl_easy *data); struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer); timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize, diff --git a/libs/libcurl/src/quic.h b/libs/libcurl/src/quic.h index f04662e820..947f13edcf 100644 --- a/libs/libcurl/src/quic.h +++ b/libs/libcurl/src/quic.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,25 +35,28 @@ #include "urldata.h" /* functions provided by the specific backends */ -CURLcode Curl_quic_connect(struct connectdata *conn, +CURLcode Curl_quic_connect(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t sockfd, int sockindex, const struct sockaddr *addr, socklen_t addrlen); -CURLcode Curl_quic_is_connected(struct connectdata *conn, +CURLcode Curl_quic_is_connected(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool *connected); int Curl_quic_ver(char *p, size_t len); -CURLcode Curl_quic_done_sending(struct connectdata *conn); +CURLcode Curl_quic_done_sending(struct Curl_easy *data); void Curl_quic_done(struct Curl_easy *data, bool premature); bool Curl_quic_data_pending(const struct Curl_easy *data); -void Curl_quic_disconnect(struct connectdata *conn, int tempindex); +void Curl_quic_disconnect(struct Curl_easy *data, + struct connectdata *conn, int tempindex); #else /* ENABLE_QUIC */ #define Curl_quic_done_sending(x) #define Curl_quic_done(x,y) #define Curl_quic_data_pending(x) -#define Curl_quic_disconnect(x,y) +#define Curl_quic_disconnect(x,y,z) #endif /* !ENABLE_QUIC */ #endif /* HEADER_CURL_QUIC_H */ diff --git a/libs/libcurl/src/rtsp.c b/libs/libcurl/src/rtsp.c index 151ff4af27..55766757a8 100644 --- a/libs/libcurl/src/rtsp.c +++ b/libs/libcurl/src/rtsp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * 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" -#ifndef CURL_DISABLE_RTSP +#if !defined(CURL_DISABLE_RTSP) && !defined(USE_HYPER) #include "urldata.h" #include @@ -48,11 +48,13 @@ ((int)((unsigned char)((p)[3])))) /* protocol-specific functions set up to be called by the main engine */ -static CURLcode rtsp_do(struct connectdata *conn, bool *done); -static CURLcode rtsp_done(struct connectdata *conn, CURLcode, bool premature); -static CURLcode rtsp_connect(struct connectdata *conn, bool *done); -static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead); -static int rtsp_getsock_do(struct connectdata *conn, curl_socket_t *socks); +static CURLcode rtsp_do(struct Curl_easy *data, bool *done); +static CURLcode rtsp_done(struct Curl_easy *data, CURLcode, bool premature); +static CURLcode rtsp_connect(struct Curl_easy *data, bool *done); +static CURLcode rtsp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); +static int rtsp_getsock_do(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); /* * Parse and write out any available RTP data. @@ -66,23 +68,26 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, ssize_t *nread, bool *readmore); -static CURLcode rtsp_setup_connection(struct connectdata *conn); -static unsigned int rtsp_conncheck(struct connectdata *check, +static CURLcode rtsp_setup_connection(struct Curl_easy *data, + struct connectdata *conn); +static unsigned int rtsp_conncheck(struct Curl_easy *data, + struct connectdata *check, unsigned int checks_to_perform); /* this returns the socket to wait for in the DO and DOING state for the multi interface and then we're always _sending_ a request and thus we wait for the single socket to become writable only */ -static int rtsp_getsock_do(struct connectdata *conn, +static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn, curl_socket_t *socks) { /* write mode */ + (void)data; socks[0] = conn->sock[FIRSTSOCKET]; return GETSOCK_WRITESOCK(0); } static -CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len); +CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len); /* @@ -111,11 +116,13 @@ const struct Curl_handler Curl_handler_rtsp = { }; -static CURLcode rtsp_setup_connection(struct connectdata *conn) +static CURLcode rtsp_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { struct RTSP *rtsp; + (void)conn; - conn->data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP)); + data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP)); if(!rtsp) return CURLE_OUT_OF_MEMORY; @@ -156,13 +163,15 @@ static bool rtsp_connisdead(struct connectdata *check) /* * Function to check on various aspects of a connection. */ -static unsigned int rtsp_conncheck(struct connectdata *check, +static unsigned int rtsp_conncheck(struct Curl_easy *data, + struct connectdata *conn, unsigned int checks_to_perform) { unsigned int ret_val = CONNRESULT_NONE; + (void)data; if(checks_to_perform & CONNCHECK_ISDEAD) { - if(rtsp_connisdead(check)) + if(rtsp_connisdead(conn)) ret_val |= CONNRESULT_DEAD; } @@ -170,12 +179,11 @@ static unsigned int rtsp_conncheck(struct connectdata *check, } -static CURLcode rtsp_connect(struct connectdata *conn, bool *done) +static CURLcode rtsp_connect(struct Curl_easy *data, bool *done) { CURLcode httpStatus; - struct Curl_easy *data = conn->data; - httpStatus = Curl_http_connect(conn, done); + httpStatus = Curl_http_connect(data, done); /* Initialize the CSeq if not already done */ if(data->state.rtsp_next_client_CSeq == 0) @@ -183,23 +191,24 @@ static CURLcode rtsp_connect(struct connectdata *conn, bool *done) if(data->state.rtsp_next_server_CSeq == 0) data->state.rtsp_next_server_CSeq = 1; - conn->proto.rtspc.rtp_channel = -1; + data->conn->proto.rtspc.rtp_channel = -1; return httpStatus; } -static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead) +static CURLcode rtsp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead) { (void) dead; + (void) data; Curl_safefree(conn->proto.rtspc.rtp_buf); return CURLE_OK; } -static CURLcode rtsp_done(struct connectdata *conn, +static CURLcode rtsp_done(struct Curl_easy *data, CURLcode status, bool premature) { - struct Curl_easy *data = conn->data; struct RTSP *rtsp = data->req.p.rtsp; CURLcode httpStatus; @@ -207,7 +216,7 @@ static CURLcode rtsp_done(struct connectdata *conn, if(data->set.rtspreq == RTSPREQ_RECEIVE) premature = TRUE; - httpStatus = Curl_http_done(conn, status, premature); + httpStatus = Curl_http_done(data, status, premature); if(rtsp) { /* Check the sequence numbers */ @@ -220,7 +229,7 @@ static CURLcode rtsp_done(struct connectdata *conn, return CURLE_RTSP_CSEQ_ERROR; } if(data->set.rtspreq == RTSPREQ_RECEIVE && - (conn->proto.rtspc.rtp_channel == -1)) { + (data->conn->proto.rtspc.rtp_channel == -1)) { infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv); } } @@ -228,9 +237,9 @@ static CURLcode rtsp_done(struct connectdata *conn, return httpStatus; } -static CURLcode rtsp_do(struct connectdata *conn, bool *done) +static CURLcode rtsp_do(struct Curl_easy *data, bool *done) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; CURLcode result = CURLE_OK; Curl_RtspReq rtspreq = data->set.rtspreq; struct RTSP *rtsp = data->req.p.rtsp; @@ -330,7 +339,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) } /* Transport Header for SETUP requests */ - p_transport = Curl_checkheaders(conn, "Transport"); + p_transport = Curl_checkheaders(data, "Transport"); if(rtspreq == RTSPREQ_SETUP && !p_transport) { /* New Transport: setting? */ if(data->set.str[STRING_RTSP_TRANSPORT]) { @@ -354,11 +363,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) /* Accept Headers for DESCRIBE requests */ if(rtspreq == RTSPREQ_DESCRIBE) { /* Accept Header */ - p_accept = Curl_checkheaders(conn, "Accept")? + p_accept = Curl_checkheaders(data, "Accept")? NULL:"Accept: application/sdp\r\n"; /* Accept-Encoding header */ - if(!Curl_checkheaders(conn, "Accept-Encoding") && + if(!Curl_checkheaders(data, "Accept-Encoding") && data->set.str[STRING_ENCODING]) { Curl_safefree(data->state.aptr.accept_encoding); data->state.aptr.accept_encoding = @@ -375,17 +384,18 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) it might have been used in the proxy connect, but if we have got a header with the user-agent string specified, we erase the previously made string here. */ - if(Curl_checkheaders(conn, "User-Agent") && data->state.aptr.uagent) { + if(Curl_checkheaders(data, "User-Agent") && data->state.aptr.uagent) { Curl_safefree(data->state.aptr.uagent); data->state.aptr.uagent = NULL; } - else if(!Curl_checkheaders(conn, "User-Agent") && + else if(!Curl_checkheaders(data, "User-Agent") && data->set.str[STRING_USERAGENT]) { p_uagent = data->state.aptr.uagent; } /* setup the authentication headers */ - result = Curl_http_output_auth(conn, p_request, p_stream_uri, FALSE); + result = Curl_http_output_auth(data, conn, p_request, HTTPREQ_GET, + p_stream_uri, FALSE); if(result) return result; @@ -394,7 +404,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) /* Referrer */ Curl_safefree(data->state.aptr.ref); - if(data->change.referer && !Curl_checkheaders(conn, "Referer")) + if(data->change.referer && !Curl_checkheaders(data, "Referer")) data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer); else data->state.aptr.ref = NULL; @@ -411,7 +421,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) (rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) { /* Check to see if there is a range set in the custom headers */ - if(!Curl_checkheaders(conn, "Range") && data->state.range) { + if(!Curl_checkheaders(data, "Range") && data->state.range) { Curl_safefree(data->state.aptr.rangeline); data->state.aptr.rangeline = aprintf("Range: %s\r\n", data->state.range); p_range = data->state.aptr.rangeline; @@ -421,11 +431,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) /* * Sanity check the custom headers */ - if(Curl_checkheaders(conn, "CSeq")) { + if(Curl_checkheaders(data, "CSeq")) { failf(data, "CSeq cannot be set as a custom header."); return CURLE_RTSP_CSEQ_ERROR; } - if(Curl_checkheaders(conn, "Session")) { + if(Curl_checkheaders(data, "Session")) { failf(data, "Session ID cannot be set as a custom header."); return CURLE_BAD_FUNCTION_ARGUMENT; } @@ -484,12 +494,12 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) return result; if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) { - result = Curl_add_timecondition(conn, &req_buffer); + result = Curl_add_timecondition(data, &req_buffer); if(result) return result; } - result = Curl_add_custom_headers(conn, FALSE, &req_buffer); + result = Curl_add_custom_headers(data, FALSE, &req_buffer); if(result) return result; @@ -512,7 +522,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) if(putsize > 0 || postsize > 0) { /* As stated in the http comments, it is probably not wise to * actually set a custom Content-Length in the headers */ - if(!Curl_checkheaders(conn, "Content-Length")) { + if(!Curl_checkheaders(data, "Content-Length")) { result = Curl_dyn_addf(&req_buffer, "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n", @@ -523,7 +533,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) if(rtspreq == RTSPREQ_SET_PARAMETER || rtspreq == RTSPREQ_GET_PARAMETER) { - if(!Curl_checkheaders(conn, "Content-Type")) { + if(!Curl_checkheaders(data, "Content-Type")) { result = Curl_dyn_addf(&req_buffer, "Content-Type: text/parameters\r\n"); if(result) @@ -532,7 +542,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) } if(rtspreq == RTSPREQ_ANNOUNCE) { - if(!Curl_checkheaders(conn, "Content-Type")) { + if(!Curl_checkheaders(data, "Content-Type")) { result = Curl_dyn_addf(&req_buffer, "Content-Type: application/sdp\r\n"); if(result) @@ -564,7 +574,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) } /* issue the request */ - result = Curl_buffer_send(&req_buffer, conn, + result = Curl_buffer_send(&req_buffer, data, &data->info.request_size, 0, FIRSTSOCKET); if(result) { failf(data, "Failed sending RTSP request"); @@ -580,7 +590,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) /* if a request-body has been sent off, we make sure this progress is noted properly */ Curl_pgrsSetUploadCounter(data, data->req.writebytecount); - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; } @@ -642,7 +652,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, * Write out the header including the leading '$' */ DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n", rtspc->rtp_channel, rtp_length)); - result = rtp_client_write(conn, &rtp[0], rtp_length + 4); + result = rtp_client_write(data, &rtp[0], rtp_length + 4); if(result) { failf(data, "Got an error writing an RTP packet"); *readmore = FALSE; @@ -713,9 +723,8 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, } static -CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len) +CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len) { - struct Curl_easy *data = conn->data; size_t wrote; curl_write_callback writeit; void *user_ptr; @@ -755,10 +764,8 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len) return CURLE_OK; } -CURLcode Curl_rtsp_parseheader(struct connectdata *conn, - char *header) +CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header) { - struct Curl_easy *data = conn->data; long CSeq = 0; if(checkprefix("CSeq:", header)) { @@ -826,4 +833,4 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn, return CURLE_OK; } -#endif /* CURL_DISABLE_RTSP */ +#endif /* CURL_DISABLE_RTSP or using Hyper */ diff --git a/libs/libcurl/src/rtsp.h b/libs/libcurl/src/rtsp.h index bf7f0bc8ef..1e9cb7d2c9 100644 --- a/libs/libcurl/src/rtsp.h +++ b/libs/libcurl/src/rtsp.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -21,11 +21,15 @@ * KIND, either express or implied. * ***************************************************************************/ +#ifdef USE_HYPER +#define CURL_DISABLE_RTSP +#endif + #ifndef CURL_DISABLE_RTSP extern const struct Curl_handler Curl_handler_rtsp; -CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header); +CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header); #else /* disabled */ diff --git a/libs/libcurl/src/select.c b/libs/libcurl/src/select.c index 7d1f944cdb..d7346b195f 100644 --- a/libs/libcurl/src/select.c +++ b/libs/libcurl/src/select.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -130,6 +130,7 @@ int Curl_wait_ms(timediff_t timeout_ms) return r; } +#ifndef HAVE_POLL_FINE /* * This is a wrapper around select() to aid in Windows compatibility. * A negative timeout value makes this function wait indefinitely, @@ -141,11 +142,11 @@ int Curl_wait_ms(timediff_t timeout_ms) * 0 = timeout * N = number of signalled file descriptors */ -int Curl_select(curl_socket_t maxfd, /* highest socket number */ - fd_set *fds_read, /* sockets ready for reading */ - fd_set *fds_write, /* sockets ready for writing */ - fd_set *fds_err, /* sockets with errors */ - timediff_t timeout_ms) /* milliseconds to wait */ +static int our_select(curl_socket_t maxfd, /* highest socket number */ + fd_set *fds_read, /* sockets ready for reading */ + fd_set *fds_write, /* sockets ready for writing */ + fd_set *fds_err, /* sockets with errors */ + timediff_t timeout_ms) /* milliseconds to wait */ { struct timeval pending_tv; struct timeval *ptimeout; @@ -220,6 +221,8 @@ int Curl_select(curl_socket_t maxfd, /* highest socket number */ #endif } +#endif + /* * Wait for read or write events on a set of file descriptors. It uses poll() * when a fine poll() is available, in order to avoid limits with FD_SETSIZE, @@ -412,7 +415,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) curl_socket_t is unsigned in such cases and thus -1 is the largest value). */ - r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms); + r = our_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms); if(r <= 0) return r; diff --git a/libs/libcurl/src/select.h b/libs/libcurl/src/select.h index 1350950439..4db64877bb 100644 --- a/libs/libcurl/src/select.h +++ b/libs/libcurl/src/select.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -72,12 +72,6 @@ struct pollfd therefore defined here */ #define CURL_CSELECT_IN2 (CURL_CSELECT_ERR << 1) -int Curl_select(curl_socket_t maxfd, - fd_set *fds_read, - fd_set *fds_write, - fd_set *fds_err, - timediff_t timeout_ms); - int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, curl_socket_t writefd, timediff_t timeout_ms); diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c index 04cc725f5a..b3c7fe33d3 100644 --- a/libs/libcurl/src/sendf.c +++ b/libs/libcurl/src/sendf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -142,7 +142,8 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) psnd->recv_size > psnd->recv_processed; } -static CURLcode pre_receive_plain(struct connectdata *conn, int num) +static CURLcode pre_receive_plain(struct Curl_easy *data, + struct connectdata *conn, int num) { const curl_socket_t sockfd = conn->sock[num]; struct postponed_data * const psnd = &(conn->postponed[num]); @@ -161,7 +162,7 @@ static CURLcode pre_receive_plain(struct connectdata *conn, int num) /* Have some incoming data */ if(!psnd->buffer) { /* Use buffer double default size for intermediate buffer */ - psnd->allocated_size = 2 * conn->data->set.buffer_size; + psnd->allocated_size = 2 * data->set.buffer_size; psnd->buffer = malloc(psnd->allocated_size); if(!psnd->buffer) return CURLE_OUT_OF_MEMORY; @@ -230,7 +231,7 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) (void)sockindex; return false; } -#define pre_receive_plain(c,n) CURLE_OK +#define pre_receive_plain(d,c,n) CURLE_OK #define get_pre_recved(c,n,b,l) 0 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ @@ -267,6 +268,7 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...) void Curl_failf(struct Curl_easy *data, const char *fmt, ...) { + DEBUGASSERT(!strchr(fmt, '\n')); if(data->set.verbose || data->set.errorbuffer) { va_list ap; size_t len; @@ -292,7 +294,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...) * If the write would block (CURLE_AGAIN), we return CURLE_OK and * (*written == 0). Otherwise we return regular CURLcode value. */ -CURLcode Curl_write(struct connectdata *conn, +CURLcode Curl_write(struct Curl_easy *data, curl_socket_t sockfd, const void *mem, size_t len, @@ -300,9 +302,14 @@ CURLcode Curl_write(struct connectdata *conn, { ssize_t bytes_written; CURLcode result = CURLE_OK; - int num = (sockfd == conn->sock[SECONDARYSOCKET]); + struct connectdata *conn; + int num; + DEBUGASSERT(data); + DEBUGASSERT(data->conn); + conn = data->conn; + num = (sockfd == conn->sock[SECONDARYSOCKET]); - bytes_written = conn->send[num](conn, num, mem, len, &result); + bytes_written = conn->send[num](data, num, mem, len, &result); *written = bytes_written; if(bytes_written >= 0) @@ -325,17 +332,23 @@ CURLcode Curl_write(struct connectdata *conn, } } -ssize_t Curl_send_plain(struct connectdata *conn, int num, +ssize_t Curl_send_plain(struct Curl_easy *data, int num, const void *mem, size_t len, CURLcode *code) { - curl_socket_t sockfd = conn->sock[num]; + struct connectdata *conn; + curl_socket_t sockfd; ssize_t bytes_written; + + DEBUGASSERT(data); + DEBUGASSERT(data->conn); + conn = data->conn; + sockfd = conn->sock[num]; /* WinSock will destroy unread received data if send() is failed. To avoid lossage of received data, recv() must be performed before every send() if any incoming data is available. */ - if(pre_receive_plain(conn, num)) { + if(pre_receive_plain(data, conn, num)) { *code = CURLE_OUT_OF_MEMORY; return -1; } @@ -372,9 +385,9 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num, } else { char buffer[STRERROR_LEN]; - failf(conn->data, "Send failure: %s", + failf(data, "Send failure: %s", Curl_strerror(err, buffer, sizeof(buffer))); - conn->data->state.os_errno = err; + data->state.os_errno = err; *code = CURLE_SEND_ERROR; } } @@ -386,28 +399,33 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num, * server using plain sockets only. Otherwise meant to have the exact same * proto as Curl_write() */ -CURLcode Curl_write_plain(struct connectdata *conn, +CURLcode Curl_write_plain(struct Curl_easy *data, curl_socket_t sockfd, const void *mem, size_t len, ssize_t *written) { - ssize_t bytes_written; CURLcode result; - int num = (sockfd == conn->sock[SECONDARYSOCKET]); + struct connectdata *conn = data->conn; + int num; + DEBUGASSERT(conn); + num = (sockfd == conn->sock[SECONDARYSOCKET]); - bytes_written = Curl_send_plain(conn, num, mem, len, &result); - - *written = bytes_written; + *written = Curl_send_plain(data, num, mem, len, &result); return result; } -ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, +ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf, size_t len, CURLcode *code) { - curl_socket_t sockfd = conn->sock[num]; + struct connectdata *conn; + curl_socket_t sockfd; ssize_t nread; + DEBUGASSERT(data); + DEBUGASSERT(data->conn); + conn = data->conn; + sockfd = conn->sock[num]; /* Check and return data that already received and storied in internal intermediate buffer */ nread = get_pre_recved(conn, num, buf, len); @@ -438,9 +456,9 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, } else { char buffer[STRERROR_LEN]; - failf(conn->data, "Recv failure: %s", + failf(data, "Recv failure: %s", Curl_strerror(err, buffer, sizeof(buffer))); - conn->data->state.os_errno = err; + data->state.os_errno = err; *code = CURLE_RECV_ERROR; } } @@ -499,12 +517,12 @@ static CURLcode pausewrite(struct Curl_easy *data, * client write callback(s) and takes care of pause requests from the * callbacks. */ -static CURLcode chop_write(struct connectdata *conn, +static CURLcode chop_write(struct Curl_easy *data, int type, char *optr, size_t olen) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; curl_write_callback writeheader = NULL; curl_write_callback writebody = NULL; char *ptr = optr; @@ -594,13 +612,12 @@ static CURLcode chop_write(struct connectdata *conn, local character encoding. This is a problem and should be changed in the future to leave the original data alone. */ -CURLcode Curl_client_write(struct connectdata *conn, +CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr, size_t len) { - struct Curl_easy *data = conn->data; - + struct connectdata *conn = data->conn; if(0 == len) len = strlen(ptr); @@ -622,7 +639,7 @@ CURLcode Curl_client_write(struct connectdata *conn, #endif /* CURL_DO_LINEEND_CONV */ } - return chop_write(conn, type, ptr, len); + return chop_write(data, type, ptr, len); } CURLcode Curl_read_plain(curl_socket_t sockfd, @@ -657,7 +674,7 @@ CURLcode Curl_read_plain(curl_socket_t sockfd, * * Returns a regular CURLcode value. */ -CURLcode Curl_read(struct connectdata *conn, /* connection data */ +CURLcode Curl_read(struct Curl_easy *data, /* transfer */ curl_socket_t sockfd, /* read from this socket */ char *buf, /* store read data here */ size_t sizerequested, /* max amount to read */ @@ -667,7 +684,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */ ssize_t nread = 0; size_t bytesfromsocket = 0; char *buffertofill = NULL; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; /* Set 'num' to 0 or 1, depending on which socket that has been sent here. If it is the second socket, we set num to 1. Otherwise to 0. This lets @@ -679,7 +696,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */ bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size); buffertofill = buf; - nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result); + nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result); if(nread < 0) return result; diff --git a/libs/libcurl/src/sendf.h b/libs/libcurl/src/sendf.h index c7e67c7451..108a5e934a 100644 --- a/libs/libcurl/src/sendf.h +++ b/libs/libcurl/src/sendf.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -49,7 +49,7 @@ void Curl_failf(struct Curl_easy *, const char *fmt, ...); #define CLIENTWRITE_HEADER (1<<1) #define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER) -CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, +CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr, size_t len) WARN_UNUSED_RESULT; bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex); @@ -60,23 +60,24 @@ CURLcode Curl_read_plain(curl_socket_t sockfd, size_t bytesfromsocket, ssize_t *n); -ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, +ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf, size_t len, CURLcode *code); -ssize_t Curl_send_plain(struct connectdata *conn, int num, +ssize_t Curl_send_plain(struct Curl_easy *data, int num, const void *mem, size_t len, CURLcode *code); /* internal read-function, does plain socket, SSL and krb4 */ -CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd, +CURLcode Curl_read(struct Curl_easy *data, curl_socket_t sockfd, char *buf, size_t buffersize, ssize_t *n); + /* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */ -CURLcode Curl_write(struct connectdata *conn, +CURLcode Curl_write(struct Curl_easy *data, curl_socket_t sockfd, const void *mem, size_t len, ssize_t *written); /* internal write-function, does plain sockets ONLY */ -CURLcode Curl_write_plain(struct connectdata *conn, +CURLcode Curl_write_plain(struct Curl_easy *data, curl_socket_t sockfd, const void *mem, size_t len, ssize_t *written); diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c index 58956c1e95..ce73a34a7f 100644 --- a/libs/libcurl/src/setopt.c +++ b/libs/libcurl/src/setopt.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -274,11 +274,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Do not include the body part in the output data stream. */ data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE; +#ifndef CURL_DISABLE_HTTP if(data->set.opt_no_body) /* in HTTP lingo, no body means using the HEAD request... */ data->set.method = HTTPREQ_HEAD; else if(data->set.method == HTTPREQ_HEAD) data->set.method = HTTPREQ_GET; +#endif break; case CURLOPT_FAILONERROR: /* @@ -600,7 +602,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_POSTREDIR: /* - * Set the behaviour of POST when redirecting + * Set the behavior of POST when redirecting * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302 * CURL_REDIR_POST_301 - POST is kept as POST after 301 * CURL_REDIR_POST_302 - POST is kept as POST after 302 @@ -636,6 +638,21 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.method = HTTPREQ_POST_FORM; data->set.opt_no_body = FALSE; /* this is implied */ break; + + case CURLOPT_AWS_SIGV4: + /* + * String that is merged to some authentication + * parameters are used by the algorithm. + */ + result = Curl_setstropt(&data->set.str[STRING_AWS_SIGV4], + va_arg(param, char *)); + /* + * Basic been set by default it need to be unset here + */ + if(data->set.str[STRING_AWS_SIGV4]) + data->set.httpauth = CURLAUTH_AWS_SIGV4; + break; + #endif /* CURL_DISABLE_HTTP */ case CURLOPT_MIMEPOST: @@ -865,7 +882,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) ; else #endif -#ifndef USE_NGHTTP2 +#if !defined(USE_NGHTTP2) && !defined(USE_HYPER) if(arg >= CURL_HTTP_VERSION_2) return CURLE_UNSUPPORTED_PROTOCOL; #else @@ -1444,13 +1461,16 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_RESOLVE: /* - * List of NAME:[address] names to populate the DNS cache with - * Prefix the NAME with dash (-) to _remove_ the name from the cache. - * - * Names added with this API will remain in the cache until explicitly + * List of HOST:PORT:[addresses] strings to populate the DNS cache with + * Entries added this way will remain in the cache until explicitly * removed or the handle is cleaned up. * - * This API can remove any name from the DNS cache, but only entries + * Prefix the HOST with plus sign (+) to have the entry expire just like + * automatically added entries. + * + * Prefix the HOST with dash (-) to _remove_ the entry from the cache. + * + * This API can remove any entry from the DNS cache, but only entries * that aren't actually in use right now will be pruned immediately. */ data->set.resolve = va_arg(param, struct curl_slist *); @@ -2150,8 +2170,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->share = NULL; } - /* use new share if it set */ - data->share = set; + if(GOOD_SHARE_HANDLE(set)) + /* use new share if it set */ + data->share = set; if(data->share) { Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); @@ -2251,7 +2272,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) arg = va_arg(param, long); if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6)) return CURLE_BAD_FUNCTION_ARGUMENT; - data->set.ipver = arg; + data->set.ipver = (unsigned char) arg; break; case CURLOPT_MAXFILESIZE_LARGE: diff --git a/libs/libcurl/src/sha256.c b/libs/libcurl/src/sha256.c index 910d7ae1e8..d915117917 100644 --- a/libs/libcurl/src/sha256.c +++ b/libs/libcurl/src/sha256.c @@ -27,6 +27,7 @@ #include "warnless.h" #include "curl_sha256.h" +#include "curl_hmac.h" #if defined(USE_OPENSSL) @@ -343,11 +344,14 @@ static int sha256_compress(struct sha256_state *md, } /* Compress */ -#define RND(a,b,c,d,e,f,g,h,i) \ - unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ - unsigned long t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; +#define RND(a,b,c,d,e,f,g,h,i) \ + do { \ + unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + unsigned long t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; \ + } while(0) + for(i = 0; i < 64; ++i) { unsigned long t; RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); @@ -491,4 +495,23 @@ void Curl_sha256it(unsigned char *output, const unsigned char *input, SHA256_Final(output, &ctx); } + +const struct HMAC_params Curl_HMAC_SHA256[] = { + { + /* Hash initialization function. */ + CURLX_FUNCTION_CAST(HMAC_hinit_func, SHA256_Init), + /* Hash update function. */ + CURLX_FUNCTION_CAST(HMAC_hupdate_func, SHA256_Update), + /* Hash computation end function. */ + CURLX_FUNCTION_CAST(HMAC_hfinal_func, SHA256_Final), + /* Size of hash context structure. */ + sizeof(SHA256_CTX), + /* Maximum key length. */ + 64, + /* Result size. */ + 32 + } +}; + + #endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libs/libcurl/src/share.c b/libs/libcurl/src/share.c index 5ce9830335..4f1804dbd2 100644 --- a/libs/libcurl/src/share.c +++ b/libs/libcurl/src/share.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,6 +37,7 @@ curl_share_init(void) { struct Curl_share *share = calloc(1, sizeof(struct Curl_share)); if(share) { + share->magic = CURL_GOOD_SHARE; share->specifier |= (1<hostcache)) { @@ -59,6 +60,9 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...) void *ptr; CURLSHcode res = CURLSHE_OK; + if(!GOOD_SHARE_HANDLE(share)) + return CURLSHE_INVALID; + if(share->dirty) /* don't allow setting options while one or more handles are already using this share */ @@ -184,7 +188,7 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...) CURLSHcode curl_share_cleanup(struct Curl_share *share) { - if(share == NULL) + if(!GOOD_SHARE_HANDLE(share)) return CURLSHE_INVALID; if(share->lockfunc) @@ -218,6 +222,7 @@ curl_share_cleanup(struct Curl_share *share) if(share->unlockfunc) share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); + share->magic = 0; free(share); return CURLSHE_OK; diff --git a/libs/libcurl/src/share.h b/libs/libcurl/src/share.h index 01aa9cda59..222e34ba6e 100644 --- a/libs/libcurl/src/share.h +++ b/libs/libcurl/src/share.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,8 +37,12 @@ #define CURL_VOLATILE volatile #endif +#define CURL_GOOD_SHARE 0x7e117a1e +#define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE) + /* this struct is libcurl-private, don't export details */ struct Curl_share { + unsigned int magic; /* CURL_GOOD_SHARE */ unsigned int specifier; CURL_VOLATILE unsigned int dirty; diff --git a/libs/libcurl/src/smb.c b/libs/libcurl/src/smb.c index dd914a05bf..dd4e4fdbf6 100644 --- a/libs/libcurl/src/smb.c +++ b/libs/libcurl/src/smb.c @@ -5,8 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * + * Copyright (C) 2016 - 2021, Daniel Stenberg, , et al. * Copyright (C) 2014, Bill Nagel , Exacq Technologies - * Copyright (C) 2016-2020, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -54,16 +54,20 @@ #include "memdebug.h" /* Local API functions */ -static CURLcode smb_setup_connection(struct connectdata *conn); -static CURLcode smb_connect(struct connectdata *conn, bool *done); -static CURLcode smb_connection_state(struct connectdata *conn, bool *done); -static CURLcode smb_do(struct connectdata *conn, bool *done); -static CURLcode smb_request_state(struct connectdata *conn, bool *done); -static CURLcode smb_done(struct connectdata *conn, CURLcode status, +static CURLcode smb_setup_connection(struct Curl_easy *data, + struct connectdata *conn); +static CURLcode smb_connect(struct Curl_easy *data, bool *done); +static CURLcode smb_connection_state(struct Curl_easy *data, bool *done); +static CURLcode smb_do(struct Curl_easy *data, bool *done); +static CURLcode smb_request_state(struct Curl_easy *data, bool *done); +static CURLcode smb_done(struct Curl_easy *data, CURLcode status, bool premature); -static CURLcode smb_disconnect(struct connectdata *conn, bool dead); -static int smb_getsock(struct connectdata *conn, curl_socket_t *socks); -static CURLcode smb_parse_url_path(struct connectdata *conn); +static CURLcode smb_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); +static int smb_getsock(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t *socks); +static CURLcode smb_parse_url_path(struct Curl_easy *data, + struct connectdata *conn); /* * SMB handler interface @@ -124,13 +128,17 @@ const struct Curl_handler Curl_handler_smbs = { /* Append a string to an SMB message */ #define MSGCAT(str) \ - strcpy(p, (str)); \ - p += strlen(str); + do { \ + strcpy(p, (str)); \ + p += strlen(str); \ + } while(0) /* Append a null-terminated string to an SMB message */ #define MSGCATNULL(str) \ - strcpy(p, (str)); \ - p += strlen(str) + 1; + do { \ + strcpy(p, (str)); \ + p += strlen(str) + 1; \ + } while(0) /* SMB is mostly little endian */ #if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ @@ -179,9 +187,9 @@ struct smb_request { CURLcode result; }; -static void conn_state(struct connectdata *conn, enum smb_conn_state newstate) +static void conn_state(struct Curl_easy *data, enum smb_conn_state newstate) { - struct smb_conn *smbc = &conn->proto.smbc; + struct smb_conn *smbc = &data->conn->proto.smbc; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* For debug purposes */ static const char * const names[] = { @@ -194,17 +202,17 @@ static void conn_state(struct connectdata *conn, enum smb_conn_state newstate) }; if(smbc->state != newstate) - infof(conn->data, "SMB conn %p state change from %s to %s\n", + infof(data, "SMB conn %p state change from %s to %s\n", (void *)smbc, names[smbc->state], names[newstate]); #endif smbc->state = newstate; } -static void request_state(struct connectdata *conn, +static void request_state(struct Curl_easy *data, enum smb_req_state newstate) { - struct smb_request *req = conn->data->req.p.smb; + struct smb_request *req = data->req.p.smb; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* For debug purposes */ static const char * const names[] = { @@ -220,7 +228,7 @@ static void request_state(struct connectdata *conn, }; if(req->state != newstate) - infof(conn->data, "SMB request %p state change from %s to %s\n", + infof(data, "SMB request %p state change from %s to %s\n", (void *)req, names[req->state], names[newstate]); #endif @@ -229,21 +237,23 @@ static void request_state(struct connectdata *conn, /* this should setup things in the connection, not in the easy handle */ -static CURLcode smb_setup_connection(struct connectdata *conn) +static CURLcode smb_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { struct smb_request *req; /* Initialize the request state */ - conn->data->req.p.smb = req = calloc(1, sizeof(struct smb_request)); + data->req.p.smb = req = calloc(1, sizeof(struct smb_request)); if(!req) return CURLE_OUT_OF_MEMORY; /* Parse the URL path */ - return smb_parse_url_path(conn); + return smb_parse_url_path(data, conn); } -static CURLcode smb_connect(struct connectdata *conn, bool *done) +static CURLcode smb_connect(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; struct smb_conn *smbc = &conn->proto.smbc; char *slash; @@ -284,8 +294,9 @@ static CURLcode smb_connect(struct connectdata *conn, bool *done) return CURLE_OK; } -static CURLcode smb_recv_message(struct connectdata *conn, void **msg) +static CURLcode smb_recv_message(struct Curl_easy *data, void **msg) { + struct connectdata *conn = data->conn; struct smb_conn *smbc = &conn->proto.smbc; char *buf = smbc->recv_buf; ssize_t bytes_read; @@ -294,7 +305,7 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg) size_t len = MAX_MESSAGE_SIZE - smbc->got; CURLcode result; - result = Curl_read(conn, FIRSTSOCKET, buf + smbc->got, len, &bytes_read); + result = Curl_read(data, FIRSTSOCKET, buf + smbc->got, len, &bytes_read); if(result) return result; @@ -338,11 +349,12 @@ static void smb_pop_message(struct connectdata *conn) smbc->got = 0; } -static void smb_format_message(struct connectdata *conn, struct smb_header *h, +static void smb_format_message(struct Curl_easy *data, struct smb_header *h, unsigned char cmd, size_t len) { + struct connectdata *conn = data->conn; struct smb_conn *smbc = &conn->proto.smbc; - struct smb_request *req = conn->data->req.p.smb; + struct smb_request *req = data->req.p.smb; unsigned int pid; memset(h, 0, sizeof(*h)); @@ -359,14 +371,15 @@ static void smb_format_message(struct connectdata *conn, struct smb_header *h, h->pid = smb_swap16((unsigned short) pid); } -static CURLcode smb_send(struct connectdata *conn, ssize_t len, +static CURLcode smb_send(struct Curl_easy *data, ssize_t len, size_t upload_size) { + struct connectdata *conn = data->conn; struct smb_conn *smbc = &conn->proto.smbc; ssize_t bytes_written; CURLcode result; - result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf, + result = Curl_write(data, FIRSTSOCKET, data->state.ulbuf, len, &bytes_written); if(result) return result; @@ -381,8 +394,9 @@ static CURLcode smb_send(struct connectdata *conn, ssize_t len, return CURLE_OK; } -static CURLcode smb_flush(struct connectdata *conn) +static CURLcode smb_flush(struct Curl_easy *data) { + struct connectdata *conn = data->conn; struct smb_conn *smbc = &conn->proto.smbc; ssize_t bytes_written; ssize_t len = smbc->send_size - smbc->sent; @@ -391,8 +405,8 @@ static CURLcode smb_flush(struct connectdata *conn) if(!smbc->send_size) return CURLE_OK; - result = Curl_write(conn, FIRSTSOCKET, - conn->data->state.ulbuf + smbc->sent, + result = Curl_write(data, FIRSTSOCKET, + data->state.ulbuf + smbc->sent, len, &bytes_written); if(result) return result; @@ -405,29 +419,30 @@ static CURLcode smb_flush(struct connectdata *conn) return CURLE_OK; } -static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd, +static CURLcode smb_send_message(struct Curl_easy *data, unsigned char cmd, const void *msg, size_t msg_len) { - CURLcode result = Curl_get_upload_buffer(conn->data); + CURLcode result = Curl_get_upload_buffer(data); if(result) return result; - smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf, + smb_format_message(data, (struct smb_header *)data->state.ulbuf, cmd, msg_len); - memcpy(conn->data->state.ulbuf + sizeof(struct smb_header), + memcpy(data->state.ulbuf + sizeof(struct smb_header), msg, msg_len); - return smb_send(conn, sizeof(struct smb_header) + msg_len, 0); + return smb_send(data, sizeof(struct smb_header) + msg_len, 0); } -static CURLcode smb_send_negotiate(struct connectdata *conn) +static CURLcode smb_send_negotiate(struct Curl_easy *data) { const char *msg = "\x00\x0c\x00\x02NT LM 0.12"; - return smb_send_message(conn, SMB_COM_NEGOTIATE, msg, 15); + return smb_send_message(data, SMB_COM_NEGOTIATE, msg, 15); } -static CURLcode smb_send_setup(struct connectdata *conn) +static CURLcode smb_send_setup(struct Curl_easy *data) { + struct connectdata *conn = data->conn; struct smb_conn *smbc = &conn->proto.smbc; struct smb_setup msg; char *p = msg.bytes; @@ -442,10 +457,10 @@ static CURLcode smb_send_setup(struct connectdata *conn) if(byte_count > sizeof(msg.bytes)) return CURLE_FILESIZE_EXCEEDED; - Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash); + Curl_ntlm_core_mk_lm_hash(data, conn->passwd, lm_hash); Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm); #ifdef USE_NTRESPONSES - Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash); + Curl_ntlm_core_mk_nt_hash(data, conn->passwd, nt_hash); Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt); #else memset(nt, 0, sizeof(nt)); @@ -472,13 +487,14 @@ static CURLcode smb_send_setup(struct connectdata *conn) byte_count = p - msg.bytes; msg.byte_count = smb_swap16((unsigned short)byte_count); - return smb_send_message(conn, SMB_COM_SETUP_ANDX, &msg, + return smb_send_message(data, SMB_COM_SETUP_ANDX, &msg, sizeof(msg) - sizeof(msg.bytes) + byte_count); } -static CURLcode smb_send_tree_connect(struct connectdata *conn) +static CURLcode smb_send_tree_connect(struct Curl_easy *data) { struct smb_tree_connect msg; + struct connectdata *conn = data->conn; struct smb_conn *smbc = &conn->proto.smbc; char *p = msg.bytes; @@ -499,13 +515,13 @@ static CURLcode smb_send_tree_connect(struct connectdata *conn) byte_count = p - msg.bytes; msg.byte_count = smb_swap16((unsigned short)byte_count); - return smb_send_message(conn, SMB_COM_TREE_CONNECT_ANDX, &msg, + return smb_send_message(data, SMB_COM_TREE_CONNECT_ANDX, &msg, sizeof(msg) - sizeof(msg.bytes) + byte_count); } -static CURLcode smb_send_open(struct connectdata *conn) +static CURLcode smb_send_open(struct Curl_easy *data) { - struct smb_request *req = conn->data->req.p.smb; + struct smb_request *req = data->req.p.smb; struct smb_nt_create msg; size_t byte_count; @@ -518,7 +534,7 @@ static CURLcode smb_send_open(struct connectdata *conn) byte_count = strlen(req->path); msg.name_length = smb_swap16((unsigned short)byte_count); msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL); - if(conn->data->set.upload) { + if(data->set.upload) { msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE); msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF); } @@ -529,35 +545,35 @@ static CURLcode smb_send_open(struct connectdata *conn) msg.byte_count = smb_swap16((unsigned short) ++byte_count); strcpy(msg.bytes, req->path); - return smb_send_message(conn, SMB_COM_NT_CREATE_ANDX, &msg, + return smb_send_message(data, SMB_COM_NT_CREATE_ANDX, &msg, sizeof(msg) - sizeof(msg.bytes) + byte_count); } -static CURLcode smb_send_close(struct connectdata *conn) +static CURLcode smb_send_close(struct Curl_easy *data) { - struct smb_request *req = conn->data->req.p.smb; + struct smb_request *req = data->req.p.smb; struct smb_close msg; memset(&msg, 0, sizeof(msg)); msg.word_count = SMB_WC_CLOSE; msg.fid = smb_swap16(req->fid); - return smb_send_message(conn, SMB_COM_CLOSE, &msg, sizeof(msg)); + return smb_send_message(data, SMB_COM_CLOSE, &msg, sizeof(msg)); } -static CURLcode smb_send_tree_disconnect(struct connectdata *conn) +static CURLcode smb_send_tree_disconnect(struct Curl_easy *data) { struct smb_tree_disconnect msg; memset(&msg, 0, sizeof(msg)); - return smb_send_message(conn, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg)); + return smb_send_message(data, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg)); } -static CURLcode smb_send_read(struct connectdata *conn) +static CURLcode smb_send_read(struct Curl_easy *data) { - struct smb_request *req = conn->data->req.p.smb; - curl_off_t offset = conn->data->req.offset; + struct smb_request *req = data->req.p.smb; + curl_off_t offset = data->req.offset; struct smb_read msg; memset(&msg, 0, sizeof(msg)); @@ -569,19 +585,19 @@ static CURLcode smb_send_read(struct connectdata *conn) msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE); msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE); - return smb_send_message(conn, SMB_COM_READ_ANDX, &msg, sizeof(msg)); + return smb_send_message(data, SMB_COM_READ_ANDX, &msg, sizeof(msg)); } -static CURLcode smb_send_write(struct connectdata *conn) +static CURLcode smb_send_write(struct Curl_easy *data) { struct smb_write *msg; - struct smb_request *req = conn->data->req.p.smb; - curl_off_t offset = conn->data->req.offset; - curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount; - CURLcode result = Curl_get_upload_buffer(conn->data); + struct smb_request *req = data->req.p.smb; + curl_off_t offset = data->req.offset; + curl_off_t upload_size = data->req.size - data->req.bytecount; + CURLcode result = Curl_get_upload_buffer(data); if(result) return result; - msg = (struct smb_write *)conn->data->state.ulbuf; + msg = (struct smb_write *)data->state.ulbuf; if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */ upload_size = MAX_PAYLOAD_SIZE - 1; @@ -596,25 +612,26 @@ static CURLcode smb_send_write(struct connectdata *conn) msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int)); msg->byte_count = smb_swap16((unsigned short) (upload_size + 1)); - smb_format_message(conn, &msg->h, SMB_COM_WRITE_ANDX, + smb_format_message(data, &msg->h, SMB_COM_WRITE_ANDX, sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size); - return smb_send(conn, sizeof(*msg), (size_t) upload_size); + return smb_send(data, sizeof(*msg), (size_t) upload_size); } -static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg) +static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg) { + struct connectdata *conn = data->conn; struct smb_conn *smbc = &conn->proto.smbc; CURLcode result; *msg = NULL; /* if it returns early */ /* Check if there is data in the transfer buffer */ if(!smbc->send_size && smbc->upload_size) { - size_t nread = smbc->upload_size > conn->data->set.upload_buffer_size ? - conn->data->set.upload_buffer_size : + size_t nread = smbc->upload_size > data->set.upload_buffer_size ? + data->set.upload_buffer_size : smbc->upload_size; - conn->data->req.upload_fromhere = conn->data->state.ulbuf; - result = Curl_fillreadbuffer(conn, nread, &nread); + data->req.upload_fromhere = data->state.ulbuf; + result = Curl_fillreadbuffer(data, nread, &nread); if(result && result != CURLE_AGAIN) return result; if(!nread) @@ -627,7 +644,7 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg) /* Check if there is data to send */ if(smbc->send_size) { - result = smb_flush(conn); + result = smb_flush(data); if(result) return result; } @@ -636,11 +653,12 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg) if(smbc->send_size || smbc->upload_size) return CURLE_AGAIN; - return smb_recv_message(conn, msg); + return smb_recv_message(data, msg); } -static CURLcode smb_connection_state(struct connectdata *conn, bool *done) +static CURLcode smb_connection_state(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; struct smb_conn *smbc = &conn->proto.smbc; struct smb_negotiate_response *nrsp; struct smb_header *h; @@ -651,7 +669,8 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done) #ifdef USE_SSL if((conn->handler->flags & PROTOPT_SSL)) { bool ssl_done = FALSE; - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &ssl_done); + result = Curl_ssl_connect_nonblocking(data, conn, + FIRSTSOCKET, &ssl_done); if(result && result != CURLE_AGAIN) return result; if(!ssl_done) @@ -659,17 +678,17 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done) } #endif - result = smb_send_negotiate(conn); + result = smb_send_negotiate(data); if(result) { connclose(conn, "SMB: failed to send negotiate message"); return result; } - conn_state(conn, SMB_NEGOTIATE); + conn_state(data, SMB_NEGOTIATE); } /* Send the previous message and check for a response */ - result = smb_send_and_recv(conn, &msg); + result = smb_send_and_recv(data, &msg); if(result && result != CURLE_AGAIN) { connclose(conn, "SMB: failed to communicate"); return result; @@ -690,12 +709,12 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done) nrsp = msg; memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge)); smbc->session_key = smb_swap32(nrsp->session_key); - result = smb_send_setup(conn); + result = smb_send_setup(data); if(result) { connclose(conn, "SMB: failed to send setup message"); return result; } - conn_state(conn, SMB_SETUP); + conn_state(data, SMB_SETUP); break; case SMB_SETUP: @@ -704,7 +723,7 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done) return CURLE_LOGIN_DENIED; } smbc->uid = smb_swap16(h->uid); - conn_state(conn, SMB_CONNECTED); + conn_state(data, SMB_CONNECTED); *done = true; break; @@ -736,9 +755,10 @@ static void get_posix_time(time_t *out, curl_off_t timestamp) *out = (time_t) timestamp; } -static CURLcode smb_request_state(struct connectdata *conn, bool *done) +static CURLcode smb_request_state(struct Curl_easy *data, bool *done) { - struct smb_request *req = conn->data->req.p.smb; + struct connectdata *conn = data->conn; + struct smb_request *req = data->req.p.smb; struct smb_header *h; struct smb_conn *smbc = &conn->proto.smbc; enum smb_req_state next_state = SMB_DONE; @@ -750,17 +770,17 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) /* Start the request */ if(req->state == SMB_REQUESTING) { - result = smb_send_tree_connect(conn); + result = smb_send_tree_connect(data); if(result) { connclose(conn, "SMB: failed to send tree connect message"); return result; } - request_state(conn, SMB_TREE_CONNECT); + request_state(data, SMB_TREE_CONNECT); } /* Send the previous message and check for a response */ - result = smb_send_and_recv(conn, &msg); + result = smb_send_and_recv(data, &msg); if(result && result != CURLE_AGAIN) { connclose(conn, "SMB: failed to communicate"); return result; @@ -793,23 +813,23 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) } smb_m = (const struct smb_nt_create_response*) msg; req->fid = smb_swap16(smb_m->fid); - conn->data->req.offset = 0; - if(conn->data->set.upload) { - conn->data->req.size = conn->data->state.infilesize; - Curl_pgrsSetUploadSize(conn->data, conn->data->req.size); + data->req.offset = 0; + if(data->set.upload) { + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->req.size); next_state = SMB_UPLOAD; } else { smb_m = (const struct smb_nt_create_response*) msg; - conn->data->req.size = smb_swap64(smb_m->end_of_file); - if(conn->data->req.size < 0) { + data->req.size = smb_swap64(smb_m->end_of_file); + if(data->req.size < 0) { req->result = CURLE_WEIRD_SERVER_REPLY; next_state = SMB_CLOSE; } else { - Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size); - if(conn->data->set.get_filetime) - get_posix_time(&conn->data->info.filetime, smb_m->last_change_time); + Curl_pgrsSetDownloadSize(data, data->req.size); + if(data->set.get_filetime) + get_posix_time(&data->info.filetime, smb_m->last_change_time); next_state = SMB_DOWNLOAD; } } @@ -827,11 +847,11 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) sizeof(struct smb_header) + 13); if(len > 0) { if(off + sizeof(unsigned int) + len > smbc->got) { - failf(conn->data, "Invalid input packet"); + failf(data, "Invalid input packet"); result = CURLE_RECV_ERROR; } else - result = Curl_client_write(conn, CLIENTWRITE_BODY, + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)msg + off + sizeof(unsigned int), len); if(result) { @@ -840,9 +860,9 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) break; } } - conn->data->req.bytecount += len; - conn->data->req.offset += len; - Curl_pgrsSetDownloadCounter(conn->data, conn->data->req.bytecount); + data->req.bytecount += len; + data->req.offset += len; + Curl_pgrsSetDownloadCounter(data, data->req.bytecount); next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD; break; @@ -854,10 +874,10 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) } len = Curl_read16_le(((const unsigned char *) msg) + sizeof(struct smb_header) + 5); - conn->data->req.bytecount += len; - conn->data->req.offset += len; - Curl_pgrsSetUploadCounter(conn->data, conn->data->req.bytecount); - if(conn->data->req.bytecount >= conn->data->req.size) + data->req.bytecount += len; + data->req.offset += len; + Curl_pgrsSetUploadCounter(data, data->req.bytecount); + if(data->req.bytecount >= data->req.size) next_state = SMB_CLOSE; else next_state = SMB_UPLOAD; @@ -881,23 +901,23 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) switch(next_state) { case SMB_OPEN: - result = smb_send_open(conn); + result = smb_send_open(data); break; case SMB_DOWNLOAD: - result = smb_send_read(conn); + result = smb_send_read(data); break; case SMB_UPLOAD: - result = smb_send_write(conn); + result = smb_send_write(data); break; case SMB_CLOSE: - result = smb_send_close(conn); + result = smb_send_close(data); break; case SMB_TREE_DISCONNECT: - result = smb_send_tree_disconnect(conn); + result = smb_send_tree_disconnect(data); break; case SMB_DONE: @@ -914,37 +934,42 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) return result; } - request_state(conn, next_state); + request_state(data, next_state); return CURLE_OK; } -static CURLcode smb_done(struct connectdata *conn, CURLcode status, +static CURLcode smb_done(struct Curl_easy *data, CURLcode status, bool premature) { (void) premature; - Curl_safefree(conn->data->req.p.smb); + Curl_safefree(data->req.p.smb); return status; } -static CURLcode smb_disconnect(struct connectdata *conn, bool dead) +static CURLcode smb_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead) { struct smb_conn *smbc = &conn->proto.smbc; (void) dead; + (void) data; Curl_safefree(smbc->share); Curl_safefree(smbc->domain); Curl_safefree(smbc->recv_buf); return CURLE_OK; } -static int smb_getsock(struct connectdata *conn, curl_socket_t *socks) +static int smb_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { + (void)data; socks[0] = conn->sock[FIRSTSOCKET]; return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0); } -static CURLcode smb_do(struct connectdata *conn, bool *done) +static CURLcode smb_do(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; struct smb_conn *smbc = &conn->proto.smbc; *done = FALSE; @@ -954,9 +979,9 @@ static CURLcode smb_do(struct connectdata *conn, bool *done) return CURLE_URL_MALFORMAT; } -static CURLcode smb_parse_url_path(struct connectdata *conn) +static CURLcode smb_parse_url_path(struct Curl_easy *data, + struct connectdata *conn) { - struct Curl_easy *data = conn->data; struct smb_request *req = data->req.p.smb; struct smb_conn *smbc = &conn->proto.smbc; char *path; diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c index 509d802f1c..1fc880065a 100644 --- a/libs/libcurl/src/smtp.c +++ b/libs/libcurl/src/smtp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -91,24 +91,29 @@ #include "memdebug.h" /* Local API functions */ -static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done); -static CURLcode smtp_do(struct connectdata *conn, bool *done); -static CURLcode smtp_done(struct connectdata *conn, CURLcode status, +static CURLcode smtp_regular_transfer(struct Curl_easy *data, bool *done); +static CURLcode smtp_do(struct Curl_easy *data, bool *done); +static CURLcode smtp_done(struct Curl_easy *data, CURLcode status, bool premature); -static CURLcode smtp_connect(struct connectdata *conn, bool *done); -static CURLcode smtp_disconnect(struct connectdata *conn, bool dead); -static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done); -static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks); -static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done); -static CURLcode smtp_setup_connection(struct connectdata *conn); +static CURLcode smtp_connect(struct Curl_easy *data, bool *done); +static CURLcode smtp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); +static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done); +static int smtp_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); +static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done); +static CURLcode smtp_setup_connection(struct Curl_easy *data, + struct connectdata *conn); static CURLcode smtp_parse_url_options(struct connectdata *conn); -static CURLcode smtp_parse_url_path(struct connectdata *conn); -static CURLcode smtp_parse_custom_request(struct connectdata *conn); -static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma, +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 connectdata *conn, const char *mech, +static CURLcode smtp_perform_auth(struct Curl_easy *data, + struct connectdata *conn, const char *mech, const char *initresp); -static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp); +static CURLcode smtp_continue_auth(struct Curl_easy *data, + struct connectdata *conn, const char *resp); static void smtp_get_message(char *buffer, char **outptr); /* @@ -199,11 +204,12 @@ static void smtp_to_smtps(struct connectdata *conn) * also detects various capabilities from the EHLO response including the * supported authentication mechanisms. */ -static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, - int *resp) +static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn, + char *line, size_t len, int *resp) { struct smtp_conn *smtpc = &conn->proto.smtpc; bool result = FALSE; + (void)data; /* Nothing for us */ if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) @@ -277,9 +283,9 @@ static void smtp_get_message(char *buffer, char **outptr) * * This is the ONLY way to change SMTP state! */ -static void state(struct connectdata *conn, smtpstate newstate) +static void state(struct Curl_easy *data, smtpstate newstate) { - struct smtp_conn *smtpc = &conn->proto.smtpc; + struct smtp_conn *smtpc = &data->conn->proto.smtpc; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* for debug purposes */ static const char * const names[] = { @@ -300,7 +306,7 @@ static void state(struct connectdata *conn, smtpstate newstate) }; if(smtpc->state != newstate) - infof(conn->data, "SMTP %p state change from %s to %s\n", + infof(data, "SMTP %p state change from %s to %s\n", (void *)smtpc, names[smtpc->state], names[newstate]); #endif @@ -314,9 +320,10 @@ static void state(struct connectdata *conn, smtpstate newstate) * Sends the EHLO command to not only initialise communication with the ESMTP * server but to also obtain a list of server side supported capabilities. */ -static CURLcode smtp_perform_ehlo(struct connectdata *conn) +static CURLcode smtp_perform_ehlo(struct Curl_easy *data) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; smtpc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanism yet */ @@ -326,10 +333,10 @@ static CURLcode smtp_perform_ehlo(struct connectdata *conn) smtpc->auth_supported = FALSE; /* Clear the AUTH capability */ /* Send the EHLO command */ - result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain); + result = Curl_pp_sendf(data, &smtpc->pp, "EHLO %s", smtpc->domain); if(!result) - state(conn, SMTP_EHLO); + state(data, SMTP_EHLO); return result; } @@ -340,7 +347,8 @@ static CURLcode smtp_perform_ehlo(struct connectdata *conn) * * Sends the HELO command to initialise communication with the SMTP server. */ -static CURLcode smtp_perform_helo(struct connectdata *conn) +static CURLcode smtp_perform_helo(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; @@ -349,10 +357,10 @@ static CURLcode smtp_perform_helo(struct connectdata *conn) in smtp connections */ /* Send the HELO command */ - result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain); + result = Curl_pp_sendf(data, &smtpc->pp, "HELO %s", smtpc->domain); if(!result) - state(conn, SMTP_HELO); + state(data, SMTP_HELO); return result; } @@ -363,13 +371,15 @@ static CURLcode smtp_perform_helo(struct connectdata *conn) * * Sends the STLS command to start the upgrade to TLS. */ -static CURLcode smtp_perform_starttls(struct connectdata *conn) +static CURLcode smtp_perform_starttls(struct Curl_easy *data, + struct connectdata *conn) { /* Send the STARTTLS command */ - CURLcode result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "STARTTLS"); + CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, + "%s", "STARTTLS"); if(!result) - state(conn, SMTP_STARTTLS); + state(data, SMTP_STARTTLS); return result; } @@ -380,20 +390,21 @@ static CURLcode smtp_perform_starttls(struct connectdata *conn) * * Performs the upgrade to TLS. */ -static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn) +static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data) { /* Start the SSL connection */ + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; - CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, &smtpc->ssldone); if(!result) { if(smtpc->state != SMTP_UPGRADETLS) - state(conn, SMTP_UPGRADETLS); + state(data, SMTP_UPGRADETLS); if(smtpc->ssldone) { smtp_to_smtps(conn); - result = smtp_perform_ehlo(conn); + result = smtp_perform_ehlo(data); } } @@ -407,7 +418,8 @@ static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn) * Sends an AUTH command allowing the client to login with the given SASL * authentication mechanism. */ -static CURLcode smtp_perform_auth(struct connectdata *conn, +static CURLcode smtp_perform_auth(struct Curl_easy *data, + struct connectdata *conn, const char *mech, const char *initresp) { @@ -416,11 +428,11 @@ static CURLcode smtp_perform_auth(struct connectdata *conn, if(initresp) { /* AUTH ... */ /* Send the AUTH command with the initial response */ - result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp); + result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s %s", mech, initresp); } else { /* Send the AUTH command */ - result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech); + result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s", mech); } return result; @@ -432,11 +444,12 @@ static CURLcode smtp_perform_auth(struct connectdata *conn, * * Sends SASL continuation data or cancellation. */ -static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp) +static CURLcode smtp_continue_auth(struct Curl_easy *data, + struct connectdata *conn, const char *resp) { struct smtp_conn *smtpc = &conn->proto.smtpc; - return Curl_pp_sendf(&smtpc->pp, "%s", resp); + return Curl_pp_sendf(data, &smtpc->pp, "%s", resp); } /*********************************************************************** @@ -446,9 +459,10 @@ static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp) * Initiates the authentication sequence, with the appropriate SASL * authentication mechanism. */ -static CURLcode smtp_perform_authentication(struct connectdata *conn) +static CURLcode smtp_perform_authentication(struct Curl_easy *data) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; saslprogress progress; @@ -456,19 +470,19 @@ static CURLcode smtp_perform_authentication(struct connectdata *conn) server supports authentiation, and end the connect phase if not */ if(!smtpc->auth_supported || !Curl_sasl_can_authenticate(&smtpc->sasl, conn)) { - state(conn, SMTP_STOP); + state(data, SMTP_STOP); return result; } /* Calculate the SASL login details */ - result = Curl_sasl_start(&smtpc->sasl, conn, FALSE, &progress); + result = Curl_sasl_start(&smtpc->sasl, data, conn, FALSE, &progress); if(!result) { if(progress == SASL_INPROGRESS) - state(conn, SMTP_AUTH); + state(data, SMTP_AUTH); else { /* Other mechanisms not supported */ - infof(conn->data, "No known authentication mechanisms supported!\n"); + infof(data, "No known authentication mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; } } @@ -482,10 +496,10 @@ static CURLcode smtp_perform_authentication(struct connectdata *conn) * * Sends a SMTP based command. */ -static CURLcode smtp_perform_command(struct connectdata *conn) +static CURLcode smtp_perform_command(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SMTP *smtp = data->req.p.smtp; if(smtp->rcpt) { @@ -501,7 +515,7 @@ static CURLcode smtp_perform_command(struct connectdata *conn) /* Parse the mailbox to verify into the local address and host name parts, converting the host name to an IDN A-label if necessary */ - result = smtp_parse_address(conn, smtp->rcpt->data, + result = smtp_parse_address(data, smtp->rcpt->data, &address, &host); if(result) return result; @@ -514,7 +528,7 @@ static CURLcode smtp_perform_command(struct connectdata *conn) /* Send the VRFY command (Note: The host name part may be absent when the host is a local system) */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "VRFY %s%s%s%s", + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "VRFY %s%s%s%s", address, host.name ? "@" : "", host.name ? host.name : "", @@ -530,19 +544,20 @@ static CURLcode smtp_perform_command(struct connectdata *conn) (!strcmp(smtp->custom, "EXPN")); /* Send the custom recipient based command such as the EXPN command */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s%s", smtp->custom, + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, + "%s %s%s", smtp->custom, smtp->rcpt->data, utf8 ? " SMTPUTF8" : ""); } } else /* Send the non-recipient based command such as HELP */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", smtp->custom && smtp->custom[0] != '\0' ? smtp->custom : "HELP"); if(!result) - state(conn, SMTP_COMMAND); + state(data, SMTP_COMMAND); return result; } @@ -553,13 +568,13 @@ static CURLcode smtp_perform_command(struct connectdata *conn) * * Sends an MAIL command to initiate the upload of a message. */ -static CURLcode smtp_perform_mail(struct connectdata *conn) +static CURLcode smtp_perform_mail(struct Curl_easy *data) { char *from = NULL; char *auth = NULL; char *size = NULL; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->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 @@ -574,7 +589,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) /* Parse the FROM mailbox into the local address and host name parts, converting the host name to an IDN A-label if necessary */ - result = smtp_parse_address(conn, data->set.str[STRING_MAIL_FROM], + result = smtp_parse_address(data, data->set.str[STRING_MAIL_FROM], &address, &host); if(result) return result; @@ -612,7 +627,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) /* Parse the AUTH mailbox into the local address and host name parts, converting the host name to an IDN A-label if necessary */ - result = smtp_parse_address(conn, data->set.str[STRING_MAIL_AUTH], + result = smtp_parse_address(data, data->set.str[STRING_MAIL_AUTH], &address, &host); if(result) { free(from); @@ -660,7 +675,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) NULL, MIMESTRATEGY_MAIL); if(!result) - if(!Curl_checkheaders(conn, "Mime-Version")) + if(!Curl_checkheaders(data, "Mime-Version")) result = Curl_mime_add_header(&data->set.mimepost.curlheaders, "Mime-Version: 1.0"); @@ -712,7 +727,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) } /* Send the MAIL command */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "MAIL FROM:%s%s%s%s%s%s", from, /* Mandatory */ auth ? " AUTH=" : "", /* Optional on AUTH support */ @@ -727,7 +742,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) free(size); if(!result) - state(conn, SMTP_MAIL); + state(data, SMTP_MAIL); return result; } @@ -739,35 +754,36 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) * Sends a RCPT TO command for a given recipient as part of the message upload * process. */ -static CURLcode smtp_perform_rcpt_to(struct connectdata *conn) +static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SMTP *smtp = data->req.p.smtp; char *address = NULL; struct hostname host = { NULL, NULL, NULL, NULL }; /* Parse the recipient mailbox into the local address and host name parts, converting the host name to an IDN A-label if necessary */ - result = smtp_parse_address(conn, smtp->rcpt->data, + result = smtp_parse_address(data, smtp->rcpt->data, &address, &host); if(result) return result; /* Send the RCPT TO command */ if(host.name) - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s@%s>", address, - host.name); + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s@%s>", + address, host.name); else /* An invalid mailbox was provided but we'll simply let the server worry about that and reply with a 501 error */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", address); + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s>", + address); Curl_free_idnconverted_hostname(&host); free(address); if(!result) - state(conn, SMTP_RCPT); + state(data, SMTP_RCPT); return result; } @@ -778,25 +794,24 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn) * * Performs the quit action prior to sclose() being called. */ -static CURLcode smtp_perform_quit(struct connectdata *conn) +static CURLcode smtp_perform_quit(struct Curl_easy *data, + struct connectdata *conn) { /* Send the QUIT command */ - CURLcode result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "QUIT"); + CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "QUIT"); if(!result) - state(conn, SMTP_QUIT); + state(data, SMTP_QUIT); return result; } /* For the initial server greeting */ -static CURLcode smtp_state_servergreet_resp(struct connectdata *conn, +static CURLcode smtp_state_servergreet_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(smtpcode/100 != 2) { @@ -804,19 +819,17 @@ static CURLcode smtp_state_servergreet_resp(struct connectdata *conn, result = CURLE_WEIRD_SERVER_REPLY; } else - result = smtp_perform_ehlo(conn); + result = smtp_perform_ehlo(data); return result; } /* For STARTTLS responses */ -static CURLcode smtp_state_starttls_resp(struct connectdata *conn, +static CURLcode smtp_state_starttls_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(smtpcode != 220) { @@ -825,20 +838,20 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn, result = CURLE_USE_SSL_FAILED; } else - result = smtp_perform_authentication(conn); + result = smtp_perform_authentication(data); } else - result = smtp_perform_upgrade_tls(conn); + result = smtp_perform_upgrade_tls(data); return result; } /* For EHLO responses */ -static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data, + struct connectdata *conn, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct smtp_conn *smtpc = &conn->proto.smtpc; const char *line = data->state.buffer; size_t len = strlen(line); @@ -847,7 +860,7 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, if(smtpcode/100 != 2 && smtpcode != 1) { if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) - result = smtp_perform_helo(conn); + result = smtp_perform_helo(data, conn); else { failf(data, "Remote access denied: %d", smtpcode); result = CURLE_REMOTE_ACCESS_DENIED; @@ -915,17 +928,17 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, /* We don't have a SSL/TLS connection yet, but SSL is requested */ if(smtpc->tls_supported) /* Switch to TLS connection now */ - result = smtp_perform_starttls(conn); + result = smtp_perform_starttls(data, conn); else if(data->set.use_ssl == CURLUSESSL_TRY) /* Fallback and carry on with authentication */ - result = smtp_perform_authentication(conn); + result = smtp_perform_authentication(data); else { failf(data, "STARTTLS not supported."); result = CURLE_USE_SSL_FAILED; } } else - result = smtp_perform_authentication(conn); + result = smtp_perform_authentication(data); } } else { @@ -937,12 +950,10 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, } /* For HELO responses */ -static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_helo_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(smtpcode/100 != 2) { @@ -951,28 +962,28 @@ static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode, } else /* End of connect phase */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); return result; } /* For SASL authentication responses */ -static CURLcode smtp_state_auth_resp(struct connectdata *conn, +static CURLcode smtp_state_auth_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; saslprogress progress; (void)instate; /* no use for this yet */ - result = Curl_sasl_continue(&smtpc->sasl, conn, smtpcode, &progress); + result = Curl_sasl_continue(&smtpc->sasl, data, conn, smtpcode, &progress); if(!result) switch(progress) { case SASL_DONE: - state(conn, SMTP_STOP); /* Authenticated */ + state(data, SMTP_STOP); /* Authenticated */ break; case SASL_IDLE: /* No mechanism left after cancellation */ failf(data, "Authentication cancelled"); @@ -986,11 +997,10 @@ static CURLcode smtp_state_auth_resp(struct connectdata *conn, } /* For command responses */ -static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.p.smtp; char *line = data->state.buffer; size_t len = strlen(line); @@ -1006,7 +1016,7 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, /* Temporarily add the LF character back and send as body to the client */ if(!data->set.opt_no_body) { line[len] = '\n'; - result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); + result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1); line[len] = '\0'; } @@ -1016,15 +1026,15 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, if(smtp->rcpt) { /* Send the next command */ - result = smtp_perform_command(conn); + result = smtp_perform_command(data); } else /* End of DO phase */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); } else /* End of DO phase */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); } } @@ -1032,12 +1042,10 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, } /* For MAIL responses */ -static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_mail_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(smtpcode/100 != 2) { @@ -1046,17 +1054,17 @@ static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode, } else /* Start the RCPT TO command */ - result = smtp_perform_rcpt_to(conn); + result = smtp_perform_rcpt_to(data); return result; } /* For RCPT responses */ -static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data, + struct connectdata *conn, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.p.smtp; bool is_smtp_err = FALSE; bool is_smtp_blocking_err = FALSE; @@ -1090,7 +1098,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, if(smtp->rcpt) /* Send the next RCPT TO command */ - result = smtp_perform_rcpt_to(conn); + result = smtp_perform_rcpt_to(data); else { /* We weren't able to issue a successful RCPT TO command while going over recipients (potentially multiple). Sending back last error. */ @@ -1100,10 +1108,10 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, } else { /* Send the DATA command */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA"); + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "DATA"); if(!result) - state(conn, SMTP_DATA); + state(data, SMTP_DATA); } } } @@ -1112,12 +1120,10 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, } /* For DATA response */ -static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(smtpcode != 354) { @@ -1132,7 +1138,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* End of DO phase */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); } return result; @@ -1140,7 +1146,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, /* For POSTDATA responses, which are received after the entire DATA part has been sent to the server */ -static CURLcode smtp_state_postdata_resp(struct connectdata *conn, +static CURLcode smtp_state_postdata_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { @@ -1152,16 +1158,16 @@ static CURLcode smtp_state_postdata_resp(struct connectdata *conn, result = CURLE_RECV_ERROR; /* End of DONE phase */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); return result; } -static CURLcode smtp_statemach_act(struct connectdata *conn) +static CURLcode smtp_statemachine(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; curl_socket_t sock = conn->sock[FIRSTSOCKET]; - struct Curl_easy *data = conn->data; int smtpcode; struct smtp_conn *smtpc = &conn->proto.smtpc; struct pingpong *pp = &smtpc->pp; @@ -1169,15 +1175,15 @@ static CURLcode smtp_statemach_act(struct connectdata *conn) /* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */ if(smtpc->state == SMTP_UPGRADETLS) - return smtp_perform_upgrade_tls(conn); + return smtp_perform_upgrade_tls(data); /* Flush any data that needs to be sent */ if(pp->sendleft) - return Curl_pp_flushsend(pp); + return Curl_pp_flushsend(data, pp); do { /* Read the response from the server */ - result = Curl_pp_readresp(sock, pp, &smtpcode, &nread); + result = Curl_pp_readresp(data, sock, pp, &smtpcode, &nread); if(result) return result; @@ -1191,50 +1197,50 @@ static CURLcode smtp_statemach_act(struct connectdata *conn) /* We have now received a full SMTP server response */ switch(smtpc->state) { case SMTP_SERVERGREET: - result = smtp_state_servergreet_resp(conn, smtpcode, smtpc->state); + result = smtp_state_servergreet_resp(data, smtpcode, smtpc->state); break; case SMTP_EHLO: - result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state); + result = smtp_state_ehlo_resp(data, conn, smtpcode, smtpc->state); break; case SMTP_HELO: - result = smtp_state_helo_resp(conn, smtpcode, smtpc->state); + result = smtp_state_helo_resp(data, smtpcode, smtpc->state); break; case SMTP_STARTTLS: - result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state); + result = smtp_state_starttls_resp(data, smtpcode, smtpc->state); break; case SMTP_AUTH: - result = smtp_state_auth_resp(conn, smtpcode, smtpc->state); + result = smtp_state_auth_resp(data, smtpcode, smtpc->state); break; case SMTP_COMMAND: - result = smtp_state_command_resp(conn, smtpcode, smtpc->state); + result = smtp_state_command_resp(data, smtpcode, smtpc->state); break; case SMTP_MAIL: - result = smtp_state_mail_resp(conn, smtpcode, smtpc->state); + result = smtp_state_mail_resp(data, smtpcode, smtpc->state); break; case SMTP_RCPT: - result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state); + result = smtp_state_rcpt_resp(data, conn, smtpcode, smtpc->state); break; case SMTP_DATA: - result = smtp_state_data_resp(conn, smtpcode, smtpc->state); + result = smtp_state_data_resp(data, smtpcode, smtpc->state); break; case SMTP_POSTDATA: - result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state); + result = smtp_state_postdata_resp(data, smtpcode, smtpc->state); break; case SMTP_QUIT: /* fallthrough, just stop! */ default: /* internal error */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); break; } } while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp)); @@ -1243,41 +1249,43 @@ static CURLcode smtp_statemach_act(struct connectdata *conn) } /* Called repeatedly until done from multi.c */ -static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done) +static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) { - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); + result = Curl_ssl_connect_nonblocking(data, conn, + FIRSTSOCKET, &smtpc->ssldone); if(result || !smtpc->ssldone) return result; } - result = Curl_pp_statemach(&smtpc->pp, FALSE, FALSE); + result = Curl_pp_statemach(data, &smtpc->pp, FALSE, FALSE); *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE; return result; } -static CURLcode smtp_block_statemach(struct connectdata *conn, +static CURLcode smtp_block_statemach(struct Curl_easy *data, + struct connectdata *conn, bool disconnecting) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; while(smtpc->state != SMTP_STOP && !result) - result = Curl_pp_statemach(&smtpc->pp, TRUE, disconnecting); + result = Curl_pp_statemach(data, &smtpc->pp, TRUE, disconnecting); return result; } /* Allocate and initialize the SMTP struct for the current Curl_easy if required */ -static CURLcode smtp_init(struct connectdata *conn) +static CURLcode smtp_init(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct SMTP *smtp; smtp = data->req.p.smtp = calloc(sizeof(struct SMTP), 1); @@ -1288,9 +1296,10 @@ static CURLcode smtp_init(struct connectdata *conn) } /* For the SMTP "protocol connect" and "doing" phases only */ -static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks) +static int smtp_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { - return Curl_pp_getsock(&conn->proto.smtpc.pp, socks); + return Curl_pp_getsock(data, &conn->proto.smtpc.pp, socks); } /*********************************************************************** @@ -1303,9 +1312,10 @@ static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks) * The variable pointed to by 'done' will be TRUE if the protocol-layer * connect phase is done when this function returns, or FALSE if not. */ -static CURLcode smtp_connect(struct connectdata *conn, bool *done) +static CURLcode smtp_connect(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; struct pingpong *pp = &smtpc->pp; @@ -1314,18 +1324,14 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done) /* We always support persistent connections in SMTP */ connkeep(conn, "SMTP default"); - /* Set the default response time-out */ - pp->response_time = RESP_TIMEOUT; - pp->statemach_act = smtp_statemach_act; - pp->endofresp = smtp_endofresp; - pp->conn = conn; + PINGPONG_SETUP(pp, smtp_statemachine, smtp_endofresp); /* Initialize the SASL storage */ Curl_sasl_init(&smtpc->sasl, &saslsmtp); /* Initialise the pingpong layer */ Curl_pp_setup(pp); - Curl_pp_init(pp); + Curl_pp_init(data, pp); /* Parse the URL options */ result = smtp_parse_url_options(conn); @@ -1333,14 +1339,14 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done) return result; /* Parse the URL path */ - result = smtp_parse_url_path(conn); + result = smtp_parse_url_path(data); if(result) return result; /* Start off waiting for the server greeting response */ - state(conn, SMTP_SERVERGREET); + state(data, SMTP_SERVERGREET); - result = smtp_multi_statemach(conn, done); + result = smtp_multi_statemach(data, done); return result; } @@ -1354,11 +1360,11 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done) * * Input argument is already checked for validity. */ -static CURLcode smtp_done(struct connectdata *conn, CURLcode status, +static CURLcode smtp_done(struct Curl_easy *data, CURLcode status, bool premature) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SMTP *smtp = data->req.p.smtp; struct pingpong *pp = &conn->proto.smtpc.pp; char *eob; @@ -1367,7 +1373,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, (void)premature; - if(!smtp || !pp->conn) + if(!smtp) return CURLE_OK; /* Cleanup our per-request based variables */ @@ -1387,7 +1393,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, fail when using a different pointer following a previous write, that returned CURLE_AGAIN, we duplicate the EOB now rather than when the bytes written doesn't equal len. */ - if(smtp->trailing_crlf || !conn->data->state.infilesize) { + if(smtp->trailing_crlf || !data->state.infilesize) { eob = strdup(&SMTP_EOB[2]); len = SMTP_EOB_LEN - 2; } @@ -1400,7 +1406,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, return CURLE_OUT_OF_MEMORY; /* Send the end of block data */ - result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written); + result = Curl_write(data, conn->writesockfd, eob, len, &bytes_written); if(result) { free(eob); return result; @@ -1420,10 +1426,10 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, free(eob); } - state(conn, SMTP_POSTDATA); + state(data, SMTP_POSTDATA); /* Run the state-machine */ - result = smtp_block_statemach(conn, FALSE); + result = smtp_block_statemach(data, conn, FALSE); } /* Clear the transfer mode for the next request */ @@ -1439,15 +1445,15 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, * This is the actual DO function for SMTP. Transfer a mail, send a command * or get some data according to the options previously setup. */ -static CURLcode smtp_perform(struct connectdata *conn, bool *connected, +static CURLcode smtp_perform(struct Curl_easy *data, bool *connected, bool *dophase_done) { /* This is SMTP and no proxy */ CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SMTP *smtp = data->req.p.smtp; - DEBUGF(infof(conn->data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts\n")); if(data->set.opt_no_body) { /* Requested no body means no transfer */ @@ -1473,21 +1479,21 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected, /* Start the first command in the DO phase */ if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt) /* MAIL transfer */ - result = smtp_perform_mail(conn); + result = smtp_perform_mail(data); else /* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */ - result = smtp_perform_command(conn); + result = smtp_perform_command(data); if(result) return result; /* Run the state-machine */ - result = smtp_multi_statemach(conn, dophase_done); + result = smtp_multi_statemach(data, dophase_done); *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); return result; } @@ -1501,18 +1507,17 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected, * * The input argument is already checked for validity. */ -static CURLcode smtp_do(struct connectdata *conn, bool *done) +static CURLcode smtp_do(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; - *done = FALSE; /* default to false */ /* Parse the custom request */ - result = smtp_parse_custom_request(conn); + result = smtp_parse_custom_request(data); if(result) return result; - result = smtp_regular_transfer(conn, done); + result = smtp_regular_transfer(data, done); return result; } @@ -1524,19 +1529,21 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done) * Disconnect from an SMTP server. Cleanup protocol-specific per-connection * resources. BLOCKING. */ -static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode smtp_disconnect(struct Curl_easy *data, + struct connectdata *conn, + bool dead_connection) { struct smtp_conn *smtpc = &conn->proto.smtpc; + (void)data; /* We cannot send quit unconditionally. If this connection is stale or bad in any way, sending quit and waiting around here will make the disconnect wait in vain and cause more problems than we need to. */ - /* The SMTP session may or may not have been allocated/setup at this - point! */ - if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart) - if(!smtp_perform_quit(conn)) - (void)smtp_block_statemach(conn, TRUE); /* ignore errors on QUIT */ + if(!dead_connection && conn->bits.protoconnstart) { + if(!smtp_perform_quit(data, conn)) + (void)smtp_block_statemach(data, conn, TRUE); /* ignore errors on QUIT */ + } /* Disconnect from the server */ Curl_pp_disconnect(&smtpc->pp); @@ -1551,30 +1558,30 @@ static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection) } /* Call this when the DO phase has completed */ -static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected) +static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected) { - struct SMTP *smtp = conn->data->req.p.smtp; + struct SMTP *smtp = data->req.p.smtp; (void)connected; if(smtp->transfer != FTPTRANSFER_BODY) /* no data to transfer */ - Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); + Curl_setup_transfer(data, -1, -1, FALSE, -1); return CURLE_OK; } /* Called from multi.c while DOing */ -static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done) +static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done) { - CURLcode result = smtp_multi_statemach(conn, dophase_done); + CURLcode result = smtp_multi_statemach(data, dophase_done); if(result) - DEBUGF(infof(conn->data, "DO phase failed\n")); + DEBUGF(infof(data, "DO phase failed\n")); else if(*dophase_done) { - result = smtp_dophase_done(conn, FALSE /* not connected */); + result = smtp_dophase_done(data, FALSE /* not connected */); - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; @@ -1589,12 +1596,11 @@ static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done) * Performs all commands done before a regular transfer between a local and a * remote host. */ -static CURLcode smtp_regular_transfer(struct connectdata *conn, +static CURLcode smtp_regular_transfer(struct Curl_easy *data, bool *dophase_done) { CURLcode result = CURLE_OK; bool connected = FALSE; - struct Curl_easy *data = conn->data; /* Make sure size is unknown at this point */ data->req.size = -1; @@ -1606,16 +1612,17 @@ static CURLcode smtp_regular_transfer(struct connectdata *conn, Curl_pgrsSetDownloadSize(data, -1); /* Carry out the perform */ - result = smtp_perform(conn, &connected, dophase_done); + result = smtp_perform(data, &connected, dophase_done); /* Perform post DO phase operations if necessary */ if(!result && *dophase_done) - result = smtp_dophase_done(conn, connected); + result = smtp_dophase_done(data, connected); return result; } -static CURLcode smtp_setup_connection(struct connectdata *conn) +static CURLcode smtp_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result; @@ -1623,7 +1630,7 @@ static CURLcode smtp_setup_connection(struct connectdata *conn) conn->bits.tls_upgraded = FALSE; /* Initialise the SMTP layer */ - result = smtp_init(conn); + result = smtp_init(data); if(result) return result; @@ -1675,10 +1682,10 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn) * * Parse the URL path into separate path components. */ -static CURLcode smtp_parse_url_path(struct connectdata *conn) +static CURLcode smtp_parse_url_path(struct Curl_easy *data) { /* The SMTP struct is already initialised in smtp_connect() */ - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; const char *path = &data->state.up.path[1]; /* skip leading path */ char localhost[HOSTNAME_MAX + 1]; @@ -1692,7 +1699,7 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn) } /* URL decode the path and use it as the domain in our EHLO */ - return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, + return Curl_urldecode(data, path, 0, &smtpc->domain, NULL, REJECT_CTRL); } @@ -1702,10 +1709,9 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn) * * Parse the custom request. */ -static CURLcode smtp_parse_custom_request(struct connectdata *conn) +static CURLcode smtp_parse_custom_request(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.p.smtp; const char *custom = data->set.str[STRING_CUSTOMREQUEST]; @@ -1750,7 +1756,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn) * calling function deems it to be) then the input will simply be returned in * the address part with the host name being NULL. */ -static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma, +static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma, char **address, struct hostname *host) { CURLcode result = CURLE_OK; @@ -1775,7 +1781,7 @@ static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma, host->name = host->name + 1; /* Attempt to convert the host name to IDN ACE */ - (void) Curl_idnconvert_hostname(conn, host); + (void) Curl_idnconvert_hostname(data, host); /* If Curl_idnconvert_hostname() fails then we shall attempt to continue and send the host name using UTF-8 rather than as 7-bit ACE (which is @@ -1788,7 +1794,7 @@ static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma, return result; } -CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) +CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread) { /* When sending a SMTP payload we must detect CRLF. sequences making sure they are sent as CRLF.. instead, as a . on the beginning of a line will @@ -1798,7 +1804,6 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) */ ssize_t i; ssize_t si; - struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.p.smtp; char *scratch = data->state.scratch; char *newscratch = NULL; diff --git a/libs/libcurl/src/smtp.h b/libs/libcurl/src/smtp.h index c7c62ee857..1fe45346ee 100644 --- a/libs/libcurl/src/smtp.h +++ b/libs/libcurl/src/smtp.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2009 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2009 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -57,10 +57,10 @@ struct SMTP { struct curl_slist *rcpt; /* Recipient list */ bool rcpt_had_ok; /* Whether any of RCPT TO commands (depends on total number of recipients) succeeded so far */ + bool trailing_crlf; /* Specifies if the trailing CRLF is present */ int rcpt_last_error; /* The last error received for RCPT TO command */ size_t eob; /* Number of bytes of the EOB (End Of Body) that have been received so far */ - bool trailing_crlf; /* Specifies if the tailing CRLF is present */ }; /* smtp_conn is used for struct connection-oriented data in the connectdata @@ -91,6 +91,6 @@ extern const struct Curl_handler Curl_handler_smtps; #define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e" #define SMTP_EOB_REPL_LEN 4 -CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread); +CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread); #endif /* HEADER_CURL_SMTP_H */ diff --git a/libs/libcurl/src/socks.c b/libs/libcurl/src/socks.c index a2d1e621f9..d1c2a2ed14 100644 --- a/libs/libcurl/src/socks.c +++ b/libs/libcurl/src/socks.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , 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 @@ * * This is STUPID BLOCKING behavior. Only used by the SOCKS GSSAPI functions. */ -int Curl_blockread_all(struct connectdata *conn, /* connection data */ +int Curl_blockread_all(struct Curl_easy *data, /* transfer */ curl_socket_t sockfd, /* read from this socket */ char *buf, /* store read data here */ ssize_t buffersize, /* max amount to read */ @@ -62,7 +62,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */ int result; *n = 0; for(;;) { - timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, TRUE); + timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); if(timeout_ms < 0) { /* we already got the timeout */ result = CURLE_OPERATION_TIMEDOUT; @@ -107,13 +107,14 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */ /* always use this function to change state, to make debugging easier */ -static void socksstate(struct connectdata *conn, +static void socksstate(struct Curl_easy *data, enum connect_t state #ifdef DEBUGBUILD , int lineno #endif ) { + struct connectdata *conn = data->conn; enum connect_t oldstate = conn->cnnct.state; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* synced with the state list in urldata.h */ @@ -146,7 +147,7 @@ static void socksstate(struct connectdata *conn, conn->cnnct.state = state; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - infof(conn->data, + infof(data, "SXSTATE: %s => %s conn %p; line %d\n", statename[oldstate], statename[conn->cnnct.state], conn, lineno); @@ -188,29 +189,32 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn, + struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; const bool protocol4a = (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE; - unsigned char *socksreq = &conn->cnnct.socksreq[0]; + unsigned char *socksreq = (unsigned char *)data->state.buffer; CURLcode result; curl_socket_t sockfd = conn->sock[sockindex]; - struct Curl_easy *data = conn->data; struct connstate *sx = &conn->cnnct; struct Curl_dns_entry *dns = NULL; ssize_t actualread; ssize_t written; + /* make sure that the buffer is at least 600 bytes */ + DEBUGASSERT(READBUFFER_MIN >= 600); + if(!SOCKS_STATE(sx->state) && !*done) - sxstate(conn, CONNECT_SOCKS_INIT); + sxstate(data, CONNECT_SOCKS_INIT); switch(sx->state) { case CONNECT_SOCKS_INIT: /* SOCKS4 can only do IPv4, insist! */ conn->ip_version = CURL_IPRESOLVE_V4; if(conn->bits.httpproxy) - infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n", + infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n", protocol4a ? "a" : "", hostname, remote_port); infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port); @@ -234,37 +238,37 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, /* DNS resolve only for SOCKS4, not SOCKS4a */ if(!protocol4a) { enum resolve_t rc = - Curl_resolv(conn, hostname, remote_port, FALSE, &dns); + Curl_resolv(data, hostname, remote_port, FALSE, &dns); if(rc == CURLRESOLV_ERROR) return CURLPX_RESOLVE_HOST; else if(rc == CURLRESOLV_PENDING) { - sxstate(conn, CONNECT_RESOLVING); + sxstate(data, CONNECT_RESOLVING); infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname); return CURLPX_OK; } - sxstate(conn, CONNECT_RESOLVED); + sxstate(data, CONNECT_RESOLVED); goto CONNECT_RESOLVED; } /* socks4a doesn't resolve anything locally */ - sxstate(conn, CONNECT_REQ_INIT); + sxstate(data, CONNECT_REQ_INIT); goto CONNECT_REQ_INIT; case CONNECT_RESOLVING: /* check if we have the name resolved by now */ - dns = Curl_fetch_addr(conn, hostname, (int)conn->port); + dns = Curl_fetch_addr(data, hostname, (int)conn->port); if(dns) { #ifdef CURLRES_ASYNCH - conn->async.dns = dns; - conn->async.done = TRUE; + data->state.async.dns = dns; + data->state.async.done = TRUE; #endif infof(data, "Hostname '%s' was found\n", hostname); - sxstate(conn, CONNECT_RESOLVED); + sxstate(data, CONNECT_RESOLVED); } else { - result = Curl_resolv_check(data->conn, &dns); + result = Curl_resolv_check(data, &dns); if(!dns) { if(result) return CURLPX_RESOLVE_HOST; @@ -298,7 +302,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, } else { hp = NULL; /* fail! */ - failf(data, "SOCKS4 connection to %s not supported\n", buf); + failf(data, "SOCKS4 connection to %s not supported", buf); } Curl_resolv_unlock(data, dns); /* not used anymore from now on */ @@ -318,8 +322,8 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, socksreq[8] = 0; /* ensure empty userid is NUL-terminated */ if(proxy_user) { size_t plen = strlen(proxy_user); - if(plen >= sizeof(sx->socksreq) - 8) { - failf(data, "Too long SOCKS proxy user name, can't use!\n"); + if(plen >= (size_t)data->set.buffer_size - 8) { + failf(data, "Too long SOCKS proxy user name, can't use!"); return CURLPX_LONG_USER; } /* copy the proxy name WITH trailing zero */ @@ -352,12 +356,12 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, } sx->outp = socksreq; sx->outstanding = packetsize; - sxstate(conn, CONNECT_REQ_SENDING); + sxstate(data, CONNECT_REQ_SENDING); } /* FALLTHROUGH */ case CONNECT_REQ_SENDING: /* Send request */ - result = Curl_write_plain(conn, sockfd, (char *)sx->outp, + result = Curl_write_plain(data, sockfd, (char *)sx->outp, sx->outstanding, &written); if(result && (CURLE_AGAIN != result)) { failf(data, "Failed to send SOCKS4 connect request."); @@ -373,7 +377,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, /* done sending! */ sx->outstanding = 8; /* receive data size */ sx->outp = socksreq; - sxstate(conn, CONNECT_SOCKS_READ); + sxstate(data, CONNECT_SOCKS_READ); /* FALLTHROUGH */ case CONNECT_SOCKS_READ: @@ -396,7 +400,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, sx->outp += actualread; return CURLPX_OK; } - sxstate(conn, CONNECT_DONE); + sxstate(data, CONNECT_DONE); break; default: /* lots of unused states in SOCKS4 */ break; @@ -437,8 +441,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, failf(data, "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" ", request rejected or failed.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], + socksreq[4], socksreq[5], socksreq[6], socksreq[7], (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), (unsigned char)socksreq[1]); return CURLPX_REQUEST_FAILED; @@ -447,8 +450,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" ", request rejected because SOCKS server cannot connect to " "identd on the client.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], + socksreq[4], socksreq[5], socksreq[6], socksreq[7], (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), (unsigned char)socksreq[1]); return CURLPX_IDENTD; @@ -457,8 +459,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" ", request rejected because the client program and identd " "report different user-ids.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], + socksreq[4], socksreq[5], socksreq[6], socksreq[7], (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), (unsigned char)socksreq[1]); return CURLPX_IDENTD_DIFFER; @@ -466,8 +467,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, failf(data, "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" ", Unknown.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], + socksreq[4], socksreq[5], socksreq[6], socksreq[7], (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), (unsigned char)socksreq[1]); return CURLPX_UNKNOWN_FAIL; @@ -486,7 +486,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn, + struct Curl_easy *data, bool *done) { /* @@ -505,14 +505,14 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, o REP Reply field: o X'00' succeeded */ - unsigned char *socksreq = &conn->cnnct.socksreq[0]; + struct connectdata *conn = data->conn; + unsigned char *socksreq = (unsigned char *)data->state.buffer; char dest[256] = "unknown"; /* printable hostname:port */ int idx; ssize_t actualread; ssize_t written; CURLcode result; curl_socket_t sockfd = conn->sock[sockindex]; - struct Curl_easy *data = conn->data; bool socks5_resolve_local = (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE; const size_t hostname_len = strlen(hostname); @@ -523,23 +523,23 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, struct Curl_dns_entry *dns = NULL; if(!SOCKS_STATE(sx->state) && !*done) - sxstate(conn, CONNECT_SOCKS_INIT); + sxstate(data, CONNECT_SOCKS_INIT); switch(sx->state) { case CONNECT_SOCKS_INIT: if(conn->bits.httpproxy) - infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n", + infof(data, "SOCKS5: connecting to HTTP proxy %s port %d\n", hostname, remote_port); /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ if(!socks5_resolve_local && hostname_len > 255) { - infof(conn->data, "SOCKS5: server resolving disabled for hostnames of " + infof(data, "SOCKS5: server resolving disabled for hostnames of " "length > 255 [actual len=%zu]\n", hostname_len); socks5_resolve_local = TRUE; } if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) - infof(conn->data, + infof(data, "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n", auth); if(!(auth & CURLAUTH_BASIC)) @@ -561,21 +561,21 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, /* write the number of authentication methods */ socksreq[1] = (unsigned char) (idx - 2); - result = Curl_write_plain(conn, sockfd, (char *)socksreq, idx, &written); + result = Curl_write_plain(data, sockfd, (char *)socksreq, idx, &written); if(result && (CURLE_AGAIN != result)) { failf(data, "Unable to send initial SOCKS5 request."); return CURLPX_SEND_CONNECT; } if(written != idx) { - sxstate(conn, CONNECT_SOCKS_SEND); + sxstate(data, CONNECT_SOCKS_SEND); sx->outstanding = idx - written; sx->outp = &socksreq[written]; return CURLPX_OK; } - sxstate(conn, CONNECT_SOCKS_READ); + sxstate(data, CONNECT_SOCKS_READ); goto CONNECT_SOCKS_READ_INIT; case CONNECT_SOCKS_SEND: - result = Curl_write_plain(conn, sockfd, (char *)sx->outp, + result = Curl_write_plain(data, sockfd, (char *)sx->outp, sx->outstanding, &written); if(result && (CURLE_AGAIN != result)) { failf(data, "Unable to send initial SOCKS5 request."); @@ -617,18 +617,18 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, } else if(socksreq[1] == 0) { /* DONE! No authentication needed. Send request. */ - sxstate(conn, CONNECT_REQ_INIT); + sxstate(data, CONNECT_REQ_INIT); goto CONNECT_REQ_INIT; } else if(socksreq[1] == 2) { /* regular name + password authentication */ - sxstate(conn, CONNECT_AUTH_INIT); + sxstate(data, CONNECT_AUTH_INIT); goto CONNECT_AUTH_INIT; } #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) else if(allow_gssapi && (socksreq[1] == 1)) { - sxstate(conn, CONNECT_GSSAPI_INIT); - result = Curl_SOCKS5_gssapi_negotiate(sockindex, conn); + sxstate(data, CONNECT_GSSAPI_INIT); + result = Curl_SOCKS5_gssapi_negotiate(sockindex, data); if(result) { failf(data, "Unable to negotiate SOCKS5 GSS-API context."); return CURLPX_GSSAPI; @@ -701,13 +701,13 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, memcpy(socksreq + len, proxy_password, proxy_password_len); } len += proxy_password_len; - sxstate(conn, CONNECT_AUTH_SEND); + sxstate(data, CONNECT_AUTH_SEND); sx->outstanding = len; sx->outp = socksreq; } /* FALLTHROUGH */ case CONNECT_AUTH_SEND: - result = Curl_write_plain(conn, sockfd, (char *)sx->outp, + result = Curl_write_plain(data, sockfd, (char *)sx->outp, sx->outstanding, &written); if(result && (CURLE_AGAIN != result)) { failf(data, "Failed to send SOCKS5 sub-negotiation request."); @@ -721,7 +721,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, } sx->outp = socksreq; sx->outstanding = 2; - sxstate(conn, CONNECT_AUTH_READ); + sxstate(data, CONNECT_AUTH_READ); /* FALLTHROUGH */ case CONNECT_AUTH_READ: result = Curl_read_plain(sockfd, (char *)sx->outp, @@ -749,40 +749,40 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, } /* Everything is good so far, user was authenticated! */ - sxstate(conn, CONNECT_REQ_INIT); + sxstate(data, CONNECT_REQ_INIT); /* FALLTHROUGH */ CONNECT_REQ_INIT: case CONNECT_REQ_INIT: if(socks5_resolve_local) { - enum resolve_t rc = Curl_resolv(conn, hostname, remote_port, + enum resolve_t rc = Curl_resolv(data, hostname, remote_port, FALSE, &dns); if(rc == CURLRESOLV_ERROR) return CURLPX_RESOLVE_HOST; if(rc == CURLRESOLV_PENDING) { - sxstate(conn, CONNECT_RESOLVING); + sxstate(data, CONNECT_RESOLVING); return CURLPX_OK; } - sxstate(conn, CONNECT_RESOLVED); + sxstate(data, CONNECT_RESOLVED); goto CONNECT_RESOLVED; } goto CONNECT_RESOLVE_REMOTE; case CONNECT_RESOLVING: /* check if we have the name resolved by now */ - dns = Curl_fetch_addr(conn, hostname, remote_port); + dns = Curl_fetch_addr(data, hostname, remote_port); if(dns) { #ifdef CURLRES_ASYNCH - conn->async.dns = dns; - conn->async.done = TRUE; + data->state.async.dns = dns; + data->state.async.done = TRUE; #endif infof(data, "SOCKS5: hostname '%s' found\n", hostname); } if(!dns) { - result = Curl_resolv_check(data->conn, &dns); + result = Curl_resolv_check(data, &dns); if(!dns) { if(result) return CURLPX_RESOLVE_HOST; @@ -839,7 +839,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, #endif else { hp = NULL; /* fail! */ - failf(data, "SOCKS5 connection to %s not supported\n", dest); + failf(data, "SOCKS5 connection to %s not supported", dest); } Curl_resolv_unlock(data, dns); /* not used anymore from now on */ @@ -878,10 +878,10 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, #endif sx->outp = socksreq; sx->outstanding = len; - sxstate(conn, CONNECT_REQ_SENDING); + sxstate(data, CONNECT_REQ_SENDING); /* FALLTHROUGH */ case CONNECT_REQ_SENDING: - result = Curl_write_plain(conn, sockfd, (char *)sx->outp, + result = Curl_write_plain(data, sockfd, (char *)sx->outp, sx->outstanding, &written); if(result && (CURLE_AGAIN != result)) { failf(data, "Failed to send SOCKS5 connect request."); @@ -901,7 +901,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, #endif sx->outstanding = 10; /* minimum packet size is 10 */ sx->outp = socksreq; - sxstate(conn, CONNECT_REQ_READ); + sxstate(data, CONNECT_REQ_READ); /* FALLTHROUGH */ case CONNECT_REQ_READ: result = Curl_read_plain(sockfd, (char *)sx->outp, @@ -992,10 +992,10 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, if(len > 10) { sx->outstanding = len - 10; /* get the rest */ sx->outp = &socksreq[10]; - sxstate(conn, CONNECT_REQ_READ_MORE); + sxstate(data, CONNECT_REQ_READ_MORE); } else { - sxstate(conn, CONNECT_DONE); + sxstate(data, CONNECT_DONE); break; } #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) @@ -1020,7 +1020,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, sx->outp += actualread; return CURLPX_OK; } - sxstate(conn, CONNECT_DONE); + sxstate(data, CONNECT_DONE); } infof(data, "SOCKS5 request granted.\n"); diff --git a/libs/libcurl/src/socks.h b/libs/libcurl/src/socks.h index 1fae58b6fa..b0c7f9b26b 100644 --- a/libs/libcurl/src/socks.h +++ b/libs/libcurl/src/socks.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,7 +35,7 @@ * * This is STUPID BLOCKING behavior */ -int Curl_blockread_all(struct connectdata *conn, +int Curl_blockread_all(struct Curl_easy *data, curl_socket_t sockfd, char *buf, ssize_t buffersize, @@ -52,7 +52,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_name, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn, + struct Curl_easy *data, bool *done); /* @@ -64,7 +64,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_name, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn, + struct Curl_easy *data, bool *done); #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) @@ -72,7 +72,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_name, * This function handles the SOCKS5 GSS-API negotiation and initialisation */ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, - struct connectdata *conn); + struct Curl_easy *data); #endif #endif /* CURL_DISABLE_PROXY */ diff --git a/libs/libcurl/src/socks_gssapi.c b/libs/libcurl/src/socks_gssapi.c index a96579692b..3ab786d0bd 100644 --- a/libs/libcurl/src/socks_gssapi.c +++ b/libs/libcurl/src/socks_gssapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * Copyright (C) 2009, Markus Moeller, * * This software is licensed as described in the file COPYING, which @@ -92,7 +92,7 @@ static int check_gss_err(struct Curl_easy *data, } gss_release_buffer(&min_stat, &status_string); } - failf(data, "GSS-API error: %s failed:\n%s", function, buf); + failf(data, "GSS-API error: %s failed: %s", function, buf); return 1; } @@ -100,9 +100,9 @@ static int check_gss_err(struct Curl_easy *data, } CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, - struct connectdata *conn) + struct Curl_easy *data) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; curl_socket_t sock = conn->sock[sockindex]; CURLcode code; ssize_t actualread; @@ -201,7 +201,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, us_length = htons((short)gss_send_token.length); memcpy(socksreq + 2, &us_length, sizeof(short)); - code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written); if(code || (4 != written)) { failf(data, "Failed to send GSS-API authentication request."); gss_release_name(&gss_status, &server); @@ -211,7 +211,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - code = Curl_write_plain(conn, sock, (char *)gss_send_token.value, + code = Curl_write_plain(data, sock, (char *)gss_send_token.value, gss_send_token.length, &written); if(code || ((ssize_t)gss_send_token.length != written)) { @@ -240,7 +240,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, * +----+------+-----+----------------+ */ - result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread); if(result || (actualread != 4)) { failf(data, "Failed to receive GSS-API authentication response."); gss_release_name(&gss_status, &server); @@ -279,7 +279,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_OUT_OF_MEMORY; } - result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, + result = Curl_blockread_all(data, sock, (char *)gss_recv_token.value, gss_recv_token.length, &actualread); if(result || (actualread != us_length)) { @@ -408,7 +408,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, memcpy(socksreq + 2, &us_length, sizeof(short)); } - code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written); if(code || (4 != written)) { failf(data, "Failed to send GSS-API encryption request."); gss_release_buffer(&gss_status, &gss_w_token); @@ -418,7 +418,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, if(data->set.socks5_gssapi_nec) { memcpy(socksreq, &gss_enc, 1); - code = Curl_write_plain(conn, sock, socksreq, 1, &written); + code = Curl_write_plain(data, sock, socksreq, 1, &written); if(code || ( 1 != written)) { failf(data, "Failed to send GSS-API encryption type."); gss_delete_sec_context(&gss_status, &gss_context, NULL); @@ -426,7 +426,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, } } else { - code = Curl_write_plain(conn, sock, (char *)gss_w_token.value, + code = Curl_write_plain(data, sock, (char *)gss_w_token.value, gss_w_token.length, &written); if(code || ((ssize_t)gss_w_token.length != written)) { failf(data, "Failed to send GSS-API encryption type."); @@ -437,7 +437,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_release_buffer(&gss_status, &gss_w_token); } - result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread); if(result || (actualread != 4)) { failf(data, "Failed to receive GSS-API encryption response."); gss_delete_sec_context(&gss_status, &gss_context, NULL); @@ -468,7 +468,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_OUT_OF_MEMORY; } - result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, + result = Curl_blockread_all(data, sock, (char *)gss_recv_token.value, gss_recv_token.length, &actualread); if(result || (actualread != us_length)) { diff --git a/libs/libcurl/src/socks_sspi.c b/libs/libcurl/src/socks_sspi.c index b9ac2ade8e..b343538f0c 100644 --- a/libs/libcurl/src/socks_sspi.c +++ b/libs/libcurl/src/socks_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * Copyright (C) 2009, 2011, Markus Moeller, * * This software is licensed as described in the file COPYING, which @@ -43,7 +43,7 @@ /* * Helper sspi error functions. */ -static int check_sspi_err(struct connectdata *conn, +static int check_sspi_err(struct Curl_easy *data, SECURITY_STATUS status, const char *function) { @@ -52,7 +52,7 @@ static int check_sspi_err(struct connectdata *conn, status != SEC_I_COMPLETE_NEEDED && status != SEC_I_CONTINUE_NEEDED) { char buffer[STRERROR_LEN]; - failf(conn->data, "SSPI error: %s failed: %s", function, + failf(data, "SSPI error: %s failed: %s", function, Curl_sspi_strerror(status, buffer, sizeof(buffer))); return 1; } @@ -61,9 +61,9 @@ static int check_sspi_err(struct connectdata *conn, /* This is the SSPI-using version of this function */ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, - struct connectdata *conn) + struct Curl_easy *data) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; curl_socket_t sock = conn->sock[sockindex]; CURLcode code; ssize_t actualread; @@ -86,7 +86,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, unsigned long qop; unsigned char socksreq[4]; /* room for GSS-API exchange header only */ const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ? - data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; + data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; const size_t service_length = strlen(service); /* GSS-API request looks like @@ -146,7 +146,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, &cred_handle, &expiry); - if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) { + if(check_sspi_err(data, status, "AcquireCredentialsHandle")) { failf(data, "Failed to acquire credentials."); free(service_name); s_pSecFn->FreeCredentialsHandle(&cred_handle); @@ -188,7 +188,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, sspi_recv_token.cbBuffer = 0; } - if(check_sspi_err(conn, status, "InitializeSecurityContext")) { + if(check_sspi_err(data, status, "InitializeSecurityContext")) { free(service_name); s_pSecFn->FreeCredentialsHandle(&cred_handle); s_pSecFn->DeleteSecurityContext(&sspi_context); @@ -204,7 +204,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, us_length = htons((short)sspi_send_token.cbBuffer); memcpy(socksreq + 2, &us_length, sizeof(short)); - code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written); if(code || (4 != written)) { failf(data, "Failed to send SSPI authentication request."); free(service_name); @@ -217,7 +217,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, + code = Curl_write_plain(data, sock, (char *)sspi_send_token.pvBuffer, sspi_send_token.cbBuffer, &written); if(code || (sspi_send_token.cbBuffer != (size_t)written)) { failf(data, "Failed to send SSPI authentication token."); @@ -258,7 +258,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, * +----+------+-----+----------------+ */ - result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread); if(result || (actualread != 4)) { failf(data, "Failed to receive SSPI authentication response."); free(service_name); @@ -298,7 +298,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, s_pSecFn->DeleteSecurityContext(&sspi_context); return CURLE_OUT_OF_MEMORY; } - result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer, + result = Curl_blockread_all(data, sock, (char *)sspi_recv_token.pvBuffer, sspi_recv_token.cbBuffer, &actualread); if(result || (actualread != us_length)) { @@ -321,7 +321,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, SECPKG_CRED_ATTR_NAMES, &names); s_pSecFn->FreeCredentialsHandle(&cred_handle); - if(check_sspi_err(conn, status, "QueryCredentialAttributes")) { + if(check_sspi_err(data, status, "QueryCredentialAttributes")) { s_pSecFn->DeleteSecurityContext(&sspi_context); s_pSecFn->FreeContextBuffer(names.sUserName); failf(data, "Failed to determine user name."); @@ -386,7 +386,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, status = s_pSecFn->QueryContextAttributes(&sspi_context, SECPKG_ATTR_SIZES, &sspi_sizes); - if(check_sspi_err(conn, status, "QueryContextAttributes")) { + if(check_sspi_err(data, status, "QueryContextAttributes")) { s_pSecFn->DeleteSecurityContext(&sspi_context); failf(data, "Failed to query security context attributes."); return CURLE_COULDNT_CONNECT; @@ -423,7 +423,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, KERB_WRAP_NO_ENCRYPT, &wrap_desc, 0); - if(check_sspi_err(conn, status, "EncryptMessage")) { + if(check_sspi_err(data, status, "EncryptMessage")) { s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); @@ -466,7 +466,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, memcpy(socksreq + 2, &us_length, sizeof(short)); } - code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written); if(code || (4 != written)) { failf(data, "Failed to send SSPI encryption request."); if(sspi_send_token.pvBuffer) @@ -477,7 +477,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, if(data->set.socks5_gssapi_nec) { memcpy(socksreq, &gss_enc, 1); - code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written); + code = Curl_write_plain(data, sock, (char *)socksreq, 1, &written); if(code || (1 != written)) { failf(data, "Failed to send SSPI encryption type."); s_pSecFn->DeleteSecurityContext(&sspi_context); @@ -485,7 +485,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, } } else { - code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, + code = Curl_write_plain(data, sock, (char *)sspi_send_token.pvBuffer, sspi_send_token.cbBuffer, &written); if(code || (sspi_send_token.cbBuffer != (size_t)written)) { failf(data, "Failed to send SSPI encryption type."); @@ -498,7 +498,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); } - result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread); if(result || (actualread != 4)) { failf(data, "Failed to receive SSPI encryption response."); s_pSecFn->DeleteSecurityContext(&sspi_context); @@ -530,7 +530,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_OUT_OF_MEMORY; } - result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer, + result = Curl_blockread_all(data, sock, (char *)sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer, &actualread); if(result || (actualread != us_length)) { @@ -553,7 +553,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, 0, &qop); - if(check_sspi_err(conn, status, "DecryptMessage")) { + if(check_sspi_err(data, status, "DecryptMessage")) { if(sspi_w_token[0].pvBuffer) s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); if(sspi_w_token[1].pvBuffer) diff --git a/libs/libcurl/src/speedcheck.c b/libs/libcurl/src/speedcheck.c index 2665a44c55..841d256b48 100644 --- a/libs/libcurl/src/speedcheck.c +++ b/libs/libcurl/src/speedcheck.c @@ -39,6 +39,10 @@ void Curl_speedinit(struct Curl_easy *data) CURLcode Curl_speedcheck(struct Curl_easy *data, struct curltime now) { + if(data->req.keepon & KEEP_RECV_PAUSE) + /* A paused transfer is not qualified for speed checks */ + return CURLE_OK; + if((data->progress.current_speed >= 0) && data->set.low_speed_time) { if(data->progress.current_speed < data->set.low_speed_limit) { if(!data->state.keeps_speed.tv_sec) diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c index 9b2fc26c2f..3862aabd6f 100644 --- a/libs/libcurl/src/strerror.c +++ b/libs/libcurl/src/strerror.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2004 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2004 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -721,7 +721,9 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) if(!buflen) return NULL; +#ifndef WIN32 DEBUGASSERT(err >= 0); +#endif max = buflen - 1; *buf = '\0'; diff --git a/libs/libcurl/src/system_win32.c b/libs/libcurl/src/system_win32.c index b377da7d8b..2132f43ef7 100644 --- a/libs/libcurl/src/system_win32.c +++ b/libs/libcurl/src/system_win32.c @@ -196,7 +196,7 @@ HMODULE Curl_load_library(LPCTSTR filename) pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : LoadLibrary(filename); } - /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only + /* Detect if KB2533623 is installed, as LOAD_LIBRARY_SEARCH_SYSTEM32 is only supported on Windows Vista, Windows Server 2008, Windows 7 and Windows Server 2008 R2 with this patch or natively on Windows 8 and above */ else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) { diff --git a/libs/libcurl/src/telnet.c b/libs/libcurl/src/telnet.c index 8bf64a9f2b..f96a4cb4c5 100644 --- a/libs/libcurl/src/telnet.c +++ b/libs/libcurl/src/telnet.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -88,7 +88,7 @@ #endif static -CURLcode telrcv(struct connectdata *, +CURLcode telrcv(struct Curl_easy *data, const unsigned char *inbuf, /* Data received from socket */ ssize_t count); /* Number of bytes received */ @@ -98,23 +98,23 @@ static void printoption(struct Curl_easy *data, int cmd, int option); #endif -static void negotiate(struct connectdata *); -static void send_negotiation(struct connectdata *, int cmd, int option); -static void set_local_option(struct connectdata *conn, +static void negotiate(struct Curl_easy *data); +static void send_negotiation(struct Curl_easy *data, int cmd, int option); +static void set_local_option(struct Curl_easy *data, int option, int newstate); -static void set_remote_option(struct connectdata *conn, +static void set_remote_option(struct Curl_easy *data, int option, int newstate); static void printsub(struct Curl_easy *data, int direction, unsigned char *pointer, size_t length); -static void suboption(struct connectdata *); -static void sendsuboption(struct connectdata *conn, int option); +static void suboption(struct Curl_easy *data); +static void sendsuboption(struct Curl_easy *data, int option); -static CURLcode telnet_do(struct connectdata *conn, bool *done); -static CURLcode telnet_done(struct connectdata *conn, +static CURLcode telnet_do(struct Curl_easy *data, bool *done); +static CURLcode telnet_done(struct Curl_easy *data, CURLcode, bool premature); -static CURLcode send_telnet_data(struct connectdata *conn, +static CURLcode send_telnet_data(struct Curl_easy *data, char *buffer, ssize_t nread); /* For negotiation compliant to RFC 1143 */ @@ -156,13 +156,12 @@ struct TELNET { char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */ unsigned short subopt_wsx; /* Set with suboption NAWS */ unsigned short subopt_wsy; /* Set with suboption NAWS */ + TelnetReceive telrcv_state; struct curl_slist *telnet_vars; /* Environment variables */ /* suboptions */ unsigned char subbuffer[SUBBUFSIZE]; unsigned char *subpointer, *subend; /* buffer for sub-options */ - - TelnetReceive telrcv_state; }; @@ -194,7 +193,7 @@ const struct Curl_handler Curl_handler_telnet = { static -CURLcode init_telnet(struct connectdata *conn) +CURLcode init_telnet(struct Curl_easy *data) { struct TELNET *tn; @@ -202,7 +201,7 @@ CURLcode init_telnet(struct connectdata *conn) if(!tn) return CURLE_OUT_OF_MEMORY; - conn->data->req.p.telnet = tn; /* make us known */ + data->req.p.telnet = tn; /* make us known */ tn->telrcv_state = CURL_TS_DATA; @@ -214,7 +213,7 @@ CURLcode init_telnet(struct connectdata *conn) tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES; /* To be compliant with previous releases of libcurl - we enable this option by default. This behaviour + we enable this option by default. This behavior can be changed thanks to the "BINARY" option in CURLOPT_TELNETOPTIONS */ @@ -244,20 +243,20 @@ CURLcode init_telnet(struct connectdata *conn) return CURLE_OK; } -static void negotiate(struct connectdata *conn) +static void negotiate(struct Curl_easy *data) { int i; - struct TELNET *tn = (struct TELNET *) conn->data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; for(i = 0; i < CURL_NTELOPTS; i++) { if(i == CURL_TELOPT_ECHO) continue; if(tn->us_preferred[i] == CURL_YES) - set_local_option(conn, i, CURL_YES); + set_local_option(data, i, CURL_YES); if(tn->him_preferred[i] == CURL_YES) - set_remote_option(conn, i, CURL_YES); + set_remote_option(data, i, CURL_YES); } } @@ -298,34 +297,34 @@ static void printoption(struct Curl_easy *data, } #endif -static void send_negotiation(struct connectdata *conn, int cmd, int option) +static void send_negotiation(struct Curl_easy *data, int cmd, int option) { - unsigned char buf[3]; - ssize_t bytes_written; - struct Curl_easy *data = conn->data; + unsigned char buf[3]; + ssize_t bytes_written; + struct connectdata *conn = data->conn; - buf[0] = CURL_IAC; - buf[1] = (unsigned char)cmd; - buf[2] = (unsigned char)option; + buf[0] = CURL_IAC; + buf[1] = (unsigned char)cmd; + buf[2] = (unsigned char)option; - bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3); - if(bytes_written < 0) { - int err = SOCKERRNO; - failf(data,"Sending data failed (%d)",err); - } + bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3); + if(bytes_written < 0) { + int err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } - printoption(conn->data, "SENT", cmd, option); + printoption(data, "SENT", cmd, option); } static -void set_remote_option(struct connectdata *conn, int option, int newstate) +void set_remote_option(struct Curl_easy *data, int option, int newstate) { - struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; if(newstate == CURL_YES) { switch(tn->him[option]) { case CURL_NO: tn->him[option] = CURL_WANTYES; - send_negotiation(conn, CURL_DO, option); + send_negotiation(data, CURL_DO, option); break; case CURL_YES: @@ -364,7 +363,7 @@ void set_remote_option(struct connectdata *conn, int option, int newstate) case CURL_YES: tn->him[option] = CURL_WANTNO; - send_negotiation(conn, CURL_DONT, option); + send_negotiation(data, CURL_DONT, option); break; case CURL_WANTNO: @@ -392,17 +391,17 @@ void set_remote_option(struct connectdata *conn, int option, int newstate) } static -void rec_will(struct connectdata *conn, int option) +void rec_will(struct Curl_easy *data, int option) { - struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; switch(tn->him[option]) { case CURL_NO: if(tn->him_preferred[option] == CURL_YES) { tn->him[option] = CURL_YES; - send_negotiation(conn, CURL_DO, option); + send_negotiation(data, CURL_DO, option); } else - send_negotiation(conn, CURL_DONT, option); + send_negotiation(data, CURL_DONT, option); break; @@ -432,7 +431,7 @@ void rec_will(struct connectdata *conn, int option) case CURL_OPPOSITE: tn->him[option] = CURL_WANTNO; tn->himq[option] = CURL_EMPTY; - send_negotiation(conn, CURL_DONT, option); + send_negotiation(data, CURL_DONT, option); break; } break; @@ -440,9 +439,9 @@ void rec_will(struct connectdata *conn, int option) } static -void rec_wont(struct connectdata *conn, int option) +void rec_wont(struct Curl_easy *data, int option) { - struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; switch(tn->him[option]) { case CURL_NO: /* Already disabled */ @@ -450,7 +449,7 @@ void rec_wont(struct connectdata *conn, int option) case CURL_YES: tn->him[option] = CURL_NO; - send_negotiation(conn, CURL_DONT, option); + send_negotiation(data, CURL_DONT, option); break; case CURL_WANTNO: @@ -462,7 +461,7 @@ void rec_wont(struct connectdata *conn, int option) case CURL_OPPOSITE: tn->him[option] = CURL_WANTYES; tn->himq[option] = CURL_EMPTY; - send_negotiation(conn, CURL_DO, option); + send_negotiation(data, CURL_DO, option); break; } break; @@ -482,14 +481,14 @@ void rec_wont(struct connectdata *conn, int option) } static void -set_local_option(struct connectdata *conn, int option, int newstate) +set_local_option(struct Curl_easy *data, int option, int newstate) { - struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; if(newstate == CURL_YES) { switch(tn->us[option]) { case CURL_NO: tn->us[option] = CURL_WANTYES; - send_negotiation(conn, CURL_WILL, option); + send_negotiation(data, CURL_WILL, option); break; case CURL_YES: @@ -528,7 +527,7 @@ set_local_option(struct connectdata *conn, int option, int newstate) case CURL_YES: tn->us[option] = CURL_WANTNO; - send_negotiation(conn, CURL_WONT, option); + send_negotiation(data, CURL_WONT, option); break; case CURL_WANTNO: @@ -556,26 +555,26 @@ set_local_option(struct connectdata *conn, int option, int newstate) } static -void rec_do(struct connectdata *conn, int option) +void rec_do(struct Curl_easy *data, int option) { - struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; switch(tn->us[option]) { case CURL_NO: if(tn->us_preferred[option] == CURL_YES) { tn->us[option] = CURL_YES; - send_negotiation(conn, CURL_WILL, option); + send_negotiation(data, CURL_WILL, option); if(tn->subnegotiation[option] == CURL_YES) /* transmission of data option */ - sendsuboption(conn, option); + sendsuboption(data, option); } else if(tn->subnegotiation[option] == CURL_YES) { /* send information to achieve this option*/ tn->us[option] = CURL_YES; - send_negotiation(conn, CURL_WILL, option); - sendsuboption(conn, option); + send_negotiation(data, CURL_WILL, option); + sendsuboption(data, option); } else - send_negotiation(conn, CURL_WONT, option); + send_negotiation(data, CURL_WONT, option); break; case CURL_YES: @@ -602,13 +601,13 @@ void rec_do(struct connectdata *conn, int option) tn->us[option] = CURL_YES; if(tn->subnegotiation[option] == CURL_YES) { /* transmission of data option */ - sendsuboption(conn, option); + sendsuboption(data, option); } break; case CURL_OPPOSITE: tn->us[option] = CURL_WANTNO; tn->himq[option] = CURL_EMPTY; - send_negotiation(conn, CURL_WONT, option); + send_negotiation(data, CURL_WONT, option); break; } break; @@ -616,9 +615,9 @@ void rec_do(struct connectdata *conn, int option) } static -void rec_dont(struct connectdata *conn, int option) +void rec_dont(struct Curl_easy *data, int option) { - struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; switch(tn->us[option]) { case CURL_NO: /* Already disabled */ @@ -626,7 +625,7 @@ void rec_dont(struct connectdata *conn, int option) case CURL_YES: tn->us[option] = CURL_NO; - send_negotiation(conn, CURL_WONT, option); + send_negotiation(data, CURL_WONT, option); break; case CURL_WANTNO: @@ -638,7 +637,7 @@ void rec_dont(struct connectdata *conn, int option) case CURL_OPPOSITE: tn->us[option] = CURL_WANTYES; tn->usq[option] = CURL_EMPTY; - send_negotiation(conn, CURL_WILL, option); + send_negotiation(data, CURL_WILL, option); break; } break; @@ -770,14 +769,14 @@ static void printsub(struct Curl_easy *data, } } -static CURLcode check_telnet_options(struct connectdata *conn) +static CURLcode check_telnet_options(struct Curl_easy *data) { struct curl_slist *head; struct curl_slist *beg; char option_keyword[128] = ""; char option_arg[256] = ""; - struct Curl_easy *data = conn->data; - struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; + struct connectdata *conn = data->conn; CURLcode result = CURLE_OK; int binary_option; @@ -874,7 +873,7 @@ static CURLcode check_telnet_options(struct connectdata *conn) * side. */ -static void suboption(struct connectdata *conn) +static void suboption(struct Curl_easy *data) { struct curl_slist *v; unsigned char temp[2048]; @@ -883,8 +882,8 @@ static void suboption(struct connectdata *conn) int err; char varname[128] = ""; char varval[128] = ""; - struct Curl_easy *data = conn->data; - struct TELNET *tn = (struct TELNET *)data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; + struct connectdata *conn = data->conn; printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn) + 2); switch(CURL_SB_GET(tn)) { @@ -951,15 +950,14 @@ static void suboption(struct connectdata *conn) * Send suboption information to the server side. */ -static void sendsuboption(struct connectdata *conn, int option) +static void sendsuboption(struct Curl_easy *data, int option) { ssize_t bytes_written; int err; unsigned short x, y; unsigned char *uc1, *uc2; - - struct Curl_easy *data = conn->data; - struct TELNET *tn = (struct TELNET *)data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; + struct connectdata *conn = data->conn; switch(option) { case CURL_TELOPT_NAWS: @@ -995,7 +993,7 @@ static void sendsuboption(struct connectdata *conn, int option) } /* ... then the window size with the send_telnet_data() function to deal with 0xFF cases ... */ - send_telnet_data(conn, (char *)tn->subbuffer + 3, 4); + send_telnet_data(data, (char *)tn->subbuffer + 3, 4); /* ... and the footer */ bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2); if(bytes_written < 0) { @@ -1008,7 +1006,7 @@ static void sendsuboption(struct connectdata *conn, int option) static -CURLcode telrcv(struct connectdata *conn, +CURLcode telrcv(struct Curl_easy *data, const unsigned char *inbuf, /* Data received from socket */ ssize_t count) /* Number of bytes received */ { @@ -1016,12 +1014,11 @@ CURLcode telrcv(struct connectdata *conn, CURLcode result; int in = 0; int startwrite = -1; - struct Curl_easy *data = conn->data; - struct TELNET *tn = (struct TELNET *)data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; #define startskipping() \ if(startwrite >= 0) { \ - result = Curl_client_write(conn, \ + result = Curl_client_write(data, \ CLIENTWRITE_BODY, \ (char *)&inbuf[startwrite], \ in-startwrite); \ @@ -1097,28 +1094,28 @@ CURLcode telrcv(struct connectdata *conn, case CURL_TS_WILL: printoption(data, "RCVD", CURL_WILL, c); tn->please_negotiate = 1; - rec_will(conn, c); + rec_will(data, c); tn->telrcv_state = CURL_TS_DATA; break; case CURL_TS_WONT: printoption(data, "RCVD", CURL_WONT, c); tn->please_negotiate = 1; - rec_wont(conn, c); + rec_wont(data, c); tn->telrcv_state = CURL_TS_DATA; break; case CURL_TS_DO: printoption(data, "RCVD", CURL_DO, c); tn->please_negotiate = 1; - rec_do(conn, c); + rec_do(data, c); tn->telrcv_state = CURL_TS_DATA; break; case CURL_TS_DONT: printoption(data, "RCVD", CURL_DONT, c); tn->please_negotiate = 1; - rec_dont(conn, c); + rec_dont(data, c); tn->telrcv_state = CURL_TS_DATA; break; @@ -1147,7 +1144,7 @@ CURLcode telrcv(struct connectdata *conn, CURL_SB_TERM(tn); printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c); - suboption(conn); /* handle sub-option */ + suboption(data); /* handle sub-option */ tn->telrcv_state = CURL_TS_IAC; goto process_iac; } @@ -1159,7 +1156,7 @@ CURLcode telrcv(struct connectdata *conn, CURL_SB_ACCUM(tn, CURL_SE); tn->subpointer -= 2; CURL_SB_TERM(tn); - suboption(conn); /* handle sub-option */ + suboption(data); /* handle sub-option */ tn->telrcv_state = CURL_TS_DATA; } break; @@ -1171,13 +1168,14 @@ CURLcode telrcv(struct connectdata *conn, } /* Escape and send a telnet data block */ -static CURLcode send_telnet_data(struct connectdata *conn, +static CURLcode send_telnet_data(struct Curl_easy *data, char *buffer, ssize_t nread) { ssize_t escapes, i, outlen; unsigned char *outbuf = NULL; CURLcode result = CURLE_OK; ssize_t bytes_written, total_written; + struct connectdata *conn = data->conn; /* Determine size of new buffer after escaping */ escapes = 0; @@ -1216,7 +1214,7 @@ static CURLcode send_telnet_data(struct connectdata *conn, break; default: /* write! */ bytes_written = 0; - result = Curl_write(conn, conn->sock[FIRSTSOCKET], + result = Curl_write(data, conn->sock[FIRSTSOCKET], outbuf + total_written, outlen - total_written, &bytes_written); @@ -1232,10 +1230,10 @@ static CURLcode send_telnet_data(struct connectdata *conn, return result; } -static CURLcode telnet_done(struct connectdata *conn, - CURLcode status, bool premature) +static CURLcode telnet_done(struct Curl_easy *data, + CURLcode status, bool premature) { - struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet; + struct TELNET *tn = data->req.p.telnet; (void)status; /* unused */ (void)premature; /* not used */ @@ -1245,15 +1243,15 @@ static CURLcode telnet_done(struct connectdata *conn, curl_slist_free_all(tn->telnet_vars); tn->telnet_vars = NULL; - Curl_safefree(conn->data->req.p.telnet); + Curl_safefree(data->req.p.telnet); return CURLE_OK; } -static CURLcode telnet_do(struct connectdata *conn, bool *done) +static CURLcode telnet_do(struct Curl_easy *data, bool *done) { CURLcode result; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; #ifdef USE_WINSOCK WSAEVENT event_handle; @@ -1279,13 +1277,13 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) *done = TRUE; /* unconditionally */ - result = init_telnet(conn); + result = init_telnet(data); if(result) return result; tn = data->req.p.telnet; - result = check_telnet_options(conn); + result = check_telnet_options(data); if(result) return result; @@ -1378,7 +1376,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) } } - result = send_telnet_data(conn, buf, readfile_read); + result = send_telnet_data(data, buf, readfile_read); if(result) { keepon = FALSE; break; @@ -1396,7 +1394,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) break; } - result = send_telnet_data(conn, buf, readfile_read); + result = send_telnet_data(data, buf, readfile_read); if(result) { keepon = FALSE; break; @@ -1418,7 +1416,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) } if(events.lNetworkEvents & FD_READ) { /* read data from network */ - result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread); + result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread); /* read would've blocked. Loop again */ if(result == CURLE_AGAIN) break; @@ -1434,7 +1432,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) break; } - result = telrcv(conn, (unsigned char *) buf, nread); + result = telrcv(data, (unsigned char *) buf, nread); if(result) { keepon = FALSE; break; @@ -1444,7 +1442,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) otherwise don't. We don't want to speak telnet with non-telnet servers, like POP or SMTP. */ if(tn->please_negotiate && !tn->already_negotiated) { - negotiate(conn); + negotiate(data); tn->already_negotiated = 1; } } @@ -1498,7 +1496,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) default: /* read! */ if(pfd[0].revents & POLLIN) { /* read data from network */ - result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread); + result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread); /* read would've blocked. Loop again */ if(result == CURLE_AGAIN) break; @@ -1516,7 +1514,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) total_dl += nread; Curl_pgrsSetDownloadCounter(data, total_dl); - result = telrcv(conn, (unsigned char *)buf, nread); + result = telrcv(data, (unsigned char *)buf, nread); if(result) { keepon = FALSE; break; @@ -1526,7 +1524,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) otherwise don't. We don't want to speak telnet with non-telnet servers, like POP or SMTP. */ if(tn->please_negotiate && !tn->already_negotiated) { - negotiate(conn); + negotiate(data); tn->already_negotiated = 1; } } @@ -1550,7 +1548,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) } if(nread > 0) { - result = send_telnet_data(conn, buf, nread); + result = send_telnet_data(data, buf, nread); if(result) { keepon = FALSE; break; @@ -1573,7 +1571,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) } } - if(Curl_pgrsUpdate(conn)) { + if(Curl_pgrsUpdate(data)) { result = CURLE_ABORTED_BY_CALLBACK; break; } diff --git a/libs/libcurl/src/tftp.c b/libs/libcurl/src/tftp.c index fba3f5e8c2..3f1d1b51b7 100644 --- a/libs/libcurl/src/tftp.c +++ b/libs/libcurl/src/tftp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -124,7 +124,7 @@ struct tftp_state_data { tftp_mode_t mode; tftp_error_t error; tftp_event_t event; - struct connectdata *conn; + struct Curl_easy *data; curl_socket_t sockfd; int retries; int retry_time; @@ -132,7 +132,6 @@ struct tftp_state_data { time_t start_time; time_t max_time; time_t rx_time; - unsigned short block; struct Curl_sockaddr_storage local_addr; struct Curl_sockaddr_storage remote_addr; curl_socklen_t remote_addrlen; @@ -140,6 +139,7 @@ struct tftp_state_data { int sbytes; int blksize; int requested_blksize; + unsigned short block; struct tftp_packet rpacket; struct tftp_packet spacket; }; @@ -148,16 +148,19 @@ struct tftp_state_data { /* Forward declarations */ static CURLcode tftp_rx(struct tftp_state_data *state, tftp_event_t event); static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event); -static CURLcode tftp_connect(struct connectdata *conn, bool *done); -static CURLcode tftp_disconnect(struct connectdata *conn, +static CURLcode tftp_connect(struct Curl_easy *data, bool *done); +static CURLcode tftp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection); -static CURLcode tftp_do(struct connectdata *conn, bool *done); -static CURLcode tftp_done(struct connectdata *conn, +static CURLcode tftp_do(struct Curl_easy *data, bool *done); +static CURLcode tftp_done(struct Curl_easy *data, CURLcode, bool premature); -static CURLcode tftp_setup_connection(struct connectdata *conn); -static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done); -static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done); -static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks); +static CURLcode tftp_setup_connection(struct Curl_easy *data, + struct connectdata *conn); +static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done); +static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done); +static int tftp_getsock(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t *socks); static CURLcode tftp_translate_code(tftp_error_t error); @@ -206,11 +209,11 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state) time(&state->start_time); /* Compute drop-dead time */ - timeout_ms = Curl_timeleft(state->conn->data, NULL, start); + timeout_ms = Curl_timeleft(state->data, NULL, start); if(timeout_ms < 0) { /* time-out, bail out, go home */ - failf(state->conn->data, "Connection time-out"); + failf(state->data, "Connection time-out"); return CURLE_OPERATION_TIMEDOUT; } @@ -261,7 +264,7 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state) if(state->retry_time<1) state->retry_time = 1; - infof(state->conn->data, + infof(state->data, "set timeouts for state %d; Total %ld, retry %d maxtry %d\n", (int)state->state, (long)(state->max_time-state->start_time), state->retry_time, state->retry_max); @@ -303,7 +306,7 @@ static unsigned short getrpacketblock(const struct tftp_packet *packet) return (unsigned short)((packet->data[2] << 8) | packet->data[3]); } -static size_t Curl_strnlen(const char *string, size_t maxlen) +static size_t tftp_strnlen(const char *string, size_t maxlen) { const char *end = memchr(string, '\0', maxlen); return end ? (size_t) (end - string) : maxlen; @@ -314,14 +317,14 @@ static const char *tftp_option_get(const char *buf, size_t len, { size_t loc; - loc = Curl_strnlen(buf, len); + loc = tftp_strnlen(buf, len); loc++; /* NULL term */ if(loc >= len) return NULL; *option = buf; - loc += Curl_strnlen(buf + loc, len-loc); + loc += tftp_strnlen(buf + loc, len-loc); loc++; /* NULL term */ if(loc > len) @@ -335,7 +338,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state, const char *ptr, int len) { const char *tmp = ptr; - struct Curl_easy *data = state->conn->data; + struct Curl_easy *data = state->data; /* if OACK doesn't contain blksize option, the default (512) must be used */ state->blksize = TFTP_BLKSIZE_DEFAULT; @@ -419,7 +422,7 @@ static CURLcode tftp_connect_for_tx(struct tftp_state_data *state, { CURLcode result; #ifndef CURL_DISABLE_VERBOSE_STRINGS - struct Curl_easy *data = state->conn->data; + struct Curl_easy *data = state->data; infof(data, "%s\n", "Connected for transmit"); #endif @@ -435,7 +438,7 @@ static CURLcode tftp_connect_for_rx(struct tftp_state_data *state, { CURLcode result; #ifndef CURL_DISABLE_VERBOSE_STRINGS - struct Curl_easy *data = state->conn->data; + struct Curl_easy *data = state->data; infof(data, "%s\n", "Connected for receive"); #endif @@ -453,7 +456,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state, ssize_t senddata; const char *mode = "octet"; char *filename; - struct Curl_easy *data = state->conn->data; + struct Curl_easy *data = state->data; CURLcode result = CURLE_OK; /* Set ascii mode if -B flag was used */ @@ -475,7 +478,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state, if(data->set.upload) { /* If we are uploading, send an WRQ */ setpacketevent(&state->spacket, TFTP_EVENT_WRQ); - state->conn->data->req.upload_fromhere = + state->data->req.upload_fromhere = (char *)state->spacket.data + 4; if(data->state.infilesize != -1) Curl_pgrsSetUploadSize(data, data->state.infilesize); @@ -487,13 +490,13 @@ static CURLcode tftp_send_first(struct tftp_state_data *state, /* As RFC3617 describes the separator slash is not actually part of the file name so we skip the always-present first letter of the path string. */ - result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0, + result = Curl_urldecode(data, &state->data->state.up.path[1], 0, &filename, NULL, REJECT_ZERO); if(result) return result; if(strlen(filename) > (state->blksize - strlen(mode) - 4)) { - failf(data, "TFTP file name too long\n"); + failf(data, "TFTP file name too long"); free(filename); return CURLE_TFTP_ILLEGAL; /* too long file name field */ } @@ -551,8 +554,8 @@ static CURLcode tftp_send_first(struct tftp_state_data *state, not have a size_t argument, like older unixes that want an 'int' */ senddata = sendto(state->sockfd, (void *)state->spacket.data, (SEND_TYPE_ARG3)sbytes, 0, - state->conn->ip_addr->ai_addr, - state->conn->ip_addr->ai_addrlen); + data->conn->ip_addr->ai_addr, + data->conn->ip_addr->ai_addrlen); if(senddata != (ssize_t)sbytes) { char buffer[STRERROR_LEN]; failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); @@ -582,7 +585,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state, break; default: - failf(state->conn->data, "tftp_send_first: internal error"); + failf(state->data, "tftp_send_first: internal error"); break; } @@ -605,7 +608,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state, { ssize_t sbytes; int rblock; - struct Curl_easy *data = state->conn->data; + struct Curl_easy *data = state->data; char buffer[STRERROR_LEN]; switch(event) { @@ -725,7 +728,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state, **********************************************************/ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event) { - struct Curl_easy *data = state->conn->data; + struct Curl_easy *data = state->data; ssize_t sbytes; CURLcode result = CURLE_OK; struct SingleRequest *k = &data->req; @@ -794,14 +797,13 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event) * data block. * */ state->sbytes = 0; - state->conn->data->req.upload_fromhere = (char *)state->spacket.data + 4; + state->data->req.upload_fromhere = (char *)state->spacket.data + 4; do { - result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes, - &cb); + result = Curl_fillreadbuffer(data, state->blksize - state->sbytes, &cb); if(result) return result; state->sbytes += (int)cb; - state->conn->data->req.upload_fromhere += cb; + state->data->req.upload_fromhere += cb; } while(state->sbytes < state->blksize && cb != 0); sbytes = sendto(state->sockfd, (void *) state->spacket.data, @@ -927,7 +929,7 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state, tftp_event_t event) { CURLcode result = CURLE_OK; - struct Curl_easy *data = state->conn->data; + struct Curl_easy *data = state->data; switch(state->state) { case TFTP_STATE_START: @@ -962,9 +964,11 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state, * The disconnect callback * **********************************************************/ -static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode tftp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { struct tftp_state_data *state = conn->proto.tftpc; + (void) data; (void) dead_connection; /* done, free dynamically allocated pkt buffers */ @@ -984,11 +988,12 @@ static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection) * The connect callback * **********************************************************/ -static CURLcode tftp_connect(struct connectdata *conn, bool *done) +static CURLcode tftp_connect(struct Curl_easy *data, bool *done) { struct tftp_state_data *state; int blksize; int need_blksize; + struct connectdata *conn = data->conn; blksize = TFTP_BLKSIZE_DEFAULT; @@ -997,8 +1002,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; /* alloc pkt buffers based on specified blksize */ - if(conn->data->set.tftp_blksize) { - blksize = (int)conn->data->set.tftp_blksize; + if(data->set.tftp_blksize) { + blksize = (int)data->set.tftp_blksize; if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN) return CURLE_TFTP_ILLEGAL; } @@ -1026,8 +1031,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) * little gain for UDP */ connclose(conn, "TFTP"); - state->conn = conn; - state->sockfd = state->conn->sock[FIRSTSOCKET]; + state->data = data; + state->sockfd = conn->sock[FIRSTSOCKET]; state->state = TFTP_STATE_START; state->error = TFTP_ERR_NONE; state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */ @@ -1056,14 +1061,14 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) conn->ip_addr->ai_addrlen); if(rc) { char buffer[STRERROR_LEN]; - failf(conn->data, "bind() failed; %s", + failf(data, "bind() failed; %s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_COULDNT_CONNECT; } conn->bits.bound = TRUE; } - Curl_pgrsStartNow(conn->data); + Curl_pgrsStartNow(data); *done = TRUE; @@ -1077,16 +1082,17 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) * The done callback * **********************************************************/ -static CURLcode tftp_done(struct connectdata *conn, CURLcode status, +static CURLcode tftp_done(struct Curl_easy *data, CURLcode status, bool premature) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct tftp_state_data *state = conn->proto.tftpc; (void)status; /* unused */ (void)premature; /* not used */ - if(Curl_pgrsDone(conn)) + if(Curl_pgrsDone(data)) return CURLE_ABORTED_BY_CALLBACK; /* If we have encountered an error */ @@ -1103,8 +1109,10 @@ static CURLcode tftp_done(struct connectdata *conn, CURLcode status, * The getsock callback * **********************************************************/ -static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks) +static int tftp_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { + (void)data; socks[0] = conn->sock[FIRSTSOCKET]; return GETSOCK_READSOCK(0); } @@ -1116,12 +1124,12 @@ static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks) * Called once select fires and data is ready on the socket * **********************************************************/ -static CURLcode tftp_receive_packet(struct connectdata *conn) +static CURLcode tftp_receive_packet(struct Curl_easy *data) { struct Curl_sockaddr_storage fromaddr; curl_socklen_t fromlen; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct tftp_state_data *state = conn->proto.tftpc; struct SingleRequest *k = &data->req; @@ -1154,7 +1162,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn) /* Don't pass to the client empty or retransmitted packets */ if(state->rbytes > 4 && (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) { - result = Curl_client_write(conn, CLIENTWRITE_BODY, + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)state->rpacket.data + 4, state->rbytes-4); if(result) { @@ -1171,7 +1179,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn) char *str = (char *)state->rpacket.data + 4; size_t strn = state->rbytes - 4; state->error = (tftp_error_t)error; - if(Curl_strnlen(str, strn) < strn) + if(tftp_strnlen(str, strn) < strn) infof(data, "TFTP error: %s\n", str); break; } @@ -1192,7 +1200,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn) } /* Update the progress meter */ - if(Curl_pgrsUpdate(conn)) { + if(Curl_pgrsUpdate(data)) { tftp_state_machine(state, TFTP_EVENT_ERROR); return CURLE_ABORTED_BY_CALLBACK; } @@ -1207,9 +1215,10 @@ static CURLcode tftp_receive_packet(struct connectdata *conn) * Check if timeouts have been reached * **********************************************************/ -static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event) +static long tftp_state_timeout(struct Curl_easy *data, tftp_event_t *event) { time_t current; + struct connectdata *conn = data->conn; struct tftp_state_data *state = conn->proto.tftpc; if(event) @@ -1217,7 +1226,7 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event) time(¤t); if(current > state->max_time) { - DEBUGF(infof(conn->data, "timeout: %ld > %ld\n", + DEBUGF(infof(data, "timeout: %ld > %ld\n", (long)current, (long)state->max_time)); state->error = TFTP_ERR_TIMEOUT; state->state = TFTP_STATE_FIN; @@ -1242,13 +1251,13 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event) * Handle single RX socket event and return * **********************************************************/ -static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) +static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done) { - tftp_event_t event; - CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + tftp_event_t event; + CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct tftp_state_data *state = conn->proto.tftpc; - long timeout_ms = tftp_state_timeout(conn, &event); + long timeout_ms = tftp_state_timeout(data, &event); *done = FALSE; @@ -1277,7 +1286,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) state->event = TFTP_EVENT_ERROR; } else if(rc != 0) { - result = tftp_receive_packet(conn); + result = tftp_receive_packet(data); if(result) return result; result = tftp_state_machine(state, state->event); @@ -1301,22 +1310,22 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) * Called from multi.c while DOing * **********************************************************/ -static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done) +static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done) { CURLcode result; - result = tftp_multi_statemach(conn, dophase_done); + result = tftp_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } else if(!result) { /* The multi code doesn't have this logic for the DOING state so we provide it for TFTP since it may do the entire transfer in this state. */ - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; else - result = Curl_speedcheck(conn->data, Curl_now()); + result = Curl_speedcheck(data, Curl_now()); } return result; } @@ -1328,9 +1337,10 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done) * Entry point for transfer from tftp_do, sarts state mach * **********************************************************/ -static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done) +static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done) { - CURLcode result = CURLE_OK; + CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct tftp_state_data *state = conn->proto.tftpc; *dophase_done = FALSE; @@ -1340,10 +1350,10 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done) if((state->state == TFTP_STATE_FIN) || result) return result; - tftp_multi_statemach(conn, dophase_done); + tftp_multi_statemach(data, dophase_done); if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); return result; } @@ -1359,15 +1369,16 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done) * **********************************************************/ -static CURLcode tftp_do(struct connectdata *conn, bool *done) +static CURLcode tftp_do(struct Curl_easy *data, bool *done) { struct tftp_state_data *state; CURLcode result; + struct connectdata *conn = data->conn; *done = FALSE; if(!conn->proto.tftpc) { - result = tftp_connect(conn, done); + result = tftp_connect(data, done); if(result) return result; } @@ -1376,7 +1387,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done) if(!state) return CURLE_TFTP_ILLEGAL; - result = tftp_perform(conn, done); + result = tftp_perform(data, done); /* If tftp_perform() returned an error, use that for return code. If it was OK, see if tftp_translate_code() has an error. */ @@ -1387,9 +1398,9 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done) return result; } -static CURLcode tftp_setup_connection(struct connectdata *conn) +static CURLcode tftp_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { - struct Curl_easy *data = conn->data; char *type; conn->transport = TRNSPRT_UDP; diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c index bfd0218fef..2f29b29d8e 100644 --- a/libs/libcurl/src/transfer.c +++ b/libs/libcurl/src/transfer.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -93,12 +93,11 @@ * * Returns a pointer to the first matching header or NULL if none matched. */ -char *Curl_checkheaders(const struct connectdata *conn, +char *Curl_checkheaders(const struct Curl_easy *data, const char *thisheader) { struct curl_slist *head; size_t thislen = strlen(thisheader); - struct Curl_easy *data = conn->data; for(head = data->set.headers; head; head = head->next) { if(strncasecompare(head->data, thisheader, thislen) && @@ -125,8 +124,8 @@ CURLcode Curl_get_upload_buffer(struct Curl_easy *data) * This function will be called to loop through the trailers buffer * until no more data is available for sending. */ -static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems, - void *raw) +static size_t trailers_read(char *buffer, size_t size, size_t nitems, + void *raw) { struct Curl_easy *data = (struct Curl_easy *)raw; struct dynbuf *trailers_buf = &data->state.trailers_buf; @@ -142,7 +141,7 @@ static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems, return to_copy; } -static size_t Curl_trailers_left(void *raw) +static size_t trailers_left(void *raw) { struct Curl_easy *data = (struct Curl_easy *)raw; struct dynbuf *trailers_buf = &data->state.trailers_buf; @@ -154,10 +153,9 @@ static size_t Curl_trailers_left(void *raw) * This function will call the read callback to fill our buffer with data * to upload. */ -CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, +CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, size_t *nreadp) { - struct Curl_easy *data = conn->data; size_t buffersize = bytes; size_t nread; @@ -166,6 +164,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, #ifdef CURL_DOES_CONVERSIONS bool sending_http_headers = FALSE; + struct connectdata *conn = data->conn; if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { const struct HTTP *http = data->req.p.http; @@ -231,7 +230,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, simply return to the previous point in the state machine as if nothing happened. */ - readfunc = Curl_trailers_read; + readfunc = trailers_read; extra_data = (void *)data; } else @@ -254,7 +253,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, if(nread == CURL_READFUNC_PAUSE) { struct SingleRequest *k = &data->req; - if(conn->handler->flags & PROTOPT_NONETWORK) { + if(data->conn->handler->flags & PROTOPT_NONETWORK) { /* protocols that work without network cannot be paused. This is actually only FILE:// just now, and it can't pause since the transfer isn't done using the "normal" procedure. */ @@ -367,7 +366,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, #ifndef CURL_DISABLE_HTTP if(data->state.trailers_state == TRAILERS_SENDING && - !Curl_trailers_left(data)) { + !trailers_left(data)) { Curl_dyn_free(&data->state.trailers_buf); data->state.trailers_state = TRAILERS_DONE; data->set.trailer_data = NULL; @@ -410,9 +409,9 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, * POST/PUT with multi-pass authentication when a sending was denied and a * resend is necessary. */ -CURLcode Curl_readrewind(struct connectdata *conn) +CURLcode Curl_readrewind(struct Curl_easy *data) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; curl_mimepart *mimepart = &data->set.mimepost; conn->bits.rewindaftersend = FALSE; /* we rewind now */ @@ -436,9 +435,10 @@ CURLcode Curl_readrewind(struct connectdata *conn) ; /* do nothing */ else if(data->state.httpreq == HTTPREQ_POST_MIME || data->state.httpreq == HTTPREQ_POST_FORM) { - if(Curl_mime_rewind(mimepart)) { + CURLcode result = Curl_mime_rewind(mimepart); + if(result) { failf(data, "Cannot rewind mime/post data"); - return CURLE_SEND_FAIL_REWIND; + return result; } } else { @@ -599,7 +599,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, if(bytestoread) { /* receive data from the network! */ - result = Curl_read(conn, conn->sockfd, buf, bytestoread, &nread); + result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread); /* read would've blocked */ if(CURLE_AGAIN == result) @@ -708,64 +708,10 @@ static CURLcode readwrite_data(struct Curl_easy *data, write a piece of the body */ if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { /* HTTP-only checks */ - - if(data->req.newurl) { - if(conn->bits.close) { - /* Abort after the headers if "follow Location" is set - and we're set to close anyway. */ - k->keepon &= ~KEEP_RECV; - *done = TRUE; - return CURLE_OK; - } - /* We have a new url to load, but since we want to be able - to re-use this connection properly, we read the full - response in "ignore more" */ - k->ignorebody = TRUE; - infof(data, "Ignoring the response-body\n"); - } - if(data->state.resume_from && !k->content_range && - (data->state.httpreq == HTTPREQ_GET) && - !k->ignorebody) { - - if(k->size == data->state.resume_from) { - /* The resume point is at the end of file, consider this fine - even if it doesn't allow resume from here. */ - infof(data, "The entire document is already downloaded"); - connclose(conn, "already downloaded"); - /* Abort download */ - k->keepon &= ~KEEP_RECV; - *done = TRUE; - return CURLE_OK; - } - - /* we wanted to resume a download, although the server doesn't - * seem to support this and we did this with a GET (if it - * wasn't a GET we did a POST or PUT resume) */ - failf(data, "HTTP server doesn't seem to support " - "byte ranges. Cannot resume."); - return CURLE_RANGE_ERROR; - } - - if(data->set.timecondition && !data->state.range) { - /* A time condition has been set AND no ranges have been - requested. This seems to be what chapter 13.3.4 of - RFC 2616 defines to be the correct action for a - HTTP/1.1 client */ - - if(!Curl_meets_timecondition(data, k->timeofdoc)) { - *done = TRUE; - /* We're simulating a http 304 from server so we return - what should have been returned from the server */ - data->info.httpcode = 304; - infof(data, "Simulate a HTTP 304 response!\n"); - /* we abort the transfer before it is completed == we ruin the - re-use ability. Close the connection */ - connclose(conn, "Simulated 304 handling"); - return CURLE_OK; - } - } /* we have a time condition */ - - } /* this is HTTP or RTSP */ + result = Curl_http_firstwrite(data, conn, done); + if(result || *done) + return result; + } } /* this is the first time we write a body part */ #endif /* CURL_DISABLE_HTTP */ @@ -796,7 +742,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, */ CURLcode extra; CHUNKcode res = - Curl_httpchunk_read(conn, k->str, nread, &nread, &extra); + Curl_httpchunk_read(data, k->str, nread, &nread, &extra); if(CHUNKE_OK < res) { if(CHUNKE_PASSTHRU_ERROR == res) { @@ -807,18 +753,15 @@ static CURLcode readwrite_data(struct Curl_easy *data, return CURLE_RECV_ERROR; } if(CHUNKE_STOP == res) { - size_t dataleft; /* we're done reading chunks! */ k->keepon &= ~KEEP_RECV; /* read no more */ - /* There are now possibly N number of bytes at the end of the - str buffer that weren't written to the client. - Push it back to be read on the next pass. */ - - dataleft = conn->chunk.dataleft; - if(dataleft != 0) { - infof(conn->data, "Leftovers after chunking: %zu bytes\n", - dataleft); + /* N number of bytes at the end of the str buffer that weren't + written to the client. */ + if(conn->chunk.datasize) { + infof(data, "Leftovers after chunking: % " + CURL_FORMAT_CURL_OFF_T "u bytes\n", + conn->chunk.datasize); } } /* If it returned OK, we just keep going */ @@ -868,11 +811,11 @@ static CURLcode readwrite_data(struct Curl_easy *data, /* Don't let excess data pollute body writes */ if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload) - result = Curl_client_write(conn, CLIENTWRITE_BODY, + result = Curl_client_write(data, CLIENTWRITE_BODY, Curl_dyn_ptr(&data->state.headerb), headlen); else - result = Curl_client_write(conn, CLIENTWRITE_BODY, + result = Curl_client_write(data, CLIENTWRITE_BODY, Curl_dyn_ptr(&data->state.headerb), (size_t)k->maxdownload); @@ -885,19 +828,19 @@ static CURLcode readwrite_data(struct Curl_easy *data, in http_chunks.c. Make sure that ALL_CONTENT_ENCODINGS contains all the encodings handled here. */ - if(conn->data->set.http_ce_skip || !k->writer_stack) { + if(data->set.http_ce_skip || !k->writer_stack) { if(!k->ignorebody) { #ifndef CURL_DISABLE_POP3 if(conn->handler->protocol & PROTO_FAMILY_POP3) - result = Curl_pop3_write(conn, k->str, nread); + result = Curl_pop3_write(data, k->str, nread); else #endif /* CURL_DISABLE_POP3 */ - result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str, + result = Curl_client_write(data, CLIENTWRITE_BODY, k->str, nread); } } else if(!k->ignorebody) - result = Curl_unencode_write(conn, k->writer_stack, k->str, nread); + result = Curl_unencode_write(data, k->writer_stack, k->str, nread); } k->badheader = HEADER_NORMAL; /* taken care of now */ @@ -958,17 +901,18 @@ static CURLcode readwrite_data(struct Curl_easy *data, return CURLE_OK; } -CURLcode Curl_done_sending(struct connectdata *conn, +CURLcode Curl_done_sending(struct Curl_easy *data, struct SingleRequest *k) { + struct connectdata *conn = data->conn; k->keepon &= ~KEEP_SEND; /* we're done writing */ /* These functions should be moved into the handler struct! */ - Curl_http2_done_sending(conn); - Curl_quic_done_sending(conn); + Curl_http2_done_sending(data, conn); + Curl_quic_done_sending(data); if(conn->bits.rewindaftersend) { - CURLcode result = Curl_readrewind(conn); + CURLcode result = Curl_readrewind(data); if(result) return result; } @@ -1016,6 +960,8 @@ static CURLcode readwrite_upload(struct Curl_easy *data, *didwhat |= KEEP_SEND; do { + curl_off_t nbody; + /* only read more data if there's no upload data already present in the upload buffer */ if(0 == k->upload_present) { @@ -1054,7 +1000,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, sending_http_headers = FALSE; } - result = Curl_fillreadbuffer(conn, data->set.upload_buffer_size, + result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount); if(result) return result; @@ -1069,7 +1015,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, break; } if(nread <= 0) { - result = Curl_done_sending(conn, k); + result = Curl_done_sending(data, k); if(result) return result; break; @@ -1131,7 +1077,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, #ifndef CURL_DISABLE_SMTP if(conn->handler->protocol & PROTO_FAMILY_SMTP) { - result = Curl_smtp_escape_eob(conn, nread); + result = Curl_smtp_escape_eob(data, nread); if(result) return result; } @@ -1143,7 +1089,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, } /* write to socket (send away data) */ - result = Curl_write(conn, + result = Curl_write(data, conn->writesockfd, /* socket to send to */ k->upload_fromhere, /* buffer pointer */ k->upload_present, /* buffer size */ @@ -1153,12 +1099,26 @@ static CURLcode readwrite_upload(struct Curl_easy *data, win_update_buffer_size(conn->writesockfd); - /* show the data before we change the pointer upload_fromhere */ - Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere, - (size_t)bytes_written); + if(k->pendingheader) { + /* parts of what was sent was header */ + curl_off_t n = CURLMIN(k->pendingheader, bytes_written); + /* show the data before we change the pointer upload_fromhere */ + Curl_debug(data, CURLINFO_HEADER_OUT, k->upload_fromhere, (size_t)n); + k->pendingheader -= n; + nbody = bytes_written - n; /* size of the written body part */ + } + else + nbody = bytes_written; + + if(nbody) { + /* show the data before we change the pointer upload_fromhere */ + Curl_debug(data, CURLINFO_DATA_OUT, + &k->upload_fromhere[bytes_written - nbody], + (size_t)nbody); - k->writebytecount += bytes_written; - Curl_pgrsSetUploadCounter(data, k->writebytecount); + k->writebytecount += nbody; + Curl_pgrsSetUploadCounter(data, k->writebytecount); + } if((!k->upload_chunky || k->forbidchunk) && (k->writebytecount == data->state.infilesize)) { @@ -1186,7 +1146,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, k->upload_present = 0; /* no more bytes left */ if(k->upload_done) { - result = Curl_done_sending(conn, k); + result = Curl_done_sending(data, k); if(result) return result; } @@ -1233,7 +1193,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, else fd_write = CURL_SOCKET_BAD; - if(conn->data->state.drain) { + if(data->state.drain) { select_res |= CURL_CSELECT_IN; DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n")); } @@ -1247,6 +1207,10 @@ CURLcode Curl_readwrite(struct connectdata *conn, return CURLE_SEND_ERROR; } +#ifdef USE_HYPER + if(conn->datastream) + return conn->datastream(data, conn, &didwhat, done, select_res); +#endif /* We go ahead and do a read if we have a readable socket or if the stream was rewound (in which case we have data in a buffer) */ @@ -1266,10 +1230,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, } k->now = Curl_now(); - if(didwhat) { - ; - } - else { + if(!didwhat) { /* no read no write, this is a timeout? */ if(k->exp100 == EXP100_AWAITING_CONTINUE) { /* This should allow some time for the header to arrive, but only a @@ -1296,7 +1257,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, } } - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; else result = Curl_speedcheck(data, k->now); @@ -1355,7 +1316,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, failf(data, "transfer closed with outstanding read data remaining"); return CURLE_PARTIAL_FILE; } - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) return CURLE_ABORTED_BY_CALLBACK; } @@ -1373,15 +1334,15 @@ CURLcode Curl_readwrite(struct connectdata *conn, * keeps track of. This function will only be called for connections that are * in the proper state to have this information available. */ -int Curl_single_getsock(const struct connectdata *conn, +int Curl_single_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *sock) { - const struct Curl_easy *data = conn->data; int bitmap = GETSOCK_BLANK; unsigned sockindex = 0; if(conn->handler->perform_getsock) - return conn->handler->perform_getsock(conn, sock); + return conn->handler->perform_getsock(data, conn, sock); /* don't include HOLD and PAUSE connections */ if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) { @@ -1532,6 +1493,20 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) Curl_hsts_loadcb(data, data->hsts); } + /* + * Set user-agent. Used for HTTP, but since we can attempt to tunnel + * basically anything through a http proxy we can't limit this based on + * protocol. + */ + if(data->set.str[STRING_USERAGENT]) { + Curl_safefree(data->state.aptr.uagent); + data->state.aptr.uagent = + aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]); + if(!data->state.aptr.uagent) + return CURLE_OUT_OF_MEMORY; + } + + data->req.headerbytecount = 0; return result; } @@ -1574,6 +1549,8 @@ CURLcode Curl_follow(struct Curl_easy *data, bool reachedmax = FALSE; CURLUcode uc; + DEBUGASSERT(type != FOLLOW_NONE); + if(type == FOLLOW_REDIR) { if((data->set.maxredirs != -1) && (data->set.followlocation >= data->set.maxredirs)) { @@ -1605,8 +1582,11 @@ CURLcode Curl_follow(struct Curl_easy *data, } } - if(Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN)) - /* This is an absolute URL, don't allow the custom port number */ + if((type != FOLLOW_RETRY) && + (data->req.httpcode != 401) && (data->req.httpcode != 407) && + Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN)) + /* If this is not redirect due to a 401 or 407 response and an absolute + URL: don't allow a custom port number */ disallowport = TRUE; DEBUGASSERT(data->state.uh); @@ -1687,7 +1667,7 @@ CURLcode Curl_follow(struct Curl_easy *data, * request with an error page. To be sure that libcurl gets the page that * most user agents would get, libcurl has to force GET. * - * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and + * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and * can be overridden with CURLOPT_POSTREDIR. */ if((data->state.httpreq == HTTPREQ_POST @@ -1712,7 +1692,7 @@ CURLcode Curl_follow(struct Curl_easy *data, * request with an error page. To be sure that libcurl gets the page that * most user agents would get, libcurl has to force GET. * - * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and + * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and * can be overridden with CURLOPT_POSTREDIR. */ if((data->state.httpreq == HTTPREQ_POST @@ -1766,10 +1746,9 @@ CURLcode Curl_follow(struct Curl_easy *data, /* Returns CURLE_OK *and* sets '*url' if a request retry is wanted. NOTE: that the *url is malloc()ed. */ -CURLcode Curl_retry_request(struct connectdata *conn, - char **url) +CURLcode Curl_retry_request(struct Curl_easy *data, char **url) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; bool retry = FALSE; *url = NULL; @@ -1799,7 +1778,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, to issue again, but the nghttp2 API can deliver the message to other streams as well, which is why this adds the check the data counters too. */ - infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n"); + infof(data, "REFUSED_STREAM, retrying a fresh connect\n"); data->state.refused_stream = FALSE; /* clear again */ retry = TRUE; } @@ -1811,9 +1790,9 @@ CURLcode Curl_retry_request(struct connectdata *conn, data->state.retrycount = 0; return CURLE_SEND_ERROR; } - infof(conn->data, "Connection died, retrying a fresh connect\ + infof(data, "Connection died, retrying a fresh connect\ (retry count: %d)\n", data->state.retrycount); - *url = strdup(conn->data->change.url); + *url = strdup(data->change.url); if(!*url) return CURLE_OUT_OF_MEMORY; @@ -1827,7 +1806,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, if(conn->handler->protocol&PROTO_FAMILY_HTTP) { if(data->req.writebytecount) { - CURLcode result = Curl_readrewind(conn); + CURLcode result = Curl_readrewind(data); if(result) { Curl_safefree(*url); return result; diff --git a/libs/libcurl/src/transfer.h b/libs/libcurl/src/transfer.h index 178bb58fb0..0fa3d55e82 100644 --- a/libs/libcurl/src/transfer.h +++ b/libs/libcurl/src/transfer.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,7 +23,7 @@ ***************************************************************************/ #define Curl_headersep(x) ((((x)==':') || ((x)==';'))) -char *Curl_checkheaders(const struct connectdata *conn, +char *Curl_checkheaders(const struct Curl_easy *data, const char *thisheader); void Curl_init_CONNECT(struct Curl_easy *data); @@ -36,9 +36,8 @@ typedef enum { allow initing to this */ FOLLOW_FAKE, /* only records stuff, not actually following */ FOLLOW_RETRY, /* set if this is a request retry as opposed to a real - redirect following */ - FOLLOW_REDIR, /* a full true redirect */ - FOLLOW_LAST /* never used */ + redirect following */ + FOLLOW_REDIR /* a full true redirect */ } followtype; CURLcode Curl_follow(struct Curl_easy *data, char *newurl, @@ -46,16 +45,16 @@ CURLcode Curl_follow(struct Curl_easy *data, char *newurl, CURLcode Curl_readwrite(struct connectdata *conn, struct Curl_easy *data, bool *done, bool *comeback); -int Curl_single_getsock(const struct connectdata *conn, - curl_socket_t *socks); -CURLcode Curl_readrewind(struct connectdata *conn); -CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, +int Curl_single_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); +CURLcode Curl_readrewind(struct Curl_easy *data); +CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, size_t *nreadp); -CURLcode Curl_retry_request(struct connectdata *conn, char **url); +CURLcode Curl_retry_request(struct Curl_easy *data, char **url); bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc); CURLcode Curl_get_upload_buffer(struct Curl_easy *data); -CURLcode Curl_done_sending(struct connectdata *conn, +CURLcode Curl_done_sending(struct Curl_easy *data, struct SingleRequest *k); /* This sets up a forthcoming transfer */ diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c index 2b0ba87ba8..c02d2c2019 100644 --- a/libs/libcurl/src/url.c +++ b/libs/libcurl/src/url.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -251,6 +251,9 @@ static const struct Curl_handler * const protocols[] = { #ifndef CURL_DISABLE_GOPHER &Curl_handler_gopher, +#ifdef USE_SSL + &Curl_handler_gophers, +#endif #endif #ifdef USE_LIBRTMP @@ -361,6 +364,9 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_expire_clear(data); /* shut off timers */ + /* Detach connection if any is left. This should not be normal, but can be + the case for example with CONNECT_ONLY + recv/send (test 556) */ + Curl_detach_connnection(data); m = data->multi; if(m) /* This handle is still part of a multi handle, take care of this first @@ -421,7 +427,7 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->info.wouldredirect); /* this destroys the channel and we cannot use it anymore after this */ - Curl_resolver_cleanup(data->state.resolver); + Curl_resolver_cleanup(data->state.async.resolver); Curl_http2_cleanup_dependencies(data); Curl_convert_close(data); @@ -445,9 +451,12 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->state.aptr.rtsp_transport); #ifndef CURL_DISABLE_DOH - Curl_dyn_free(&data->req.doh.probe[0].serverdoh); - Curl_dyn_free(&data->req.doh.probe[1].serverdoh); - curl_slist_free_all(data->req.doh.headers); + if(data->req.doh) { + Curl_dyn_free(&data->req.doh->probe[0].serverdoh); + Curl_dyn_free(&data->req.doh->probe[1].serverdoh); + curl_slist_free_all(data->req.doh->headers); + Curl_safefree(data->req.doh); + } #endif /* destruct wildcard structures if it is needed */ @@ -634,7 +643,7 @@ CURLcode Curl_open(struct Curl_easy **curl) data->magic = CURLEASY_MAGIC_NUMBER; - result = Curl_resolver_init(data, &data->state.resolver); + result = Curl_resolver_init(data, &data->state.async.resolver); if(result) { DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); free(data); @@ -655,7 +664,7 @@ CURLcode Curl_open(struct Curl_easy **curl) } if(result) { - Curl_resolver_cleanup(data->state.resolver); + Curl_resolver_cleanup(data->state.async.resolver); Curl_dyn_free(&data->state.headerb); Curl_freeset(data); free(data); @@ -706,29 +715,29 @@ static void conn_reset_all_postponed_data(struct connectdata *conn) #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ -static void conn_shutdown(struct connectdata *conn) +static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn) { DEBUGASSERT(conn); - infof(conn->data, "Closing connection %ld\n", conn->connection_id); - DEBUGASSERT(conn->data); + DEBUGASSERT(data); + infof(data, "Closing connection %ld\n", conn->connection_id); /* possible left-overs from the async name resolvers */ - Curl_resolver_cancel(conn); + Curl_resolver_cancel(data); /* close the SSL stuff before we close any sockets since they will/may write to the sockets */ - Curl_ssl_close(conn, FIRSTSOCKET); - Curl_ssl_close(conn, SECONDARYSOCKET); + Curl_ssl_close(data, conn, FIRSTSOCKET); + Curl_ssl_close(data, conn, SECONDARYSOCKET); /* close possibly still open sockets */ if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) - Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]); if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET]) - Curl_closesocket(conn, conn->sock[FIRSTSOCKET]); + Curl_closesocket(data, conn, conn->sock[FIRSTSOCKET]); if(CURL_SOCKET_BAD != conn->tempsock[0]) - Curl_closesocket(conn, conn->tempsock[0]); + Curl_closesocket(data, conn, conn->tempsock[0]); if(CURL_SOCKET_BAD != conn->tempsock[1]) - Curl_closesocket(conn, conn->tempsock[1]); + Curl_closesocket(data, conn, conn->tempsock[1]); } static void conn_free(struct connectdata *conn) @@ -823,19 +832,23 @@ CURLcode Curl_disconnect(struct Curl_easy *data, /* Cleanup NEGOTIATE connection-related data */ Curl_http_auth_cleanup_negotiate(conn); - /* the protocol specific disconnect handler and conn_shutdown need a transfer - for the connection! */ - conn->data = data; - if(conn->bits.connect_only) /* treat the connection as dead in CONNECT_ONLY situations */ dead_connection = TRUE; + /* temporarily attach the connection to this transfer handle for the + disonnect and shutdown */ + Curl_attach_connnection(data, conn); + if(conn->handler->disconnect) /* This is set if protocol-specific cleanups should be made */ - conn->handler->disconnect(conn, dead_connection); + conn->handler->disconnect(data, conn, dead_connection); + + conn_shutdown(data, conn); + + /* detach it again */ + Curl_detach_connnection(data); - conn_shutdown(conn); conn_free(conn); return CURLE_OK; } @@ -933,15 +946,13 @@ static bool conn_maxage(struct Curl_easy *data, struct connectdata *conn, struct curltime now) { - if(!conn->data) { - timediff_t idletime = Curl_timediff(now, conn->lastused); - idletime /= 1000; /* integer seconds is fine */ + timediff_t 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\n", - idletime); - return TRUE; - } + if(idletime > data->set.maxage_conn) { + infof(data, "Too old connection (%ld seconds), disconnect it\n", + idletime); + return TRUE; } return FALSE; } @@ -958,23 +969,29 @@ static bool conn_maxage(struct Curl_easy *data, static bool extract_if_dead(struct connectdata *conn, struct Curl_easy *data) { - if(!CONN_INUSE(conn) && !conn->data) { + if(!CONN_INUSE(conn)) { /* The check for a dead socket makes sense only if the connection isn't in use */ bool dead; struct curltime now = Curl_now(); if(conn_maxage(data, conn, now)) { + /* avoid check if already too old */ dead = TRUE; } else if(conn->handler->connection_check) { /* The protocol has a special method for checking the state of the connection. Use it to check if the connection is dead. */ unsigned int state; - struct Curl_easy *olddata = conn->data; - conn->data = data; /* use this transfer for now */ - state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD); - conn->data = olddata; + + /* briefly attach the connection to this transfer for the purpose of + checking it */ + Curl_attach_connnection(data, conn); + conn->data = data; /* find the way back if necessary */ + state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD); dead = (state & CONNRESULT_DEAD); + /* detach the connection again */ + Curl_detach_connnection(data); + conn->data = NULL; /* clear it again */ } else { /* Use the general method for determining the death of a connection */ @@ -999,10 +1016,11 @@ struct prunedead { * Wrapper to use extract_if_dead() function in Curl_conncache_foreach() * */ -static int call_extract_if_dead(struct connectdata *conn, void *param) +static int call_extract_if_dead(struct Curl_easy *data, + struct connectdata *conn, void *param) { struct prunedead *p = (struct prunedead *)param; - if(extract_if_dead(conn, p->data)) { + if(extract_if_dead(conn, data)) { /* stop the iteration here, pass back the connection that was extracted */ p->extracted = conn; return 1; @@ -1012,14 +1030,16 @@ static int call_extract_if_dead(struct connectdata *conn, void *param) /* * This function scans the connection cache for half-open/dead connections, - * closes and removes them. - * The cleanup is done at most once per second. + * closes and removes them. The cleanup is done at most once per second. + * + * When called, this transfer has no connection attached. */ static void prune_dead_connections(struct Curl_easy *data) { struct curltime now = Curl_now(); timediff_t elapsed; + DEBUGASSERT(!data->conn); /* no connection */ CONNCACHE_LOCK(data); elapsed = Curl_timediff(now, data->state.conn_cache->last_cleanup); @@ -1089,7 +1109,7 @@ ConnectionExists(struct Curl_easy *data, /* Look up the bundle with all the connections to this particular host. Locks the connection cache, beware of early returns! */ - bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache, + bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache, &hostbundle); if(bundle) { /* Max pipe length is zero (unlimited) for multiplexed connections */ @@ -1148,10 +1168,7 @@ ConnectionExists(struct Curl_easy *data, if(bundle->multiuse == BUNDLE_MULTIPLEX) multiplexed = CONN_INUSE(check); - if(canmultiplex) { - ; - } - else { + if(!canmultiplex) { if(multiplexed) { /* can only happen within multi handles, and means that another easy handle is using this connection */ @@ -1159,9 +1176,9 @@ ConnectionExists(struct Curl_easy *data, } if(Curl_resolver_asynch()) { - /* ip_addr_str[0] is NUL only if the resolving of the name hasn't + /* primary_ip[0] is NUL only if the resolving of the name hasn't completed yet and until then we don't re-use this connection */ - if(!check->ip_addr_str[0]) { + if(!check->primary_ip[0]) { infof(data, "Connection #%ld is still name resolving, can't reuse\n", check->connection_id); @@ -1463,17 +1480,18 @@ ConnectionExists(struct Curl_easy *data, * verboseconnect() displays verbose information after a connect */ #ifndef CURL_DISABLE_VERBOSE_STRINGS -void Curl_verboseconnect(struct connectdata *conn) +void Curl_verboseconnect(struct Curl_easy *data, + struct connectdata *conn) { - if(conn->data->set.verbose) - infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n", + if(data->set.verbose) + infof(data, "Connected to %s (%s) port %ld (#%ld)\n", #ifndef CURL_DISABLE_PROXY conn->bits.socksproxy ? conn->socks_proxy.host.dispname : conn->bits.httpproxy ? conn->http_proxy.host.dispname : #endif conn->bits.conn_to_host ? conn->conn_to_host.dispname : conn->host.dispname, - conn->ip_addr_str, conn->port, conn->connection_id); + conn->primary_ip, conn->port, conn->connection_id); } #endif @@ -1512,16 +1530,14 @@ static void strip_trailing_dot(struct hostname *host) /* * Perform any necessary IDN conversion of hostname */ -CURLcode Curl_idnconvert_hostname(struct connectdata *conn, +CURLcode Curl_idnconvert_hostname(struct Curl_easy *data, struct hostname *host) { - struct Curl_easy *data = conn->data; - #ifndef USE_LIBIDN2 (void)data; - (void)conn; + (void)data; #elif defined(CURL_DISABLE_VERBOSE_STRINGS) - (void)conn; + (void)data; #endif /* set the name we use to display the host name */ @@ -1541,13 +1557,18 @@ CURLcode Curl_idnconvert_hostname(struct connectdata *conn, int flags = IDN2_NFC_INPUT; #endif int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags); + if(rc != IDN2_OK) + /* fallback to TR46 Transitional mode for better IDNA2003 + compatibility */ + rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, + IDN2_TRANSITIONAL); if(rc == IDN2_OK) { host->encalloc = (char *)ace_hostname; /* change the name pointer to point to the encoded hostname */ host->name = host->encalloc; } else { - failf(data, "Failed to convert %s to ACE; %s\n", host->name, + failf(data, "Failed to convert %s to ACE; %s", host->name, idn2_strerror(rc)); return CURLE_URL_MALFORMAT; } @@ -1562,7 +1583,7 @@ CURLcode Curl_idnconvert_hostname(struct connectdata *conn, } else { char buffer[STRERROR_LEN]; - failf(data, "Failed to convert %s to ACE; %s\n", host->name, + failf(data, "Failed to convert %s to ACE; %s", host->name, Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); return CURLE_URL_MALFORMAT; } @@ -1653,9 +1674,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) /* Store current time to give a baseline to keepalive connection times. */ conn->keepalive = Curl_now(); - /* Store off the configured connection upkeep time. */ - conn->upkeep_interval_ms = data->set.upkeep_interval_ms; - conn->data = data; /* Setup the association between this connection and the Curl_easy */ @@ -1811,12 +1829,14 @@ CURLcode Curl_uc_to_curlcode(CURLUcode uc) * the scope_id based on that! */ -static void zonefrom_url(CURLU *uh, struct connectdata *conn) +static void zonefrom_url(CURLU *uh, struct Curl_easy *data, + struct connectdata *conn) { char *zoneid; - CURLUcode uc; - - uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0); + CURLUcode uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0); +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)data; +#endif if(!uc && zoneid) { char *endp; @@ -1839,7 +1859,7 @@ static void zonefrom_url(CURLU *uh, struct connectdata *conn) scopeidx = if_nametoindex(zoneid); #endif if(!scopeidx) - infof(conn->data, "Invalid zoneid: %s; %s\n", zoneid, + infof(data, "Invalid zoneid: %s; %s\n", zoneid, strerror(errno)); else conn->scope_id = scopeidx; @@ -2003,7 +2023,9 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, } else { unsigned long port = strtoul(data->state.up.port, NULL, 10); - conn->port = conn->remote_port = curlx_ultous(port); + conn->port = conn->remote_port = + (data->set.use_port && data->state.allow_port) ? + (int)data->set.use_port : curlx_ultous(port); } (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0); @@ -2019,7 +2041,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, hlen = strlen(hostname); hostname[hlen - 1] = 0; - zonefrom_url(uh, conn); + zonefrom_url(uh, data, conn); } /* make sure the connect struct gets its own copy of the host name */ @@ -2077,7 +2099,8 @@ static CURLcode setup_range(struct Curl_easy *data) * * This MUST get called after proxy magic has been figured out. */ -static CURLcode setup_connection_internals(struct connectdata *conn) +static CURLcode setup_connection_internals(struct Curl_easy *data, + struct connectdata *conn) { const struct Curl_handler *p; CURLcode result; @@ -2086,7 +2109,7 @@ static CURLcode setup_connection_internals(struct connectdata *conn) p = conn->handler; if(p->setup_connection) { - result = (*p->setup_connection)(conn); + result = (*p->setup_connection)(data, conn); if(result) return result; @@ -2113,8 +2136,10 @@ void Curl_free_request_state(struct Curl_easy *data) Curl_safefree(data->req.newurl); #ifndef CURL_DISABLE_DOH - Curl_close(&data->req.doh.probe[0].easy); - Curl_close(&data->req.doh.probe[1].easy); + if(data->req.doh) { + Curl_close(&data->req.doh->probe[0].easy); + Curl_close(&data->req.doh->probe[1].easy); + } #endif } @@ -2171,7 +2196,7 @@ static bool check_noproxy(const char *name, const char *no_proxy) /* Look for the end of the token. */ ; - /* To match previous behaviour, where it was necessary to specify + /* To match previous behavior, where it was necessary to specify * ".local.com" to prevent matching "notlocal.com", we will leave * the '.' off. */ @@ -2204,7 +2229,8 @@ static bool check_noproxy(const char *name, const char *no_proxy) * name and is not limited to HTTP proxies only. * The returned pointer must be freed by the caller (unless NULL) ****************************************************************/ -static char *detect_proxy(struct connectdata *conn) +static char *detect_proxy(struct Curl_easy *data, + struct connectdata *conn) { char *proxy = NULL; @@ -2229,6 +2255,9 @@ static char *detect_proxy(struct connectdata *conn) const char *protop = conn->handler->scheme; char *envp = proxy_env; char *prox; +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)data; +#endif /* Now, build _proxy and check for such a one to use */ while(*protop) @@ -2271,7 +2300,7 @@ static char *detect_proxy(struct connectdata *conn) } } if(proxy) - infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy); + infof(data, "Uses proxy env variable %s == '%s'\n", envp, proxy); return proxy; } @@ -2287,7 +2316,7 @@ static CURLcode parse_proxy(struct Curl_easy *data, curl_proxytype proxytype) { char *portptr = NULL; - long port = -1; + int port = -1; char *proxyuser = NULL; char *proxypasswd = NULL; char *host; @@ -2376,14 +2405,14 @@ static CURLcode parse_proxy(struct Curl_easy *data, curl_url_get(uhp, CURLUPART_PORT, &portptr, 0); if(portptr) { - port = strtol(portptr, NULL, 10); + port = (int)strtol(portptr, NULL, 10); free(portptr); } else { if(data->set.proxyport) /* None given in the proxy string, then get the default one if it is given */ - port = data->set.proxyport; + port = (int)data->set.proxyport; else { if(proxytype == CURLPROXY_HTTPS) port = CURL_DEFAULT_HTTPS_PROXY_PORT; @@ -2410,7 +2439,7 @@ static CURLcode parse_proxy(struct Curl_easy *data, size_t len = strlen(host); host[len-1] = 0; /* clear the trailing bracket */ host++; - zonefrom_url(uhp, conn); + zonefrom_url(uhp, data, conn); } proxyinfo->host.name = host; @@ -2443,13 +2472,13 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data, /* create_conn helper to parse and init proxy values. to be called after unix socket init but before any proxy vars are evaluated. */ -static CURLcode create_conn_helper_init_proxy(struct connectdata *conn) +static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, + struct connectdata *conn) { char *proxy = NULL; char *socksproxy = NULL; char *no_proxy = NULL; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; /************************************************************* * Extract the user and password from the authentication string @@ -2491,7 +2520,7 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn) no_proxy = curl_getenv(p); } if(no_proxy) { - infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy); + infof(data, "Uses proxy env variable %s == '%s'\n", p, no_proxy); } } @@ -2503,7 +2532,7 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn) #ifndef CURL_DISABLE_HTTP else if(!proxy && !socksproxy) /* if the host is not in the noproxy list, detect proxy. */ - proxy = detect_proxy(conn); + proxy = detect_proxy(data, conn); #endif /* CURL_DISABLE_HTTP */ Curl_safefree(no_proxy); @@ -3277,7 +3306,7 @@ static CURLcode resolve_server(struct Curl_easy *data, conn->hostname_resolve = strdup(connhost->name); if(!conn->hostname_resolve) return CURLE_OUT_OF_MEMORY; - rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port, + rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port, &hostaddr, timeout_ms); if(rc == CURLRESOLV_PENDING) *async = TRUE; @@ -3302,7 +3331,7 @@ static CURLcode resolve_server(struct Curl_easy *data, conn->hostname_resolve = strdup(host->name); if(!conn->hostname_resolve) return CURLE_OUT_OF_MEMORY; - rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port, + rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port, &hostaddr, timeout_ms); if(rc == CURLRESOLV_PENDING) @@ -3330,9 +3359,15 @@ static CURLcode resolve_server(struct Curl_easy *data, * previously existing one. All relevant data is copied over and old_conn is * ready for freeing once this function returns. */ -static void reuse_conn(struct connectdata *old_conn, +static void reuse_conn(struct Curl_easy *data, + struct connectdata *old_conn, struct connectdata *conn) { + /* '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] = ""; + long local_port = -1; #ifndef CURL_DISABLE_PROXY Curl_free_idnconverted_hostname(&old_conn->http_proxy.host); Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host); @@ -3345,7 +3380,7 @@ static void reuse_conn(struct connectdata *old_conn, allocated in vain and is targeted for destruction */ Curl_free_primary_ssl_config(&old_conn->ssl_config); - conn->data = old_conn->data; + conn->data = data; /* get the user+password information from the old_conn struct since it may * be new for this request even when we re-use an existing connection */ @@ -3399,7 +3434,11 @@ static void reuse_conn(struct connectdata *old_conn, old_conn->hostname_resolve = NULL; /* persist connection info in session handle */ - Curl_persistconninfo(conn); + if(conn->transport == TRNSPRT_TCP) { + Curl_conninfo_local(data, conn->sock[FIRSTSOCKET], + local_ip, &local_port); + } + Curl_persistconninfo(data, conn, local_ip, local_port); conn_reset_all_postponed_data(old_conn); /* free buffers */ @@ -3500,7 +3539,7 @@ static CURLcode create_conn(struct Curl_easy *data, /* After the unix socket init but before the proxy vars are used, parse and initialize the proxy vars */ #ifndef CURL_DISABLE_PROXY - result = create_conn_helper_init_proxy(conn); + result = create_conn_helper_init_proxy(data, conn); if(result) goto out; @@ -3541,22 +3580,22 @@ static CURLcode create_conn(struct Curl_easy *data, /************************************************************* * IDN-convert the hostnames *************************************************************/ - result = Curl_idnconvert_hostname(conn, &conn->host); + result = Curl_idnconvert_hostname(data, &conn->host); if(result) goto out; if(conn->bits.conn_to_host) { - result = Curl_idnconvert_hostname(conn, &conn->conn_to_host); + result = Curl_idnconvert_hostname(data, &conn->conn_to_host); if(result) goto out; } #ifndef CURL_DISABLE_PROXY if(conn->bits.httpproxy) { - result = Curl_idnconvert_hostname(conn, &conn->http_proxy.host); + result = Curl_idnconvert_hostname(data, &conn->http_proxy.host); if(result) goto out; } if(conn->bits.socksproxy) { - result = Curl_idnconvert_hostname(conn, &conn->socks_proxy.host); + result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host); if(result) goto out; } @@ -3593,7 +3632,7 @@ static CURLcode create_conn(struct Curl_easy *data, * Setup internals depending on protocol. Needs to be done after * we figured out what/if proxy to use. *************************************************************/ - result = setup_connection_internals(conn); + result = setup_connection_internals(data, conn); if(result) goto out; @@ -3613,15 +3652,15 @@ static CURLcode create_conn(struct Curl_easy *data, /* this is supposed to be the connect function so we better at least check that the file is present here! */ DEBUGASSERT(conn->handler->connect_it); - Curl_persistconninfo(conn); - result = conn->handler->connect_it(conn, &done); + Curl_persistconninfo(data, conn, NULL, -1); + result = conn->handler->connect_it(data, &done); /* Setup a "faked" transfer that'll do nothing */ if(!result) { conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */ Curl_attach_connnection(data, conn); - result = Curl_conncache_add_conn(data->state.conn_cache, conn); + result = Curl_conncache_add_conn(data); if(result) goto out; @@ -3632,7 +3671,7 @@ static CURLcode create_conn(struct Curl_easy *data, if(result) { DEBUGASSERT(conn->handler->done); /* we ignore the return code for the protocol-specific DONE */ - (void)conn->handler->done(conn, result, FALSE); + (void)conn->handler->done(data, result, FALSE); goto out; } Curl_setup_transfer(data, -1, -1, FALSE, -1); @@ -3745,12 +3784,11 @@ static CURLcode create_conn(struct Curl_easy *data, if(reuse) { /* - * We already have a connection for this, we got the former connection - * in the conn_temp variable and thus we need to cleanup the one we - * just allocated before we can move along and use the previously - * existing one. + * We already have a connection for this, we got the former connection in + * the conn_temp variable and thus we need to cleanup the one we just + * allocated before we can move along and use the previously existing one. */ - reuse_conn(conn, conn_temp); + reuse_conn(data, conn, conn_temp); #ifdef USE_SSL free(conn->ssl_extra); #endif @@ -3792,7 +3830,8 @@ static CURLcode create_conn(struct Curl_easy *data, /* this gets a lock on the conncache */ const char *bundlehost; struct connectbundle *bundle = - Curl_conncache_find_bundle(conn, data->state.conn_cache, &bundlehost); + Curl_conncache_find_bundle(data, conn, data->state.conn_cache, + &bundlehost); if(max_host_connections > 0 && bundle && (bundle->num_connections >= max_host_connections)) { @@ -3845,8 +3884,7 @@ static CURLcode create_conn(struct Curl_easy *data, * cache of ours! */ Curl_attach_connnection(data, conn); - - result = Curl_conncache_add_conn(data->state.conn_cache, conn); + result = Curl_conncache_add_conn(data); if(result) goto out; } @@ -3918,11 +3956,11 @@ out: * conn->data MUST already have been setup fine (in create_conn) */ -CURLcode Curl_setup_conn(struct connectdata *conn, +CURLcode Curl_setup_conn(struct Curl_easy *data, bool *protocol_done) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; Curl_pgrsTime(data, TIMER_NAMELOOKUP); @@ -3940,20 +3978,6 @@ CURLcode Curl_setup_conn(struct connectdata *conn, lingering set from a previous invoke */ conn->bits.proxy_connect_closed = FALSE; #endif - /* - * Set user-agent. Used for HTTP, but since we can attempt to tunnel - * basically anything through a http proxy we can't limit this based on - * protocol. - */ - if(data->set.str[STRING_USERAGENT]) { - Curl_safefree(data->state.aptr.uagent); - data->state.aptr.uagent = - aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]); - if(!data->state.aptr.uagent) - return CURLE_OUT_OF_MEMORY; - } - - data->req.headerbytecount = 0; #ifdef CURL_DO_LINEEND_CONV data->state.crlf_conversions = 0; /* reset CRLF conversion counter */ @@ -3965,7 +3989,7 @@ CURLcode Curl_setup_conn(struct connectdata *conn, if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) { conn->bits.tcpconnect[FIRSTSOCKET] = FALSE; - result = Curl_connecthost(conn, conn->dns_entry); + result = Curl_connecthost(data, conn, conn->dns_entry); if(result) return result; } @@ -3976,8 +4000,8 @@ CURLcode Curl_setup_conn(struct connectdata *conn, Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */ conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; *protocol_done = TRUE; - Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]); - Curl_verboseconnect(conn); + Curl_updateconninfo(data, conn, conn->sock[FIRSTSOCKET]); + Curl_verboseconnect(data, conn); } conn->now = Curl_now(); /* time this *after* the connect is done, we set @@ -4010,7 +4034,7 @@ CURLcode Curl_connect(struct Curl_easy *data, /* DNS resolution is done: that's either because this is a reused connection, in which case DNS was unnecessary, or because DNS really did finish already (synch resolver/fast async resolve) */ - result = Curl_setup_conn(conn, protocol_done); + result = Curl_setup_conn(data, protocol_done); } } diff --git a/libs/libcurl/src/url.h b/libs/libcurl/src/url.h index a9d5bda29c..929fc60f26 100644 --- a/libs/libcurl/src/url.h +++ b/libs/libcurl/src/url.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,22 +23,6 @@ ***************************************************************************/ #include "curl_setup.h" -#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE -#define READBUFFER_MAX CURL_MAX_READ_SIZE -#define READBUFFER_MIN 1024 - -/* The default upload buffer size, should not be smaller than - CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in - a write callback. - - The size was 16KB for many years but was bumped to 64KB because it makes - libcurl able to do significantly faster uploads in some circumstances. Even - larger buffers can help further, but this is deemed a fair memory/speed - compromise. */ -#define UPLOADBUFFER_DEFAULT 65536 -#define UPLOADBUFFER_MAX (2*1024*1024) -#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE - /* * Prototypes for library-wide functions provided by url.c */ @@ -53,7 +37,7 @@ CURLcode Curl_close(struct Curl_easy **datap); /* opposite of curl_open() */ CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect); CURLcode Curl_disconnect(struct Curl_easy *data, struct connectdata *, bool dead_connection); -CURLcode Curl_setup_conn(struct connectdata *conn, +CURLcode Curl_setup_conn(struct Curl_easy *data, bool *protocol_done); void Curl_free_request_state(struct Curl_easy *data); CURLcode Curl_parse_login_details(const char *login, const size_t len, @@ -63,7 +47,7 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len, const struct Curl_handler *Curl_builtin_scheme(const char *scheme); bool Curl_is_ASCII_name(const char *hostname); -CURLcode Curl_idnconvert_hostname(struct connectdata *conn, +CURLcode Curl_idnconvert_hostname(struct Curl_easy *data, struct hostname *host); void Curl_free_idnconverted_hostname(struct hostname *host); @@ -72,9 +56,9 @@ void Curl_free_idnconverted_hostname(struct hostname *host); specified */ #ifdef CURL_DISABLE_VERBOSE_STRINGS -#define Curl_verboseconnect(x) Curl_nop_stmt +#define Curl_verboseconnect(x,y) Curl_nop_stmt #else -void Curl_verboseconnect(struct connectdata *conn); +void Curl_verboseconnect(struct Curl_easy *data, struct connectdata *conn); #endif #ifdef CURL_DISABLE_PROXY diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c index ae75963595..e3a788221b 100644 --- a/libs/libcurl/src/urlapi.c +++ b/libs/libcurl/src/urlapi.c @@ -983,12 +983,14 @@ void curl_url_cleanup(CURLU *u) } } -#define DUP(dest, src, name) \ - if(src->name) { \ - dest->name = strdup(src->name); \ - if(!dest->name) \ - goto fail; \ - } +#define DUP(dest, src, name) \ + do { \ + if(src->name) { \ + dest->name = strdup(src->name); \ + if(!dest->name) \ + goto fail; \ + } \ + } while(0) CURLU *curl_url_dup(CURLU *in) { diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h index 4679c9d463..f7d60b249b 100644 --- a/libs/libcurl/src/urldata.h +++ b/libs/libcurl/src/urldata.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -105,19 +105,27 @@ #include "dynbuf.h" /* return the count of bytes sent, or -1 on error */ -typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */ +typedef ssize_t (Curl_send)(struct Curl_easy *data, /* transfer */ int sockindex, /* socketindex */ const void *buf, /* data to write */ size_t len, /* max amount to write */ CURLcode *err); /* error to return */ /* return the count of bytes read, or -1 on error */ -typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ +typedef ssize_t (Curl_recv)(struct Curl_easy *data, /* transfer */ int sockindex, /* socketindex */ char *buf, /* store data here */ size_t len, /* max amount to read */ CURLcode *err); /* error to return */ +#ifdef USE_HYPER +typedef CURLcode (*Curl_datastream)(struct Curl_easy *data, + struct connectdata *conn, + int *didwhat, + bool *done, + int select_res); +#endif + #include "mime.h" #include "imap.h" #include "pop3.h" @@ -132,6 +140,7 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ #include "wildcard.h" #include "multihandle.h" #include "quic.h" +#include "c-hyper.h" #ifdef HAVE_GSSAPI # ifdef HAVE_GSSGNU @@ -151,6 +160,22 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ #include #endif /* HAVE_LIBSSH2_H */ +#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE +#define READBUFFER_MAX CURL_MAX_READ_SIZE +#define READBUFFER_MIN 1024 + +/* The default upload buffer size, should not be smaller than + CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in + a write callback. + + The size was 16KB for many years but was bumped to 64KB because it makes + libcurl able to do significantly faster uploads in some circumstances. Even + larger buffers can help further, but this is deemed a fair memory/speed + compromise. */ +#define UPLOADBUFFER_DEFAULT 65536 +#define UPLOADBUFFER_MAX (2*1024*1024) +#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE + #define CURLEASY_MAGIC_NUMBER 0xc0dedbadU #define GOOD_EASY_HANDLE(x) \ ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER)) @@ -368,8 +393,8 @@ struct ntlmdata { #else unsigned int flags; unsigned char nonce[8]; - void *target_info; /* TargetInfo received in the ntlm type-2 message */ unsigned int target_info_len; + void *target_info; /* TargetInfo received in the ntlm type-2 message */ #if defined(NTLM_WB_ENABLED) /* used for communication with Samba's winbind daemon helper ntlm_auth */ @@ -514,24 +539,24 @@ struct hostname { #define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) #define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) +#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH) +#define USE_CURL_ASYNC struct Curl_async { char *hostname; - int port; struct Curl_dns_entry *dns; - int status; /* if done is TRUE, this is the status from the callback */ struct thread_data *tdata; + void *resolver; /* resolver state, if it is used in the URL state - + ares_channel f.e. */ + int port; + int status; /* if done is TRUE, this is the status from the callback */ BIT(done); /* set TRUE when the lookup is complete */ }; +#endif + #define FIRSTSOCKET 0 #define SECONDARYSOCKET 1 -/* These function pointer types are here only to allow easier typecasting - within the source when we need to cast between data pointers (such as NULL) - and function pointers. */ -typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *); -typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool); - enum expect100 { EXP100_SEND_DATA, /* enough waiting, just send the body now */ EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */ @@ -578,8 +603,8 @@ struct dohdata { struct curl_slist *headers; struct dnsprobe probe[DOH_PROBE_SLOTS]; unsigned int pending; /* still outstanding requests */ - const char *host; int port; + const char *host; }; /* @@ -604,6 +629,8 @@ struct SingleRequest { following second response code) result in a CURLE_GOT_NOTHING error code */ + curl_off_t pendingheader; /* this many bytes left to send is actually + header and not body */ struct curltime start; /* transfer started at this time */ struct curltime now; /* current time */ enum { @@ -620,6 +647,7 @@ struct SingleRequest { Content-Range: header */ int httpcode; /* error code from the 'HTTP/1.? XXX' or 'RTSP/1.? XXX' line */ + int keepon; struct curltime start100; /* time stamp to wait for the 100 code from */ enum expect100 exp100; /* expect 100 continue state */ enum upgrade101 upgr101; /* 101 upgrade state */ @@ -628,7 +656,6 @@ struct SingleRequest { struct contenc_writer *writer_stack; time_t timeofdoc; long bodywrites; - int keepon; char *location; /* This points to an allocated version of the Location: header data */ char *newurl; /* Set to the new URL to use when a redirect or a retry is @@ -661,7 +688,7 @@ struct SingleRequest { struct TELNET *telnet; } p; #ifndef CURL_DISABLE_DOH - struct dohdata doh; /* DoH specific data for this request */ + struct dohdata *doh; /* DoH specific data for this request */ #endif BIT(header); /* incoming data has HTTP header */ BIT(content_range); /* set TRUE if Content-Range: was found */ @@ -686,18 +713,20 @@ struct SingleRequest { struct Curl_handler { const char *scheme; /* URL scheme name. */ - /* Complement to setup_connection_internals(). */ - CURLcode (*setup_connection)(struct connectdata *); + /* Complement to setup_connection_internals(). This is done before the + transfer "owns" the connection. */ + CURLcode (*setup_connection)(struct Curl_easy *data, + struct connectdata *conn); /* These two functions MUST be set to be protocol dependent */ - CURLcode (*do_it)(struct connectdata *, bool *done); - Curl_done_func done; + CURLcode (*do_it)(struct Curl_easy *data, bool *done); + CURLcode (*done)(struct Curl_easy *, CURLcode, bool); /* If the curl_do() function is better made in two halves, this * curl_do_more() function will be called afterwards, if set. For example * for doing the FTP stuff after the PASV/PORT command. */ - Curl_do_more_func do_more; + CURLcode (*do_more)(struct Curl_easy *, int *); /* This function *MAY* be set to a protocol-dependent function that is run * after the connect() and everything is done, as a step in the connection. @@ -705,39 +734,41 @@ struct Curl_handler { * function completes before return. If it doesn't complete, the caller * should call the curl_connecting() function until it is. */ - CURLcode (*connect_it)(struct connectdata *, bool *done); + CURLcode (*connect_it)(struct Curl_easy *data, bool *done); /* See above. */ - CURLcode (*connecting)(struct connectdata *, bool *done); - CURLcode (*doing)(struct connectdata *, bool *done); + CURLcode (*connecting)(struct Curl_easy *data, bool *done); + CURLcode (*doing)(struct Curl_easy *data, bool *done); /* Called from the multi interface during the PROTOCONNECT phase, and it should then return a proper fd set */ - int (*proto_getsock)(struct connectdata *conn, - curl_socket_t *socks); + int (*proto_getsock)(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); /* Called from the multi interface during the DOING phase, and it should then return a proper fd set */ - int (*doing_getsock)(struct connectdata *conn, - curl_socket_t *socks); + int (*doing_getsock)(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); /* Called from the multi interface during the DO_MORE phase, and it should then return a proper fd set */ - int (*domore_getsock)(struct connectdata *conn, - curl_socket_t *socks); + int (*domore_getsock)(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); /* Called from the multi interface during the DO_DONE, PERFORM and WAITPERFORM phases, and it should then return a proper fd set. Not setting this will make libcurl use the generic default one. */ - int (*perform_getsock)(const struct connectdata *conn, - curl_socket_t *socks); + int (*perform_getsock)(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); /* This function *MAY* be set to a protocol-dependent function that is run * by the curl_disconnect(), as a step in the disconnection. If the handler - * is called because the connection has been considered dead, dead_connection - * is set to TRUE. + * is called because the connection has been considered dead, + * dead_connection is set to TRUE. The connection is already disassociated + * from the transfer here. */ - CURLcode (*disconnect)(struct connectdata *, bool dead_connection); + CURLcode (*disconnect)(struct Curl_easy *, struct connectdata *, + bool dead_connection); /* If used, this function gets called from transfer.c:readwrite_data() to allow the protocol to do extra reads/writes */ @@ -747,10 +778,11 @@ struct Curl_handler { /* This function can perform various checks on the connection. See CONNCHECK_* for more information about the checks that can be performed, and CONNRESULT_* for the results that can be returned. */ - unsigned int (*connection_check)(struct connectdata *conn, + unsigned int (*connection_check)(struct Curl_easy *data, + struct connectdata *conn, unsigned int checks_to_perform); - long defport; /* Default port. */ + int defport; /* Default port. */ unsigned int protocol; /* See CURLPROTO_* - this needs to be the single specific protocol bit */ unsigned int family; /* single bit for protocol family; basically the @@ -858,13 +890,9 @@ enum connect_t { #define SOCKS_STATE(x) (((x) >= CONNECT_SOCKS_INIT) && \ ((x) < CONNECT_DONE)) -#define SOCKS_REQUEST_BUFSIZE 600 /* room for large user/pw (255 max each) */ struct connstate { enum connect_t state; - unsigned char socksreq[SOCKS_REQUEST_BUFSIZE]; - - /* CONNECT_SOCKS_SEND */ ssize_t outstanding; /* send this many bytes more */ unsigned char *outp; /* send from this pointer */ }; @@ -911,11 +939,6 @@ struct connectdata { struct Curl_addrinfo *ip_addr; struct Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */ - /* 'ip_addr_str' is the ip_addr data as a human readable string. - It remains available as long as the connection does, which is longer than - the ip_addr itself. */ - char ip_addr_str[MAX_IPADR_LEN]; - unsigned int scope_id; /* Scope id for IPv6 */ enum { @@ -938,7 +961,7 @@ struct connectdata { struct proxy_info socks_proxy; struct proxy_info http_proxy; #endif - long port; /* which port to use locally */ + int port; /* which port to use locally - to connect to */ int remote_port; /* the remote port, not the proxy port! */ int conn_to_port; /* the remote port to connect to. valid only if bits.conn_to_port is set */ @@ -953,14 +976,7 @@ struct connectdata { these are updated with data which comes directly from the socket. */ char primary_ip[MAX_IPADR_LEN]; - long primary_port; - - /* '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]; - long local_port; + unsigned char ip_version; /* copied from the Curl_easy at creation time */ char *user; /* user name string, allocated */ char *passwd; /* password string, allocated */ @@ -997,13 +1013,14 @@ struct connectdata { #endif struct ConnectBits bits; /* various state-flags for this connection */ + /* The field below gets set in Curl_connecthost */ + int num_addr; /* number of addresses to try to connect to */ /* connecttime: when connect() is called on the current IP address. Used to be able to track when to move on to try next IP - but only when the multi interface is used. */ struct curltime connecttime; - /* The two fields below get set in Curl_connecthost */ - int num_addr; /* number of addresses to try to connect to */ + /* The field below gets set in Curl_connecthost */ /* how long time in milliseconds to spend on trying to connect to each IP address, per family */ timediff_t timeoutms_per_addr[2]; @@ -1011,15 +1028,11 @@ struct connectdata { const struct Curl_handler *handler; /* Connection's protocol handler */ const struct Curl_handler *given; /* The protocol first given */ - long ip_version; /* copied from the Curl_easy at creation time */ - /* Protocols can use a custom keepalive mechanism to keep connections alive. This allows those protocols to track the last time the keepalive mechanism was used on this connection. */ struct curltime keepalive; - long upkeep_interval_ms; /* Time between calls for connection upkeep. */ - /**** curl_get() phase fields */ curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */ @@ -1070,9 +1083,6 @@ struct connectdata { struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ #endif - /* data used for the asynch name resolve callback */ - struct Curl_async async; - /* for chunked-encoded trailer */ struct dynbuf trailer; @@ -1091,27 +1101,30 @@ struct connectdata { struct mqtt_conn mqtt; } proto; - int cselect_bits; /* bitmask of socket events */ - int waitfor; /* current READ/WRITE bits to wait for */ - -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - int socks5_gssapi_enctype; + struct http_connect_state *connect_state; /* for HTTP CONNECT */ + struct connectbundle *bundle; /* The bundle we are member of */ +#ifdef USE_UNIX_SOCKETS + char *unix_domain_socket; +#endif +#ifdef USE_HYPER + /* if set, an alternative data transfer function */ + Curl_datastream datastream; #endif - /* When this connection is created, store the conditions for the local end bind. This is stored before the actual bind and before any connection is made and will serve the purpose of being used for comparison reasons so that subsequent bound-requested connections aren't accidentally re-using wrong connections. */ char *localdev; - unsigned short localport; int localportrange; - struct http_connect_state *connect_state; /* for HTTP CONNECT */ - struct connectbundle *bundle; /* The bundle we are member of */ + int cselect_bits; /* bitmask of socket events */ + int waitfor; /* current READ/WRITE bits to wait for */ int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */ -#ifdef USE_UNIX_SOCKETS - char *unix_domain_socket; + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + int socks5_gssapi_enctype; #endif + unsigned short localport; }; /* The end of connectdata. */ @@ -1206,17 +1219,6 @@ struct Progress { BIT(is_t_startransfer_set); }; -typedef enum { - HTTPREQ_NONE, /* first in list */ - HTTPREQ_GET, - HTTPREQ_POST, - HTTPREQ_POST_FORM, /* we make a difference internally */ - HTTPREQ_POST_MIME, /* we make a difference internally */ - HTTPREQ_PUT, - HTTPREQ_HEAD, - HTTPREQ_LAST /* last in list */ -} Curl_HttpReq; - typedef enum { RTSPREQ_NONE, /* first in list */ RTSPREQ_OPTIONS, @@ -1314,7 +1316,6 @@ struct urlpieces { struct UrlState { /* Points to the connection cache */ struct conncache *conn_cache; - int retrycount; /* number of retries on a new connection */ /* buffers to store authentication data in, as parsed from input options */ @@ -1336,10 +1337,10 @@ struct UrlState { int first_remote_port; /* remote port of the first (not followed) request */ struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ long sessionage; /* number of the most recent session */ - unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */ struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */ - char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */ + unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */ int os_errno; /* filled in with errno whenever an error occurs */ + char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */ #ifdef HAVE_SIGNAL /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */ void (*prev_signal)(int sig); @@ -1349,8 +1350,9 @@ struct UrlState { struct auth authhost; /* auth details for host */ struct auth authproxy; /* auth details for proxy */ - void *resolver; /* resolver state, if it is used in the URL state - - ares_channel f.e. */ +#ifdef USE_CURL_ASYNC + struct Curl_async async; /* asynchronous name resolver data */ +#endif #if defined(USE_OPENSSL) /* void instead of ENGINE to avoid bleeding OpenSSL into this header */ @@ -1398,7 +1400,9 @@ struct UrlState { int stream_weight; CURLU *uh; /* URL handle for the current parsed URL */ struct urlpieces up; +#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT) Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ +#endif #ifndef CURL_DISABLE_HTTP size_t trailers_bytes_sent; struct dynbuf trailers_buf; /* a buffer containing the compiled trailing @@ -1406,6 +1410,9 @@ struct UrlState { #endif trailers_state trailers_state; /* whether we are sending trailers and what stage are we at */ +#ifdef USE_HYPER + CURLcode hresult; /* used to pass return codes back from hyper callbacks */ +#endif /* Dynamically allocated strings, MUST be freed before this struct is killed. */ @@ -1569,7 +1576,6 @@ enum dupstring { STRING_ALTSVC, /* CURLOPT_ALTSVC */ STRING_HSTS, /* CURLOPT_HSTS */ STRING_SASL_AUTHZID, /* CURLOPT_SASL_AUTHZID */ - STRING_TEMP_URL, /* temp URL storage for proxy use */ STRING_DNS_SERVERS, STRING_DNS_INTERFACE, STRING_DNS_LOCAL_IP4, @@ -1584,6 +1590,7 @@ enum dupstring { STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ + STRING_AWS_SIGV4, /* Parameters for V4 signature */ STRING_LAST /* not used, just an end-of-list marker */ }; @@ -1699,8 +1706,11 @@ struct UserDefined { struct curl_slist *connect_to; /* list of host:port mappings to override the hostname and port to connect to */ curl_TimeCond timecondition; /* kind of time/date comparison */ + curl_proxytype proxytype; /* what kind of proxy that is in use */ time_t timevalue; /* what time to compare with */ +#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT) Curl_HttpReq method; /* what kind of HTTP request (if any) is this */ +#endif long httpversion; /* when non-zero, a specific HTTP version requested to be used in the library's request(s) */ struct ssl_config_data ssl; /* user defined SSL stuff */ @@ -1708,15 +1718,14 @@ struct UserDefined { struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ #endif struct ssl_general_config general_ssl; /* general user defined SSL stuff */ - curl_proxytype proxytype; /* what kind of proxy that is in use */ long dns_cache_timeout; /* DNS cache timeout */ long buffer_size; /* size of receive buffer to use */ size_t upload_buffer_size; /* size of upload buffer to use, keep it >= CURL_MAX_WRITE_SIZE */ void *private_data; /* application-private data */ struct curl_slist *http200aliases; /* linked list of aliases for http200 */ - long ipver; /* the CURL_IPRESOLVE_* defines in the public header file - 0 - whatever, 1 - v2, 2 - v6 */ + unsigned char ipver; /* the CURL_IPRESOLVE_* defines in the public header + file 0 - whatever, 1 - v2, 2 - v6 */ curl_off_t max_filesize; /* Maximum file size to download */ #ifndef CURL_DISABLE_FTP curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */ @@ -1874,6 +1883,10 @@ struct Names { */ struct Curl_easy { + /* First a simple identifier to easier detect if a user mix up this easy + handle with a multi handle. Set this to CURLEASY_MAGIC_NUMBER */ + unsigned int magic; + /* first, two fields for the linked list of these */ struct Curl_easy *next; struct Curl_easy *prev; @@ -1934,7 +1947,9 @@ struct Curl_easy { iconv_t inbound_cd; /* for translating from the network encoding */ iconv_t utf8_cd; /* for translating to UTF8 */ #endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ - unsigned int magic; /* set to a CURLEASY_MAGIC_NUMBER */ +#ifdef USE_HYPER + struct hyptransfer hyp; +#endif }; #define LIBCURL_NAME "libcurl" diff --git a/libs/libcurl/src/vauth/digest.c b/libs/libcurl/src/vauth/digest.c index 5fc9285263..559852fcba 100644 --- a/libs/libcurl/src/vauth/digest.c +++ b/libs/libcurl/src/vauth/digest.c @@ -61,12 +61,14 @@ It converts digest text to ASCII so the MD5 will be correct for what ultimately goes over the network. */ -#define CURL_OUTPUT_DIGEST_CONV(a, b) \ - result = Curl_convert_to_network(a, b, strlen(b)); \ - if(result) { \ - free(b); \ - return result; \ - } +#define CURL_OUTPUT_DIGEST_CONV(a, b) \ + do { \ + result = Curl_convert_to_network(a, b, strlen(b)); \ + if(result) { \ + free(b); \ + return result; \ + } \ + } while(0) #endif /* !USE_WINDOWS_SSPI */ bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, diff --git a/libs/libcurl/src/vauth/digest_sspi.c b/libs/libcurl/src/vauth/digest_sspi.c index 91d18c992b..dad947a37e 100644 --- a/libs/libcurl/src/vauth/digest_sspi.c +++ b/libs/libcurl/src/vauth/digest_sspi.c @@ -38,6 +38,7 @@ #include "sendf.h" #include "strdup.h" #include "strcase.h" +#include "strerror.h" /* The last #include files should be: */ #include "curl_memory.h" @@ -134,7 +135,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(status != SEC_E_OK) { free(input_token); - failf(data, "SSPI: couldn't get auth info\n"); + failf(data, "SSPI: couldn't get auth info"); return CURLE_AUTH_ERROR; } @@ -220,6 +221,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, status == SEC_I_COMPLETE_AND_CONTINUE) s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; + s_pSecFn->FreeCredentialsHandle(&credentials); Curl_sspi_free_identity(p_identity); free(spn); @@ -229,6 +232,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(status == SEC_E_INSUFFICIENT_MEMORY) return CURLE_OUT_OF_MEMORY; + infof(data, "schannel: InitializeSecurityContext failed: %s\n", + Curl_sspi_strerror(status, buffer, sizeof(buffer))); + return CURLE_AUTH_ERROR; } @@ -433,7 +439,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), &SecurityPackage); if(status != SEC_E_OK) { - failf(data, "SSPI: couldn't get auth info\n"); + failf(data, "SSPI: couldn't get auth info"); return CURLE_AUTH_ERROR; } @@ -611,6 +617,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, status == SEC_I_COMPLETE_AND_CONTINUE) s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; + s_pSecFn->FreeCredentialsHandle(&credentials); Curl_sspi_free_identity(p_identity); @@ -621,6 +629,9 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, if(status == SEC_E_INSUFFICIENT_MEMORY) return CURLE_OUT_OF_MEMORY; + infof(data, "schannel: InitializeSecurityContext failed: %s\n", + Curl_sspi_strerror(status, buffer, sizeof(buffer))); + return CURLE_AUTH_ERROR; } diff --git a/libs/libcurl/src/vauth/krb5_sspi.c b/libs/libcurl/src/vauth/krb5_sspi.c index 8e56a82409..b2d1635343 100644 --- a/libs/libcurl/src/vauth/krb5_sspi.c +++ b/libs/libcurl/src/vauth/krb5_sspi.c @@ -125,7 +125,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, TEXT(SP_NAME_KERBEROS), &SecurityPackage); if(status != SEC_E_OK) { - failf(data, "SSPI: couldn't get auth info\n"); + failf(data, "SSPI: couldn't get auth info"); return CURLE_AUTH_ERROR; } diff --git a/libs/libcurl/src/vauth/ntlm_sspi.c b/libs/libcurl/src/vauth/ntlm_sspi.c index 28bc3efdaa..07dc97398e 100644 --- a/libs/libcurl/src/vauth/ntlm_sspi.c +++ b/libs/libcurl/src/vauth/ntlm_sspi.c @@ -106,7 +106,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM), &SecurityPackage); if(status != SEC_E_OK) { - failf(data, "SSPI: couldn't get auth info\n"); + failf(data, "SSPI: couldn't get auth info"); return CURLE_AUTH_ERROR; } diff --git a/libs/libcurl/src/vauth/spnego_sspi.c b/libs/libcurl/src/vauth/spnego_sspi.c index e7482a43e2..4aa1ba9572 100644 --- a/libs/libcurl/src/vauth/spnego_sspi.c +++ b/libs/libcurl/src/vauth/spnego_sspi.c @@ -130,7 +130,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, TEXT(SP_NAME_NEGOTIATE), &SecurityPackage); if(nego->status != SEC_E_OK) { - failf(data, "SSPI: couldn't get auth info\n"); + failf(data, "SSPI: couldn't get auth info"); return CURLE_AUTH_ERROR; } diff --git a/libs/libcurl/src/version.c b/libs/libcurl/src/version.c index 7064c20d2f..a9102ec1ea 100644 --- a/libs/libcurl/src/version.c +++ b/libs/libcurl/src/version.c @@ -100,7 +100,7 @@ static size_t zstd_version(char *buf, size_t bufsz) * zeros in the data. */ -#define VERSION_PARTS 14 /* number of substrings we can concatenate */ +#define VERSION_PARTS 15 /* number of substrings we can concatenate */ char *curl_version(void) { @@ -143,6 +143,9 @@ char *curl_version(void) #endif #ifdef USE_LIBRTMP char rtmp_version[40]; +#endif +#ifdef USE_HYPER + char hyper_buf[30]; #endif int i = 0; int j; @@ -228,6 +231,10 @@ char *curl_version(void) src[i++] = rtmp_version; } #endif +#ifdef USE_HYPER + msnprintf(hyper_buf, sizeof(hyper_buf), "Hyper/%s", hyper_version()); + src[i++] = hyper_buf; +#endif DEBUGASSERT(i <= VERSION_PARTS); @@ -274,6 +281,9 @@ static const char * const protocols[] = { #ifndef CURL_DISABLE_GOPHER "gopher", #endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER) + "gophers", +#endif #ifndef CURL_DISABLE_HTTP "http", #endif @@ -394,7 +404,7 @@ static curl_version_info_data version_info = { #if defined(USE_TLS_SRP) | CURL_VERSION_TLSAUTH_SRP #endif -#if defined(USE_NGHTTP2) +#if defined(USE_NGHTTP2) || defined(USE_HYPER) | CURL_VERSION_HTTP2 #endif #if defined(ENABLE_QUIC) @@ -447,7 +457,8 @@ static curl_version_info_data version_info = { NULL, #endif 0, /* zstd_ver_num */ - NULL /* zstd version */ + NULL, /* zstd version */ + NULL /* Hyper version */ }; curl_version_info_data *curl_version_info(CURLversion stamp) @@ -469,7 +480,6 @@ curl_version_info_data *curl_version_info(CURLversion stamp) static char zstd_buffer[80]; #endif - #ifdef USE_SSL Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer)); version_info.ssl_version = ssl_buffer; @@ -544,6 +554,14 @@ curl_version_info_data *curl_version_info(CURLversion stamp) } #endif +#ifdef USE_HYPER + { + static char hyper_buffer[30]; + msnprintf(hyper_buffer, sizeof(hyper_buffer), "Hyper/%s", hyper_version()); + version_info.hyper_version = hyper_buffer; + } +#endif + (void)stamp; /* avoid compiler warnings, we don't use this */ return &version_info; } diff --git a/libs/libcurl/src/vquic/ngtcp2.c b/libs/libcurl/src/vquic/ngtcp2.c index 0f2fea0af7..d4d0e8bf43 100644 --- a/libs/libcurl/src/vquic/ngtcp2.c +++ b/libs/libcurl/src/vquic/ngtcp2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -87,10 +87,10 @@ struct h3out { "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1" #endif -static CURLcode ng_process_ingress(struct connectdata *conn, +static CURLcode ng_process_ingress(struct Curl_easy *data, curl_socket_t sockfd, struct quicsocket *qs); -static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, +static CURLcode ng_flush_egress(struct Curl_easy *data, int sockfd, struct quicsocket *qs); static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id, size_t datalen, void *user_data, @@ -170,20 +170,22 @@ static void quic_settings(struct quicsocket *qs, uint64_t stream_buffer_size) { ngtcp2_settings *s = &qs->settings; + ngtcp2_transport_params *t = &qs->transport_params; ngtcp2_settings_default(s); + ngtcp2_transport_params_default(t); #ifdef DEBUG_NGTCP2 s->log_printf = quic_printf; #else s->log_printf = NULL; #endif s->initial_ts = timestamp(); - s->transport_params.initial_max_stream_data_bidi_local = stream_buffer_size; - s->transport_params.initial_max_stream_data_bidi_remote = QUIC_MAX_STREAMS; - s->transport_params.initial_max_stream_data_uni = QUIC_MAX_STREAMS; - s->transport_params.initial_max_data = QUIC_MAX_DATA; - s->transport_params.initial_max_streams_bidi = 1; - s->transport_params.initial_max_streams_uni = 3; - s->transport_params.max_idle_timeout = QUIC_IDLE_TIMEOUT; + t->initial_max_stream_data_bidi_local = stream_buffer_size; + t->initial_max_stream_data_bidi_remote = QUIC_MAX_STREAMS; + t->initial_max_stream_data_uni = QUIC_MAX_STREAMS; + t->initial_max_data = QUIC_MAX_DATA; + t->initial_max_streams_bidi = 1; + t->initial_max_streams_uni = 3; + t->max_idle_timeout = QUIC_IDLE_TIMEOUT; if(qs->qlogfd != -1) { s->qlog.write = qlog_callback; } @@ -556,10 +558,8 @@ cb_recv_crypto_data(ngtcp2_conn *tconn, ngtcp2_crypto_level crypto_level, static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data) { - struct quicsocket *qs = (struct quicsocket *)user_data; + (void)user_data; (void)tconn; - infof(qs->conn->data, "QUIC handshake is completed\n"); - return 0; } @@ -587,8 +587,6 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags, nconsumed = nghttp3_conn_read_stream(qs->h3conn, stream_id, buf, buflen, fin); if(nconsumed < 0) { - failf(qs->conn->data, "nghttp3_conn_read_stream returned error: %s\n", - nghttp3_strerror((int)nconsumed)); return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -616,8 +614,6 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, rv = nghttp3_conn_add_ack_offset(qs->h3conn, stream_id, datalen); if(rv != 0) { - failf(qs->conn->data, "nghttp3_conn_add_ack_offset returned error: %s\n", - nghttp3_strerror(rv)); return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -637,8 +633,6 @@ static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id, rv = nghttp3_conn_close_stream(qs->h3conn, stream_id, app_error_code); if(rv != 0) { - failf(qs->conn->data, "nghttp3_conn_close_stream returned error: %s\n", - nghttp3_strerror(rv)); return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -658,8 +652,6 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id, rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id); if(rv != 0) { - failf(qs->conn->data, "nghttp3_conn_reset_stream returned error: %s\n", - nghttp3_strerror(rv)); return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -689,8 +681,6 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id, rv = nghttp3_conn_unblock_stream(qs->h3conn, stream_id); if(rv != 0) { - failf(qs->conn->data, "nghttp3_conn_unblock_stream returned error: %s\n", - nghttp3_strerror(rv)); return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -701,23 +691,23 @@ static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid, uint8_t *token, size_t cidlen, void *user_data) { - struct quicsocket *qs = (struct quicsocket *)user_data; CURLcode result; (void)tconn; + (void)user_data; - result = Curl_rand(qs->conn->data, cid->data, cidlen); + result = Curl_rand(NULL, cid->data, cidlen); if(result) return NGTCP2_ERR_CALLBACK_FAILURE; cid->datalen = cidlen; - result = Curl_rand(qs->conn->data, token, NGTCP2_STATELESS_RESET_TOKENLEN); + result = Curl_rand(NULL, token, NGTCP2_STATELESS_RESET_TOKENLEN); if(result) return NGTCP2_ERR_CALLBACK_FAILURE; return 0; } -static ngtcp2_conn_callbacks ng_callbacks = { +static ngtcp2_callbacks ng_callbacks = { ngtcp2_crypto_client_initial_cb, NULL, /* recv_client_initial */ cb_recv_crypto_data, @@ -755,7 +745,8 @@ static ngtcp2_conn_callbacks ng_callbacks = { /* * Might be called twice for happy eyeballs. */ -CURLcode Curl_quic_connect(struct connectdata *conn, +CURLcode Curl_quic_connect(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t sockfd, int sockindex, const struct sockaddr *addr, @@ -765,14 +756,13 @@ CURLcode Curl_quic_connect(struct connectdata *conn, int rv; CURLcode result; ngtcp2_path path; /* TODO: this must be initialized properly */ - struct Curl_easy *data = conn->data; struct quicsocket *qs = &conn->hequic[sockindex]; char ipbuf[40]; long port; int qfd; if(qs->conn) - Curl_quic_disconnect(conn, sockindex); + Curl_quic_disconnect(data, conn, sockindex); qs->conn = conn; /* extract the used address as a string */ @@ -822,7 +812,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path, NGTCP2_PROTO_VER_MIN, &ng_callbacks, - &qs->settings, NULL, qs); + &qs->settings, &qs->transport_params, NULL, qs); if(rc) return CURLE_QUIC_CONNECT_ERROR; @@ -843,9 +833,10 @@ int Curl_quic_ver(char *p, size_t len) ng2->version_str, ht3->version_str); } -static int ng_getsock(struct connectdata *conn, curl_socket_t *socks) +static int ng_getsock(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t *socks) { - struct SingleRequest *k = &conn->data->req; + struct SingleRequest *k = &data->req; int bitmap = GETSOCK_BLANK; socks[0] = conn->sock[FIRSTSOCKET]; @@ -861,12 +852,6 @@ static int ng_getsock(struct connectdata *conn, curl_socket_t *socks) return bitmap; } -static int ng_perform_getsock(const struct connectdata *conn, - curl_socket_t *socks) -{ - return ng_getsock((struct connectdata *)conn, socks); -} - static void qs_disconnect(struct quicsocket *qs) { int i; @@ -897,25 +882,30 @@ static void qs_disconnect(struct quicsocket *qs) #endif } -void Curl_quic_disconnect(struct connectdata *conn, +void Curl_quic_disconnect(struct Curl_easy *data, + struct connectdata *conn, int tempindex) { + (void)data; if(conn->transport == TRNSPRT_QUIC) qs_disconnect(&conn->hequic[tempindex]); } -static CURLcode ng_disconnect(struct connectdata *conn, +static CURLcode ng_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { (void)dead_connection; - Curl_quic_disconnect(conn, 0); - Curl_quic_disconnect(conn, 1); + Curl_quic_disconnect(data, conn, 0); + Curl_quic_disconnect(data, conn, 1); return CURLE_OK; } -static unsigned int ng_conncheck(struct connectdata *conn, +static unsigned int ng_conncheck(struct Curl_easy *data, + struct connectdata *conn, unsigned int checks_to_perform) { + (void)data; (void)conn; (void)checks_to_perform; return CONNRESULT_NONE; @@ -933,7 +923,7 @@ static const struct Curl_handler Curl_handler_http3 = { ng_getsock, /* proto_getsock */ ng_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - ng_perform_getsock, /* perform_getsock */ + ng_getsock, /* perform_getsock */ ng_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ng_conncheck, /* connection_check */ @@ -1134,7 +1124,7 @@ static int cb_h3_send_stop_sending(nghttp3_conn *conn, int64_t stream_id, return 0; } -static nghttp3_conn_callbacks ngh3_callbacks = { +static nghttp3_callbacks ngh3_callbacks = { cb_h3_acked_stream_data, /* acked_stream_data */ cb_h3_stream_close, cb_h3_recv_data, @@ -1162,11 +1152,10 @@ static int init_ngh3_conn(struct quicsocket *qs) int64_t ctrl_stream_id, qpack_enc_stream_id, qpack_dec_stream_id; if(ngtcp2_conn_get_max_local_streams_uni(qs->qconn) < 3) { - failf(qs->conn->data, "too few available QUIC streams"); return CURLE_QUIC_CONNECT_ERROR; } - nghttp3_conn_settings_default(&qs->h3settings); + nghttp3_settings_default(&qs->h3settings); rc = nghttp3_conn_client_new(&qs->h3conn, &ngh3_callbacks, @@ -1235,14 +1224,15 @@ static size_t drain_overflow_buffer(struct HTTP *stream) } /* incoming data frames on the h3 stream */ -static ssize_t ngh3_stream_recv(struct connectdata *conn, +static ssize_t ngh3_stream_recv(struct Curl_easy *data, int sockindex, char *buf, size_t buffersize, CURLcode *curlcode) { + struct connectdata *conn = data->conn; curl_socket_t sockfd = conn->sock[sockindex]; - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; struct quicsocket *qs = conn->quic; if(!stream->memlen) { @@ -1257,11 +1247,11 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn, as possible to the receive buffer before receiving more */ drain_overflow_buffer(stream); - if(ng_process_ingress(conn, sockfd, qs)) { + if(ng_process_ingress(data, sockfd, qs)) { *curlcode = CURLE_RECV_ERROR; return -1; } - if(ng_flush_egress(conn, sockfd, qs)) { + if(ng_flush_egress(data, sockfd, qs)) { *curlcode = CURLE_SEND_ERROR; return -1; } @@ -1277,7 +1267,7 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn, /* extend the stream window with the data we're consuming and send out any additional packets to tell the server that we can receive more */ extend_stream_window(qs->qconn, stream); - if(ng_flush_egress(conn, sockfd, qs)) { + if(ng_flush_egress(data, sockfd, qs)) { *curlcode = CURLE_SEND_ERROR; return -1; } @@ -1289,7 +1279,7 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn, return 0; } - infof(conn->data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n"); + infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n"); *curlcode = CURLE_AGAIN; return -1; } @@ -1301,8 +1291,7 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id, { struct Curl_easy *data = stream_user_data; struct HTTP *stream = data->req.p.http; - (void)conn; - (void)stream_id; + int rv; (void)user_data; if(!data->set.postfields) { @@ -1311,6 +1300,13 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id, "cb_h3_acked_stream_data, %zd bytes, %zd left unacked\n", datalen, stream->h3out->used)); DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE); + + if(stream->h3out->used == 0) { + rv = nghttp3_conn_resume_stream(conn, stream_id); + if(rv != 0) { + return NGTCP2_ERR_CALLBACK_FAILURE; + } + } } return 0; } @@ -1346,13 +1342,14 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id, nread = H3_SEND_SIZE - out->windex; memcpy(&out->buf[out->windex], stream->upload_mem, nread); - out->windex += nread; - out->used += nread; /* that's the chunk we return to nghttp3 */ vec[0].base = &out->buf[out->windex]; vec[0].len = nread; + out->windex += nread; + out->used += nread; + if(out->windex == H3_SEND_SIZE) out->windex = 0; /* wrap */ stream->upload_mem += nread; @@ -1370,7 +1367,7 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id, (stream->upload_left <= 0)) { H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF\n")); *pflags = NGHTTP3_DATA_FLAG_EOF; - return 0; + return nread ? 1 : 0; } else if(!nread) { return NGHTTP3_ERR_WOULDBLOCK; @@ -1382,10 +1379,11 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id, field list. */ #define AUTHORITY_DST_IDX 3 -static CURLcode http_request(struct connectdata *conn, const void *mem, +static CURLcode http_request(struct Curl_easy *data, const void *mem, size_t len) { - struct HTTP *stream = conn->data->req.p.http; + struct connectdata *conn = data->conn; + struct HTTP *stream = data->req.p.http; size_t nheader; size_t i; size_t authority_idx; @@ -1393,7 +1391,6 @@ static CURLcode http_request(struct connectdata *conn, const void *mem, char *end, *line_end; struct quicsocket *qs = conn->quic; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; nghttp3_nv *nva = NULL; int64_t stream3_id; int rc; @@ -1401,7 +1398,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem, rc = ngtcp2_conn_open_bidi_stream(qs->qconn, &stream3_id, NULL); if(rc) { - failf(conn->data, "can get bidi streams"); + failf(data, "can get bidi streams"); result = CURLE_SEND_ERROR; goto fail; } @@ -1587,8 +1584,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem, stream->h3out = h3out; rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id, - nva, nheader, &data_reader, - conn->data); + nva, nheader, &data_reader, data); if(rc) { result = CURLE_SEND_ERROR; goto fail; @@ -1598,9 +1594,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem, default: stream->upload_left = 0; /* nothing left to send */ rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id, - nva, nheader, - NULL, /* no body! */ - conn->data); + nva, nheader, NULL, data); if(rc) { result = CURLE_SEND_ERROR; goto fail; @@ -1619,19 +1613,20 @@ fail: free(nva); return result; } -static ssize_t ngh3_stream_send(struct connectdata *conn, +static ssize_t ngh3_stream_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *curlcode) { ssize_t sent; + struct connectdata *conn = data->conn; struct quicsocket *qs = conn->quic; curl_socket_t sockfd = conn->sock[sockindex]; - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; if(!stream->h3req) { - CURLcode result = http_request(conn, mem, len); + CURLcode result = http_request(data, mem, len); if(result) { *curlcode = CURLE_SEND_ERROR; return -1; @@ -1639,7 +1634,7 @@ static ssize_t ngh3_stream_send(struct connectdata *conn, sent = len; } else { - H3BUGF(infof(conn->data, "ngh3_stream_send() wants to send %zd bytes\n", + H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes\n", len)); if(!stream->upload_len) { stream->upload_mem = mem; @@ -1653,7 +1648,7 @@ static ssize_t ngh3_stream_send(struct connectdata *conn, } } - if(ng_flush_egress(conn, sockfd, qs)) { + if(ng_flush_egress(data, sockfd, qs)) { *curlcode = CURLE_SEND_ERROR; return -1; } @@ -1671,13 +1666,13 @@ static void ng_has_connected(struct connectdata *conn, int tempindex) conn->httpversion = 30; conn->bundle->multiuse = BUNDLE_MULTIPLEX; conn->quic = &conn->hequic[tempindex]; - DEBUGF(infof(conn->data, "ngtcp2 established connection!\n")); } /* * There can be multiple connection attempts going on in parallel. */ -CURLcode Curl_quic_is_connected(struct connectdata *conn, +CURLcode Curl_quic_is_connected(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool *done) { @@ -1685,11 +1680,11 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn, struct quicsocket *qs = &conn->hequic[sockindex]; curl_socket_t sockfd = conn->tempsock[sockindex]; - result = ng_process_ingress(conn, sockfd, qs); + result = ng_process_ingress(data, sockfd, qs); if(result) goto error; - result = ng_flush_egress(conn, sockfd, qs); + result = ng_flush_egress(data, sockfd, qs); if(result) goto error; @@ -1705,7 +1700,7 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn, } -static CURLcode ng_process_ingress(struct connectdata *conn, +static CURLcode ng_process_ingress(struct Curl_easy *data, curl_socket_t sockfd, struct quicsocket *qs) { @@ -1730,7 +1725,7 @@ static CURLcode ng_process_ingress(struct connectdata *conn, if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) break; - failf(conn->data, "ngtcp2: recvfrom() unexpectedly returned %zd", recvd); + failf(data, "ngtcp2: recvfrom() unexpectedly returned %zd", recvd); return CURLE_RECV_ERROR; } @@ -1749,7 +1744,8 @@ static CURLcode ng_process_ingress(struct connectdata *conn, return CURLE_OK; } -static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, +static CURLcode ng_flush_egress(struct Curl_easy *data, + int sockfd, struct quicsocket *qs) { int rv; @@ -1767,6 +1763,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, int fin; nghttp3_vec vec[16]; ssize_t ndatalen; + uint32_t flags; switch(qs->local_addr.ss_family) { case AF_INET: @@ -1783,7 +1780,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, rv = ngtcp2_conn_handle_expiry(qs->qconn, ts); if(rv != 0) { - failf(conn->data, "ngtcp2_conn_handle_expiry returned error: %s\n", + failf(data, "ngtcp2_conn_handle_expiry returned error: %s", ngtcp2_strerror(rv)); return CURLE_SEND_ERROR; } @@ -1792,72 +1789,64 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, for(;;) { outlen = -1; + veccnt = 0; + stream_id = -1; + fin = 0; + if(qs->h3conn && ngtcp2_conn_get_max_data_left(qs->qconn)) { veccnt = nghttp3_conn_writev_stream(qs->h3conn, &stream_id, &fin, vec, sizeof(vec) / sizeof(vec[0])); if(veccnt < 0) { - failf(conn->data, "nghttp3_conn_writev_stream returned error: %s\n", + failf(data, "nghttp3_conn_writev_stream returned error: %s", nghttp3_strerror((int)veccnt)); return CURLE_SEND_ERROR; } - else if(veccnt > 0) { - uint32_t 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, &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) { - assert(ndatalen == -1); - rv = nghttp3_conn_block_stream(qs->h3conn, stream_id); - if(rv != 0) { - failf(conn->data, - "nghttp3_conn_block_stream returned error: %s\n", - nghttp3_strerror(rv)); - return CURLE_SEND_ERROR; - } - continue; - } - else if(outlen == NGTCP2_ERR_WRITE_MORE) { - assert(ndatalen > 0); - rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, - ndatalen); - if(rv != 0) { - failf(conn->data, - "nghttp3_conn_add_write_offset returned error: %s\n", - nghttp3_strerror(rv)); - return CURLE_SEND_ERROR; - } - continue; - } - else { - assert(ndatalen == -1); - failf(conn->data, "ngtcp2_conn_writev_stream returned error: %s\n", - ngtcp2_strerror((int)outlen)); - return CURLE_SEND_ERROR; - } + } + + 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, + &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) { + assert(ndatalen == -1); + rv = nghttp3_conn_block_stream(qs->h3conn, stream_id); + if(rv != 0) { + failf(data, "nghttp3_conn_block_stream returned error: %s\n", + nghttp3_strerror(rv)); + return CURLE_SEND_ERROR; } - else { - assert(ndatalen == -1); + continue; + } + else if(outlen == NGTCP2_ERR_WRITE_MORE) { + assert(ndatalen >= 0); + rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen); + if(rv != 0) { + failf(data, "nghttp3_conn_add_write_offset returned error: %s\n", + nghttp3_strerror(rv)); + return CURLE_SEND_ERROR; } + continue; } - } - if(outlen < 0) { - outlen = ngtcp2_conn_write_pkt(qs->qconn, &ps.path, NULL, - out, pktlen, ts); - if(outlen < 0) { - failf(conn->data, "ngtcp2_conn_write_pkt returned error: %s\n", + else { + assert(ndatalen == -1); + failf(data, "ngtcp2_conn_writev_stream returned error: %s", ngtcp2_strerror((int)outlen)); return CURLE_SEND_ERROR; } - if(outlen == 0) - break; + } + else if(ndatalen >= 0) { + rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen); + if(rv != 0) { + failf(data, "nghttp3_conn_add_write_offset returned error: %s\n", + nghttp3_strerror(rv)); + return CURLE_SEND_ERROR; + } } memcpy(&remote_addr, ps.path.remote.addr, ps.path.remote.addrlen); @@ -1871,7 +1860,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, break; } else { - failf(conn->data, "send() returned %zd (errno %d)\n", sent, + failf(data, "send() returned %zd (errno %d)", sent, SOCKERRNO); return CURLE_SEND_ERROR; } @@ -1886,7 +1875,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, else { timeout = expiry - ts; } - Curl_expire(conn->data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC); + Curl_expire(data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC); } return CURLE_OK; @@ -1895,11 +1884,13 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, /* * Called from transfer.c:done_sending when we stop HTTP/3 uploading. */ -CURLcode Curl_quic_done_sending(struct connectdata *conn) +CURLcode Curl_quic_done_sending(struct Curl_easy *data) { + struct connectdata *conn = data->conn; + DEBUGASSERT(conn); if(conn->handler == &Curl_handler_http3) { /* only for HTTP/3 transfers */ - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; struct quicsocket *qs = conn->quic; stream->upload_done = TRUE; (void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id); diff --git a/libs/libcurl/src/vquic/ngtcp2.h b/libs/libcurl/src/vquic/ngtcp2.h index c6d4d12e65..cbede45146 100644 --- a/libs/libcurl/src/vquic/ngtcp2.h +++ b/libs/libcurl/src/vquic/ngtcp2.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -48,6 +48,7 @@ struct quicsocket { ngtcp2_cid scid; uint32_t version; ngtcp2_settings settings; + ngtcp2_transport_params transport_params; #ifdef USE_OPENSSL SSL_CTX *sslctx; SSL *ssl; @@ -62,7 +63,7 @@ struct quicsocket { socklen_t local_addrlen; nghttp3_conn *h3conn; - nghttp3_conn_settings h3settings; + nghttp3_settings h3settings; int qlogfd; }; diff --git a/libs/libcurl/src/vquic/quiche.c b/libs/libcurl/src/vquic/quiche.c index d0d150e391..d138dd3a24 100644 --- a/libs/libcurl/src/vquic/quiche.c +++ b/libs/libcurl/src/vquic/quiche.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -53,21 +53,22 @@ #define QUIC_MAX_DATA (1*1024*1024) #define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */ -static CURLcode process_ingress(struct connectdata *conn, +static CURLcode process_ingress(struct Curl_easy *data, curl_socket_t sockfd, struct quicsocket *qs); -static CURLcode flush_egress(struct connectdata *conn, curl_socket_t sockfd, +static CURLcode flush_egress(struct Curl_easy *data, curl_socket_t sockfd, struct quicsocket *qs); -static CURLcode http_request(struct connectdata *conn, const void *mem, +static CURLcode http_request(struct Curl_easy *data, const void *mem, size_t len); static Curl_recv h3_stream_recv; static Curl_send h3_stream_send; -static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks) +static int quiche_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { - struct SingleRequest *k = &conn->data->req; + struct SingleRequest *k = &data->req; int bitmap = GETSOCK_BLANK; socks[0] = conn->sock[FIRSTSOCKET]; @@ -83,20 +84,15 @@ static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks) return bitmap; } -static int quiche_perform_getsock(const struct connectdata *conn, - curl_socket_t *socks) -{ - return quiche_getsock((struct connectdata *)conn, socks); -} - -static CURLcode qs_disconnect(struct connectdata *conn, +static CURLcode qs_disconnect(struct Curl_easy *data, struct quicsocket *qs) { + DEBUGASSERT(qs); if(qs->conn) { (void)quiche_conn_close(qs->conn, TRUE, 0, NULL, 0); /* flushing the egress is not a failsafe way to deliver all the outstanding packets, but we also don't want to get stuck here... */ - (void)flush_egress(conn, qs->sockfd, qs); + (void)flush_egress(data, qs->sockfd, qs); quiche_conn_free(qs->conn); qs->conn = NULL; } @@ -111,34 +107,38 @@ static CURLcode qs_disconnect(struct connectdata *conn, return CURLE_OK; } -static CURLcode quiche_disconnect(struct connectdata *conn, +static CURLcode quiche_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { struct quicsocket *qs = conn->quic; (void)dead_connection; - return qs_disconnect(conn, qs); + return qs_disconnect(data, qs); } -void Curl_quic_disconnect(struct connectdata *conn, +void Curl_quic_disconnect(struct Curl_easy *data, + struct connectdata *conn, int tempindex) { if(conn->transport == TRNSPRT_QUIC) - qs_disconnect(conn, &conn->hequic[tempindex]); + qs_disconnect(data, &conn->hequic[tempindex]); } -static unsigned int quiche_conncheck(struct connectdata *conn, +static unsigned int quiche_conncheck(struct Curl_easy *data, + struct connectdata *conn, unsigned int checks_to_perform) { + (void)data; (void)conn; (void)checks_to_perform; return CONNRESULT_NONE; } -static CURLcode quiche_do(struct connectdata *conn, bool *done) +static CURLcode quiche_do(struct Curl_easy *data, bool *done) { - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; stream->h3req = FALSE; /* not sent */ - return Curl_http(conn, done); + return Curl_http(data, done); } static const struct Curl_handler Curl_handler_http3 = { @@ -153,7 +153,7 @@ static const struct Curl_handler Curl_handler_http3 = { quiche_getsock, /* proto_getsock */ quiche_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - quiche_perform_getsock, /* perform_getsock */ + quiche_getsock, /* perform_getsock */ quiche_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ quiche_conncheck, /* connection_check */ @@ -171,14 +171,16 @@ static void quiche_debug_log(const char *line, void *argp) } #endif -CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd, +CURLcode Curl_quic_connect(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t sockfd, int sockindex, const struct sockaddr *addr, socklen_t addrlen) { CURLcode result; struct quicsocket *qs = &conn->hequic[sockindex]; - struct Curl_easy *data = conn->data; char *keylog_file = NULL; + char ipbuf[40]; + long port; #ifdef DEBUG_QUICHE /* initialize debug log callback only once */ @@ -243,20 +245,22 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd, } #endif - result = flush_egress(conn, sockfd, qs); + result = flush_egress(data, sockfd, qs); if(result) return result; - /* store the used address as a string */ - if(!Curl_addr2string((struct sockaddr*)addr, addrlen, - conn->primary_ip, &conn->primary_port)) { + /* extract the used address as a string */ + if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) { char buffer[STRERROR_LEN]; failf(data, "ssrem inet_ntop() failed with errno %d: %s", SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_BAD_FUNCTION_ARGUMENT; } - memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); - Curl_persistconninfo(conn); + + infof(data, "Connect socket %d over QUIC to %s:%ld\n", + sockfd, ipbuf, port); + + Curl_persistconninfo(data, conn, NULL, -1); /* for connection reuse purposes: */ conn->ssl[FIRSTSOCKET].state = ssl_connection_complete; @@ -320,38 +324,39 @@ static CURLcode quiche_has_connected(struct connectdata *conn, /* * This function gets polled to check if this QUIC connection has connected. */ -CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex, +CURLcode Curl_quic_is_connected(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { CURLcode result; struct quicsocket *qs = &conn->hequic[sockindex]; curl_socket_t sockfd = conn->tempsock[sockindex]; - result = process_ingress(conn, sockfd, qs); + result = process_ingress(data, sockfd, qs); if(result) goto error; - result = flush_egress(conn, sockfd, qs); + result = flush_egress(data, sockfd, qs); if(result) goto error; if(quiche_conn_is_established(qs->conn)) { *done = TRUE; result = quiche_has_connected(conn, 0, sockindex); - DEBUGF(infof(conn->data, "quiche established connection!\n")); + DEBUGF(infof(data, "quiche established connection!\n")); } return result; error: - qs_disconnect(conn, qs); + qs_disconnect(data, qs); return result; } -static CURLcode process_ingress(struct connectdata *conn, int sockfd, +static CURLcode process_ingress(struct Curl_easy *data, int sockfd, struct quicsocket *qs) { ssize_t recvd; - struct Curl_easy *data = conn->data; uint8_t *buf = (uint8_t *)data->state.buffer; size_t bufsize = data->set.buffer_size; @@ -364,7 +369,7 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd, break; if(recvd < 0) { - failf(conn->data, "quiche: recv() unexpectedly returned %zd " + failf(data, "quiche: recv() unexpectedly returned %zd " "(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd); return CURLE_RECV_ERROR; } @@ -374,7 +379,7 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd, break; if(recvd < 0) { - failf(conn->data, "quiche_conn_recv() == %zd", recvd); + failf(data, "quiche_conn_recv() == %zd", recvd); return CURLE_RECV_ERROR; } } while(1); @@ -386,7 +391,7 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd, * flush_egress drains the buffers and sends off data. * Calls failf() on errors. */ -static CURLcode flush_egress(struct connectdata *conn, int sockfd, +static CURLcode flush_egress(struct Curl_easy *data, int sockfd, struct quicsocket *qs) { ssize_t sent; @@ -399,14 +404,13 @@ static CURLcode flush_egress(struct connectdata *conn, int sockfd, break; if(sent < 0) { - failf(conn->data, "quiche_conn_send returned %zd\n", - sent); + failf(data, "quiche_conn_send returned %zd", sent); return CURLE_SEND_ERROR; } sent = send(sockfd, out, sent, 0); if(sent < 0) { - failf(conn->data, "send() returned %zd\n", sent); + failf(data, "send() returned %zd", sent); return CURLE_SEND_ERROR; } } while(1); @@ -415,7 +419,7 @@ static CURLcode flush_egress(struct connectdata *conn, int sockfd, timeout_ns = quiche_conn_timeout_as_nanos(qs->conn); if(timeout_ns) /* expire uses milliseconds */ - Curl_expire(conn->data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC); + Curl_expire(data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC); return CURLE_OK; } @@ -453,7 +457,7 @@ static int cb_each_header(uint8_t *name, size_t name_len, return 0; } -static ssize_t h3_stream_recv(struct connectdata *conn, +static ssize_t h3_stream_recv(struct Curl_easy *data, int sockindex, char *buf, size_t buffersize, @@ -461,18 +465,18 @@ static ssize_t h3_stream_recv(struct connectdata *conn, { ssize_t recvd = -1; ssize_t rcode; + struct connectdata *conn = data->conn; struct quicsocket *qs = conn->quic; curl_socket_t sockfd = conn->sock[sockindex]; quiche_h3_event *ev; int rc; struct h3h1header headers; - struct Curl_easy *data = conn->data; struct HTTP *stream = data->req.p.http; headers.dest = buf; headers.destlen = buffersize; headers.nlen = 0; - if(process_ingress(conn, sockfd, qs)) { + if(process_ingress(data, sockfd, qs)) { infof(data, "h3_stream_recv returns on ingress\n"); *curlcode = CURLE_RECV_ERROR; return -1; @@ -532,7 +536,7 @@ static ssize_t h3_stream_recv(struct connectdata *conn, quiche_h3_event_free(ev); } - if(flush_egress(conn, sockfd, qs)) { + if(flush_egress(data, sockfd, qs)) { *curlcode = CURLE_SEND_ERROR; return -1; } @@ -546,19 +550,20 @@ static ssize_t h3_stream_recv(struct connectdata *conn, return recvd; } -static ssize_t h3_stream_send(struct connectdata *conn, +static ssize_t h3_stream_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *curlcode) { ssize_t sent; + struct connectdata *conn = data->conn; struct quicsocket *qs = conn->quic; curl_socket_t sockfd = conn->sock[sockindex]; - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; if(!stream->h3req) { - CURLcode result = http_request(conn, mem, len); + CURLcode result = http_request(data, mem, len); if(result) { *curlcode = CURLE_SEND_ERROR; return -1; @@ -566,8 +571,7 @@ static ssize_t h3_stream_send(struct connectdata *conn, sent = len; } else { - H3BUGF(infof(conn->data, "Pass on %zd body bytes to quiche\n", - len)); + H3BUGF(infof(data, "Pass on %zd body bytes to quiche\n", len)); sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id, (uint8_t *)mem, len, FALSE); if(sent < 0) { @@ -576,7 +580,7 @@ static ssize_t h3_stream_send(struct connectdata *conn, } } - if(flush_egress(conn, sockfd, qs)) { + if(flush_egress(data, sockfd, qs)) { *curlcode = CURLE_SEND_ERROR; return -1; } @@ -598,12 +602,13 @@ int Curl_quic_ver(char *p, size_t len) field list. */ #define AUTHORITY_DST_IDX 3 -static CURLcode http_request(struct connectdata *conn, const void *mem, +static CURLcode http_request(struct Curl_easy *data, const void *mem, size_t len) { /* */ - struct HTTP *stream = conn->data->req.p.http; + struct connectdata *conn = data->conn; + struct HTTP *stream = data->req.p.http; size_t nheader; size_t i; size_t authority_idx; @@ -613,7 +618,6 @@ static CURLcode http_request(struct connectdata *conn, const void *mem, quiche_h3_header *nva = NULL; struct quicsocket *qs = conn->quic; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; stream->h3req = TRUE; /* senf off! */ @@ -826,14 +830,15 @@ fail: /* * Called from transfer.c:done_sending when we stop HTTP/3 uploading. */ -CURLcode Curl_quic_done_sending(struct connectdata *conn) +CURLcode Curl_quic_done_sending(struct Curl_easy *data) { + struct connectdata *conn = data->conn; + DEBUGASSERT(conn); if(conn->handler == &Curl_handler_http3) { /* only for HTTP/3 transfers */ ssize_t sent; - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; struct quicsocket *qs = conn->quic; - fprintf(stderr, "!!! Curl_quic_done_sending\n"); stream->upload_done = TRUE; sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id, NULL, 0, TRUE); diff --git a/libs/libcurl/src/vssh/libssh.c b/libs/libcurl/src/vssh/libssh.c index e79d8e823c..08896ab5b1 100644 --- a/libs/libcurl/src/vssh/libssh.c +++ b/libs/libcurl/src/vssh/libssh.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2017 - 2020 Red Hat, Inc. + * Copyright (C) 2017 - 2021 Red Hat, Inc. * * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek, * Robert Kolcun, Andreas Schneider @@ -107,34 +107,37 @@ #endif /* Local functions: */ -static CURLcode myssh_connect(struct connectdata *conn, bool *done); -static CURLcode myssh_multi_statemach(struct connectdata *conn, +static CURLcode myssh_connect(struct Curl_easy *data, bool *done); +static CURLcode myssh_multi_statemach(struct Curl_easy *data, bool *done); -static CURLcode myssh_do_it(struct connectdata *conn, bool *done); +static CURLcode myssh_do_it(struct Curl_easy *data, bool *done); -static CURLcode scp_done(struct connectdata *conn, +static CURLcode scp_done(struct Curl_easy *data, CURLcode, bool premature); -static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done); -static CURLcode scp_disconnect(struct connectdata *conn, +static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done); +static CURLcode scp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection); -static CURLcode sftp_done(struct connectdata *conn, +static CURLcode sftp_done(struct Curl_easy *data, CURLcode, bool premature); -static CURLcode sftp_doing(struct connectdata *conn, +static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done); -static CURLcode sftp_disconnect(struct connectdata *conn, bool dead); +static CURLcode sftp_disconnect(struct Curl_easy *data, + struct connectdata *conn, + bool dead); static -CURLcode sftp_perform(struct connectdata *conn, +CURLcode sftp_perform(struct Curl_easy *data, bool *connected, bool *dophase_done); -static void sftp_quote(struct connectdata *conn); -static void sftp_quote_stat(struct connectdata *conn); -static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock); -static int myssh_perform_getsock(const struct connectdata *conn, - curl_socket_t *sock); +static void sftp_quote(struct Curl_easy *data); +static void sftp_quote_stat(struct Curl_easy *data); +static int myssh_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *sock); -static CURLcode myssh_setup_connection(struct connectdata *conn); +static CURLcode myssh_setup_connection(struct Curl_easy *data, + struct connectdata *conn); /* * SCP protocol handler. @@ -152,7 +155,7 @@ const struct Curl_handler Curl_handler_scp = { myssh_getsock, /* proto_getsock */ myssh_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - myssh_perform_getsock, /* perform_getsock */ + myssh_getsock, /* perform_getsock */ scp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ @@ -178,7 +181,7 @@ const struct Curl_handler Curl_handler_sftp = { myssh_getsock, /* proto_getsock */ myssh_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - myssh_perform_getsock, /* perform_getsock */ + myssh_getsock, /* perform_getsock */ sftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ @@ -223,12 +226,13 @@ static CURLcode sftp_error_to_CURLE(int err) * SSH State machine related code */ /* This is the ONLY way to change SSH state! */ -static void mystate(struct connectdata *conn, sshstate nowstate +static void mystate(struct Curl_easy *data, sshstate nowstate #ifdef DEBUGBUILD , int lineno #endif ) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* for debug purposes */ @@ -297,7 +301,7 @@ static void mystate(struct connectdata *conn, sshstate nowstate if(sshc->state != nowstate) { - infof(conn->data, "SSH %p state change from %s to %s (line %d)\n", + infof(data, "SSH %p state change from %s to %s (line %d)\n", (void *) sshc, names[sshc->state], names[nowstate], lineno); } @@ -316,10 +320,10 @@ static void mystate(struct connectdata *conn, sshstate nowstate * * Returns SSH_OK or SSH_ERROR. */ -static int myssh_is_known(struct connectdata *conn) +static int myssh_is_known(struct Curl_easy *data) { int rc; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; ssh_key pubkey; size_t hlen; @@ -529,10 +533,10 @@ static int myssh_is_known(struct connectdata *conn) cleanup: if(found_base64) { - free(found_base64); + (free)(found_base64); } if(known_base64) { - free(known_base64); + (free)(known_base64); } if(hash) ssh_clean_pubkey_hash(&hash); @@ -546,14 +550,14 @@ cleanup: } #define MOVE_TO_ERROR_STATE(_r) { \ - state(conn, SSH_SESSION_DISCONNECT); \ + state(data, SSH_SESSION_DISCONNECT); \ sshc->actualcode = _r; \ rc = SSH_ERROR; \ break; \ } #define MOVE_TO_SFTP_CLOSE_STATE() { \ - state(conn, SSH_SFTP_CLOSE); \ + state(data, SSH_SFTP_CLOSE); \ sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \ rc = SSH_ERROR; \ break; \ @@ -562,7 +566,7 @@ cleanup: #define MOVE_TO_LAST_AUTH \ if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \ rc = SSH_OK; \ - state(conn, SSH_AUTH_PASS_INIT); \ + state(data, SSH_AUTH_PASS_INIT); \ break; \ } \ else { \ @@ -572,7 +576,7 @@ cleanup: #define MOVE_TO_TERTIARY_AUTH \ if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \ rc = SSH_OK; \ - state(conn, SSH_AUTH_KEY_INIT); \ + state(data, SSH_AUTH_KEY_INIT); \ break; \ } \ else { \ @@ -582,7 +586,7 @@ cleanup: #define MOVE_TO_SECONDARY_AUTH \ if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \ rc = SSH_OK; \ - state(conn, SSH_AUTH_GSSAPI); \ + state(data, SSH_AUTH_GSSAPI); \ break; \ } \ else { \ @@ -660,10 +664,10 @@ restart: * to will be set to TRUE if the libssh function returns SSH_AGAIN * meaning it wants to be called again when the socket is ready */ -static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) +static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SSHPROTO *protop = data->req.p.ssh; struct ssh_conn *sshc = &conn->proto.sshc; curl_socket_t sock = conn->sock[FIRSTSOCKET]; @@ -689,7 +693,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) non-blocking */ ssh_set_blocking(sshc->ssh_session, 0); - state(conn, SSH_S_STARTUP); + state(data, SSH_S_STARTUP); /* FALLTHROUGH */ case SSH_S_STARTUP: @@ -702,17 +706,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT); } - state(conn, SSH_HOSTKEY); + state(data, SSH_HOSTKEY); /* FALLTHROUGH */ case SSH_HOSTKEY: - rc = myssh_is_known(conn); + rc = myssh_is_known(data); if(rc != SSH_OK) { MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION); } - state(conn, SSH_AUTHLIST); + state(data, SSH_AUTHLIST); /* FALLTHROUGH */ case SSH_AUTHLIST:{ sshc->authed = FALSE; @@ -726,7 +730,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) if(rc == SSH_AUTH_SUCCESS) { sshc->authed = TRUE; infof(data, "Authenticated with none\n"); - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); break; } else if(rc == SSH_AUTH_ERROR) { @@ -735,17 +739,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL); if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { - state(conn, SSH_AUTH_PKEY_INIT); + state(data, SSH_AUTH_PKEY_INIT); infof(data, "Authentication using SSH public key file\n"); } else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { - state(conn, SSH_AUTH_GSSAPI); + state(data, SSH_AUTH_GSSAPI); } else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { - state(conn, SSH_AUTH_KEY_INIT); + state(data, SSH_AUTH_KEY_INIT); } else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { - state(conn, SSH_AUTH_PASS_INIT); + state(data, SSH_AUTH_PASS_INIT); } else { /* unsupported authentication method */ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); @@ -785,7 +789,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) break; } - state(conn, SSH_AUTH_PKEY); + state(data, SSH_AUTH_PKEY); break; } @@ -800,7 +804,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) rc = SSH_OK; sshc->authed = TRUE; infof(data, "Completed public key authentication\n"); - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); break; } @@ -817,7 +821,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) if(rc == SSH_AUTH_SUCCESS) { sshc->authed = TRUE; infof(data, "Completed public key authentication\n"); - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); break; } else { @@ -841,7 +845,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) rc = SSH_OK; sshc->authed = TRUE; infof(data, "Completed gssapi authentication\n"); - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); break; } @@ -850,7 +854,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) case SSH_AUTH_KEY_INIT: if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) { - state(conn, SSH_AUTH_KEY); + state(data, SSH_AUTH_KEY); } else { MOVE_TO_LAST_AUTH; @@ -868,7 +872,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sshc->authed = TRUE; infof(data, "completed keyboard interactive authentication\n"); } - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); break; case SSH_AUTH_PASS_INIT: @@ -876,7 +880,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) /* Host key authentication is intentionally not implemented */ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); } - state(conn, SSH_AUTH_PASS); + state(data, SSH_AUTH_PASS); /* FALLTHROUGH */ case SSH_AUTH_PASS: @@ -889,7 +893,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) if(rc == SSH_AUTH_SUCCESS) { sshc->authed = TRUE; infof(data, "Completed password authentication\n"); - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); } else { MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); @@ -908,17 +912,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) */ infof(data, "Authentication complete\n"); - Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */ + Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */ conn->sockfd = sock; conn->writesockfd = CURL_SOCKET_BAD; if(conn->handler->protocol == CURLPROTO_SFTP) { - state(conn, SSH_SFTP_INIT); + state(data, SSH_SFTP_INIT); break; } infof(data, "SSH CONNECT phase done\n"); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; case SSH_SFTP_INIT: @@ -940,7 +944,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc)); break; } - state(conn, SSH_SFTP_REALPATH); + state(data, SSH_SFTP_REALPATH); /* FALLTHROUGH */ case SSH_SFTP_REALPATH: /* @@ -950,32 +954,31 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) if(sshc->homedir == NULL) { MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); } - conn->data->state.most_recent_ftp_entrypath = sshc->homedir; + data->state.most_recent_ftp_entrypath = sshc->homedir; /* This is the last step in the SFTP connect phase. Do note that while we get the homedir here, we get the "workingpath" in the DO action since the homedir will remain the same between request but the working path will not. */ DEBUGF(infof(data, "SSH CONNECT phase done\n")); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; case SSH_SFTP_QUOTE_INIT: - - result = Curl_getworkingpath(conn, sshc->homedir, &protop->path); + result = Curl_getworkingpath(data, sshc->homedir, &protop->path); if(result) { sshc->actualcode = result; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } if(data->set.quote) { infof(data, "Sending quote commands\n"); sshc->quote_item = data->set.quote; - state(conn, SSH_SFTP_QUOTE); + state(data, SSH_SFTP_QUOTE); } else { - state(conn, SSH_SFTP_GETINFO); + state(data, SSH_SFTP_GETINFO); } break; @@ -983,16 +986,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) if(data->set.postquote) { infof(data, "Sending quote commands\n"); sshc->quote_item = data->set.postquote; - state(conn, SSH_SFTP_QUOTE); + state(data, SSH_SFTP_QUOTE); } else { - state(conn, SSH_STOP); + state(data, SSH_STOP); } break; case SSH_SFTP_QUOTE: /* Send any quote commands */ - sftp_quote(conn); + sftp_quote(data); break; case SSH_SFTP_NEXT_QUOTE: @@ -1002,21 +1005,21 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sshc->quote_item = sshc->quote_item->next; if(sshc->quote_item) { - state(conn, SSH_SFTP_QUOTE); + state(data, SSH_SFTP_QUOTE); } else { if(sshc->nextstate != SSH_NO_STATE) { - state(conn, sshc->nextstate); + state(data, sshc->nextstate); sshc->nextstate = SSH_NO_STATE; } else { - state(conn, SSH_SFTP_GETINFO); + state(data, SSH_SFTP_GETINFO); } } break; case SSH_SFTP_QUOTE_STAT: - sftp_quote_stat(conn); + sftp_quote_stat(data); break; case SSH_SFTP_QUOTE_SETSTAT: @@ -1027,7 +1030,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path2); failf(data, "Attempt to set SFTP stats failed: %s", ssh_get_error(sshc->ssh_session)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; /* sshc->actualcode = sftp_error_to_CURLE(err); @@ -1035,7 +1038,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) * the error the libssh2 backend is returning */ break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_SYMLINK: @@ -1046,12 +1049,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path2); failf(data, "symlink command failed: %s", ssh_get_error(sshc->ssh_session)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_MKDIR: @@ -1061,12 +1064,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path1); failf(data, "mkdir command failed: %s", ssh_get_error(sshc->ssh_session)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_RENAME: @@ -1077,12 +1080,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path2); failf(data, "rename command failed: %s", ssh_get_error(sshc->ssh_session)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_RMDIR: @@ -1091,12 +1094,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path1); failf(data, "rmdir command failed: %s", ssh_get_error(sshc->ssh_session)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_UNLINK: @@ -1105,12 +1108,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path1); failf(data, "rm command failed: %s", ssh_get_error(sshc->ssh_session)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_STATVFS: @@ -1122,7 +1125,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path1); failf(data, "statvfs command failed: %s", ssh_get_error(sshc->ssh_session)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; @@ -1145,29 +1148,29 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) if(!tmp) { result = CURLE_OUT_OF_MEMORY; - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; break; } - result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); free(tmp); if(result) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; } } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; } case SSH_SFTP_GETINFO: if(data->set.get_filetime) { - state(conn, SSH_SFTP_FILETIME); + state(data, SSH_SFTP_FILETIME); } else { - state(conn, SSH_SFTP_TRANS_INIT); + state(data, SSH_SFTP_TRANS_INIT); } break; @@ -1181,18 +1184,18 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sftp_attributes_free(attrs); } - state(conn, SSH_SFTP_TRANS_INIT); + state(data, SSH_SFTP_TRANS_INIT); break; } case SSH_SFTP_TRANS_INIT: if(data->set.upload) - state(conn, SSH_SFTP_UPLOAD_INIT); + state(data, SSH_SFTP_UPLOAD_INIT); else { if(protop->path[strlen(protop->path)-1] == '/') - state(conn, SSH_SFTP_READDIR_INIT); + state(data, SSH_SFTP_READDIR_INIT); else - state(conn, SSH_SFTP_DOWNLOAD_INIT); + state(data, SSH_SFTP_DOWNLOAD_INIT); } break; @@ -1228,7 +1231,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) /* If we have restart position then open for append */ flags = O_WRONLY|O_APPEND; else - /* Clear file before writing (normal behaviour) */ + /* Clear file before writing (normal behavior) */ flags = O_WRONLY|O_CREAT|O_TRUNC; if(sshc->sftp_file) @@ -1246,7 +1249,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) /* try to create the path remotely */ rc = 0; sshc->secondCreateDirs = 1; - state(conn, SSH_SFTP_CREATE_DIRS_INIT); + state(data, SSH_SFTP_CREATE_DIRS_INIT); break; } else { @@ -1329,17 +1332,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) timeout here */ Curl_expire(data, 0, EXPIRE_RUN_NOW); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } case SSH_SFTP_CREATE_DIRS_INIT: if(strlen(protop->path) > 1) { sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */ - state(conn, SSH_SFTP_CREATE_DIRS); + state(data, SSH_SFTP_CREATE_DIRS); } else { - state(conn, SSH_SFTP_UPLOAD_INIT); + state(data, SSH_SFTP_UPLOAD_INIT); } break; @@ -1349,10 +1352,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) *sshc->slash_pos = 0; infof(data, "Creating directory '%s'\n", protop->path); - state(conn, SSH_SFTP_CREATE_DIRS_MKDIR); + state(data, SSH_SFTP_CREATE_DIRS_MKDIR); break; } - state(conn, SSH_SFTP_UPLOAD_INIT); + state(data, SSH_SFTP_UPLOAD_INIT); break; case SSH_SFTP_CREATE_DIRS_MKDIR: @@ -1375,13 +1378,13 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) } rc = 0; /* clear rc and continue */ } - state(conn, SSH_SFTP_CREATE_DIRS); + state(data, SSH_SFTP_CREATE_DIRS); break; case SSH_SFTP_READDIR_INIT: Curl_pgrsSetDownloadSize(data, -1); if(data->set.opt_no_body) { - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } @@ -1396,7 +1399,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) ssh_get_error(sshc->ssh_session)); MOVE_TO_SFTP_CLOSE_STATE(); } - state(conn, SSH_SFTP_READDIR); + state(data, SSH_SFTP_READDIR); break; case SSH_SFTP_READDIR: @@ -1415,16 +1418,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) tmpLine = aprintf("%s\n", sshc->readdir_filename); if(tmpLine == NULL) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } - result = Curl_client_write(conn, CLIENTWRITE_BODY, + result = Curl_client_write(data, CLIENTWRITE_BODY, tmpLine, sshc->readdir_len + 1); free(tmpLine); if(result) { - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } /* since this counts what we send to the client, we include the @@ -1440,7 +1443,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sshc->readdir_totalLen = 80 + sshc->readdir_currLen; sshc->readdir_line = calloc(sshc->readdir_totalLen, 1); if(!sshc->readdir_line) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } @@ -1452,7 +1455,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) S_IFLNK)) { sshc->readdir_linkPath = malloc(PATH_MAX + 1); if(sshc->readdir_linkPath == NULL) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } @@ -1460,15 +1463,15 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path, sshc->readdir_filename); - state(conn, SSH_SFTP_READDIR_LINK); + state(data, SSH_SFTP_READDIR_LINK); break; } - state(conn, SSH_SFTP_READDIR_BOTTOM); + state(data, SSH_SFTP_READDIR_BOTTOM); break; } } else if(sftp_dir_eof(sshc->sftp_dir)) { - state(conn, SSH_SFTP_READDIR_DONE); + state(data, SSH_SFTP_READDIR_DONE); break; } else { @@ -1515,7 +1518,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sshc->readdir_totalLen); if(!new_readdir_line) { sshc->readdir_line = NULL; - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } @@ -1533,14 +1536,14 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sshc->readdir_filename = NULL; sshc->readdir_longentry = NULL; - state(conn, SSH_SFTP_READDIR_BOTTOM); + state(data, SSH_SFTP_READDIR_BOTTOM); /* FALLTHROUGH */ case SSH_SFTP_READDIR_BOTTOM: sshc->readdir_currLen += msnprintf(sshc->readdir_line + sshc->readdir_currLen, sshc->readdir_totalLen - sshc->readdir_currLen, "\n"); - result = Curl_client_write(conn, CLIENTWRITE_BODY, + result = Curl_client_write(data, CLIENTWRITE_BODY, sshc->readdir_line, sshc->readdir_currLen); @@ -1555,10 +1558,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sshc->readdir_tmp = NULL; if(result) { - state(conn, SSH_STOP); + state(data, SSH_STOP); } else - state(conn, SSH_SFTP_READDIR); + state(data, SSH_SFTP_READDIR); break; case SSH_SFTP_READDIR_DONE: @@ -1567,7 +1570,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; case SSH_SFTP_DOWNLOAD_INIT: @@ -1586,7 +1589,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) MOVE_TO_SFTP_CLOSE_STATE(); } - state(conn, SSH_SFTP_DOWNLOAD_STAT); + state(data, SSH_SFTP_DOWNLOAD_STAT); break; case SSH_SFTP_DOWNLOAD_STAT: @@ -1618,14 +1621,14 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); return CURLE_BAD_DOWNLOAD_RESUME; } - if(conn->data->state.use_range) { + if(data->state.use_range) { curl_off_t from, to; char *ptr; char *ptr2; CURLofft to_t; CURLofft from_t; - from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from); + from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from); if(from_t == CURL_OFFT_FLOW) { return CURLE_RANGE_ERROR; } @@ -1708,7 +1711,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); infof(data, "File already completely downloaded\n"); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); @@ -1724,12 +1727,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) if(result) { /* this should never occur; the close state should be entered at the time the error occurs */ - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = result; } else { sshc->sftp_recv_state = 0; - state(conn, SSH_STOP); + state(data, SSH_STOP); } break; @@ -1747,11 +1750,11 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) SSH_SFTP_CLOSE to pass the correct result back */ if(sshc->nextstate != SSH_NO_STATE && sshc->nextstate != SSH_SFTP_CLOSE) { - state(conn, sshc->nextstate); + state(data, sshc->nextstate); sshc->nextstate = SSH_SFTP_CLOSE; } else { - state(conn, SSH_STOP); + state(data, SSH_STOP); result = sshc->actualcode; } break; @@ -1772,17 +1775,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) } SSH_STRING_FREE_CHAR(sshc->homedir); - conn->data->state.most_recent_ftp_entrypath = NULL; + data->state.most_recent_ftp_entrypath = NULL; - state(conn, SSH_SESSION_DISCONNECT); + state(data, SSH_SESSION_DISCONNECT); break; - case SSH_SCP_TRANS_INIT: - result = Curl_getworkingpath(conn, sshc->homedir, &protop->path); + result = Curl_getworkingpath(data, sshc->homedir, &protop->path); if(result) { sshc->actualcode = result; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } @@ -1798,17 +1800,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sshc->scp_session = ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path); - state(conn, SSH_SCP_UPLOAD_INIT); + state(data, SSH_SCP_UPLOAD_INIT); } else { sshc->scp_session = ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path); - state(conn, SSH_SCP_DOWNLOAD_INIT); + state(data, SSH_SCP_DOWNLOAD_INIT); } if(!sshc->scp_session) { err_msg = ssh_get_error(sshc->ssh_session); - failf(conn->data, "%s", err_msg); + failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); } @@ -1819,7 +1821,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) rc = ssh_scp_init(sshc->scp_session); if(rc != SSH_OK) { err_msg = ssh_get_error(sshc->ssh_session); - failf(conn->data, "%s", err_msg); + failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); } @@ -1828,7 +1830,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) (int)data->set.new_file_perms); if(rc != SSH_OK) { err_msg = ssh_get_error(sshc->ssh_session); - failf(conn->data, "%s", err_msg); + failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); } @@ -1847,7 +1849,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) with both accordingly */ conn->cselect_bits = CURL_CSELECT_OUT; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; @@ -1856,10 +1858,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) rc = ssh_scp_init(sshc->scp_session); if(rc != SSH_OK) { err_msg = ssh_get_error(sshc->ssh_session); - failf(conn->data, "%s", err_msg); + failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); } - state(conn, SSH_SCP_DOWNLOAD); + state(data, SSH_SCP_DOWNLOAD); /* FALLTHROUGH */ case SSH_SCP_DOWNLOAD:{ @@ -1868,7 +1870,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) rc = ssh_scp_pull_request(sshc->scp_session); if(rc != SSH_SCP_REQUEST_NEWFILE) { err_msg = ssh_get_error(sshc->ssh_session); - failf(conn->data, "%s", err_msg); + failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND); break; } @@ -1886,14 +1888,14 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) with both accordingly */ conn->cselect_bits = CURL_CSELECT_IN; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } case SSH_SCP_DONE: if(data->set.upload) - state(conn, SSH_SCP_SEND_EOF); + state(data, SSH_SCP_SEND_EOF); else - state(conn, SSH_SCP_CHANNEL_FREE); + state(data, SSH_SCP_CHANNEL_FREE); break; case SSH_SCP_SEND_EOF: @@ -1911,7 +1913,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) } } - state(conn, SSH_SCP_CHANNEL_FREE); + state(data, SSH_SCP_CHANNEL_FREE); break; case SSH_SCP_CHANNEL_FREE: @@ -1923,7 +1925,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) ssh_set_blocking(sshc->ssh_session, 0); - state(conn, SSH_SESSION_DISCONNECT); + state(data, SSH_SESSION_DISCONNECT); /* FALLTHROUGH */ case SSH_SESSION_DISCONNECT: @@ -1938,9 +1940,9 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) ssh_disconnect(sshc->ssh_session); SSH_STRING_FREE_CHAR(sshc->homedir); - conn->data->state.most_recent_ftp_entrypath = NULL; + data->state.most_recent_ftp_entrypath = NULL; - state(conn, SSH_SESSION_FREE); + state(data, SSH_SESSION_FREE); /* FALLTHROUGH */ case SSH_SESSION_FREE: if(sshc->ssh_session) { @@ -1988,7 +1990,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) connclose(conn, "SSH session free"); sshc->state = SSH_SESSION_FREE; /* current */ sshc->nextstate = SSH_NO_STATE; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; case SSH_QUIT: @@ -1996,7 +1998,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) default: /* internal error */ sshc->nextstate = SSH_NO_STATE; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } @@ -2015,10 +2017,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) /* called by the multi interface to figure out what socket(s) to wait for and for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ -static int myssh_perform_getsock(const struct connectdata *conn, - curl_socket_t *sock) +static int myssh_getsock(struct Curl_easy *data, + struct connectdata *conn, + curl_socket_t *sock) { int bitmap = GETSOCK_BLANK; + (void)data; sock[0] = conn->sock[FIRSTSOCKET]; if(conn->waitfor & KEEP_RECV) @@ -2030,16 +2034,6 @@ static int myssh_perform_getsock(const struct connectdata *conn, return bitmap; } -/* Generic function called by the multi interface to figure out what socket(s) - to wait for and for what actions during the DOING and PROTOCONNECT states*/ -static int myssh_getsock(struct connectdata *conn, - curl_socket_t *sock) -{ - /* if we know the direction we can use the generic *_getsock() function even - for the protocol_connect and doing states */ - return myssh_perform_getsock(conn, sock); -} - static void myssh_block2waitfor(struct connectdata *conn, bool block) { struct ssh_conn *sshc = &conn->proto.sshc; @@ -2061,13 +2055,14 @@ static void myssh_block2waitfor(struct connectdata *conn, bool block) } /* called repeatedly until done from multi.c */ -static CURLcode myssh_multi_statemach(struct connectdata *conn, +static CURLcode myssh_multi_statemach(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; bool block; /* we store the status and use that to provide a ssh_getsock() implementation */ - CURLcode result = myssh_statemach_act(conn, &block); + CURLcode result = myssh_statemach_act(data, &block); *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; myssh_block2waitfor(conn, block); @@ -2075,24 +2070,24 @@ static CURLcode myssh_multi_statemach(struct connectdata *conn, return result; } -static CURLcode myssh_block_statemach(struct connectdata *conn, +static CURLcode myssh_block_statemach(struct Curl_easy *data, bool disconnect) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; while((sshc->state != SSH_STOP) && !result) { bool block; timediff_t left = 1000; struct curltime now = Curl_now(); - result = myssh_statemach_act(conn, &block); + result = myssh_statemach_act(data, &block); if(result) break; if(!disconnect) { - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) return CURLE_ABORTED_BY_CALLBACK; result = Curl_speedcheck(data, now); @@ -2121,11 +2116,13 @@ static CURLcode myssh_block_statemach(struct connectdata *conn, /* * SSH setup connection */ -static CURLcode myssh_setup_connection(struct connectdata *conn) +static CURLcode myssh_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { struct SSHPROTO *ssh; + (void)conn; - conn->data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); + data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); if(!ssh) return CURLE_OUT_OF_MEMORY; @@ -2139,17 +2136,17 @@ static Curl_send scp_send, sftp_send; * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to * do protocol-specific actions at connect-time. */ -static CURLcode myssh_connect(struct connectdata *conn, bool *done) +static CURLcode myssh_connect(struct Curl_easy *data, bool *done) { struct ssh_conn *ssh; CURLcode result; + struct connectdata *conn = data->conn; curl_socket_t sock = conn->sock[FIRSTSOCKET]; - struct Curl_easy *data = conn->data; int rc; /* initialize per-handle data if not already */ if(!data->req.p.ssh) - myssh_setup_connection(conn); + myssh_setup_connection(data, conn); /* We default to persistent connections. We set this already in this connect function to make the re-use checks properly be able to check this bit. */ @@ -2242,22 +2239,22 @@ static CURLcode myssh_connect(struct connectdata *conn, bool *done) /* we do not verify here, we do it at the state machine, * after connection */ - state(conn, SSH_INIT); + state(data, SSH_INIT); - result = myssh_multi_statemach(conn, done); + result = myssh_multi_statemach(data, done); return result; } /* called from multi.c while DOing */ -static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done) +static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done) { CURLcode result; - result = myssh_multi_statemach(conn, dophase_done); + result = myssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; } @@ -2272,34 +2269,35 @@ static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done) */ static -CURLcode scp_perform(struct connectdata *conn, +CURLcode scp_perform(struct Curl_easy *data, bool *connected, bool *dophase_done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; - DEBUGF(infof(conn->data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts\n")); *dophase_done = FALSE; /* not done yet */ /* start the first command in the DO phase */ - state(conn, SSH_SCP_TRANS_INIT); + state(data, SSH_SCP_TRANS_INIT); - result = myssh_multi_statemach(conn, dophase_done); + result = myssh_multi_statemach(data, dophase_done); *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; } -static CURLcode myssh_do_it(struct connectdata *conn, bool *done) +static CURLcode myssh_do_it(struct Curl_easy *data, bool *done) { CURLcode result; bool connected = 0; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; *done = FALSE; /* default to false */ @@ -2316,9 +2314,9 @@ static CURLcode myssh_do_it(struct connectdata *conn, bool *done) Curl_pgrsSetDownloadSize(data, -1); if(conn->handler->protocol & CURLPROTO_SCP) - result = scp_perform(conn, &connected, done); + result = scp_perform(data, &connected, done); else - result = sftp_perform(conn, &connected, done); + result = sftp_perform(data, &connected, done); return result; } @@ -2326,7 +2324,8 @@ static CURLcode myssh_do_it(struct connectdata *conn, bool *done) /* BLOCKING, but the function is using the state machine so the only reason this is still blocking is that the multi interface code has no support for disconnecting operations that takes a while */ -static CURLcode scp_disconnect(struct connectdata *conn, +static CURLcode scp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { CURLcode result = CURLE_OK; @@ -2336,9 +2335,9 @@ static CURLcode scp_disconnect(struct connectdata *conn, if(ssh->ssh_session) { /* only if there's a session still around to use! */ - state(conn, SSH_SESSION_DISCONNECT); + state(data, SSH_SESSION_DISCONNECT); - result = myssh_block_statemach(conn, TRUE); + result = myssh_block_statemach(data, TRUE); } return result; @@ -2346,44 +2345,45 @@ static CURLcode scp_disconnect(struct connectdata *conn, /* generic done function for both SCP and SFTP called from their specific done functions */ -static CURLcode myssh_done(struct connectdata *conn, CURLcode status) +static CURLcode myssh_done(struct Curl_easy *data, CURLcode status) { CURLcode result = CURLE_OK; - struct SSHPROTO *protop = conn->data->req.p.ssh; + struct SSHPROTO *protop = data->req.p.ssh; if(!status) { /* run the state-machine */ - result = myssh_block_statemach(conn, FALSE); + result = myssh_block_statemach(data, FALSE); } else result = status; if(protop) Curl_safefree(protop->path); - if(Curl_pgrsDone(conn)) + if(Curl_pgrsDone(data)) return CURLE_ABORTED_BY_CALLBACK; - conn->data->req.keepon = 0; /* clear all bits */ + data->req.keepon = 0; /* clear all bits */ return result; } -static CURLcode scp_done(struct connectdata *conn, CURLcode status, +static CURLcode scp_done(struct Curl_easy *data, CURLcode status, bool premature) { (void) premature; /* not used */ if(!status) - state(conn, SSH_SCP_DONE); + state(data, SSH_SCP_DONE); - return myssh_done(conn, status); + return myssh_done(data, status); } -static ssize_t scp_send(struct connectdata *conn, int sockindex, +static ssize_t scp_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *err) { int rc; + struct connectdata *conn = data->conn; (void) sockindex; /* we only support SCP on the fixed known primary socket */ (void) err; @@ -2409,10 +2409,11 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex, return len; } -static ssize_t scp_recv(struct connectdata *conn, int sockindex, +static ssize_t scp_recv(struct Curl_easy *data, int sockindex, char *mem, size_t len, CURLcode *err) { ssize_t nread; + struct connectdata *conn = data->conn; (void) err; (void) sockindex; /* we only support SCP on the fixed known primary socket */ @@ -2448,38 +2449,39 @@ static ssize_t scp_recv(struct connectdata *conn, int sockindex, */ static -CURLcode sftp_perform(struct connectdata *conn, +CURLcode sftp_perform(struct Curl_easy *data, bool *connected, bool *dophase_done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; - DEBUGF(infof(conn->data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts\n")); *dophase_done = FALSE; /* not done yet */ /* start the first command in the DO phase */ - state(conn, SSH_SFTP_QUOTE_INIT); + state(data, SSH_SFTP_QUOTE_INIT); /* run the state-machine */ - result = myssh_multi_statemach(conn, dophase_done); + result = myssh_multi_statemach(data, dophase_done); *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; } /* called from multi.c while DOing */ -static CURLcode sftp_doing(struct connectdata *conn, +static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done) { - CURLcode result = myssh_multi_statemach(conn, dophase_done); + CURLcode result = myssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; } @@ -2487,46 +2489,50 @@ static CURLcode sftp_doing(struct connectdata *conn, /* BLOCKING, but the function is using the state machine so the only reason this is still blocking is that the multi interface code has no support for disconnecting operations that takes a while */ -static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode sftp_disconnect(struct Curl_easy *data, + struct connectdata *conn, + bool dead_connection) { CURLcode result = CURLE_OK; (void) dead_connection; - DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); + DEBUGF(infof(data, "SSH DISCONNECT starts now\n")); if(conn->proto.sshc.ssh_session) { /* only if there's a session still around to use! */ - state(conn, SSH_SFTP_SHUTDOWN); - result = myssh_block_statemach(conn, TRUE); + state(data, SSH_SFTP_SHUTDOWN); + result = myssh_block_statemach(data, TRUE); } - DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); + DEBUGF(infof(data, "SSH DISCONNECT is done\n")); return result; } -static CURLcode sftp_done(struct connectdata *conn, CURLcode status, - bool premature) +static CURLcode sftp_done(struct Curl_easy *data, CURLcode status, + bool premature) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; if(!status) { /* Post quote commands are executed after the SFTP_CLOSE state to avoid errors that could happen due to open file handles during POSTQUOTE operation */ - if(!premature && conn->data->set.postquote && !conn->bits.retry) + if(!premature && data->set.postquote && !conn->bits.retry) sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); } - return myssh_done(conn, status); + return myssh_done(data, status); } /* return number of sent bytes */ -static ssize_t sftp_send(struct connectdata *conn, int sockindex, +static ssize_t sftp_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *err) { ssize_t nwrite; + struct connectdata *conn = data->conn; (void)sockindex; nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len); @@ -2552,10 +2558,11 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex, * Return number of received (decrypted) bytes * or <0 on error */ -static ssize_t sftp_recv(struct connectdata *conn, int sockindex, +static ssize_t sftp_recv(struct Curl_easy *data, int sockindex, char *mem, size_t len, CURLcode *err) { ssize_t nread; + struct connectdata *conn = data->conn; (void)sockindex; DEBUGASSERT(len < CURL_MAX_READ_SIZE); @@ -2563,8 +2570,8 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex, switch(conn->proto.sshc.sftp_recv_state) { case 0: conn->proto.sshc.sftp_file_index = - sftp_async_read_begin(conn->proto.sshc.sftp_file, - (uint32_t)len); + sftp_async_read_begin(conn->proto.sshc.sftp_file, + (uint32_t)len); if(conn->proto.sshc.sftp_file_index < 0) { *err = CURLE_RECV_ERROR; return -1; @@ -2598,10 +2605,10 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex, } } -static void sftp_quote(struct connectdata *conn) +static void sftp_quote(struct Curl_easy *data) { const char *cp; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SSHPROTO *protop = data->req.p.ssh; struct ssh_conn *sshc = &conn->proto.sshc; CURLcode result; @@ -2628,7 +2635,7 @@ static void sftp_quote(struct connectdata *conn) protop->path); if(!tmp) { sshc->actualcode = CURLE_OUT_OF_MEMORY; - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; return; } @@ -2638,15 +2645,15 @@ static void sftp_quote(struct connectdata *conn) /* this sends an FTP-like "header" to the header callback so that the current directory can be read very similar to how it is read when using ordinary FTP. */ - result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); free(tmp); if(result) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; } else - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); return; } @@ -2657,7 +2664,7 @@ static void sftp_quote(struct connectdata *conn) cp = strchr(cmd, ' '); if(cp == NULL) { failf(data, "Syntax error in SFTP command. Supply parameter(s)!"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; return; @@ -2673,7 +2680,7 @@ static void sftp_quote(struct connectdata *conn) failf(data, "Out of memory"); else failf(data, "Syntax error: Bad first parameter"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; return; @@ -2702,13 +2709,13 @@ static void sftp_quote(struct connectdata *conn) failf(data, "Syntax error in chgrp/chmod/chown/atime/mtime: " "Bad second parameter"); Curl_safefree(sshc->quote_path1); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; return; } sshc->quote_attrs = NULL; - state(conn, SSH_SFTP_QUOTE_STAT); + state(data, SSH_SFTP_QUOTE_STAT); return; } if(strncasecompare(cmd, "ln ", 3) || @@ -2723,17 +2730,17 @@ static void sftp_quote(struct connectdata *conn) else failf(data, "Syntax error in ln/symlink: Bad second parameter"); Curl_safefree(sshc->quote_path1); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; return; } - state(conn, SSH_SFTP_QUOTE_SYMLINK); + state(data, SSH_SFTP_QUOTE_SYMLINK); return; } else if(strncasecompare(cmd, "mkdir ", 6)) { /* create dir */ - state(conn, SSH_SFTP_QUOTE_MKDIR); + state(data, SSH_SFTP_QUOTE_MKDIR); return; } else if(strncasecompare(cmd, "rename ", 7)) { @@ -2747,26 +2754,26 @@ static void sftp_quote(struct connectdata *conn) else failf(data, "Syntax error in rename: Bad second parameter"); Curl_safefree(sshc->quote_path1); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; return; } - state(conn, SSH_SFTP_QUOTE_RENAME); + state(data, SSH_SFTP_QUOTE_RENAME); return; } else if(strncasecompare(cmd, "rmdir ", 6)) { /* delete dir */ - state(conn, SSH_SFTP_QUOTE_RMDIR); + state(data, SSH_SFTP_QUOTE_RMDIR); return; } else if(strncasecompare(cmd, "rm ", 3)) { - state(conn, SSH_SFTP_QUOTE_UNLINK); + state(data, SSH_SFTP_QUOTE_UNLINK); return; } #ifdef HAS_STATVFS_SUPPORT else if(strncasecompare(cmd, "statvfs ", 8)) { - state(conn, SSH_SFTP_QUOTE_STATVFS); + state(data, SSH_SFTP_QUOTE_STATVFS); return; } #endif @@ -2774,14 +2781,14 @@ static void sftp_quote(struct connectdata *conn) failf(data, "Unknown SFTP command"); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; } -static void sftp_quote_stat(struct connectdata *conn) +static void sftp_quote_stat(struct Curl_easy *data) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; char *cmd = sshc->quote_item->data; sshc->acceptfail = FALSE; @@ -2809,7 +2816,7 @@ static void sftp_quote_stat(struct connectdata *conn) Curl_safefree(sshc->quote_path2); failf(data, "Attempt to get SFTP stats failed: %d", sftp_get_error(sshc->sftp_session)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; return; @@ -2823,7 +2830,7 @@ static void sftp_quote_stat(struct connectdata *conn) Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Syntax error: chgrp gid not a number"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; return; @@ -2838,7 +2845,7 @@ static void sftp_quote_stat(struct connectdata *conn) Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Syntax error: chmod permissions not a number"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; return; @@ -2853,7 +2860,7 @@ static void sftp_quote_stat(struct connectdata *conn) Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Syntax error: chown uid not a number"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; return; @@ -2866,7 +2873,7 @@ static void sftp_quote_stat(struct connectdata *conn) Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Syntax error: incorrect access date format"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; return; @@ -2880,7 +2887,7 @@ static void sftp_quote_stat(struct connectdata *conn) Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Syntax error: incorrect modification date format"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; return; @@ -2890,7 +2897,7 @@ static void sftp_quote_stat(struct connectdata *conn) } /* Now send the completed structure... */ - state(conn, SSH_SFTP_QUOTE_SETSTAT); + state(data, SSH_SFTP_QUOTE_SETSTAT); return; } diff --git a/libs/libcurl/src/vssh/libssh2.c b/libs/libcurl/src/vssh/libssh2.c index a69bcda995..3130dcc74d 100644 --- a/libs/libcurl/src/vssh/libssh2.c +++ b/libs/libcurl/src/vssh/libssh2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -103,30 +103,24 @@ static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc); static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc); static LIBSSH2_FREE_FUNC(my_libssh2_free); -static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn); -static CURLcode ssh_connect(struct connectdata *conn, bool *done); -static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done); -static CURLcode ssh_do(struct connectdata *conn, bool *done); - -static CURLcode scp_done(struct connectdata *conn, - CURLcode, bool premature); -static CURLcode scp_doing(struct connectdata *conn, - bool *dophase_done); -static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection); - -static CURLcode sftp_done(struct connectdata *conn, - CURLcode, bool premature); -static CURLcode sftp_doing(struct connectdata *conn, - bool *dophase_done); -static CURLcode sftp_disconnect(struct connectdata *conn, bool dead); -static -CURLcode sftp_perform(struct connectdata *conn, - bool *connected, - bool *dophase_done); -static int ssh_getsock(struct connectdata *conn, curl_socket_t *sock); -static int ssh_perform_getsock(const struct connectdata *conn, - curl_socket_t *sock); -static CURLcode ssh_setup_connection(struct connectdata *conn); +static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data); +static CURLcode ssh_connect(struct Curl_easy *data, bool *done); +static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done); +static CURLcode ssh_do(struct Curl_easy *data, bool *done); +static CURLcode scp_done(struct Curl_easy *data, CURLcode c, bool premature); +static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done); +static CURLcode scp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection); +static CURLcode sftp_done(struct Curl_easy *data, CURLcode, bool premature); +static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done); +static CURLcode sftp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); +static CURLcode sftp_perform(struct Curl_easy *data, bool *connected, + bool *dophase_done); +static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t *sock); +static CURLcode ssh_setup_connection(struct Curl_easy *data, + struct connectdata *conn); /* * SCP protocol handler. @@ -144,7 +138,7 @@ const struct Curl_handler Curl_handler_scp = { ssh_getsock, /* proto_getsock */ ssh_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - ssh_perform_getsock, /* perform_getsock */ + ssh_getsock, /* perform_getsock */ scp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ @@ -172,7 +166,7 @@ const struct Curl_handler Curl_handler_sftp = { ssh_getsock, /* proto_getsock */ ssh_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - ssh_perform_getsock, /* perform_getsock */ + ssh_getsock, /* perform_getsock */ sftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ @@ -308,8 +302,9 @@ static LIBSSH2_FREE_FUNC(my_libssh2_free) * SSH State machine related code */ /* This is the ONLY way to change SSH state! */ -static void state(struct connectdata *conn, sshstate nowstate) +static void state(struct Curl_easy *data, sshstate nowstate) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* for debug purposes */ @@ -380,7 +375,7 @@ static void state(struct connectdata *conn, sshstate nowstate) DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST); if(sshc->state != nowstate) { - infof(conn->data, "SFTP %p state change from %s to %s\n", + infof(data, "SFTP %p state change from %s to %s\n", (void *)sshc, names[sshc->state], names[nowstate]); } #endif @@ -434,15 +429,14 @@ static int sshkeycallback(struct Curl_easy *easy, #define libssh2_session_startup(x,y) libssh2_session_handshake(x,y) #endif -static CURLcode ssh_knownhost(struct connectdata *conn) +static CURLcode ssh_knownhost(struct Curl_easy *data) { CURLcode result = CURLE_OK; #ifdef HAVE_LIBSSH2_KNOWNHOST_API - struct Curl_easy *data = conn->data; - if(data->set.str[STRING_SSH_KNOWNHOSTS]) { /* we're asked to verify the host against a file */ + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; struct libssh2_knownhost *host = NULL; int rc; @@ -564,7 +558,7 @@ static CURLcode ssh_knownhost(struct connectdata *conn) default: /* unknown return codes will equal reject */ /* FALLTHROUGH */ case CURLKHSTAT_REJECT: - state(conn, SSH_SESSION_FREE); + state(data, SSH_SESSION_FREE); /* FALLTHROUGH */ case CURLKHSTAT_DEFER: /* DEFER means bail out but keep the SSH_HOSTKEY state */ @@ -609,15 +603,15 @@ static CURLcode ssh_knownhost(struct connectdata *conn) } } #else /* HAVE_LIBSSH2_KNOWNHOST_API */ - (void)conn; + (void)data; #endif return result; } -static CURLcode ssh_check_fingerprint(struct connectdata *conn) +static CURLcode ssh_check_fingerprint(struct Curl_easy *data) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; - struct Curl_easy *data = conn->data; const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]; char md5buffer[33]; @@ -644,7 +638,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn) else failf(data, "Denied establishing ssh session: md5 fingerprint not available"); - state(conn, SSH_SESSION_FREE); + state(data, SSH_SESSION_FREE); sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; return sshc->actualcode; } @@ -652,14 +646,14 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn) /* as we already matched, we skip the check for known hosts */ return CURLE_OK; } - return ssh_knownhost(conn); + return ssh_knownhost(data); } /* * ssh_force_knownhost_key_type() will check the known hosts file and try to * force a specific public key type from the server if an entry is found. */ -static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn) +static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data) { CURLcode result = CURLE_OK; @@ -687,8 +681,8 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn) = "ssh-dss"; const char *hostkey_method = NULL; + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; - struct Curl_easy *data = conn->data; struct libssh2_knownhost* store = NULL; const char *kh_name_end = NULL; size_t kh_name_size = 0; @@ -763,18 +757,18 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn) hostkey_method = hostkey_method_ssh_dss; break; case LIBSSH2_KNOWNHOST_KEY_RSA1: - failf(data, "Found host key type RSA1 which is not supported\n"); + failf(data, "Found host key type RSA1 which is not supported"); return CURLE_SSH; default: - failf(data, "Unknown host key type: %i\n", + failf(data, "Unknown host key type: %i", (store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK)); return CURLE_SSH; } infof(data, "Set \"%s\" as SSH hostkey type\n", hostkey_method); result = libssh2_session_error_to_CURLE( - libssh2_session_method_pref( - sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method)); + libssh2_session_method_pref( + sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method)); } else { infof(data, "Did not find host %s in %s\n", @@ -794,11 +788,11 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn) * meaning it wants to be called again when the socket is ready */ -static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) +static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - struct SSHPROTO *sftp_scp = data->req.p.ssh; + struct connectdata *conn = data->conn; + struct SSHPROTO *sshp = data->req.p.ssh; struct ssh_conn *sshc = &conn->proto.sshc; curl_socket_t sock = conn->sock[FIRSTSOCKET]; int rc = LIBSSH2_ERROR_NONE; @@ -809,7 +803,6 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) *block = 0; /* we're not blocking by default */ do { - switch(sshc->state) { case SSH_INIT: sshc->secondCreateDirs = 0; @@ -820,14 +813,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) non-blocking */ libssh2_session_set_blocking(sshc->ssh_session, 0); - result = ssh_force_knownhost_key_type(conn); + result = ssh_force_knownhost_key_type(data); if(result) { - state(conn, SSH_SESSION_FREE); + state(data, SSH_SESSION_FREE); sshc->actualcode = result; break; } - state(conn, SSH_S_STARTUP); + state(data, SSH_S_STARTUP); /* FALLTHROUGH */ case SSH_S_STARTUP: @@ -840,12 +833,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg); - state(conn, SSH_SESSION_FREE); + state(data, SSH_SESSION_FREE); sshc->actualcode = CURLE_FAILED_INIT; break; } - state(conn, SSH_HOSTKEY); + state(data, SSH_HOSTKEY); /* FALLTHROUGH */ case SSH_HOSTKEY: @@ -854,9 +847,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) * against our known hosts. How that is handled (reading from file, * whatever) is up to us. */ - result = ssh_check_fingerprint(conn); + result = ssh_check_fingerprint(data); if(!result) - state(conn, SSH_AUTHLIST); + state(data, SSH_AUTHLIST); /* ssh_check_fingerprint sets state appropriately on error */ break; @@ -879,14 +872,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(libssh2_userauth_authenticated(sshc->ssh_session)) { sshc->authed = TRUE; infof(data, "SSH user accepted with no authentication\n"); - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); break; } ssherr = libssh2_session_last_errno(sshc->ssh_session); if(ssherr == LIBSSH2_ERROR_EAGAIN) rc = LIBSSH2_ERROR_EAGAIN; else { - state(conn, SSH_SESSION_FREE); + state(data, SSH_SESSION_FREE); sshc->actualcode = libssh2_session_error_to_CURLE(ssherr); } break; @@ -894,7 +887,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) infof(data, "SSH authentication methods available: %s\n", sshc->authlist); - state(conn, SSH_AUTH_PKEY_INIT); + state(data, SSH_AUTH_PKEY_INIT); break; case SSH_AUTH_PKEY_INIT: @@ -966,7 +959,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(out_of_memory || sshc->rsa == NULL) { Curl_safefree(sshc->rsa); Curl_safefree(sshc->rsa_pub); - state(conn, SSH_SESSION_FREE); + state(data, SSH_SESSION_FREE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } @@ -979,10 +972,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub); infof(data, "Using SSH private key file '%s'\n", sshc->rsa); - state(conn, SSH_AUTH_PKEY); + state(data, SSH_AUTH_PKEY); } else { - state(conn, SSH_AUTH_PASS_INIT); + state(data, SSH_AUTH_PASS_INIT); } break; @@ -1005,14 +998,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == 0) { sshc->authed = TRUE; infof(data, "Initialized SSH public key authentication\n"); - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); } else { char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); infof(data, "SSH public key authentication failed: %s\n", err_msg); - state(conn, SSH_AUTH_PASS_INIT); + state(data, SSH_AUTH_PASS_INIT); rc = 0; /* clear rc and continue */ } break; @@ -1020,10 +1013,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) case SSH_AUTH_PASS_INIT: if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) && (strstr(sshc->authlist, "password") != NULL)) { - state(conn, SSH_AUTH_PASS); + state(data, SSH_AUTH_PASS); } else { - state(conn, SSH_AUTH_HOST_INIT); + state(data, SSH_AUTH_HOST_INIT); rc = 0; /* clear rc and continue */ } break; @@ -1040,10 +1033,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == 0) { sshc->authed = TRUE; infof(data, "Initialized password authentication\n"); - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); } else { - state(conn, SSH_AUTH_HOST_INIT); + state(data, SSH_AUTH_HOST_INIT); rc = 0; /* clear rc and continue */ } break; @@ -1051,15 +1044,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) case SSH_AUTH_HOST_INIT: if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) && (strstr(sshc->authlist, "hostbased") != NULL)) { - state(conn, SSH_AUTH_HOST); + state(data, SSH_AUTH_HOST); } else { - state(conn, SSH_AUTH_AGENT_INIT); + state(data, SSH_AUTH_AGENT_INIT); } break; case SSH_AUTH_HOST: - state(conn, SSH_AUTH_AGENT_INIT); + state(data, SSH_AUTH_AGENT_INIT); break; case SSH_AUTH_AGENT_INIT: @@ -1075,7 +1068,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(!sshc->ssh_agent) { infof(data, "Could not create agent object\n"); - state(conn, SSH_AUTH_KEY_INIT); + state(data, SSH_AUTH_KEY_INIT); break; } } @@ -1085,16 +1078,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) break; if(rc < 0) { infof(data, "Failure connecting to agent\n"); - state(conn, SSH_AUTH_KEY_INIT); + state(data, SSH_AUTH_KEY_INIT); rc = 0; /* clear rc and continue */ } else { - state(conn, SSH_AUTH_AGENT_LIST); + state(data, SSH_AUTH_AGENT_LIST); } } else #endif /* HAVE_LIBSSH2_AGENT_API */ - state(conn, SSH_AUTH_KEY_INIT); + state(data, SSH_AUTH_KEY_INIT); break; case SSH_AUTH_AGENT_LIST: @@ -1105,11 +1098,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) break; if(rc < 0) { infof(data, "Failure requesting identities to agent\n"); - state(conn, SSH_AUTH_KEY_INIT); + state(data, SSH_AUTH_KEY_INIT); rc = 0; /* clear rc and continue */ } else { - state(conn, SSH_AUTH_AGENT); + state(data, SSH_AUTH_AGENT); sshc->sshagent_prev_identity = NULL; } #endif @@ -1147,10 +1140,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_NONE) { sshc->authed = TRUE; infof(data, "Agent based authentication successful\n"); - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); } else { - state(conn, SSH_AUTH_KEY_INIT); + state(data, SSH_AUTH_KEY_INIT); rc = 0; /* clear rc and continue */ } #endif @@ -1159,10 +1152,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) case SSH_AUTH_KEY_INIT: if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { - state(conn, SSH_AUTH_KEY); + state(data, SSH_AUTH_KEY); } else { - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); } break; @@ -1180,13 +1173,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) sshc->authed = TRUE; infof(data, "Initialized keyboard interactive authentication\n"); } - state(conn, SSH_AUTH_DONE); + state(data, SSH_AUTH_DONE); break; case SSH_AUTH_DONE: if(!sshc->authed) { failf(data, "Authentication failure"); - state(conn, SSH_SESSION_FREE); + state(data, SSH_SESSION_FREE); sshc->actualcode = CURLE_LOGIN_DENIED; break; } @@ -1196,17 +1189,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) */ infof(data, "Authentication complete\n"); - Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */ + Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */ conn->sockfd = sock; conn->writesockfd = CURL_SOCKET_BAD; if(conn->handler->protocol == CURLPROTO_SFTP) { - state(conn, SSH_SFTP_INIT); + state(data, SSH_SFTP_INIT); break; } infof(data, "SSH CONNECT phase done\n"); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; case SSH_SFTP_INIT: @@ -1225,11 +1218,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); failf(data, "Failure initializing sftp session: %s", err_msg); - state(conn, SSH_SESSION_FREE); + state(data, SSH_SESSION_FREE); sshc->actualcode = CURLE_FAILED_INIT; break; } - state(conn, SSH_SFTP_REALPATH); + state(data, SSH_SFTP_REALPATH); break; case SSH_SFTP_REALPATH: @@ -1249,11 +1242,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) tempHome[rc] = '\0'; sshc->homedir = strdup(tempHome); if(!sshc->homedir) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } - conn->data->state.most_recent_ftp_entrypath = sshc->homedir; + data->state.most_recent_ftp_entrypath = sshc->homedir; } else { /* Return the error type */ @@ -1267,7 +1260,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) sshc->actualcode = result; DEBUGF(infof(data, "error = %lu makes libcurl = %d\n", sftperr, (int)result)); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } } @@ -1276,25 +1269,25 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) since the homedir will remain the same between request but the working path will not. */ DEBUGF(infof(data, "SSH CONNECT phase done\n")); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; case SSH_SFTP_QUOTE_INIT: - result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path); + result = Curl_getworkingpath(data, sshc->homedir, &sshp->path); if(result) { sshc->actualcode = result; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } if(data->set.quote) { infof(data, "Sending quote commands\n"); sshc->quote_item = data->set.quote; - state(conn, SSH_SFTP_QUOTE); + state(data, SSH_SFTP_QUOTE); } else { - state(conn, SSH_SFTP_GETINFO); + state(data, SSH_SFTP_GETINFO); } break; @@ -1302,10 +1295,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(data->set.postquote) { infof(data, "Sending quote commands\n"); sshc->quote_item = data->set.postquote; - state(conn, SSH_SFTP_QUOTE); + state(data, SSH_SFTP_QUOTE); } else { - state(conn, SSH_STOP); + state(data, SSH_STOP); } break; @@ -1336,10 +1329,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(strcasecompare("pwd", cmd)) { /* output debug output if that is requested */ char *tmp = aprintf("257 \"%s\" is current directory.\n", - sftp_scp->path); + sshp->path); if(!tmp) { result = CURLE_OUT_OF_MEMORY; - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; break; } @@ -1349,15 +1342,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* this sends an FTP-like "header" to the header callback so that the current directory can be read very similar to how it is read when using ordinary FTP. */ - result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); free(tmp); if(result) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; } else - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; } { @@ -1369,7 +1362,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(cp == NULL) { failf(data, "Syntax error command '%s'. Missing parameter!", cmd); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; @@ -1385,7 +1378,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) failf(data, "Out of memory"); else failf(data, "Syntax error: Bad first parameter to '%s'", cmd); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; break; @@ -1413,13 +1406,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) else failf(data, "Syntax error in %s: Bad second parameter", cmd); Curl_safefree(sshc->quote_path1); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; break; } - memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - state(conn, SSH_SFTP_QUOTE_STAT); + memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); + state(data, SSH_SFTP_QUOTE_STAT); break; } if(strncasecompare(cmd, "ln ", 3) || @@ -1435,17 +1428,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) failf(data, "Syntax error in ln/symlink: Bad second parameter"); Curl_safefree(sshc->quote_path1); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; break; } - state(conn, SSH_SFTP_QUOTE_SYMLINK); + state(data, SSH_SFTP_QUOTE_SYMLINK); break; } else if(strncasecompare(cmd, "mkdir ", 6)) { /* create dir */ - state(conn, SSH_SFTP_QUOTE_MKDIR); + state(data, SSH_SFTP_QUOTE_MKDIR); break; } else if(strncasecompare(cmd, "rename ", 7)) { @@ -1459,26 +1452,26 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) else failf(data, "Syntax error in rename: Bad second parameter"); Curl_safefree(sshc->quote_path1); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; break; } - state(conn, SSH_SFTP_QUOTE_RENAME); + state(data, SSH_SFTP_QUOTE_RENAME); break; } else if(strncasecompare(cmd, "rmdir ", 6)) { /* delete dir */ - state(conn, SSH_SFTP_QUOTE_RMDIR); + state(data, SSH_SFTP_QUOTE_RMDIR); break; } else if(strncasecompare(cmd, "rm ", 3)) { - state(conn, SSH_SFTP_QUOTE_UNLINK); + state(data, SSH_SFTP_QUOTE_UNLINK); break; } #ifdef HAS_STATVFS_SUPPORT else if(strncasecompare(cmd, "statvfs ", 8)) { - state(conn, SSH_SFTP_QUOTE_STATVFS); + state(data, SSH_SFTP_QUOTE_STATVFS); break; } #endif @@ -1486,7 +1479,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) failf(data, "Unknown SFTP command"); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; @@ -1501,15 +1494,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) sshc->quote_item = sshc->quote_item->next; if(sshc->quote_item) { - state(conn, SSH_SFTP_QUOTE); + state(data, SSH_SFTP_QUOTE); } else { if(sshc->nextstate != SSH_NO_STATE) { - state(conn, sshc->nextstate); + state(data, sshc->nextstate); sshc->nextstate = SSH_NO_STATE; } else { - state(conn, SSH_SFTP_GETINFO); + state(data, SSH_SFTP_GETINFO); } } break; @@ -1537,7 +1530,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, curlx_uztoui(strlen(sshc->quote_path2)), LIBSSH2_SFTP_STAT, - &sshc->quote_attrs); + &sshp->quote_attrs); if(rc == LIBSSH2_ERROR_EAGAIN) { break; } @@ -1547,7 +1540,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path2); failf(data, "Attempt to get SFTP stats failed: %s", sftp_libssh2_strerror(sftperr)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; @@ -1556,43 +1549,43 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* Now set the new attributes... */ if(strncasecompare(cmd, "chgrp", 5)) { - sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10); - sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; - if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10); + sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; + if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Syntax error: chgrp gid not a number"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } } else if(strncasecompare(cmd, "chmod", 5)) { - sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8); - sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS; + sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8); + sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS; /* permissions are octal */ - if(sshc->quote_attrs.permissions == 0 && + if(sshp->quote_attrs.permissions == 0 && !ISDIGIT(sshc->quote_path1[0])) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Syntax error: chmod permissions not a number"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } } else if(strncasecompare(cmd, "chown", 5)) { - sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10); - sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; - if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10); + sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; + if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Syntax error: chown uid not a number"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; @@ -1604,13 +1597,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Syntax error: incorrect access date format"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - sshc->quote_attrs.atime = (unsigned long)date; - sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME; + sshp->quote_attrs.atime = (unsigned long)date; + sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME; } else if(strncasecompare(cmd, "mtime", 5)) { time_t date = Curl_getdate_capped(sshc->quote_path1); @@ -1618,17 +1611,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Syntax error: incorrect modification date format"); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - sshc->quote_attrs.mtime = (unsigned long)date; - sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME; + sshp->quote_attrs.mtime = (unsigned long)date; + sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME; } /* Now send the completed structure... */ - state(conn, SSH_SFTP_QUOTE_SETSTAT); + state(data, SSH_SFTP_QUOTE_SETSTAT); break; } @@ -1636,7 +1629,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, curlx_uztoui(strlen(sshc->quote_path2)), LIBSSH2_SFTP_SETSTAT, - &sshc->quote_attrs); + &sshp->quote_attrs); if(rc == LIBSSH2_ERROR_EAGAIN) { break; } @@ -1646,12 +1639,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path2); failf(data, "Attempt to set SFTP stats failed: %s", sftp_libssh2_strerror(sftperr)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_SYMLINK: @@ -1669,12 +1662,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path2); failf(data, "symlink command failed: %s", sftp_libssh2_strerror(sftperr)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_MKDIR: @@ -1689,12 +1682,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path1); failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(sftperr)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_RENAME: @@ -1715,12 +1708,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path2); failf(data, "rename command failed: %s", sftp_libssh2_strerror(sftperr)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_RMDIR: @@ -1734,12 +1727,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path1); failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(sftperr)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; case SSH_SFTP_QUOTE_UNLINK: @@ -1752,12 +1745,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; #ifdef HAS_STATVFS_SUPPORT @@ -1776,7 +1769,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path1); failf(data, "statvfs command failed: %s", sftp_libssh2_strerror(sftperr)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; @@ -1797,30 +1790,30 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) statvfs.f_namemax); if(!tmp) { result = CURLE_OUT_OF_MEMORY; - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; break; } - result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); free(tmp); if(result) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = result; } } - state(conn, SSH_SFTP_NEXT_QUOTE); + state(data, SSH_SFTP_NEXT_QUOTE); break; } #endif case SSH_SFTP_GETINFO: { if(data->set.get_filetime) { - state(conn, SSH_SFTP_FILETIME); + state(data, SSH_SFTP_FILETIME); } else { - state(conn, SSH_SFTP_TRANS_INIT); + state(data, SSH_SFTP_TRANS_INIT); } break; } @@ -1829,8 +1822,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) { LIBSSH2_SFTP_ATTRIBUTES attrs; - rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, - curlx_uztoui(strlen(sftp_scp->path)), + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, + curlx_uztoui(strlen(sshp->path)), LIBSSH2_SFTP_STAT, &attrs); if(rc == LIBSSH2_ERROR_EAGAIN) { break; @@ -1839,18 +1832,18 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) data->info.filetime = attrs.mtime; } - state(conn, SSH_SFTP_TRANS_INIT); + state(data, SSH_SFTP_TRANS_INIT); break; } case SSH_SFTP_TRANS_INIT: if(data->set.upload) - state(conn, SSH_SFTP_UPLOAD_INIT); + state(data, SSH_SFTP_UPLOAD_INIT); else { - if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') - state(conn, SSH_SFTP_READDIR_INIT); + if(sshp->path[strlen(sshp->path)-1] == '/') + state(data, SSH_SFTP_READDIR_INIT); else - state(conn, SSH_SFTP_DOWNLOAD_INIT); + state(data, SSH_SFTP_DOWNLOAD_INIT); } break; @@ -1867,8 +1860,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(data->state.resume_from != 0) { LIBSSH2_SFTP_ATTRIBUTES attrs; if(data->state.resume_from < 0) { - rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, - curlx_uztoui(strlen(sftp_scp->path)), + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, + curlx_uztoui(strlen(sshp->path)), LIBSSH2_SFTP_STAT, &attrs); if(rc == LIBSSH2_ERROR_EAGAIN) { break; @@ -1894,12 +1887,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* If we have restart position then open for append */ flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND; else - /* Clear file before writing (normal behaviour) */ + /* Clear file before writing (normal behavior) */ flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC; sshc->sftp_handle = - libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, - curlx_uztoui(strlen(sftp_scp->path)), + libssh2_sftp_open_ex(sshc->sftp_session, sshp->path, + curlx_uztoui(strlen(sshp->path)), flags, data->set.new_file_perms, LIBSSH2_SFTP_OPENFILE); @@ -1917,7 +1910,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */ if(sshc->secondCreateDirs) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = sftperr != LIBSSH2_FX_OK ? sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH; failf(data, "Creating the dir/file failed: %s", @@ -1928,14 +1921,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) (sftperr == LIBSSH2_FX_FAILURE) || (sftperr == LIBSSH2_FX_NO_SUCH_PATH)) && (data->set.ftp_create_missing_dirs && - (strlen(sftp_scp->path) > 1))) { + (strlen(sshp->path) > 1))) { /* try to create the path remotely */ rc = 0; /* clear rc and continue */ sshc->secondCreateDirs = 1; - state(conn, SSH_SFTP_CREATE_DIRS_INIT); + state(data, SSH_SFTP_CREATE_DIRS_INIT); break; } - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = sftperr != LIBSSH2_FX_OK ? sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH; if(!sshc->actualcode) { @@ -2014,7 +2007,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) conn->sockfd = conn->writesockfd; if(result) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = result; } else { @@ -2032,18 +2025,18 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) timeout here */ Curl_expire(data, 0, EXPIRE_RUN_NOW); - state(conn, SSH_STOP); + state(data, SSH_STOP); } break; } case SSH_SFTP_CREATE_DIRS_INIT: - if(strlen(sftp_scp->path) > 1) { - sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */ - state(conn, SSH_SFTP_CREATE_DIRS); + if(strlen(sshp->path) > 1) { + sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */ + state(data, SSH_SFTP_CREATE_DIRS); } else { - state(conn, SSH_SFTP_UPLOAD_INIT); + state(data, SSH_SFTP_UPLOAD_INIT); } break; @@ -2052,17 +2045,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(sshc->slash_pos) { *sshc->slash_pos = 0; - infof(data, "Creating directory '%s'\n", sftp_scp->path); - state(conn, SSH_SFTP_CREATE_DIRS_MKDIR); + infof(data, "Creating directory '%s'\n", sshp->path); + state(data, SSH_SFTP_CREATE_DIRS_MKDIR); break; } - state(conn, SSH_SFTP_UPLOAD_INIT); + state(data, SSH_SFTP_UPLOAD_INIT); break; case SSH_SFTP_CREATE_DIRS_MKDIR: /* 'mode' - parameter is preliminary - default to 0644 */ - rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path, - curlx_uztoui(strlen(sftp_scp->path)), + rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path, + curlx_uztoui(strlen(sshp->path)), data->set.new_directory_perms); if(rc == LIBSSH2_ERROR_EAGAIN) { break; @@ -2080,19 +2073,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) (sftperr != LIBSSH2_FX_FAILURE) && (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) { result = sftp_libssh2_error_to_CURLE(sftperr); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = result?result:CURLE_SSH; break; } rc = 0; /* clear rc and continue */ } - state(conn, SSH_SFTP_CREATE_DIRS); + state(data, SSH_SFTP_CREATE_DIRS); break; case SSH_SFTP_READDIR_INIT: Curl_pgrsSetDownloadSize(data, -1); if(data->set.opt_no_body) { - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } @@ -2101,9 +2094,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) * listing */ sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session, - sftp_scp->path, + sshp->path, curlx_uztoui( - strlen(sftp_scp->path)), + strlen(sshp->path)), 0, 0, LIBSSH2_SFTP_OPENDIR); if(!sshc->sftp_handle) { if(libssh2_session_last_errno(sshc->ssh_session) == @@ -2114,51 +2107,51 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) sftperr = libssh2_sftp_last_error(sshc->sftp_session); failf(data, "Could not open directory for reading: %s", sftp_libssh2_strerror(sftperr)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); result = sftp_libssh2_error_to_CURLE(sftperr); sshc->actualcode = result?result:CURLE_SSH; break; } - sshc->readdir_filename = malloc(PATH_MAX + 1); - if(!sshc->readdir_filename) { - state(conn, SSH_SFTP_CLOSE); + sshp->readdir_filename = malloc(PATH_MAX + 1); + if(!sshp->readdir_filename) { + state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } - sshc->readdir_longentry = malloc(PATH_MAX + 1); - if(!sshc->readdir_longentry) { - Curl_safefree(sshc->readdir_filename); - state(conn, SSH_SFTP_CLOSE); + sshp->readdir_longentry = malloc(PATH_MAX + 1); + if(!sshp->readdir_longentry) { + Curl_safefree(sshp->readdir_filename); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } - Curl_dyn_init(&sshc->readdir, PATH_MAX * 2); - state(conn, SSH_SFTP_READDIR); + Curl_dyn_init(&sshp->readdir, PATH_MAX * 2); + state(data, SSH_SFTP_READDIR); break; case SSH_SFTP_READDIR: rc = libssh2_sftp_readdir_ex(sshc->sftp_handle, - sshc->readdir_filename, + sshp->readdir_filename, PATH_MAX, - sshc->readdir_longentry, + sshp->readdir_longentry, PATH_MAX, - &sshc->readdir_attrs); + &sshp->readdir_attrs); if(rc == LIBSSH2_ERROR_EAGAIN) { break; } if(rc > 0) { readdir_len = (size_t) rc; - sshc->readdir_filename[readdir_len] = '\0'; + sshp->readdir_filename[readdir_len] = '\0'; if(data->set.ftp_list_only) { - result = Curl_client_write(conn, CLIENTWRITE_BODY, - sshc->readdir_filename, + result = Curl_client_write(data, CLIENTWRITE_BODY, + sshp->readdir_filename, readdir_len); if(!result) - result = Curl_client_write(conn, CLIENTWRITE_BODY, + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(result) { - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } /* since this counts what we send to the client, we include the @@ -2166,37 +2159,37 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) data->req.bytecount += readdir_len + 1; /* output debug output if that is requested */ - Curl_debug(data, CURLINFO_DATA_IN, sshc->readdir_filename, + Curl_debug(data, CURLINFO_DATA_IN, sshp->readdir_filename, readdir_len); Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1); } else { - result = Curl_dyn_add(&sshc->readdir, sshc->readdir_longentry); + result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry); if(!result) { - if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && - ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) == + if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && + ((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFLNK)) { - Curl_dyn_init(&sshc->readdir_link, PATH_MAX); - result = Curl_dyn_add(&sshc->readdir_link, sftp_scp->path); - state(conn, SSH_SFTP_READDIR_LINK); + Curl_dyn_init(&sshp->readdir_link, PATH_MAX); + result = Curl_dyn_add(&sshp->readdir_link, sshp->path); + state(data, SSH_SFTP_READDIR_LINK); if(!result) break; } else { - state(conn, SSH_SFTP_READDIR_BOTTOM); + state(data, SSH_SFTP_READDIR_BOTTOM); break; } } sshc->actualcode = result; - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); break; } } else if(rc == 0) { - Curl_safefree(sshc->readdir_filename); - Curl_safefree(sshc->readdir_longentry); - state(conn, SSH_SFTP_READDIR_DONE); + Curl_safefree(sshp->readdir_filename); + Curl_safefree(sshp->readdir_longentry); + state(data, SSH_SFTP_READDIR_DONE); break; } else if(rc < 0) { @@ -2206,9 +2199,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) failf(data, "Could not open remote file for reading: %s :: %d", sftp_libssh2_strerror(sftperr), libssh2_session_last_errno(sshc->ssh_session)); - Curl_safefree(sshc->readdir_filename); - Curl_safefree(sshc->readdir_longentry); - state(conn, SSH_SFTP_CLOSE); + Curl_safefree(sshp->readdir_filename); + Curl_safefree(sshp->readdir_longentry); + state(data, SSH_SFTP_CLOSE); break; } break; @@ -2216,52 +2209,51 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) case SSH_SFTP_READDIR_LINK: rc = libssh2_sftp_symlink_ex(sshc->sftp_session, - Curl_dyn_ptr(&sshc->readdir_link), - (int)Curl_dyn_len(&sshc->readdir_link), - sshc->readdir_filename, + Curl_dyn_ptr(&sshp->readdir_link), + (int)Curl_dyn_len(&sshp->readdir_link), + sshp->readdir_filename, PATH_MAX, LIBSSH2_SFTP_READLINK); if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - readdir_len = (size_t) rc; - Curl_dyn_free(&sshc->readdir_link); + Curl_dyn_free(&sshp->readdir_link); /* append filename and extra output */ - result = Curl_dyn_addf(&sshc->readdir, " -> %s", sshc->readdir_filename); + result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename); if(result) { sshc->readdir_line = NULL; - Curl_safefree(sshc->readdir_filename); - Curl_safefree(sshc->readdir_longentry); - state(conn, SSH_SFTP_CLOSE); + Curl_safefree(sshp->readdir_filename); + Curl_safefree(sshp->readdir_longentry); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = result; break; } - state(conn, SSH_SFTP_READDIR_BOTTOM); + state(data, SSH_SFTP_READDIR_BOTTOM); break; case SSH_SFTP_READDIR_BOTTOM: - result = Curl_dyn_addn(&sshc->readdir, "\n", 1); + result = Curl_dyn_addn(&sshp->readdir, "\n", 1); if(!result) - result = Curl_client_write(conn, CLIENTWRITE_BODY, - Curl_dyn_ptr(&sshc->readdir), - Curl_dyn_len(&sshc->readdir)); + result = Curl_client_write(data, CLIENTWRITE_BODY, + Curl_dyn_ptr(&sshp->readdir), + Curl_dyn_len(&sshp->readdir)); if(!result) { /* output debug output if that is requested */ Curl_debug(data, CURLINFO_DATA_IN, - Curl_dyn_ptr(&sshc->readdir), - Curl_dyn_len(&sshc->readdir)); - data->req.bytecount += Curl_dyn_len(&sshc->readdir); + Curl_dyn_ptr(&sshp->readdir), + Curl_dyn_len(&sshp->readdir)); + data->req.bytecount += Curl_dyn_len(&sshp->readdir); } if(result) { - Curl_dyn_free(&sshc->readdir); - state(conn, SSH_STOP); + Curl_dyn_free(&sshp->readdir); + state(data, SSH_STOP); } else { - Curl_dyn_reset(&sshc->readdir); - state(conn, SSH_SFTP_READDIR); + Curl_dyn_reset(&sshp->readdir); + state(data, SSH_SFTP_READDIR); } break; @@ -2272,12 +2264,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) break; } sshc->sftp_handle = NULL; - Curl_safefree(sshc->readdir_filename); - Curl_safefree(sshc->readdir_longentry); + Curl_safefree(sshp->readdir_filename); + Curl_safefree(sshp->readdir_longentry); /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; case SSH_SFTP_DOWNLOAD_INIT: @@ -2285,8 +2277,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) * Work on getting the specified file */ sshc->sftp_handle = - libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, - curlx_uztoui(strlen(sftp_scp->path)), + libssh2_sftp_open_ex(sshc->sftp_session, sshp->path, + curlx_uztoui(strlen(sshp->path)), LIBSSH2_FXF_READ, data->set.new_file_perms, LIBSSH2_SFTP_OPENFILE); if(!sshc->sftp_handle) { @@ -2298,20 +2290,20 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) sftperr = libssh2_sftp_last_error(sshc->sftp_session); failf(data, "Could not open remote file for reading: %s", sftp_libssh2_strerror(sftperr)); - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); result = sftp_libssh2_error_to_CURLE(sftperr); sshc->actualcode = result?result:CURLE_SSH; break; } - state(conn, SSH_SFTP_DOWNLOAD_STAT); + state(data, SSH_SFTP_DOWNLOAD_STAT); break; case SSH_SFTP_DOWNLOAD_STAT: { LIBSSH2_SFTP_ATTRIBUTES attrs; - rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, - curlx_uztoui(strlen(sftp_scp->path)), + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, + curlx_uztoui(strlen(sshp->path)), LIBSSH2_SFTP_STAT, &attrs); if(rc == LIBSSH2_ERROR_EAGAIN) { break; @@ -2336,14 +2328,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); return CURLE_BAD_DOWNLOAD_RESUME; } - if(conn->data->state.use_range) { + if(data->state.use_range) { curl_off_t from, to; char *ptr; char *ptr2; CURLofft to_t; CURLofft from_t; - from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from); + from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from); if(from_t == CURL_OFFT_FLOW) return CURLE_RANGE_ERROR; while(*ptr && (ISSPACE(*ptr) || (*ptr == '-'))) @@ -2374,7 +2366,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) size = to - from + 1; } - SFTP_SEEK(conn->proto.sshc.sftp_handle, from); + SFTP_SEEK(sshc->sftp_handle, from); } data->req.size = size; data->req.maxdownload = size; @@ -2417,7 +2409,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); infof(data, "File already completely downloaded\n"); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); @@ -2433,11 +2425,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(result) { /* this should never occur; the close state should be entered at the time the error occurs */ - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = result; } else { - state(conn, SSH_STOP); + state(data, SSH_STOP); } break; @@ -2456,7 +2448,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) sshc->sftp_handle = NULL; } - Curl_safefree(sftp_scp->path); + Curl_safefree(sshp->path); DEBUGF(infof(data, "SFTP DONE done\n")); @@ -2465,11 +2457,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) SSH_SFTP_CLOSE to pass the correct result back */ if(sshc->nextstate != SSH_NO_STATE && sshc->nextstate != SSH_SFTP_CLOSE) { - state(conn, sshc->nextstate); + state(data, sshc->nextstate); sshc->nextstate = SSH_SFTP_CLOSE; } else { - state(conn, SSH_STOP); + state(data, SSH_STOP); result = sshc->actualcode; } break; @@ -2504,16 +2496,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } Curl_safefree(sshc->homedir); - conn->data->state.most_recent_ftp_entrypath = NULL; + data->state.most_recent_ftp_entrypath = NULL; - state(conn, SSH_SESSION_DISCONNECT); + state(data, SSH_SESSION_DISCONNECT); break; case SSH_SCP_TRANS_INIT: - result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path); + result = Curl_getworkingpath(data, sshc->homedir, &sshp->path); if(result) { sshc->actualcode = result; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } @@ -2521,13 +2513,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(data->state.infilesize < 0) { failf(data, "SCP requires a known file size for upload"); sshc->actualcode = CURLE_UPLOAD_FAILED; - state(conn, SSH_SCP_CHANNEL_FREE); + state(data, SSH_SCP_CHANNEL_FREE); break; } - state(conn, SSH_SCP_UPLOAD_INIT); + state(data, SSH_SCP_UPLOAD_INIT); } else { - state(conn, SSH_SCP_DOWNLOAD_INIT); + state(data, SSH_SCP_DOWNLOAD_INIT); } break; @@ -2539,7 +2531,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) * directory in the path. */ sshc->ssh_channel = - SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms, + SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms, data->state.infilesize); if(!sshc->ssh_channel) { int ssh_err; @@ -2553,8 +2545,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0)); - failf(conn->data, "%s", err_msg); - state(conn, SSH_SCP_CHANNEL_FREE); + failf(data, "%s", err_msg); + state(data, SSH_SCP_CHANNEL_FREE); sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); /* Map generic errors to upload failed */ if(sshc->actualcode == CURLE_SSH || @@ -2572,7 +2564,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) conn->sockfd = conn->writesockfd; if(result) { - state(conn, SSH_SCP_CHANNEL_FREE); + state(data, SSH_SCP_CHANNEL_FREE); sshc->actualcode = result; } else { @@ -2585,7 +2577,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) with both accordingly */ conn->cselect_bits = CURL_CSELECT_OUT; - state(conn, SSH_STOP); + state(data, SSH_STOP); } break; @@ -2607,12 +2599,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) struct stat sb; memset(&sb, 0, sizeof(struct stat)); sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session, - sftp_scp->path, &sb); + sshp->path, &sb); #else libssh2_struct_stat sb; memset(&sb, 0, sizeof(libssh2_struct_stat)); sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session, - sftp_scp->path, &sb); + sshp->path, &sb); #endif if(!sshc->ssh_channel) { @@ -2628,8 +2620,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0)); - failf(conn->data, "%s", err_msg); - state(conn, SSH_SCP_CHANNEL_FREE); + failf(data, "%s", err_msg); + state(data, SSH_SCP_CHANNEL_FREE); sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); break; } @@ -2648,19 +2640,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) conn->cselect_bits = CURL_CSELECT_IN; if(result) { - state(conn, SSH_SCP_CHANNEL_FREE); + state(data, SSH_SCP_CHANNEL_FREE); sshc->actualcode = result; } else - state(conn, SSH_STOP); + state(data, SSH_STOP); } break; case SSH_SCP_DONE: if(data->set.upload) - state(conn, SSH_SCP_SEND_EOF); + state(data, SSH_SCP_SEND_EOF); else - state(conn, SSH_SCP_CHANNEL_FREE); + state(data, SSH_SCP_CHANNEL_FREE); break; case SSH_SCP_SEND_EOF: @@ -2677,7 +2669,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) rc, err_msg); } } - state(conn, SSH_SCP_WAIT_EOF); + state(data, SSH_SCP_WAIT_EOF); break; case SSH_SCP_WAIT_EOF: @@ -2693,7 +2685,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg); } } - state(conn, SSH_SCP_WAIT_CLOSE); + state(data, SSH_SCP_WAIT_CLOSE); break; case SSH_SCP_WAIT_CLOSE: @@ -2709,7 +2701,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) infof(data, "Channel failed to close: %d %s\n", rc, err_msg); } } - state(conn, SSH_SCP_CHANNEL_FREE); + state(data, SSH_SCP_CHANNEL_FREE); break; case SSH_SCP_CHANNEL_FREE: @@ -2729,9 +2721,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } DEBUGF(infof(data, "SCP DONE phase complete\n")); #if 0 /* PREV */ - state(conn, SSH_SESSION_DISCONNECT); + state(data, SSH_SESSION_DISCONNECT); #endif - state(conn, SSH_STOP); + state(data, SSH_STOP); result = sshc->actualcode; break; @@ -2769,9 +2761,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } Curl_safefree(sshc->homedir); - conn->data->state.most_recent_ftp_entrypath = NULL; + data->state.most_recent_ftp_entrypath = NULL; - state(conn, SSH_SESSION_FREE); + state(data, SSH_SESSION_FREE); break; case SSH_SESSION_FREE: @@ -2839,11 +2831,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->quote_path2); Curl_safefree(sshc->homedir); - - Curl_safefree(sshc->readdir_filename); - Curl_safefree(sshc->readdir_longentry); Curl_safefree(sshc->readdir_line); - Curl_dyn_free(&sshc->readdir); /* the code we are about to return */ result = sshc->actualcode; @@ -2853,7 +2841,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) connclose(conn, "SSH session free"); sshc->state = SSH_SESSION_FREE; /* current */ sshc->nextstate = SSH_NO_STATE; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; case SSH_QUIT: @@ -2861,7 +2849,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) default: /* internal error */ sshc->nextstate = SSH_NO_STATE; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } @@ -2878,10 +2866,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* called by the multi interface to figure out what socket(s) to wait for and for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ -static int ssh_perform_getsock(const struct connectdata *conn, - curl_socket_t *sock) +static int ssh_getsock(struct Curl_easy *data, + struct connectdata *conn, + curl_socket_t *sock) { int bitmap = GETSOCK_BLANK; + (void)data; sock[0] = conn->sock[FIRSTSOCKET]; @@ -2894,16 +2884,6 @@ static int ssh_perform_getsock(const struct connectdata *conn, return bitmap; } -/* Generic function called by the multi interface to figure out what socket(s) - to wait for and for what actions during the DOING and PROTOCONNECT states*/ -static int ssh_getsock(struct connectdata *conn, - curl_socket_t *sock) -{ - /* if we know the direction we can use the generic *_getsock() function even - for the protocol_connect and doing states */ - return ssh_perform_getsock(conn, sock); -} - /* * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this * function is used to figure out in what direction and stores this info so @@ -2911,8 +2891,9 @@ static int ssh_getsock(struct connectdata *conn, * function in all cases so that when it _doesn't_ return EAGAIN we can * restore the default wait bits. */ -static void ssh_block2waitfor(struct connectdata *conn, bool block) +static void ssh_block2waitfor(struct Curl_easy *data, bool block) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; int dir = 0; if(block) { @@ -2930,40 +2911,41 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block) } /* called repeatedly until done from multi.c */ -static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done) +static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; CURLcode result = CURLE_OK; bool block; /* we store the status and use that to provide a ssh_getsock() implementation */ do { - result = ssh_statemach_act(conn, &block); + result = ssh_statemach_act(data, &block); *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then try again */ } while(!result && !*done && !block); - ssh_block2waitfor(conn, block); + ssh_block2waitfor(data, block); return result; } -static CURLcode ssh_block_statemach(struct connectdata *conn, - bool duringconnect) +static CURLcode ssh_block_statemach(struct Curl_easy *data, + struct connectdata *conn, + bool duringconnect) { struct ssh_conn *sshc = &conn->proto.sshc; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; while((sshc->state != SSH_STOP) && !result) { bool block; timediff_t left = 1000; struct curltime now = Curl_now(); - result = ssh_statemach_act(conn, &block); + result = ssh_statemach_act(data, &block); if(result) break; - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) return CURLE_ABORTED_BY_CALLBACK; result = Curl_speedcheck(data, now); @@ -2997,11 +2979,13 @@ static CURLcode ssh_block_statemach(struct connectdata *conn, /* * SSH setup and connection */ -static CURLcode ssh_setup_connection(struct connectdata *conn) +static CURLcode ssh_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { struct SSHPROTO *ssh; + (void)conn; - conn->data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); + data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); if(!ssh) return CURLE_OUT_OF_MEMORY; @@ -3015,9 +2999,10 @@ static Curl_send scp_send, sftp_send; static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags, void **abstract) { - struct connectdata *conn = (struct connectdata *)*abstract; + struct Curl_easy *data = (struct Curl_easy *)*abstract; ssize_t nread; CURLcode result; + struct connectdata *conn = data->conn; Curl_recv *backup = conn->recv[0]; struct ssh_conn *ssh = &conn->proto.sshc; (void)flags; @@ -3025,22 +3010,23 @@ static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer, /* swap in the TLS reader function for this call only, and then swap back the SSH one again */ conn->recv[0] = ssh->tls_recv; - result = Curl_read(conn, sock, buffer, length, &nread); + result = Curl_read(data, sock, buffer, length, &nread); conn->recv[0] = backup; if(result == CURLE_AGAIN) return -EAGAIN; /* magic return code for libssh2 */ else if(result) return -1; /* generic error */ - Curl_debug(conn->data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread); + Curl_debug(data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread); return nread; } static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer, size_t length, int flags, void **abstract) { - struct connectdata *conn = (struct connectdata *)*abstract; + struct Curl_easy *data = (struct Curl_easy *)*abstract; ssize_t nwrite; CURLcode result; + struct connectdata *conn = data->conn; Curl_send *backup = conn->send[0]; struct ssh_conn *ssh = &conn->proto.sshc; (void)flags; @@ -3048,13 +3034,13 @@ static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer, /* swap in the TLS writer function for this call only, and then swap back the SSH one again */ conn->send[0] = ssh->tls_send; - result = Curl_write(conn, sock, buffer, length, &nwrite); + result = Curl_write(data, sock, buffer, length, &nwrite); conn->send[0] = backup; if(result == CURLE_AGAIN) return -EAGAIN; /* magic return code for libssh2 */ else if(result) return -1; /* error */ - Curl_debug(conn->data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite); + Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite); return nwrite; } #endif @@ -3063,24 +3049,29 @@ static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer, * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to * do protocol-specific actions at connect-time. */ -static CURLcode ssh_connect(struct connectdata *conn, bool *done) +static CURLcode ssh_connect(struct Curl_easy *data, bool *done) { #ifdef CURL_LIBSSH2_DEBUG curl_socket_t sock; #endif - struct ssh_conn *ssh; + struct SSHPROTO *sshp = data->req.p.ssh; + struct ssh_conn *sshc; CURLcode result; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; /* initialize per-handle data if not already */ - if(!data->req.p.ssh) - ssh_setup_connection(conn); + if(!sshp) { + result = ssh_setup_connection(data, conn); + if(result) + return result; + sshp = data->req.p.ssh; + } /* We default to persistent connections. We set this already in this connect function to make the re-use checks properly be able to check this bit. */ connkeep(conn, "SSH default"); - ssh = &conn->proto.sshc; + sshc = &conn->proto.sshc; #ifdef CURL_LIBSSH2_DEBUG if(conn->user) { @@ -3092,10 +3083,10 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done) sock = conn->sock[FIRSTSOCKET]; #endif /* CURL_LIBSSH2_DEBUG */ - ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc, - my_libssh2_free, - my_libssh2_realloc, conn); - if(ssh->ssh_session == NULL) { + sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc, + my_libssh2_free, + my_libssh2_realloc, data); + if(sshc->ssh_session == NULL) { failf(data, "Failure initialising ssh session"); return CURLE_FAILED_INIT; } @@ -3134,15 +3125,15 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done) int flags, void **abstract); */ - libssh2_session_callback_set(ssh->ssh_session, + libssh2_session_callback_set(sshc->ssh_session, LIBSSH2_CALLBACK_RECV, sshrecv.recvp); - libssh2_session_callback_set(ssh->ssh_session, + libssh2_session_callback_set(sshc->ssh_session, LIBSSH2_CALLBACK_SEND, sshsend.sendp); /* Store the underlying TLS recv/send function pointers to be used when reading from the proxy */ - ssh->tls_recv = conn->recv[FIRSTSOCKET]; - ssh->tls_send = conn->send[FIRSTSOCKET]; + sshc->tls_recv = conn->recv[FIRSTSOCKET]; + sshc->tls_send = conn->send[FIRSTSOCKET]; } #endif /* CURL_DISABLE_PROXY */ @@ -3157,7 +3148,7 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done) if(data->set.ssh_compression) { #if LIBSSH2_VERSION_NUM >= 0x010208 - if(libssh2_session_flag(ssh->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) + if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) #endif infof(data, "Failed to enable compression for ssh session\n"); } @@ -3165,14 +3156,14 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done) #ifdef HAVE_LIBSSH2_KNOWNHOST_API if(data->set.str[STRING_SSH_KNOWNHOSTS]) { int rc; - ssh->kh = libssh2_knownhost_init(ssh->ssh_session); - if(!ssh->kh) { - libssh2_session_free(ssh->ssh_session); + sshc->kh = libssh2_knownhost_init(sshc->ssh_session); + if(!sshc->kh) { + libssh2_session_free(sshc->ssh_session); return CURLE_FAILED_INIT; } /* read all known hosts from there */ - rc = libssh2_knownhost_readfile(ssh->kh, + rc = libssh2_knownhost_readfile(sshc->kh, data->set.str[STRING_SSH_KNOWNHOSTS], LIBSSH2_KNOWNHOST_FILE_OPENSSH); if(rc < 0) @@ -3182,13 +3173,13 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done) #endif /* HAVE_LIBSSH2_KNOWNHOST_API */ #ifdef CURL_LIBSSH2_DEBUG - libssh2_trace(ssh->ssh_session, ~0); + libssh2_trace(sshc->ssh_session, ~0); infof(data, "SSH socket: %d\n", (int)sock); #endif /* CURL_LIBSSH2_DEBUG */ - state(conn, SSH_INIT); + state(data, SSH_INIT); - result = ssh_multi_statemach(conn, done); + result = ssh_multi_statemach(data, done); return result; } @@ -3203,40 +3194,41 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done) */ static -CURLcode scp_perform(struct connectdata *conn, - bool *connected, - bool *dophase_done) +CURLcode scp_perform(struct Curl_easy *data, + bool *connected, + bool *dophase_done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; - DEBUGF(infof(conn->data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts\n")); *dophase_done = FALSE; /* not done yet */ /* start the first command in the DO phase */ - state(conn, SSH_SCP_TRANS_INIT); + state(data, SSH_SCP_TRANS_INIT); /* run the state-machine */ - result = ssh_multi_statemach(conn, dophase_done); + result = ssh_multi_statemach(data, dophase_done); *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; } /* called from multi.c while DOing */ -static CURLcode scp_doing(struct connectdata *conn, - bool *dophase_done) +static CURLcode scp_doing(struct Curl_easy *data, + bool *dophase_done) { CURLcode result; - result = ssh_multi_statemach(conn, dophase_done); + result = ssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; } @@ -3246,11 +3238,11 @@ static CURLcode scp_doing(struct connectdata *conn, * separate ones but this way means less duplicated code. */ -static CURLcode ssh_do(struct connectdata *conn, bool *done) +static CURLcode ssh_do(struct Curl_easy *data, bool *done) { CURLcode result; bool connected = 0; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; *done = FALSE; /* default to false */ @@ -3267,9 +3259,9 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done) Curl_pgrsSetDownloadSize(data, -1); if(conn->handler->protocol & CURLPROTO_SCP) - result = scp_perform(conn, &connected, done); + result = scp_perform(data, &connected, done); else - result = sftp_perform(conn, &connected, done); + result = sftp_perform(data, &connected, done); return result; } @@ -3277,18 +3269,20 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done) /* BLOCKING, but the function is using the state machine so the only reason this is still blocking is that the multi interface code has no support for disconnecting operations that takes a while */ -static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode scp_disconnect(struct Curl_easy *data, + struct connectdata *conn, + bool dead_connection) { CURLcode result = CURLE_OK; - struct ssh_conn *ssh = &conn->proto.sshc; + struct ssh_conn *sshc = &conn->proto.sshc; (void) dead_connection; - if(ssh->ssh_session) { + if(sshc->ssh_session) { /* only if there's a session still around to use! */ - state(conn, SSH_SESSION_DISCONNECT); + state(data, SSH_SESSION_DISCONNECT); - result = ssh_block_statemach(conn, FALSE); + result = ssh_block_statemach(data, conn, FALSE); } return result; @@ -3296,51 +3290,56 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection) /* generic done function for both SCP and SFTP called from their specific done functions */ -static CURLcode ssh_done(struct connectdata *conn, CURLcode status) +static CURLcode ssh_done(struct Curl_easy *data, CURLcode status) { CURLcode result = CURLE_OK; - struct SSHPROTO *sftp_scp = conn->data->req.p.ssh; + struct SSHPROTO *sshp = data->req.p.ssh; + struct connectdata *conn = data->conn; if(!status) { /* run the state-machine */ - result = ssh_block_statemach(conn, FALSE); + result = ssh_block_statemach(data, conn, FALSE); } else result = status; - if(sftp_scp) - Curl_safefree(sftp_scp->path); - if(Curl_pgrsDone(conn)) + Curl_safefree(sshp->path); + Curl_safefree(sshp->readdir_filename); + Curl_safefree(sshp->readdir_longentry); + Curl_dyn_free(&sshp->readdir); + + if(Curl_pgrsDone(data)) return CURLE_ABORTED_BY_CALLBACK; - conn->data->req.keepon = 0; /* clear all bits */ + data->req.keepon = 0; /* clear all bits */ return result; } -static CURLcode scp_done(struct connectdata *conn, CURLcode status, +static CURLcode scp_done(struct Curl_easy *data, CURLcode status, bool premature) { (void)premature; /* not used */ if(!status) - state(conn, SSH_SCP_DONE); + state(data, SSH_SCP_DONE); - return ssh_done(conn, status); + return ssh_done(data, status); } -static ssize_t scp_send(struct connectdata *conn, int sockindex, +static ssize_t scp_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *err) { ssize_t nwrite; + struct connectdata *conn = data->conn; + struct ssh_conn *sshc = &conn->proto.sshc; (void)sockindex; /* we only support SCP on the fixed known primary socket */ /* libssh2_channel_write() returns int! */ - nwrite = (ssize_t) - libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len); + nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len); - ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); if(nwrite == LIBSSH2_ERROR_EAGAIN) { *err = CURLE_AGAIN; @@ -3354,17 +3353,18 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex, return nwrite; } -static ssize_t scp_recv(struct connectdata *conn, int sockindex, +static ssize_t scp_recv(struct Curl_easy *data, int sockindex, char *mem, size_t len, CURLcode *err) { ssize_t nread; + struct connectdata *conn = data->conn; + struct ssh_conn *sshc = &conn->proto.sshc; (void)sockindex; /* we only support SCP on the fixed known primary socket */ /* libssh2_channel_read() returns int */ - nread = (ssize_t) - libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len); + nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len); - ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); if(nread == LIBSSH2_ERROR_EAGAIN) { *err = CURLE_AGAIN; nread = -1; @@ -3387,39 +3387,39 @@ static ssize_t scp_recv(struct connectdata *conn, int sockindex, */ static -CURLcode sftp_perform(struct connectdata *conn, +CURLcode sftp_perform(struct Curl_easy *data, bool *connected, bool *dophase_done) { CURLcode result = CURLE_OK; - DEBUGF(infof(conn->data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts\n")); *dophase_done = FALSE; /* not done yet */ /* start the first command in the DO phase */ - state(conn, SSH_SFTP_QUOTE_INIT); + state(data, SSH_SFTP_QUOTE_INIT); /* run the state-machine */ - result = ssh_multi_statemach(conn, dophase_done); + result = ssh_multi_statemach(data, dophase_done); - *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + *connected = data->conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; } /* called from multi.c while DOing */ -static CURLcode sftp_doing(struct connectdata *conn, +static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done) { - CURLcode result = ssh_multi_statemach(conn, dophase_done); + CURLcode result = ssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; } @@ -3427,53 +3427,56 @@ static CURLcode sftp_doing(struct connectdata *conn, /* BLOCKING, but the function is using the state machine so the only reason this is still blocking is that the multi interface code has no support for disconnecting operations that takes a while */ -static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode sftp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { CURLcode result = CURLE_OK; + struct ssh_conn *sshc = &conn->proto.sshc; (void) dead_connection; - DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); + DEBUGF(infof(data, "SSH DISCONNECT starts now\n")); - if(conn->proto.sshc.ssh_session) { + if(sshc->ssh_session) { /* only if there's a session still around to use! */ - state(conn, SSH_SFTP_SHUTDOWN); - result = ssh_block_statemach(conn, FALSE); + state(data, SSH_SFTP_SHUTDOWN); + result = ssh_block_statemach(data, conn, FALSE); } - DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); + DEBUGF(infof(data, "SSH DISCONNECT is done\n")); return result; } -static CURLcode sftp_done(struct connectdata *conn, CURLcode status, +static CURLcode sftp_done(struct Curl_easy *data, CURLcode status, bool premature) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; if(!status) { /* Post quote commands are executed after the SFTP_CLOSE state to avoid errors that could happen due to open file handles during POSTQUOTE operation */ - if(!premature && conn->data->set.postquote && !conn->bits.retry) + if(!premature && data->set.postquote && !conn->bits.retry) sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); } - return ssh_done(conn, status); + return ssh_done(data, status); } /* return number of sent bytes */ -static ssize_t sftp_send(struct connectdata *conn, int sockindex, +static ssize_t sftp_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *err) { - ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14 - but is changed to ssize_t in 0.15. These days we don't - support libssh2 0.15*/ + ssize_t nwrite; + struct connectdata *conn = data->conn; + struct ssh_conn *sshc = &conn->proto.sshc; (void)sockindex; - nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len); + nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len); - ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); if(nwrite == LIBSSH2_ERROR_EAGAIN) { *err = CURLE_AGAIN; @@ -3491,15 +3494,17 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex, * Return number of received (decrypted) bytes * or <0 on error */ -static ssize_t sftp_recv(struct connectdata *conn, int sockindex, +static ssize_t sftp_recv(struct Curl_easy *data, int sockindex, char *mem, size_t len, CURLcode *err) { ssize_t nread; + struct connectdata *conn = data->conn; + struct ssh_conn *sshc = &conn->proto.sshc; (void)sockindex; - nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len); + nread = libssh2_sftp_read(sshc->sftp_handle, mem, len); - ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); if(nread == LIBSSH2_ERROR_EAGAIN) { *err = CURLE_AGAIN; diff --git a/libs/libcurl/src/vssh/ssh.h b/libs/libcurl/src/vssh/ssh.h index 377337031d..52e1ee6c20 100644 --- a/libs/libcurl/src/vssh/ssh.h +++ b/libs/libcurl/src/vssh/ssh.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -111,6 +111,17 @@ typedef enum { struct. */ struct SSHPROTO { char *path; /* the path we operate on */ +#ifdef USE_LIBSSH2 + struct dynbuf readdir_link; + struct dynbuf readdir; + char *readdir_filename; + char *readdir_longentry; + + LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */ + + /* Here's a set of struct members used by the SFTP_READDIR state */ + LIBSSH2_SFTP_ATTRIBUTES readdir_attrs; +#endif }; /* ssh_conn is used for struct connection-oriented data in the connectdata @@ -123,6 +134,8 @@ struct ssh_conn { char *rsa_pub; /* path name */ char *rsa; /* path name */ bool authed; /* the connection has been authenticated fine */ + bool acceptfail; /* used by the SFTP_QUOTE (continue if + quote command fails) */ sshstate state; /* always use ssh.c:state() to change state! */ sshstate nextstate; /* the state to goto after stopping */ CURLcode actualcode; /* the actual error code */ @@ -130,8 +143,6 @@ struct ssh_conn { char *quote_path1; /* two generic pointers for the QUOTE stuff */ char *quote_path2; - bool acceptfail; /* used by the SFTP_QUOTE (continue if - quote command fails) */ char *homedir; /* when doing SFTP we figure out home dir in the connect phase */ char *readdir_line; @@ -140,9 +151,8 @@ struct ssh_conn { int secondCreateDirs; /* counter use by the code to see if the second attempt has been made to change to/create a directory */ - char *slash_pos; /* used by the SFTP_CREATE_DIRS state */ - int orig_waitfor; /* default READ/WRITE bits wait for */ + char *slash_pos; /* used by the SFTP_CREATE_DIRS state */ #if defined(USE_LIBSSH) char *readdir_linkPath; @@ -168,15 +178,6 @@ struct ssh_conn { const char *readdir_longentry; char *readdir_tmp; #elif defined(USE_LIBSSH2) - struct dynbuf readdir_link; - struct dynbuf readdir; - char *readdir_filename; - char *readdir_longentry; - - LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */ - - /* Here's a set of struct members used by the SFTP_READDIR state */ - LIBSSH2_SFTP_ATTRIBUTES readdir_attrs; LIBSSH2_SESSION *ssh_session; /* Secure Shell session */ LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */ LIBSSH2_SFTP *sftp_session; /* SFTP handle */ diff --git a/libs/libcurl/src/vssh/wolfssh.c b/libs/libcurl/src/vssh/wolfssh.c index b0dfb20478..6020180a5e 100644 --- a/libs/libcurl/src/vssh/wolfssh.c +++ b/libs/libcurl/src/vssh/wolfssh.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2019 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2019 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -45,27 +45,30 @@ #include "curl_memory.h" #include "memdebug.h" -static CURLcode wssh_connect(struct connectdata *conn, bool *done); -static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done); -static CURLcode wssh_do(struct connectdata *conn, bool *done); +static CURLcode wssh_connect(struct Curl_easy *data, bool *done); +static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done); +static CURLcode wssh_do(struct Curl_easy *data, bool *done); #if 0 -static CURLcode wscp_done(struct connectdata *conn, +static CURLcode wscp_done(struct Curl_easy *data, CURLcode, bool premature); -static CURLcode wscp_doing(struct connectdata *conn, +static CURLcode wscp_doing(struct Curl_easy *data, bool *dophase_done); -static CURLcode wscp_disconnect(struct connectdata *conn, +static CURLcode wscp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection); #endif -static CURLcode wsftp_done(struct connectdata *conn, +static CURLcode wsftp_done(struct Curl_easy *data, CURLcode, bool premature); -static CURLcode wsftp_doing(struct connectdata *conn, +static CURLcode wsftp_doing(struct Curl_easy *data, bool *dophase_done); -static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead); -static int wssh_getsock(struct connectdata *conn, +static CURLcode wsftp_disconnect(struct Curl_easy *data, + struct connectdata *conn, + bool dead); +static int wssh_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *sock); -static int wssh_perform_getsock(const struct connectdata *conn, - curl_socket_t *sock); -static CURLcode wssh_setup_connection(struct connectdata *conn); +static CURLcode wssh_setup_connection(struct Curl_easy *data, + struct connectdata *conn); #if 0 /* @@ -84,7 +87,7 @@ const struct Curl_handler Curl_handler_scp = { wssh_getsock, /* proto_getsock */ wssh_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - wssh_perform_getsock, /* perform_getsock */ + wssh_getsock, /* perform_getsock */ wscp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ @@ -112,12 +115,13 @@ const struct Curl_handler Curl_handler_sftp = { wssh_getsock, /* proto_getsock */ wssh_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - wssh_perform_getsock, /* perform_getsock */ + wssh_getsock, /* perform_getsock */ wsftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ PORT_SSH, /* defport */ CURLPROTO_SFTP, /* protocol */ + CURLPROTO_SFTP, /* family */ PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */ }; @@ -126,8 +130,9 @@ const struct Curl_handler Curl_handler_sftp = { * SSH State machine related code */ /* This is the ONLY way to change SSH state! */ -static void state(struct connectdata *conn, sshstate nowstate) +static void state(struct Curl_easy *data, sshstate nowstate) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* for debug purposes */ @@ -198,7 +203,7 @@ static void state(struct connectdata *conn, sshstate nowstate) DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST); if(sshc->state != nowstate) { - infof(conn->data, "wolfssh %p state change from %s to %s\n", + infof(data, "wolfssh %p state change from %s to %s\n", (void *)sshc, names[sshc->state], names[nowstate]); } #endif @@ -206,11 +211,11 @@ static void state(struct connectdata *conn, sshstate nowstate) sshc->state = nowstate; } -static ssize_t wscp_send(struct connectdata *conn, int sockindex, +static ssize_t wscp_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *err) { ssize_t nwrite = 0; - (void)conn; + (void)data; (void)sockindex; /* we only support SCP on the fixed known primary socket */ (void)mem; (void)len; @@ -219,11 +224,11 @@ static ssize_t wscp_send(struct connectdata *conn, int sockindex, return nwrite; } -static ssize_t wscp_recv(struct connectdata *conn, int sockindex, +static ssize_t wscp_recv(struct Curl_easy *data, int sockindex, char *mem, size_t len, CURLcode *err) { ssize_t nread = 0; - (void)conn; + (void)data; (void)sockindex; /* we only support SCP on the fixed known primary socket */ (void)mem; (void)len; @@ -233,9 +238,10 @@ static ssize_t wscp_recv(struct connectdata *conn, int sockindex, } /* return number of sent bytes */ -static ssize_t wsftp_send(struct connectdata *conn, int sockindex, +static ssize_t wsftp_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *err) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; word32 offset[2]; int rc; @@ -262,11 +268,11 @@ static ssize_t wsftp_send(struct connectdata *conn, int sockindex, return -1; } if(rc < 0) { - failf(conn->data, "wolfSSH_SFTP_SendWritePacket returned %d\n", rc); + failf(data, "wolfSSH_SFTP_SendWritePacket returned %d", rc); return -1; } DEBUGASSERT(rc == (int)len); - infof(conn->data, "sent %zd bytes SFTP from offset %zd\n", + infof(data, "sent %zd bytes SFTP from offset %zd\n", len, sshc->offset); sshc->offset += len; return (ssize_t)rc; @@ -276,10 +282,11 @@ static ssize_t wsftp_send(struct connectdata *conn, int sockindex, * Return number of received (decrypted) bytes * or <0 on error */ -static ssize_t wsftp_recv(struct connectdata *conn, int sockindex, +static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex, char *mem, size_t len, CURLcode *err) { int rc; + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; word32 offset[2]; (void)sockindex; @@ -307,7 +314,7 @@ static ssize_t wsftp_recv(struct connectdata *conn, int sockindex, DEBUGASSERT(rc <= (int)len); if(rc < 0) { - failf(conn->data, "wolfSSH_SFTP_SendReadPacket returned %d\n", rc); + failf(data, "wolfSSH_SFTP_SendReadPacket returned %d", rc); return -1; } sshc->offset += len; @@ -318,11 +325,13 @@ static ssize_t wsftp_recv(struct connectdata *conn, int sockindex, /* * SSH setup and connection */ -static CURLcode wssh_setup_connection(struct connectdata *conn) +static CURLcode wssh_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { struct SSHPROTO *ssh; + (void)conn; - conn->data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); + data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); if(!ssh) return CURLE_OUT_OF_MEMORY; @@ -336,28 +345,28 @@ static int userauth(byte authtype, WS_UserAuthData* authdata, void *ctx) { - struct connectdata *conn = ctx; - DEBUGF(infof(conn->data, "wolfssh callback: type %s\n", + struct Curl_easy *data = ctx; + DEBUGF(infof(data, "wolfssh callback: type %s\n", authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" : "PUBLICCKEY")); if(authtype == WOLFSSH_USERAUTH_PASSWORD) { - authdata->sf.password.password = (byte *)conn->passwd; - authdata->sf.password.passwordSz = (word32) strlen(conn->passwd); + authdata->sf.password.password = (byte *)data->conn->passwd; + authdata->sf.password.passwordSz = (word32) strlen(data->conn->passwd); } return 0; } -static CURLcode wssh_connect(struct connectdata *conn, bool *done) +static CURLcode wssh_connect(struct Curl_easy *data, bool *done) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ssh_conn *sshc; curl_socket_t sock = conn->sock[FIRSTSOCKET]; int rc; /* initialize per-handle data if not already */ if(!data->req.p.ssh) - wssh_setup_connection(conn); + wssh_setup_connection(data, conn); /* We default to persistent connections. We set this already in this connect function to make the re-use checks properly be able to check this bit. */ @@ -392,7 +401,7 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done) /* set callback for authentication */ wolfSSH_SetUserAuth(sshc->ctx, userauth); - wolfSSH_SetUserAuthCtx(sshc->ssh_session, conn); + wolfSSH_SetUserAuthCtx(sshc->ssh_session, data); rc = wolfSSH_set_fd(sshc->ssh_session, (int)sock); if(rc) { @@ -406,11 +415,11 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done) *done = TRUE; if(conn->handler->protocol & CURLPROTO_SCP) - state(conn, SSH_INIT); + state(data, SSH_INIT); else - state(conn, SSH_SFTP_INIT); + state(data, SSH_SFTP_INIT); - return wssh_multi_statemach(conn, done); + return wssh_multi_statemach(data, done); error: wolfSSH_free(sshc->ssh_session); wolfSSH_CTX_free(sshc->ctx); @@ -424,11 +433,11 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done) * wants to be called again when the socket is ready */ -static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) +static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; - struct Curl_easy *data = conn->data; struct SSHPROTO *sftp_scp = data->req.p.ssh; WS_SFTPNAME *name; int rc = 0; @@ -437,7 +446,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) do { switch(sshc->state) { case SSH_INIT: - state(conn, SSH_S_STARTUP); + state(data, SSH_S_STARTUP); /* FALLTHROUGH */ case SSH_S_STARTUP: rc = wolfSSH_connect(sshc->ssh_session); @@ -454,11 +463,11 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) return CURLE_OK; } else if(rc != WS_SUCCESS) { - state(conn, SSH_STOP); + state(data, SSH_STOP); return CURLE_SSH; } infof(data, "wolfssh connected!\n"); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; case SSH_STOP: break; @@ -479,7 +488,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) } else if(rc == WS_SUCCESS) { infof(data, "wolfssh SFTP connected!\n"); - state(conn, SSH_SFTP_REALPATH); + state(data, SSH_SFTP_REALPATH); } else { failf(data, "wolfssh SFTP connect error %d", rc); @@ -510,45 +519,45 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) infof(data, "wolfssh SFTP realpath succeeded!\n"); } wolfSSH_SFTPNAME_list_free(name); - state(conn, SSH_STOP); + state(data, SSH_STOP); return CURLE_OK; } failf(data, "wolfssh SFTP realpath %d", rc); return CURLE_SSH; case SSH_SFTP_QUOTE_INIT: - result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path); + result = Curl_getworkingpath(data, sshc->homedir, &sftp_scp->path); if(result) { sshc->actualcode = result; - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } if(data->set.quote) { infof(data, "Sending quote commands\n"); sshc->quote_item = data->set.quote; - state(conn, SSH_SFTP_QUOTE); + state(data, SSH_SFTP_QUOTE); } else { - state(conn, SSH_SFTP_GETINFO); + state(data, SSH_SFTP_GETINFO); } break; case SSH_SFTP_GETINFO: if(data->set.get_filetime) { - state(conn, SSH_SFTP_FILETIME); + state(data, SSH_SFTP_FILETIME); } else { - state(conn, SSH_SFTP_TRANS_INIT); + state(data, SSH_SFTP_TRANS_INIT); } break; case SSH_SFTP_TRANS_INIT: if(data->set.upload) - state(conn, SSH_SFTP_UPLOAD_INIT); + state(data, SSH_SFTP_UPLOAD_INIT); else { if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') - state(conn, SSH_SFTP_READDIR_INIT); + state(data, SSH_SFTP_READDIR_INIT); else - state(conn, SSH_SFTP_DOWNLOAD_INIT); + state(data, SSH_SFTP_DOWNLOAD_INIT); } break; case SSH_SFTP_UPLOAD_INIT: { @@ -583,7 +592,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) /* If we have restart position then open for append */ flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND; else - /* Clear file before writing (normal behaviour) */ + /* Clear file before writing (normal behavior) */ flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC; memset(&createattrs, 0, sizeof(createattrs)); @@ -611,7 +620,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) failf(data, "wolfssh SFTP upload open failed: %d", rc); return CURLE_SSH; } - state(conn, SSH_SFTP_DOWNLOAD_STAT); + state(data, SSH_SFTP_DOWNLOAD_STAT); /* If we have a restart point then we need to seek to the correct position. */ @@ -676,7 +685,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) conn->sockfd = conn->writesockfd; if(result) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = result; } else { @@ -694,7 +703,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) timeout here */ Curl_expire(data, 0, EXPIRE_RUN_NOW); - state(conn, SSH_STOP); + state(data, SSH_STOP); } break; } @@ -717,7 +726,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) } else if(rc == WS_SUCCESS) { infof(data, "wolfssh SFTP open succeeded!\n"); - state(conn, SSH_SFTP_DOWNLOAD_STAT); + state(data, SSH_SFTP_DOWNLOAD_STAT); return CURLE_OK; } @@ -762,7 +771,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) /* We cannot seek with wolfSSH so resuming and range requests are not possible */ - if(conn->data->state.use_range || data->state.resume_from) { + if(data->state.use_range || data->state.resume_from) { infof(data, "wolfSSH cannot do range/seek on SFTP\n"); return CURLE_BAD_DOWNLOAD_RESUME; } @@ -772,7 +781,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); infof(data, "File already completely downloaded\n"); - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); @@ -788,11 +797,11 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) if(result) { /* this should never occur; the close state should be entered at the time the error occurs */ - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = result; } else { - state(conn, SSH_STOP); + state(data, SSH_STOP); } break; } @@ -813,7 +822,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) return CURLE_OK; } else if(rc == WS_SUCCESS) { - state(conn, SSH_STOP); + state(data, SSH_STOP); return CURLE_OK; } @@ -823,10 +832,10 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) case SSH_SFTP_READDIR_INIT: Curl_pgrsSetDownloadSize(data, -1); if(data->set.opt_no_body) { - state(conn, SSH_STOP); + state(data, SSH_STOP); break; } - state(conn, SSH_SFTP_READDIR); + state(data, SSH_SFTP_READDIR); /* FALLTHROUGH */ case SSH_SFTP_READDIR: name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path); @@ -853,11 +862,11 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) data->set.ftp_list_only ? name->fName : name->lName); if(line == NULL) { - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } - result = Curl_client_write(conn, CLIENTWRITE_BODY, + result = Curl_client_write(data, CLIENTWRITE_BODY, line, strlen(line)); free(line); if(result) { @@ -867,7 +876,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) name = name->next; } wolfSSH_SFTPNAME_list_free(origname); - state(conn, SSH_STOP); + state(data, SSH_STOP); return result; } failf(data, "wolfssh SFTP ls failed: %d", rc); @@ -877,7 +886,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->homedir); wolfSSH_free(sshc->ssh_session); wolfSSH_CTX_free(sshc->ctx); - state(conn, SSH_STOP); + state(data, SSH_STOP); return CURLE_OK; default: break; @@ -887,19 +896,20 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) } /* called repeatedly until done from multi.c */ -static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done) +static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; CURLcode result = CURLE_OK; bool block; /* we store the status and use that to provide a ssh_getsock() implementation */ do { - result = wssh_statemach_act(conn, &block); + result = wssh_statemach_act(data, &block); *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then try again */ if(*done) { - DEBUGF(infof(conn->data, "wssh_statemach_act says DONE\n")); + DEBUGF(infof(data, "wssh_statemach_act says DONE\n")); } } while(!result && !*done && !block); @@ -907,37 +917,38 @@ static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done) } static -CURLcode wscp_perform(struct connectdata *conn, +CURLcode wscp_perform(struct Curl_easy *data, bool *connected, bool *dophase_done) { - (void)conn; + (void)data; (void)connected; (void)dophase_done; return CURLE_OK; } static -CURLcode wsftp_perform(struct connectdata *conn, +CURLcode wsftp_perform(struct Curl_easy *data, bool *connected, bool *dophase_done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; - DEBUGF(infof(conn->data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts\n")); *dophase_done = FALSE; /* not done yet */ /* start the first command in the DO phase */ - state(conn, SSH_SFTP_QUOTE_INIT); + state(data, SSH_SFTP_QUOTE_INIT); /* run the state-machine */ - result = wssh_multi_statemach(conn, dophase_done); + result = wssh_multi_statemach(data, dophase_done); *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; @@ -946,11 +957,11 @@ CURLcode wsftp_perform(struct connectdata *conn, /* * The DO function is generic for both protocols. */ -static CURLcode wssh_do(struct connectdata *conn, bool *done) +static CURLcode wssh_do(struct Curl_easy *data, bool *done) { CURLcode result; bool connected = 0; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; *done = FALSE; /* default to false */ @@ -965,31 +976,31 @@ static CURLcode wssh_do(struct connectdata *conn, bool *done) Curl_pgrsSetDownloadSize(data, -1); if(conn->handler->protocol & CURLPROTO_SCP) - result = wscp_perform(conn, &connected, done); + result = wscp_perform(data, &connected, done); else - result = wsftp_perform(conn, &connected, done); + result = wsftp_perform(data, &connected, done); return result; } -static CURLcode wssh_block_statemach(struct connectdata *conn, +static CURLcode wssh_block_statemach(struct Curl_easy *data, bool disconnect) { + struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; while((sshc->state != SSH_STOP) && !result) { bool block; timediff_t left = 1000; struct curltime now = Curl_now(); - result = wssh_statemach_act(conn, &block); + result = wssh_statemach_act(data, &block); if(result) break; if(!disconnect) { - if(Curl_pgrsUpdate(conn)) + if(Curl_pgrsUpdate(data)) return CURLE_ABORTED_BY_CALLBACK; result = Curl_speedcheck(data, now); @@ -1024,29 +1035,29 @@ static CURLcode wssh_block_statemach(struct connectdata *conn, /* generic done function for both SCP and SFTP called from their specific done functions */ -static CURLcode wssh_done(struct connectdata *conn, CURLcode status) +static CURLcode wssh_done(struct Curl_easy *data, CURLcode status) { CURLcode result = CURLE_OK; - struct SSHPROTO *sftp_scp = conn->data->req.p.ssh; + struct SSHPROTO *sftp_scp = data->req.p.ssh; if(!status) { /* run the state-machine */ - result = wssh_block_statemach(conn, FALSE); + result = wssh_block_statemach(data, FALSE); } else result = status; if(sftp_scp) Curl_safefree(sftp_scp->path); - if(Curl_pgrsDone(conn)) + if(Curl_pgrsDone(data)) return CURLE_ABORTED_BY_CALLBACK; - conn->data->req.keepon = 0; /* clear all bits */ + data->req.keepon = 0; /* clear all bits */ return result; } #if 0 -static CURLcode wscp_done(struct connectdata *conn, +static CURLcode wscp_done(struct Curl_easy *data, CURLcode code, bool premature) { CURLcode result = CURLE_OK; @@ -1057,7 +1068,7 @@ static CURLcode wscp_done(struct connectdata *conn, return result; } -static CURLcode wscp_doing(struct connectdata *conn, +static CURLcode wscp_doing(struct Curl_easy *data, bool *dophase_done) { CURLcode result = CURLE_OK; @@ -1067,9 +1078,11 @@ static CURLcode wscp_doing(struct connectdata *conn, return result; } -static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode wscp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { CURLcode result = CURLE_OK; + (void)data; (void)conn; (void)dead_connection; @@ -1077,54 +1090,52 @@ static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection) } #endif -static CURLcode wsftp_done(struct connectdata *conn, +static CURLcode wsftp_done(struct Curl_easy *data, CURLcode code, bool premature) { (void)premature; - state(conn, SSH_SFTP_CLOSE); + state(data, SSH_SFTP_CLOSE); - return wssh_done(conn, code); + return wssh_done(data, code); } -static CURLcode wsftp_doing(struct connectdata *conn, +static CURLcode wsftp_doing(struct Curl_easy *data, bool *dophase_done) { - CURLcode result = wssh_multi_statemach(conn, dophase_done); + CURLcode result = wssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; } -static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead) +static CURLcode wsftp_disconnect(struct Curl_easy *data, + struct connectdata *conn, + bool dead) { CURLcode result = CURLE_OK; (void)dead; - DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); + DEBUGF(infof(data, "SSH DISCONNECT starts now\n")); if(conn->proto.sshc.ssh_session) { /* only if there's a session still around to use! */ - state(conn, SSH_SFTP_SHUTDOWN); - result = wssh_block_statemach(conn, TRUE); + state(data, SSH_SFTP_SHUTDOWN); + result = wssh_block_statemach(data, TRUE); } - DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); + DEBUGF(infof(data, "SSH DISCONNECT is done\n")); return result; } -static int wssh_getsock(struct connectdata *conn, +static int wssh_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *sock) -{ - return wssh_perform_getsock(conn, sock); -} - -static int wssh_perform_getsock(const struct connectdata *conn, - curl_socket_t *sock) { int bitmap = GETSOCK_BLANK; int dir = conn->waitfor; + (void)data; sock[0] = conn->sock[FIRSTSOCKET]; if(dir == KEEP_RECV) diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c index b0c3dc2f07..29b08c0e6d 100644 --- a/libs/libcurl/src/vtls/bearssl.c +++ b/libs/libcurl/src/vtls/bearssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2019 - 2020, Michael Forney, + * Copyright (C) 2019 - 2021, Michael Forney, * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -294,9 +294,9 @@ static const br_x509_class x509_vtable = { x509_get_pkey }; -static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) +static CURLcode bearssl_connect_step1(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->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); @@ -349,8 +349,8 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len); if(ret != CURLE_OK) { if(verifypeer) { - failf(data, "error setting certificate verify locations:\n" - " CAfile: %s\n", ssl_cafile); + failf(data, "error setting certificate verify locations." + " CAfile: %s", ssl_cafile); return ret; } infof(data, "error setting certificate verify locations," @@ -374,12 +374,12 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) if(SSL_SET_OPTION(primary.sessionid)) { void *session; - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &session, NULL, sockindex)) { + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, &session, NULL, sockindex)) { br_ssl_engine_set_session_parameters(&backend->ctx.eng, session); infof(data, "BearSSL: re-using session ID\n"); } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } if(conn->bits.tls_enable_alpn) { @@ -429,10 +429,10 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_OK; } -static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex, +static CURLcode bearssl_run_until(struct Curl_easy *data, + struct connectdata *conn, int sockindex, unsigned target) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; curl_socket_t sockfd = conn->sock[sockindex]; @@ -507,14 +507,15 @@ static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex, } } -static CURLcode bearssl_connect_step2(struct connectdata *conn, int sockindex) +static CURLcode bearssl_connect_step2(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; CURLcode ret; - ret = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP | BR_SSL_RECVAPP); + ret = bearssl_run_until(data, conn, sockindex, + BR_SSL_SENDAPP | BR_SSL_RECVAPP); if(ret == CURLE_AGAIN) return CURLE_OK; if(ret == CURLE_OK) { @@ -527,9 +528,9 @@ static CURLcode bearssl_connect_step2(struct connectdata *conn, int sockindex) return ret; } -static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex) +static CURLcode bearssl_connect_step3(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; CURLcode ret; @@ -552,7 +553,7 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex) conn->negnpn = CURL_HTTP_VERSION_1_1; else infof(data, "ALPN, unrecognized protocol %s\n", protocol); - Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } else @@ -568,12 +569,13 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex) if(!session) return CURLE_OUT_OF_MEMORY; br_ssl_engine_get_session_parameters(&backend->ctx.eng, session); - Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &oldsession, NULL, sockindex)); + Curl_ssl_sessionid_lock(data); + incache = !(Curl_ssl_getsessionid(data, conn, + &oldsession, NULL, sockindex)); if(incache) - Curl_ssl_delsessionid(conn, oldsession); - ret = Curl_ssl_addsessionid(conn, session, 0, sockindex); - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_delsessionid(data, oldsession); + ret = Curl_ssl_addsessionid(data, conn, session, 0, sockindex); + Curl_ssl_sessionid_unlock(data); if(ret) { free(session); return CURLE_OUT_OF_MEMORY; @@ -585,17 +587,17 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex) return CURLE_OK; } -static ssize_t bearssl_send(struct connectdata *conn, int sockindex, +static ssize_t bearssl_send(struct Curl_easy *data, int sockindex, const void *buf, size_t len, CURLcode *err) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; unsigned char *app; size_t applen; for(;;) { - *err = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP); + *err = bearssl_run_until(data, conn, sockindex, BR_SSL_SENDAPP); if (*err != CURLE_OK) return -1; app = br_ssl_engine_sendapp_buf(&backend->ctx.eng, &applen); @@ -618,15 +620,16 @@ static ssize_t bearssl_send(struct connectdata *conn, int sockindex, } } -static ssize_t bearssl_recv(struct connectdata *conn, int sockindex, +static ssize_t bearssl_recv(struct Curl_easy *data, int sockindex, char *buf, size_t len, CURLcode *err) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; unsigned char *app; size_t applen; - *err = bearssl_run_until(conn, sockindex, BR_SSL_RECVAPP); + *err = bearssl_run_until(data, conn, sockindex, BR_SSL_RECVAPP); if(*err != CURLE_OK) return -1; app = br_ssl_engine_recvapp_buf(&backend->ctx.eng, &applen); @@ -640,13 +643,13 @@ static ssize_t bearssl_recv(struct connectdata *conn, int sockindex, return applen; } -static CURLcode bearssl_connect_common(struct connectdata *conn, +static CURLcode bearssl_connect_common(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool nonblocking, bool *done) { CURLcode ret; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; timediff_t timeout_ms; @@ -659,7 +662,7 @@ static CURLcode bearssl_connect_common(struct connectdata *conn, } if(ssl_connect_1 == connssl->connecting_state) { - ret = bearssl_connect_step1(conn, sockindex); + ret = bearssl_connect_step1(data, conn, sockindex); if(ret) return ret; } @@ -712,7 +715,7 @@ static CURLcode bearssl_connect_common(struct connectdata *conn, * before step2 has completed while ensuring that a client using select() * or epoll() will always have a valid fdset to wait on. */ - ret = bearssl_connect_step2(conn, sockindex); + ret = bearssl_connect_step2(data, conn, sockindex); if(ret || (nonblocking && (ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || @@ -721,7 +724,7 @@ static CURLcode bearssl_connect_common(struct connectdata *conn, } if(ssl_connect_3 == connssl->connecting_state) { - ret = bearssl_connect_step3(conn, sockindex); + ret = bearssl_connect_step3(data, conn, sockindex); if(ret) return ret; } @@ -741,21 +744,21 @@ static CURLcode bearssl_connect_common(struct connectdata *conn, return CURLE_OK; } -static size_t Curl_bearssl_version(char *buffer, size_t size) +static size_t bearssl_version(char *buffer, size_t size) { return msnprintf(buffer, size, "BearSSL"); } -static bool Curl_bearssl_data_pending(const struct connectdata *conn, - int connindex) +static bool bearssl_data_pending(const struct connectdata *conn, + int connindex) { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; struct ssl_backend_data *backend = connssl->backend; return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP; } -static CURLcode Curl_bearssl_random(struct Curl_easy *data UNUSED_PARAM, - unsigned char *entropy, size_t length) +static CURLcode bearssl_random(struct Curl_easy *data UNUSED_PARAM, + unsigned char *entropy, size_t length) { static br_hmac_drbg_context ctx; static bool seeded = FALSE; @@ -774,12 +777,13 @@ static CURLcode Curl_bearssl_random(struct Curl_easy *data UNUSED_PARAM, return CURLE_OK; } -static CURLcode Curl_bearssl_connect(struct connectdata *conn, int sockindex) +static CURLcode bearssl_connect(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { CURLcode ret; bool done = FALSE; - ret = bearssl_connect_common(conn, sockindex, FALSE, &done); + ret = bearssl_connect_common(data, conn, sockindex, FALSE, &done); if(ret) return ret; @@ -788,20 +792,22 @@ static CURLcode Curl_bearssl_connect(struct connectdata *conn, int sockindex) return CURLE_OK; } -static CURLcode Curl_bearssl_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) +static CURLcode bearssl_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { - return bearssl_connect_common(conn, sockindex, TRUE, done); + return bearssl_connect_common(data, conn, sockindex, TRUE, done); } -static void *Curl_bearssl_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) +static void *bearssl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) { struct ssl_backend_data *backend = connssl->backend; return &backend->ctx; } -static void Curl_bearssl_close(struct connectdata *conn, int sockindex) +static void bearssl_close(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; @@ -809,35 +815,22 @@ static void Curl_bearssl_close(struct connectdata *conn, int sockindex) if(backend->active) { br_ssl_engine_close(&backend->ctx.eng); - (void)bearssl_run_until(conn, sockindex, BR_SSL_CLOSED); + (void)bearssl_run_until(data, conn, sockindex, BR_SSL_CLOSED); } for(i = 0; i < backend->anchors_len; ++i) free(backend->anchors[i].dn.data); free(backend->anchors); } -static void Curl_bearssl_session_free(void *ptr) +static void bearssl_session_free(void *ptr) { free(ptr); } -static CURLcode Curl_bearssl_md5sum(unsigned char *input, - size_t inputlen, - unsigned char *md5sum, - size_t md5len UNUSED_PARAM) -{ - br_md5_context ctx; - - br_md5_init(&ctx); - br_md5_update(&ctx, input, inputlen); - br_md5_out(&ctx, md5sum); - return CURLE_OK; -} - -static CURLcode Curl_bearssl_sha256sum(const unsigned char *input, - size_t inputlen, - unsigned char *sha256sum, - size_t sha256len UNUSED_PARAM) +static CURLcode bearssl_sha256sum(const unsigned char *input, + size_t inputlen, + unsigned char *sha256sum, + size_t sha256len UNUSED_PARAM) { br_sha256_context ctx; @@ -854,24 +847,23 @@ const struct Curl_ssl Curl_ssl_bearssl = { Curl_none_init, Curl_none_cleanup, - Curl_bearssl_version, + bearssl_version, Curl_none_check_cxn, Curl_none_shutdown, - Curl_bearssl_data_pending, - Curl_bearssl_random, + bearssl_data_pending, + bearssl_random, Curl_none_cert_status_request, - Curl_bearssl_connect, - Curl_bearssl_connect_nonblocking, - Curl_bearssl_get_internals, - Curl_bearssl_close, + bearssl_connect, + bearssl_connect_nonblocking, + bearssl_get_internals, + bearssl_close, Curl_none_close_all, - Curl_bearssl_session_free, + bearssl_session_free, Curl_none_set_engine, Curl_none_set_engine_default, Curl_none_engines_list, Curl_none_false_start, - Curl_bearssl_md5sum, - Curl_bearssl_sha256sum + bearssl_sha256sum }; #endif /* USE_BEARSSL */ diff --git a/libs/libcurl/src/vtls/gskit.c b/libs/libcurl/src/vtls/gskit.c index 17584c750f..9b5f649f7d 100644 --- a/libs/libcurl/src/vtls/gskit.c +++ b/libs/libcurl/src/vtls/gskit.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -301,10 +301,9 @@ static CURLcode set_callback(struct Curl_easy *data, } -static CURLcode set_ciphers(struct connectdata *conn, +static CURLcode set_ciphers(struct Curl_easy *data, gsk_handle h, unsigned int *protoflags) { - struct Curl_easy *data = conn->data; const char *cipherlist = SSL_CONN_CONFIG(cipher_list); const char *clp; const struct gskit_cipher *ctp; @@ -435,7 +434,7 @@ static CURLcode set_ciphers(struct connectdata *conn, } -static int Curl_gskit_init(void) +static int gskit_init(void) { /* No initialisation needed. */ @@ -443,7 +442,7 @@ static int Curl_gskit_init(void) } -static void Curl_gskit_cleanup(void) +static void gskit_cleanup(void) { /* Nothing to do. */ } @@ -587,11 +586,11 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex, } -static void close_one(struct ssl_connect_data *connssl, +static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data, struct connectdata *conn, int sockindex) { if(BACKEND->handle) { - gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle), + gskit_status(data, gsk_secure_soc_close(&BACKEND->handle), "gsk_secure_soc_close()", 0); /* Last chance to drain output. */ while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) @@ -612,10 +611,10 @@ static void close_one(struct ssl_connect_data *connssl, static ssize_t gskit_send(struct connectdata *conn, int sockindex, - const void *mem, size_t len, CURLcode *curlcode) + const void *mem, size_t len, CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - struct Curl_easy *data = conn->data; CURLcode cc = CURLE_SEND_ERROR; int written; @@ -636,11 +635,11 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex, } -static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, - size_t buffersize, CURLcode *curlcode) +static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf, + size_t buffersize, CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[num]; - struct Curl_easy *data = conn->data; int nread; CURLcode cc = CURLE_RECV_ERROR; @@ -664,9 +663,8 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, } static CURLcode -set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn) +set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data) { - struct Curl_easy *data = conn->data; long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); long i = ssl_version; @@ -696,9 +694,9 @@ set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn) return CURLE_OK; } -static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) +static CURLcode gskit_connect_step1(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; gsk_handle envir; CURLcode result; @@ -798,7 +796,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: - result = set_ssl_version_min_max(&protoflags, conn); + result = set_ssl_version_min_max(&protoflags, data); if(result != CURLE_OK) return result; break; @@ -832,7 +830,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0? BACKEND->localfd: conn->sock[sockindex]); if(!result) - result = set_ciphers(conn, BACKEND->handle, &protoflags); + result = set_ciphers(data, BACKEND->handle, &protoflags); if(!protoflags) { failf(data, "No SSL protocol/cipher combination enabled"); result = CURLE_SSL_CIPHER; @@ -915,15 +913,15 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) } /* Error: rollback. */ - close_one(connssl, conn, sockindex); + close_one(connssl, data, conn, sockindex); return result; } -static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, +static CURLcode gskit_connect_step2(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool nonblocking) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; Qso_OverlappedIO_t cstat; struct timeval stmv; @@ -971,9 +969,9 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, } -static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) +static CURLcode gskit_connect_step3(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; const gsk_cert_data_elem *cdev; int cdec; @@ -1016,7 +1014,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) } /* Verify host. */ - result = Curl_verifyhost(conn, cert, certend); + result = Curl_verifyhost(data, conn, cert, certend); if(result) return result; @@ -1031,7 +1029,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) return result; if(cert) { - result = Curl_extract_certinfo(conn, 0, cert, certend); + result = Curl_extract_certinfo(data, 0, cert, certend); if(result) return result; } @@ -1059,10 +1057,10 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) } -static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, +static CURLcode gskit_connect_common(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool nonblocking, bool *done) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; timediff_t timeout_ms; CURLcode result = CURLE_OK; @@ -1082,7 +1080,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, result = CURLE_OPERATION_TIMEDOUT; } else - result = gskit_connect_step1(conn, sockindex); + result = gskit_connect_step1(data, conn, sockindex); } /* Handle handshake pipelining. */ @@ -1101,7 +1099,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, result = CURLE_OPERATION_TIMEDOUT; } else - result = gskit_connect_step2(conn, sockindex, nonblocking); + result = gskit_connect_step2(data, conn, sockindex, nonblocking); } /* Handle handshake pipelining. */ @@ -1111,10 +1109,10 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, /* Step 3: gather certificate info, verify host. */ if(!result && connssl->connecting_state == ssl_connect_3) - result = gskit_connect_step3(conn, sockindex); + result = gskit_connect_step3(data, conn, sockindex); if(result) - close_one(connssl, conn, sockindex); + close_one(connssl, data, conn, sockindex); else if(connssl->connecting_state == ssl_connect_done) { connssl->state = ssl_connection_complete; connssl->connecting_state = ssl_connect_1; @@ -1127,25 +1125,27 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, } -static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) +static CURLcode gskit_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { CURLcode result; - result = gskit_connect_common(conn, sockindex, TRUE, done); + result = gskit_connect_common(data, conn, sockindex, TRUE, done); if(*done || result) conn->ssl[sockindex].connecting_state = ssl_connect_1; return result; } -static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex) +static CURLcode gskit_connect(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { CURLcode result; bool done; conn->ssl[sockindex].connecting_state = ssl_connect_1; - result = gskit_connect_common(conn, sockindex, FALSE, &done); + result = gskit_connect_common(data, conn, sockindex, FALSE, &done); if(result) return result; @@ -1155,17 +1155,18 @@ static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex) } -static void Curl_gskit_close(struct connectdata *conn, int sockindex) +static void gskit_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { - close_one(&conn->ssl[sockindex], conn, sockindex); - close_one(&conn->proxy_ssl[sockindex], conn, sockindex); + close_one(&conn->ssl[sockindex], data, conn, sockindex); + close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex); } -static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) +static int gskit_shutdown(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - struct Curl_easy *data = conn->data; int what; int rc; char buf[120]; @@ -1178,7 +1179,7 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) return 0; #endif - close_one(connssl, conn, sockindex); + close_one(connssl, data, conn, sockindex); rc = 0; what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); @@ -1219,13 +1220,13 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) } -static size_t Curl_gskit_version(char *buffer, size_t size) +static size_t gskit_version(char *buffer, size_t size) { return msnprintf(buffer, size, "GSKit"); } -static int Curl_gskit_check_cxn(struct connectdata *cxn) +static int gskit_check_cxn(struct connectdata *cxn) { struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET]; int err; @@ -1247,8 +1248,8 @@ static int Curl_gskit_check_cxn(struct connectdata *cxn) return -1; /* connection status unknown */ } -static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) +static void *gskit_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) { (void)info; return BACKEND->handle; @@ -1262,18 +1263,18 @@ const struct Curl_ssl Curl_ssl_gskit = { sizeof(struct ssl_backend_data), - Curl_gskit_init, /* init */ - Curl_gskit_cleanup, /* cleanup */ - Curl_gskit_version, /* version */ - Curl_gskit_check_cxn, /* check_cxn */ - Curl_gskit_shutdown, /* shutdown */ + gskit_init, /* init */ + gskit_cleanup, /* cleanup */ + gskit_version, /* version */ + gskit_check_cxn, /* check_cxn */ + gskit_shutdown, /* shutdown */ Curl_none_data_pending, /* data_pending */ Curl_none_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ - Curl_gskit_connect, /* connect */ - Curl_gskit_connect_nonblocking, /* connect_nonblocking */ - Curl_gskit_get_internals, /* get_internals */ - Curl_gskit_close, /* close_one */ + gskit_connect, /* connect */ + gskit_connect_nonblocking, /* connect_nonblocking */ + gskit_get_internals, /* get_internals */ + gskit_close, /* close_one */ Curl_none_close_all, /* close_all */ /* No session handling for GSKit */ Curl_none_session_free, /* session_free */ @@ -1281,7 +1282,6 @@ const struct Curl_ssl Curl_ssl_gskit = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - Curl_none_md5sum, /* md5sum */ NULL /* sha256sum */ }; diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c index e848c3f05a..3ddee19742 100644 --- a/libs/libcurl/src/vtls/gtls.c +++ b/libs/libcurl/src/vtls/gtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -86,38 +86,38 @@ struct ssl_backend_data { #endif }; -static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len) +static ssize_t gtls_push(void *s, const void *buf, size_t len) { curl_socket_t sock = *(curl_socket_t *)s; ssize_t ret = swrite(sock, buf, len); return ret; } -static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len) +static ssize_t gtls_pull(void *s, void *buf, size_t len) { curl_socket_t sock = *(curl_socket_t *)s; ssize_t ret = sread(sock, buf, len); return ret; } -static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len) +static ssize_t gtls_push_ssl(void *s, const void *buf, size_t len) { return gnutls_record_send((gnutls_session_t) s, buf, len); } -static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len) +static ssize_t gtls_pull_ssl(void *s, void *buf, size_t len) { return gnutls_record_recv((gnutls_session_t) s, buf, len); } -/* Curl_gtls_init() +/* gtls_init() * * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that * are not thread-safe and thus this function itself is not thread-safe and * must only be called from within curl_global_init() to keep the thread * situation under control! */ -static int Curl_gtls_init(void) +static int gtls_init(void) { int ret = 1; if(!gtls_inited) { @@ -131,7 +131,7 @@ static int Curl_gtls_init(void) return ret; } -static void Curl_gtls_cleanup(void) +static void gtls_cleanup(void) { if(gtls_inited) { gnutls_global_deinit(); @@ -200,12 +200,12 @@ static void unload_file(gnutls_datum_t data) /* this function does a SSL/TLS (re-)handshake */ -static CURLcode handshake(struct connectdata *conn, +static CURLcode handshake(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool duringconnect, bool nonblocking) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; gnutls_session_t session = backend->session; @@ -314,9 +314,9 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type) #define GNUTLS_SRP "+SRP" static CURLcode -set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn) +set_ssl_version_min_max(const char **prioritylist, struct Curl_easy *data) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); @@ -379,10 +379,10 @@ set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn) } static CURLcode -gtls_connect_step1(struct connectdata *conn, +gtls_connect_step1(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; unsigned int init_flags; @@ -408,7 +408,7 @@ gtls_connect_step1(struct connectdata *conn, return CURLE_OK; if(!gtls_inited) - Curl_gtls_init(); + gtls_init(); /* Initialize certverifyresult to OK */ *certverifyresult = 0; @@ -568,7 +568,7 @@ gtls_connect_step1(struct connectdata *conn, case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: { - CURLcode result = set_ssl_version_min_max(&prioritylist, conn); + CURLcode result = set_ssl_version_min_max(&prioritylist, data); if(result != CURLE_OK) return result; break; @@ -698,16 +698,16 @@ gtls_connect_step1(struct connectdata *conn, #ifndef CURL_DISABLE_PROXY if(conn->proxy_ssl[sockindex].use) { transport_ptr = conn->proxy_ssl[sockindex].backend->session; - gnutls_transport_push = Curl_gtls_push_ssl; - gnutls_transport_pull = Curl_gtls_pull_ssl; + gnutls_transport_push = gtls_push_ssl; + gnutls_transport_pull = gtls_pull_ssl; } else #endif { /* file descriptor for the socket */ transport_ptr = &conn->sock[sockindex]; - gnutls_transport_push = Curl_gtls_push; - gnutls_transport_pull = Curl_gtls_pull; + gnutls_transport_push = gtls_push; + gnutls_transport_pull = gtls_pull; } /* set the connection handle */ @@ -731,15 +731,16 @@ gtls_connect_step1(struct connectdata *conn, void *ssl_sessionid; size_t ssl_idsize; - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) { + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, + &ssl_sessionid, &ssl_idsize, sockindex)) { /* we got a session id, use it! */ gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); /* Informational message */ infof(data, "SSL re-using session ID\n"); } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } return CURLE_OK; @@ -807,7 +808,8 @@ static Curl_recv gtls_recv; static Curl_send gtls_send; static CURLcode -gtls_connect_step3(struct connectdata *conn, +gtls_connect_step3(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { unsigned int cert_list_size; @@ -820,7 +822,6 @@ gtls_connect_step3(struct connectdata *conn, size_t size; time_t certclock; const char *ptr; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; gnutls_session_t session = backend->session; @@ -885,7 +886,7 @@ gtls_connect_step3(struct connectdata *conn, const char *beg = (const char *) chainp[i].data; const char *end = beg + chainp[i].size; - result = Curl_extract_certinfo(conn, i, beg, end); + result = Curl_extract_certinfo(data, i, beg, end); if(result) return result; } @@ -1263,7 +1264,7 @@ gtls_connect_step3(struct connectdata *conn, else infof(data, "ALPN, server did not agree to a protocol\n"); - Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } @@ -1290,19 +1291,19 @@ gtls_connect_step3(struct connectdata *conn, /* extract session ID to the allocated buffer */ gnutls_session_get_data(session, connect_sessionid, &connect_idsize); - Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, + Curl_ssl_sessionid_lock(data); + incache = !(Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)); if(incache) { /* there was one before in the cache, so instead of risking that the previous one was rejected, we just kill that and store the new */ - Curl_ssl_delsessionid(conn, ssl_sessionid); + Curl_ssl_delsessionid(data, ssl_sessionid); } /* store this session id */ - result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize, - sockindex); - Curl_ssl_sessionid_unlock(conn); + result = Curl_ssl_addsessionid(data, conn, connect_sessionid, + connect_idsize, sockindex); + Curl_ssl_sessionid_unlock(data); if(result) { free(connect_sessionid); result = CURLE_OUT_OF_MEMORY; @@ -1326,7 +1327,8 @@ gtls_connect_step3(struct connectdata *conn, 'ssl_connect_2_writing' (waiting to be able to write). */ static CURLcode -gtls_connect_common(struct connectdata *conn, +gtls_connect_common(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool nonblocking, bool *done) @@ -1336,19 +1338,19 @@ gtls_connect_common(struct connectdata *conn, /* Initiate the connection, if not already done */ if(ssl_connect_1 == connssl->connecting_state) { - rc = gtls_connect_step1(conn, sockindex); + rc = gtls_connect_step1(data, conn, sockindex); if(rc) return rc; } - rc = handshake(conn, sockindex, TRUE, nonblocking); + rc = handshake(data, conn, sockindex, TRUE, nonblocking); if(rc) /* handshake() sets its own error message with failf() */ return rc; /* Finish connecting once the handshake is done */ if(ssl_connect_1 == connssl->connecting_state) { - rc = gtls_connect_step3(conn, sockindex); + rc = gtls_connect_step3(data, conn, sockindex); if(rc) return rc; } @@ -1358,18 +1360,20 @@ gtls_connect_common(struct connectdata *conn, return CURLE_OK; } -static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) +static CURLcode gtls_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { - return gtls_connect_common(conn, sockindex, TRUE, done); + return gtls_connect_common(data, conn, sockindex, TRUE, done); } -static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex) +static CURLcode gtls_connect(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { CURLcode result; bool done = FALSE; - result = gtls_connect_common(conn, sockindex, FALSE, &done); + result = gtls_connect_common(data, conn, sockindex, FALSE, &done); if(result) return result; @@ -1378,8 +1382,8 @@ static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex) return CURLE_OK; } -static bool Curl_gtls_data_pending(const struct connectdata *conn, - int connindex) +static bool gtls_data_pending(const struct connectdata *conn, + int connindex) { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; bool res = FALSE; @@ -1399,12 +1403,13 @@ static bool Curl_gtls_data_pending(const struct connectdata *conn, return res; } -static ssize_t gtls_send(struct connectdata *conn, +static ssize_t gtls_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; ssize_t rc = gnutls_record_send(backend->session, mem, len); @@ -1440,8 +1445,10 @@ static void close_one(struct ssl_connect_data *connssl) #endif } -static void Curl_gtls_close(struct connectdata *conn, int sockindex) +static void gtls_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { + (void) data; close_one(&conn->ssl[sockindex]); #ifndef CURL_DISABLE_PROXY close_one(&conn->proxy_ssl[sockindex]); @@ -1452,12 +1459,12 @@ static void Curl_gtls_close(struct connectdata *conn, int sockindex) * This function is called to shut down the SSL layer but keep the * socket open (CCC - Clear Command Channel) */ -static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) +static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; int retval = 0; - struct Curl_easy *data = conn->data; #ifndef CURL_DISABLE_FTP /* This has only been tested on the proftpd server, and the mod_tls code @@ -1526,12 +1533,13 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) return retval; } -static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ +static ssize_t gtls_recv(struct Curl_easy *data, /* connection data */ int num, /* socketindex */ char *buf, /* store read data here */ size_t buffersize, /* max amount to read */ CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_backend_data *backend = connssl->backend; ssize_t ret; @@ -1545,7 +1553,7 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ if(ret == GNUTLS_E_REHANDSHAKE) { /* BLOCKING call, this is bad but a work-around for now. Fixing this "the proper way" takes a whole lot of work. */ - CURLcode result = handshake(conn, num, FALSE, FALSE); + CURLcode result = handshake(data, conn, num, FALSE, FALSE); if(result) /* handshake() writes error message on its own */ *curlcode = result; @@ -1555,7 +1563,7 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ } if(ret < 0) { - failf(conn->data, "GnuTLS recv error (%d): %s", + failf(data, "GnuTLS recv error (%d): %s", (int)ret, gnutls_strerror((int)ret)); *curlcode = CURLE_RECV_ERROR; @@ -1565,18 +1573,18 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ return ret; } -static void Curl_gtls_session_free(void *ptr) +static void gtls_session_free(void *ptr) { free(ptr); } -static size_t Curl_gtls_version(char *buffer, size_t size) +static size_t gtls_version(char *buffer, size_t size) { return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL)); } #ifndef USE_GNUTLS_NETTLE -static int Curl_gtls_seed(struct Curl_easy *data) +static int gtls_seed(struct Curl_easy *data) { /* we have the "SSL is seeded" boolean static to prevent multiple time-consuming seedings in vain */ @@ -1594,8 +1602,8 @@ static int Curl_gtls_seed(struct Curl_easy *data) #endif /* data might be NULL! */ -static CURLcode Curl_gtls_random(struct Curl_easy *data, - unsigned char *entropy, size_t length) +static CURLcode gtls_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) { #if defined(USE_GNUTLS_NETTLE) int rc; @@ -1604,36 +1612,16 @@ static CURLcode Curl_gtls_random(struct Curl_easy *data, return rc?CURLE_FAILED_INIT:CURLE_OK; #elif defined(USE_GNUTLS) if(data) - Curl_gtls_seed(data); /* Initiate the seed if not already done */ + gtls_seed(data); /* Initiate the seed if not already done */ gcry_randomize(entropy, length, GCRY_STRONG_RANDOM); #endif return CURLE_OK; } -static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len) -{ -#if defined(USE_GNUTLS_NETTLE) - struct md5_ctx MD5pw; - md5_init(&MD5pw); - md5_update(&MD5pw, (unsigned int)tmplen, tmp); - md5_digest(&MD5pw, (unsigned int)md5len, md5sum); -#elif defined(USE_GNUTLS) - gcry_md_hd_t MD5pw; - gcry_md_open(&MD5pw, GCRY_MD_MD5, 0); - gcry_md_write(MD5pw, tmp, tmplen); - memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len); - gcry_md_close(MD5pw); -#endif - return CURLE_OK; -} - -static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum, /* output */ - size_t sha256len) +static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) { #if defined(USE_GNUTLS_NETTLE) struct sha256_ctx SHA256pw; @@ -1650,12 +1638,12 @@ static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ return CURLE_OK; } -static bool Curl_gtls_cert_status_request(void) +static bool gtls_cert_status_request(void) { return TRUE; } -static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl, +static void *gtls_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { struct ssl_backend_data *backend = connssl->backend; @@ -1673,26 +1661,25 @@ const struct Curl_ssl Curl_ssl_gnutls = { sizeof(struct ssl_backend_data), - Curl_gtls_init, /* init */ - Curl_gtls_cleanup, /* cleanup */ - Curl_gtls_version, /* version */ + gtls_init, /* init */ + gtls_cleanup, /* cleanup */ + gtls_version, /* version */ Curl_none_check_cxn, /* check_cxn */ - Curl_gtls_shutdown, /* shutdown */ - Curl_gtls_data_pending, /* data_pending */ - Curl_gtls_random, /* random */ - Curl_gtls_cert_status_request, /* cert_status_request */ - Curl_gtls_connect, /* connect */ - Curl_gtls_connect_nonblocking, /* connect_nonblocking */ - Curl_gtls_get_internals, /* get_internals */ - Curl_gtls_close, /* close_one */ + gtls_shutdown, /* shutdown */ + gtls_data_pending, /* data_pending */ + gtls_random, /* random */ + gtls_cert_status_request, /* cert_status_request */ + gtls_connect, /* connect */ + gtls_connect_nonblocking, /* connect_nonblocking */ + gtls_get_internals, /* get_internals */ + gtls_close, /* close_one */ Curl_none_close_all, /* close_all */ - Curl_gtls_session_free, /* session_free */ + gtls_session_free, /* session_free */ Curl_none_set_engine, /* set_engine */ Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - Curl_gtls_md5sum, /* md5sum */ - Curl_gtls_sha256sum /* sha256sum */ + gtls_sha256sum /* sha256sum */ }; #endif /* USE_GNUTLS */ diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c index 191315df8b..fc3a948d1e 100644 --- a/libs/libcurl/src/vtls/mbedtls.c +++ b/libs/libcurl/src/vtls/mbedtls.c @@ -5,8 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * Copyright (C) 2010 - 2011, Hoi-Ho Chan, - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -196,9 +196,9 @@ static CURLcode mbedtls_version_from_curl(int *mbedver, long version) } static CURLcode -set_ssl_version_min_max(struct connectdata *conn, int sockindex) +set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; @@ -241,10 +241,9 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) } static CURLcode -mbed_connect_step1(struct connectdata *conn, +mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->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); @@ -280,7 +279,7 @@ mbed_connect_step1(struct connectdata *conn, #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ - failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", + failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s", -ret, errorbuf); } #else @@ -293,7 +292,7 @@ mbed_connect_step1(struct connectdata *conn, #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ - failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", + failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ @@ -427,7 +426,7 @@ mbed_connect_step1(struct connectdata *conn, case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: { - CURLcode result = set_ssl_version_min_max(conn, sockindex); + CURLcode result = set_ssl_version_min_max(data, conn, sockindex); if(result != CURLE_OK) return result; break; @@ -463,17 +462,17 @@ mbed_connect_step1(struct connectdata *conn, if(SSL_SET_OPTION(primary.sessionid)) { void *old_session = NULL; - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, &old_session, NULL, sockindex)) { ret = mbedtls_ssl_set_session(&backend->ssl, old_session); if(ret) { - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } infof(data, "mbedTLS re-using session\n"); } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } mbedtls_ssl_conf_ca_chain(&backend->config, @@ -541,11 +540,10 @@ mbed_connect_step1(struct connectdata *conn, } static CURLcode -mbed_connect_step2(struct connectdata *conn, +mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, int sockindex) { int ret; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; const mbedtls_x509_crt *peercert; @@ -701,7 +699,7 @@ mbed_connect_step2(struct connectdata *conn, else { infof(data, "ALPN, server did not agree to a protocol\n"); } - Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } #endif @@ -713,13 +711,12 @@ mbed_connect_step2(struct connectdata *conn, } static CURLcode -mbed_connect_step3(struct connectdata *conn, +mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn, int sockindex) { CURLcode retcode = CURLE_OK; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; - struct Curl_easy *data = conn->data; DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); @@ -744,12 +741,13 @@ mbed_connect_step3(struct connectdata *conn, } /* If there's already a matching session in the cache, delete it */ - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) - Curl_ssl_delsessionid(conn, old_ssl_sessionid); + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL, sockindex)) + Curl_ssl_delsessionid(data, old_ssl_sessionid); - retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); - Curl_ssl_sessionid_unlock(conn); + retcode = Curl_ssl_addsessionid(data, conn, + our_ssl_sessionid, 0, sockindex); + Curl_ssl_sessionid_unlock(data); if(retcode) { mbedtls_ssl_session_free(our_ssl_sessionid); free(our_ssl_sessionid); @@ -763,16 +761,16 @@ mbed_connect_step3(struct connectdata *conn, return CURLE_OK; } -static ssize_t mbed_send(struct connectdata *conn, int sockindex, +static ssize_t mbed_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; int ret = -1; - ret = mbedtls_ssl_write(&backend->ssl, - (unsigned char *)mem, len); + ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len); if(ret < 0) { *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ? @@ -783,15 +781,18 @@ static ssize_t mbed_send(struct connectdata *conn, int sockindex, return ret; } -static void Curl_mbedtls_close_all(struct Curl_easy *data) +static void mbedtls_close_all(struct Curl_easy *data) { (void)data; } -static void Curl_mbedtls_close(struct connectdata *conn, int sockindex) +static void mbedtls_close(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; + + (void) data; mbedtls_pk_free(&backend->pk); mbedtls_x509_crt_free(&backend->clicert); mbedtls_x509_crt_free(&backend->cacert); @@ -804,16 +805,16 @@ static void Curl_mbedtls_close(struct connectdata *conn, int sockindex) #endif /* THREADING_SUPPORT */ } -static ssize_t mbed_recv(struct connectdata *conn, int num, +static ssize_t mbed_recv(struct Curl_easy *data, int num, char *buf, size_t buffersize, CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_backend_data *backend = connssl->backend; int ret = -1; ssize_t len = -1; - memset(buf, 0, buffersize); ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, buffersize); @@ -831,13 +832,13 @@ static ssize_t mbed_recv(struct connectdata *conn, int num, return len; } -static void Curl_mbedtls_session_free(void *ptr) +static void mbedtls_session_free(void *ptr) { mbedtls_ssl_session_free(ptr); free(ptr); } -static size_t Curl_mbedtls_version(char *buffer, size_t size) +static size_t mbedtls_version(char *buffer, size_t size) { #ifdef MBEDTLS_VERSION_C /* if mbedtls_version_get_number() is available it is better */ @@ -849,8 +850,8 @@ static size_t Curl_mbedtls_version(char *buffer, size_t size) #endif } -static CURLcode Curl_mbedtls_random(struct Curl_easy *data, - unsigned char *entropy, size_t length) +static CURLcode mbedtls_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) { #if defined(MBEDTLS_CTR_DRBG_C) int ret = -1; @@ -868,7 +869,7 @@ static CURLcode Curl_mbedtls_random(struct Curl_easy *data, #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ - failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n", + failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s", -ret, errorbuf); } else { @@ -878,7 +879,7 @@ static CURLcode Curl_mbedtls_random(struct Curl_easy *data, #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ - failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", + failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s", -ret, errorbuf); } } @@ -899,13 +900,13 @@ static CURLcode Curl_mbedtls_random(struct Curl_easy *data, } static CURLcode -mbed_connect_common(struct connectdata *conn, +mbed_connect_common(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool nonblocking, bool *done) { CURLcode retcode; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; timediff_t timeout_ms; @@ -926,7 +927,7 @@ mbed_connect_common(struct connectdata *conn, failf(data, "SSL connection timeout"); return CURLE_OPERATION_TIMEDOUT; } - retcode = mbed_connect_step1(conn, sockindex); + retcode = mbed_connect_step1(data, conn, sockindex); if(retcode) return retcode; } @@ -981,7 +982,7 @@ mbed_connect_common(struct connectdata *conn, * ensuring that a client using select() or epoll() will always * have a valid fdset to wait on. */ - retcode = mbed_connect_step2(conn, sockindex); + retcode = mbed_connect_step2(data, conn, sockindex); if(retcode || (nonblocking && (ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || @@ -991,7 +992,7 @@ mbed_connect_common(struct connectdata *conn, } /* repeat step2 until all transactions are done. */ if(ssl_connect_3 == connssl->connecting_state) { - retcode = mbed_connect_step3(conn, sockindex); + retcode = mbed_connect_step3(data, conn, sockindex); if(retcode) return retcode; } @@ -1011,19 +1012,21 @@ mbed_connect_common(struct connectdata *conn, return CURLE_OK; } -static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) +static CURLcode mbedtls_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { - return mbed_connect_common(conn, sockindex, TRUE, done); + return mbed_connect_common(data, conn, sockindex, TRUE, done); } -static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex) +static CURLcode mbedtls_connect(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { CURLcode retcode; bool done = FALSE; - retcode = mbed_connect_common(conn, sockindex, FALSE, &done); + retcode = mbed_connect_common(data, conn, sockindex, FALSE, &done); if(retcode) return retcode; @@ -1036,28 +1039,28 @@ static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex) * return 0 error initializing SSL * return 1 SSL initialized successfully */ -static int Curl_mbedtls_init(void) +static int mbedtls_init(void) { return Curl_mbedtlsthreadlock_thread_setup(); } -static void Curl_mbedtls_cleanup(void) +static void mbedtls_cleanup(void) { (void)Curl_mbedtlsthreadlock_thread_cleanup(); } -static bool Curl_mbedtls_data_pending(const struct connectdata *conn, - int sockindex) +static bool mbedtls_data_pending(const struct connectdata *conn, + int sockindex) { const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0; } -static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input, - size_t inputlen, - unsigned char *sha256sum, - size_t sha256len UNUSED_PARAM) +static CURLcode mbedtls_sha256sum(const unsigned char *input, + size_t inputlen, + unsigned char *sha256sum, + size_t sha256len UNUSED_PARAM) { (void)sha256len; #if MBEDTLS_VERSION_NUMBER < 0x02070000 @@ -1070,8 +1073,8 @@ static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input, return CURLE_OK; } -static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) +static void *mbedtls_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) { struct ssl_backend_data *backend = connssl->backend; (void)info; @@ -1087,26 +1090,25 @@ const struct Curl_ssl Curl_ssl_mbedtls = { sizeof(struct ssl_backend_data), - Curl_mbedtls_init, /* init */ - Curl_mbedtls_cleanup, /* cleanup */ - Curl_mbedtls_version, /* version */ + mbedtls_init, /* init */ + mbedtls_cleanup, /* cleanup */ + mbedtls_version, /* version */ Curl_none_check_cxn, /* check_cxn */ Curl_none_shutdown, /* shutdown */ - Curl_mbedtls_data_pending, /* data_pending */ - Curl_mbedtls_random, /* random */ + mbedtls_data_pending, /* data_pending */ + mbedtls_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ - Curl_mbedtls_connect, /* connect */ - Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */ - Curl_mbedtls_get_internals, /* get_internals */ - Curl_mbedtls_close, /* close_one */ - Curl_mbedtls_close_all, /* close_all */ - Curl_mbedtls_session_free, /* session_free */ + mbedtls_connect, /* connect */ + mbedtls_connect_nonblocking, /* connect_nonblocking */ + mbedtls_get_internals, /* get_internals */ + mbedtls_close, /* close_one */ + mbedtls_close_all, /* close_all */ + mbedtls_session_free, /* session_free */ Curl_none_set_engine, /* set_engine */ Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - Curl_none_md5sum, /* md5sum */ - Curl_mbedtls_sha256sum /* sha256sum */ + mbedtls_sha256sum /* sha256sum */ }; #endif /* USE_MBEDTLS */ diff --git a/libs/libcurl/src/vtls/mesalink.c b/libs/libcurl/src/vtls/mesalink.c index 309786cf83..b6d1005ec1 100644 --- a/libs/libcurl/src/vtls/mesalink.c +++ b/libs/libcurl/src/vtls/mesalink.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2017 - 2018, Yiming Jing, - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -89,10 +89,10 @@ static int do_file_type(const char *type) * layer and do all necessary magic. */ static CURLcode -mesalink_connect_step1(struct connectdata *conn, int sockindex) +mesalink_connect_step1(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { char *ciphers; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct in_addr addr4; #ifdef ENABLE_IPV6 @@ -260,11 +260,11 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex) if(SSL_SET_OPTION(primary.sessionid)) { void *ssl_sessionid = NULL; - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); failf( data, "SSL: SSL_set_session failed: %s", @@ -274,7 +274,7 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex) /* Informational message */ infof(data, "SSL re-using session ID\n"); } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } #endif /* MESALINK_HAVE_SESSION */ @@ -288,10 +288,10 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex) } static CURLcode -mesalink_connect_step2(struct connectdata *conn, int sockindex) +mesalink_connect_step2(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { int ret = -1; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; conn->recv[sockindex] = mesalink_recv; @@ -348,27 +348,28 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex) our_ssl_sessionid = SSL_get_session(BACKEND->handle); - Curl_ssl_sessionid_lock(conn); + Curl_ssl_sessionid_lock(data); incache = - !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)); + !(Curl_ssl_getsessionid(data, conn, + &old_ssl_sessionid, NULL, sockindex)); if(incache) { if(old_ssl_sessionid != our_ssl_sessionid) { infof(data, "old SSL session ID is stale, removing\n"); - Curl_ssl_delsessionid(conn, old_ssl_sessionid); + Curl_ssl_delsessionid(data, old_ssl_sessionid); incache = FALSE; } } if(!incache) { result = Curl_ssl_addsessionid( - conn, our_ssl_sessionid, 0 /* unknown size */, sockindex); + data, conn, our_ssl_sessionid, 0 /* unknown size */, sockindex); if(result) { - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); failf(data, "failed to store ssl session"); return result; } } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } #endif /* MESALINK_HAVE_SESSION */ @@ -378,9 +379,10 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex) } static ssize_t -mesalink_send(struct connectdata *conn, int sockindex, const void *mem, +mesalink_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; char error_buffer[MESALINK_MAX_ERROR_SZ]; int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; @@ -395,7 +397,7 @@ mesalink_send(struct connectdata *conn, int sockindex, const void *mem, *curlcode = CURLE_AGAIN; return -1; default: - failf(conn->data, + failf(data, "SSL write: %s, errno %d", ERR_error_string_n(err, error_buffer, sizeof(error_buffer)), SOCKERRNO); @@ -407,10 +409,12 @@ mesalink_send(struct connectdata *conn, int sockindex, const void *mem, } static void -Curl_mesalink_close(struct connectdata *conn, int sockindex) +mesalink_close(struct Curl_easy *data, struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + (void) data; + if(BACKEND->handle) { (void)SSL_shutdown(BACKEND->handle); SSL_free(BACKEND->handle); @@ -423,9 +427,10 @@ Curl_mesalink_close(struct connectdata *conn, int sockindex) } static ssize_t -mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize, +mesalink_recv(struct Curl_easy *data, int num, char *buf, size_t buffersize, CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[num]; char error_buffer[MESALINK_MAX_ERROR_SZ]; int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; @@ -444,7 +449,7 @@ mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize, *curlcode = CURLE_AGAIN; return -1; default: - failf(conn->data, + failf(data, "SSL read: %s, errno %d", ERR_error_string_n(err, error_buffer, sizeof(error_buffer)), SOCKERRNO); @@ -456,13 +461,13 @@ mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize, } static size_t -Curl_mesalink_version(char *buffer, size_t size) +mesalink_version(char *buffer, size_t size) { return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING); } static int -Curl_mesalink_init(void) +mesalink_init(void) { return (SSL_library_init() == SSL_SUCCESS); } @@ -472,11 +477,14 @@ Curl_mesalink_init(void) * socket open (CCC - Clear Command Channel) */ static int -Curl_mesalink_shutdown(struct connectdata *conn, int sockindex) +mesalink_shutdown(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { int retval = 0; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + (void) data; + if(BACKEND->handle) { SSL_free(BACKEND->handle); BACKEND->handle = NULL; @@ -485,11 +493,10 @@ Curl_mesalink_shutdown(struct connectdata *conn, int sockindex) } static CURLcode -mesalink_connect_common(struct connectdata *conn, int sockindex, - bool nonblocking, bool *done) +mesalink_connect_common(struct Curl_easy *data, struct connectdata *conn, + int sockindex, bool nonblocking, bool *done) { CURLcode result; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; timediff_t timeout_ms; @@ -511,7 +518,7 @@ mesalink_connect_common(struct connectdata *conn, int sockindex, return CURLE_OPERATION_TIMEDOUT; } - result = mesalink_connect_step1(conn, sockindex); + result = mesalink_connect_step1(data, conn, sockindex); if(result) return result; } @@ -568,7 +575,7 @@ mesalink_connect_common(struct connectdata *conn, int sockindex, * ensuring that a client using select() or epoll() will always * have a valid fdset to wait on. */ - result = mesalink_connect_step2(conn, sockindex); + result = mesalink_connect_step2(data, conn, sockindex); if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state || @@ -600,19 +607,20 @@ mesalink_connect_common(struct connectdata *conn, int sockindex, } static CURLcode -Curl_mesalink_connect_nonblocking(struct connectdata *conn, int sockindex, - bool *done) +mesalink_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, + int sockindex, bool *done) { - return mesalink_connect_common(conn, sockindex, TRUE, done); + return mesalink_connect_common(data, conn, sockindex, TRUE, done); } static CURLcode -Curl_mesalink_connect(struct connectdata *conn, int sockindex) +mesalink_connect(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { CURLcode result; bool done = FALSE; - result = mesalink_connect_common(conn, sockindex, FALSE, &done); + result = mesalink_connect_common(data, conn, sockindex, FALSE, &done); if(result) return result; @@ -622,8 +630,8 @@ Curl_mesalink_connect(struct connectdata *conn, int sockindex) } static void * -Curl_mesalink_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) +mesalink_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) { (void)info; return BACKEND->handle; @@ -636,26 +644,25 @@ const struct Curl_ssl Curl_ssl_mesalink = { sizeof(struct ssl_backend_data), - Curl_mesalink_init, /* init */ - Curl_none_cleanup, /* cleanup */ - Curl_mesalink_version, /* version */ - Curl_none_check_cxn, /* check_cxn */ - Curl_mesalink_shutdown, /* shutdown */ - Curl_none_data_pending, /* data_pending */ - Curl_none_random, /* random */ + mesalink_init, /* init */ + Curl_none_cleanup, /* cleanup */ + mesalink_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + mesalink_shutdown, /* shutdown */ + Curl_none_data_pending, /* data_pending */ + Curl_none_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ - Curl_mesalink_connect, /* connect */ - Curl_mesalink_connect_nonblocking, /* connect_nonblocking */ - Curl_mesalink_get_internals, /* get_internals */ - Curl_mesalink_close, /* close_one */ - Curl_none_close_all, /* close_all */ - Curl_none_session_free, /* session_free */ - Curl_none_set_engine, /* set_engine */ - Curl_none_set_engine_default, /* set_engine_default */ - Curl_none_engines_list, /* engines_list */ - Curl_none_false_start, /* false_start */ - Curl_none_md5sum, /* md5sum */ - NULL /* sha256sum */ + mesalink_connect, /* connect */ + mesalink_connect_nonblocking, /* connect_nonblocking */ + mesalink_get_internals, /* get_internals */ + mesalink_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + NULL /* sha256sum */ }; #endif diff --git a/libs/libcurl/src/vtls/nss.c b/libs/libcurl/src/vtls/nss.c index 59649ccc3a..e5ab71cdf6 100644 --- a/libs/libcurl/src/vtls/nss.c +++ b/libs/libcurl/src/vtls/nss.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -443,7 +443,7 @@ static CURLcode insert_wrapped_ptr(struct Curl_llist *list, void *ptr) /* Call PK11_CreateGenericObject() with the given obj_class and filename. If * the call succeeds, append the object handle to the list of objects so that - * the object can be destroyed in Curl_nss_close(). */ + * the object can be destroyed in nss_close(). */ static CURLcode nss_create_object(struct ssl_connect_data *connssl, CK_OBJECT_CLASS obj_class, const char *filename, bool cacert) @@ -508,7 +508,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *connssl, /* Destroy the NSS object whose handle is given by ptr. This function is * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy - * NSS objects in Curl_nss_close() */ + * NSS objects in nss_close() */ static void nss_destroy_object(void *user, void *ptr) { struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr; @@ -587,7 +587,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der) return CURLE_SSL_CRL_BADFILE; } - /* store the CRL item so that we can free it in Curl_nss_cleanup() */ + /* store the CRL item so that we can free it in nss_cleanup() */ if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) { if(SECSuccess == CERT_UncacheCRL(db, crl_der)) SECITEM_FreeItem(crl_der, PR_TRUE); @@ -665,14 +665,13 @@ fail: return CURLE_SSL_CRL_BADFILE; } -static CURLcode nss_load_key(struct connectdata *conn, int sockindex, - char *key_file) +static CURLcode nss_load_key(struct Curl_easy *data, struct connectdata *conn, + int sockindex, char *key_file) { PK11SlotInfo *slot, *tmp; SECStatus status; CURLcode result; struct ssl_connect_data *ssl = conn->ssl; - struct Curl_easy *data = conn->data; (void)sockindex; /* unused */ @@ -701,15 +700,15 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex, return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; } -static int display_error(struct connectdata *conn, PRInt32 err, +static int display_error(struct Curl_easy *data, PRInt32 err, const char *filename) { switch(err) { case SEC_ERROR_BAD_PASSWORD: - failf(conn->data, "Unable to load client key: Incorrect password"); + failf(data, "Unable to load client key: Incorrect password"); return 1; case SEC_ERROR_UNKNOWN_CERT: - failf(conn->data, "Unable to load certificate %s", filename); + failf(data, "Unable to load certificate %s", filename); return 1; default: break; @@ -717,17 +716,16 @@ static int display_error(struct connectdata *conn, PRInt32 err, return 0; /* The caller will print a generic error */ } -static CURLcode cert_stuff(struct connectdata *conn, int sockindex, - char *cert_file, char *key_file) +static CURLcode cert_stuff(struct Curl_easy *data, struct connectdata *conn, + int sockindex, char *cert_file, char *key_file) { - struct Curl_easy *data = conn->data; CURLcode result; if(cert_file) { result = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE); if(result) { const PRErrorCode err = PR_GetError(); - if(!display_error(conn, err, cert_file)) { + if(!display_error(data, err, cert_file)) { const char *err_name = nss_error_to_name(err); failf(data, "unable to load client cert: %d (%s)", err, err_name); } @@ -738,13 +736,13 @@ static CURLcode cert_stuff(struct connectdata *conn, int sockindex, if(key_file || (is_file(cert_file))) { if(key_file) - result = nss_load_key(conn, sockindex, key_file); + result = nss_load_key(data, conn, sockindex, key_file); else /* In case the cert file also has the key */ - result = nss_load_key(conn, sockindex, cert_file); + result = nss_load_key(data, conn, sockindex, cert_file); if(result) { const PRErrorCode err = PR_GetError(); - if(!display_error(conn, err, key_file)) { + if(!display_error(data, err, key_file)) { const char *err_name = nss_error_to_name(err); failf(data, "unable to load client key: %d (%s)", err, err_name); } @@ -771,7 +769,8 @@ static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg) static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, PRBool isServer) { - struct connectdata *conn = (struct connectdata *)arg; + struct Curl_easy *data = (struct Curl_easy *)arg; + struct connectdata *conn = data->conn; #ifdef SSL_ENABLE_OCSP_STAPLING if(SSL_CONN_CONFIG(verifystatus)) { @@ -779,12 +778,12 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd); if(!csa) { - failf(conn->data, "Invalid OCSP response"); + failf(data, "Invalid OCSP response"); return SECFailure; } if(csa->len == 0) { - failf(conn->data, "No OCSP response received"); + failf(data, "No OCSP response received"); return SECFailure; } @@ -794,14 +793,14 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, ); if(cacheResult != SECSuccess) { - failf(conn->data, "Invalid OCSP response"); + failf(data, "Invalid OCSP response"); return cacheResult; } } #endif if(!SSL_CONN_CONFIG(verifypeer)) { - infof(conn->data, "skipping SSL peer certificate verification\n"); + infof(data, "skipping SSL peer certificate verification\n"); return SECSuccess; } @@ -813,7 +812,8 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, */ static void HandshakeCallback(PRFileDesc *sock, void *arg) { - struct connectdata *conn = (struct connectdata*) arg; + struct Curl_easy *data = (struct Curl_easy *)arg; + struct connectdata *conn = data->conn; unsigned int buflenmax = 50; unsigned char buf[50]; unsigned int buflen; @@ -833,15 +833,15 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) #endif case SSL_NEXT_PROTO_NO_SUPPORT: case SSL_NEXT_PROTO_NO_OVERLAP: - infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n"); + infof(data, "ALPN/NPN, server did not agree to a protocol\n"); return; #ifdef SSL_ENABLE_ALPN case SSL_NEXT_PROTO_SELECTED: - infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf); + infof(data, "ALPN, server accepted to use %.*s\n", buflen, buf); break; #endif case SSL_NEXT_PROTO_NEGOTIATED: - infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf); + infof(data, "NPN, server accepted to use %.*s\n", buflen, buf); break; } @@ -856,7 +856,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_1_1; } - Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } } @@ -865,8 +865,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data, PRBool *canFalseStart) { - struct connectdata *conn = client_data; - struct Curl_easy *data = conn->data; + struct Curl_easy *data = (struct Curl_easy *)client_data; SSLChannelInfo channelInfo; SSLCipherSuiteInfo cipherInfo; @@ -949,7 +948,7 @@ static void display_cert_info(struct Curl_easy *data, PR_Free(common_name); } -static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock) +static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock) { CURLcode result = CURLE_OK; SSLChannelInfo channel; @@ -965,16 +964,16 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock) channel.cipherSuite) { if(SSL_GetCipherSuiteInfo(channel.cipherSuite, &suite, sizeof(suite)) == SECSuccess) { - infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName); + infof(data, "SSL connection using %s\n", suite.cipherSuiteName); } } cert = SSL_PeerCertificate(sock); if(cert) { - infof(conn->data, "Server certificate:\n"); + infof(data, "Server certificate:\n"); - if(!conn->data->set.ssl.certinfo) { - display_cert_info(conn->data, cert); + if(!data->set.ssl.certinfo) { + display_cert_info(data, cert); CERT_DestroyCertificate(cert); } else { @@ -995,10 +994,10 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock) } } - result = Curl_ssl_init_certinfo(conn->data, i); + result = Curl_ssl_init_certinfo(data, i); if(!result) { for(i = 0; cert; cert = cert2) { - result = Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data, + result = Curl_extract_certinfo(data, i++, (char *)cert->derCert.data, (char *)cert->derCert.data + cert->derCert.len); if(result) @@ -1021,8 +1020,8 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock) static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) { - struct connectdata *conn = (struct connectdata *)arg; - struct Curl_easy *data = conn->data; + struct Curl_easy *data = (struct Curl_easy *)arg; + struct connectdata *conn = data->conn; PRErrorCode err = PR_GetError(); CERTCertificate *cert; @@ -1335,7 +1334,7 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir) infof(data, "Initializing NSS with certpath: %s\n", certpath); nss_context = NSS_InitContext(certpath, "", "", "", &initparams, - NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); free(certpath); if(nss_context != NULL) @@ -1360,7 +1359,7 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir) } /* data might be NULL */ -static CURLcode nss_init(struct Curl_easy *data) +static CURLcode nss_setup(struct Curl_easy *data) { char *cert_dir; struct_stat st; @@ -1369,7 +1368,7 @@ static CURLcode nss_init(struct Curl_easy *data) if(initialized) return CURLE_OK; - /* list of all CRL items we need to destroy in Curl_nss_cleanup() */ + /* list of all CRL items we need to destroy in nss_cleanup() */ Curl_llist_init(&nss_crl_list, nss_destroy_crl_item); /* First we check if $SSL_DIR points to a valid dir */ @@ -1423,7 +1422,7 @@ static CURLcode nss_init(struct Curl_easy *data) * @retval 0 error initializing SSL * @retval 1 SSL initialized successfully */ -static int Curl_nss_init(void) +static int nss_init(void) { /* curl_global_init() is not thread-safe so this test is ok */ if(nss_initlock == NULL) { @@ -1451,14 +1450,14 @@ CURLcode Curl_nss_force_init(struct Curl_easy *data) } PR_Lock(nss_initlock); - result = nss_init(data); + result = nss_setup(data); PR_Unlock(nss_initlock); return result; } /* Global cleanup */ -static void Curl_nss_cleanup(void) +static void nss_cleanup(void) { /* This function isn't required to be threadsafe and this is only done * as a safety feature. @@ -1498,7 +1497,7 @@ static void Curl_nss_cleanup(void) * 0 means the connection has been closed * -1 means the connection status is unknown */ -static int Curl_nss_check_cxn(struct connectdata *conn) +static int nss_check_cxn(struct connectdata *conn) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; struct ssl_backend_data *backend = connssl->backend; @@ -1517,7 +1516,7 @@ static int Curl_nss_check_cxn(struct connectdata *conn) return -1; /* connection status unknown */ } -static void nss_close(struct ssl_connect_data *connssl) +static void close_one(struct ssl_connect_data *connssl) { /* before the cleanup, check whether we are using a client certificate */ struct ssl_backend_data *backend = connssl->backend; @@ -1547,7 +1546,8 @@ static void nss_close(struct ssl_connect_data *connssl) /* * This function is called when an SSL connection is closed. */ -static void Curl_nss_close(struct connectdata *conn, int sockindex) +static void nss_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; #ifndef CURL_DISABLE_PROXY @@ -1555,6 +1555,7 @@ static void Curl_nss_close(struct connectdata *conn, int sockindex) #endif struct ssl_backend_data *backend = connssl->backend; + (void)data; if(backend->handle #ifndef CURL_DISABLE_PROXY || connssl_proxy->backend->handle @@ -1573,9 +1574,9 @@ static void Curl_nss_close(struct connectdata *conn, int sockindex) a double close leading to crash. */ connssl_proxy->backend->handle = NULL; - nss_close(connssl_proxy); + close_one(connssl_proxy); #endif - nss_close(connssl); + close_one(connssl); } /* return true if NSS can provide error code (and possibly msg) for the @@ -1611,10 +1612,10 @@ static bool is_cc_error(PRInt32 err) static Curl_recv nss_recv; static Curl_send nss_send; -static CURLcode nss_load_ca_certificates(struct connectdata *conn, +static CURLcode nss_load_ca_certificates(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; const char *cafile = SSL_CONN_CONFIG(CAfile); const char *capath = SSL_CONN_CONFIG(CApath); bool use_trust_module; @@ -1819,14 +1820,14 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl, return CURLE_OK; } -static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) +static CURLcode nss_setup_connect(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { PRFileDesc *model = NULL; PRFileDesc *nspr_io = NULL; PRFileDesc *nspr_io_stub = NULL; PRBool ssl_no_cache; PRBool ssl_cbc_random_iv; - struct Curl_easy *data = conn->data; curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; @@ -1849,11 +1850,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) backend->data = data; - /* list of all NSS objects we need to destroy in Curl_nss_close() */ + /* list of all NSS objects we need to destroy in nss_do_close() */ Curl_llist_init(&backend->obj_list, nss_destroy_object); PR_Lock(nss_initlock); - result = nss_init(conn->data); + result = nss_setup(data); if(result) { PR_Unlock(nss_initlock); goto error; @@ -1933,20 +1934,20 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) /* bypass the default SSL_AuthCertificate() hook in case we do not want to * verify peer */ - if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess) + if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, data) != SECSuccess) goto error; /* not checked yet */ SSL_SET_OPTION_LVALUE(certverifyresult) = 0; - if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess) + if(SSL_BadCertHook(model, BadCertHandler, data) != SECSuccess) goto error; - if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess) + if(SSL_HandshakeCallback(model, HandshakeCallback, data) != SECSuccess) goto error; { - const CURLcode rv = nss_load_ca_certificates(conn, sockindex); + const CURLcode rv = nss_load_ca_certificates(data, conn, sockindex); if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer)) /* not a fatal error because we are not going to verify the peer */ infof(data, "warning: CA certificates failed to load\n"); @@ -1972,7 +1973,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) backend->obj_clicert = NULL; } else { - CURLcode rv = cert_stuff(conn, sockindex, + CURLcode rv = cert_stuff(data, conn, sockindex, SSL_SET_OPTION(primary.clientcert), SSL_SET_OPTION(key)); if(rv) { @@ -2071,7 +2072,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; if(SSL_SetCanFalseStartCallback(backend->handle, CanFalseStartCallback, - conn) != SECSuccess) + data) != SECSuccess) goto error; } #endif @@ -2125,11 +2126,11 @@ error: return nss_fail_connect(connssl, data, result); } -static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) +static CURLcode nss_do_connect(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; - struct Curl_easy *data = conn->data; CURLcode result = CURLE_SSL_CONNECT_ERROR; PRUint32 timeout; @@ -2154,7 +2155,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) goto error; } - result = display_conn_info(conn, backend->handle); + result = display_conn_info(data, backend->handle); if(result) goto error; @@ -2188,11 +2189,11 @@ error: return nss_fail_connect(connssl, data, result); } -static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, +static CURLcode nss_connect_common(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool *done) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - struct Curl_easy *data = conn->data; const bool blocking = (done == NULL); CURLcode result; @@ -2203,7 +2204,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, } if(connssl->connecting_state == ssl_connect_1) { - result = nss_setup_connect(conn, sockindex); + result = nss_setup_connect(data, conn, sockindex); if(result) /* we do not expect CURLE_AGAIN from nss_setup_connect() */ return result; @@ -2216,7 +2217,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, if(result) return result; - result = nss_do_connect(conn, sockindex); + result = nss_do_connect(data, conn, sockindex); switch(result) { case CURLE_OK: break; @@ -2249,30 +2250,33 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, return CURLE_OK; } -static CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) +static CURLcode nss_connect(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { - return nss_connect_common(conn, sockindex, /* blocking */ NULL); + return nss_connect_common(data, conn, sockindex, /* blocking */ NULL); } -static CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) +static CURLcode nss_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { - return nss_connect_common(conn, sockindex, done); + return nss_connect_common(data, conn, sockindex, done); } -static ssize_t nss_send(struct connectdata *conn, /* connection data */ +static ssize_t nss_send(struct Curl_easy *data, /* transfer */ int sockindex, /* socketindex */ const void *mem, /* send this data */ size_t len, /* amount to write */ CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; ssize_t rc; /* The SelectClientCert() hook uses this for infof() and failf() but the handle stored in nss_setup_connect() could have already been freed. */ - backend->data = conn->data; + backend->data = data; rc = PR_Send(backend->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT); if(rc < 0) { @@ -2282,10 +2286,10 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */ else { /* print the error number and error string */ const char *err_name = nss_error_to_name(err); - infof(conn->data, "SSL write: error %d (%s)\n", err, err_name); + infof(data, "SSL write: error %d (%s)\n", err, err_name); /* print a human-readable message describing the error if available */ - nss_print_error_message(conn->data, err); + nss_print_error_message(data, err); *curlcode = (is_cc_error(err)) ? CURLE_SSL_CERTPROBLEM @@ -2298,19 +2302,20 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */ return rc; /* number of bytes */ } -static ssize_t nss_recv(struct connectdata *conn, /* connection data */ +static ssize_t nss_recv(struct Curl_easy *data, /* transfer */ int sockindex, /* socketindex */ - char *buf, /* store read data here */ - size_t buffersize, /* max amount to read */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; ssize_t nread; /* The SelectClientCert() hook uses this for infof() and failf() but the handle stored in nss_setup_connect() could have already been freed. */ - backend->data = conn->data; + backend->data = data; nread = PR_Recv(backend->handle, buf, (int)buffersize, 0, PR_INTERVAL_NO_WAIT); @@ -2323,10 +2328,10 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */ else { /* print the error number and error string */ const char *err_name = nss_error_to_name(err); - infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name); + infof(data, "SSL read: errno %d (%s)\n", err, err_name); /* print a human-readable message describing the error if available */ - nss_print_error_message(conn->data, err); + nss_print_error_message(data, err); *curlcode = (is_cc_error(err)) ? CURLE_SSL_CERTPROBLEM @@ -2339,9 +2344,9 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */ return nread; } -static size_t Curl_nss_version(char *buffer, size_t size) +static size_t nss_version(char *buffer, size_t size) { - return msnprintf(buffer, size, "NSS/%s", NSS_VERSION); + return msnprintf(buffer, size, "NSS/%s", NSS_GetVersion()); } /* data might be NULL */ @@ -2352,9 +2357,9 @@ static int Curl_nss_seed(struct Curl_easy *data) } /* data might be NULL */ -static CURLcode Curl_nss_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length) +static CURLcode nss_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) { Curl_nss_seed(data); /* Initiate the seed if not already done */ @@ -2365,28 +2370,10 @@ static CURLcode Curl_nss_random(struct Curl_easy *data, return CURLE_OK; } -static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len) -{ - PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5); - unsigned int MD5out; - - if(!MD5pw) - return CURLE_NOT_BUILT_IN; - - PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen)); - PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len)); - PK11_DestroyContext(MD5pw, PR_TRUE); - - return CURLE_OK; -} - -static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum, /* output */ - size_t sha256len) +static CURLcode nss_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) { PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256); unsigned int SHA256out; @@ -2401,7 +2388,7 @@ static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */ return CURLE_OK; } -static bool Curl_nss_cert_status_request(void) +static bool nss_cert_status_request(void) { #ifdef SSL_ENABLE_OCSP_STAPLING return TRUE; @@ -2410,7 +2397,7 @@ static bool Curl_nss_cert_status_request(void) #endif } -static bool Curl_nss_false_start(void) +static bool nss_false_start(void) { #if NSSVERNUM >= 0x030f04 /* 3.15.4 */ return TRUE; @@ -2419,7 +2406,7 @@ static bool Curl_nss_false_start(void) #endif } -static void *Curl_nss_get_internals(struct ssl_connect_data *connssl, +static void *nss_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { struct ssl_backend_data *backend = connssl->backend; @@ -2437,28 +2424,27 @@ const struct Curl_ssl Curl_ssl_nss = { sizeof(struct ssl_backend_data), - Curl_nss_init, /* init */ - Curl_nss_cleanup, /* cleanup */ - Curl_nss_version, /* version */ - Curl_nss_check_cxn, /* check_cxn */ + nss_init, /* init */ + nss_cleanup, /* cleanup */ + nss_version, /* version */ + nss_check_cxn, /* check_cxn */ /* NSS has no shutdown function provided and thus always fail */ Curl_none_shutdown, /* shutdown */ Curl_none_data_pending, /* data_pending */ - Curl_nss_random, /* random */ - Curl_nss_cert_status_request, /* cert_status_request */ - Curl_nss_connect, /* connect */ - Curl_nss_connect_nonblocking, /* connect_nonblocking */ - Curl_nss_get_internals, /* get_internals */ - Curl_nss_close, /* close_one */ + nss_random, /* random */ + nss_cert_status_request, /* cert_status_request */ + nss_connect, /* connect */ + nss_connect_nonblocking, /* connect_nonblocking */ + nss_get_internals, /* get_internals */ + nss_close, /* close_one */ Curl_none_close_all, /* close_all */ /* NSS has its own session ID cache */ Curl_none_session_free, /* session_free */ Curl_none_set_engine, /* set_engine */ Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ - Curl_nss_false_start, /* false_start */ - Curl_nss_md5sum, /* md5sum */ - Curl_nss_sha256sum /* sha256sum */ + nss_false_start, /* false_start */ + nss_sha256sum /* sha256sum */ }; #endif /* USE_NSS */ diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c index e9c535f8f4..784d9f70e0 100644 --- a/libs/libcurl/src/vtls/openssl.c +++ b/libs/libcurl/src/vtls/openssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -362,6 +362,18 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size) return buf; } +/* Return an extra data index for the transfer data. + * This index can be used with SSL_get_ex_data() and SSL_set_ex_data(). + */ +static int ossl_get_ssl_data_index(void) +{ + static int ssl_ex_data_data_index = -1; + if(ssl_ex_data_data_index < 0) { + ssl_ex_data_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + } + return ssl_ex_data_data_index; +} + /* Return an extra data index for the connection data. * This index can be used with SSL_get_ex_data() and SSL_set_ex_data(). */ @@ -410,7 +422,7 @@ static bool rand_enough(void) return (0 != RAND_status()) ? TRUE : FALSE; } -static CURLcode Curl_ossl_seed(struct Curl_easy *data) +static CURLcode ossl_seed(struct Curl_easy *data) { /* we have the "SSL is seeded" boolean static to prevent multiple time-consuming seedings in vain */ @@ -572,8 +584,7 @@ static bool is_pkcs11_uri(const char *string) #endif -static CURLcode Curl_ossl_set_engine(struct Curl_easy *data, - const char *engine); +static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine); static int SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type, @@ -700,7 +711,7 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in, } static -int cert_stuff(struct connectdata *conn, +int cert_stuff(struct Curl_easy *data, SSL_CTX* ctx, char *cert_file, BIO *cert_bio, @@ -710,7 +721,6 @@ int cert_stuff(struct connectdata *conn, const char *key_type, char *key_passwd) { - struct Curl_easy *data = conn->data; char error_buffer[256]; bool check_privkey = TRUE; @@ -773,7 +783,7 @@ int cert_stuff(struct connectdata *conn, * cert_file is a PKCS#11 URI */ if(!data->state.engine) { if(is_pkcs11_uri(cert_file)) { - if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) { + if(ossl_set_engine(data, "pkcs11") != CURLE_OK) { return 0; } } @@ -972,7 +982,7 @@ int cert_stuff(struct connectdata *conn, * key_file is a PKCS#11 URI */ if(!data->state.engine) { if(is_pkcs11_uri(key_file)) { - if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) { + if(ossl_set_engine(data, "pkcs11") != CURLE_OK) { return 0; } } @@ -1113,7 +1123,7 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size) * @retval 0 error initializing SSL * @retval 1 SSL initialized successfully */ -static int Curl_ossl_init(void) +static int ossl_init(void) { #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ !defined(LIBRESSL_VERSION_NUMBER) @@ -1161,14 +1171,15 @@ static int Curl_ossl_init(void) Curl_tls_keylog_open(); /* Initialize the extra data indexes */ - if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0) + if(ossl_get_ssl_data_index() < 0 || ossl_get_ssl_conn_index() < 0 || + ossl_get_ssl_sockindex_index() < 0) return 0; return 1; } /* Global cleanup */ -static void Curl_ossl_cleanup(void) +static void ossl_cleanup(void) { #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ !defined(LIBRESSL_VERSION_NUMBER) @@ -1212,7 +1223,7 @@ static void Curl_ossl_cleanup(void) * 0 means the connection has been closed * -1 means the connection status is unknown */ -static int Curl_ossl_check_cxn(struct connectdata *conn) +static int ossl_check_cxn(struct connectdata *conn) { /* SSL_peek takes data out of the raw recv buffer without peeking so we use recv MSG_PEEK instead. Bug #795 */ @@ -1258,8 +1269,7 @@ static int Curl_ossl_check_cxn(struct connectdata *conn) /* Selects an OpenSSL crypto engine */ -static CURLcode Curl_ossl_set_engine(struct Curl_easy *data, - const char *engine) +static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine) { #ifdef USE_OPENSSL_ENGINE ENGINE *e; @@ -1289,7 +1299,7 @@ static CURLcode Curl_ossl_set_engine(struct Curl_easy *data, char buf[256]; ENGINE_free(e); - failf(data, "Failed to initialise SSL Engine '%s':\n%s", + failf(data, "Failed to initialise SSL Engine '%s': %s", engine, ossl_strerror(ERR_get_error(), buf, sizeof(buf))); return CURLE_SSL_ENGINE_INITFAILED; } @@ -1304,7 +1314,7 @@ static CURLcode Curl_ossl_set_engine(struct Curl_easy *data, /* Sets engine as default for all SSL operations */ -static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data) +static CURLcode ossl_set_engine_default(struct Curl_easy *data) { #ifdef USE_OPENSSL_ENGINE if(data->state.engine) { @@ -1326,7 +1336,7 @@ static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data) /* Return list of OpenSSL crypto engine names. */ -static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) +static struct curl_slist *ossl_engines_list(struct Curl_easy *data) { struct curl_slist *list = NULL; #ifdef USE_OPENSSL_ENGINE @@ -1346,7 +1356,7 @@ static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) return list; } -static void ossl_close(struct ssl_connect_data *connssl) +static void ossl_closeone(struct ssl_connect_data *connssl) { struct ssl_backend_data *backend = connssl->backend; if(backend->handle) { @@ -1365,11 +1375,13 @@ static void ossl_close(struct ssl_connect_data *connssl) /* * This function is called when an SSL connection is closed. */ -static void Curl_ossl_close(struct connectdata *conn, int sockindex) +static void ossl_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { - ossl_close(&conn->ssl[sockindex]); + (void) data; + ossl_closeone(&conn->ssl[sockindex]); #ifndef CURL_DISABLE_PROXY - ossl_close(&conn->proxy_ssl[sockindex]); + ossl_closeone(&conn->proxy_ssl[sockindex]); #endif } @@ -1377,11 +1389,11 @@ static void Curl_ossl_close(struct connectdata *conn, int sockindex) * This function is called to shut down the SSL layer but keep the * socket open (CCC - Clear Command Channel) */ -static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) +static int ossl_shutdown(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { int retval = 0; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - struct Curl_easy *data = conn->data; char buf[256]; /* We will use this for the OpenSSL error buffer, so it has to be at least 256 bytes long. */ unsigned long sslerror; @@ -1433,7 +1445,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) default: /* openssl/ssl.h says "look at error stack/return value/errno" */ sslerror = ERR_get_error(); - failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d", + failf(data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d", (sslerror ? ossl_strerror(sslerror, buf, sizeof(buf)) : SSL_ERROR_to_str(err)), @@ -1478,7 +1490,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) return retval; } -static void Curl_ossl_session_free(void *ptr) +static void ossl_session_free(void *ptr) { /* free the ID */ SSL_SESSION_free(ptr); @@ -1488,7 +1500,7 @@ static void Curl_ossl_session_free(void *ptr) * This function is called when the 'data' struct is going away. Close * down everything and free all resources! */ -static void Curl_ossl_close_all(struct Curl_easy *data) +static void ossl_close_all(struct Curl_easy *data) { #ifdef USE_OPENSSL_ENGINE if(data->state.engine) { @@ -1582,12 +1594,12 @@ static bool subj_alt_hostcheck(struct Curl_easy *data, in the certificate and must exactly match the IP in the URI. */ -static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) +static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn, + X509 *server_cert) { bool matched = FALSE; int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */ size_t addrlen = 0; - struct Curl_easy *data = conn->data; STACK_OF(GENERAL_NAME) *altnames; #ifdef ENABLE_IPV6 struct in6_addr addr; @@ -1782,14 +1794,13 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) -static CURLcode verifystatus(struct connectdata *conn, +static CURLcode verifystatus(struct Curl_easy *data, struct ssl_connect_data *connssl) { int i, ocsp_status; unsigned char *status; const unsigned char *p; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; OCSP_RESPONSE *rsp = NULL; OCSP_BASICRESP *br = NULL; X509_STORE *st = NULL; @@ -1871,7 +1882,7 @@ static CURLcode verifystatus(struct connectdata *conn, /* Compute the certificate's ID */ cert = SSL_get_peer_certificate(backend->handle); if(!cert) { - failf(data, "Error getting peer certficate"); + failf(data, "Error getting peer certificate"); result = CURLE_SSL_INVALIDCERTSTATUS; goto end; } @@ -2206,15 +2217,15 @@ select_next_proto_cb(SSL *ssl, const unsigned char *in, unsigned int inlen, void *arg) { - struct connectdata *conn = (struct connectdata*) arg; - + struct Curl_easy *data = (struct Curl_easy *)arg; + struct connectdata *conn = data->conn; (void)ssl; #ifdef USE_NGHTTP2 - if(conn->data->set.httpversion >= CURL_HTTP_VERSION_2 && + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN)) { - infof(conn->data, "NPN, negotiated HTTP2 (%s)\n", + infof(data, "NPN, negotiated HTTP2 (%s)\n", NGHTTP2_PROTO_VERSION_ID); conn->negnpn = CURL_HTTP_VERSION_2; return SSL_TLSEXT_ERR_OK; @@ -2223,12 +2234,12 @@ select_next_proto_cb(SSL *ssl, if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) { - infof(conn->data, "NPN, negotiated HTTP1.1\n"); + infof(data, "NPN, negotiated HTTP1.1\n"); conn->negnpn = CURL_HTTP_VERSION_1_1; return SSL_TLSEXT_ERR_OK; } - infof(conn->data, "NPN, no overlap, use HTTP1.1\n"); + infof(data, "NPN, no overlap, use HTTP1.1\n"); *out = (unsigned char *)ALPN_HTTP_1_1; *outlen = ALPN_HTTP_1_1_LENGTH; conn->negnpn = CURL_HTTP_VERSION_1_1; @@ -2359,16 +2370,14 @@ typedef long ctx_option_t; #if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */ static CURLcode set_ssl_version_min_max_legacy(ctx_option_t *ctx_options, - struct connectdata *conn, int sockindex) + struct Curl_easy *data, + struct connectdata *conn, int sockindex) { -#if (OPENSSL_VERSION_NUMBER < 0x1000100FL) || !defined(TLS1_3_VERSION) - /* convoluted #if condition just to avoid compiler warnings on unused - variable */ - struct Curl_easy *data = conn->data; -#endif long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); + (void) data; /* In case it's unused. */ + switch(ssl_version) { case CURL_SSLVERSION_TLSv1_3: #ifdef TLS1_3_VERSION @@ -2443,17 +2452,18 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) struct Curl_easy *data; int sockindex; curl_socket_t *sockindex_ptr; + int data_idx = ossl_get_ssl_data_index(); int connectdata_idx = ossl_get_ssl_conn_index(); int sockindex_idx = ossl_get_ssl_sockindex_index(); - if(connectdata_idx < 0 || sockindex_idx < 0) + if(data_idx < 0 || connectdata_idx < 0 || sockindex_idx < 0) return 0; conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx); if(!conn) return 0; - data = conn->data; + data = (struct Curl_easy *) SSL_get_ex_data(ssl, data_idx); /* The sockindex has been stored as a pointer to an array element */ sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx); @@ -2463,19 +2473,19 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) bool incache; void *old_ssl_sessionid = NULL; - Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + Curl_ssl_sessionid_lock(data); + incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL, sockindex)); if(incache) { if(old_ssl_sessionid != ssl_sessionid) { infof(data, "old SSL session ID is stale, removing\n"); - Curl_ssl_delsessionid(conn, old_ssl_sessionid); + Curl_ssl_delsessionid(data, old_ssl_sessionid); incache = FALSE; } } if(!incache) { - if(!Curl_ssl_addsessionid(conn, ssl_sessionid, + if(!Curl_ssl_addsessionid(data, conn, ssl_sessionid, 0 /* unknown size */, sockindex)) { /* the session has been put into the session cache */ res = 1; @@ -2483,17 +2493,17 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) else failf(data, "failed to store ssl session"); } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } return res; } -static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) +static CURLcode ossl_connect_step1(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { CURLcode result = CURLE_OK; char *ciphers; - struct Curl_easy *data = conn->data; SSL_METHOD_QUAL SSL_METHOD *req_method = NULL; X509_LOOKUP *lookup = NULL; curl_socket_t sockfd = conn->sock[sockindex]; @@ -2528,7 +2538,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); /* Make funny stuff to get random input */ - result = Curl_ossl_seed(data); + result = ossl_seed(data); if(result) return result; @@ -2714,7 +2724,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */ result = set_ssl_version_min_max(backend->ctx, conn); #else - result = set_ssl_version_min_max_legacy(&ctx_options, conn, sockindex); + result = set_ssl_version_min_max_legacy(&ctx_options, data, conn, + sockindex); #endif if(result != CURLE_OK) return result; @@ -2729,7 +2740,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #ifdef HAS_NPN if(conn->bits.tls_enable_npn) - SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, conn); + SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, data); #endif #ifdef HAS_ALPN @@ -2782,7 +2793,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) result = CURLE_OUT_OF_MEMORY; } if(!result && - !cert_stuff(conn, backend->ctx, + !cert_stuff(data, backend->ctx, ssl_cert, ssl_cert_bio, ssl_cert_type, SSL_SET_OPTION(key), ssl_key_bio, SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd))) @@ -3178,30 +3189,43 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #ifdef ENABLE_IPV6 (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && #endif - sni && - !SSL_set_tlsext_host_name(backend->handle, hostname)) - infof(data, "WARNING: failed to configure server name indication (SNI) " - "TLS extension\n"); + sni) { + size_t nlen = strlen(hostname); + if((long)nlen >= data->set.buffer_size) + /* this is seriously messed up */ + return CURLE_SSL_CONNECT_ERROR; + + /* RFC 6066 section 3 says the SNI field is case insensitive, but browsers + send the data lowercase and subsequently there are now numerous servers + out there that don't work unless the name is lowercased */ + Curl_strntolower(data->state.buffer, hostname, nlen); + data->state.buffer[nlen] = 0; + if(!SSL_set_tlsext_host_name(backend->handle, data->state.buffer)) + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); + } #endif /* Check if there's a cached ID we can/should use here! */ if(SSL_SET_OPTION(primary.sessionid)) { void *ssl_sessionid = NULL; + int data_idx = ossl_get_ssl_data_index(); int connectdata_idx = ossl_get_ssl_conn_index(); int sockindex_idx = ossl_get_ssl_sockindex_index(); - if(connectdata_idx >= 0 && sockindex_idx >= 0) { + if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0) { /* Store the data needed for the "new session" callback. * The sockindex is stored as a pointer to an array element. */ + SSL_set_ex_data(backend->handle, data_idx, data); SSL_set_ex_data(backend->handle, connectdata_idx, conn); SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex); } - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(backend->handle, ssl_sessionid)) { - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); failf(data, "SSL: SSL_set_session failed: %s", ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); @@ -3210,7 +3234,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) /* Informational message */ infof(data, "SSL re-using session ID\n"); } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } #ifndef CURL_DISABLE_PROXY @@ -3237,9 +3261,9 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_OK; } -static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) +static CURLcode ossl_connect_step2(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; int err; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; @@ -3385,7 +3409,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) else infof(data, "ALPN, server did not agree to a protocol\n"); - Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } #endif @@ -3491,13 +3515,12 @@ typedef size_t numcert_t; typedef int numcert_t; #endif -static CURLcode get_cert_chain(struct connectdata *conn, +static CURLcode get_cert_chain(struct Curl_easy *data, struct ssl_connect_data *connssl) { CURLcode result; STACK_OF(X509) *sk; int i; - struct Curl_easy *data = conn->data; numcert_t numcerts; BIO *mem; struct ssl_backend_data *backend = connssl->backend; @@ -3772,14 +3795,14 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, * We check certificates to authenticate the server; otherwise we risk * man-in-the-middle attack. */ -static CURLcode servercert(struct connectdata *conn, +static CURLcode servercert(struct Curl_easy *data, + struct connectdata *conn, struct ssl_connect_data *connssl, bool strict) { CURLcode result = CURLE_OK; int rc; long lerr; - struct Curl_easy *data = conn->data; X509 *issuer; BIO *fp = NULL; char error_buffer[256]=""; @@ -3790,7 +3813,7 @@ static CURLcode servercert(struct connectdata *conn, if(data->set.ssl.certinfo) /* we've been asked to gather certificate info! */ - (void)get_cert_chain(conn, connssl); + (void)get_cert_chain(data, connssl); backend->server_cert = SSL_get_peer_certificate(backend->handle); if(!backend->server_cert) { @@ -3826,7 +3849,7 @@ static CURLcode servercert(struct connectdata *conn, BIO_free(mem); if(SSL_CONN_CONFIG(verifyhost)) { - result = verifyhost(conn, backend->server_cert); + result = verifyhost(data, conn, backend->server_cert); if(result) { X509_free(backend->server_cert); backend->server_cert = NULL; @@ -3928,7 +3951,7 @@ static CURLcode servercert(struct connectdata *conn, #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) if(SSL_CONN_CONFIG(verifystatus)) { - result = verifystatus(conn, connssl); + result = verifystatus(data, connssl); if(result) { X509_free(backend->server_cert); backend->server_cert = NULL; @@ -3956,7 +3979,8 @@ static CURLcode servercert(struct connectdata *conn, return result; } -static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) +static CURLcode ossl_connect_step3(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { CURLcode result = CURLE_OK; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; @@ -3970,8 +3994,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) * operations. */ - result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) || - SSL_CONN_CONFIG(verifyhost))); + result = servercert(data, conn, connssl, (SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost))); if(!result) connssl->connecting_state = ssl_connect_done; @@ -3982,13 +4006,13 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) static Curl_recv ossl_recv; static Curl_send ossl_send; -static CURLcode ossl_connect_common(struct connectdata *conn, +static CURLcode ossl_connect_common(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool nonblocking, bool *done) { CURLcode result; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; int what; @@ -4009,7 +4033,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn, return CURLE_OPERATION_TIMEDOUT; } - result = ossl_connect_step1(conn, sockindex); + result = ossl_connect_step1(data, conn, sockindex); if(result) return result; } @@ -4061,7 +4085,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn, * before step2 has completed while ensuring that a client using select() * or epoll() will always have a valid fdset to wait on. */ - result = ossl_connect_step2(conn, sockindex); + result = ossl_connect_step2(data, conn, sockindex); if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || @@ -4071,7 +4095,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn, } /* repeat step2 until all transactions are done. */ if(ssl_connect_3 == connssl->connecting_state) { - result = ossl_connect_step3(conn, sockindex); + result = ossl_connect_step3(data, conn, sockindex); if(result) return result; } @@ -4091,19 +4115,21 @@ static CURLcode ossl_connect_common(struct connectdata *conn, return CURLE_OK; } -static CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done) +static CURLcode ossl_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, + bool *done) { - return ossl_connect_common(conn, sockindex, TRUE, done); + return ossl_connect_common(data, conn, sockindex, TRUE, done); } -static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex) +static CURLcode ossl_connect(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { CURLcode result; bool done = FALSE; - result = ossl_connect_common(conn, sockindex, FALSE, &done); + result = ossl_connect_common(data, conn, sockindex, FALSE, &done); if(result) return result; @@ -4112,8 +4138,8 @@ static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex) return CURLE_OK; } -static bool Curl_ossl_data_pending(const struct connectdata *conn, - int connindex) +static bool ossl_data_pending(const struct connectdata *conn, + int connindex) { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; if(connssl->backend->handle && SSL_pending(connssl->backend->handle)) @@ -4128,9 +4154,9 @@ static bool Curl_ossl_data_pending(const struct connectdata *conn, return FALSE; } -static size_t Curl_ossl_version(char *buffer, size_t size); +static size_t ossl_version(char *buffer, size_t size); -static ssize_t ossl_send(struct connectdata *conn, +static ssize_t ossl_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, @@ -4143,6 +4169,7 @@ static ssize_t ossl_send(struct connectdata *conn, unsigned long sslerror; int memlen; int rc; + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; @@ -4174,7 +4201,7 @@ static ssize_t ossl_send(struct connectdata *conn, strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer)); error_buffer[sizeof(error_buffer) - 1] = '\0'; } - failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d", + failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d", error_buffer, sockerr); *curlcode = CURLE_SEND_ERROR; return -1; @@ -4191,18 +4218,17 @@ static ssize_t ossl_send(struct connectdata *conn, #endif ) { char ver[120]; - Curl_ossl_version(ver, 120); - failf(conn->data, "Error: %s does not support double SSL tunneling.", - ver); + ossl_version(ver, 120); + failf(data, "Error: %s does not support double SSL tunneling.", ver); } else - failf(conn->data, "SSL_write() error: %s", + failf(data, "SSL_write() error: %s", ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); *curlcode = CURLE_SEND_ERROR; return -1; } /* a true error */ - failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d", + failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d", SSL_ERROR_to_str(err), SOCKERRNO); *curlcode = CURLE_SEND_ERROR; return -1; @@ -4211,7 +4237,7 @@ static ssize_t ossl_send(struct connectdata *conn, return (ssize_t)rc; /* number of bytes */ } -static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ +static ssize_t ossl_recv(struct Curl_easy *data, /* transfer */ int num, /* socketindex */ char *buf, /* store read data here */ size_t buffersize, /* max amount to read */ @@ -4221,6 +4247,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ unsigned long sslerror; ssize_t nread; int buffsize; + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_backend_data *backend = connssl->backend; @@ -4264,7 +4291,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer)); error_buffer[sizeof(error_buffer) - 1] = '\0'; } - failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d", + failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d", error_buffer, sockerr); *curlcode = CURLE_RECV_ERROR; return -1; @@ -4286,7 +4313,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ msnprintf(error_buffer, sizeof(error_buffer), "Connection closed abruptly"); } - failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d" + failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d" " (Fatal because this is a curl debug build)", error_buffer, sockerr); *curlcode = CURLE_RECV_ERROR; @@ -4298,7 +4325,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ return nread; } -static size_t Curl_ossl_version(char *buffer, size_t size) +static size_t ossl_version(char *buffer, size_t size) { #ifdef LIBRESSL_VERSION_NUMBER #if LIBRESSL_VERSION_NUMBER < 0x2070100fL @@ -4369,12 +4396,12 @@ static size_t Curl_ossl_version(char *buffer, size_t size) } /* can be called with data == NULL */ -static CURLcode Curl_ossl_random(struct Curl_easy *data, - unsigned char *entropy, size_t length) +static CURLcode ossl_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) { int rc; if(data) { - if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */ + if(ossl_seed(data)) /* Initiate the seed if not already done */ return CURLE_FAILED_INIT; /* couldn't seed for some reason */ } else { @@ -4386,30 +4413,11 @@ static CURLcode Curl_ossl_random(struct Curl_easy *data, return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT); } -static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum /* output */, - size_t unused) -{ - EVP_MD_CTX *mdctx; - unsigned int len = 0; - (void) unused; - - mdctx = EVP_MD_CTX_create(); - if(!mdctx) - return CURLE_OUT_OF_MEMORY; - EVP_DigestInit(mdctx, EVP_md5()); - EVP_DigestUpdate(mdctx, tmp, tmplen); - EVP_DigestFinal_ex(mdctx, md5sum, &len); - EVP_MD_CTX_destroy(mdctx); - return CURLE_OK; -} - #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) -static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum /* output */, - size_t unused) +static CURLcode ossl_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum /* output */, + size_t unused) { EVP_MD_CTX *mdctx; unsigned int len = 0; @@ -4426,7 +4434,7 @@ static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */ } #endif -static bool Curl_ossl_cert_status_request(void) +static bool ossl_cert_status_request(void) { #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) @@ -4436,8 +4444,8 @@ static bool Curl_ossl_cert_status_request(void) #endif } -static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl, - CURLINFO info) +static void *ossl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info) { /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */ struct ssl_backend_data *backend = connssl->backend; @@ -4459,29 +4467,28 @@ const struct Curl_ssl Curl_ssl_openssl = { sizeof(struct ssl_backend_data), - Curl_ossl_init, /* init */ - Curl_ossl_cleanup, /* cleanup */ - Curl_ossl_version, /* version */ - Curl_ossl_check_cxn, /* check_cxn */ - Curl_ossl_shutdown, /* shutdown */ - Curl_ossl_data_pending, /* data_pending */ - Curl_ossl_random, /* random */ - Curl_ossl_cert_status_request, /* cert_status_request */ - Curl_ossl_connect, /* connect */ - Curl_ossl_connect_nonblocking, /* connect_nonblocking */ - Curl_ossl_get_internals, /* get_internals */ - Curl_ossl_close, /* close_one */ - Curl_ossl_close_all, /* close_all */ - Curl_ossl_session_free, /* session_free */ - Curl_ossl_set_engine, /* set_engine */ - Curl_ossl_set_engine_default, /* set_engine_default */ - Curl_ossl_engines_list, /* engines_list */ - Curl_none_false_start, /* false_start */ - Curl_ossl_md5sum, /* md5sum */ + ossl_init, /* init */ + ossl_cleanup, /* cleanup */ + ossl_version, /* version */ + ossl_check_cxn, /* check_cxn */ + ossl_shutdown, /* shutdown */ + ossl_data_pending, /* data_pending */ + ossl_random, /* random */ + ossl_cert_status_request, /* cert_status_request */ + ossl_connect, /* connect */ + ossl_connect_nonblocking, /* connect_nonblocking */ + ossl_get_internals, /* get_internals */ + ossl_close, /* close_one */ + ossl_close_all, /* close_all */ + ossl_session_free, /* session_free */ + ossl_set_engine, /* set_engine */ + ossl_set_engine_default, /* set_engine_default */ + ossl_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) - Curl_ossl_sha256sum /* sha256sum */ + ossl_sha256sum /* sha256sum */ #else - NULL /* sha256sum */ + NULL /* sha256sum */ #endif }; diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c index d7bc38917f..0668f98f29 100644 --- a/libs/libcurl/src/vtls/schannel.c +++ b/libs/libcurl/src/vtls/schannel.c @@ -5,9 +5,9 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * Copyright (C) 2012 - 2016, Marc Hoersken, * Copyright (C) 2012, Mark Salisbury, - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -142,7 +142,8 @@ static Curl_recv schannel_recv; static Curl_send schannel_send; -static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, +static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, + struct connectdata *conn, int sockindex, const char *pinnedpubkey); static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType, @@ -162,9 +163,9 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr, } static CURLcode -set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn) +set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct Curl_easy *data, + struct connectdata *conn) { - struct Curl_easy *data = conn->data; long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); long i = ssl_version; @@ -405,10 +406,10 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, #endif static CURLcode -schannel_connect_step1(struct connectdata *conn, int sockindex) +schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { ssize_t written = -1; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SecBuffer outbuf; SecBufferDesc outbuf_desc; @@ -493,8 +494,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) /* check for an existing re-usable credential handle */ if(SSL_SET_OPTION(primary.sessionid)) { - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, + (void **)&old_cred, NULL, sockindex)) { BACKEND->cred = old_cred; DEBUGF(infof(data, "schannel: re-using existing credential handle\n")); @@ -504,7 +506,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) "schannel: incremented credential handle refcount = %d\n", BACKEND->cred->refcount)); } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } if(!BACKEND->cred) { @@ -563,7 +565,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: { - result = set_ssl_version_min_max(&schannel_cred, conn); + result = set_ssl_version_min_max(&schannel_cred, data, conn); if(result != CURLE_OK) return result; break; @@ -956,7 +958,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) "sending %lu bytes...\n", outbuf.cbBuffer)); /* send initial handshake data which is now stored in output buffer */ - result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, + result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer, outbuf.cbBuffer, &written); s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { @@ -980,11 +982,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) } static CURLcode -schannel_connect_step2(struct connectdata *conn, int sockindex) +schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { int i; ssize_t nread = -1, written = -1; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; unsigned char *reallocated_buffer; SecBuffer outbuf[3]; @@ -1153,7 +1155,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) "sending %lu bytes...\n", outbuf[i].cbBuffer)); /* send handshake token to server */ - result = Curl_write_plain(conn, conn->sock[sockindex], + result = Curl_write_plain(data, conn->sock[sockindex], outbuf[i].pvBuffer, outbuf[i].cbBuffer, &written); if((result != CURLE_OK) || @@ -1252,7 +1254,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; if(pubkey_ptr) { - result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr); + result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr); if(result) { failf(data, "SSL: public key does not match pinned public key!"); return result; @@ -1261,7 +1263,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) #ifdef HAS_MANUAL_VERIFY_API if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) { - return Curl_verify_certificate(conn, sockindex); + return Curl_verify_certificate(data, conn, sockindex); } #endif @@ -1305,7 +1307,7 @@ cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count) struct Adder_args { - struct connectdata *conn; + struct Curl_easy *data; CURLcode result; int idx; int certs_count; @@ -1320,17 +1322,18 @@ add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg) const char *beg = (const char *) ccert_context->pbCertEncoded; const char *end = beg + ccert_context->cbCertEncoded; int insert_index = (args->certs_count - 1) - args->idx; - args->result = Curl_extract_certinfo(args->conn, insert_index, beg, end); + args->result = Curl_extract_certinfo(args->data, insert_index, + beg, end); args->idx++; } return args->result == CURLE_OK; } static CURLcode -schannel_connect_step3(struct connectdata *conn, int sockindex) +schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; @@ -1400,7 +1403,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) } else infof(data, "ALPN, server did not agree to a protocol\n"); - Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } #endif @@ -1410,24 +1413,24 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) bool incache; struct Curl_schannel_cred *old_cred = NULL; - Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, + Curl_ssl_sessionid_lock(data); + incache = !(Curl_ssl_getsessionid(data, conn, (void **)&old_cred, NULL, sockindex)); if(incache) { if(old_cred != BACKEND->cred) { DEBUGF(infof(data, "schannel: old credential handle is stale, removing\n")); /* we're not taking old_cred ownership here, no refcount++ is needed */ - Curl_ssl_delsessionid(conn, (void *)old_cred); + Curl_ssl_delsessionid(data, (void *)old_cred); incache = FALSE; } } if(!incache) { - result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred, + result = Curl_ssl_addsessionid(data, conn, (void *)BACKEND->cred, sizeof(struct Curl_schannel_cred), sockindex); if(result) { - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); failf(data, "schannel: failed to store credential handle"); return result; } @@ -1438,7 +1441,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) "schannel: stored credential handle in session cache\n")); } } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } if(data->set.ssl.certinfo) { @@ -1458,7 +1461,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) result = Curl_ssl_init_certinfo(data, certs_count); if(!result) { struct Adder_args args; - args.conn = conn; + args.data = data; args.idx = 0; args.certs_count = certs_count; traverse_cert_store(ccert_context, add_cert_to_certinfo, &args); @@ -1475,11 +1478,10 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) } static CURLcode -schannel_connect_common(struct connectdata *conn, int sockindex, - bool nonblocking, bool *done) +schannel_connect_common(struct Curl_easy *data, struct connectdata *conn, + int sockindex, bool nonblocking, bool *done) { CURLcode result; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; timediff_t timeout_ms; @@ -1501,7 +1503,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex, return CURLE_OPERATION_TIMEDOUT; } - result = schannel_connect_step1(conn, sockindex); + result = schannel_connect_step1(data, conn, sockindex); if(result) return result; } @@ -1556,7 +1558,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex, * ensuring that a client using select() or epoll() will always * have a valid fdset to wait on. */ - result = schannel_connect_step2(conn, sockindex); + result = schannel_connect_step2(data, conn, sockindex); if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || @@ -1566,7 +1568,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex, } /* repeat step2 until all transactions are done. */ if(ssl_connect_3 == connssl->connecting_state) { - result = schannel_connect_step3(conn, sockindex); + result = schannel_connect_step3(data, conn, sockindex); if(result) return result; } @@ -1597,12 +1599,13 @@ schannel_connect_common(struct connectdata *conn, int sockindex, } static ssize_t -schannel_send(struct connectdata *conn, int sockindex, +schannel_send(struct Curl_easy *data, int sockindex, const void *buf, size_t len, CURLcode *err) { ssize_t written = -1; size_t data_len = 0; - unsigned char *data = NULL; + unsigned char *ptr = NULL; + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SecBuffer outbuf[4]; SecBufferDesc outbuf_desc; @@ -1629,19 +1632,19 @@ schannel_send(struct connectdata *conn, int sockindex, /* calculate the complete message length and allocate a buffer for it */ data_len = BACKEND->stream_sizes.cbHeader + len + BACKEND->stream_sizes.cbTrailer; - data = (unsigned char *) malloc(data_len); - if(data == NULL) { + ptr = (unsigned char *) malloc(data_len); + if(!ptr) { *err = CURLE_OUT_OF_MEMORY; return -1; } /* setup output buffers (header, data, trailer, empty) */ InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER, - data, BACKEND->stream_sizes.cbHeader); + ptr, BACKEND->stream_sizes.cbHeader); InitSecBuffer(&outbuf[1], SECBUFFER_DATA, - data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len)); + ptr + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len)); InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER, - data + BACKEND->stream_sizes.cbHeader + len, + ptr + BACKEND->stream_sizes.cbHeader + len, BACKEND->stream_sizes.cbTrailer); InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); InitSecBufferDesc(&outbuf_desc, outbuf, 4); @@ -1680,10 +1683,10 @@ schannel_send(struct connectdata *conn, int sockindex, while(len > (size_t)written) { ssize_t this_write = 0; int what; - timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, FALSE); + timediff_t timeout_ms = Curl_timeleft(data, NULL, FALSE); if(timeout_ms < 0) { /* we already got the timeout */ - failf(conn->data, "schannel: timed out sending data " + failf(data, "schannel: timed out sending data " "(bytes sent: %zd)", written); *err = CURLE_OPERATION_TIMEDOUT; written = -1; @@ -1694,13 +1697,13 @@ schannel_send(struct connectdata *conn, int sockindex, what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms); if(what < 0) { /* fatal error */ - failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); *err = CURLE_SEND_ERROR; written = -1; break; } else if(0 == what) { - failf(conn->data, "schannel: timed out sending data " + failf(data, "schannel: timed out sending data " "(bytes sent: %zd)", written); *err = CURLE_OPERATION_TIMEDOUT; written = -1; @@ -1708,7 +1711,7 @@ schannel_send(struct connectdata *conn, int sockindex, } /* socket is writable */ - result = Curl_write_plain(conn, conn->sock[sockindex], data + written, + result = Curl_write_plain(data, conn->sock[sockindex], ptr + written, len - written, &this_write); if(result == CURLE_AGAIN) continue; @@ -1728,7 +1731,7 @@ schannel_send(struct connectdata *conn, int sockindex, *err = CURLE_SEND_ERROR; } - Curl_safefree(data); + Curl_safefree(ptr); if(len == (size_t)written) /* Encrypted message including header, data and trailer entirely sent. @@ -1739,12 +1742,12 @@ schannel_send(struct connectdata *conn, int sockindex, } static ssize_t -schannel_recv(struct connectdata *conn, int sockindex, +schannel_recv(struct Curl_easy *data, int sockindex, char *buf, size_t len, CURLcode *err) { size_t size = 0; ssize_t nread = -1; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; unsigned char *reallocated_buffer; size_t reallocated_length; @@ -1783,14 +1786,12 @@ schannel_recv(struct connectdata *conn, int sockindex, infof(data, "schannel: server indicated shutdown in a prior call\n"); goto cleanup; } - else if(!len) { - /* It's debatable what to return when !len. Regardless we can't return - immediately because there may be data to decrypt (in the case we want to - decrypt all encrypted cached data) so handle !len later in cleanup. - */ - ; /* do nothing */ - } - else if(!BACKEND->recv_connection_closed) { + + /* It's debatable what to return when !len. Regardless we can't return + immediately because there may be data to decrypt (in the case we want to + decrypt all encrypted cached data) so handle !len later in cleanup. + */ + else if(len && !BACKEND->recv_connection_closed) { /* increase enc buffer in order to fit the requested amount of data */ size = BACKEND->encdata_length - BACKEND->encdata_offset; if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE || @@ -1957,7 +1958,7 @@ schannel_recv(struct connectdata *conn, int sockindex, infof(data, "schannel: renegotiating SSL/TLS connection\n"); connssl->state = ssl_connection_negotiating; connssl->connecting_state = ssl_connect_2_writing; - *err = schannel_connect_common(conn, sockindex, FALSE, &done); + *err = schannel_connect_common(data, conn, sockindex, FALSE, &done); if(*err) { infof(data, "schannel: renegotiation failed\n"); goto cleanup; @@ -2064,18 +2065,20 @@ schannel_recv(struct connectdata *conn, int sockindex, return *err ? -1 : 0; } -static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) +static CURLcode schannel_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { - return schannel_connect_common(conn, sockindex, TRUE, done); + return schannel_connect_common(data, conn, sockindex, TRUE, done); } -static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex) +static CURLcode schannel_connect(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { CURLcode result; bool done = FALSE; - result = schannel_connect_common(conn, sockindex, FALSE, &done); + result = schannel_connect_common(data, conn, sockindex, FALSE, &done); if(result) return result; @@ -2084,8 +2087,8 @@ static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex) return CURLE_OK; } -static bool Curl_schannel_data_pending(const struct connectdata *conn, - int sockindex) +static bool schannel_data_pending(const struct connectdata *conn, + int sockindex) { const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; @@ -2096,14 +2099,15 @@ static bool Curl_schannel_data_pending(const struct connectdata *conn, return FALSE; } -static void Curl_schannel_close(struct connectdata *conn, int sockindex) +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(conn, sockindex); + Curl_ssl_shutdown(data, conn, sockindex); } -static void Curl_schannel_session_free(void *ptr) +static void schannel_session_free(void *ptr) { /* this is expected to be called under sessionid lock */ struct Curl_schannel_cred *cred = ptr; @@ -2115,12 +2119,12 @@ static void Curl_schannel_session_free(void *ptr) } } -static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) +static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx * Shutting Down an Schannel Connection */ - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; #ifndef CURL_DISABLE_PROXY char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : @@ -2183,7 +2187,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) { /* send close message which is in output buffer */ ssize_t written; - result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, + result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer, outbuf.cbBuffer, &written); s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); @@ -2203,14 +2207,9 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) /* free SSPI Schannel API credential handle */ if(BACKEND->cred) { - /* - * When this function is called from Curl_schannel_close() the connection - * might not have an associated transfer so the check for conn->data is - * necessary. - */ - Curl_ssl_sessionid_lock(conn); - Curl_schannel_session_free(BACKEND->cred); - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_lock(data); + schannel_session_free(BACKEND->cred); + Curl_ssl_sessionid_unlock(data); BACKEND->cred = NULL; } @@ -2232,25 +2231,25 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) return CURLE_OK; } -static int Curl_schannel_init(void) +static int schannel_init(void) { return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0); } -static void Curl_schannel_cleanup(void) +static void schannel_cleanup(void) { Curl_sspi_global_cleanup(); } -static size_t Curl_schannel_version(char *buffer, size_t size) +static size_t schannel_version(char *buffer, size_t size) { size = msnprintf(buffer, size, "Schannel"); return size; } -static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM, - unsigned char *entropy, size_t length) +static CURLcode schannel_random(struct Curl_easy *data UNUSED_PARAM, + unsigned char *entropy, size_t length) { HCRYPTPROV hCryptProv = 0; @@ -2269,10 +2268,10 @@ static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM, return CURLE_OK; } -static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, +static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, + struct connectdata *conn, int sockindex, const char *pinnedpubkey) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CERT_CONTEXT *pCertContextServer = NULL; @@ -2334,12 +2333,12 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, return result; } -static void Curl_schannel_checksum(const unsigned char *input, - size_t inputlen, - unsigned char *checksum, - size_t checksumlen, - DWORD provType, - const unsigned int algId) +static void schannel_checksum(const unsigned char *input, + size_t inputlen, + unsigned char *checksum, + size_t checksumlen, + DWORD provType, + const unsigned int algId) { HCRYPTPROV hProv = 0; HCRYPTHASH hHash = 0; @@ -2384,28 +2383,18 @@ static void Curl_schannel_checksum(const unsigned char *input, CryptReleaseContext(hProv, 0); } -static CURLcode Curl_schannel_md5sum(unsigned char *input, - size_t inputlen, - unsigned char *md5sum, - size_t md5len) -{ - Curl_schannel_checksum(input, inputlen, md5sum, md5len, - PROV_RSA_FULL, CALG_MD5); - return CURLE_OK; -} - -static CURLcode Curl_schannel_sha256sum(const unsigned char *input, - size_t inputlen, - unsigned char *sha256sum, - size_t sha256len) +static CURLcode schannel_sha256sum(const unsigned char *input, + size_t inputlen, + unsigned char *sha256sum, + size_t sha256len) { - Curl_schannel_checksum(input, inputlen, sha256sum, sha256len, - PROV_RSA_AES, CALG_SHA_256); + schannel_checksum(input, inputlen, sha256sum, sha256len, + PROV_RSA_AES, CALG_SHA_256); return CURLE_OK; } -static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) +static void *schannel_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) { (void)info; return &BACKEND->ctxt->ctxt_handle; @@ -2419,26 +2408,25 @@ const struct Curl_ssl Curl_ssl_schannel = { sizeof(struct ssl_backend_data), - Curl_schannel_init, /* init */ - Curl_schannel_cleanup, /* cleanup */ - Curl_schannel_version, /* version */ + schannel_init, /* init */ + schannel_cleanup, /* cleanup */ + schannel_version, /* version */ Curl_none_check_cxn, /* check_cxn */ - Curl_schannel_shutdown, /* shutdown */ - Curl_schannel_data_pending, /* data_pending */ - Curl_schannel_random, /* random */ + schannel_shutdown, /* shutdown */ + schannel_data_pending, /* data_pending */ + schannel_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ - Curl_schannel_connect, /* connect */ - Curl_schannel_connect_nonblocking, /* connect_nonblocking */ - Curl_schannel_get_internals, /* get_internals */ - Curl_schannel_close, /* close_one */ + schannel_connect, /* connect */ + schannel_connect_nonblocking, /* connect_nonblocking */ + schannel_get_internals, /* get_internals */ + schannel_close, /* close_one */ Curl_none_close_all, /* close_all */ - Curl_schannel_session_free, /* session_free */ + schannel_session_free, /* session_free */ Curl_none_set_engine, /* set_engine */ Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - Curl_schannel_md5sum, /* md5sum */ - Curl_schannel_sha256sum /* sha256sum */ + schannel_sha256sum /* sha256sum */ }; #endif /* USE_SCHANNEL */ diff --git a/libs/libcurl/src/vtls/schannel.h b/libs/libcurl/src/vtls/schannel.h index 085b3f455c..2952caa1a5 100644 --- a/libs/libcurl/src/vtls/schannel.h +++ b/libs/libcurl/src/vtls/schannel.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012, Marc Hoersken, , et al. - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -53,7 +53,8 @@ extern const struct Curl_ssl Curl_ssl_schannel; -CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex); +CURLcode Curl_verify_certificate(struct Curl_easy *data, + struct connectdata *conn, int sockindex); /* structs to expose only in schannel.c and schannel_verify.c */ #ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c index 31b3b2f02f..2ef39cc0f4 100644 --- a/libs/libcurl/src/vtls/schannel_verify.c +++ b/libs/libcurl/src/vtls/schannel_verify.c @@ -7,7 +7,7 @@ * * Copyright (C) 2012 - 2016, Marc Hoersken, * Copyright (C) 2012, Mark Salisbury, - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -79,10 +79,9 @@ static int is_cr_or_lf(char c) static CURLcode add_certs_to_store(HCERTSTORE trust_store, const char *ca_file, - struct connectdata *conn) + struct Curl_easy *data) { CURLcode result; - struct Curl_easy *data = conn->data; HANDLE ca_file_handle = INVALID_HANDLE_VALUE; LARGE_INTEGER file_size; char *ca_file_buffer = NULL; @@ -477,7 +476,7 @@ static CURLcode verify_host(struct Curl_easy *data, * (or some equivalent) encoding */ cert_hostname = curlx_convert_tchar_to_UTF8( - &cert_hostname_buff[cert_hostname_buff_index]); + &cert_hostname_buff[cert_hostname_buff_index]); if(!cert_hostname) { result = CURLE_OUT_OF_MEMORY; } @@ -500,8 +499,8 @@ static CURLcode verify_host(struct Curl_easy *data, "against certificate name (%s)\n", conn_hostname, cert_hostname); - cert_hostname_len = _tcslen( - &cert_hostname_buff[cert_hostname_buff_index]); + cert_hostname_len = + _tcslen(&cert_hostname_buff[cert_hostname_buff_index]); /* Move on to next cert name */ cert_hostname_buff_index += cert_hostname_len + 1; @@ -522,15 +521,15 @@ static CURLcode verify_host(struct Curl_easy *data, failf(data, "schannel: server certificate name verification failed"); cleanup: - curlx_unicodefree(cert_hostname_buff); + Curl_safefree(cert_hostname_buff); return result; } -CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) +CURLcode Curl_verify_certificate(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { SECURITY_STATUS sspi_status; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CURLcode result = CURLE_OK; CERT_CONTEXT *pCertContextServer = NULL; @@ -584,7 +583,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) } else { result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile), - conn); + data); } } @@ -675,7 +674,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) if(result == CURLE_OK) { if(SSL_CONN_CONFIG(verifyhost)) { - result = verify_host(conn->data, pCertContextServer, conn_hostname); + result = verify_host(data, pCertContextServer, conn_hostname); } } diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c index 8ef60cb1f3..9a8f7de8d5 100644 --- a/libs/libcurl/src/vtls/sectransp.c +++ b/libs/libcurl/src/vtls/sectransp.c @@ -5,8 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * + * Copyright (C) 2012 - 2021, Daniel Stenberg, , et al. * Copyright (C) 2012 - 2017, Nick Zitzmann, . - * Copyright (C) 2012 - 2020, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1291,9 +1291,9 @@ static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver, #endif static CURLcode -set_ssl_version_min_max(struct connectdata *conn, int sockindex) +set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; long ssl_version = SSL_CONN_CONFIG(version); @@ -1387,10 +1387,10 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) } -static CURLcode sectransp_connect_step1(struct connectdata *conn, +static CURLcode sectransp_connect_step1(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; @@ -1478,7 +1478,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: { - CURLcode result = set_ssl_version_min_max(conn, sockindex); + CURLcode result = set_ssl_version_min_max(data, conn, sockindex); if(result != CURLE_OK) return result; break; @@ -1527,7 +1527,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: { - CURLcode result = set_ssl_version_min_max(conn, sockindex); + CURLcode result = set_ssl_version_min_max(data, conn, sockindex); if(result != CURLE_OK) return result; break; @@ -1952,12 +1952,12 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, char *ssl_sessionid; size_t ssl_sessionid_len; - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, (void **)&ssl_sessionid, &ssl_sessionid_len, sockindex)) { /* we got a session id, use it! */ err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len); - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); if(err != noErr) { failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); return CURLE_SSL_CONNECT_ERROR; @@ -1976,14 +1976,14 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len); if(err != noErr) { - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); return CURLE_SSL_CONNECT_ERROR; } - result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len, - sockindex); - Curl_ssl_sessionid_unlock(conn); + result = Curl_ssl_addsessionid(data, conn, ssl_sessionid, + ssl_sessionid_len, sockindex); + Curl_ssl_sessionid_unlock(data); if(result) { failf(data, "failed to store ssl session"); return result; @@ -2379,9 +2379,9 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, #endif /* SECTRANSP_PINNEDPUBKEY */ static CURLcode -sectransp_connect_step2(struct connectdata *conn, int sockindex) +sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; OSStatus err; @@ -2418,7 +2418,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex) return result; } /* the documentation says we need to call SSLHandshake() again */ - return sectransp_connect_step2(conn, sockindex); + return sectransp_connect_step2(data, conn, sockindex); /* Problem with encrypt / decrypt */ case errSSLPeerDecodeError: @@ -2693,7 +2693,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex) else infof(data, "ALPN, server did not agree to a protocol\n"); - Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); /* chosenProtocol is a reference to the string within alpnArr @@ -2711,10 +2711,10 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex) #ifndef CURL_DISABLE_VERBOSE_STRINGS /* This should be called during step3 of the connection at the earliest */ static void -show_verbose_server_cert(struct connectdata *conn, +show_verbose_server_cert(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; CFArrayRef server_certs = NULL; @@ -2817,10 +2817,9 @@ show_verbose_server_cert(struct connectdata *conn, #endif /* !CURL_DISABLE_VERBOSE_STRINGS */ static CURLcode -sectransp_connect_step3(struct connectdata *conn, +sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; /* There is no step 3! @@ -2828,7 +2827,7 @@ sectransp_connect_step3(struct connectdata *conn, * server certificates. */ #ifndef CURL_DISABLE_VERBOSE_STRINGS if(data->set.verbose) - show_verbose_server_cert(conn, sockindex); + show_verbose_server_cert(data, conn, sockindex); #endif connssl->connecting_state = ssl_connect_done; @@ -2839,13 +2838,13 @@ static Curl_recv sectransp_recv; static Curl_send sectransp_send; static CURLcode -sectransp_connect_common(struct connectdata *conn, +sectransp_connect_common(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool nonblocking, bool *done) { CURLcode result; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; int what; @@ -2866,7 +2865,7 @@ sectransp_connect_common(struct connectdata *conn, return CURLE_OPERATION_TIMEDOUT; } - result = sectransp_connect_step1(conn, sockindex); + result = sectransp_connect_step1(data, conn, sockindex); if(result) return result; } @@ -2920,7 +2919,7 @@ sectransp_connect_common(struct connectdata *conn, * before step2 has completed while ensuring that a client using select() * or epoll() will always have a valid fdset to wait on. */ - result = sectransp_connect_step2(conn, sockindex); + result = sectransp_connect_step2(data, conn, sockindex); if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || @@ -2931,7 +2930,7 @@ sectransp_connect_common(struct connectdata *conn, if(ssl_connect_3 == connssl->connecting_state) { - result = sectransp_connect_step3(conn, sockindex); + result = sectransp_connect_step3(data, conn, sockindex); if(result) return result; } @@ -2951,18 +2950,20 @@ sectransp_connect_common(struct connectdata *conn, return CURLE_OK; } -static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) +static CURLcode sectransp_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { - return sectransp_connect_common(conn, sockindex, TRUE, done); + return sectransp_connect_common(data, conn, sockindex, TRUE, done); } -static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex) +static CURLcode sectransp_connect(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { CURLcode result; bool done = FALSE; - result = sectransp_connect_common(conn, sockindex, FALSE, &done); + result = sectransp_connect_common(data, conn, sockindex, FALSE, &done); if(result) return result; @@ -2972,11 +2973,14 @@ static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex) return CURLE_OK; } -static void Curl_sectransp_close(struct connectdata *conn, int sockindex) +static void sectransp_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; + (void) data; + if(backend->ssl_ctx) { (void)SSLClose(backend->ssl_ctx); #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS @@ -2994,11 +2998,11 @@ static void Curl_sectransp_close(struct connectdata *conn, int sockindex) backend->ssl_sockfd = 0; } -static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex) +static int sectransp_shutdown(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; - struct Curl_easy *data = conn->data; ssize_t nread; int what; int rc; @@ -3012,7 +3016,7 @@ static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex) return 0; #endif - Curl_sectransp_close(conn, sockindex); + sectransp_close(data, conn, sockindex); rc = 0; @@ -3050,7 +3054,7 @@ static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex) return rc; } -static void Curl_sectransp_session_free(void *ptr) +static void sectransp_session_free(void *ptr) { /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a cached session ID inside the Security framework. There is a private @@ -3061,7 +3065,7 @@ static void Curl_sectransp_session_free(void *ptr) Curl_safefree(ptr); } -static size_t Curl_sectransp_version(char *buffer, size_t size) +static size_t sectransp_version(char *buffer, size_t size) { return msnprintf(buffer, size, "SecureTransport"); } @@ -3074,7 +3078,7 @@ static size_t Curl_sectransp_version(char *buffer, size_t size) * 0 means the connection has been closed * -1 means the connection status is unknown */ -static int Curl_sectransp_check_cxn(struct connectdata *conn) +static int sectransp_check_cxn(struct connectdata *conn) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; struct ssl_backend_data *backend = connssl->backend; @@ -3090,8 +3094,8 @@ static int Curl_sectransp_check_cxn(struct connectdata *conn) return 0; } -static bool Curl_sectransp_data_pending(const struct connectdata *conn, - int connindex) +static bool sectransp_data_pending(const struct connectdata *conn, + int connindex) { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; struct ssl_backend_data *backend = connssl->backend; @@ -3108,8 +3112,8 @@ static bool Curl_sectransp_data_pending(const struct connectdata *conn, return false; } -static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM, - unsigned char *entropy, size_t length) +static CURLcode sectransp_random(struct Curl_easy *data UNUSED_PARAM, + unsigned char *entropy, size_t length) { /* arc4random_buf() isn't available on cats older than Lion, so let's do this manually for the benefit of the older cats. */ @@ -3128,27 +3132,17 @@ static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM, return CURLE_OK; } -static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len) -{ - (void)md5len; - (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); - return CURLE_OK; -} - -static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum, /* output */ - size_t sha256len) +static CURLcode sectransp_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) { assert(sha256len >= CURL_SHA256_DIGEST_LENGTH); (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum); return CURLE_OK; } -static bool Curl_sectransp_false_start(void) +static bool sectransp_false_start(void) { #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 if(SSLSetSessionOption != NULL) @@ -3157,13 +3151,13 @@ static bool Curl_sectransp_false_start(void) return FALSE; } -static ssize_t sectransp_send(struct connectdata *conn, +static ssize_t sectransp_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *curlcode) { - /*struct Curl_easy *data = conn->data;*/ + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; size_t processed = 0UL; @@ -3198,7 +3192,7 @@ static ssize_t sectransp_send(struct connectdata *conn, *curlcode = CURLE_AGAIN; return -1L; default: - failf(conn->data, "SSLWrite() returned error %d", err); + failf(data, "SSLWrite() returned error %d", err); *curlcode = CURLE_SEND_ERROR; return -1L; } @@ -3215,7 +3209,7 @@ static ssize_t sectransp_send(struct connectdata *conn, *curlcode = CURLE_AGAIN; return -1L; default: - failf(conn->data, "SSLWrite() returned error %d", err); + failf(data, "SSLWrite() returned error %d", err); *curlcode = CURLE_SEND_ERROR; return -1L; } @@ -3224,13 +3218,13 @@ static ssize_t sectransp_send(struct connectdata *conn, return (ssize_t)processed; } -static ssize_t sectransp_recv(struct connectdata *conn, +static ssize_t sectransp_recv(struct Curl_easy *data, int num, char *buf, size_t buffersize, CURLcode *curlcode) { - /*struct Curl_easy *data = conn->data;*/ + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_backend_data *backend = connssl->backend; size_t processed = 0UL; @@ -3262,14 +3256,14 @@ static ssize_t sectransp_recv(struct connectdata *conn, Leopard's headers */ case -9841: if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { - CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), conn->data, + CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data, backend->ssl_ctx); if(result) return result; } goto again; default: - failf(conn->data, "SSLRead() return error %d", err); + failf(data, "SSLRead() return error %d", err); *curlcode = CURLE_RECV_ERROR; return -1L; break; @@ -3278,8 +3272,8 @@ static ssize_t sectransp_recv(struct connectdata *conn, return (ssize_t)processed; } -static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) +static void *sectransp_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) { struct ssl_backend_data *backend = connssl->backend; (void)info; @@ -3299,24 +3293,23 @@ const struct Curl_ssl Curl_ssl_sectransp = { Curl_none_init, /* init */ Curl_none_cleanup, /* cleanup */ - Curl_sectransp_version, /* version */ - Curl_sectransp_check_cxn, /* check_cxn */ - Curl_sectransp_shutdown, /* shutdown */ - Curl_sectransp_data_pending, /* data_pending */ - Curl_sectransp_random, /* random */ + sectransp_version, /* version */ + sectransp_check_cxn, /* check_cxn */ + sectransp_shutdown, /* shutdown */ + sectransp_data_pending, /* data_pending */ + sectransp_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ - Curl_sectransp_connect, /* connect */ - Curl_sectransp_connect_nonblocking, /* connect_nonblocking */ - Curl_sectransp_get_internals, /* get_internals */ - Curl_sectransp_close, /* close_one */ + sectransp_connect, /* connect */ + sectransp_connect_nonblocking, /* connect_nonblocking */ + sectransp_get_internals, /* get_internals */ + sectransp_close, /* close_one */ Curl_none_close_all, /* close_all */ - Curl_sectransp_session_free, /* session_free */ + sectransp_session_free, /* session_free */ Curl_none_set_engine, /* set_engine */ Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ - Curl_sectransp_false_start, /* false_start */ - Curl_sectransp_md5sum, /* md5sum */ - Curl_sectransp_sha256sum /* sha256sum */ + sectransp_false_start, /* false_start */ + sectransp_sha256sum /* sha256sum */ }; #ifdef __clang__ diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c index 3bd51fdaf2..b8ab7494fd 100644 --- a/libs/libcurl/src/vtls/vtls.c +++ b/libs/libcurl/src/vtls/vtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -75,17 +75,21 @@ (1<var) { \ - dest->var = strdup(source->var); \ - if(!dest->var) \ - return FALSE; \ - } \ - else \ - dest->var = NULL; - -#define CLONE_BLOB(var) \ - if(blobdup(&dest->var, source->var)) \ - return FALSE; + do { \ + if(source->var) { \ + dest->var = strdup(source->var); \ + if(!dest->var) \ + return FALSE; \ + } \ + else \ + dest->var = NULL; \ + } while(0) + +#define CLONE_BLOB(var) \ + do { \ + if(blobdup(&dest->var, source->var)) \ + return FALSE; \ + } while(0) static CURLcode blobdup(struct curl_blob **dest, struct curl_blob *src) @@ -185,13 +189,13 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) } #ifdef USE_SSL -static int multissl_init(const struct Curl_ssl *backend); +static int multissl_setup(const struct Curl_ssl *backend); #endif int Curl_ssl_backend(void) { #ifdef USE_SSL - multissl_init(NULL); + multissl_setup(NULL); return Curl_ssl->info.id; #else return (int)CURLSSLBACKEND_NONE; @@ -287,7 +291,8 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex) #endif CURLcode -Curl_ssl_connect(struct connectdata *conn, int sockindex) +Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { CURLcode result; @@ -299,26 +304,27 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex) } #endif - if(!ssl_prefs_check(conn->data)) + if(!ssl_prefs_check(data)) return CURLE_SSL_CONNECT_ERROR; /* mark this is being ssl-enabled from here on. */ conn->ssl[sockindex].use = TRUE; conn->ssl[sockindex].state = ssl_connection_negotiating; - result = Curl_ssl->connect_blocking(conn, sockindex); + result = Curl_ssl->connect_blocking(data, conn, sockindex); if(!result) - Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ + Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */ return result; } CURLcode -Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, - bool *done) +Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, + int sockindex, bool *done) { CURLcode result; + #ifndef CURL_DISABLE_PROXY if(conn->bits.proxy_ssl_connected[sockindex]) { result = ssl_connect_init_proxy(conn, sockindex); @@ -326,47 +332,46 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, return result; } #endif - if(!ssl_prefs_check(conn->data)) + if(!ssl_prefs_check(data)) return CURLE_SSL_CONNECT_ERROR; /* mark this is being ssl requested from here on. */ conn->ssl[sockindex].use = TRUE; - result = Curl_ssl->connect_nonblocking(conn, sockindex, done); + result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done); if(!result && *done) - Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ + Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */ return result; } /* * Lock shared SSL session data */ -void Curl_ssl_sessionid_lock(struct connectdata *conn) +void Curl_ssl_sessionid_lock(struct Curl_easy *data) { - if(SSLSESSION_SHARED(conn->data)) - Curl_share_lock(conn->data, - CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); + if(SSLSESSION_SHARED(data)) + Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); } /* * Unlock shared SSL session data */ -void Curl_ssl_sessionid_unlock(struct connectdata *conn) +void Curl_ssl_sessionid_unlock(struct Curl_easy *data) { - if(SSLSESSION_SHARED(conn->data)) - Curl_share_unlock(conn->data, CURL_LOCK_DATA_SSL_SESSION); + if(SSLSESSION_SHARED(data)) + Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); } /* * Check if there's a session ID for the given connection in the cache, and if * there's one suitable, it is provided. Returns TRUE when no entry matched. */ -bool Curl_ssl_getsessionid(struct connectdata *conn, +bool Curl_ssl_getsessionid(struct Curl_easy *data, + struct connectdata *conn, void **ssl_sessionid, size_t *idsize, /* set 0 if unknown */ int sockindex) { struct Curl_ssl_session *check; - struct Curl_easy *data = conn->data; size_t i; long *general_age; bool no_match = TRUE; @@ -453,10 +458,9 @@ void Curl_ssl_kill_session(struct Curl_ssl_session *session) /* * Delete the given session ID from the cache. */ -void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) +void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid) { size_t i; - struct Curl_easy *data = conn->data; for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) { struct Curl_ssl_session *check = &data->state.session[i]; @@ -474,13 +478,13 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) * layer. Curl_XXXX_session_free() will be called to free/kill the session ID * later on. */ -CURLcode Curl_ssl_addsessionid(struct connectdata *conn, +CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, + struct connectdata *conn, void *ssl_sessionid, size_t idsize, int sockindex) { size_t i; - struct Curl_easy *data = conn->data; /* the mother of all structs */ struct Curl_ssl_session *store = &data->state.session[0]; long oldest_age = data->state.session[0].age; /* zero if unused */ char *clone_host; @@ -620,16 +624,18 @@ int Curl_ssl_getsock(struct connectdata *conn, /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */ #endif -void Curl_ssl_close(struct connectdata *conn, int sockindex) +void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); - Curl_ssl->close_one(conn, sockindex); + Curl_ssl->close_one(data, conn, sockindex); conn->ssl[sockindex].state = ssl_connection_none; } -CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) +CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { - if(Curl_ssl->shut_down(conn, sockindex)) + if(Curl_ssl->shut_down(data, conn, sockindex)) return CURLE_SSL_SHUTDOWN_FAILED; conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ @@ -684,12 +690,12 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount) return CURLE_OK; } -static size_t Curl_multissl_version(char *buffer, size_t size); +static size_t multissl_version(char *buffer, size_t size); size_t Curl_ssl_version(char *buffer, size_t size) { #ifdef CURL_WITH_MULTI_SSL - return Curl_multissl_version(buffer, size); + return multissl_version(buffer, size); #else return Curl_ssl->version(buffer, size); #endif @@ -1030,16 +1036,6 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, return result; } -#ifndef CURL_DISABLE_CRYPTO_AUTH -CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len) -{ - return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len); -} -#endif - /* * Check whether the SSL backend supports the status_request extension. */ @@ -1076,9 +1072,11 @@ int Curl_none_init(void) void Curl_none_cleanup(void) { } -int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM, +int Curl_none_shutdown(struct Curl_easy *data UNUSED_PARAM, + struct connectdata *conn UNUSED_PARAM, int sockindex UNUSED_PARAM) { + (void)data; (void)conn; (void)sockindex; return 0; @@ -1148,70 +1146,44 @@ bool Curl_none_false_start(void) return FALSE; } -#ifndef CURL_DISABLE_CRYPTO_AUTH -CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, - unsigned char *md5sum, size_t md5len UNUSED_PARAM) +static int multissl_init(void) { - struct MD5_context *MD5pw; - - (void)md5len; - - MD5pw = Curl_MD5_init(Curl_DIGEST_MD5); - if(!MD5pw) - return CURLE_OUT_OF_MEMORY; - Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen)); - Curl_MD5_final(MD5pw, md5sum); - return CURLE_OK; -} -#else -CURLcode Curl_none_md5sum(unsigned char *input UNUSED_PARAM, - size_t inputlen UNUSED_PARAM, - unsigned char *md5sum UNUSED_PARAM, - size_t md5len UNUSED_PARAM) -{ - (void)input; - (void)inputlen; - (void)md5sum; - (void)md5len; - return CURLE_NOT_BUILT_IN; -} -#endif - -static int Curl_multissl_init(void) -{ - if(multissl_init(NULL)) + if(multissl_setup(NULL)) return 1; return Curl_ssl->init(); } -static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex) +static CURLcode multissl_connect(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { - if(multissl_init(NULL)) + if(multissl_setup(NULL)) return CURLE_FAILED_INIT; - return Curl_ssl->connect_blocking(conn, sockindex); + return Curl_ssl->connect_blocking(data, conn, sockindex); } -static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) +static CURLcode multissl_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { - if(multissl_init(NULL)) + if(multissl_setup(NULL)) return CURLE_FAILED_INIT; - return Curl_ssl->connect_nonblocking(conn, sockindex, done); + return Curl_ssl->connect_nonblocking(data, conn, sockindex, done); } -static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl, - CURLINFO info) +static void *multissl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info) { - if(multissl_init(NULL)) + if(multissl_setup(NULL)) return NULL; return Curl_ssl->get_internals(connssl, info); } -static void Curl_multissl_close(struct connectdata *conn, int sockindex) +static void multissl_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { - if(multissl_init(NULL)) + if(multissl_setup(NULL)) return; - Curl_ssl->close_one(conn, sockindex); + Curl_ssl->close_one(data, conn, sockindex); } static const struct Curl_ssl Curl_ssl_multi = { @@ -1219,25 +1191,24 @@ static const struct Curl_ssl Curl_ssl_multi = { 0, /* supports nothing */ (size_t)-1, /* something insanely large to be on the safe side */ - Curl_multissl_init, /* init */ + multissl_init, /* init */ Curl_none_cleanup, /* cleanup */ - Curl_multissl_version, /* version */ + multissl_version, /* version */ Curl_none_check_cxn, /* check_cxn */ Curl_none_shutdown, /* shutdown */ Curl_none_data_pending, /* data_pending */ Curl_none_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ - Curl_multissl_connect, /* connect */ - Curl_multissl_connect_nonblocking, /* connect_nonblocking */ - Curl_multissl_get_internals, /* get_internals */ - Curl_multissl_close, /* close_one */ + multissl_connect, /* connect */ + multissl_connect_nonblocking, /* connect_nonblocking */ + multissl_get_internals, /* get_internals */ + multissl_close, /* close_one */ Curl_none_close_all, /* close_all */ Curl_none_session_free, /* session_free */ Curl_none_set_engine, /* set_engine */ Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - Curl_none_md5sum, /* md5sum */ NULL /* sha256sum */ }; @@ -1302,7 +1273,7 @@ static const struct Curl_ssl *available_backends[] = { NULL }; -static size_t Curl_multissl_version(char *buffer, size_t size) +static size_t multissl_version(char *buffer, size_t size) { static const struct Curl_ssl *selected; static char backends[200]; @@ -1346,7 +1317,7 @@ static size_t Curl_multissl_version(char *buffer, size_t size) return backends_len; } -static int multissl_init(const struct Curl_ssl *backend) +static int multissl_setup(const struct Curl_ssl *backend) { const char *env; char *env_tmp; @@ -1405,7 +1376,7 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, for(i = 0; available_backends[i]; i++) { if(available_backends[i]->info.id == id || (name && strcasecompare(available_backends[i]->info.name, name))) { - multissl_init(available_backends[i]); + multissl_setup(available_backends[i]); return CURLSSLSET_OK; } } diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h index f4cab9988f..9666682ec2 100644 --- a/libs/libcurl/src/vtls/vtls.h +++ b/libs/libcurl/src/vtls/vtls.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -47,7 +47,8 @@ struct Curl_ssl { size_t (*version)(char *buffer, size_t size); int (*check_cxn)(struct connectdata *cxn); - int (*shut_down)(struct connectdata *conn, int sockindex); + int (*shut_down)(struct Curl_easy *data, struct connectdata *conn, + int sockindex); bool (*data_pending)(const struct connectdata *conn, int connindex); @@ -56,11 +57,14 @@ struct Curl_ssl { size_t length); bool (*cert_status_request)(void); - CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex); - CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex, + CURLcode (*connect_blocking)(struct Curl_easy *data, + struct connectdata *conn, int sockindex); + CURLcode (*connect_nonblocking)(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool *done); void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); - void (*close_one)(struct connectdata *conn, int sockindex); + void (*close_one)(struct Curl_easy *data, struct connectdata *conn, + int sockindex); void (*close_all)(struct Curl_easy *data); void (*session_free)(void *ptr); @@ -69,9 +73,6 @@ struct Curl_ssl { struct curl_slist *(*engines_list)(struct Curl_easy *data); bool (*false_start)(void); - - CURLcode (*md5sum)(unsigned char *input, size_t inputlen, - unsigned char *md5sum, size_t md5sumlen); CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen, unsigned char *sha256sum, size_t sha256sumlen); }; @@ -82,7 +83,8 @@ extern const struct Curl_ssl *Curl_ssl; int Curl_none_init(void); void Curl_none_cleanup(void); -int Curl_none_shutdown(struct connectdata *conn, int sockindex); +int Curl_none_shutdown(struct Curl_easy *data, struct connectdata *conn, + int sockindex); int Curl_none_check_cxn(struct connectdata *conn); CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy, size_t length); @@ -95,8 +97,6 @@ CURLcode Curl_none_set_engine_default(struct Curl_easy *data); struct curl_slist *Curl_none_engines_list(struct Curl_easy *data); bool Curl_none_false_start(void); bool Curl_ssl_tls13_ciphersuites(void); -CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, - unsigned char *md5sum, size_t md5len); #include "openssl.h" /* OpenSSL versions */ #include "gtls.h" /* GnuTLS versions */ @@ -165,15 +165,19 @@ int Curl_ssl_backend(void); #ifdef USE_SSL int Curl_ssl_init(void); void Curl_ssl_cleanup(void); -CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex); -CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, +CURLcode Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn, + int sockindex); +CURLcode Curl_ssl_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool *done); /* tell the SSL stuff to close down all open information regarding connections (and thus session ID caching etc) */ void Curl_ssl_close_all(struct Curl_easy *data); -void Curl_ssl_close(struct connectdata *conn, int sockindex); -CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex); +void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex); +CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn, + int sockindex); CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine); /* Sets engine as default for all SSL operations */ CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data); @@ -205,10 +209,10 @@ CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum, * The purpose of explicitly locking SSL session cache data is to allow * individual SSL engines to manage session lifetime in their specific way. */ -void Curl_ssl_sessionid_lock(struct connectdata *conn); +void Curl_ssl_sessionid_lock(struct Curl_easy *data); /* Unlock session cache mutex */ -void Curl_ssl_sessionid_unlock(struct connectdata *conn); +void Curl_ssl_sessionid_unlock(struct Curl_easy *data); /* extract a session ID * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). @@ -216,7 +220,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn); * is properly taken (e.g. its refcount is incremented * under sessionid mutex). */ -bool Curl_ssl_getsessionid(struct connectdata *conn, +bool Curl_ssl_getsessionid(struct Curl_easy *data, + struct connectdata *conn, void **ssl_sessionid, size_t *idsize, /* set 0 if unknown */ int sockindex); @@ -225,7 +230,8 @@ bool Curl_ssl_getsessionid(struct connectdata *conn, * Caller must ensure that it has properly shared ownership of this sessionid * object with cache (e.g. incrementing refcount on success) */ -CURLcode Curl_ssl_addsessionid(struct connectdata *conn, +CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, + struct connectdata *conn, void *ssl_sessionid, size_t idsize, int sockindex); @@ -242,15 +248,11 @@ void Curl_ssl_kill_session(struct Curl_ssl_session *session); * take sessionid object ownership from sessionid cache * (e.g. decrement refcount). */ -void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); +void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid); /* get N random bytes into the buffer */ CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer, size_t length); -CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len); /* Check pinned public key. */ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, const char *pinnedpubkey, @@ -267,10 +269,10 @@ bool Curl_ssl_false_start(void); /* When SSL support is not present, just define away these function calls */ #define Curl_ssl_init() 1 #define Curl_ssl_cleanup() Curl_nop_stmt -#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_connect(x,y,z) CURLE_NOT_BUILT_IN #define Curl_ssl_close_all(x) Curl_nop_stmt -#define Curl_ssl_close(x,y) Curl_nop_stmt -#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_close(x,y,z) Curl_nop_stmt +#define Curl_ssl_shutdown(x,y,z) CURLE_NOT_BUILT_IN #define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN #define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN #define Curl_ssl_engines_list(x) NULL @@ -280,7 +282,7 @@ bool Curl_ssl_false_start(void); #define Curl_ssl_data_pending(x,y) 0 #define Curl_ssl_check_cxn(x) 0 #define Curl_ssl_free_certinfo(x) Curl_nop_stmt -#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN +#define Curl_ssl_connect_nonblocking(x,y,z,w) CURLE_NOT_BUILT_IN #define Curl_ssl_kill_session(x) Curl_nop_stmt #define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN) #define Curl_ssl_cert_status_request() FALSE diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index 44ee2d9ec1..e1fa459265 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -217,11 +217,10 @@ static int do_file_type(const char *type) * layer and do all necessary magic. */ static CURLcode -wolfssl_connect_step1(struct connectdata *conn, +wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, int sockindex) { char *ciphers; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; SSL_METHOD* req_method = NULL; @@ -256,7 +255,7 @@ wolfssl_connect_step1(struct connectdata *conn, use_sni(TRUE); break; case CURL_SSLVERSION_TLSv1_0: -#ifdef WOLFSSL_ALLOW_TLSV10 +#if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS) req_method = TLSv1_client_method(); use_sni(TRUE); #else @@ -265,8 +264,13 @@ wolfssl_connect_step1(struct connectdata *conn, #endif break; case CURL_SSLVERSION_TLSv1_1: +#ifndef NO_OLD_TLS req_method = TLSv1_1_client_method(); use_sni(TRUE); +#else + failf(data, "wolfSSL does not support TLS 1.1"); + return CURLE_NOT_BUILT_IN; +#endif break; case CURL_SSLVERSION_TLSv1_2: req_method = TLSv1_2_client_method(); @@ -500,16 +504,23 @@ wolfssl_connect_step1(struct connectdata *conn, } #endif /* OPENSSL_EXTRA */ +#ifdef HAVE_SECURE_RENEGOTIATION + if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) { + failf(data, "SSL: failed setting secure renegotiation"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + /* Check if there's a cached ID we can/should use here! */ if(SSL_SET_OPTION(primary.sessionid)) { void *ssl_sessionid = NULL; - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(backend->handle, ssl_sessionid)) { char error_buffer[WOLFSSL_MAX_ERROR_SZ]; - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); failf(data, "SSL: SSL_set_session failed: %s", ERR_error_string(SSL_get_error(backend->handle, 0), error_buffer)); @@ -518,7 +529,7 @@ wolfssl_connect_step1(struct connectdata *conn, /* Informational message */ infof(data, "SSL re-using session ID\n"); } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } /* pass the raw socket into the SSL layer */ @@ -533,11 +544,10 @@ wolfssl_connect_step1(struct connectdata *conn, static CURLcode -wolfssl_connect_step2(struct connectdata *conn, +wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, int sockindex) { int ret = -1; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; #ifndef CURL_DISABLE_PROXY @@ -608,7 +618,7 @@ wolfssl_connect_step2(struct connectdata *conn, * as also mismatching CN fields */ else if(DOMAIN_NAME_MISMATCH == detail) { #if 1 - failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n", + failf(data, "\tsubject alt name(s) or common name do not match \"%s\"", dispname); return CURLE_PEER_FAILED_VERIFICATION; #else @@ -635,7 +645,7 @@ wolfssl_connect_step2(struct connectdata *conn, #if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */ else if(ASN_NO_SIGNER_E == detail) { if(SSL_CONN_CONFIG(verifypeer)) { - failf(data, "\tCA signer not available for verification\n"); + failf(data, "\tCA signer not available for verification"); return CURLE_SSL_CACERT_BADFILE; } else { @@ -723,7 +733,7 @@ wolfssl_connect_step2(struct connectdata *conn, else infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len, protocol); - Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } else if(rc == SSL_ALPN_NOT_FOUND) @@ -749,11 +759,10 @@ wolfssl_connect_step2(struct connectdata *conn, static CURLcode -wolfssl_connect_step3(struct connectdata *conn, +wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn, int sockindex) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; @@ -766,27 +775,27 @@ wolfssl_connect_step3(struct connectdata *conn, our_ssl_sessionid = SSL_get_session(backend->handle); - Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + Curl_ssl_sessionid_lock(data); + incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL, sockindex)); if(incache) { if(old_ssl_sessionid != our_ssl_sessionid) { infof(data, "old SSL session ID is stale, removing\n"); - Curl_ssl_delsessionid(conn, old_ssl_sessionid); + Curl_ssl_delsessionid(data, old_ssl_sessionid); incache = FALSE; } } if(!incache) { - result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, + result = Curl_ssl_addsessionid(data, conn, our_ssl_sessionid, 0 /* unknown size */, sockindex); if(result) { - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); failf(data, "failed to store ssl session"); return result; } } - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(data); } connssl->connecting_state = ssl_connect_done; @@ -795,12 +804,13 @@ wolfssl_connect_step3(struct connectdata *conn, } -static ssize_t wolfssl_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len, - CURLcode *curlcode) +static ssize_t wolfssl_send(struct Curl_easy *data, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; char error_buffer[WOLFSSL_MAX_ERROR_SZ]; @@ -817,7 +827,7 @@ static ssize_t wolfssl_send(struct connectdata *conn, *curlcode = CURLE_AGAIN; return -1; default: - failf(conn->data, "SSL write: %s, errno %d", + failf(data, "SSL write: %s, errno %d", ERR_error_string(err, error_buffer), SOCKERRNO); *curlcode = CURLE_SEND_ERROR; @@ -827,11 +837,14 @@ static ssize_t wolfssl_send(struct connectdata *conn, return rc; } -static void Curl_wolfssl_close(struct connectdata *conn, int sockindex) +static void wolfssl_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; + (void) data; + if(backend->handle) { (void)SSL_shutdown(backend->handle); SSL_free(backend->handle); @@ -843,12 +856,13 @@ static void Curl_wolfssl_close(struct connectdata *conn, int sockindex) } } -static ssize_t wolfssl_recv(struct connectdata *conn, +static ssize_t wolfssl_recv(struct Curl_easy *data, int num, char *buf, size_t buffersize, CURLcode *curlcode) { + struct connectdata *conn = data->conn; struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_backend_data *backend = connssl->backend; char error_buffer[WOLFSSL_MAX_ERROR_SZ]; @@ -867,9 +881,8 @@ static ssize_t wolfssl_recv(struct connectdata *conn, *curlcode = CURLE_AGAIN; return -1; default: - failf(conn->data, "SSL read: %s, errno %d", - ERR_error_string(err, error_buffer), - SOCKERRNO); + failf(data, "SSL read: %s, errno %d", + ERR_error_string(err, error_buffer), SOCKERRNO); *curlcode = CURLE_RECV_ERROR; return -1; } @@ -878,14 +891,14 @@ static ssize_t wolfssl_recv(struct connectdata *conn, } -static void Curl_wolfssl_session_free(void *ptr) +static void wolfssl_session_free(void *ptr) { (void)ptr; /* wolfSSL reuses sessions on own, no free */ } -static size_t Curl_wolfssl_version(char *buffer, size_t size) +static size_t wolfssl_version(char *buffer, size_t size) { #if LIBWOLFSSL_VERSION_HEX >= 0x03006000 return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version()); @@ -895,7 +908,7 @@ static size_t Curl_wolfssl_version(char *buffer, size_t size) } -static int Curl_wolfssl_init(void) +static int wolfssl_init(void) { #ifdef OPENSSL_EXTRA Curl_tls_keylog_open(); @@ -904,7 +917,7 @@ static int Curl_wolfssl_init(void) } -static void Curl_wolfssl_cleanup(void) +static void wolfssl_cleanup(void) { wolfSSL_Cleanup(); #ifdef OPENSSL_EXTRA @@ -913,8 +926,8 @@ static void Curl_wolfssl_cleanup(void) } -static bool Curl_wolfssl_data_pending(const struct connectdata *conn, - int connindex) +static bool wolfssl_data_pending(const struct connectdata *conn, + int connindex) { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; struct ssl_backend_data *backend = connssl->backend; @@ -929,12 +942,15 @@ static bool Curl_wolfssl_data_pending(const struct connectdata *conn, * This function is called to shut down the SSL layer but keep the * socket open (CCC - Clear Command Channel) */ -static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex) +static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn, + int sockindex) { int retval = 0; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; + (void) data; + if(backend->handle) { SSL_free(backend->handle); backend->handle = NULL; @@ -944,13 +960,13 @@ static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex) static CURLcode -wolfssl_connect_common(struct connectdata *conn, +wolfssl_connect_common(struct Curl_easy *data, + struct connectdata *conn, int sockindex, bool nonblocking, bool *done) { CURLcode result; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; int what; @@ -971,7 +987,7 @@ wolfssl_connect_common(struct connectdata *conn, return CURLE_OPERATION_TIMEDOUT; } - result = wolfssl_connect_step1(conn, sockindex); + result = wolfssl_connect_step1(data, conn, sockindex); if(result) return result; } @@ -1026,7 +1042,7 @@ wolfssl_connect_common(struct connectdata *conn, * ensuring that a client using select() or epoll() will always * have a valid fdset to wait on. */ - result = wolfssl_connect_step2(conn, sockindex); + result = wolfssl_connect_step2(data, conn, sockindex); if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || @@ -1035,7 +1051,7 @@ wolfssl_connect_common(struct connectdata *conn, } /* repeat step2 until all transactions are done. */ if(ssl_connect_3 == connssl->connecting_state) { - result = wolfssl_connect_step3(conn, sockindex); + result = wolfssl_connect_step3(data, conn, sockindex); if(result) return result; } @@ -1056,19 +1072,21 @@ wolfssl_connect_common(struct connectdata *conn, } -static CURLcode Curl_wolfssl_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) +static CURLcode wolfssl_connect_nonblocking(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { - return wolfssl_connect_common(conn, sockindex, TRUE, done); + return wolfssl_connect_common(data, conn, sockindex, TRUE, done); } -static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex) +static CURLcode wolfssl_connect(struct Curl_easy *data, + struct connectdata *conn, int sockindex) { CURLcode result; bool done = FALSE; - result = wolfssl_connect_common(conn, sockindex, FALSE, &done); + result = wolfssl_connect_common(data, conn, sockindex, FALSE, &done); if(result) return result; @@ -1077,8 +1095,8 @@ static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex) return CURLE_OK; } -static CURLcode Curl_wolfssl_random(struct Curl_easy *data, - unsigned char *entropy, size_t length) +static CURLcode wolfssl_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) { WC_RNG rng; (void)data; @@ -1093,10 +1111,10 @@ static CURLcode Curl_wolfssl_random(struct Curl_easy *data, return CURLE_OK; } -static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum /* output */, - size_t unused) +static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum /* output */, + size_t unused) { wc_Sha256 SHA256pw; (void)unused; @@ -1106,7 +1124,7 @@ static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */ return CURLE_OK; } -static void *Curl_wolfssl_get_internals(struct ssl_connect_data *connssl, +static void *wolfssl_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { struct ssl_backend_data *backend = connssl->backend; @@ -1124,26 +1142,25 @@ const struct Curl_ssl Curl_ssl_wolfssl = { sizeof(struct ssl_backend_data), - Curl_wolfssl_init, /* init */ - Curl_wolfssl_cleanup, /* cleanup */ - Curl_wolfssl_version, /* version */ + wolfssl_init, /* init */ + wolfssl_cleanup, /* cleanup */ + wolfssl_version, /* version */ Curl_none_check_cxn, /* check_cxn */ - Curl_wolfssl_shutdown, /* shutdown */ - Curl_wolfssl_data_pending, /* data_pending */ - Curl_wolfssl_random, /* random */ + wolfssl_shutdown, /* shutdown */ + wolfssl_data_pending, /* data_pending */ + wolfssl_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ - Curl_wolfssl_connect, /* connect */ - Curl_wolfssl_connect_nonblocking, /* connect_nonblocking */ - Curl_wolfssl_get_internals, /* get_internals */ - Curl_wolfssl_close, /* close_one */ + wolfssl_connect, /* connect */ + wolfssl_connect_nonblocking, /* connect_nonblocking */ + wolfssl_get_internals, /* get_internals */ + wolfssl_close, /* close_one */ Curl_none_close_all, /* close_all */ - Curl_wolfssl_session_free, /* session_free */ + wolfssl_session_free, /* session_free */ Curl_none_set_engine, /* set_engine */ Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - Curl_none_md5sum, /* md5sum */ - Curl_wolfssl_sha256sum /* sha256sum */ + wolfssl_sha256sum /* sha256sum */ }; #endif diff --git a/libs/libcurl/src/warnless.c b/libs/libcurl/src/warnless.c index 908ee6cb70..c0764c42d0 100644 --- a/libs/libcurl/src/warnless.c +++ b/libs/libcurl/src/warnless.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -155,25 +155,6 @@ unsigned char curlx_ultouc(unsigned long ulnum) #endif } -/* -** unsigned long to signed int -*/ - -int curlx_ultosi(unsigned long ulnum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_SINT); - return (int)(ulnum & (unsigned long) CURL_MASK_SINT); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - /* ** unsigned size_t to signed curl_off_t */ diff --git a/libs/libcurl/src/warnless.h b/libs/libcurl/src/warnless.h index ca3737859b..2c619bf819 100644 --- a/libs/libcurl/src/warnless.h +++ b/libs/libcurl/src/warnless.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -33,8 +33,6 @@ unsigned short curlx_ultous(unsigned long ulnum); unsigned char curlx_ultouc(unsigned long ulnum); -int curlx_ultosi(unsigned long ulnum); - int curlx_uztosi(size_t uznum); curl_off_t curlx_uztoso(size_t uznum); diff --git a/libs/libcurl/src/x509asn1.c b/libs/libcurl/src/x509asn1.c index d7cf9eb2af..f29aa05b87 100644 --- a/libs/libcurl/src/x509asn1.c +++ b/libs/libcurl/src/x509asn1.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -945,13 +945,12 @@ static void do_pubkey(struct Curl_easy *data, int certnum, } } -CURLcode Curl_extract_certinfo(struct connectdata *conn, +CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum, const char *beg, const char *end) { struct Curl_X509certificate cert; - struct Curl_easy *data = conn->data; struct Curl_asn1Element param; const char *ccp; char *cp1; @@ -1132,10 +1131,9 @@ static const char *checkOID(const char *beg, const char *end, return matched? ccp: NULL; } -CURLcode Curl_verifyhost(struct connectdata *conn, +CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn, const char *beg, const char *end) { - struct Curl_easy *data = conn->data; struct Curl_X509certificate cert; struct Curl_asn1Element dn; struct Curl_asn1Element elem; diff --git a/libs/libcurl/src/x509asn1.h b/libs/libcurl/src/x509asn1.h index 849714492d..326e32d588 100644 --- a/libs/libcurl/src/x509asn1.h +++ b/libs/libcurl/src/x509asn1.h @@ -8,7 +8,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -125,9 +125,9 @@ const char *Curl_ASN1tostr(struct Curl_asn1Element *elem, int type); const char *Curl_DNtostr(struct Curl_asn1Element *dn); int Curl_parseX509(struct Curl_X509certificate *cert, const char *beg, const char *end); -CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum, +CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum, const char *beg, const char *end); -CURLcode Curl_verifyhost(struct connectdata *conn, +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 /* HEADER_CURL_X509ASN1_H */ -- cgit v1.2.3