diff options
Diffstat (limited to 'libs/libcurl')
137 files changed, 5729 insertions, 4749 deletions
diff --git a/libs/libcurl/docs/CHANGES b/libs/libcurl/docs/CHANGES index 62dce2ee97..e7a462b50e 100644 --- a/libs/libcurl/docs/CHANGES +++ b/libs/libcurl/docs/CHANGES @@ -6,6 +6,1698 @@ Changelog +Version 7.77.0 (26 May 2021) + +Daniel Stenberg (26 May 2021) +- RELEASE-NOTES: synced + +- THANKS: added contributors from 7.77.0 cycle + +- copyright: update copyright year ranges to 2021 + +- [Radek Zajic brought this change] + + hostip: fix broken macOS/CMake/GCC builds + + Follow-up to 31f631a142d855f06 + + Fixes #7128 + Closes #7129 + +- TODO: netrc caching and sharing + + URL: https://curl.se/mail/archive-2021-05/0018.html + +- [Orgad Shaneh brought this change] + + setopt: streamline ssl option code + + Make it use the same style as the code next to it + + Closes #7123 + +- [Radek Zajic brought this change] + + lib/hostip6.c: make NAT64 address synthesis on macOS work + + Closes #7121 + +- [ejanchivdorj brought this change] + + sectransp: fix EXC_BAD_ACCESS caused by uninitialized buffer + + When the SecCertificateCopyCommonName function fails, it leaves + common_name in a invalid state so CFStringCompare uses the invalid + result, causing EXC_BAD_ACCESS. + + The fix is to check the return value of the function before using the + name. + + Closes #7126 + +- [PaweÅ‚ Wegner brought this change] + + CMake: add CURL_ENABLE_EXPORT_TARGET option + + install(EXPORT ...) causes trouble when embedding curl dependencies + which don't provide install(EXPORT ...) targets (e.g libressl and + nghttp2) with cmake's add_subdirectory. + + Reviewed-by: Jakub Zakrzewski + Closes #7060 + +- [Alessandro Ghedini brought this change] + + quiche: update for network path aware API + + Latest version of quiche requires the application to pass the peer + address of received packets, and it provides the address for outgoing + packets back. + + Closes #7120 + +- [Jacob Hoffman-Andrews brought this change] + + rustls: switch read_tls and write_tls to callbacks + + And update to 0.6.0, including a rename from session to connection for + many fields. + + Closes #7071 + +- [Koichi Shiraishi brought this change] + + sectransp: fix 7f4a9a9b2a49 commit about missing comma + + Follow-up to 7f4a9a9b2a495 + + Closes #7119 + +- [Harry Sintonen brought this change] + + openssl: associate/detach the transfer from connection + + CVE-2021-22901 + + Bug: https://curl.se/docs/CVE-2021-22901.html + +- [Harry Sintonen brought this change] + + telnet: check sscanf() for correct number of matches + + CVE-2021-22898 + + Bug: https://curl.se/docs/CVE-2021-22898.html + +- schannel: don't use static to store selected ciphers + + CVE-2021-22897 + + Bug: https://curl.se/docs/CVE-2021-22897.html + +- docs/tests: remove freenode references + +- RELEASE-NOTES: synced + +- [Sergey Markelov brought this change] + + NSS: make colons, commas and spaces valid separators in cipher list + + Fixes #7110 + Closes #7115 + +- curl: include libmetalink version in --version output + + Closes #7112 + +Jay Satiro (21 May 2021) +- [Matias N. Goldberg brought this change] + + cmake: Use multithreaded compilation on VS 2008+ + + Multithreaded compilation has been supported since at least VS 2005 and + been robustly stable since at least VS 2008 + + Closes https://github.com/curl/curl/pull/7109 + +Daniel Stenberg (21 May 2021) +- [Matias N. Goldberg brought this change] + + cmake: fix two invokes result in different curl_config.h + + Fixes #7100 + Closes #7101 + + Reviewed-by: Jakub Zakrzewski + Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar> + +- [Peng-Yu Chen brought this change] + + cmake: detect CURL_SA_FAMILY_T + + Fixes #7049 + Closes #7065 + +- [Lucas Clemente Vella brought this change] + + CURLOPT_IPRESOLVE: preventing wrong IP version from being used + + In some situations, it was possible that a transfer was setup to + use an specific IP version, but due do DNS caching or connection + reuse, it ended up using a different IP version from requested. + + This commit changes the effect of CURLOPT_IPRESOLVE from simply + restricting address resolution to preventing the wrong connection + type being used, when choosing a connection from the pool, and + to restricting what addresses could be used when establishing + a new connection. + + It is important that all addresses versions are resolved, even if + not used in that transfer in particular, because the result is + cached, and could be useful for a different transfer with a + different CURLOPT_IPRESOLVE setting. + + Closes #6853 + +- [Oliver Urbann brought this change] + + AmigaOS: add functions definitions for SHA256 + + AmiSSL replaces many functions with macros. Curl requires pointer + to some of these functions. Thus, we have to encapsulate these macros: + SHA256_Init, SHA256_Update, SHA256_Final, X509_INFO_free. + + Bug: https://github.com/jens-maus/amissl/issues/15 + Co-authored-by: Daniel Stenberg <daniel@haxx.se> + + Closes #7099 + +- test2100: make it run with and require IPv6 + + Closes #7083 + +- tests/getpart: generate output URL encoded for better diffs + + Closes #7083 + +- [Ryan Beck-Buysse brought this change] + + docs/TheArtOfHttpScripting: fix markdown links + + extra parens cause the links to be incorrectly formatted + and inconsistent with the rest of the document. + + Signed-off-by: Ryan Beck-Buysse <rbuysse@gmail.com> + Closes #7097 + +- RELEASE-NOTES: synced + +- [Emil Engler brought this change] + + docs: replace dots with dashes in markdown enums + + We use dashes instead of dots nearly everywhere except for those few + cases. This commit addresses this issues and brings more coherency into + it. + + Closes #7093 + +- [Emil Engler brought this change] + + docs: improve INTERNALS.md regarding getsock cb + + This adds the I/O prefix to indicate that those "actions" are kind-of + related to those found in select(2) or poll(2) (reading/writing). + + It also adds a note where the prototypes of those functions can be found + in the source code. + + Closes #7092 + +- [Emil Engler brought this change] + + docs: document attach in INTERNALS.md + + The new field in the Curl_handler struct still lacks documentation. This + adds it it from the information extracted from lib/urldata.h:797 + + Closes #7091 + +- [Marc Aldorasi brought this change] + + config: remove now-unused macros + + Closes #7094 + +- [Marc Aldorasi brought this change] + + hostip.h: remove declaration of unimplemented function + + Closes #7094 + +- h3: add 'attach' callback to protocol handlers + + Follow-up to 0c55fbab45be + + Reviewed-by: Emil Engler + Closes #7090 + +- wolfssl: remove SSLv3 support leftovers + + Closes #7088 + +- curl-wolfssl.m4: without custom include path, assume /usr/include + + ... so that we can point out the root of the OpenSSL emulation headers. + Previously this used the '$includedir' variable which is wrong since + that defaults to the dir where the current configure invoke will install + the built libcurl headers: /usr/local by default. + + Fixes #7085 + Reported-by: Joel Jakobsson + Closes #7087 + +- [Joel Depooter brought this change] + + data_pending: check only SECONDARY socket for FTP(S) transfers + + Check the FIRST for all other protocols. + + This fixes a timeout in an ftps download. The server sends a TLS + close_notify message in the same packet as the file data. The + close_notify seems to not be handled in the schannel_recv function, so + libcurl is not aware that the server has closed the connection. Thus + libcurl ends up waiting for action on the socket until a timeout is + reached. With the secondary socket check added to the data_pending + function, the close_notify is properly handled, and the ftps transfer + terminates as expected. + + Fixes #7068 + Closes #7069 + +- github: inhibit deprecated declarations for clang on macOS + + ... as they otherwise cause ldap build errors in the CI. + + Fixes #7081 + Closes #7082 + +- conn: add 'attach' to protocol handler, make libssh2 use it + + The libssh2 backend has SSH session associated with the connection but + the callback context is the easy handle, so when a connection gets + attached to a transfer, the protocol handler now allows for a custom + function to get used to set things up correctly. + + Reported-by: Michael O'Farrell + Fixes #6898 + Closes #7078 + +- http2: make sure pause is done on HTTP + + Since the function is called for any protocol, we can't assume that the + HTTP struct is there without first making sure it is HTTP. + + Reported-by: Denis Goleshchikhin + Fixes #7079 + Closes #7080 + +- docs: cookies from HTTP headers need domain set + + ... or the cookies won't get sent. Push users to using the "Netscape" + format instead, which curl uses when saving a cookie "jar". + + Reported-by: Martin Dorey + Reviewed-by: Daniel Gustafsson + Fixes #6723 + Closes #7077 + +- RELEASE-NOTES: synced + +- github: add a workflow with libssh2 on macOS using cmake + + Closes #7047 + +- sws: allow HTTP requests up to 2MB in size + + To allow tests with slightly larger payloads. Like #7071 ... + + Closes #7075 + +Marc Hoersken (16 May 2021) +- CI/azure: increase verbosity and fix outdated task names + + Closes #7063 + +- CI/cirrus: add shared and static Windows release builds + + Azure Pipelines is currently being used for debug builds, + let's also run some non-debug (release) Windows builds and + make use of previously underutilized Cirrus CI for that. + + Reviewed-by: Marcel Raad + + Closes #6991 + +Daniel Stenberg (16 May 2021) +- CURLOPT_CAPATH.3: defaults to a path, not NULL + + Reported-by: Andrew Barnert + + Closes #7062 + +- [Jacob Hoffman-Andrews brought this change] + + c-hyper: handle body on HYPER_TASK_EMPTY + + Some of the time, we get a HYPER_TASK_EMPTY response before the status + line, headers, and body have been read. Previously, that would cause us + to poll again, leading to a 1 second timeout. + + The HYPER_TASK_EMPTY docs say: + + The value of this task is null (does not imply an error). + + So, if we receive a HYPER_TASK_EMPTY, continue on with processing the + response. + + Reported-by: Kevin Burke + Fixes #7064 + Closes #7070 + +- [Ikko Ashimine brought this change] + + tool_getparam: fix comment typo in tool_getparam.c + + enfore -> enforce + + Closes #7074 + +- mem-include-scan.pl: require a non-word letter before memory funcs + + ... so that ldap_memfree() for example doesn't match the scan for free. + + Closes #7061 + +- version: free the openldap info correctly + + ... to avoid memory leaks. + + Follow-up to: bf0feae7768d9 + Closes #7061 + +- dupset: remove totally off comment + + Closes #7067 + +- configure: if asked for, fail if ldap is not found + + Reported-by: Jakub Zakrzewski + Fixes #7053 + Closes #7055 + +- version: add OpenLDAP version in the output + + Assisted-by: Howard Chu + Closes #7054 + +Jay Satiro (13 May 2021) +- [Joel Depooter brought this change] + + schannel: Ensure the security context request flags are always set + + As of commit 54e7475, these flags would only be set when using a new + credential handle. When re-using an existing credential handle, the + flags would not be set. + + Closes https://github.com/curl/curl/pull/7051 + +Dan Fandrich (12 May 2021) +- tests: Fix some tag matching issues in a number of tests + +Daniel Stenberg (12 May 2021) +- sasl: use 'unsigned short' to store mechanism + + ... saves a few bytes of struct size in memory and it only uses + 10 bits anyway. + + Closes #7045 + +- hostip: remove the debug code for LocalHost + + The Curl_resolv() had special code (when built in debug mode) for when + resolving the host name "LocalHost" (using that exact casing). It would + then get the host name from the --interface option instead. + + This development-only feature was not used by anything (anymore) and we + have the --resolve feature if we want to play similar tricks properly + going forward. + + Closes #7044 + +- progress: reset limit_size variables at transfer start + + Otherwise the old value would linger from a previous use and would mess + up the network speed cap logic. + + Reported-by: Ymir1711 on github + + Fixes #7042 + Closes #7043 + +- RELEASE-NOTES: synced + +- [Daniel Gustafsson brought this change] + + cookies: use CURLcode for cookie_output reporting + + Writing the cookie file has multiple error conditions, and was using an + int with magic numbers to report the different error (which in turn were + disregarded anyways). This moves reporting to use a CURLcode value. + + Lightly-touched-by: Daniel Stenberg + + Closes #7037 + Closes #6749 + +- [Daniel Gustafsson brought this change] + + cookies: make use of string duplication function + + strstore() is defined as a strdup which ensures to free the target + pointer before duping the source char * into it. Make use of it in + two more cases where it can simplify the code. + +- [Daniel Gustafsson brought this change] + + cookies: refactor comments + + Comments in the cookie code were a bit all over the place in terms of + style and wording. This takes a stab at cleaning them up by keeping to + a single style and overall shape. Some comments are moved a little and + some removed alltogether due to being redundant. No functional changes + have been made, + +- [Peng-Yu Chen brought this change] + + http2: skip immediate parsing of payload following protocol switch + + This is considered not harmful as a following http2_recv shall be + called very soon. + + This is considered helpful in the specific situation where some + servers (e.g. nghttpx v1.43.0) may fulfill stream 1 immediately + following the return of HTTP status 101, other than waiting for + the client-side connection preface to arrive. + + Fixes #7036 + Closes #7040 + +- [Peng-Yu Chen brought this change] + + http2: use nghttp2_session_upgrade2 instead of nghttp2_session_upgrade + + Following the upstream deprecation of nghttp2_session_upgrade. + + Also provides further checks for requests with the HEAD method. + + Closes #7041 + +- progress/trspeed: use a local convenient pointer to beautify code + + The function becomes easier to read and understand with less repetition. + +- trspeed: use long double for transfer speed calculation + +- progress: move transfer speed calc into function + + This silences two scan-build-11 warnings: "The result of the '/' + expression is undefined" + + Bug: https://curl.se/mail/lib-2021-05/0022.html + Closes #7035 + +- [Cameron Cawley brought this change] + + openssl: remove unneeded cast for CertOpenSystemStore() + + Closes #7025 + +- travis: disable the libssh build + + It can't run on focal and causes warnings on bionic. Since the focal + failure started rather suddenly a while ago, we can suspect it might be + temporary. + + Added "bring back the build" to the TODO document. + + Fixes #7011 + Closes #7012 + +- [Peng-Yu Chen brought this change] + + http: use calculated offsets inst of integer literals for header parsing + + Assumed to be a minor coding style improvement with no behavior change. + + A modern compiler is expected to have the calculation optimized during + compilation. It may be deemed okay even if that's not the case, since + the added overhead is considered very low. + + Closes #7032 + +- [Peng-Yu Chen brought this change] + + GIT-INFO: suggest using autoreconf instead of buildconf + + Follow-up to 85868537d + + Closes #7033 + +- http: deal with partial CONNECT sends + + Also added 'CURL_SMALLSENDS' to make Curl_write() send short packets, + which helped verifying this even more. + + Add test 363 to verify. + + Reported-by: ustcqidi on github + Fixes #6950 + Closes #7024 + +- HTTP3: make the ngtcp2 build use the quictls fork + + ... as ngtcp2 itself documents the build this way. + + Closes #7031 + +- http: limit the initial send amount to used upload buffer size + + Previously this logic would cap the send to CURL_MAX_WRITE_SIZE bytes, + but for the situations where a larger upload buffer has been set, this + function can benefit from sending more bytes. With default size used, + this does the same as before. + + Also changed the storage of the size to an 'unsigned int' as it is not + allowed to be set larger than 2M. + + Also added cautions to the man pages about changing buffer sizes in + run-time. + + Closes #7022 + +- RELEASE-NOTES: synced + +- ngtcp2: fix the cb_acked_stream_data_offset proto + + The 'datalen' value should be 64 bit, not size_t! + + Reported-by: Dmitry Karpov + Bug: https://curl.se/mail/lib-2021-05/0019.html + Closes #7027 + +- progress: when possible, calculate transfer speeds with microseconds + + ... this improves precision, especially for transfers in the few or even + sub millisecond range. + + Reported-by: J. Bromley + Fixes #7017 + Closes #7020 + +- http: reset the header buffer when sending the request + + A reused transfer handle could otherwise reuse the previous leftover + buffer and havoc would ensue. + + Reported-by: sergio-nsk on github + Fixes #7018 + Closes #7021 + +- curl_mprintf.3: add description + + These functions have existed in the API since the dawn of time. It is + about time we describe how they work, even if we discourage users from + using them. + + Closes #7010 + +- [Timothy Gu brought this change] + + URL-SYNTAX: update IDNA section for WHATWG spec changes + + WHATWG URL has dictated the use of Nontransitional Processing (IDNA + 2008) for several years now. Chrome (and derivatives) still use + Transitional Processing, but Firefox and Safari have both switched. + + Also document the fact that winidn functions differently from libidn2 + here. + + Closes #7026 + +- [Calvin Buckley brought this change] + + INSTALL: add IBM i specific quirks + + Fixes #6830 + Closes #7013 + +- libcurl.3: mention the URL API + + To make it easier to find. Also a minor polish of libcurl-url.3 + + Closes #7009 + +- GnuTLS: don't allow TLS 1.3 for versions that don't support it + + Follow-up to 781864bedbc5 + + ... as they don't understand it and will return error at us! + + Closes #7014 + +Kamil Dudka (6 May 2021) +- tool_getparam: handle failure of curlx_convert_tchar_to_UTF8() + + Reported by GCC analyzer: + + Error: GCC_ANALYZER_WARNING (CWE-476): + src/tool_getparam.c: scope_hint: In function 'parse_args' + src/tool_getparam.c:2318:38: warning[-Wanalyzer-possible-null-dereference]: dereference of possibly-NULL 'orig_opt' + lib/curlx.h:56: included_from: Included from here. + src/tool_getparam.c:28: included_from: Included from here. + lib/curl_multibyte.h:70:51: note: in definition of macro 'curlx_convert_tchar_to_UTF8' + src/tool_getparam.c:2316:16: note: in expansion of macro 'curlx_convert_tchar_to_UTF8' + + Reviewed-by: Marcel Raad + Reviewed-by: Daniel Stenberg + Closes #7023 + +Daniel Stenberg (6 May 2021) +- scripts/delta: also show total number of days + +Marc Hoersken (5 May 2021) +- sockfilt: fix invalid increment of handles index variable nfd + + Only increment the array index if we actually stored a handle. + + Follow up to e917492048f4b85a0fd58a033d10072fc7666c3b + Closes #6992 + +- sockfilt: avoid getting stuck waiting for writable socket + + Reset FD_WRITE event using the same approach as in multi.c + + Follow up to b36442b24305f3cda7c13cc64b46838995a4985b + Closes #6992 + +Jay Satiro (5 May 2021) +- test678: Fix for Windows multibyte builds + + Follow-up to 77fc385 from yesterday. + + Bug: https://github.com/curl/curl/pull/6662#issuecomment-832966557 + Reported-by: Marc Hörsken + +- [Dmitry Kostjuchenko brought this change] + + build: fix compilation for Windows UWP platform + + - Include afunix.h which is necessary for sockaddr_un when + USE_UNIX_SOCKETS is defined on Windows. + + Closes https://github.com/curl/curl/pull/7006 + +Daniel Stenberg (5 May 2021) +- gnutls: make setting only the MAX TLS allowed version work + + Previously, settting only the max allowed TLS version, leaving the + minimum one at default, didn't actually set it and left it to default + (TLS 1.3) too! + + As a bonus, this change also removes the dead code handling of SSLv3 + since that version can't be set anymore (since eff614fb0242cb). + + Reported-by: Daniel Carpenter + Fixes #6998 + Closes #7000 + +- openldap: replace ldap_ prefix on private functions + + Since openldap itself uses that prefix and with OpenĹDAP 2.5.4 (at + least) there's a symbol collision because of that. + + The private functions now use the 'oldap_' prefix where it previously + used 'ldap_'. + + Reported-by: 3eka on github + Fixes #7004 + Closes #7005 + +Jay Satiro (5 May 2021) +- http2: fix potentially uninitialized variable + + introduced several days ago in 3193170. caught by visual studio linker. + +- [Gilles Vollant brought this change] + + SSL: support in-memory CA certs for some backends + + - New options CURLOPT_CAINFO_BLOB and CURLOPT_PROXY_CAINFO_BLOB to + specify in-memory PEM certificates for OpenSSL, Schannel (Windows) + and Secure Transport (Apple) SSL backends. + + Prior to this change PEM certificates could only be imported from a file + and not from memory. + + Co-authored-by: moparisthebest@users.noreply.github.com + + Ref: https://github.com/curl/curl/pull/4679 + Ref: https://github.com/curl/curl/pull/5677 + Ref: https://github.com/curl/curl/pull/6109 + + Closes https://github.com/curl/curl/pull/6662 + +Daniel Stenberg (4 May 2021) +- [David Cook brought this change] + + tests: ignore case of chunked hex numbers in tests + + When hyper is used, it emits uppercase hexadecimal numbers for chunked + encoding lengths. Without hyper, lowercase hexadecimal numbers are used. + This change adds preprocessor statements to tests where this is an + issue, and adapts the fixtures to match. + + Closes #6987 + +- cmake: check for getppid and utimes + + ... as they're checked for in the configure script and are used by + source code. + + Removed checks for perror, setvbuf and strlcat since those defines are + not checked for in source code. + + Bonus: removed HAVE_STRLCPY from a few config-*.h files since that + symbol is not used in source code. + + Closes #6997 + +- libtest: remove lib530.c + + Follow up from e50a877df when test 530 was removed. Since then this + source file has not been used/needed. + + Closes #6999 + +- FILEFORMAT: mention sectransp as a feature + + Been supported since at least 40259ca65 + + Closes #7001 + +- RELEASE-NOTES: synced + +- libssh2: ignore timeout during disconnect + + ... to avoid memory leaks! + + libssh2 is tricky as we have to deal with the non-blockiness even in + close and shutdown cases. In the cases when we shutdown after a timeout + already expired, it is crucial that curl doen't let the timeout abort + the shutdown process as that then leaks memory! + + Reported-by: Benjamin Riefenstahl + Fixes #6990 + +- KNOWN_BUGS: add two HTTP/2 bugs + +- KNOWN_BUGS: add three HTTP/3 issues + + ... and moved the HTTP/2 issues to its own section + + Closes #6606 + Closes #6510 + Closes #6494 + +- [ejanchivdorj brought this change] + + CURLcode: add CURLE_SSL_CLIENTCERT + + When a TLS server requests a client certificate during handshake and + none can be provided, libcurl now returns this new error code + CURLE_SSL_CLIENTCERT + + Only supported by Secure Transport and OpenSSL for TLS 1.3 so far. + + Closes #6721 + +- [Tobias Gabriel brought this change] + + .github/FUNDING: add link to GitHub sponsors + + Closes #6985 + +- [Harry Sintonen brought this change] + + krb5/name_to_level: replace checkprefix with curl_strequal + + Closes #6993 + +- [Harry Sintonen brought this change] + + Curl_input_digest: require space after Digest + + Closes #6993 + +- [Harry Sintonen brought this change] + + Curl_http_header: check for colon when matching Persistent-Auth + + Closes #6993 + +- [Harry Sintonen brought this change] + + Curl_http_input_auth: require valid separator after negotiation type + + Closes #6993 + +- http: fix the check for 'Authorization' with Bearer + + The code would wrongly check for it using an additional colon. + + Reported-by: Blake Burkhart + Closes #6988 + +- [Kamil Dudka brought this change] + + http2: fix a resource leak in push_promise() + + ... detected by Coverity: + + Error: RESOURCE_LEAK (CWE-772): + lib/http2.c:532: alloc_fn: Storage is returned from allocation function "duphandle". + lib/http2.c:532: var_assign: Assigning: "newhandle" = storage returned from "duphandle(data)". + lib/http2.c:552: noescape: Resource "newhandle" is not freed or pointed-to in "set_transfer_url". + lib/http2.c:555: leaked_storage: Variable "newhandle" going out of scope leaks the storage it points to. + + Closes #6986 + +- [Kamil Dudka brought this change] + + http2: fix resource leaks in set_transfer_url() + + ... detected by Coverity: + + Error: RESOURCE_LEAK (CWE-772): + lib/http2.c:480: alloc_fn: Storage is returned from allocation function "curl_url". [Note: The source code implementation of the function has been overridden by a builtin model.] + lib/http2.c:480: var_assign: Assigning: "u" = storage returned from "curl_url()". + lib/http2.c:486: noescape: Resource "u" is not freed or pointed-to in "curl_url_set". [Note: The source code implementation of the function has been overridden by a builtin model.] + lib/http2.c:488: leaked_storage: Variable "u" going out of scope leaks the storage it points to. + + Error: RESOURCE_LEAK (CWE-772): + lib/http2.c:480: alloc_fn: Storage is returned from allocation function "curl_url". [Note: The source code implementation of the function has been overridden by a builtin model.] + lib/http2.c:480: var_assign: Assigning: "u" = storage returned from "curl_url()". + lib/http2.c:493: noescape: Resource "u" is not freed or pointed-to in "curl_url_set". [Note: The source code implementation of the function has been overridden by a builtin model.] + lib/http2.c:495: leaked_storage: Variable "u" going out of scope leaks the storage it points to. + + Error: RESOURCE_LEAK (CWE-772): + lib/http2.c:480: alloc_fn: Storage is returned from allocation function "curl_url". [Note: The source code implementation of the function has been overridden by a builtin model.] + lib/http2.c:480: var_assign: Assigning: "u" = storage returned from "curl_url()". + lib/http2.c:500: noescape: Resource "u" is not freed or pointed-to in "curl_url_set". [Note: The source code implementation of the function has been overridden by a builtin model.] + lib/http2.c:502: leaked_storage: Variable "u" going out of scope leaks the storage it points to. + + Error: RESOURCE_LEAK (CWE-772): + lib/http2.c:480: alloc_fn: Storage is returned from allocation function "curl_url". [Note: The source code implementation of the function has been overridden by a builtin model.] + lib/http2.c:480: var_assign: Assigning: "u" = storage returned from "curl_url()". + lib/http2.c:505: noescape: Resource "u" is not freed or pointed-to in "curl_url_get". [Note: The source code implementation of the function has been overridden by a builtin model.] + lib/http2.c:507: leaked_storage: Variable "u" going out of scope leaks the storage it points to. + + Closes #6986 + +- [Jacob Hoffman-Andrews brought this change] + + rustls: use ALPN + + Update required rustls to 0.5.0 + + Closes #6960 + +- [MAntoniak brought this change] + + gskit: fix CURL_DISABLE_PROXY build + + Removed localfd and remotefd from ssl_backend_data (ued only with proxy + connection). Function pipe_ssloverssl return always 0, when proxy is not + used. + + Closes #6981 + +- [MAntoniak brought this change] + + gskit: fix undefined reference to 'conn' + + Closes #6980 + +- [Jacob Hoffman-Andrews brought this change] + + tls: add USE_HTTP2 define + + This abstracts across the two HTTP/2 backends: nghttp2 and Hyper. + + Add our own define for the "h2" ALPN protocol, so TLS backends can use + it without depending on a specific HTTP backend. + + Closes #6959 + +- [Jacob Hoffman-Andrews brought this change] + + lib: fix 0-length Curl_client_write calls + + Closes #6954 + +- [Jacob Hoffman-Andrews brought this change] + + lib: remove strlen call from Curl_client_write + + At all call sites with an explicit 0 len, pass an appropriate nonzero + len. + + Closes #6954 + +- [Ayushman Singh Chauhan brought this change] + + docs: camelcase it like GitHub everywhere + + Closes #6979 + +Jay Satiro (27 Apr 2021) +- [Lucas Servén MarÃn brought this change] + + docs: fix typo in fail-with-body doc + + This commit fixes a small typo in the documentation for the + --fail-with-body flag. + + Closes https://github.com/curl/curl/pull/6977 + +- lib: fix some misuse of curlx_convert_UTF8_to_tchar + + curlx_convert_UTF8_to_tchar must be freed by curlx_unicodefree, but + prior to this change some uses mistakenly called free. + + I've reviewed all other uses of curlx_convert_UTF8_to_tchar and + curlx_convert_tchar_to_UTF8. + + Bug: https://github.com/curl/curl/pull/6602#issuecomment-825236763 + Reported-by: sergio-nsk@users.noreply.github.com + + Closes https://github.com/curl/curl/pull/6938 + +Daniel Stenberg (27 Apr 2021) +- ntlm: precaution against super huge type2 offsets + + ... which otherwise caused an integer overflow and circumvented the if() + conditional size check. + + Detected by OSS-Fuzz + Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=33720 + Assisted-by: Max Dymond + Closes #6975 + +- c-hyper: fix unused variable ‘wrote’ + +- libcurl-security.3: be careful of setuid + + Reported-by: Harry Sintonen + Closes #6970 + +- [Kevin Burke brought this change] + + c-hyper: don't write to set.writeheader if null + + Previously if a caller set CURLOPT_WRITEFUNCTION but did not set a + CURLOPT_HEADERDATA buffer, Hyper would still attempt to write headers to + the data->set.writeheader header buffer, even though it is null. This + led to NPE segfaults attempting to use libcurl+Hyper with Git, for + example. + + Instead, process the client write for the status line using the same + logic we use to process the client write for the later HTTP headers, + which contains the appropriate guard logic. As a side benefit, + data->set.writeheader is now only read in one file instead of two. + + Fixes #6619 + Fixes abetterinternet/crustls#49 + Fixes hyperium/hyper#2438 + Closes #6971 + +- wolfssl: handle SSL_write() returns 0 for error + + Reported-by: Timo Lange + + Closes #6967 + +- easy: ignore sigpipe in curl_easy_send + + Closes #6965 + +- sigpipe: ignore SIGPIPE when using wolfSSL as well + + Closes #6966 + +- libcurl-security.3: don't try to filter IPv4 hosts based on the URL + + Closes #6942 + +- [Harry Sintonen brought this change] + + nss_set_blocking: avoid static for sock_opt + + Reviewed-by: Kamil Dudka + Closes #6945 + +- RELEASE-NOTES: synced + +- [Yusuke Nakamura brought this change] + + docs/HTTP3.md: fix nghttp2's HTTP/3 server port + + Port 8443 does not work now. + Correct origin is in the quicwg's wiki. + https://github.com/quicwg/base-drafts/wiki/Implementations#ngtcp2 + + Closes #6964 + +- krb5: don't use 'static' to store PBSZ size response + + ... because it makes the knowledge and usage cross-transfer in funny and + unexpected ways. + + Reported-by: Harry Sintonen + Closes #6963 + +- [Kevin Burke brought this change] + + m4: add security frameworks on Mac when compiling rustls + + Previously compiling rustls on Mac would only complete if you also + compiled the SecureTransport TLS backend, which curl would prefer to + the Rust backend. + + Appending these flags to LDFLAGS makes it possible to compile the + Rustls backend on Mac without the SecureTransport backend, which means + this patch will make it possible for Mac users to use the Rustls + backend for TLS. + + Reviewed-by: Jacob Hoffman-Andrews + + Fixes #6955 + Cloes #6956 + +- krb5: remove the unused 'overhead' function + + Closes #6947 + +- [Johann150 brought this change] + + curl_url_set.3: add memory management information + + wording taken from man page for CURLOPT_URL.3 + + As far as I can see, the URL part is either malloc'ed before due to + encoding or it is strdup'ed. + + Closes #6953 + +- [Jacob Hoffman-Andrews brought this change] + + c-hpyer: fix handling of zero-byte chunk from hyper + + Closes #6951 + +- CURLOPT_POSTFIELDS.3: clarify how it gets the size of the data + + Ref: https://curl.se/mail/lib-2021-04/0085.html + Closes #6943 + +- [Ralph Langendam brought this change] + + cmake: make libcurl output filename configurable + + Reviewed-by: Jakub Zakrzewski + Closes #6933 + +- [Patrick Monnerat brought this change] + + vtls: reset ssl use flag upon negotiation failure + + Fixes the segfault in ldaps disconnect. + + Reported-by: Illarion Taev + Fixes #6934 + Closes #6937 + +- configure: fix typo in TLS error message + + Reported-by: Pontus Lundkvist + +- README: link to the commercial support option + +Jay Satiro (22 Apr 2021) +- [Martin Halle brought this change] + + version: add gsasl_version to curl_version_info_data + + - Add gsasl_version string and bump to CURLVERSION_TENTH. + + Ref: https://curl.se/mail/lib-2021-04/0003.html + + Closes https://github.com/curl/curl/pull/6843 + +- [Morten Minde Neergaard brought this change] + + schannel: Support strong crypto option + + - Support enabling strong crypto via optional user cipher list when + USE_STRONG_CRYPTO or SCH_USE_STRONG_CRYPTO is in the list. + + MSDN says SCH_USE_STRONG_CRYPTO "Instructs Schannel to disable known + weak cryptographic algorithms, cipher suites, and SSL/TLS protocol + versions that may be otherwise enabled for better interoperability." + + Ref: https://curl.se/mail/lib-2021-02/0066.html + Ref: https://curl.se/docs/manpage.html#--ciphers + Ref: https://curl.se/libcurl/c/CURLOPT_SSL_CIPHER_LIST.html + Ref: https://docs.microsoft.com/en-us/windows/win32/api/schannel/ns-schannel-schannel_cred + + Closes https://github.com/curl/curl/pull/6734 + +Daniel Stenberg (22 Apr 2021) +- RELEASE-NOTES: synced + +- ci: adapt to configure requiring an explicit TLS choice + +- configure: split out each TLS library detector into its own function + + ... and put those functions in separate m4 files per TLS library. + +- configure: make the TLS library choice(s) explicit + + configure no longer tries to find a TLS library by default, but all + libraries are now equal: the user needs to explicitly ask what TLS + library or libraries to use. + + If no TLS library is selected, configure will error out unless + --without-ssl is explicitly used to request a built without TLS (as that + is very rare these days). + + Removes: --with-winssl, --with-darwinssl and all --without-* options for + TLS libraries. + + Closes #6897 + +- tests/disable-scan.pl: also scan all m4 files + + Fixes test 1165 when functions are moved from configure.ac to files in + m4/ + +Jay Satiro (22 Apr 2021) +- schannel: Disable auto credentials; add an option to enable it + + - Disable auto credentials by default. This is a breaking change + for clients that are using it, wittingly or not. + + - New libcurl ssl option value CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl + to automatically locate and use a client certificate for + authentication, when requested by the server. + + - New curl tool options --ssl-auto-client-cert and + --proxy-ssl-auto-client-cert map to CURLSSLOPT_AUTO_CLIENT_CERT. + + This option is only supported for Schannel (the native Windows SSL + library). Prior to this change Schannel would, with no notification to + the client, attempt to locate a client certificate and send it to the + server, when requested by the server. Since the server can request any + certificate that supports client authentication in the OS certificate + store it could be a privacy violation and unexpected. + + Fixes https://github.com/curl/curl/issues/2262 + Reported-by: Jeroen Ooms + Assisted-by: Wes Hinsley + Assisted-by: Rich FitzJohn + + Ref: https://curl.se/mail/lib-2021-02/0066.html + Reported-by: Morten Minde Neergaard + + Closes https://github.com/curl/curl/pull/6673 + +Daniel Stenberg (22 Apr 2021) +- [MichaÅ‚ Antoniak brought this change] + + vtls: deduplicate some DISABLE_PROXY ifdefs + + continue from #5735 + + - using SSL_HOST_NAME, SSL_HOST_DISPNAME, SSL_PINNED_PUB_KEY for other + tls backend + + - create SSL_HOST_PORT + + Closes #6660 + +Jay Satiro (22 Apr 2021) +- OS400: fix typo + + CURLVERSION_HEIGHTH -> CURLVERSION_EIGHTH + +Daniel Stenberg (22 Apr 2021) +- checksrc: complain on == NULL or != 0 checks in conditions + + ... to make them all consistenly use if(!var) and if(var) + + Also added a few missing warnings to the documentation. + + Closes #6912 + +- tidy-up: make conditional checks more consistent + + ... remove '== NULL' and '!= 0' + + Closes #6912 + +- [Patrick Monnerat brought this change] + + vauth: factor base64 conversions out of authentication procedures + + Input challenges and returned messages are now in binary. + Conversions from/to base64 are performed by callers (currently curl_sasl.c + and http_ntlm.c). + + Closes #6654 + +- [Patrick Monnerat brought this change] + + bufref: buffer reference support + + A struct bufref holds a buffer pointer, a data size and a destructor. + When freed or its contents are changed, the previous buffer is implicitly + released by the associated destructor. The data size, although not used + internally, allows binary data support. + + A unit test checks its handling methods: test 1661 + + Closes #6654 + +- [Patrick Monnerat brought this change] + + os400: additional support for options metadata + + New functions curl_easy_option_by_name_ccsid() and + curl_easy_option_get_name_ccsid() allows accessing metadata in alternate + character encoding. + + This commit also updates curl_version_info_ccsid() to handle info version 9 + and adds recent definitions to the ILE/RPG include file. + + Documentation updated accordingly. + + Reviewed-by: Jon Rumsey + Closes #6574 + +- [Patrick Monnerat brought this change] + + test server: take care of siginterrupt() deprecation + + Closes #6529 + +Marc Hoersken (21 Apr 2021) +- lib1564.c: enable last wakeup test part on Windows + + Suggested-by: Gergely Nagy + Reviewed-by: Jay Satiro + Reviewed-by: Marcel Raad + + Closes #6245 + +- multi: fix slow write/upload performance on Windows + + Reset FD_WRITE by sending zero bytes which is permissible + and will be treated by implementations as successful send. + + Without this we won't be notified in case a socket is still + writable if we already received such a notification and did + not send any data afterwards on the socket. This would lead + to waiting forever on a writable socket being writable again. + + Assisted-by: Tommy Odom + Reviewed-by: Jay Satiro + Reviewed-by: Marcel Raad + Tested-by: tmkk on github + + Bug: #6146 + Closes #6245 + +- multi: reduce Win32 API calls to improve performance + + 1. Consolidate pre-checks into a single Curl_poll call: + + This is an attempt to restructure the code in Curl_multi_wait + in such a way that less syscalls are made by removing individual + calls to Curl_socket_check via SOCKET_READABLE/SOCKET_WRITABLE. + + 2. Avoid resetting the WinSock event multiple times: + + We finally call WSAResetEvent anyway, so specifying it as + an optional parameter to WSAEnumNetworkEvents is redundant. + + 3. Wakeup directly in case no sockets are being monitoring: + + Fix the WinSock based implementation to skip extra waiting by + not sleeping in case no sockets are to be waited on and just + the WinSock event is being monitored for wakeup functionality. + + Assisted-by: Tommy Odom + Reviewed-by: Jay Satiro + Reviewed-by: Marcel Raad + + Bug: #6146 + Closes #6245 + +- Revert "Revert 'multi: implement wait using winsock events'" + + This reverts commit 2260e0ebe6d45529495231b3e37a0c58fb92a6a2, + also restoring previous follow up changes which were reverted. + + Authored-by: rcombs on github + Authored-by: Marc Hörsken + Reviewed-by: Jay Satiro + Reviewed-by: Marcel Raad + + Restores #5634 + Reverts #6281 + Part of #6245 + +Daniel Stenberg (21 Apr 2021) +- Revert "cmake: make libcurl library output name configurable" + + This reverts commit 1cba36d2166c396f987eea587cf92671b27acb92. + + CMake provides properties that can be set on a target to rename the + output artifact without changing the name of a target. + + Ref: #6899 + +- [Michael Kolechkin brought this change] + + sectransp: allow cipher name to be specified + + Add parser for CURLOPT_SSL_CIPHER_LIST option for Secure Transport (ST) + back-end. Similar to NSS and GSKit back-ends, new code parses string + value and configures ST library to use those ciphers for communication. + Create cipher spec data structure and initialize the array of specs with + cipher number, name, alias, and 'weak' flag. + + Mark triple-DES ciphers as 'weak', and exclude them from the default + ciphers list. + + Closes #6464 + +- [Michael Kolechkin brought this change] + + NSS: add ciphers to map + + Add cipher names to the `cipherlist` map, based on the list of ciphers + implemented by the NSS in the source code file + https://github.com/nss-dev/nss/blob/master/lib/ssl/sslenum.c + + Closes #6670 + +- http2: remove DEBUG_HTTP2 + + Accidentally committed in 605e84235 + +- [Ralph Langendam brought this change] + + cmake: make libcurl library output name configurable + + Closes #6899 + +- sws: #ifdef S_IFSOCK use + + SCO OpenServer 5.0.7 does not define S_IFSOCK. + + Reported-by: Kevin R. Bulgrien + Bug: https://curl.se/mail/lib-2021-04/0074.html + Closes #6926 + +- curl_setup: provide the shutdown flags wider + + By using #ifdef on the symbol names to work on anything that don't + provide them. SCO OpenServer 5.0.7, sys/socket.h does not define either + SHUT_RDWR, SHUT_RD, and SHUT_WR. + + Reported-by: Kevin R. Bulgrien + Bug: https://curl.se/mail/lib-2021-04/0073.html + Closes #6925 + +- connect: use CURL_SA_FAMILY_T for portability + + Reported-by: Kevin R. Bulgrien + Bug: https://curl.se/mail/lib-2021-04/0071.html + + Closes #6918 + +- urlapi: make sure no +/- signs are accepted in IPv4 numericals + + Follow-up to 56a037cc0ad1b2. Extends test 1560 to verify. + + Reported-by: Tuomas Siipola + Fixes #6916 + Closes #6917 + +- ConnectionExists: respect requests for h1 connections better + + ... for situations when multiplexing isn't enabled on the h2 connection + and h1 is explicitly requested for the transfer. + + Assisted-by: Gergely Nagy + +- multi: don't close connection HTTP_1_1_REQUIRED + + The ConnectionExists() function will note that the new transfer wants + less then h2 and that it can't multiplex it and therefor opt to open a + new connection instead. + +- http2: move the stream error field to the per-transfer storage + + Storing a stream error in the per-connection struct was an error that lead to + race conditions as subsequent stream handling could overwrite the error code + before it was used for the stream with the actual problem. + + Closes #6910 + +- http2: call the handle-closed function correctly on closed stream + + This was this one condition where the stream could be closed due to an + error and the function would still wrongly just return 0 for it. + + Reported-by: Gergely Nagy + Fixes #6862 + Closes #6910 + +- test1660: check the created HSTS file as text mode + + Closes #6922 + +- RELEASE-NOTES: synced + +- test 493: require https in curl to run + + Closes #6927 + +Jay Satiro (20 Apr 2021) +- tool_operate: don't discard failed parallel transfer result + + - Save a parallel transfer's result code only when it fails and the + transfer is not being retried. + + Prior to this change the result code was always set which meant that a + failed result could be erroneously discarded if a different transfer + later had a successful result (CURLE_OK). + + Before: + + > curl --fail -Z https://httpbin.org/status/404 https://httpbin.org/delay/10 + > echo %ERRORLEVEL% + 0 + + After: + + > curl --fail -Z https://httpbin.org/status/404 https://httpbin.org/delay/10 + > echo %ERRORLEVEL% + 22 + + Closes #xxxx + +- [Georeth Zhou brought this change] + + openssl: fix build error with OpenSSL < 1.0.2 + + Closes https://github.com/curl/curl/pull/6920 + +Viktor Szakats (19 Apr 2021) +- README.md: delete Codacy UTM parameters & follow permanent redirect [ci skip] + + UTM parameters leak referrer and various marketing/tracking information + even if these would normally be stripped by website or client policy. + This link also works fine without them. Also took the opportunity to + update the URL to the one pointed to by the previous one via permanent + redirect. + + Reviewed-by: Daniel Stenberg + Closes #6919 + +Daniel Stenberg (19 Apr 2021) +- urlapi: "normalize" numerical IPv4 host names + + When the host name in a URL is given as an IPv4 numerical address, the + address can be specified with dotted numericals in four different ways: + a32, a.b24, a.b.c16 or a.b.c.d and each part can be specified in + decimal, octal (0-prefixed) or hexadecimal (0x-prefixed). + + Instead of passing on the name as-is and leaving the handling to the + underlying name functions, which made them not work with c-ares but work + with getaddrinfo, this change now makes the curl URL API itself detect + and "normalize" host names specified as IPv4 numericals. + + The WHATWG URL Spec says this is an okay way to specify a host name in a + URL. RFC 3896 does not allow them, but curl didn't prevent them before + and it seems other RFC 3896-using tools have not either. Host names used + like this are widely supported by other tools as well due to the + handling being done by getaddrinfo and friends. + + I decided to add the functionality into the URL API itself so that all + users of these functions get the benefits, when for example wanting to + compare two URLs. Also, it makes curl built to use c-ares now support + them as well and make curl builds more consistent. + + The normalization makes HTTPS and virtual hosted HTTP work fine even + when curl gets the address specified using one of the "obscure" formats. + + Test 1560 is extended to verify. + + Fixes #6863 + Closes #6871 + +- libssh: fix "empty expression statement has no effect" warnings + + ... by fixing macros to do-while constructs and moving out the calls to + "break" outside of the actual macro. It also fixes the problem where the + macro was used witin a loop and the break didn't do right. + + Reported-by: Emil Engler + Fixes #6847 + Closes #6909 + +- hsts: enable by default + + No longer considered experimental. + + Closes #6700 + +- vtls: refuse setting any SSL version + + ... previously they were supported if a TLS library would (unexpectedly) + still support them, but from this change they will be refused already in + curl_easy_setopt(). SSLv2 and SSLv3 have been known to be insecure for + many years now. + + Closes #6773 + +- curl: ignore options asking for SSLv2 or SSLv3 + + Instead output a warning about it and continue with the defaults. + + These SSL versions are typically not supported by the TLS libraries since a + long time back already since they are inherently insecure and broken. Asking + for them to be used will just cause an error to be returned slightly later. + + In the unlikely event that a user's TLS library actually still supports these + protocol versions, this change might make the request a little less insecure. + + Closes #6772 + +- test972: verify the json output with jsonlint + + Make sure one of the azure jobs has jsonlint installed so that the test + runs there. + + Ref: #6905 + +- [Jay Satiro brought this change] + + tool_writeout: fix the HTTP_CODE json output + + Update test 970 accordingly. + + Reported-by: Michal Rus + Fixes #6905 + Closes #6906 + +- openldap: protect SSL-specific code with proper #ifdef + + Closes #6901 + +- libssh2: fix Value stored to 'sshp' is never read + + Pointed out by scan-build + + Closes #6900 + +- [Victor Vieux brought this change] + + tool_getparam: replace (in-place) '%20' by '+' according to RFC1866 + + Signed-off-by: Victor Vieux <victorvieux@gmail.com> + + Closes #6895 + +- configure: provide --with-openssl, deprecate --with-ssl + + Makes the option more explicit. + + Closes #6887 + +- RELEASE-NOTES: synced + + and bumped curlver to 7.77.0 + +- [Javier Blazquez brought this change] + + rustls: only return CURLE_AGAIN when TLS session is fully drained + + The code in cr_recv was returning prematurely as soon as the socket + reported no more data to read. However, this could be leaving some + unread plaintext data in the rustls session from a previous call, + causing causing the transfer to hang if the socket never receives + further data. + + We need to ensure that the session is fully drained of plaintext data + before returning CURLE_AGAIN to the caller. + + Reviewed-by: Jacob Hoffman-Andrews + Closes #6894 + +- cookie: CURLOPT_COOKIEFILE set to NULL switches off cookies + + Add test 676 to verify that setting CURLOPT_COOKIEFILE to NULL again clears + the cookiejar from memory. + + Reported-by: Stefan Karpinski + Fixes #6889 + Closes #6891 + Version 7.76.1 (14 Apr 2021) Daniel Stenberg (14 Apr 2021) @@ -6136,1543 +7828,3 @@ Daniel Stenberg (16 Sep 2020) - dynbuf: make sure Curl_dyn_tail() zero terminates Closes #5959 - -- tests: add test1912 to the dist - - Follow-up to 70984ce1be4cab6c - -- docs/LICENSE-MIXING: remove - - This document is not maintained and I feel that it doesn't provide much - value to users anymore (if it ever did). - - Closes #5955 - -- [Laramie Leavitt brought this change] - - http: consolidate nghttp2_session_mem_recv() call paths - - 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. - - 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. - - 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 - -- base64: also build for pop3 and imap - - Follow-up to the fix in 20417a13fb8f83 - - Reported-by: Michael Olbrich - Fixes #5937 - Closes #5948 - -- base64: enable in build with SMTP - - The oauth2 support is used with SMTP and it uses base64 functions. - - Reported-by: Michael Olbrich - Fixes #5937 - Closes #5938 - -- curl_mime_headers.3: fix the example's use of curl_slist_append - - Reported-by: sofaboss on github - Fixes #5942 - Closes #5943 - -- lib583: fix enum mixup - - grrr the previous follow-up to 17fcdf6a31 was wrong - -- libtest: fix build errors - - Follow-up from 17fcdf6a310d4c8076 - -- lib: fix -Wassign-enum warnings - - configure --enable-debug now enables -Wassign-enum with clang, - identifying several enum "abuses" also fixed. - - Reported-by: Gisle Vanem - Bug: https://github.com/curl/curl/commit/879007f8118771f4896334731aaca5850a154675#commitcomment-42087553 - - Closes #5929 - -- RELEASE-NOTES: synced - -- [Diven Qi 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) - - Fixed #5911 - Closes #5914 - -- travis: add a build using libressl (from git master) - - The v3.2.1 tag (latest release atm) results in a broken build. - - Closes #5932 - -- configure: let --enable-debug set -Wenum-conversion with gcc >= 10 - - Unfortunately, this option is not detecting the same issues as clang's - -Wassign-enum flag, but should still be useful to detect future - mistakes. - - Closes #5930 - -- 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. - - This unifies the libcurl return code and makes libressl run test 313 - (CRL testing) fine. - - Closes #5934 - -- FAQ: refreshed some very old language - -- cmake: make HTTP_ONLY also disable MQTT - - ... and alphasort the order of disabling protocols to make it easier to - browse. - - Closes #5931 - -- libtest: remove lib1541 leftovers - - Caused automake errors. - - Follow-up to 8ca54a03ea08a - -- tests/libtests: remove test 1900 and 2033 - - We already remove the test files, now remove the libtest codes as well. - - Follow-up to e50a877df74 - -Marc Hoersken (7 Sep 2020) -- CI/azure: add test number to title for display in analytics - - 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. - - Bump test case revision to make Azure DevOps update titles. - - Closes #5927 - -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. - - Closes #5923 - -- test1541: remove since it is a known bug - - 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. - - The test code in lib1541.c is left in git to allow us to restore it when - we get to fix this. - - Closes #5922 - -- tests: remove pipelining tests - - Remove the tests 530, 584, 1900, 1901, 1902, 1903 and 2033. They were - previously disabled. - - The Pipelining code was removed from curl in commit 2f44e94efb3df8e, - April 2019. - - Closes #5921 - -- 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 - -- curl:parallel_transfers: make sure retry readds the transfer - - Reported-by: htasta on github - Fixes #5905 - Closes #5917 - -- build: drop support for building with Watcom - - These files are not maintained, they seem to have no users, Watcom - compilers look like not having users nor releases anymore. - - Closes #5918 - -- winbuild/rundebug.cmd: remove - - Seems to have been added by mistake? Not included in dists. - - Closes #5919 - -- curl: in retry output don't call all problems "transient" - - ... because when --retry-all-errors is used, the error isn't necessarily - transient at all. - - Closes #5916 - -- easygetopt: pass a valid enum to avoid compiler warning - - "integer constant not in range of enumerated type 'CURLoption'" - - Reported-by: Gisle Vanem - Bug: https://github.com/curl/curl/commit/6ebe63fac23f38df911edc348e8ccc72280f9434#commitcomment-42042843 - - Closes #5915 - -- [Emil Engler brought this change] - - tests: Add tests for new --help - - This commit is a part of "--help me if you can" - - Closes #5680 - -- [Emil Engler brought this change] - - tool: update --help with categories - - This commit is a part of "--help me if you can" - - Closes #5680 - -- [Emil Engler brought this change] - - docs: add categories to all cmdline opts - - Adapted gen.pl with 'listcats' - - This commit is a part of "--help me if you can" - - Closes #5680 - -- RELEASE-NOTES: synced - -- [ihsinme brought this change] - - connect.c: remove superfluous 'else' in Curl_getconnectinfo - - Closes #5912 - -- [Samuel Marks brought this change] - - CMake: remove explicit `CMAKE_ANSI_CFLAGS` - - 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 - - Reviewed-By: Peter Wu - Closes #5439 - -- [cbe brought this change] - - libssh2: pass on the error from ssh_force_knownhost_key_type - - Closes #5909 - -- scripts/delta: add diffstat summary - - ... and make output more table-like - -- [Martin BaÅ¡ti brought this change] - - http_proxy: do not crash with HTTPS_PROXY and NO_PROXY set - - ... in case NO_PROXY takes an effect - - Without this patch, the following command crashes: - - $ GIT_CURL_VERBOSE=1 NO_PROXY=github.com HTTPS_PROXY=https://example.com \ - git clone https://github.com/curl/curl.git - - Minimal libcurl-based reproducer: - - #include <curl/curl.h> - - 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 - -- travis: add a CI job with openssl3 (from git master) - - Closes #5908 - -- openssl: avoid error conditions when importing native CA - - 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 #5907 - -- setopt: avoid curl_ on local variable - - Closes #5906 - -- mqtt.c: avoid curl_ prefix on local variable - - Closes #5906 - -- wildcard: strip "curl_" prefix from private symbols - - Closes #5906 - -- vtls: make it 'struct Curl_ssl_session' - - Use uppercase C for internal symbols. - - Closes #5906 - -- curl_threads: make it 'struct Curl_actual_call' - - Internal names should not be prefixed "curl_" - - Closes #5906 - -- schannel: make it 'struct Curl_schannel*' - - As internal global names should use captical C. - - Closes #5906 - -- hash: make it 'struct Curl_hash' - - As internal global names should use captical C. - - Closes #5906 - -- llist: make it "struct Curl_llist" - - As internal global names should use captical C. - - Closes #5906 - -Marc Hoersken (2 Sep 2020) -- telnet.c: depend on static requirement of WinSock version 2 - - Drop dynamic loading of ws2_32.dll and instead rely on the - imported version which is now required to be at least 2.2. - - Reviewed-by: Marcel Raad - Reviewed-by: Jay Satiro - Reviewed-by: Daniel Stenberg - Reviewed-by: Viktor Szakats - - Closes #5854 - -- 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 - - Follow up to #5634 - Closes #5854 - -- select: align poll emulation to return all relevant events - - 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. - - Also fix indentation in input event handling block. - - Assisted-by: Jay Satiro - Reviewed-by: Daniel Stenberg - - Replaces #5852 - Closes #5883 - -- CI/azure: MQTT is now enabled by default - - Reviewed-by: Daniel Stenberg - - Follow up to #5858 - Closes #5903 - -Daniel Stenberg (2 Sep 2020) -- copyright.pl: ignore buildconf - -- test971: show test mismatches "inline" - -- lib/Makefile.am: bump VERSIONINFO due to new functions - - ... we're generally bad at this, but we are adding new functions for - this release. - - Closes #5899 - -- optiontable: use DEBUGBUILD - - Follow-up to commit 6e18568ba38 (#5877) - -- cmdline-opts/gen.pl: generate nicer "See Also" in curl.1 - - 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. - - Closes #5898 - -- curl.1: add see also no-progress-meter on two spots - - Ref: #5894 - - Closes #5897 - -- RELEASE-NOTES: synced - -- mqtt: enable by default - - No longer considered experimental. - - Closes #5858 - -- [Michael Baentsch brought this change] - - tls: add CURLOPT_SSL_EC_CURVES and --curves - - Closes #5892 - -- url: remove funny embedded comments in Curl_disonnect calls - -- [Chris Paulson-Ellis 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. - - Partial revert of 755083d00deb16 - - Fixes #5884 - Closes #5893 - -Marc Hoersken (29 Aug 2020) -- buildconf: exec autoreconf to avoid additional process - - Also make buildconf exit with the return code of autoreconf. - - Reviewed-by: Daniel Stenberg - - Follow up to #5853 - Closes #5890 - -- CI/azure: no longer ignore results of test 1013 - - Follow up to #5771 - Closes #5889 - -- docs: add description about CI platforms to CONTRIBUTE.md - - Reviewed-by: Daniel Stenberg - Reviewed-by: Marcel Raad - Reviewed-by: Jay Satiro - - Closes #5882 - -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. - - It also happens to use the exact same function name, which otherwise - causes a run-time warning. - - Reported-by: Marc Hörsken - Fixes #5885 - Closes #5887 - -Marcel Raad (29 Aug 2020) -- ntlm: fix condition for curl_ntlm_core usage - - `USE_WINDOWS_SSPI` without `USE_WIN32_CRYPTO` but with any other DES - backend is fine, but was excluded before. - - 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 - -- AppVeyor: switch 64-bit Schannel Debug CMake builds to Unicode - - 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. - - Closes https://github.com/curl/curl/pull/5843 - -- CMake: add option to enable Unicode on Windows - - As already existing for winbuild. - - Closes https://github.com/curl/curl/pull/5843 - -Marc Hoersken (29 Aug 2020) -- select: simplify return code handling for poll and select - - 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. - - Also we can just use one check with <= 0 on the return code. - - Assisted-by: Daniel Stenberg - Reviewed-by: Jay Satiro - - Replaces #5852 - Closes #5880 - -Daniel Stenberg (28 Aug 2020) -- RELEASE-NOTES: synced - -- [Jeroen Ooms brought this change] - - tests: add test1912 with typechecks - - Validates that gcc-typecheck macros match the new option type API. - - Closes #5873 - -- easyoptions: provide debug function when DEBUGBUILD - - ... not CURLDEBUG as they're not always set in conjunction. - - Follow-up to 6ebe63fac23f38df - - Fixes #5877 - Closes #5878 - -Marc Hoersken (28 Aug 2020) -- sockfilt: handle FD_CLOSE winsock event on write socket - - 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. - - Follow up to #5867 - Closes #5879 - -- multi: handle connection state winsock events - - 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. - - Reviewed-by: Jay Satiro - Reviewed-by: Marcel Raad - - Follow up to #5634 - Closes #5867 - -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. - - 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: IonuÈ›-Francisc Oancea - Fixes #5583 - Closes #5847 - -- TLS: fix SRP detection by using the proper #ifdefs - - USE_TLS_SRP will be true if *any* selected TLS backend can use SRP - - HAVE_OPENSSL_SRP is defined when OpenSSL can use it - - HAVE_GNUTLS_SRP is defined when GnuTLS can use it - - Clarify in the curl_verison_info docs that CURL_VERSION_TLSAUTH_SRP is - set if at least one of the supported backends offers SRP. - - Reported-by: Stefan Strogin - Fixes #5865 - Closes #5870 - -- [Dan Kenigsberg brought this change] - - docs: SSLCERTS: fix English syntax - - Signed-off-by: Dan Kenigsberg <danken@redhat.com> - - Closes #5876 - -- [Alessandro Ghedini brought this change] - - docs: non-existing macros in man pages - - As reported by man(1) when invoked as: - - man --warnings -E UTF-8 -l -Tutf8 -Z <file> >/dev/null - - Closes #5846 - -- [Alessandro Ghedini brought this change] - - curl.1: fix typo invokved -> invoked - - Closes #5846 - -- buildconf: invoke 'autoreconf -fi' instead - - The custom script isn't necessary anymore - but remains for simplicity - and just invokes autoreconf. - - Closes #5853 - -- [Emil Engler brought this change] - - 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"? - - Closes #5866 - -- docs/libcurl: update "Added in" version for curl_easy_option* - - Follow-up to 6ebe63fac23f38 - -- scripts: improve the "get latest curl release tag" logic - - ... by insiting on it matching "^curl-". - -- configure: added --disable-get-easy-options - - To allow disabling of the curl_easy_option APIs in a build. - - Closes #5365 - -- options: API for meta-data about easy options - - const struct curl_easyoption *curl_easy_option_by_name(const char *name); - - const struct curl_easyoption *curl_easy_option_by_id (CURLoption id); - - const struct curl_easyoption * - curl_easy_option_next(const struct curl_easyoption *prev); - - 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. - - Assisted-by: Jeroen Ooms - Closes #5365 - -- [Eric Curtin brought this change] - - HTTP/3: update to OpenSSL_1_1_1g-quic-draft-29 - - Closes #5871 - -- RELEASE-NOTES: synced - -Jay Satiro (26 Aug 2020) -- openssl: Fix wincrypt symbols conflict with BoringSSL - - OpenSSL undefines the conflicting symbols but BoringSSL does not so we - must do it ourselves. - - Reported-by: Samuel Tranchet - Assisted-by: Javier Blazquez - - 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 - - Fixes https://github.com/curl/curl/issues/5669 - Closes https://github.com/curl/curl/pull/5857 - -Daniel Stenberg (26 Aug 2020) -- socketpair: allow CURL_DISABLE_SOCKETPAIR - - ... to completely disable the use of socketpair - - Closes #5850 - -- curl_get_line: build only if cookies or alt-svc are enabled - - Closes #5851 - -- [fullincome brought this change] - - schannel: fix memory leak when using get_cert_location - - 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. - - Fixes #5855 - Closes #5860 - -- [Emil Engler brought this change] - - git: ignore libtests in 3XXX area - - 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 #5859 - -- [Emil Engler brought this change] - - doh: add error message for DOH_DNS_NAME_TOO_LONG - - When this error code was introduced in b6a53fff6c1d07e8a9, it was - forgotten to be added in the errors array and doh_strerror function. - - Closes #5863 - -- ngtcp2: adapt to the new pkt_info arguments - - Guidance-by: Tatsuhiro Tsujikawa - - Closes #5864 - -- winbuild/README.md: make <options> visible - - Follow-up to be753add31c2d8c - -- winbuild: convert the instruction text to README.md - - Closes #5861 - -- lib1560: verify "redirect" to double-slash leading URL - - Closes #5849 - -Marc Hoersken (25 Aug 2020) -- multi: expand pre-check for socket readiness - - 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 - -- [rcombs brought this change] - - 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. - - 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. - - 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. - - 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 - - Replaces #5397 - Reverts #5632 - Closes #5634 - -- select: reduce duplication of Curl_poll in Curl_socket_check - - Change Curl_socket_check to use select-fallback in Curl_poll - instead of implementing it in Curl_socket_check and Curl_poll. - - Reviewed-by: Daniel Stenberg - Reviewed-by: Jay Satiro - - Replaces #5262 and #5492 - Closes #5707 - -- select: fix poll-based check not detecting connect failure - - 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). - - The select-based socket check correctly checks for connect - failures by adding the write socket also to fds_err. - - 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. - - See the follow up commit to this for more information. - - This commit makes sure connect failures can be detected - and handled if HAVE_POLL_FINE is defined, eg. on msys2-devel. - - Reviewed-by: Daniel Stenberg - Reviewed-by: Jay Satiro - - Replaces #5509 - Prepares #5707 - -- select.h: make socket validation macros test for INVALID_SOCKET - - 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 - - Reviewed-by: Jay Satiro - Reviewed-by: Marcel Raad - Reviewed-by: Daniel Stenberg - - Closes #5760 - -Daniel Stenberg (24 Aug 2020) -- docs: --output-dir is added in 7.73.0, nothing else - - Follow-up to 5620d2cc78c0 - -- curl: add --output-dir - - Works with --create-dirs and with -J - - Add test 3008, 3009, 3011, 3012 and 3013 to verify. - - Closes #5637 - -- configure: fix pkg-config detecting wolfssl - - 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 - -- [Michael Musset brought this change] - - sftp: add the option CURLKHSTAT_FINE_REPLACE - - Replace the old fingerprint of the host with a new. - - Closes #5685 - -- 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 - - Closes #5845 - -- 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 - -- etag: save and use the full received contents - - ... which makes it support weak tags and non-standard etags too! - - Added test case 347 to verify blank incoming ETag: - - Fixes #5610 - Closes #5833 - -- setopt: if the buffer exists, refuse the new BUFFERSIZE - - The buffer only exists during transfer and then we shouldn't change the - size (the setopt is not documented to work then). - - Reported-by: Harry Sintonen - Closes #5842 - -- [COFFEETALES brought this change] - - sftp: add new quote commands 'atime' and 'mtime' - - Closes #5810 - -- CURLE_PROXY: new error code - - 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. - - 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 - -- runtests: make cleardir() erase dot files too - - Because test cases might use dot files. - - Closes #5838 - -- KNOWN_BUGS: 'no_proxy' string-matches IPv6 numerical addreses - - Also: the current behavior is now documented in the curl.1 and - CURLOPT_NOPROXY.3 man pages. - - Reported-by: Andrew Barnes - Closes #5745 - Closes #5841 - -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. - - 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 - -Daniel Stenberg (21 Aug 2020) -- runtests: avoid 'fail to start' repeated messages in attempt loops - - Closes #5834 - -- runtests: clear pid variables when failing to start a server - - ... 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 - -- TODO: Virtual external sockets - - Closes #5835 - -- [Don J Olmstead brought this change] - - dist: add missing CMake Find modules to the distribution - - Closes #5836 - -- RELEASE-NOTES: synced - - ... and version bumped to 7.72.1 - -- tls: provide the CApath verbose log on its own line - - ... not newline separated from the previous line. This makes it output - asterisk prefixed properly like other verbose putput! - - Reported-by: jmdavitt on github - Fixes #5826 - Closes #5827 - -Version 7.72.0 (19 Aug 2020) - -Daniel Stenberg (19 Aug 2020) -- RELEASE-NOTES: synced - - 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 - - Reported-by: plujon@users.noreply.github.com - - Closes https://github.com/curl/curl/issues/5488 - -Daniel Stenberg (17 Aug 2020) -- Curl_easy: remember last connection by id, not by pointer - - CVE-2020-8231 - - Bug: https://curl.haxx.se/docs/CVE-2020-8231.html - - Reported-by: Marc Aldorasi - Closes #5824 - -- examples/rtsp.c: correct the copyright year - -- RELEASE-PROCEDURE.md: add more future release dates - -- [H3RSKO brought this change] - - docs: change "web site" to "website" - - According to wikipedia: - - While "web site" was the original spelling, this variant has become - rarely used, and "website" has become the standard spelling - - Closes #5822 - -- [Bevan Weiss brought this change] - - CMake: don't complain about missing nroff - - The curl_nroff_check() was always being called, and complaining if - *NROFF wasn't found, even when not making the manual. - - Only check for nroff (and complain) if actually making the manual - - Closes #5817 - -- [Brian Inglis brought this change] - - libtest/Makefile.am: add -no-undefined for libstubgss for Cygwin - - copy the LDFLAGS approach for adding same option with `libhostname` in - `libtest/Makefile.am`: - - - init `libstubgss_la_LDFLAGS_EXTRA` variable, - - add option to variable inside conditional, - - use variable in `libstubgss_la_LDFLAGS` - - Fixes #5819 - Closes #5820 - -- docs: clarify MAX_SEND/RECV_SPEED functionality - - ... 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: Tomas Berger - Fixes #5788 - Closes #5813 - -- test1140: compare stdout - - To make problems more immediately obvious when tests fail. - - Closes #5814 - -- asyn-ares: correct some bad comments - - Closes #5812 - -- [Emil Engler brought this change] - - docs: Add video link to docs/CONTRIBUTE.md - - Closes #5811 - -- curl-config: ignore REQUIRE_LIB_DEPS in --libs output - - Fixes a curl-config issue on cygwin by making sure REQUIRE_LIB_DEPS is - not considered for the --libs output. - - 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] - - multi: Remove 10-year old out-commented code - - The code hasn't been touched since 2010-08-18 - - Closes #5805 - -- KNOWN_BUGS: A shared connection cache is not thread-safe - - Closes #4915 - Closes #5802 - -- CONTRIBUTE: extend git commit message description - - In particular how the first line works. - - Closes #5803 - -- RELEASE-NOTES: synced - -- [Stefan Yohansson brought this change] - - transfer: move retrycount from connect struct to easy handle - - 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 - -- libssh2: s/ssherr/sftperr/ - - 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 7370b4e39f1 - - Reported-by: Gisle Vanem - Bug: https://github.com/curl/curl/commit/7370b4e39f1390e701f5b68d910c619151daf72b#r41334700 - Closes #5799 - -- 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. - - Have ssl_close reset the TLS connection state. - - This partially reverts commit f002c850d98d - - 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 - - This makes sure that tests ignored or skipped are not shown - just in the category "Other", but with their correct state. - - Closes #5796 - -- CI/azure: show runtime stats to investigate slowness - - Also avoid naming conflict of TFLAGS env and tflags variables. - - Closes #5776 - -Daniel Stenberg (8 Aug 2020) -- TLS naming: fix more Winssl and Darwinssl leftovers - - The CMake option is now called CMAKE_USE_SCHANNEL - - The winbuild flag is USE_SCHANNEL - - The CI jobs and build scripts only use the new names and the new name - options - - Tests now require 'Schannel' (when necessary) - - Closes #5795 - -- smtp_parse_address: handle blank input string properly - - Closes #5792 - -- runtests: run the DICT server on a random port number - - Removed support for -b (base port number) - - Closes #5783 - -- RELEASE-NOTES: synced - -- runtests: move the TELNET server to a dynamic port - - Rename the port variable to TELNETPORT to better match the existing - pattern. - - Closes #5785 - -- ngtcp2: adapt to error code rename - - Closes #5786 - -- runtests: move the smbserver to use a dynamic port number - - Closes #5782 - -- runtests: run the http2 tests on a random port number - - Closes #5779 - -- gtls: survive not being able to get name/issuer - - Closes #5778 - -- runtests: move the gnutls-serv tests to a dynamic port - - Affects test 320, 321, 322 and 324. - - Closes #5778 - -- 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. - - 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 - -- curl.1: add a few missing valid exit codes - - 93 - 96 can be returned as well. - - Closes #5777 - -- TODO: Use multiple parallel transfers for a single download - - Closes #5774 - -- TODO: Set the modification date on an uploaded file - - Closes #5768 - -- [Thomas M. DuBuisson brought this change] - - CI: Add muse CI config - - Closes #5772 - -- [Thomas M. DuBuisson brought this change] - - travis/script.sh: fix use of `-n' with unquoted envvar - - Shellcheck tells us "-n doesn't work with unquoted arguments. quote or - use [[ ]]." - - 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 - -- h2: repair trailer handling - - 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. - - This change reverts the logic back to gathering all trailers into a - single buffer, like before 54a2b63. - - Reported-by: Tadej Vengust - Fixes #5663 - Closes #5769 - -Viktor Szakats (3 Aug 2020) -- windows: disable Unix Sockets for old mingw - - 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 - - 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 - -- RELEASE-NOTES: synced - -- tlsv1.3.d. only for TLS-using connections - - ... and rephrase that "not all" TLS backends support it. - - Closes #5764 - -- tls-max.d: this option is only for TLS-using connections - - Ref: #5763 - Closes #5764 - -Marcel Raad (2 Aug 2020) -- [Cameron Cawley brought this change] - - tool_doswin: Simplify Windows version detection - - Closes https://github.com/curl/curl/pull/5754 - -- [Cameron Cawley brought this change] - - win32: Add Curl_verify_windows_version() to curlx - - Closes https://github.com/curl/curl/pull/5754 - -- runtests.pl: treat LibreSSL and BoringSSL as OpenSSL - - This makes the tests that require the OpenSSL feature also run for - those two compatible libraries. - - Closes https://github.com/curl/curl/pull/5762 - -Daniel Stenberg (1 Aug 2020) -- multi: Condition 'extrawait' is always true - - Reported by Codacy. - - Reviewed-by: Marcel Raad - Closes #5759 - -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]. - - [0] https://github.com/libressl-portable/openbsd/commit/0db809ee178457c8170abfae3931d7bd13abf3ef - - Closes https://github.com/curl/curl/pull/5757 - -Daniel Stenberg (1 Aug 2020) -- [Marc Aldorasi brought this change] - - multi_remove_handle: close unused connect-only connections - - 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 #5749 - -- checksrc: invoke script with -D to find .checksrc proper - - 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 - -- [Carlo Marcelo Arenas Belón brought this change] - - buildconf: retire ares buildconf invocation - - no longer needed after 4259d2df7dd95637a4b1e3fb174fe5e5aef81069 - -- [Carlo Marcelo Arenas Belón brought this change] - - buildconf: excempt defunct reference to ACLOCAL_FLAGS - - retired with 09f278121e815028adb24d228d8092fc6cb022aa but kept around as - the name is generic enough that it might be in use and relied upon from - the environment. - -- [Carlo Marcelo Arenas Belón brought this change] - - buildconf: avoid array concatenation in die() - - reported as error SC2145[1] by shellcheck, but not expected to cause - any behavioural differences otherwise. - - [1] https://github.com/koalaman/shellcheck/wiki/SC2145 - - Closes #5701 - -- travis: add ppc64le and s390x builds - - Closes #5752 - -Marc Hoersken (31 Jul 2020) -- connect: remove redundant message about connect failure - - Reviewed-by: Daniel Stenberg - - Closes #5708 - -- tests/sshserver.pl: fix compatibility with OpenSSH for Windows - - Follow up to #5721 - -- 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 - - Closes #5721 - -- 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 - -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 - -- url: fix CURLU and location following - - 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. - - Reported-by: sspiri@users.noreply.github.com - - Fixes https://github.com/curl/curl/issues/5709 - Closes https://github.com/curl/curl/pull/5713 - -Daniel Stenberg (30 Jul 2020) -- RELEASE-NOTES: synced - -- [divinity76 brought this change] - - docs: add date of 7.20 to CURLM_CALL_MULTI_PERFORM mentions - - 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 #5744 - -Jay Satiro (29 Jul 2020) -- tool_cb_wrt: fix outfile mode flags for Windows - - - Use S_IREAD and S_IWRITE mode permission flags to create the file - on Windows instead of S_IRUSR, S_IWUSR, etc. - - 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 - -Daniel Stenberg (28 Jul 2020) -- checksrc: ban gmtime/localtime - - They're not thread-safe so they should not be used in libcurl code. - - Explictly enabled when deemed necessary and in examples and tests - - Reviewed-by: Nicolas Sterchele - Closes #5732 diff --git a/libs/libcurl/docs/THANKS b/libs/libcurl/docs/THANKS index 6f164a9adf..2844ef1564 100644 --- a/libs/libcurl/docs/THANKS +++ b/libs/libcurl/docs/THANKS @@ -7,6 +7,7 @@ 0xflotus on github 1ocalhost on github 3dyd on github +3eka on github Aaro Koskinen Aaron Oneal Aaron Orenstein @@ -141,6 +142,7 @@ Andrei Sedoi Andrei Valeriu BICA Andrei Virtosu Andrej E Baranov +Andrew Barnert Andrew Barnes Andrew Benham Andrew Biggs @@ -212,6 +214,7 @@ Avery Fay awesomenode on github Axel Tillequin Ayoub Boudhar +Ayushman Singh Chauhan b9a1 on github Balaji Parasuram Balaji S Rao @@ -243,6 +246,7 @@ Benjamin Gerard Benjamin Gilbert Benjamin Johnson Benjamin Kircher +Benjamin Riefenstahl Benjamin Ritcey Benjamin Sergeant Benoit Neil @@ -272,6 +276,7 @@ Bjorn Augustsson Bjorn Reese Björn Stenberg Blaise Potard +Blake Burkhart bnfp on github Bob Relyea Bob Richmond @@ -460,6 +465,7 @@ Dan Zitter Daniel at touchtunes Daniel Bankhead Daniel Black +Daniel Carpenter Daniel Cater Daniel Egger Daniel Gustafsson @@ -503,6 +509,7 @@ David Binderman David Blaikie David Byron David Cohen +David Cook David Demelier David E. Narváez David Earl @@ -583,6 +590,7 @@ dmitrmax on github Dmitry Bartsevich Dmitry Eremin-Solenikov Dmitry Falko +Dmitry Karpov Dmitry Kostjuchenko Dmitry Kurochkin Dmitry Mikhirev @@ -769,6 +777,7 @@ Gaz Iqbal Gaël Portay Geeknik Labs Geoff Beier +Georeth Zhou Georg Horn Georg Huettenegger Georg Lippitsch @@ -899,6 +908,7 @@ Iida Yosiaki Ikko Ashimine Ilguiz Latypov Ilja van Sprundel +Illarion Taev Ilya Kosarev imilli on github Immanuel Gregoire @@ -919,6 +929,7 @@ Ivan Avdeev IvanoG on github Ivo Bellin Salarin iz8mbw on github +J. Bromley Jack Boos Yu Jack Zhang Jackarain on github @@ -1047,6 +1058,7 @@ Joe Malicki Joe Mason Joel Chen Joel Depooter +Joel Jakobsson Joel Teichroeb joey-l-us on github Jofell Gallardo @@ -1054,6 +1066,7 @@ Johan Anderson Johan Lantz Johan Nilsson Johan van Selst +Johann150 on github Johannes Bauer Johannes Ernst Johannes G. Kristinsson @@ -1202,6 +1215,7 @@ Kenny To Kent Boortz Keshav Krity Kevin Baughman +Kevin Burke Kevin Fisk Kevin Ji Kevin Lussier @@ -1222,6 +1236,7 @@ Klaus Stein Klevtsov Vadim Kobi Gurkan Koen Dergent +Koichi Shiraishi kokke on github Konstantin Isakov Konstantin Kushnir @@ -1311,7 +1326,9 @@ Luan Cestari Luca Altea Luca Boccassi Lucas Adamski +Lucas Clemente Vella Lucas Pardue +Lucas Servén MarÃn Lucas Severo Lucien Zürcher Ludek Finstrle @@ -1401,12 +1418,14 @@ Martijn Koster Martin Ankerl Martin BaÅ¡ti Martin C. Martin +Martin Dorey Martin Drasar Martin Dreher Martin Frodl Martin Galvan Martin Gartner Martin Hager +Martin Halle Martin Hedenfalk Martin Jansen Martin Kammerhofer @@ -1428,6 +1447,7 @@ Mateusz Loskot Mathias Axelsson Mathias Gumz Mathieu Legare +Matias N. Goldberg Mats Lidell Matt Arsenault Matt Ford @@ -1490,6 +1510,7 @@ Michael Jerris Michael Kalinin Michael Kaufmann Michael Kilburn +Michael Kolechkin Michael Kujawa Michael König Michael Lee @@ -1497,6 +1518,7 @@ Michael Maltese Michael Mealling Michael Mueller Michael Musset +Michael O'Farrell Michael Olbrich Michael Osipov Michael Schmid @@ -1508,6 +1530,7 @@ Michael Vittiglio Michael Wallner Michal Bonino Michal Marek +Michal Rus Michal Trybus Michal ÄŒaplygin MichaÅ‚ Antoniak @@ -1557,6 +1580,7 @@ Mohammad Hasbini Mohun Biswas momala454 on github moohoorama on github +Morten Minde Neergaard Mostyn Bramley-Moore Moti Avrahami MrdUkk on github @@ -1717,11 +1741,13 @@ Pavel Volgarev Pavol Markovic Pawel A. Gajda Pawel Kierski +PaweÅ‚ Wegner Pedro Larroy Pedro Monreal Pedro Neves pendrek at hackerone Peng Li +Peng-Yu Chen Per Jensen Per Lundberg Per Malmberg @@ -1781,6 +1807,7 @@ Pierre-Yves Bigourdan Piotr Dobrogost Piotr Komborski Po-Chuan Hsieh +Pontus Lundkvist Pooyan McSporran Poul T Lomholt Pramod Sharma @@ -1797,6 +1824,7 @@ Quanah Gibson-Mount Quentin Balland Quinn Slack R. Dennis Steed +Radek Zajic Radoslav Georgiev Radu Simionescu Rafa Muyo @@ -1812,6 +1840,7 @@ Rajesh Naganathan Rajkumar Mandal Ralf S. Engelschall Ralph Beckmann +Ralph Langendam Ralph Mitchell Ram Krushna Mishra ramsay-jones on github @@ -1846,6 +1875,7 @@ Reza Arbab Ricardo Cadime Ricardo Gomes Rich Burridge +Rich FitzJohn Rich Gray Rich Mirch Rich Rauenzahn @@ -1942,6 +1972,7 @@ Ruslan Gazizov Rutger Hofman Ruurd Beerstra RuurdBeerstra on github +Ryan Beck-Buysse Ryan Braud Ryan Chan Ryan Nelson @@ -1998,6 +2029,7 @@ Sebastian Rasmussen Senthil Raja Velu Sergei Kuzmin Sergei Nikulov +Sergey Markelov Sergey Ogryzkov Sergey Tatarincev Sergii Kavunenko @@ -2005,6 +2037,7 @@ Sergii Pylypenko Sergio Ballestrero Sergio Barresi Sergio Borghese +sergio-nsk on github Serj Kalichev Seshubabu Pasam Seth Mos @@ -2060,6 +2093,7 @@ Stefan Eissing Stefan Esser Stefan Grether Stefan Kanthak +Stefan Karpinski Stefan Krause Stefan Neis Stefan Strogin @@ -2171,14 +2205,17 @@ Tim Stack Tim Starling Tim Tassonis Tim Verhoeven +Timo Lange Timo Sirainen Timotej Lazar Timothe Litt +Timothy Gu Timothy Polich Tinus van den Berg TJ Saunders tmkk on github Tobias Blomberg +Tobias Gabriel Tobias Hieta Tobias Hintze Tobias Lindgren @@ -2218,6 +2255,7 @@ Tomasz Kojm Tomasz Lacki Tommie Gannert tommink[at]post.pl +Tommy Odom Tommy Petty Tommy Tam Ton Voon @@ -2238,6 +2276,7 @@ Trivikram Kamat Troels Walsted Hansen Troy Engel Tseng Jun +Tuomas Siipola Tuomo Rinne Tupone Alfredo Tyler Hall @@ -2248,6 +2287,7 @@ Ulrich Doehner Ulrich Telle Ulrich Zadow UrsusArctos on github +ustcqidi on github Valentin David Valentyn Korniienko Valerii Zapodovnikov @@ -2261,6 +2301,7 @@ Venkataramana Mokkapati Vicente Garcia Victor Magierski Victor Snezhko +Victor Vieux Vijay Panghal Vikram Saxena Viktor Szakats @@ -2298,6 +2339,7 @@ Wenchao Li Wenxiang Qian Werner Koch Werner Stolz +Wes Hinsley wesinator on github Wesley Laxton Wesley Miaw @@ -2336,6 +2378,7 @@ ygthien on github Yi Huang Yiming Jing Yingwei Liu +Ymir1711 on github Yonggang Luo youngchopin on github Yousuke Kimoto @@ -2344,6 +2387,7 @@ Yukihiro Kawada Yun SangHo Yuri Slobodyanyuk Yuriy Sosov +Yusuke Nakamura Yves Arrouye Yves Lejeune Zachary Seguin diff --git a/libs/libcurl/include/curl/curl.h b/libs/libcurl/include/curl/curl.h index bed8068b0b..97de8c88ae 100644 --- a/libs/libcurl/include/curl/curl.h +++ b/libs/libcurl/include/curl/curl.h @@ -612,6 +612,7 @@ typedef enum { CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */ CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */ CURLE_PROXY, /* 97 - proxy handshake error */ + CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */ CURL_LAST /* never use! */ } CURLcode; @@ -888,6 +889,10 @@ typedef enum { operating system. Currently implemented under MS-Windows. */ #define CURLSSLOPT_NATIVE_CA (1<<4) +/* - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use + a client certificate for authentication. (Schannel) */ +#define CURLSSLOPT_AUTO_CLIENT_CERT (1<<5) + /* The default connection attempt delay in milliseconds for happy eyeballs. CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document this value, keep them in sync. */ @@ -1461,8 +1466,8 @@ typedef enum { #define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to - tell libcurl to resolve names to those IP versions only. This only has - affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ + tell libcurl to use those IP versions only. This only has effect on + systems with support for more than one, i.e IPv4 _and_ IPv6. */ CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113), /* Set this option to limit the size of a file that will be downloaded from @@ -2088,6 +2093,14 @@ typedef enum { /* Same as CURLOPT_SSL_VERIFYSTATUS but for DOH (DNS-over-HTTPS) servers. */ CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308), + /* The CA certificates as "blob" used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309), + + /* The CA certificates as "blob" used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; @@ -2122,10 +2135,10 @@ typedef enum { /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host name resolves addresses using more than one IP protocol version, this option might be handy to force libcurl to use a specific IP version. */ -#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP +#define CURL_IPRESOLVE_WHATEVER 0 /* default, uses addresses to all IP versions that your system allows */ -#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */ -#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */ +#define CURL_IPRESOLVE_V4 1 /* uses only IPv4 addresses/connections */ +#define CURL_IPRESOLVE_V6 2 /* uses only IPv6 addresses/connections */ /* three convenient "aliases" that follow the name scheme better */ #define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER @@ -2866,6 +2879,7 @@ typedef enum { CURLVERSION_SEVENTH, CURLVERSION_EIGHTH, CURLVERSION_NINTH, + CURLVERSION_TENTH, CURLVERSION_LAST /* never actually use this */ } CURLversion; @@ -2874,7 +2888,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_NINTH +#define CURLVERSION_NOW CURLVERSION_TENTH struct curl_version_info_data { CURLversion age; /* age of the returned struct */ @@ -2927,6 +2941,9 @@ struct curl_version_info_data { /* These fields were added in CURLVERSION_NINTH */ const char *hyper_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_TENTH */ + const char *gsasl_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 b74cdc1170..98f7d0cdf4 100644 --- a/libs/libcurl/include/curl/curlver.h +++ b/libs/libcurl/include/curl/curlver.h @@ -30,13 +30,13 @@ /* This is the version number of the libcurl package from which this header file origins: */ -#define LIBCURL_VERSION "7.76.1" +#define LIBCURL_VERSION "7.77.0" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 7 -#define LIBCURL_VERSION_MINOR 76 -#define LIBCURL_VERSION_PATCH 1 +#define LIBCURL_VERSION_MINOR 77 +#define LIBCURL_VERSION_PATCH 0 /* This is the numeric version of the libcurl version number, meant for easier parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will @@ -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 0x074c01 +#define LIBCURL_VERSION_NUM 0x074d00 /* * This is the date and time when the full source package was created. The @@ -68,7 +68,7 @@ * * "2007-11-23" */ -#define LIBCURL_TIMESTAMP "2021-04-14" +#define LIBCURL_TIMESTAMP "2021-05-26" #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/libcurl.vcxproj b/libs/libcurl/libcurl.vcxproj index d601dbdd21..49e6a66c28 100644 --- a/libs/libcurl/libcurl.vcxproj +++ b/libs/libcurl/libcurl.vcxproj @@ -41,6 +41,9 @@ <ClCompile Include="src\base64.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="src\bufref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
<ClCompile Include="src\c-hyper.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
@@ -444,6 +447,7 @@ <ClInclude Include="src\amigaos.h" />
<ClInclude Include="src\arpa_telnet.h" />
<ClInclude Include="src\asyn.h" />
+ <ClInclude Include="src\bufref.h" />
<ClInclude Include="src\c-hyper.h" />
<ClInclude Include="src\config-amigaos.h" />
<ClInclude Include="src\config-dos.h" />
diff --git a/libs/libcurl/libcurl.vcxproj.filters b/libs/libcurl/libcurl.vcxproj.filters index 9a6fcc2b65..4ade79b333 100644 --- a/libs/libcurl/libcurl.vcxproj.filters +++ b/libs/libcurl/libcurl.vcxproj.filters @@ -17,6 +17,9 @@ <ClCompile Include="src\base64.c">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\bufref.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="src\c-hyper.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -463,6 +466,9 @@ <ClInclude Include="src\asyn.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="src\bufref.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="src\c-hyper.h">
<Filter>Header Files</Filter>
</ClInclude>
diff --git a/libs/libcurl/src/CMakeLists.txt b/libs/libcurl/src/CMakeLists.txt index a58b47b865..2575288f70 100644 --- a/libs/libcurl/src/CMakeLists.txt +++ b/libs/libcurl/src/CMakeLists.txt @@ -20,6 +20,7 @@ # ########################################################################### set(LIB_NAME libcurl) +set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library") if(BUILD_SHARED_LIBS) set(CURL_STATICLIB NO) @@ -98,7 +99,10 @@ if(WIN32) add_definitions(-D_USRDLL) endif() -set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL) +set_target_properties(${LIB_NAME} PROPERTIES + COMPILE_DEFINITIONS BUILDING_LIBCURL + OUTPUT_NAME ${LIBCURL_OUTPUT_NAME} + ) if(HIDES_CURL_PRIVATE_SYMBOLS) set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS") diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in index c17ae17a51..d89f375a14 100644 --- a/libs/libcurl/src/Makefile.in +++ b/libs/libcurl/src/Makefile.in @@ -125,12 +125,22 @@ host_triplet = @host@ subdir = lib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compile_check_sizeof.m4 \ + $(top_srcdir)/m4/curl-amissl.m4 \ + $(top_srcdir)/m4/curl-bearssl.m4 \ $(top_srcdir)/m4/curl-compilers.m4 \ $(top_srcdir)/m4/curl-confopts.m4 \ $(top_srcdir)/m4/curl-functions.m4 \ + $(top_srcdir)/m4/curl-gnutls.m4 \ + $(top_srcdir)/m4/curl-mbedtls.m4 \ + $(top_srcdir)/m4/curl-mesalink.m4 $(top_srcdir)/m4/curl-nss.m4 \ $(top_srcdir)/m4/curl-openssl.m4 \ $(top_srcdir)/m4/curl-override.m4 \ - $(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/curl-reentrant.m4 \ + $(top_srcdir)/m4/curl-rustls.m4 \ + $(top_srcdir)/m4/curl-schannel.m4 \ + $(top_srcdir)/m4/curl-sectransp.m4 \ + $(top_srcdir)/m4/curl-sysconfig.m4 \ + $(top_srcdir)/m4/curl-wolfssl.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/xc-am-iface.m4 \ @@ -181,22 +191,23 @@ 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-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-base64.lo libcurl_la-bufref.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 \ @@ -269,26 +280,27 @@ 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-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-ftplistparser.lo \ - libcurlu_la-getenv.lo libcurlu_la-getinfo.lo \ - libcurlu_la-gopher.lo libcurlu_la-hash.lo libcurlu_la-hmac.lo \ + libcurlu_la-base64.lo libcurlu_la-bufref.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-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 \ @@ -373,6 +385,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-bufref.Plo \ ./$(DEPDIR)/libcurl_la-c-hyper.Plo \ ./$(DEPDIR)/libcurl_la-conncache.Plo \ ./$(DEPDIR)/libcurl_la-connect.Plo \ @@ -488,6 +501,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-bufref.Plo \ ./$(DEPDIR)/libcurlu_la-c-hyper.Plo \ ./$(DEPDIR)/libcurlu_la-conncache.Plo \ ./$(DEPDIR)/libcurlu_la-connect.Plo \ @@ -1088,6 +1102,7 @@ LIB_CFILES = \ asyn-ares.c \ asyn-thread.c \ base64.c \ + bufref.c \ c-hyper.c \ conncache.c \ connect.c \ @@ -1208,6 +1223,7 @@ LIB_HFILES = \ amigaos.h \ arpa_telnet.h \ asyn.h \ + bufref.h \ c-hyper.h \ conncache.h \ connect.h \ @@ -1626,6 +1642,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-bufref.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 @@ -1745,6 +1762,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-bufref.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 @@ -1993,6 +2011,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-bufref.lo: bufref.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-bufref.lo -MD -MP -MF $(DEPDIR)/libcurl_la-bufref.Tpo -c -o libcurl_la-bufref.lo `test -f 'bufref.c' || echo '$(srcdir)/'`bufref.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-bufref.Tpo $(DEPDIR)/libcurl_la-bufref.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bufref.c' object='libcurl_la-bufref.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-bufref.lo `test -f 'bufref.c' || echo '$(srcdir)/'`bufref.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 @@ -3064,6 +3089,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-bufref.lo: bufref.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-bufref.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-bufref.Tpo -c -o libcurlu_la-bufref.lo `test -f 'bufref.c' || echo '$(srcdir)/'`bufref.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-bufref.Tpo $(DEPDIR)/libcurlu_la-bufref.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bufref.c' object='libcurlu_la-bufref.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-bufref.lo `test -f 'bufref.c' || echo '$(srcdir)/'`bufref.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 @@ -4252,6 +4284,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-bufref.Plo -rm -f ./$(DEPDIR)/libcurl_la-c-hyper.Plo -rm -f ./$(DEPDIR)/libcurl_la-conncache.Plo -rm -f ./$(DEPDIR)/libcurl_la-connect.Plo @@ -4371,6 +4404,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-bufref.Plo -rm -f ./$(DEPDIR)/libcurlu_la-c-hyper.Plo -rm -f ./$(DEPDIR)/libcurlu_la-conncache.Plo -rm -f ./$(DEPDIR)/libcurlu_la-connect.Plo @@ -4603,6 +4637,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-bufref.Plo -rm -f ./$(DEPDIR)/libcurl_la-c-hyper.Plo -rm -f ./$(DEPDIR)/libcurl_la-conncache.Plo -rm -f ./$(DEPDIR)/libcurl_la-connect.Plo @@ -4722,6 +4757,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-bufref.Plo -rm -f ./$(DEPDIR)/libcurlu_la-c-hyper.Plo -rm -f ./$(DEPDIR)/libcurlu_la-conncache.Plo -rm -f ./$(DEPDIR)/libcurlu_la-connect.Plo diff --git a/libs/libcurl/src/Makefile.inc b/libs/libcurl/src/Makefile.inc index 90ec6aa05c..3e9ddec12c 100644 --- a/libs/libcurl/src/Makefile.inc +++ b/libs/libcurl/src/Makefile.inc @@ -97,6 +97,7 @@ LIB_CFILES = \ asyn-ares.c \ asyn-thread.c \ base64.c \ + bufref.c \ c-hyper.c \ conncache.c \ connect.c \ @@ -217,6 +218,7 @@ LIB_HFILES = \ amigaos.h \ arpa_telnet.h \ asyn.h \ + bufref.h \ c-hyper.h \ conncache.h \ connect.h \ diff --git a/libs/libcurl/src/amigaos.c b/libs/libcurl/src/amigaos.c index d3b00d9083..78bb22c7e2 100644 --- a/libs/libcurl/src/amigaos.c +++ b/libs/libcurl/src/amigaos.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -90,6 +90,33 @@ void Curl_amiga_X509_free(X509 *a) { X509_free(a); } + +/* AmiSSL replaces many functions with macros. Curl requires pointer + * to some of these functions. Thus, we have to encapsulate these macros. + */ + +#include "warnless.h" + +int (SHA256_Init)(SHA256_CTX *c) +{ + return SHA256_Init(c); +}; + +int (SHA256_Update)(SHA256_CTX *c, const void *data, size_t len) +{ + return SHA256_Update(c, data, curlx_uztoui(len)); +}; + +int (SHA256_Final)(unsigned char *md, SHA256_CTX *c) +{ + return SHA256_Final(md, c); +}; + +void (X509_INFO_free)(X509_INFO *a) +{ + X509_INFO_free(a); +}; + #endif /* USE_AMISSL */ #endif /* __AMIGA__ */ diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c index c9bd9d16a5..7827847350 100644 --- a/libs/libcurl/src/asyn-ares.c +++ b/libs/libcurl/src/asyn-ares.c @@ -309,7 +309,7 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) pfd[i].fd = socks[i]; pfd[i].events |= POLLWRNORM|POLLOUT; } - if(pfd[i].events != 0) + if(pfd[i].events) num++; else break; @@ -620,28 +620,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, int *waitp) { char *bufp; - int family = PF_INET; *waitp = 0; /* default to synchronous response */ -#ifdef ENABLE_IPV6 - switch(data->set.ipver) { - default: -#if ARES_VERSION >= 0x010601 - family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older - c-ares versions this just falls through and defaults - to PF_INET */ - break; -#endif - case CURL_IPRESOLVE_V4: - family = PF_INET; - break; - case CURL_IPRESOLVE_V6: - family = PF_INET6; - break; - } -#endif /* ENABLE_IPV6 */ - bufp = strdup(hostname); if(bufp) { struct thread_data *res = NULL; @@ -661,33 +642,27 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, /* initial status - failed */ res->last_status = ARES_ENOTFOUND; -#ifdef ENABLE_IPV6 - if(family == PF_UNSPEC) { - if(Curl_ipv6works(data)) { - res->num_pending = 2; - - /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, - PF_INET, query_completed_cb, data); - ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, - PF_INET6, query_completed_cb, data); - } - else { - res->num_pending = 1; - /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, - PF_INET, query_completed_cb, data); - } +#if ARES_VERSION >= 0x010601 + /* IPv6 supported by c-ares since 1.6.1 */ + if(Curl_ipv6works(data)) { + /* The stack seems to be IPv6-enabled */ + res->num_pending = 2; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET, query_completed_cb, data); + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET6, query_completed_cb, data); } else -#endif /* ENABLE_IPV6 */ +#endif /* ARES_VERSION >= 0x010601 */ { res->num_pending = 1; /* areschannel is already setup in the Curl_open() function */ ares_gethostbyname((ares_channel)data->state.async.resolver, - hostname, family, + hostname, PF_INET, query_completed_cb, data); } diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c index c453203f75..36f68cb493 100644 --- a/libs/libcurl/src/asyn-thread.c +++ b/libs/libcurl/src/asyn-thread.c @@ -238,7 +238,7 @@ int init_thread_sync_data(struct thread_data *td, #endif tsd->mtx = malloc(sizeof(curl_mutex_t)); - if(tsd->mtx == NULL) + if(!tsd->mtx) goto err_exit; Curl_mutex_init(tsd->mtx); @@ -305,7 +305,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res); - if(rc != 0) { + if(rc) { tsd->sock_error = SOCKERRNO?SOCKERRNO:rc; if(tsd->sock_error == 0) tsd->sock_error = RESOLVER_ENOMEM; @@ -701,24 +701,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, *waitp = 0; /* default to synchronous response */ #ifdef CURLRES_IPV6 - /* - * Check if a limited name resolve has been requested. - */ - switch(data->set.ipver) { - case CURL_IPRESOLVE_V4: - pf = PF_INET; - break; - case CURL_IPRESOLVE_V6: - pf = PF_INET6; - break; - default: + if(Curl_ipv6works(data)) + /* The stack seems to be IPv6-enabled */ pf = PF_UNSPEC; - break; - } - - 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)); diff --git a/libs/libcurl/src/bufref.c b/libs/libcurl/src/bufref.c new file mode 100644 index 0000000000..b84511e185 --- /dev/null +++ b/libs/libcurl/src/bufref.c @@ -0,0 +1,127 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2021, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.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" +#include "urldata.h" +#include "bufref.h" + +#include "curl_memory.h" +#include "memdebug.h" + +#define SIGNATURE 0x5c48e9b2 /* Random pattern. */ + +/* + * Init a bufref struct. + */ +void Curl_bufref_init(struct bufref *br) +{ + DEBUGASSERT(br); + br->dtor = NULL; + br->ptr = NULL; + br->len = 0; + +#ifdef DEBUGBUILD + br->signature = SIGNATURE; +#endif +} + +/* + * Free the buffer and re-init the necessary fields. It doesn't touch the + * 'signature' field and thus this buffer reference can be reused. + */ + +void Curl_bufref_free(struct bufref *br) +{ + DEBUGASSERT(br); + DEBUGASSERT(br->signature == SIGNATURE); + DEBUGASSERT(br->ptr || !br->len); + + if(br->ptr && br->dtor) + br->dtor((void *) br->ptr); + + br->dtor = NULL; + br->ptr = NULL; + br->len = 0; +} + +/* + * Set the buffer reference to new values. The previously referenced buffer + * is released before assignment. + */ +void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len, + void (*dtor)(void *)) +{ + DEBUGASSERT(ptr || !len); + DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH); + + Curl_bufref_free(br); + br->ptr = (const unsigned char *) ptr; + br->len = len; + br->dtor = dtor; +} + +/* + * Get a pointer to the referenced buffer. + */ +const unsigned char *Curl_bufref_ptr(const struct bufref *br) +{ + DEBUGASSERT(br); + DEBUGASSERT(br->signature == SIGNATURE); + DEBUGASSERT(br->ptr || !br->len); + + return br->ptr; +} + +/* + * Get the length of the referenced buffer data. + */ +size_t Curl_bufref_len(const struct bufref *br) +{ + DEBUGASSERT(br); + DEBUGASSERT(br->signature == SIGNATURE); + DEBUGASSERT(br->ptr || !br->len); + + return br->len; +} + +CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len) +{ + unsigned char *cpy = NULL; + + DEBUGASSERT(br); + DEBUGASSERT(br->signature == SIGNATURE); + DEBUGASSERT(br->ptr || !br->len); + DEBUGASSERT(ptr || !len); + DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH); + + if(ptr) { + cpy = malloc(len + 1); + if(!cpy) + return CURLE_OUT_OF_MEMORY; + if(len) + memcpy(cpy, ptr, len); + cpy[len] = '\0'; + } + + Curl_bufref_set(br, cpy, len, curl_free); + return CURLE_OK; +} diff --git a/libs/libcurl/src/bufref.h b/libs/libcurl/src/bufref.h new file mode 100644 index 0000000000..25f65d894d --- /dev/null +++ b/libs/libcurl/src/bufref.h @@ -0,0 +1,46 @@ +#ifndef HEADER_CURL_BUFREF_H +#define HEADER_CURL_BUFREF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2021, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.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. + * + ***************************************************************************/ + +/* + * Generic buffer reference. + */ +struct bufref { + void (*dtor)(void *); /* Associated destructor. */ + const unsigned char *ptr; /* Referenced data buffer. */ + size_t len; /* The data size in bytes. */ +#ifdef DEBUGBUILD + int signature; /* Detect API use mistakes. */ +#endif +}; + + +void Curl_bufref_init(struct bufref *br); +void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len, + void (*dtor)(void *)); +const unsigned char *Curl_bufref_ptr(const struct bufref *br); +size_t Curl_bufref_len(const struct bufref *br); +CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len); +void Curl_bufref_free(struct bufref *br); + +#endif diff --git a/libs/libcurl/src/c-hyper.c b/libs/libcurl/src/c-hyper.c index 5d370d7bda..81f589eb9e 100644 --- a/libs/libcurl/src/c-hyper.c +++ b/libs/libcurl/src/c-hyper.c @@ -175,6 +175,8 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) } if(k->ignorebody) return HYPER_ITER_CONTINUE; + if(0 == len) + return HYPER_ITER_CONTINUE; Curl_debug(data, CURLINFO_DATA_IN, buf, len); if(!data->set.http_ce_skip && k->writer_stack) /* content-encoded data */ @@ -203,11 +205,8 @@ static CURLcode status_line(struct Curl_easy *data, 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 = @@ -230,12 +229,12 @@ static CURLcode status_line(struct Curl_easy *data, len = Curl_dyn_len(&data->state.headerb); Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb), len); - 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; + result = Curl_client_write(data, CLIENTWRITE_HEADER, + Curl_dyn_ptr(&data->state.headerb), len); + if(result) { + data->state.hresult = CURLE_ABORTED_BY_CALLBACK; + return HYPER_ITER_BREAK; + } data->info.header_size += (long)len; data->req.headerbytecount += (long)len; @@ -332,7 +331,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, infof(data, "hyperstream is done!\n"); break; } - else if(t != HYPER_TASK_RESPONSE) { + else if(t != HYPER_TASK_RESPONSE && t != HYPER_TASK_EMPTY) { *didwhat = KEEP_RECV; break; } diff --git a/libs/libcurl/src/checksrc.pl b/libs/libcurl/src/checksrc.pl index 13f86ecd5a..a35535c191 100644 --- a/libs/libcurl/src/checksrc.pl +++ b/libs/libcurl/src/checksrc.pl @@ -6,7 +6,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 2011 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 2011 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -86,6 +86,8 @@ my %warnings = ( 'BRACEWHILE' => 'A single space between open brace and while', 'EXCLAMATIONSPACE' => 'Whitespace after exclamation mark in expression', 'EMPTYLINEBRACE' => 'Empty line before the open brace', + 'EQUALSNULL' => 'if/while comparison with == NULL', + 'NOTEQUALSZERO' => 'if/while comparison with != 0' ); sub readskiplist { @@ -471,6 +473,21 @@ sub scanfile { "$2 with space"); } } + # check for '== NULL' in if/while conditions but not if the thing on + # the left of it is a function call + if($nostr =~ /^(.*)(if|while)(\(.*[^)]) == NULL/) { + checkwarn("EQUALSNULL", $line, + length($1) + length($2) + length($3), + $file, $l, "we prefer !variable instead of \"== NULL\" comparisons"); + } + + # check for '!= 0' in if/while conditions but not if the thing on + # the left of it is a function call + if($nostr =~ /^(.*)(if|while)(\(.*[^)]) != 0[^x]/) { + checkwarn("NOTEQUALSZERO", $line, + length($1) + length($2) + length($3), + $file, $l, "we prefer if(rc) instead of \"rc != 0\" comparisons"); + } # check spaces in 'do {' if($nostr =~ /^( *)do( *)\{/ && length($2) != 1) { diff --git a/libs/libcurl/src/config-amigaos.h b/libs/libcurl/src/config-amigaos.h index 381bf302c9..c2f5bd20b0 100644 --- a/libs/libcurl/src/config-amigaos.h +++ b/libs/libcurl/src/config-amigaos.h @@ -128,13 +128,6 @@ # define LONG_MIN (-0x7fffffffL-1) #endif -#define HAVE_GETNAMEINFO 1 -#define GETNAMEINFO_QUAL_ARG1 const -#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * -#define GETNAMEINFO_TYPE_ARG2 int -#define GETNAMEINFO_TYPE_ARG46 size_t -#define GETNAMEINFO_TYPE_ARG7 int - #define HAVE_RECV 1 #define RECV_TYPE_ARG1 long #define RECV_TYPE_ARG2 char * diff --git a/libs/libcurl/src/config-dos.h b/libs/libcurl/src/config-dos.h index 0fb98e385d..6859208ab3 100644 --- a/libs/libcurl/src/config-dos.h +++ b/libs/libcurl/src/config-dos.h @@ -45,7 +45,6 @@ #define HAVE_FCNTL_H 1 #define HAVE_FREEADDRINFO 1 #define HAVE_GETADDRINFO 1 -#define HAVE_GETNAMEINFO 1 #define HAVE_GETPROTOBYNAME 1 #define HAVE_GETTIMEOFDAY 1 #define HAVE_IO_H 1 @@ -93,7 +92,7 @@ #define STDC_HEADERS 1 #define TIME_WITH_SYS_TIME 1 -/* Qualifiers for send(), recv(), recvfrom() and getnameinfo(). */ +/* Qualifiers for send(), recv(), and recvfrom() */ #define SEND_TYPE_ARG1 int #define SEND_QUAL_ARG2 const @@ -117,12 +116,6 @@ #define RECVFROM_TYPE_RETV int #define RECVFROM_TYPE_ARG2_IS_VOID 1 -#define GETNAMEINFO_QUAL_ARG1 const -#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * -#define GETNAMEINFO_TYPE_ARG2 int -#define GETNAMEINFO_TYPE_ARG46 int -#define GETNAMEINFO_TYPE_ARG7 int - #define BSD /* CURLDEBUG definition enables memory tracking */ diff --git a/libs/libcurl/src/config-mac.h b/libs/libcurl/src/config-mac.h index 163686ec94..c8833e3006 100644 --- a/libs/libcurl/src/config-mac.h +++ b/libs/libcurl/src/config-mac.h @@ -85,13 +85,6 @@ #define SIZEOF_SHORT 2 #define SIZEOF_SIZE_T 4 -#define HAVE_GETNAMEINFO 1 -#define GETNAMEINFO_QUAL_ARG1 const -#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * -#define GETNAMEINFO_TYPE_ARG2 socklen_t -#define GETNAMEINFO_TYPE_ARG46 size_t -#define GETNAMEINFO_TYPE_ARG7 int - #define HAVE_RECV 1 #define RECV_TYPE_ARG1 int #define RECV_TYPE_ARG2 void * diff --git a/libs/libcurl/src/config-os400.h b/libs/libcurl/src/config-os400.h index b5a9823fd1..366db983f4 100644 --- a/libs/libcurl/src/config-os400.h +++ b/libs/libcurl/src/config-os400.h @@ -310,9 +310,6 @@ /* Define if you have the <string.h> header file. */ #define HAVE_STRING_H -/* Define if you have the `strlcpy' function. */ -#undef HAVE_STRLCPY - /* Define if you have the <stropts.h> header file. */ #undef HAVE_STROPTS_H @@ -452,25 +449,6 @@ /* Define if you have the ldap_url_parse procedure. */ /* #define HAVE_LDAP_URL_PARSE */ /* Disabled because of an IBM bug. */ -/* Define if you have the getnameinfo function. */ -/* OS400 has no ASCII version of this procedure: wrapped in setup-os400.h. */ -#define HAVE_GETNAMEINFO - -/* Define to the type qualifier of arg 1 for getnameinfo. */ -#define GETNAMEINFO_QUAL_ARG1 const - -/* Define to the type of arg 1 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * - -/* Define to the type of arg 2 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG2 socklen_t - -/* Define to the type of args 4 and 6 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG46 socklen_t - -/* Define to the type of arg 7 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG7 int - /* Define if you have the recv function. */ #define HAVE_RECV diff --git a/libs/libcurl/src/config-plan9.h b/libs/libcurl/src/config-plan9.h index ecfc273722..ce89309bc1 100644 --- a/libs/libcurl/src/config-plan9.h +++ b/libs/libcurl/src/config-plan9.h @@ -54,13 +54,6 @@ #define SIZEOF_TIME_T 4 #endif -#define HAVE_GETNAMEINFO 1 -#define GETNAMEINFO_QUAL_ARG1 const -#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * -#define GETNAMEINFO_TYPE_ARG2 int -#define GETNAMEINFO_TYPE_ARG46 long -#define GETNAMEINFO_TYPE_ARG7 int - #define HAVE_RECV 1 #define RECV_TYPE_ARG1 int #define RECV_TYPE_ARG2 void * diff --git a/libs/libcurl/src/config-riscos.h b/libs/libcurl/src/config-riscos.h index 2dc3c66311..13287e0a4c 100644 --- a/libs/libcurl/src/config-riscos.h +++ b/libs/libcurl/src/config-riscos.h @@ -296,9 +296,6 @@ /* Define if you have the <string.h> header file. */ #define HAVE_STRING_H -/* Define if you have the `strlcpy' function. */ -#undef HAVE_STRLCPY - /* Define if you have the `strstr' function. */ #define HAVE_STRSTR @@ -408,24 +405,6 @@ /* to disable LDAP */ #define CURL_DISABLE_LDAP -/* Define if you have the getnameinfo function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to the type qualifier of arg 1 for getnameinfo. */ -#define GETNAMEINFO_QUAL_ARG1 const - -/* Define to the type of arg 1 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * - -/* Define to the type of arg 2 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG2 socklen_t - -/* Define to the type of args 4 and 6 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG46 size_t - -/* Define to the type of arg 7 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG7 int - /* Define if you have the recv function. */ #define HAVE_RECV 1 diff --git a/libs/libcurl/src/config-tpf.h b/libs/libcurl/src/config-tpf.h index 3fdb8924c5..12c34e18e3 100644 --- a/libs/libcurl/src/config-tpf.h +++ b/libs/libcurl/src/config-tpf.h @@ -77,18 +77,6 @@ /* Define if struct sockaddr_in6 has the sin6_scope_id member */ /* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */ -/* Define to the type of arg 1 for getnameinfo. */ -/* #undef GETNAMEINFO_TYPE_ARG1 */ - -/* Define to the type of arg 2 for getnameinfo. */ -/* #undef GETNAMEINFO_TYPE_ARG2 */ - -/* Define to the type of args 4 and 6 for getnameinfo. */ -/* #undef GETNAMEINFO_TYPE_ARG46 */ - -/* Define to the type of arg 7 for getnameinfo. */ -/* #undef GETNAMEINFO_TYPE_ARG7 */ - /* Define to 1 if you have the alarm function. */ #define HAVE_ALARM 1 @@ -162,9 +150,6 @@ /* gethostbyname_r() takes 6 args */ /* #undef HAVE_GETHOSTBYNAME_R_6 1 */ -/* Define to 1 if you have the getnameinfo function. */ -/* #undef HAVE_GETNAMEINFO */ - /* Define to 1 if you have the `getpass_r' function. */ /* #undef HAVE_GETPASS_R */ @@ -450,9 +435,6 @@ /* Define to 1 if you have the <string.h> header file. */ #define HAVE_STRING_H 1 -/* Define to 1 if you have the `strlcpy' function. */ -/* #undef HAVE_STRLCPY */ - /* Define to 1 if you have the `strstr' function. */ #define HAVE_STRSTR 1 @@ -660,24 +642,6 @@ /* the signed version of size_t */ /* #undef ssize_t */ -/* Define to 1 if you have the getnameinfo function. */ -/* #undef HAVE_GETNAMEINFO 1 */ - -/* Define to the type qualifier of arg 1 for getnameinfo. */ -/* #undef GETNAMEINFO_QUAL_ARG1 const */ - -/* Define to the type of arg 1 for getnameinfo. */ -/* #undef GETNAMEINFO_TYPE_ARG1 struct sockaddr * */ - -/* Define to the type of arg 2 for getnameinfo. */ -/* #undef GETNAMEINFO_TYPE_ARG2 socklen_t */ - -/* Define to the type of args 4 and 6 for getnameinfo. */ -/* #undef GETNAMEINFO_TYPE_ARG46 size_t */ - -/* Define to the type of arg 7 for getnameinfo. */ -/* #undef GETNAMEINFO_TYPE_ARG7 int */ - /* Define to 1 if you have the recv function. */ #define HAVE_RECV 1 diff --git a/libs/libcurl/src/config-vxworks.h b/libs/libcurl/src/config-vxworks.h index 916d023383..8911b05e24 100644 --- a/libs/libcurl/src/config-vxworks.h +++ b/libs/libcurl/src/config-vxworks.h @@ -80,21 +80,6 @@ /* Define if you want to enable IPv6 support */ #define ENABLE_IPV6 1 -/* Define to the type qualifier of arg 1 for getnameinfo. */ -#define GETNAMEINFO_QUAL_ARG1 const - -/* Define to the type of arg 1 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * - -/* Define to the type of arg 2 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG2 socklen_t - -/* Define to the type of args 4 and 6 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG46 size_t - -/* Define to the type of arg 7 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG7 unsigned int - /* Specifies the number of arguments to getservbyport_r */ #define GETSERVBYPORT_R_ARGS 6 @@ -206,9 +191,6 @@ /* Define to 1 if you have a working getifaddrs function. */ /* #undef HAVE_GETIFADDRS */ -/* Define to 1 if you have the getnameinfo function. */ -#define HAVE_GETNAMEINFO 1 - /* Define to 1 if you have the `getpass_r' function. */ /* #undef HAVE_GETPASS_R */ @@ -553,9 +535,6 @@ /* Define to 1 if you have the <string.h> header file. */ #define HAVE_STRING_H 1 -/* Define to 1 if you have the `strlcpy' function. */ -/* #undef HAVE_STRLCPY */ - /* Define to 1 if you have the strncmpi function. */ /* #undef HAVE_STRNCMPI */ diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h index 98267a8033..fc81536835 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. */ #ifdef __MINGW32__ #define HAVE_STRCASECMP 1 @@ -281,21 +277,6 @@ #define HAVE_UTIME 1 #endif -/* Define to the type qualifier of arg 1 for getnameinfo. */ -#define GETNAMEINFO_QUAL_ARG1 const - -/* Define to the type of arg 1 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * - -/* Define to the type of arg 2 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG2 socklen_t - -/* Define to the type of args 4 and 6 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG46 DWORD - -/* Define to the type of arg 7 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG7 int - /* Define if you have the recv function. */ #define HAVE_RECV 1 @@ -423,7 +404,6 @@ # undef HAVE_WS2TCPIP_H # undef HAVE_ERRNO_H # undef HAVE_GETHOSTNAME -# undef HAVE_GETNAMEINFO # undef LWIP_POSIX_SOCKETS_IO_NAMES # undef RECV_TYPE_ARG1 # undef RECV_TYPE_ARG3 @@ -454,7 +434,6 @@ #undef HAVE_WINSOCK2_H #undef HAVE_WS2TCPIP_H #define HAVE_GETADDRINFO - #define HAVE_GETNAMEINFO #define HAVE_SYS_IOCTL_H #define HAVE_SYS_SOCKET_H #define HAVE_NETINET_IN_H @@ -584,7 +563,7 @@ Vista # endif #endif -/* Availability of freeaddrinfo, getaddrinfo, getnameinfo and if_nametoindex +/* Availability of freeaddrinfo, getaddrinfo, and if_nametoindex functions is quite convoluted, compiler dependent and even build target dependent. */ #if defined(HAVE_WS2TCPIP_H) @@ -592,17 +571,14 @@ Vista # define HAVE_FREEADDRINFO 1 # define HAVE_GETADDRINFO 1 # define HAVE_GETADDRINFO_THREADSAFE 1 -# define HAVE_GETNAMEINFO 1 # elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) # define HAVE_FREEADDRINFO 1 # define HAVE_GETADDRINFO 1 # define HAVE_GETADDRINFO_THREADSAFE 1 -# define HAVE_GETNAMEINFO 1 # elif defined(_MSC_VER) && (_MSC_VER >= 1200) # define HAVE_FREEADDRINFO 1 # define HAVE_GETADDRINFO 1 # define HAVE_GETADDRINFO_THREADSAFE 1 -# define HAVE_GETNAMEINFO 1 # endif #endif @@ -712,9 +688,6 @@ Vista # define CURL_DISABLE_LDAP 1 #endif -/* if SSL is enabled */ -#define USE_OPENSSL 1 - /* Define to use the Windows crypto library. */ #if !defined(CURL_WINDOWS_APP) #define USE_WIN32_CRYPTO diff --git a/libs/libcurl/src/config-win32ce.h b/libs/libcurl/src/config-win32ce.h index fb29e088f6..44cc028874 100644 --- a/libs/libcurl/src/config-win32ce.h +++ b/libs/libcurl/src/config-win32ce.h @@ -219,24 +219,6 @@ /* Define if you have the utime function */ #define HAVE_UTIME 1 -/* Define if you have the getnameinfo function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to the type qualifier of arg 1 for getnameinfo. */ -#define GETNAMEINFO_QUAL_ARG1 const - -/* Define to the type of arg 1 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * - -/* Define to the type of arg 2 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG2 socklen_t - -/* Define to the type of args 4 and 6 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG46 DWORD - -/* Define to the type of arg 7 for getnameinfo. */ -#define GETNAMEINFO_TYPE_ARG7 int - /* Define if you have the recv function. */ #define HAVE_RECV 1 diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c index 296fb62503..d9317f3783 100644 --- a/libs/libcurl/src/connect.c +++ b/libs/libcurl/src/connect.c @@ -660,7 +660,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen, #endif #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) case AF_UNIX: - if(salen > (curl_socklen_t)sizeof(sa_family_t)) { + if(salen > (curl_socklen_t)sizeof(CURL_SA_FAMILY_T)) { su = (struct sockaddr_un*)sa; msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); } @@ -1367,14 +1367,31 @@ CURLcode Curl_connecthost(struct Curl_easy *data, conn->timeoutms_per_addr[1] = conn->tempaddr[1]->ai_next == NULL ? timeout_ms : timeout_ms / 2; - conn->tempfamily[0] = conn->tempaddr[0]? - conn->tempaddr[0]->ai_family:0; + if(conn->ip_version == CURL_IPRESOLVE_WHATEVER) { + /* any IP version is allowed */ + conn->tempfamily[0] = conn->tempaddr[0]? + conn->tempaddr[0]->ai_family:0; #ifdef ENABLE_IPV6 - conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ? - AF_INET : AF_INET6; + conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ? + AF_INET : AF_INET6; #else - conn->tempfamily[1] = AF_UNSPEC; + conn->tempfamily[1] = AF_UNSPEC; #endif + } + else { + /* only one IP version is allowed */ + conn->tempfamily[0] = (conn->ip_version == CURL_IPRESOLVE_V4) ? + AF_INET : +#ifdef ENABLE_IPV6 + AF_INET6; +#else + AF_UNSPEC; +#endif + conn->tempfamily[1] = AF_UNSPEC; + + ainext(conn, 0, FALSE); /* find first address of the right type */ + } + ainext(conn, 1, FALSE); /* assigns conn->tempaddr[1] accordingly */ DEBUGF(infof(data, "family0 == %s, family1 == %s\n", diff --git a/libs/libcurl/src/content_encoding.c b/libs/libcurl/src/content_encoding.c index f179b81796..a84ff543b9 100644 --- a/libs/libcurl/src/content_encoding.c +++ b/libs/libcurl/src/content_encoding.c @@ -178,7 +178,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, /* Dynamically allocate a buffer for decompression because it's uncommonly large to hold on the stack */ decomp = malloc(DSIZ); - if(decomp == NULL) + if(!decomp) return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); /* because the buffer size is fixed, iteratively decompress and transfer to @@ -487,7 +487,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data, */ z->avail_in = (uInt) nbytes; z->next_in = malloc(z->avail_in); - if(z->next_in == NULL) { + if(!z->next_in) { return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); } memcpy(z->next_in, buf, z->avail_in); @@ -509,7 +509,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data, ssize_t hlen; z->avail_in += (uInt) nbytes; z->next_in = Curl_saferealloc(z->next_in, z->avail_in); - if(z->next_in == NULL) { + if(!z->next_in) { return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); } /* Append the new block of data to the previous one */ @@ -985,7 +985,8 @@ new_unencoding_writer(struct Curl_easy *data, return writer; } -/* Write data using an unencoding writer stack. */ +/* Write data using an unencoding writer stack. "nbytes" is not + allowed to be 0. */ CURLcode Curl_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) diff --git a/libs/libcurl/src/cookie.c b/libs/libcurl/src/cookie.c index b85e5e921c..941623f9d2 100644 --- a/libs/libcurl/src/cookie.c +++ b/libs/libcurl/src/cookie.c @@ -105,6 +105,8 @@ Example set of cookies: #include "curl_memory.h" #include "memdebug.h" +static void strstore(char **str, const char *newstr); + static void freecookie(struct Cookie *co) { free(co->expirestr); @@ -129,12 +131,13 @@ static bool tailmatch(const char *cooke_domain, const char *hostname) if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len)) return FALSE; - /* A lead char of cookie_domain is not '.'. - RFC6265 4.1.2.3. The Domain Attribute says: - For example, if the value of the Domain attribute is - "example.com", the user agent will include the cookie in the Cookie - header when making HTTP requests to example.com, www.example.com, and - www.corp.example.com. + /* + * A lead char of cookie_domain is not '.'. + * RFC6265 4.1.2.3. The Domain Attribute says: + * For example, if the value of the Domain attribute is + * "example.com", the user agent will include the cookie in the Cookie + * header when making HTTP requests to example.com, www.example.com, and + * www.corp.example.com. */ if(hostname_len == cookie_domain_len) return TRUE; @@ -144,7 +147,10 @@ static bool tailmatch(const char *cooke_domain, const char *hostname) } /* - * Return true if the given string is an IP(v4|v6) address. + * isip + * + * Returns true if the given string is an IPv4 or IPv6 address (if IPv6 has + * been enabled while building libcurl, and false otherwise. */ static bool isip(const char *domain) { @@ -193,19 +199,19 @@ static bool pathmatch(const char *cookie_path, const char *request_uri) /* #-fragments are already cut off! */ if(0 == strlen(uri_path) || uri_path[0] != '/') { - free(uri_path); - uri_path = strdup("/"); + strstore(&uri_path, "/"); if(!uri_path) return FALSE; } - /* here, RFC6265 5.1.4 says - 4. Output the characters of the uri-path from the first character up - to, but not including, the right-most %x2F ("/"). - but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site - without redirect. - Ignore this algorithm because /hoge is uri path for this case - (uri path is not /). + /* + * here, RFC6265 5.1.4 says + * 4. Output the characters of the uri-path from the first character up + * to, but not including, the right-most %x2F ("/"). + * but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site + * without redirect. + * Ignore this algorithm because /hoge is uri path for this case + * (uri path is not /). */ uri_path_len = strlen(uri_path); @@ -328,8 +334,7 @@ static char *sanitize_cookie_path(const char *cookie_path) /* RFC6265 5.2.4 The Path Attribute */ if(new_path[0] != '/') { /* Let cookie-path be the default-path. */ - free(new_path); - new_path = strdup("/"); + strstore(&new_path, "/"); return new_path; } @@ -357,7 +362,8 @@ void Curl_cookie_loadfiles(struct Curl_easy *data) data->cookies, data->set.cookiesession); if(!newcookies) - /* Failure may be due to OOM or a bad cookie; both are ignored + /* + * Failure may be due to OOM or a bad cookie; both are ignored * but only the first should be */ infof(data, "ignoring failed cookie_init for %s\n", list->data); @@ -372,10 +378,13 @@ void Curl_cookie_loadfiles(struct Curl_easy *data) } /* - * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL - * that will be freed before the allocated string is stored there. + * strstore * - * It is meant to easily replace strdup() + * A thin wrapper around strdup which ensures that any memory allocated at + * *str will be freed before the string allocated by strdup is stored there. + * The intended usecase is repeated assignments to the same variable during + * parsing in a last-wins scenario. The caller is responsible for checking + * for OOM errors. */ static void strstore(char **str, const char *newstr) { @@ -384,7 +393,11 @@ static void strstore(char **str, const char *newstr) } /* - * remove_expired() removes expired cookies. + * remove_expired + * + * Remove expired cookies from the hash by inspecting the expires timestamp on + * each cookie in the hash, freeing and deleting any where the timestamp is in + * the past. */ static void remove_expired(struct CookieInfo *cookies) { @@ -421,25 +434,23 @@ static bool bad_domain(const char *domain) return !strchr(domain, '.') && !strcasecompare(domain, "localhost"); } -/**************************************************************************** - * - * Curl_cookie_add() - * - * Add a single cookie line to the cookie keeping object. +/* + * Curl_cookie_add * - * Be aware that sometimes we get an IP-only host name, and that might also be - * a numerical IPv6 address. + * Add a single cookie line to the cookie keeping object. Be aware that + * sometimes we get an IP-only host name, and that might also be a numerical + * IPv6 address. * * Returns NULL on out of memory or invalid cookie. This is suboptimal, * as they should be treated separately. - ***************************************************************************/ - + */ struct Cookie * Curl_cookie_add(struct Curl_easy *data, - /* The 'data' pointer here may be NULL at times, and thus - must only be used very carefully for things that can deal - with data being NULL. Such as infof() and similar */ - + /* + * The 'data' pointer here may be NULL at times, and thus + * must only be used very carefully for things that can deal + * with data being NULL. Such as infof() and similar + */ struct CookieInfo *c, bool httpheader, /* TRUE if HTTP header-style line */ bool noexpire, /* if TRUE, skip remove_expired() */ @@ -493,9 +504,11 @@ Curl_cookie_add(struct Curl_easy *data, if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%" MAX_NAME_TXT "[^;\r\n]", name, what)) { - /* Use strstore() below to properly deal with received cookie - headers that have the same string property set more than once, - and then we use the last one. */ + /* + * Use strstore() below to properly deal with received cookie + * headers that have the same string property set more than once, + * and then we use the last one. + */ const char *whatptr; bool done = FALSE; bool sep; @@ -503,11 +516,13 @@ Curl_cookie_add(struct Curl_easy *data, size_t nlen = strlen(name); const char *endofn = &ptr[ nlen ]; + /* + * Check for too long individual name or contents, or too long + * combination of name + contents. Chrome and Firefox support 4095 or + * 4096 bytes combo + */ if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) || ((nlen + len) > MAX_NAME)) { - /* too long individual name or contents, or too long combination of - name + contents. Chrome and Firefox support 4095 or 4096 bytes - combo. */ freecookie(co); infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n", nlen, len); @@ -569,8 +584,10 @@ Curl_cookie_add(struct Curl_easy *data, } } else if(!len) { - /* this was a "<name>=" with no content, and we must allow - 'secure' and 'httponly' specified this weirdly */ + /* + * this was a "<name>=" with no content, and we must allow + * 'secure' and 'httponly' specified this weirdly + */ done = TRUE; /* * secure cookies are only allowed to be set when the connection is @@ -610,8 +627,10 @@ Curl_cookie_add(struct Curl_easy *data, else if(strcasecompare("domain", name)) { bool is_ip; - /* Now, we make sure that our host is within the given domain, - or the given domain is not valid and thus cannot be set. */ + /* + * Now, we make sure that our host is within the given domain, or + * the given domain is not valid and thus cannot be set. + */ if('.' == whatptr[0]) whatptr++; /* ignore preceding dot */ @@ -641,9 +660,10 @@ Curl_cookie_add(struct Curl_easy *data, given */ } else { - /* we did not get a tailmatch and then the attempted set domain - is not a domain to which the current host belongs. Mark as - bad. */ + /* + * We did not get a tailmatch and then the attempted set domain is + * not a domain to which the current host belongs. Mark as bad. + */ badcookie = TRUE; infof(data, "skipped cookie with bad tailmatch domain: %s\n", whatptr); @@ -657,15 +677,15 @@ Curl_cookie_add(struct Curl_easy *data, } } else if(strcasecompare("max-age", name)) { - /* Defined in RFC2109: - - Optional. The Max-Age attribute defines the lifetime of the - cookie, in seconds. The delta-seconds value is a decimal non- - negative integer. After delta-seconds seconds elapse, the - client should discard the cookie. A value of zero means the - cookie should be discarded immediately. - - */ + /* + * Defined in RFC2109: + * + * Optional. The Max-Age attribute defines the lifetime of the + * cookie, in seconds. The delta-seconds value is a decimal non- + * negative integer. After delta-seconds seconds elapse, the + * client should discard the cookie. A value of zero means the + * cookie should be discarded immediately. + */ strstore(&co->maxage, whatptr); if(!co->maxage) { badcookie = TRUE; @@ -679,9 +699,10 @@ Curl_cookie_add(struct Curl_easy *data, break; } } + /* - else this is the second (or more) name we don't know - about! */ + * Else, this is the second (or more) name we don't know about! + */ } else { /* this is an "illegal" <what>=<this> pair */ @@ -699,8 +720,10 @@ Curl_cookie_add(struct Curl_easy *data, semiptr = strchr(ptr, ';'); /* now, find the next semicolon */ if(!semiptr && *ptr) - /* There are no more semicolons, but there's a final name=value pair - coming up */ + /* + * There are no more semicolons, but there's a final name=value pair + * coming up + */ semiptr = strchr(ptr, '\0'); } while(semiptr); @@ -724,13 +747,16 @@ Curl_cookie_add(struct Curl_easy *data, } } else if(co->expirestr) { - /* Note that if the date couldn't get parsed for whatever reason, - the cookie will be treated as a session cookie */ + /* + * Note that if the date couldn't get parsed for whatever reason, the + * cookie will be treated as a session cookie + */ co->expires = Curl_getdate_capped(co->expirestr); - /* Session cookies have expires set to 0 so if we get that back - from the date parser let's add a second to make it a - non-session cookie */ + /* + * Session cookies have expires set to 0 so if we get that back from the + * date parser let's add a second to make it a non-session cookie + */ if(co->expires == 0) co->expires = 1; else if(co->expires < 0) @@ -747,13 +773,17 @@ Curl_cookie_add(struct Curl_easy *data, } if(!badcookie && !co->path && path) { - /* No path was given in the header line, set the default. - Note that the passed-in path to this function MAY have a '?' and - following part that MUST not be stored as part of the path. */ + /* + * No path was given in the header line, set the default. Note that the + * passed-in path to this function MAY have a '?' and following part that + * MUST NOT be stored as part of the path. + */ char *queryp = strchr(path, '?'); - /* queryp is where the interesting part of the path ends, so now we - want to the find the last */ + /* + * queryp is where the interesting part of the path ends, so now we + * want to the find the last + */ char *endslash; if(!queryp) endslash = strrchr(path, '/'); @@ -774,29 +804,34 @@ Curl_cookie_add(struct Curl_easy *data, } } + /* + * If we didn't get a cookie name, or a bad one, the this is an illegal + * line so bail out. + */ if(badcookie || !co->name) { - /* we didn't get a cookie name or a bad one, - this is an illegal line, bail out */ freecookie(co); return NULL; } } else { - /* This line is NOT a HTTP header style line, we do offer support for - reading the odd netscape cookies-file format here */ + /* + * This line is NOT a HTTP header style line, we do offer support for + * reading the odd netscape cookies-file format here + */ char *ptr; char *firstptr; char *tok_buf = NULL; int fields; - /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies - marked with httpOnly after the domain name are not accessible - from javascripts, but since curl does not operate at javascript - level, we include them anyway. In Firefox's cookie files, these - lines are preceded with #HttpOnly_ and then everything is - as usual, so we skip 10 characters of the line.. - */ + /* + * IE introduced HTTP-only cookies to prevent XSS attacks. Cookies marked + * with httpOnly after the domain name are not accessible from javascripts, + * but since curl does not operate at javascript level, we include them + * anyway. In Firefox's cookie files, these lines are preceded with + * #HttpOnly_ and then everything is as usual, so we skip 10 characters of + * the line.. + */ if(strncmp(lineptr, "#HttpOnly_", 10) == 0) { lineptr += 10; co->httponly = TRUE; @@ -817,8 +852,10 @@ Curl_cookie_add(struct Curl_easy *data, firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */ - /* Now loop through the fields and init the struct we already have - allocated */ + /* + * Now loop through the fields and init the struct we already have + * allocated + */ for(ptr = firstptr, fields = 0; ptr && !badcookie; ptr = strtok_r(NULL, "\t", &tok_buf), fields++) { switch(fields) { @@ -830,10 +867,11 @@ Curl_cookie_add(struct Curl_easy *data, badcookie = TRUE; break; case 1: - /* flag: A TRUE/FALSE value indicating if all machines within a given - domain can access the variable. Set TRUE when the cookie says - .domain.com and to false when the domain is complete www.domain.com - */ + /* + * flag: A TRUE/FALSE value indicating if all machines within a given + * domain can access the variable. Set TRUE when the cookie says + * .domain.com and to false when the domain is complete www.domain.com + */ co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE; break; case 2: @@ -942,9 +980,11 @@ Curl_cookie_add(struct Curl_easy *data, co->livecookie = c->running; co->creationtime = ++c->lastct; - /* now, we have parsed the incoming line, we must now check if this - supersedes an already existing cookie, which it may if the previous have - the same domain and path as this */ + /* + * Now we have parsed the incoming line, we must now check if this supersedes + * an already existing cookie, which it may if the previous have the same + * domain and path as this. + */ /* at first, remove expired cookies */ if(!noexpire) @@ -1032,12 +1072,12 @@ Curl_cookie_add(struct Curl_easy *data, } if(replace_old && !co->livecookie && clist->livecookie) { - /* Both cookies matched fine, except that the already present - cookie is "live", which means it was set from a header, while - the new one isn't "live" and thus only read from a file. We let - live cookies stay alive */ - - /* Free the newcomer and get out of here! */ + /* + * Both cookies matched fine, except that the already present cookie is + * "live", which means it was set from a header, while the new one was + * read from a file and thus isn't "live". "live" cookies are preferred + * so the new cookie is freed. + */ freecookie(co); return NULL; } @@ -1063,8 +1103,10 @@ Curl_cookie_add(struct Curl_easy *data, free(co); /* free the newly allocated memory */ co = clist; /* point to the previous struct instead */ - /* We have replaced a cookie, now skip the rest of the list but - make sure the 'lastc' pointer is properly set */ + /* + * We have replaced a cookie, now skip the rest of the list but make + * sure the 'lastc' pointer is properly set + */ do { lastc = clist; clist = clist->next; @@ -1096,19 +1138,19 @@ Curl_cookie_add(struct Curl_easy *data, } -/***************************************************************************** - * +/* * Curl_cookie_init() * * Inits a cookie struct to read data from a local file. This is always - * called before any cookies are set. File may be NULL. + * called before any cookies are set. File may be NULL in which case only the + * struct is initialized. Is file is "-" then STDIN is read. * * If 'newsession' is TRUE, discard all "session cookies" on read from file. * * Note that 'data' might be called as NULL pointer. * * Returns NULL on out of memory. Invalid cookies are ignored. - ****************************************************************************/ + */ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, const char *file, struct CookieInfo *inc, @@ -1170,7 +1212,12 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE); } free(line); /* free the line buffer */ - remove_expired(c); /* run this once, not on every cookie */ + + /* + * Remove expired cookies from the hash. We must make sure to run this + * after reading the file, and not not on every cookie. + */ + remove_expired(c); if(fromfile) fclose(fp); @@ -1184,16 +1231,24 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, fail: free(line); + /* + * Only clean up if we allocated it here, as the original could still be in + * use by a share handle. + */ if(!inc) - /* Only clean up if we allocated it here, as the original could still be in - * use by a share handle */ Curl_cookie_cleanup(c); if(fromfile && fp) fclose(fp); return NULL; /* out of memory */ } -/* sort this so that the longest path gets before the shorter path */ +/* + * cookie_sort + * + * Helper function to sort cookies such that the longest path gets before the + * shorter path. Path, domain and name lengths are considered in that order, + * with tge creationtime as the tiebreaker. + */ static int cookie_sort(const void *p1, const void *p2) { struct Cookie *c1 = *(struct Cookie **)p1; @@ -1225,7 +1280,11 @@ static int cookie_sort(const void *p1, const void *p2) return (c2->creationtime > c1->creationtime) ? 1 : -1; } -/* sort cookies only according to creation time */ +/* + * cookie_sort_ct + * + * Helper function to sort cookies according to creation time. + */ static int cookie_sort_ct(const void *p1, const void *p2) { struct Cookie *c1 = *(struct Cookie **)p1; @@ -1269,18 +1328,15 @@ static struct Cookie *dup_cookie(struct Cookie *src) return NULL; } -/***************************************************************************** - * - * Curl_cookie_getlist() +/* + * Curl_cookie_getlist * - * For a given host and path, return a linked list of cookies that the - * client should send to the server if used now. The secure boolean informs - * the cookie if a secure connection is achieved or not. + * For a given host and path, return a linked list of cookies that the client + * should send to the server if used now. The secure boolean informs the cookie + * if a secure connection is achieved or not. * * It shall only return cookies that haven't expired. - * - ****************************************************************************/ - + */ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, const char *host, const char *path, bool secure) @@ -1311,15 +1367,21 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, if(!co->domain || (co->tailmatch && !is_ip && tailmatch(co->domain, host)) || ((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) { - /* the right part of the host matches the domain stuff in the - cookie data */ + /* + * the right part of the host matches the domain stuff in the + * cookie data + */ - /* now check the left part of the path with the cookies path - requirement */ + /* + * now check the left part of the path with the cookies path + * requirement + */ if(!co->spath || pathmatch(co->spath, path) ) { - /* and now, we know this is a match and we should create an - entry for the return-linked-list */ + /* + * and now, we know this is a match and we should create an + * entry for the return-linked-list + */ newco = dup_cookie(co); if(newco) { @@ -1340,9 +1402,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, } if(matches) { - /* Now we need to make sure that if there is a name appearing more than - once, the longest specified path version comes first. To make this - the swiftest way, we just sort them all based on path length. */ + /* + * Now we need to make sure that if there is a name appearing more than + * once, the longest specified path version comes first. To make this + * the swiftest way, we just sort them all based on path length. + */ struct Cookie **array; size_t i; @@ -1377,13 +1441,11 @@ fail: return NULL; } -/***************************************************************************** - * - * Curl_cookie_clearall() +/* + * Curl_cookie_clearall * * Clear all existing cookies and reset the counter. - * - ****************************************************************************/ + */ void Curl_cookie_clearall(struct CookieInfo *cookies) { if(cookies) { @@ -1396,14 +1458,11 @@ void Curl_cookie_clearall(struct CookieInfo *cookies) } } -/***************************************************************************** - * - * Curl_cookie_freelist() +/* + * Curl_cookie_freelist * * Free a list of cookies previously returned by Curl_cookie_getlist(); - * - ****************************************************************************/ - + */ void Curl_cookie_freelist(struct Cookie *co) { struct Cookie *next; @@ -1414,14 +1473,11 @@ void Curl_cookie_freelist(struct Cookie *co) } } - -/***************************************************************************** - * - * Curl_cookie_clearsess() +/* + * Curl_cookie_clearsess * * Free all session cookies in the cookies list. - * - ****************************************************************************/ + */ void Curl_cookie_clearsess(struct CookieInfo *cookies) { struct Cookie *first, *curr, *next, *prev = NULL; @@ -1458,14 +1514,11 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies) } } - -/***************************************************************************** - * +/* * Curl_cookie_cleanup() * * Free a "cookie object" previous created with Curl_cookie_init(). - * - ****************************************************************************/ + */ void Curl_cookie_cleanup(struct CookieInfo *c) { if(c) { @@ -1477,12 +1530,13 @@ void Curl_cookie_cleanup(struct CookieInfo *c) } } -/* get_netscape_format() +/* + * get_netscape_format() * * Formats a string for Netscape output file, w/o a newline at the end. - * - * Function returns a char * to a formatted line. Has to be free()d -*/ + * Function returns a char * to a formatted line. The caller is responsible + * for freeing the returned pointer. + */ static char *get_netscape_format(const struct Cookie *co) { return aprintf( @@ -1495,8 +1549,10 @@ static char *get_netscape_format(const struct Cookie *co) "%s\t" /* name */ "%s", /* value */ co->httponly?"#HttpOnly_":"", - /* Make sure all domains are prefixed with a dot if they allow - tailmatching. This is Mozilla-style. */ + /* + * Make sure all domains are prefixed with a dot if they allow + * tailmatching. This is Mozilla-style. + */ (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"", co->domain?co->domain:"unknown", co->tailmatch?"TRUE":"FALSE", @@ -1515,18 +1571,18 @@ static char *get_netscape_format(const struct Cookie *co) * * The function returns non-zero on write failure. */ -static int cookie_output(struct Curl_easy *data, - struct CookieInfo *c, const char *filename) +static CURLcode cookie_output(struct Curl_easy *data, + struct CookieInfo *c, const char *filename) { struct Cookie *co; FILE *out = NULL; bool use_stdout = FALSE; char *tempstore = NULL; - bool error = false; + CURLcode error = CURLE_OK; if(!c) /* no cookie engine alive */ - return 0; + return CURLE_OK; /* at first, remove expired cookies */ remove_expired(c); @@ -1544,11 +1600,13 @@ static int cookie_output(struct Curl_easy *data, tempstore = aprintf("%s.%s.tmp", filename, randsuffix); if(!tempstore) - return 1; + return CURLE_OUT_OF_MEMORY; out = fopen(tempstore, FOPEN_WRITETEXT); - if(!out) + if(!out) { + error = CURLE_WRITE_ERROR; goto error; + } } fputs("# Netscape HTTP Cookie File\n" @@ -1563,6 +1621,7 @@ static int cookie_output(struct Curl_easy *data, array = calloc(1, sizeof(struct Cookie *) * c->numcookies); if(!array) { + error = CURLE_OUT_OF_MEMORY; goto error; } @@ -1579,9 +1638,9 @@ static int cookie_output(struct Curl_easy *data, for(i = 0; i < nvalid; i++) { char *format_ptr = get_netscape_format(array[i]); - if(format_ptr == NULL) { - fprintf(out, "#\n# Fatal libcurl error\n"); + if(!format_ptr) { free(array); + error = CURLE_OUT_OF_MEMORY; goto error; } fprintf(out, "%s\n", format_ptr); @@ -1596,18 +1655,24 @@ static int cookie_output(struct Curl_easy *data, out = NULL; if(Curl_rename(tempstore, filename)) { unlink(tempstore); + error = CURLE_WRITE_ERROR; goto error; } } - goto cleanup; + /* + * If we reach here we have successfully written a cookie file so theree is + * no need to inspect the error, any error case should have jumped into the + * error block below. + */ + free(tempstore); + return CURLE_OK; + error: - error = true; -cleanup: if(out && !use_stdout) fclose(out); free(tempstore); - return error ? 1 : 0; + return error; } static struct curl_slist *cookie_list(struct Curl_easy *data) @@ -1618,8 +1683,7 @@ static struct curl_slist *cookie_list(struct Curl_easy *data) char *line; unsigned int i; - if((data->cookies == NULL) || - (data->cookies->numcookies == 0)) + if(!data->cookies || (data->cookies->numcookies == 0)) return NULL; for(i = 0; i < COOKIE_HASH_SIZE; i++) { @@ -1655,6 +1719,8 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy *data) void Curl_flush_cookies(struct Curl_easy *data, bool cleanup) { + CURLcode res; + if(data->set.str[STRING_COOKIEJAR]) { if(data->state.cookielist) { /* If there is a list of cookie files to read, do it first so that @@ -1666,9 +1732,10 @@ void Curl_flush_cookies(struct Curl_easy *data, bool cleanup) Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); /* if we have a destination file for all the cookies to get dumped to */ - if(cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR])) - infof(data, "WARNING: failed to save cookies in %s\n", - data->set.str[STRING_COOKIEJAR]); + res = cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]); + if(res) + infof(data, "WARNING: failed to save cookies in %s: %s\n", + data->set.str[STRING_COOKIEJAR], curl_easy_strerror(res)); } else { if(cleanup && data->state.cookielist) { diff --git a/libs/libcurl/src/curl_addrinfo.c b/libs/libcurl/src/curl_addrinfo.c index 06537b275f..1d5067bc00 100644 --- a/libs/libcurl/src/curl_addrinfo.c +++ b/libs/libcurl/src/curl_addrinfo.c @@ -50,6 +50,12 @@ # define in_addr_t unsigned long #endif +#if defined(USE_UNIX_SOCKETS) && defined(WINAPI_FAMILY) && \ + (WINAPI_FAMILY == WINAPI_FAMILY_APP) + /* Required for sockaddr_un type */ +# include <afunix.h> +#endif + #include <stddef.h> #include "curl_addrinfo.h" @@ -141,7 +147,7 @@ Curl_getaddrinfo_ex(const char *nodename, continue; /* ignore elements without required address info */ - if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0)) + if(!ai->ai_addr || !(ai->ai_addrlen > 0)) continue; /* ignore elements with bogus address size */ diff --git a/libs/libcurl/src/curl_config.h.cmake b/libs/libcurl/src/curl_config.h.cmake index fbe17bc5b0..96a19afc51 100644 --- a/libs/libcurl/src/curl_config.h.cmake +++ b/libs/libcurl/src/curl_config.h.cmake @@ -112,21 +112,6 @@ /* Define if you want to enable IPv6 support */ #cmakedefine ENABLE_IPV6 1 -/* Define to the type qualifier of arg 1 for getnameinfo. */ -#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1} - -/* Define to the type of arg 1 for getnameinfo. */ -#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1} - -/* Define to the type of arg 2 for getnameinfo. */ -#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2} - -/* Define to the type of args 4 and 6 for getnameinfo. */ -#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46} - -/* Define to the type of arg 7 for getnameinfo. */ -#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7} - /* Specifies the number of arguments to getservbyport_r */ #cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS} @@ -208,6 +193,9 @@ /* Define to 1 if you have the `geteuid' function. */ #cmakedefine HAVE_GETEUID 1 +/* Define to 1 if you have the `getppid' function. */ +#cmakedefine HAVE_GETPPID 1 + /* Define to 1 if you have the gethostbyaddr function. */ #cmakedefine HAVE_GETHOSTBYADDR 1 @@ -244,9 +232,6 @@ /* Define to 1 if you have a working getifaddrs function. */ #cmakedefine HAVE_GETIFADDRS 1 -/* Define to 1 if you have the getnameinfo function. */ -#cmakedefine HAVE_GETNAMEINFO 1 - /* Define to 1 if you have the `getpass_r' function. */ #cmakedefine HAVE_GETPASS_R 1 @@ -328,6 +313,12 @@ /* Define to 1 if you have a IPv6 capable working inet_pton function. */ #cmakedefine HAVE_INET_PTON 1 +/* Define to 1 if symbol `sa_family_t' exists */ +#cmakedefine HAVE_SA_FAMILY_T 1 + +/* Define to 1 if symbol `ADDRESS_FAMILY' exists */ +#cmakedefine HAVE_ADDRESS_FAMILY 1 + /* Define to 1 if you have the <inttypes.h> header file. */ #cmakedefine HAVE_INTTYPES_H 1 @@ -500,9 +491,6 @@ /* Define to 1 if you have the <pem.h> header file. */ #cmakedefine HAVE_PEM_H 1 -/* Define to 1 if you have the `perror' function. */ -#cmakedefine HAVE_PERROR 1 - /* Define to 1 if you have the `pipe' function. */ #cmakedefine HAVE_PIPE 1 @@ -644,12 +632,6 @@ /* Define to 1 if you have the <string.h> header file. */ #cmakedefine HAVE_STRING_H 1 -/* Define to 1 if you have the strlcat function. */ -#cmakedefine HAVE_STRLCAT 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#cmakedefine HAVE_STRLCPY 1 - /* Define to 1 if you have the strncmpi function. */ #cmakedefine HAVE_STRNCMPI 1 @@ -740,6 +722,9 @@ /* Define to 1 if you have the `utime' function. */ #cmakedefine HAVE_UTIME 1 +/* Define to 1 if you have the `utimes' function. */ +#cmakedefine HAVE_UTIMES 1 + /* Define to 1 if you have the <utime.h> header file. */ #cmakedefine HAVE_UTIME_H 1 diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in index ae942fbfb8..d5f8ba9b00 100644 --- a/libs/libcurl/src/curl_config.h.in +++ b/libs/libcurl/src/curl_config.h.in @@ -42,6 +42,9 @@ /* to disable Gopher */ #undef CURL_DISABLE_GOPHER +/* disable alt-svc */ +#undef CURL_DISABLE_HSTS + /* to disable HTTP */ #undef CURL_DISABLE_HTTP @@ -807,9 +810,6 @@ /* Define to 1 if you have the <wolfssh/ssh.h> header file. */ #undef HAVE_WOLFSSH_SSH_H -/* Define to 1 if you have the `wolfSSLv3_client_method' function. */ -#undef HAVE_WOLFSSLV3_CLIENT_METHOD - /* if you have wolfSSL_DES_ecb_encrypt */ #undef HAVE_WOLFSSL_DES_ECB_ENCRYPT @@ -987,9 +987,6 @@ /* GSASL support enabled */ #undef USE_GSASL -/* to enable HSTS */ -#undef USE_HSTS - /* if hyper is in use */ #undef USE_HYPER diff --git a/libs/libcurl/src/curl_get_line.c b/libs/libcurl/src/curl_get_line.c index 438ede7046..8f3b0bd8c1 100644 --- a/libs/libcurl/src/curl_get_line.c +++ b/libs/libcurl/src/curl_get_line.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,7 +23,7 @@ #include "curl_setup.h" #if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \ - defined(USE_HSTS) + !defined(CURL_DISABLE_HSTS) #include "curl_get_line.h" #include "curl_memory.h" diff --git a/libs/libcurl/src/curl_gssapi.c b/libs/libcurl/src/curl_gssapi.c index 6445fbad09..acaaa1c683 100644 --- a/libs/libcurl/src/curl_gssapi.c +++ b/libs/libcurl/src/curl_gssapi.c @@ -102,7 +102,7 @@ static size_t display_gss_error(OM_uint32 status, int type, (char *)status_string.value); } gss_release_buffer(&min_stat, &status_string); - } while(!GSS_ERROR(maj_stat) && msg_ctx != 0); + } while(!GSS_ERROR(maj_stat) && msg_ctx); return len; } diff --git a/libs/libcurl/src/curl_krb5.h b/libs/libcurl/src/curl_krb5.h index 3f40f9a6ca..ca06840742 100644 --- a/libs/libcurl/src/curl_krb5.h +++ b/libs/libcurl/src/curl_krb5.h @@ -29,7 +29,6 @@ struct Curl_sec_client_mech { int (*auth)(void *, struct Curl_easy *data, struct connectdata *); void (*end)(void *); int (*check_prot)(void *, int); - int (*overhead)(void *, int, int); int (*encode)(void *, const void *, int, int, void **); int (*decode)(void *, void *, int, int, struct connectdata *); }; diff --git a/libs/libcurl/src/curl_path.c b/libs/libcurl/src/curl_path.c index 6100d77bd9..65106188c7 100644 --- a/libs/libcurl/src/curl_path.c +++ b/libs/libcurl/src/curl_path.c @@ -48,7 +48,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, /* Check for /~/, indicating relative to the user's home directory */ if(data->conn->handler->protocol & CURLPROTO_SCP) { real_path = malloc(working_path_len + 1); - if(real_path == NULL) { + if(!real_path) { free(working_path); return CURLE_OUT_OF_MEMORY; } @@ -62,7 +62,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, if((working_path_len > 1) && (working_path[1] == '~')) { size_t homelen = strlen(homedir); real_path = malloc(homelen + working_path_len + 1); - if(real_path == NULL) { + if(!real_path) { free(working_path); return CURLE_OUT_OF_MEMORY; } @@ -78,7 +78,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, } else { real_path = malloc(working_path_len + 1); - if(real_path == NULL) { + if(!real_path) { free(working_path); return CURLE_OUT_OF_MEMORY; } @@ -130,7 +130,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) /* Allocate enough space for home directory and filename + separator */ fullPathLength = strlen(cp) + strlen(homedir) + 2; *path = malloc(fullPathLength); - if(*path == NULL) + if(!*path) return CURLE_OUT_OF_MEMORY; /* Check for quoted filenames */ @@ -169,7 +169,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) else { /* Read to end of filename - either to whitespace or terminator */ end = strpbrk(cp, WHITESPACE); - if(end == NULL) + if(!end) end = strchr(cp, '\0'); /* return pointer to second parameter if it exists */ *cpp = end + strspn(end, WHITESPACE); diff --git a/libs/libcurl/src/curl_rtmp.c b/libs/libcurl/src/curl_rtmp.c index 1360f335fc..2fa026796e 100644 --- a/libs/libcurl/src/curl_rtmp.c +++ b/libs/libcurl/src/curl_rtmp.c @@ -79,6 +79,7 @@ const struct Curl_handler Curl_handler_rtmp = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMP, /* defport */ CURLPROTO_RTMP, /* protocol */ CURLPROTO_RTMP, /* family */ @@ -101,6 +102,7 @@ const struct Curl_handler Curl_handler_rtmpt = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMPT, /* defport */ CURLPROTO_RTMPT, /* protocol */ CURLPROTO_RTMPT, /* family */ @@ -123,6 +125,7 @@ const struct Curl_handler Curl_handler_rtmpe = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMP, /* defport */ CURLPROTO_RTMPE, /* protocol */ CURLPROTO_RTMPE, /* family */ @@ -145,6 +148,7 @@ const struct Curl_handler Curl_handler_rtmpte = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMPT, /* defport */ CURLPROTO_RTMPTE, /* protocol */ CURLPROTO_RTMPTE, /* family */ @@ -167,6 +171,7 @@ const struct Curl_handler Curl_handler_rtmps = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMPS, /* defport */ CURLPROTO_RTMPS, /* protocol */ CURLPROTO_RTMP, /* family */ @@ -189,6 +194,7 @@ const struct Curl_handler Curl_handler_rtmpts = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMPS, /* defport */ CURLPROTO_RTMPTS, /* protocol */ CURLPROTO_RTMPT, /* family */ diff --git a/libs/libcurl/src/curl_sasl.c b/libs/libcurl/src/curl_sasl.c index 2cba185470..a4d1059cb9 100644 --- a/libs/libcurl/src/curl_sasl.c +++ b/libs/libcurl/src/curl_sasl.c @@ -58,7 +58,7 @@ static const struct { const char *name; /* Name */ size_t len; /* Name length */ - unsigned int bit; /* Flag bit */ + unsigned short bit; /* Flag bit */ } mechtable[] = { { "LOGIN", 5, SASL_MECH_LOGIN }, { "PLAIN", 5, SASL_MECH_PLAIN }, @@ -128,7 +128,8 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused) * * Returns the SASL mechanism token or 0 if no match. */ -unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len) +unsigned short Curl_sasl_decode_mech(const char *ptr, size_t maxlen, + size_t *len) { unsigned int i; char c; @@ -173,7 +174,7 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, if(!strncmp(value, "*", len)) sasl->prefmech = SASL_AUTH_DEFAULT; else { - unsigned int mechbit = Curl_sasl_decode_mech(value, len, &mechlen); + unsigned short mechbit = Curl_sasl_decode_mech(value, len, &mechlen); if(mechbit && mechlen == len) sasl->prefmech |= mechbit; else @@ -242,6 +243,49 @@ static void state(struct SASL *sasl, struct Curl_easy *data, sasl->state = newstate; } +/* Get the SASL server message and convert it to binary. */ +static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data, + struct bufref *out) +{ + unsigned char *msg; + size_t msglen; + char *serverdata = NULL; + CURLcode result = CURLE_OK; + + sasl->params->getmessage(data->state.buffer, &serverdata); + if(!serverdata) + result = CURLE_BAD_CONTENT_ENCODING; + else if(!*serverdata || *serverdata == '=') + Curl_bufref_set(out, NULL, 0, NULL); + else { + result = Curl_base64_decode(serverdata, &msg, &msglen); + if(!result) + Curl_bufref_set(out, msg, msglen, curl_free); + } + return result; +} + +/* Encode the outgoing SASL message. */ +static CURLcode build_message(struct Curl_easy *data, struct bufref *msg) +{ + CURLcode result = CURLE_OK; + char *base64; + size_t base64len; + + if(!Curl_bufref_ptr(msg)) /* Empty mesage. */ + Curl_bufref_set(msg, "", 0, NULL); + else if(!Curl_bufref_len(msg)) /* Explicit empty response. */ + Curl_bufref_set(msg, "=", 1, NULL); + else { + result = Curl_base64_encode(data, (const char *) Curl_bufref_ptr(msg), + Curl_bufref_len(msg), &base64, &base64len); + if(!result) + Curl_bufref_set(msg, base64, base64len, curl_free); + } + + return result; +} + /* * Curl_sasl_can_authenticate() * @@ -272,25 +316,21 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, CURLcode result = CURLE_OK; unsigned int enabledmechs; const char *mech = NULL; - char *resp = NULL; - size_t len = 0; + struct bufref resp; saslstate state1 = SASL_STOP; saslstate state2 = SASL_FINAL; -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#else - const char * const hostname = conn->host.name; - const long int port = conn->remote_port; -#endif + const char * const hostname = SSL_HOST_NAME(); + const long int port = SSL_HOST_PORT(); #if defined(USE_KERBEROS5) || defined(USE_NTLM) const char *service = data->set.str[STRING_SERVICE_NAME] ? data->set.str[STRING_SERVICE_NAME] : sasl->params->service; #endif const char *oauth_bearer = data->set.str[STRING_BEARER]; + struct bufref nullmsg; + Curl_bufref_init(&nullmsg); + Curl_bufref_init(&resp); sasl->force_ir = force_ir; /* Latch for future use */ sasl->authused = 0; /* No mechanism used yet */ enabledmechs = sasl->authmechs & sasl->prefmech; @@ -304,8 +344,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, sasl->authused = SASL_MECH_EXTERNAL; if(force_ir || data->set.sasl_ir) - result = Curl_auth_create_external_message(data, conn->user, &resp, - &len); + result = Curl_auth_create_external_message(conn->user, &resp); } else if(conn->bits.user_passwd) { #if defined(USE_KERBEROS5) @@ -321,10 +360,10 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, result = Curl_auth_create_gssapi_user_message(data, conn->user, conn->passwd, service, - data->conn->host.name, + conn->host.name, sasl->mutual_auth, NULL, &conn->krb5, - &resp, &len); + &resp); } else #endif @@ -340,8 +379,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, result = Curl_auth_gsasl_start(data, conn->user, conn->passwd, &conn->gsasl); if(result == CURLE_OK && (force_ir || data->set.sasl_ir)) - result = Curl_auth_gsasl_token(data, NULL, &conn->gsasl, - &resp, &len); + result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp); } else if((enabledmechs & SASL_MECH_SCRAM_SHA_1) && Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_1, @@ -354,8 +392,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, result = Curl_auth_gsasl_start(data, conn->user, conn->passwd, &conn->gsasl); if(result == CURLE_OK && (force_ir || data->set.sasl_ir)) - result = Curl_auth_gsasl_token(data, NULL, &conn->gsasl, - &resp, &len); + result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp); } else #endif @@ -385,8 +422,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, conn->user, conn->passwd, service, hostname, - &conn->ntlm, &resp, - &len); + &conn->ntlm, &resp); } else #endif @@ -397,11 +433,11 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, sasl->authused = SASL_MECH_OAUTHBEARER; if(force_ir || data->set.sasl_ir) - result = Curl_auth_create_oauth_bearer_message(data, conn->user, + result = Curl_auth_create_oauth_bearer_message(conn->user, hostname, port, oauth_bearer, - &resp, &len); + &resp); } else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) { mech = SASL_MECH_STRING_XOAUTH2; @@ -409,9 +445,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, sasl->authused = SASL_MECH_XOAUTH2; if(force_ir || data->set.sasl_ir) - result = Curl_auth_create_xoauth_bearer_message(data, conn->user, + result = Curl_auth_create_xoauth_bearer_message(conn->user, oauth_bearer, - &resp, &len); + &resp); } else if(enabledmechs & SASL_MECH_PLAIN) { mech = SASL_MECH_STRING_PLAIN; @@ -419,9 +455,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, sasl->authused = SASL_MECH_PLAIN; if(force_ir || data->set.sasl_ir) - result = Curl_auth_create_plain_message(data, conn->sasl_authzid, + result = Curl_auth_create_plain_message(conn->sasl_authzid, conn->user, conn->passwd, - &resp, &len); + &resp); } else if(enabledmechs & SASL_MECH_LOGIN) { mech = SASL_MECH_STRING_LOGIN; @@ -430,26 +466,29 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, sasl->authused = SASL_MECH_LOGIN; if(force_ir || data->set.sasl_ir) - result = Curl_auth_create_login_message(data, conn->user, &resp, &len); + result = Curl_auth_create_login_message(conn->user, &resp); } } if(!result && mech) { - if(resp && sasl->params->maxirlen && - strlen(mech) + len > sasl->params->maxirlen) { - free(resp); - resp = NULL; - } + if(Curl_bufref_ptr(&resp)) + result = build_message(data, &resp); + + if(sasl->params->maxirlen && + strlen(mech) + Curl_bufref_len(&resp) > sasl->params->maxirlen) + Curl_bufref_free(&resp); + + if(!result) + result = sasl->params->sendauth(data, conn, mech, + (const char *) Curl_bufref_ptr(&resp)); - result = sasl->params->sendauth(data, conn, mech, resp); if(!result) { *progress = SASL_INPROGRESS; - state(sasl, data, resp ? state2 : state1); + state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1); } } - free(resp); - + Curl_bufref_free(&resp); return result; } @@ -464,29 +503,20 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, { CURLcode result = CURLE_OK; saslstate newstate = SASL_FINAL; - char *resp = NULL; -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#else - const char * const hostname = conn->host.name; - const long int port = conn->remote_port; -#endif -#if !defined(CURL_DISABLE_CRYPTO_AUTH) - char *chlg = NULL; - size_t chlglen = 0; -#endif + struct bufref resp; + const char * const hostname = SSL_HOST_NAME(); + const long int port = SSL_HOST_PORT(); #if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \ defined(USE_NTLM) const char *service = data->set.str[STRING_SERVICE_NAME] ? data->set.str[STRING_SERVICE_NAME] : sasl->params->service; - char *serverdata; #endif - size_t len = 0; const char *oauth_bearer = data->set.str[STRING_BEARER]; + struct bufref serverdata; + Curl_bufref_init(&serverdata); + Curl_bufref_init(&resp); *progress = SASL_INPROGRESS; if(sasl->state == SASL_FINAL) { @@ -509,50 +539,45 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, *progress = SASL_DONE; return result; case SASL_PLAIN: - result = Curl_auth_create_plain_message(data, conn->sasl_authzid, - conn->user, conn->passwd, - &resp, &len); + result = Curl_auth_create_plain_message(conn->sasl_authzid, + conn->user, conn->passwd, &resp); break; case SASL_LOGIN: - result = Curl_auth_create_login_message(data, conn->user, &resp, &len); + result = Curl_auth_create_login_message(conn->user, &resp); newstate = SASL_LOGIN_PASSWD; break; case SASL_LOGIN_PASSWD: - result = Curl_auth_create_login_message(data, conn->passwd, &resp, &len); + result = Curl_auth_create_login_message(conn->passwd, &resp); break; case SASL_EXTERNAL: - result = Curl_auth_create_external_message(data, conn->user, &resp, &len); + result = Curl_auth_create_external_message(conn->user, &resp); break; #ifndef CURL_DISABLE_CRYPTO_AUTH #ifdef USE_GSASL case SASL_GSASL: - sasl->params->getmessage(data->state.buffer, &serverdata); - result = Curl_auth_gsasl_token(data, serverdata, &conn->gsasl, - &resp, &len); - if(len > 0) + result = get_server_message(sasl, data, &serverdata); + if(!result) + result = Curl_auth_gsasl_token(data, &serverdata, &conn->gsasl, &resp); + if(!result && Curl_bufref_len(&resp) > 0) newstate = SASL_GSASL; break; #endif case SASL_CRAMMD5: - sasl->params->getmessage(data->state.buffer, &serverdata); - result = Curl_auth_decode_cram_md5_message(serverdata, &chlg, &chlglen); + result = get_server_message(sasl, data, &serverdata); if(!result) - result = Curl_auth_create_cram_md5_message(data, chlg, conn->user, - conn->passwd, &resp, &len); - free(chlg); + result = Curl_auth_create_cram_md5_message(&serverdata, conn->user, + conn->passwd, &resp); break; case SASL_DIGESTMD5: - sasl->params->getmessage(data->state.buffer, &serverdata); - result = Curl_auth_create_digest_md5_message(data, serverdata, - conn->user, conn->passwd, - service, - &resp, &len); + result = get_server_message(sasl, data, &serverdata); + if(!result) + result = Curl_auth_create_digest_md5_message(data, &serverdata, + conn->user, conn->passwd, + service, &resp); newstate = SASL_DIGESTMD5_RESP; break; case SASL_DIGESTMD5_RESP: - resp = strdup(""); - if(!resp) - result = CURLE_OUT_OF_MEMORY; + /* Keep response NULL to output an empty line. */ break; #endif @@ -562,18 +587,19 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, result = Curl_auth_create_ntlm_type1_message(data, conn->user, conn->passwd, service, hostname, - &conn->ntlm, &resp, &len); + &conn->ntlm, &resp); newstate = SASL_NTLM_TYPE2MSG; break; case SASL_NTLM_TYPE2MSG: /* Decode the type-2 message */ - sasl->params->getmessage(data->state.buffer, &serverdata); - result = Curl_auth_decode_ntlm_type2_message(data, serverdata, - &conn->ntlm); + result = get_server_message(sasl, data, &serverdata); + if(!result) + result = Curl_auth_decode_ntlm_type2_message(data, &serverdata, + &conn->ntlm); if(!result) result = Curl_auth_create_ntlm_type3_message(data, conn->user, conn->passwd, &conn->ntlm, - &resp, &len); + &resp); break; #endif @@ -582,55 +608,59 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, result = Curl_auth_create_gssapi_user_message(data, conn->user, conn->passwd, service, - data->conn->host.name, + conn->host.name, sasl->mutual_auth, NULL, &conn->krb5, - &resp, &len); + &resp); newstate = SASL_GSSAPI_TOKEN; break; case SASL_GSSAPI_TOKEN: - sasl->params->getmessage(data->state.buffer, &serverdata); - if(sasl->mutual_auth) { - /* Decode the user token challenge and create the optional response - message */ - result = Curl_auth_create_gssapi_user_message(data, NULL, NULL, - NULL, NULL, - sasl->mutual_auth, - serverdata, &conn->krb5, - &resp, &len); - newstate = SASL_GSSAPI_NO_DATA; + result = get_server_message(sasl, data, &serverdata); + if(!result) { + if(sasl->mutual_auth) { + /* Decode the user token challenge and create the optional response + message */ + result = Curl_auth_create_gssapi_user_message(data, NULL, NULL, + NULL, NULL, + sasl->mutual_auth, + &serverdata, + &conn->krb5, + &resp); + newstate = SASL_GSSAPI_NO_DATA; + } + else + /* Decode the security challenge and create the response message */ + result = Curl_auth_create_gssapi_security_message(data, &serverdata, + &conn->krb5, + &resp); } - else - /* Decode the security challenge and create the response message */ - result = Curl_auth_create_gssapi_security_message(data, serverdata, - &conn->krb5, - &resp, &len); break; case SASL_GSSAPI_NO_DATA: - sasl->params->getmessage(data->state.buffer, &serverdata); /* Decode the security challenge and create the response message */ - result = Curl_auth_create_gssapi_security_message(data, serverdata, - &conn->krb5, - &resp, &len); + result = get_server_message(sasl, data, &serverdata); + if(!result) + result = Curl_auth_create_gssapi_security_message(data, &serverdata, + &conn->krb5, + &resp); break; #endif case SASL_OAUTH2: /* Create the authorisation message */ if(sasl->authused == SASL_MECH_OAUTHBEARER) { - result = Curl_auth_create_oauth_bearer_message(data, conn->user, + result = Curl_auth_create_oauth_bearer_message(conn->user, hostname, port, oauth_bearer, - &resp, &len); + &resp); /* Failures maybe sent by the server as continuations for OAUTHBEARER */ newstate = SASL_OAUTH2_RESP; } else - result = Curl_auth_create_xoauth_bearer_message(data, conn->user, + result = Curl_auth_create_xoauth_bearer_message(conn->user, oauth_bearer, - &resp, &len); + &resp); break; case SASL_OAUTH2_RESP: @@ -642,11 +672,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, return result; } else if(code == sasl->params->contcode) { - /* Acknowledge the continuation by sending a 0x01 response base64 - encoded */ - resp = strdup("AQ=="); - if(!resp) - result = CURLE_OUT_OF_MEMORY; + /* Acknowledge the continuation by sending a 0x01 response. */ + Curl_bufref_set(&resp, "\x01", 1, NULL); break; } else { @@ -660,15 +687,15 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, sasl->authmechs ^= sasl->authused; /* Start an alternative SASL authentication */ - result = Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress); - newstate = sasl->state; /* Use state from Curl_sasl_start() */ - break; + return Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress); default: failf(data, "Unsupported SASL authentication mechanism"); result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */ break; } + Curl_bufref_free(&serverdata); + switch(result) { case CURLE_BAD_CONTENT_ENCODING: /* Cancel dialog */ @@ -676,8 +703,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, newstate = SASL_CANCEL; break; case CURLE_OK: - if(resp) - result = sasl->params->sendcont(data, conn, resp); + result = build_message(data, &resp); + if(!result) + result = sasl->params->sendcont(data, conn, + (const char *) Curl_bufref_ptr(&resp)); break; default: newstate = SASL_STOP; /* Stop on error */ @@ -685,7 +714,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, break; } - free(resp); + Curl_bufref_free(&resp); state(sasl, data, newstate); diff --git a/libs/libcurl/src/curl_sasl.h b/libs/libcurl/src/curl_sasl.h index 8648c632b6..e17d323eba 100644 --- a/libs/libcurl/src/curl_sasl.h +++ b/libs/libcurl/src/curl_sasl.h @@ -42,7 +42,7 @@ struct connectdata; /* Authentication mechanism values */ #define SASL_AUTH_NONE 0 -#define SASL_AUTH_ANY ~0U +#define SASL_AUTH_ANY 0xffff #define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & ~SASL_MECH_EXTERNAL) /* Authentication mechanism strings */ @@ -108,9 +108,9 @@ struct SASLproto { struct SASL { const struct SASLproto *params; /* Protocol dependent parameters */ saslstate state; /* Current machine state */ - unsigned int authmechs; /* Accepted authentication mechanisms */ - unsigned int prefmech; /* Preferred authentication mechanism */ - unsigned int authused; /* Auth mechanism used for the connection */ + unsigned short authmechs; /* Accepted authentication mechanisms */ + unsigned short prefmech; /* Preferred authentication mechanism */ + unsigned short authused; /* Auth mechanism used for the connection */ bool resetprefs; /* For URL auth option parsing. */ bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ bool force_ir; /* Protocol always supports initial response */ @@ -126,8 +126,8 @@ struct SASL { void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); /* Convert a mechanism name to a token */ -unsigned int Curl_sasl_decode_mech(const char *ptr, - size_t maxlen, size_t *len); +unsigned short Curl_sasl_decode_mech(const char *ptr, + size_t maxlen, size_t *len); /* Parse the URL login options */ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, diff --git a/libs/libcurl/src/curl_setup.h b/libs/libcurl/src/curl_setup.h index cf1c26a14e..be4a58d4b6 100644 --- a/libs/libcurl/src/curl_setup.h +++ b/libs/libcurl/src/curl_setup.h @@ -247,7 +247,11 @@ * performing this task will result in a synthesized IPv6 address. */ #if defined(__APPLE__) && !defined(USE_ARES) +#include <TargetConditionals.h> #define USE_RESOLVE_ON_IPS 1 +# if defined(TARGET_OS_OSX) && TARGET_OS_OSX +# define CURL_OSX_CALL_COPYPROXIES 1 +# endif #endif #ifdef USE_LWIPSOCK @@ -517,7 +521,6 @@ # undef HAVE_GETADDRINFO_THREADSAFE # undef HAVE_FREEADDRINFO # undef HAVE_GETADDRINFO -# undef HAVE_GETNAMEINFO # undef ENABLE_IPV6 # endif #endif @@ -715,13 +718,19 @@ int netware_init(void); #endif /* - * Portable symbolic names for Winsock shutdown() mode flags. + * shutdown() flags for systems that don't define them */ -#ifdef USE_WINSOCK -# define SHUT_RD 0x00 -# define SHUT_WR 0x01 -# define SHUT_RDWR 0x02 +#ifndef SHUT_RD +#define SHUT_RD 0x00 +#endif + +#ifndef SHUT_WR +#define SHUT_WR 0x01 +#endif + +#ifndef SHUT_RDWR +#define SHUT_RDWR 0x02 #endif /* Define S_ISREG if not defined by system headers, f.e. MSVC */ @@ -772,9 +781,16 @@ endings either CRLF or LF so 't' is appropriate. # endif #endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */ -/* for systems that don't detect this in configure, use a sensible default */ +/* for systems that don't detect this in configure */ #ifndef CURL_SA_FAMILY_T -#define CURL_SA_FAMILY_T unsigned short +# if defined(HAVE_SA_FAMILY_T) +# define CURL_SA_FAMILY_T sa_family_t +# elif defined(HAVE_ADDRESS_FAMILY) +# define CURL_SA_FAMILY_T ADDRESS_FAMILY +# else +/* use a sensible default */ +# define CURL_SA_FAMILY_T unsigned short +# endif #endif /* Some convenience macros to get the larger/smaller value out of two given. @@ -795,6 +811,10 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, #define UNITTEST static #endif +#if defined(USE_NGHTTP2) || defined(USE_HYPER) +#define USE_HTTP2 +#endif + #if defined(USE_NGTCP2) || defined(USE_QUICHE) #define ENABLE_QUIC #endif diff --git a/libs/libcurl/src/dict.c b/libs/libcurl/src/dict.c index 4319dadba5..625b057774 100644 --- a/libs/libcurl/src/dict.c +++ b/libs/libcurl/src/dict.c @@ -89,6 +89,7 @@ const struct Curl_handler Curl_handler_dict = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_DICT, /* defport */ CURLPROTO_DICT, /* protocol */ CURLPROTO_DICT, /* family */ @@ -214,14 +215,14 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) } } - if((word == NULL) || (*word == (char)0)) { + if(!word || (*word == (char)0)) { infof(data, "lookup word is missing\n"); word = (char *)"default"; } - if((database == NULL) || (*database == (char)0)) { + if(!database || (*database == (char)0)) { database = (char *)"!"; } - if((strategy == NULL) || (*strategy == (char)0)) { + if(!strategy || (*strategy == (char)0)) { strategy = (char *)"."; } @@ -265,11 +266,11 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) } } - if((word == NULL) || (*word == (char)0)) { + if(!word || (*word == (char)0)) { infof(data, "lookup word is missing\n"); word = (char *)"default"; } - if((database == NULL) || (*database == (char)0)) { + if(!database || (*database == (char)0)) { database = (char *)"!"; } diff --git a/libs/libcurl/src/doh.c b/libs/libcurl/src/doh.c index 52388cba3e..36f8cd58dc 100644 --- a/libs/libcurl/src/doh.c +++ b/libs/libcurl/src/doh.c @@ -313,6 +313,10 @@ static CURLcode dohprobe(struct Curl_easy *data, ERROR_CHECK_SETOPT(CURLOPT_CAINFO, data->set.str[STRING_SSL_CAFILE]); } + if(data->set.blobs[BLOB_CAINFO]) { + ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB, + data->set.blobs[BLOB_CAINFO]); + } if(data->set.str[STRING_SSL_CAPATH]) { ERROR_CHECK_SETOPT(CURLOPT_CAPATH, data->set.str[STRING_SSL_CAPATH]); @@ -351,7 +355,10 @@ static CURLcode dohprobe(struct Curl_easy *data, (data->set.ssl.revoke_best_effort ? CURLSSLOPT_REVOKE_BEST_EFFORT : 0) | (data->set.ssl.native_ca_store ? - CURLSSLOPT_NATIVE_CA : 0); + CURLSSLOPT_NATIVE_CA : 0) | + (data->set.ssl.auto_client_cert ? + CURLSSLOPT_AUTO_CLIENT_CERT : 0); + curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask); } @@ -413,17 +420,15 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, if(!dohp->headers) goto error; - if(conn->ip_version != CURL_IPRESOLVE_V6) { - /* create IPv4 DOH request */ - result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4], - DNS_TYPE_A, hostname, data->set.str[STRING_DOH], - data->multi, dohp->headers); - if(result) - goto error; - dohp->pending++; - } + /* create IPv4 DOH request */ + result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4], + DNS_TYPE_A, hostname, data->set.str[STRING_DOH], + data->multi, dohp->headers); + if(result) + goto error; + dohp->pending++; - if(conn->ip_version != CURL_IPRESOLVE_V4) { + if(Curl_ipv6works(data)) { /* create IPv6 DOH request */ result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6], DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH], diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c index 4ce1bbf63b..530b7c73f2 100644 --- a/libs/libcurl/src/easy.c +++ b/libs/libcurl/src/easy.c @@ -789,7 +789,6 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) /* duplicate all blobs */ for(j = (enum dupblob)0; j < BLOB_LAST; j++) { result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]); - /* Curl_setstropt return CURLE_BAD_FUNCTION_ARGUMENT with blob */ if(result) return result; } @@ -895,7 +894,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) (void)Curl_altsvc_load(outcurl->asi, outcurl->set.str[STRING_ALTSVC]); } #endif -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS if(data->hsts) { outcurl->hsts = Curl_hsts_init(); if(!outcurl->hsts) @@ -1105,7 +1104,7 @@ static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd, struct connectdata **connp) { - if(data == NULL) + if(!data) return CURLE_BAD_FUNCTION_ARGUMENT; /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ @@ -1171,6 +1170,7 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, CURLcode result; ssize_t n1; struct connectdata *c = NULL; + SIGPIPE_VARIABLE(pipe_st); if(Curl_is_in_callback(data)) return CURLE_RECURSIVE_API_CALL; @@ -1185,7 +1185,9 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, Curl_attach_connnection(data, c); *n = 0; + sigpipe_ignore(data, &pipe_st); result = Curl_write(data, sfd, buffer, buflen, &n1); + sigpipe_restore(&pipe_st); if(n1 == -1) return CURLE_SEND_ERROR; diff --git a/libs/libcurl/src/easyoptions.c b/libs/libcurl/src/easyoptions.c index db8337b044..4e65e3525b 100644 --- a/libs/libcurl/src/easyoptions.c +++ b/libs/libcurl/src/easyoptions.c @@ -38,6 +38,7 @@ struct curl_easyoption Curl_easyopts[] = { {"AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0}, {"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0}, {"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0}, + {"CAINFO_BLOB", CURLOPT_CAINFO_BLOB, CURLOT_BLOB, 0}, {"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0}, {"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0}, {"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0}, @@ -205,6 +206,7 @@ struct curl_easyoption Curl_easyopts[] = { {"PROXYUSERNAME", CURLOPT_PROXYUSERNAME, CURLOT_STRING, 0}, {"PROXYUSERPWD", CURLOPT_PROXYUSERPWD, CURLOT_STRING, 0}, {"PROXY_CAINFO", CURLOPT_PROXY_CAINFO, CURLOT_STRING, 0}, + {"PROXY_CAINFO_BLOB", CURLOPT_PROXY_CAINFO_BLOB, CURLOT_BLOB, 0}, {"PROXY_CAPATH", CURLOPT_PROXY_CAPATH, CURLOT_STRING, 0}, {"PROXY_CRLFILE", CURLOPT_PROXY_CRLFILE, CURLOT_STRING, 0}, {"PROXY_ISSUERCERT", CURLOPT_PROXY_ISSUERCERT, CURLOT_STRING, 0}, @@ -352,6 +354,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (308 + 1)); + return ((CURLOPT_LASTENTRY%10000) != (310 + 1)); } #endif diff --git a/libs/libcurl/src/file.c b/libs/libcurl/src/file.c index 1d174e519e..0420db3454 100644 --- a/libs/libcurl/src/file.c +++ b/libs/libcurl/src/file.c @@ -111,6 +111,7 @@ const struct Curl_handler Curl_handler_file = { file_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ 0, /* defport */ CURLPROTO_FILE, /* protocol */ CURLPROTO_FILE, /* family */ @@ -410,16 +411,18 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) struct tm buffer; const struct tm *tm = &buffer; char header[80]; + int headerlen; + char accept_ranges[24]= { "Accept-ranges: bytes\r\n" }; if(expected_size >= 0) { - msnprintf(header, sizeof(header), + headerlen = msnprintf(header, sizeof(header), "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size); - result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0); + result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen); if(result) return result; result = Curl_client_write(data, CLIENTWRITE_HEADER, - (char *)"Accept-ranges: bytes\r\n", 0); + accept_ranges, strlen(accept_ranges)); if(result != CURLE_OK) return result; } @@ -430,7 +433,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) return result; /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - msnprintf(header, sizeof(header), + headerlen = msnprintf(header, sizeof(header), "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s", Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], tm->tm_mday, @@ -440,7 +443,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) tm->tm_min, tm->tm_sec, data->set.opt_no_body ? "": "\r\n"); - result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0); + result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen); if(result) return result; /* set the file size to make it available post transfer */ diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c index 5bf44f1180..444cf35f55 100644 --- a/libs/libcurl/src/ftp.c +++ b/libs/libcurl/src/ftp.c @@ -175,6 +175,7 @@ const struct Curl_handler Curl_handler_ftp = { ftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_FTP, /* defport */ CURLPROTO_FTP, /* protocol */ CURLPROTO_FTP, /* family */ @@ -205,6 +206,7 @@ const struct Curl_handler Curl_handler_ftps = { ftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_FTPS, /* defport */ CURLPROTO_FTPS, /* protocol */ CURLPROTO_FTP, /* family */ @@ -1090,7 +1092,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, else res = NULL; /* failure! */ - if(res == NULL) { + if(!res) { failf(data, "failed to resolve the address provided to PORT: %s", host); free(addr); return CURLE_FTP_PORT_FAILED; @@ -2098,6 +2100,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, data->set.get_filetime && (data->info.filetime >= 0) ) { char headerbuf[128]; + int headerbuflen; time_t filetime = data->info.filetime; struct tm buffer; const struct tm *tm = &buffer; @@ -2107,7 +2110,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, return result; /* format: "Tue, 15 Nov 1994 12:45:26" */ - msnprintf(headerbuf, sizeof(headerbuf), + headerbuflen = msnprintf(headerbuf, sizeof(headerbuf), "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], tm->tm_mday, @@ -2116,7 +2119,8 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, tm->tm_hour, tm->tm_min, tm->tm_sec); - result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf, 0); + result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf, + headerbuflen); if(result) return result; } /* end of a ridiculous amount of conditionals */ @@ -2321,9 +2325,9 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data, #ifdef CURL_FTP_HTTPSTYLE_HEAD if(-1 != filesize) { char clbuf[128]; - msnprintf(clbuf, sizeof(clbuf), + int clbuflen = msnprintf(clbuf, sizeof(clbuf), "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize); - result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, 0); + result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, clbuflen); if(result) return result; } @@ -2357,7 +2361,8 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data, #ifdef CURL_FTP_HTTPSTYLE_HEAD if(ftpcode == 350) { char buffer[24]= { "Accept-ranges: bytes\r\n" }; - result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer, 0); + result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer, + strlen(buffer)); if(result) return result; } diff --git a/libs/libcurl/src/ftplistparser.c b/libs/libcurl/src/ftplistparser.c index 81825e6ff6..716ff38172 100644 --- a/libs/libcurl/src/ftplistparser.c +++ b/libs/libcurl/src/ftplistparser.c @@ -424,7 +424,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, endptr++; while(ISDIGIT(*endptr)) endptr++; - if(*endptr != 0) { + if(*endptr) { parser->error = CURLE_FTP_BAD_FILE_LIST; goto fail; } diff --git a/libs/libcurl/src/gopher.c b/libs/libcurl/src/gopher.c index a39cc7e6b4..f61232ff56 100644 --- a/libs/libcurl/src/gopher.c +++ b/libs/libcurl/src/gopher.c @@ -74,6 +74,7 @@ const struct Curl_handler Curl_handler_gopher = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_GOPHER, /* defport */ CURLPROTO_GOPHER, /* protocol */ CURLPROTO_GOPHER, /* family */ @@ -97,6 +98,7 @@ const struct Curl_handler Curl_handler_gophers = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_GOPHER, /* defport */ CURLPROTO_GOPHERS, /* protocol */ CURLPROTO_GOPHER, /* family */ diff --git a/libs/libcurl/src/hash.c b/libs/libcurl/src/hash.c index 5d433ad1fb..12e7aa5f27 100644 --- a/libs/libcurl/src/hash.c +++ b/libs/libcurl/src/hash.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -245,7 +245,7 @@ Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user, struct Curl_hash_element *he = le->ptr; lnext = le->next; /* ask the callback function if we shall remove this entry or not */ - if(comp == NULL || comp(user, he->ptr)) { + if(!comp || comp(user, he->ptr)) { Curl_llist_remove(list, le, (void *) h); --h->size; /* one less entry in the hash now */ } diff --git a/libs/libcurl/src/hostcheck.c b/libs/libcurl/src/hostcheck.c index 0fef98b2ad..49dbab3472 100644 --- a/libs/libcurl/src/hostcheck.c +++ b/libs/libcurl/src/hostcheck.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -81,7 +81,7 @@ static int hostmatch(char *hostname, char *pattern) pattern[len-1] = 0; pattern_wildcard = strchr(pattern, '*'); - if(pattern_wildcard == NULL) + if(!pattern_wildcard) return strcasecompare(pattern, hostname) ? CURL_HOST_MATCH : CURL_HOST_NOMATCH; @@ -97,7 +97,7 @@ static int hostmatch(char *hostname, char *pattern) match. */ wildcard_enabled = 1; pattern_label_end = strchr(pattern, '.'); - if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL || + if(!pattern_label_end || strchr(pattern_label_end + 1, '.') == NULL || pattern_wildcard > pattern_label_end || strncasecompare(pattern, "xn--", 4)) { wildcard_enabled = 0; @@ -107,7 +107,7 @@ static int hostmatch(char *hostname, char *pattern) CURL_HOST_MATCH : CURL_HOST_NOMATCH; hostname_label_end = strchr(hostname, '.'); - if(hostname_label_end == NULL || + if(!hostname_label_end || !strcasecompare(pattern_label_end, hostname_label_end)) return CURL_HOST_NOMATCH; diff --git a/libs/libcurl/src/hostip.c b/libs/libcurl/src/hostip.c index 05c09f6835..e0e3cfc2cb 100644 --- a/libs/libcurl/src/hostip.c +++ b/libs/libcurl/src/hostip.c @@ -68,6 +68,10 @@ #include "curl_memory.h" #include "memdebug.h" +#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES) +#include <SystemConfiguration/SCDynamicStoreCopySpecific.h> +#endif + #if defined(CURLRES_SYNCH) && \ defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP) /* alarm-based timeouts can only be used with all the dependencies satisfied */ @@ -466,10 +470,6 @@ Curl_cache_addr(struct Curl_easy *data, * function is used. You MUST call Curl_resolv_unlock() later (when you're * done using this struct) to decrease the counter again. * - * In debug mode, we specifically test for an interface name "LocalHost" - * and resolve "localhost" instead as a means to permit test cases - * to connect to a local test server with any host name. - * * Return codes: * * CURLRESOLV_ERROR (-1) = error, no pointer @@ -533,6 +533,19 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, return CURLRESOLV_ERROR; } +#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES) + /* + * The automagic conversion from IPv4 literals to IPv6 literals only works + * if the SCDynamicStoreCopyProxies system function gets called first. As + * Curl currently doesn't support system-wide HTTP proxies, we therefore + * don't use any value this function might return. + * + * This function is only available on a macOS and is not needed for + * IPv4-only builds, hence the conditions above. + */ + SCDynamicStoreCopyProxies(NULL); +#endif + #ifndef USE_RESOLVE_ON_IPS /* First check if this is an IPv4 address string */ if(Curl_inet_pton(AF_INET, hostname, &in) > 0) @@ -578,13 +591,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, /* 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(data, -#ifdef DEBUGBUILD - (data->set.str[STRING_DEVICE] - && !strcmp(data->set.str[STRING_DEVICE], - "LocalHost"))?"localhost": -#endif - hostname, port, &respwait); + addr = Curl_getaddrinfo(data, hostname, port, &respwait); } } if(!addr) { diff --git a/libs/libcurl/src/hostip.h b/libs/libcurl/src/hostip.h index c0fd3c8c46..d178976aa1 100644 --- a/libs/libcurl/src/hostip.h +++ b/libs/libcurl/src/hostip.h @@ -136,15 +136,6 @@ void Curl_hostcache_prune(struct Curl_easy *data); /* Return # of addresses in a Curl_addrinfo struct */ int Curl_num_addresses(const struct Curl_addrinfo *addr); -#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) -int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, - GETNAMEINFO_TYPE_ARG2 salen, - char *host, GETNAMEINFO_TYPE_ARG46 hostlen, - char *serv, GETNAMEINFO_TYPE_ARG46 servlen, - GETNAMEINFO_TYPE_ARG7 flags, - int line, const char *source); -#endif - /* IPv4 threadsafe resolve function used for synch and asynch builds */ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); diff --git a/libs/libcurl/src/hostip6.c b/libs/libcurl/src/hostip6.c index 53b3c67223..9791d86468 100644 --- a/libs/libcurl/src/hostip6.c +++ b/libs/libcurl/src/hostip6.c @@ -140,26 +140,13 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, #ifndef USE_RESOLVE_ON_IPS char addrbuf[128]; #endif - int pf; + int pf = PF_INET; *waitp = 0; /* synchronous response only */ - /* Check if a limited name resolve has been requested */ - switch(data->set.ipver) { - case CURL_IPRESOLVE_V4: - pf = PF_INET; - break; - case CURL_IPRESOLVE_V6: - pf = PF_INET6; - break; - default: + if(Curl_ipv6works(data)) + /* The stack seems to be IPv6-enabled */ pf = PF_UNSPEC; - break; - } - - 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; diff --git a/libs/libcurl/src/hsts.c b/libs/libcurl/src/hsts.c index fd4926f36b..ef166f196c 100644 --- a/libs/libcurl/src/hsts.c +++ b/libs/libcurl/src/hsts.c @@ -25,7 +25,7 @@ */ #include "curl_setup.h" -#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS) +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS) #include <curl/curl.h> #include "urldata.h" #include "llist.h" @@ -37,6 +37,7 @@ #include "parsedate.h" #include "rand.h" #include "rename.h" +#include "strtoofft.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -58,7 +59,10 @@ static time_t debugtime(void *unused) char *timestr = getenv("CURL_TIME"); (void)unused; if(timestr) { - unsigned long val = strtol(timestr, NULL, 10) + deltatime; + curl_off_t val; + (void)curlx_strtoofft(timestr, NULL, 10, &val); + + val += (curl_off_t)deltatime; return (time_t)val; } return time(NULL); @@ -274,7 +278,7 @@ static CURLcode hsts_push(struct Curl_easy *data, e.namelen = strlen(sts->host); e.includeSubDomains = sts->includeSubDomains; - result = Curl_gmtime(sts->expires, &stamp); + result = Curl_gmtime((time_t)sts->expires, &stamp); if(result) return result; @@ -294,7 +298,7 @@ static CURLcode hsts_push(struct Curl_easy *data, static CURLcode hsts_out(struct stsentry *sts, FILE *fp) { struct tm stamp; - CURLcode result = Curl_gmtime(sts->expires, &stamp); + CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp); if(result) return result; @@ -439,7 +443,10 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h) expires = Curl_getdate_capped(e.expire); else expires = TIME_T_MAX; /* the end of time */ - result = hsts_create(h, e.name, e.includeSubDomains, expires); + result = hsts_create(h, e.name, + /* bitfield to bool conversion: */ + e.includeSubDomains ? TRUE : FALSE, + expires); if(result) return result; } @@ -517,4 +524,4 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h) return hsts_pull(data, h); } -#endif /* CURL_DISABLE_HTTP || USE_HSTS */ +#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ diff --git a/libs/libcurl/src/hsts.h b/libs/libcurl/src/hsts.h index ae5db74a24..baa582864a 100644 --- a/libs/libcurl/src/hsts.h +++ b/libs/libcurl/src/hsts.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2020 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,7 +23,7 @@ ***************************************************************************/ #include "curl_setup.h" -#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS) +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS) #include <curl/curl.h> #include "llist.h" @@ -35,7 +35,7 @@ struct stsentry { struct Curl_llist_element node; const char *host; bool includeSubDomains; - time_t expires; /* the timestamp of this entry's expiry */ + curl_off_t expires; /* the timestamp of this entry's expiry */ }; /* The HSTS cache. Needs to be able to tailmatch host names. */ @@ -61,5 +61,5 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, #define Curl_hsts_cleanup(x) #define Curl_hsts_loadcb(x,y) #define Curl_hsts_save(x,y,z) -#endif /* CURL_DISABLE_HTTP || USE_HSTS */ +#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ #endif /* HEADER_CURL_HSTS_H */ diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c index 02c81c419b..628dd73703 100644 --- a/libs/libcurl/src/http.c +++ b/libs/libcurl/src/http.c @@ -133,6 +133,7 @@ const struct Curl_handler Curl_handler_http = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTP, /* defport */ CURLPROTO_HTTP, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -160,6 +161,7 @@ const struct Curl_handler Curl_handler_https = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTPS, /* defport */ CURLPROTO_HTTPS, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -740,7 +742,7 @@ output_auth_headers(struct Curl_easy *data, if(authstatus->picked == CURLAUTH_BEARER) { /* Bearer */ if((!proxy && data->set.str[STRING_BEARER] && - !Curl_checkheaders(data, "Authorization:"))) { + !Curl_checkheaders(data, "Authorization"))) { auth = "Bearer"; result = http_output_bearer(data); if(result) @@ -897,6 +899,11 @@ Curl_http_output_auth(struct Curl_easy *data, * proxy CONNECT loop. */ +static int is_valid_auth_separator(char ch) +{ + return ch == '\0' || ch == ',' || ISSPACE(ch); +} + CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, const char *auth) /* the first non-space */ { @@ -940,7 +947,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, while(*auth) { #ifdef USE_SPNEGO - if(checkprefix("Negotiate", auth)) { + if(checkprefix("Negotiate", auth) && is_valid_auth_separator(auth[9])) { if((authp->avail & CURLAUTH_NEGOTIATE) || Curl_auth_is_spnego_supported()) { *availp |= CURLAUTH_NEGOTIATE; @@ -966,7 +973,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, #endif #ifdef USE_NTLM /* NTLM support requires the SSL crypto libs */ - if(checkprefix("NTLM", auth)) { + if(checkprefix("NTLM", auth) && is_valid_auth_separator(auth[4])) { if((authp->avail & CURLAUTH_NTLM) || (authp->avail & CURLAUTH_NTLM_WB) || Curl_auth_is_ntlm_supported()) { @@ -1004,7 +1011,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, else #endif #ifndef CURL_DISABLE_CRYPTO_AUTH - if(checkprefix("Digest", auth)) { + if(checkprefix("Digest", auth) && is_valid_auth_separator(auth[6])) { if((authp->avail & CURLAUTH_DIGEST) != 0) infof(data, "Ignoring duplicate digest auth header.\n"); else if(Curl_auth_is_digest_supported()) { @@ -1026,7 +1033,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, } else #endif - if(checkprefix("Basic", auth)) { + if(checkprefix("Basic", auth) && + is_valid_auth_separator(auth[5])) { *availp |= CURLAUTH_BASIC; authp->avail |= CURLAUTH_BASIC; if(authp->picked == CURLAUTH_BASIC) { @@ -1039,7 +1047,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, } } else - if(checkprefix("Bearer", auth)) { + if(checkprefix("Bearer", auth) && + is_valid_auth_separator(auth[6])) { *availp |= CURLAUTH_BEARER; authp->avail |= CURLAUTH_BEARER; if(authp->picked == CURLAUTH_BEARER) { @@ -1266,14 +1275,6 @@ CURLcode Curl_buffer_send(struct dynbuf *in, else sendsize = size; - /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk - when we speak HTTPS, as if only a fraction of it is sent now, this data - needs to fit into the normal read-callback buffer later on and that - buffer is using this size. - */ - if(sendsize > CURL_MAX_WRITE_SIZE) - sendsize = CURL_MAX_WRITE_SIZE; - /* OpenSSL is very picky and we must send the SAME buffer pointer to the library when we attempt to re-send this buffer. Sending the same data is not enough, we must use the exact same address. For this reason, we @@ -1286,6 +1287,14 @@ CURLcode Curl_buffer_send(struct dynbuf *in, Curl_dyn_free(in); return result; } + /* We never send more than upload_buffer_size bytes in one single chunk + when we speak HTTPS, as if only a fraction of it is sent now, this data + needs to fit into the normal read-callback buffer later on and that + buffer is using this size. + */ + if(sendsize > (size_t)data->set.upload_buffer_size) + sendsize = (size_t)data->set.upload_buffer_size; + memcpy(data->state.ulbuf, ptr, sendsize); ptr = data->state.ulbuf; } @@ -3113,6 +3122,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) /* initialize a dynamic send-buffer */ Curl_dyn_init(&req, DYN_HTTP_REQUEST); + /* make sure the header buffer is reset - if there are leftovers from a + previous transfer */ + Curl_dyn_reset(&data->state.headerb); + /* add the main request stuff */ /* GET/HEAD/POST/PUT */ result = Curl_dyn_addf(&req, "%s ", request); @@ -3375,7 +3388,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, if(!k->http_bodyless && !data->set.ignorecl && checkprefix("Content-Length:", headp)) { curl_off_t contentlength; - CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength); + CURLofft offt = curlx_strtoofft(headp + strlen("Content-Length:"), + NULL, 10, &contentlength); if(offt == CURL_OFFT_OK) { if(data->set.max_filesize && @@ -3474,7 +3488,9 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, * of chunks, and a chunk-data set to zero signals the * end-of-chunks. */ - result = Curl_build_unencoding_stack(data, headp + 18, TRUE); + result = Curl_build_unencoding_stack(data, + headp + strlen("Transfer-Encoding:"), + TRUE); if(result) return result; } @@ -3487,17 +3503,20 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, * 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); + result = Curl_build_unencoding_stack(data, + headp + strlen("Content-Encoding:"), + 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]); + time_t date = Curl_getdate_capped(headp + strlen("Retry-After:")); if(-1 == date) { /* not a date, try it as a decimal number */ - (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after); + (void)curlx_strtoofft(headp + strlen("Retry-After:"), + NULL, 10, &retry_after); } else /* convert date to number of seconds into the future */ @@ -3516,7 +3535,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, The forth means the requested range was unsatisfied. */ - char *ptr = headp + 14; + char *ptr = headp + strlen("Content-Range:"); /* Move forward until first digit or asterisk */ while(*ptr && !ISDIGIT(*ptr) && *ptr != '*') @@ -3539,7 +3558,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); Curl_cookie_add(data, - data->cookies, TRUE, FALSE, headp + 11, + data->cookies, TRUE, FALSE, + headp + strlen("Set-Cookie:"), /* If there is a custom-set Host: name, use it here, or else use real peer host name. */ data->state.aptr.cookiehost? @@ -3574,7 +3594,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, return result; } #ifdef USE_SPNEGO - else if(checkprefix("Persistent-Auth", headp)) { + else if(checkprefix("Persistent-Auth:", headp)) { struct negotiatedata *negdata = &conn->negotiate; struct auth *authp = &data->state.authhost; if(authp->picked == CURLAUTH_NEGOTIATE) { @@ -3618,13 +3638,13 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, } } -#ifdef USE_HSTS +#ifndef CURL_DISABLE_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 ]); + headp + strlen("Strict-Transport-Security:")); if(check) infof(data, "Illegal STS header skipped\n"); #ifdef DEBUGBUILD @@ -3648,7 +3668,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, /* 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:") ], + headp + strlen("Alt-Svc:"), id, conn->host.name, curlx_uitous(conn->remote_port)); if(result) diff --git a/libs/libcurl/src/http.h b/libs/libcurl/src/http.h index 36e2152fe3..2a3834ae11 100644 --- a/libs/libcurl/src/http.h +++ b/libs/libcurl/src/http.h @@ -184,8 +184,7 @@ struct HTTP { enum { HTTPSEND_NADA, /* init */ HTTPSEND_REQUEST, /* sending a request */ - HTTPSEND_BODY, /* sending body */ - HTTPSEND_LAST /* never use this */ + HTTPSEND_BODY /* sending body */ } sending; #ifndef CURL_DISABLE_HTTP @@ -211,6 +210,7 @@ struct HTTP { char **push_headers; /* allocated array */ size_t push_headers_used; /* number of entries filled in */ size_t push_headers_alloc; /* number of entries allocated */ + uint32_t error; /* HTTP/2 stream error code */ #endif #if defined(USE_NGHTTP2) || defined(USE_NGHTTP3) bool closed; /* TRUE on HTTP2 stream close */ @@ -281,7 +281,6 @@ struct http_conn { /* list of settings that will be sent */ nghttp2_settings_entry local_settings[3]; size_t local_settings_num; - uint32_t error_code; /* HTTP/2 error code */ #else int unused; /* prevent a compiler warning */ #endif diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c index ce9a0d393c..f194c18b23 100644 --- a/libs/libcurl/src/http2.c +++ b/libs/libcurl/src/http2.c @@ -288,6 +288,7 @@ void Curl_http2_setup_req(struct Curl_easy *data) http->mem = NULL; http->len = 0; http->memlen = 0; + http->error = NGHTTP2_NO_ERROR; } /* called from http_setup_conn */ @@ -295,7 +296,6 @@ void Curl_http2_setup_conn(struct connectdata *conn) { conn->proto.httpc.settings.max_concurrent_streams = DEFAULT_MAX_CONCURRENT_STREAMS; - conn->proto.httpc.error_code = NGHTTP2_NO_ERROR; } /* @@ -319,6 +319,7 @@ static const struct Curl_handler Curl_handler_http2 = { http2_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ http2_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTP, /* defport */ CURLPROTO_HTTP, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -341,6 +342,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = { http2_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ http2_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTP, /* defport */ CURLPROTO_HTTPS, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -499,33 +501,43 @@ static int set_transfer_url(struct Curl_easy *data, const char *v; CURLU *u = curl_url(); CURLUcode uc; - char *url; + char *url = NULL; + int rc = 0; v = curl_pushheader_byname(hp, ":scheme"); if(v) { uc = curl_url_set(u, CURLUPART_SCHEME, v, 0); - if(uc) - return 1; + if(uc) { + rc = 1; + goto fail; + } } v = curl_pushheader_byname(hp, ":authority"); if(v) { uc = curl_url_set(u, CURLUPART_HOST, v, 0); - if(uc) - return 2; + if(uc) { + rc = 2; + goto fail; + } } v = curl_pushheader_byname(hp, ":path"); if(v) { uc = curl_url_set(u, CURLUPART_PATH, v, 0); - if(uc) - return 3; + if(uc) { + rc = 3; + goto fail; + } } uc = curl_url_get(u, CURLUPART_URL, &url, 0); if(uc) - return 4; + rc = 4; + fail: curl_url_cleanup(u); + if(rc) + return rc; if(data->state.url_alloc) free(data->state.url); @@ -571,6 +583,7 @@ static int push_promise(struct Curl_easy *data, rv = set_transfer_url(newhandle, &heads); if(rv) { + (void)Curl_close(&newhandle); rv = CURL_PUSH_DENY; goto fail; } @@ -877,7 +890,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, httpc = &conn->proto.httpc; drain_this(data_s, httpc); Curl_expire(data_s, 0, EXPIRE_RUN_NOW); - httpc->error_code = error_code; + stream->error = error_code; /* remove the entry from the hash as the stream is now gone */ rv = nghttp2_session_set_stream_user_data(session, stream_id, 0); @@ -1242,7 +1255,7 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn) nghttp2_session_callbacks *callbacks; conn->proto.httpc.inbuf = malloc(H2_BUFSIZE); - if(conn->proto.httpc.inbuf == NULL) + if(!conn->proto.httpc.inbuf) return CURLE_OUT_OF_MEMORY; rc = nghttp2_session_callbacks_new(&callbacks); @@ -1383,7 +1396,7 @@ static int h2_process_pending_input(struct Curl_easy *data, } rv = h2_session_send(data, httpc->h2); - if(rv != 0) { + if(rv) { *err = CURLE_SEND_ERROR; return -1; } @@ -1397,9 +1410,10 @@ static int h2_process_pending_input(struct Curl_easy *data, } if(should_close_session(httpc)) { + struct HTTP *stream = data->req.p.http; H2BUGF(infof(data, "h2_process_pending_input: nothing to do in this session\n")); - if(httpc->error_code) + if(stream->error) *err = CURLE_HTTP2; else { /* not an error per se, but should still close the connection */ @@ -1422,9 +1436,7 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data, if((conn->handler == &Curl_handler_http2_ssl) || (conn->handler == &Curl_handler_http2)) { /* make sure this is only attempted for HTTP/2 transfers */ - struct HTTP *stream = data->req.p.http; - struct http_conn *httpc = &conn->proto.httpc; nghttp2_session *h2 = httpc->h2; @@ -1448,7 +1460,7 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data, /* and attempt to send the pending frames */ rv = h2_session_send(data, h2); - if(rv != 0) + if(rv) result = CURLE_SEND_ERROR; if(nghttp2_session_want_write(h2)) { @@ -1482,7 +1494,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, /* Reset to FALSE to prevent infinite loop in readwrite_data function. */ stream->closed = FALSE; - if(httpc->error_code == NGHTTP2_REFUSED_STREAM) { + if(stream->error == NGHTTP2_REFUSED_STREAM) { H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n", stream->stream_id)); connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */ @@ -1490,10 +1502,10 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */ return -1; } - else if(httpc->error_code != NGHTTP2_NO_ERROR) { + else if(stream->error != NGHTTP2_NO_ERROR) { failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)", - stream->stream_id, nghttp2_http2_strerror(httpc->error_code), - httpc->error_code); + stream->stream_id, nghttp2_http2_strerror(stream->error), + stream->error); *err = CURLE_HTTP2_STREAM; return -1; } @@ -1609,6 +1621,10 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return -1; } + if(stream->closed) + /* closed overrides paused */ + return http2_handle_stream_close(conn, data, stream, err); + /* Nullify here because we call nghttp2_session_send() and they might refer to the old buffer. */ stream->upload_mem = NULL; @@ -1760,7 +1776,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, nread)); } - if(h2_process_pending_input(data, httpc, err) != 0) + if(h2_process_pending_input(data, httpc, err)) return -1; } if(stream->memlen) { @@ -1785,7 +1801,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return retlen; } if(stream->closed) - return 0; + return http2_handle_stream_close(conn, data, stream, err); *err = CURLE_AGAIN; H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n", stream->stream_id)); @@ -1960,7 +1976,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, more space. */ nheader += 1; nva = malloc(sizeof(nghttp2_nv) * nheader); - if(nva == NULL) { + if(!nva) { *err = CURLE_OUT_OF_MEMORY; return -1; } @@ -2083,7 +2099,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, } /* :authority must come before non-pseudo header fields */ - if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) { + if(authority_idx && authority_idx != AUTHORITY_DST_IDX) { nghttp2_nv authority = nva[authority_idx]; for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) { nva[i] = nva[i - 1]; @@ -2153,7 +2169,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, stream->stream_id = stream_id; rv = h2_session_send(data, h2); - if(rv != 0) { + if(rv) { H2BUGF(infof(data, "http2_send() nghttp2_session_send error (%s)%d\n", nghttp2_strerror(rv), rv)); @@ -2259,10 +2275,10 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, /* stream 1 is opened implicitly on upgrade */ stream->stream_id = 1; /* queue SETTINGS frame (again) */ - rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings, - httpc->binlen, NULL); - if(rv != 0) { - failf(data, "nghttp2_session_upgrade() failed: %s(%d)", + rv = nghttp2_session_upgrade2(httpc->h2, httpc->binsettings, httpc->binlen, + data->state.httpreq == HTTPREQ_HEAD, NULL); + if(rv) { + failf(data, "nghttp2_session_upgrade2() failed: %s(%d)", nghttp2_strerror(rv), rv); return CURLE_HTTP2; } @@ -2284,7 +2300,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, httpc->local_settings, httpc->local_settings_num); - if(rv != 0) { + if(rv) { failf(data, "nghttp2_submit_settings() failed: %s(%d)", nghttp2_strerror(rv), rv); return CURLE_HTTP2; @@ -2293,7 +2309,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0, HTTP2_HUGE_WINDOW_SIZE); - if(rv != 0) { + if(rv) { failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)", nghttp2_strerror(rv), rv); return CURLE_HTTP2; @@ -2321,8 +2337,15 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, DEBUGASSERT(httpc->nread_inbuf == 0); - if(-1 == h2_process_pending_input(data, httpc, &result)) - return CURLE_HTTP2; + /* Good enough to call it an end once the remaining payload is copied to the + * connection buffer. + * Some servers (e.g. nghttpx v1.43.0) may fulfill stream 1 immediately + * following the protocol switch other than waiting for the client-side + * connection preface. If h2_process_pending_input is invoked here to parse + * the remaining payload, stream 1 would be marked as closed too early and + * thus ignored in http2_recv (following 252790c53). + * The logic in lib/http.c and lib/transfer.c guarantees a following + * http2_recv would be invoked very soon. */ return CURLE_OK; } @@ -2332,7 +2355,8 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause) DEBUGASSERT(data); DEBUGASSERT(data->conn); /* if it isn't HTTP/2, we're done */ - if(!data->conn->proto.httpc.h2) + if(!(data->conn->handler->protocol & PROTO_FAMILY_HTTP) || + !data->conn->proto.httpc.h2) return CURLE_OK; #ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE else { @@ -2456,10 +2480,10 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data) /* Only call this function for a transfer that already got a HTTP/2 CURLE_HTTP2_STREAM error! */ -bool Curl_h2_http_1_1_error(struct connectdata *conn) +bool Curl_h2_http_1_1_error(struct Curl_easy *data) { - struct http_conn *httpc = &conn->proto.httpc; - return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED); + struct HTTP *stream = data->req.p.http; + return (stream->error == NGHTTP2_HTTP_1_1_REQUIRED); } #else /* !USE_NGHTTP2 */ diff --git a/libs/libcurl/src/http2.h b/libs/libcurl/src/http2.h index 114b382718..21e2c086a3 100644 --- a/libs/libcurl/src/http2.h +++ b/libs/libcurl/src/http2.h @@ -62,7 +62,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data); CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause); /* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */ -bool Curl_h2_http_1_1_error(struct connectdata *conn); +bool Curl_h2_http_1_1_error(struct Curl_easy *data); #else /* USE_NGHTTP2 */ #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_setup(x,y) CURLE_UNSUPPORTED_PROTOCOL diff --git a/libs/libcurl/src/http_digest.c b/libs/libcurl/src/http_digest.c index 132f3930c8..049b232e01 100644 --- a/libs/libcurl/src/http_digest.c +++ b/libs/libcurl/src/http_digest.c @@ -56,7 +56,7 @@ CURLcode Curl_input_digest(struct Curl_easy *data, digest = &data->state.digest; } - if(!checkprefix("Digest", header)) + if(!checkprefix("Digest", header) || !ISSPACE(header[6])) return CURLE_BAD_CONTENT_ENCODING; header += strlen("Digest"); diff --git a/libs/libcurl/src/http_negotiate.c b/libs/libcurl/src/http_negotiate.c index d759748f2e..68cce1bbb2 100644 --- a/libs/libcurl/src/http_negotiate.c +++ b/libs/libcurl/src/http_negotiate.c @@ -179,7 +179,7 @@ CURLcode Curl_output_negotiate(struct Curl_easy *data, free(base64); - if(userp == NULL) { + if(!userp) { return CURLE_OUT_OF_MEMORY; } diff --git a/libs/libcurl/src/http_ntlm.c b/libs/libcurl/src/http_ntlm.c index 4fa38f0b09..e200fdb1da 100644 --- a/libs/libcurl/src/http_ntlm.c +++ b/libs/libcurl/src/http_ntlm.c @@ -39,6 +39,7 @@ #include "http_ntlm.h" #include "curl_ntlm_core.h" #include "curl_ntlm_wb.h" +#include "curl_base64.h" #include "vauth/vauth.h" #include "url.h" @@ -80,7 +81,18 @@ CURLcode Curl_input_ntlm(struct Curl_easy *data, header++; if(*header) { - result = Curl_auth_decode_ntlm_type2_message(data, header, ntlm); + unsigned char *hdr; + size_t hdrlen; + + result = Curl_base64_decode(header, &hdr, &hdrlen); + if(!result) { + struct bufref hdrbuf; + + Curl_bufref_init(&hdrbuf); + Curl_bufref_set(&hdrbuf, hdr, hdrlen, curl_free); + result = Curl_auth_decode_ntlm_type2_message(data, &hdrbuf, ntlm); + Curl_bufref_free(&hdrbuf); + } if(result) return result; @@ -116,7 +128,8 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) { char *base64 = NULL; size_t len = 0; - CURLcode result; + CURLcode result = CURLE_OK; + struct bufref ntlmmsg; /* 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 */ @@ -173,10 +186,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) passwdp = ""; #ifdef USE_WINDOWS_SSPI - if(s_hSecDll == NULL) { + if(!s_hSecDll) { /* not thread safe and leaks - use curl_global_init() to avoid */ CURLcode err = Curl_sspi_global_init(); - if(s_hSecDll == NULL) + if(!s_hSecDll) return err; } #ifdef SECPKG_ATTR_ENDPOINT_BINDINGS @@ -184,50 +197,52 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) #endif #endif + Curl_bufref_init(&ntlmmsg); switch(*state) { case NTLMSTATE_TYPE1: default: /* for the weird cases we (re)start here */ /* Create a type-1 message */ result = Curl_auth_create_ntlm_type1_message(data, userp, passwdp, service, hostname, - ntlm, &base64, - &len); - if(result) - return result; - - if(base64) { - free(*allocuserpwd); - *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", - proxy ? "Proxy-" : "", - base64); - free(base64); - if(!*allocuserpwd) - return CURLE_OUT_OF_MEMORY; - - DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); + ntlm, &ntlmmsg); + if(!result) { + DEBUGASSERT(Curl_bufref_len(&ntlmmsg) != 0); + result = Curl_base64_encode(data, + (const char *) Curl_bufref_ptr(&ntlmmsg), + Curl_bufref_len(&ntlmmsg), &base64, &len); + if(!result) { + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", + proxy ? "Proxy-" : "", + base64); + free(base64); + if(!*allocuserpwd) + result = CURLE_OUT_OF_MEMORY; + } } break; case NTLMSTATE_TYPE2: /* We already received the type-2 message, create a type-3 message */ result = Curl_auth_create_ntlm_type3_message(data, userp, passwdp, - ntlm, &base64, &len); - if(result) - return result; - - if(base64) { - free(*allocuserpwd); - *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", - proxy ? "Proxy-" : "", - base64); - free(base64); - if(!*allocuserpwd) - return CURLE_OUT_OF_MEMORY; - - DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); - - *state = NTLMSTATE_TYPE3; /* we send a type-3 */ - authp->done = TRUE; + ntlm, &ntlmmsg); + if(!result && Curl_bufref_len(&ntlmmsg)) { + result = Curl_base64_encode(data, + (const char *) Curl_bufref_ptr(&ntlmmsg), + Curl_bufref_len(&ntlmmsg), &base64, &len); + if(!result) { + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", + proxy ? "Proxy-" : "", + base64); + free(base64); + if(!*allocuserpwd) + result = CURLE_OUT_OF_MEMORY; + else { + *state = NTLMSTATE_TYPE3; /* we send a type-3 */ + authp->done = TRUE; + } + } } break; @@ -241,8 +256,9 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) authp->done = TRUE; break; } + Curl_bufref_free(&ntlmmsg); - return CURLE_OK; + return result; } 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 f403ffc0e0..a3a62c1cad 100644 --- a/libs/libcurl/src/http_proxy.c +++ b/libs/libcurl/src/http_proxy.c @@ -39,6 +39,8 @@ #include "connect.h" #include "curlx.h" #include "vtls/vtls.h" +#include "transfer.h" +#include "multiif.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -88,29 +90,12 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex) if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { #ifndef CURL_DISABLE_PROXY /* for [protocol] tunneled through HTTP proxy */ - struct HTTP http_proxy; - void *prot_save; const char *hostname; int remote_port; CURLcode result; - /* BLOCKING */ /* We want "seamless" operations through HTTP proxy tunnel */ - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the - * member conn->proto.http; we want [protocol] through HTTP and we have - * to change the member temporarily for connecting to the HTTP - * proxy. After Curl_proxyCONNECT we have to set back the member to the - * original pointer - * - * This function might be called several times in the multi interface case - * if the proxy's CONNECT response is not instant. - */ - prot_save = data->req.p.http; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->req.p.http = &http_proxy; - connkeep(conn, "HTTP proxy CONNECT"); - /* for the secondary socket (FTP), use the "connect to host" * but ignore the "connect to port" (use the secondary port) */ @@ -128,8 +113,8 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex) remote_port = conn->conn_to_port; else remote_port = conn->remote_port; + 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); @@ -153,18 +138,53 @@ bool Curl_connect_ongoing(struct connectdata *conn) (conn->connect_state->tunnel_state != TUNNEL_COMPLETE); } +/* when we've sent a CONNECT to a proxy, we should rather either wait for the + socket to become readable to be able to get the response headers or if + we're still sending the request, wait for write. */ +int Curl_connect_getsock(struct connectdata *conn) +{ + struct HTTP *http; + DEBUGASSERT(conn); + DEBUGASSERT(conn->connect_state); + http = &conn->connect_state->http_proxy; + + if(http->sending) + return GETSOCK_WRITESOCK(0); + + return GETSOCK_READSOCK(0); +} + static CURLcode connect_init(struct Curl_easy *data, bool reinit) { struct http_connect_state *s; struct connectdata *conn = data->conn; if(!reinit) { + CURLcode result; DEBUGASSERT(!conn->connect_state); + /* we might need the upload buffer for streaming a partial request */ + result = Curl_get_upload_buffer(data); + if(result) + return result; + s = calloc(1, sizeof(struct http_connect_state)); if(!s) return CURLE_OUT_OF_MEMORY; infof(data, "allocate connect buffer!\n"); conn->connect_state = s; Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS); + + /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the + * member conn->proto.http; we want [protocol] through HTTP and we have + * to change the member temporarily for connecting to the HTTP + * proxy. After Curl_proxyCONNECT we have to set back the member to the + * original pointer + * + * This function might be called several times in the multi interface case + * if the proxy's CONNECT response is not instant. + */ + s->prot_save = data->req.p.http; + data->req.p.http = &s->http_proxy; + connkeep(conn, "HTTP proxy CONNECT"); } else { DEBUGASSERT(conn->connect_state); @@ -184,6 +204,10 @@ static void connect_done(struct Curl_easy *data) struct http_connect_state *s = conn->connect_state; s->tunnel_state = TUNNEL_COMPLETE; Curl_dyn_free(&s->rcvbuf); + Curl_dyn_free(&s->req); + + /* retore the protocol pointer */ + data->req.p.http = s->prot_save; infof(data, "CONNECT phase completed!\n"); } @@ -231,6 +255,7 @@ static CURLcode CONNECT(struct Curl_easy *data, struct connectdata *conn = data->conn; curl_socket_t tunnelsocket = conn->sock[sockindex]; struct http_connect_state *s = conn->connect_state; + struct HTTP *http = data->req.p.http; char *linep; size_t perline; @@ -246,7 +271,7 @@ static CURLcode CONNECT(struct Curl_easy *data, timediff_t check; if(TUNNEL_INIT == s->tunnel_state) { /* BEGIN CONNECT PHASE */ - struct dynbuf req; + struct dynbuf *req = &s->req; char *hostheader = NULL; char *host = NULL; @@ -259,8 +284,8 @@ static CURLcode CONNECT(struct Curl_easy *data, free(data->req.newurl); data->req.newurl = NULL; - /* initialize a dynamic send-buffer */ - Curl_dyn_init(&req, DYN_HTTP_REQUEST); + /* initialize send-buffer */ + Curl_dyn_init(req, DYN_HTTP_REQUEST); result = CONNECT_host(data, conn, hostname, remote_port, &hostheader, &host); @@ -285,7 +310,7 @@ static CURLcode CONNECT(struct Curl_easy *data, useragent = data->state.aptr.uagent; result = - Curl_dyn_addf(&req, + Curl_dyn_addf(req, "CONNECT %s HTTP/%s\r\n" "%s" /* Host: */ "%s" /* Proxy-Authorization */ @@ -300,16 +325,15 @@ static CURLcode CONNECT(struct Curl_easy *data, proxyconn); if(!result) - result = Curl_add_custom_headers(data, TRUE, &req); + result = Curl_add_custom_headers(data, TRUE, req); if(!result) /* CRLF terminate the request */ - result = Curl_dyn_add(&req, "\r\n"); + result = Curl_dyn_add(req, "\r\n"); if(!result) { /* Send the connect request to the proxy */ - /* BLOCKING */ - result = Curl_buffer_send(&req, data, &data->info.request_size, 0, + result = Curl_buffer_send(req, data, &data->info.request_size, 0, sockindex); } if(result) @@ -317,7 +341,6 @@ static CURLcode CONNECT(struct Curl_easy *data, } free(host); free(hostheader); - Curl_dyn_free(&req); if(result) return result; @@ -330,12 +353,42 @@ static CURLcode CONNECT(struct Curl_easy *data, return CURLE_OPERATION_TIMEDOUT; } - if(!Curl_conn_data_pending(conn, sockindex)) + if(!Curl_conn_data_pending(conn, sockindex) && !http->sending) /* return so we'll be called again polling-style */ return CURLE_OK; /* at this point, the tunnel_connecting phase is over. */ + if(http->sending == HTTPSEND_REQUEST) { + if(!s->nsend) { + size_t fillcount; + k->upload_fromhere = data->state.ulbuf; + result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, + &fillcount); + if(result) + return result; + s->nsend = fillcount; + } + if(s->nsend) { + ssize_t bytes_written; + /* write to socket (send away data) */ + result = Curl_write(data, + conn->writesockfd, /* socket to send to */ + k->upload_fromhere, /* buffer pointer */ + s->nsend, /* buffer size */ + &bytes_written); /* actually sent */ + + if(!result) + /* send to debug callback! */ + result = Curl_debug(data, CURLINFO_HEADER_OUT, + k->upload_fromhere, bytes_written); + + s->nsend -= bytes_written; + k->upload_fromhere += bytes_written; + return result; + } + /* if nothing left to send, continue */ + } { /* READING RESPONSE PHASE */ int error = SELECT_OK; diff --git a/libs/libcurl/src/http_proxy.h b/libs/libcurl/src/http_proxy.h index a78db0d046..f5a4cb07cf 100644 --- a/libs/libcurl/src/http_proxy.h +++ b/libs/libcurl/src/http_proxy.h @@ -38,15 +38,39 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex); bool Curl_connect_complete(struct connectdata *conn); bool Curl_connect_ongoing(struct connectdata *conn); +int Curl_connect_getsock(struct connectdata *conn); #else #define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN #define Curl_proxy_connect(x,y) CURLE_OK #define Curl_connect_complete(x) CURLE_OK #define Curl_connect_ongoing(x) FALSE +#define Curl_connect_getsock(x) 0 #endif void Curl_connect_free(struct Curl_easy *data); void Curl_connect_done(struct Curl_easy *data); +/* struct for HTTP CONNECT state data */ +struct http_connect_state { + struct HTTP http_proxy; + struct HTTP *prot_save; + struct dynbuf rcvbuf; + struct dynbuf req; + size_t nsend; + enum keeponval { + KEEPON_DONE, + KEEPON_CONNECT, + KEEPON_IGNORE + } keepon; + curl_off_t cl; /* size of content to read and ignore */ + enum { + TUNNEL_INIT, /* init/default/no tunnel state */ + TUNNEL_CONNECT, /* CONNECT has been sent off */ + TUNNEL_COMPLETE /* CONNECT response received completely */ + } tunnel_state; + BIT(chunked_encoding); + BIT(close_connection); +}; + #endif /* HEADER_CURL_HTTP_PROXY_H */ diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c index e887357e1c..d85bcc391d 100644 --- a/libs/libcurl/src/imap.c +++ b/libs/libcurl/src/imap.c @@ -136,6 +136,7 @@ const struct Curl_handler Curl_handler_imap = { imap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_IMAP, /* defport */ CURLPROTO_IMAP, /* protocol */ CURLPROTO_IMAP, /* family */ @@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_imaps = { imap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_IMAPS, /* defport */ CURLPROTO_IMAPS, /* protocol */ CURLPROTO_IMAP, /* family */ @@ -919,7 +921,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data, /* Do we have a SASL based authentication mechanism? */ else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { size_t llen; - unsigned int mechbit; + unsigned short mechbit; line += 5; wordlen -= 5; diff --git a/libs/libcurl/src/inet_ntop.c b/libs/libcurl/src/inet_ntop.c index 9a5af7f421..4c3e9e4dad 100644 --- a/libs/libcurl/src/inet_ntop.c +++ b/libs/libcurl/src/inet_ntop.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1996-2019 Internet Software Consortium. + * Copyright (C) 1996-2021 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -134,7 +134,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) /* Are we following an initial run of 0x00s or any real hex? */ - if(i != 0) + if(i) *tp++ = ':'; /* Is this address an encapsulated IPv4? diff --git a/libs/libcurl/src/krb5.c b/libs/libcurl/src/krb5.c index eb83566d6b..4d1102da36 100644 --- a/libs/libcurl/src/krb5.c +++ b/libs/libcurl/src/krb5.c @@ -160,16 +160,6 @@ krb5_decode(void *app_data, void *buf, int len, } static int -krb5_overhead(void *app_data, int level, int len) -{ - /* no arguments are used */ - (void)app_data; - (void)level; - (void)len; - return 0; -} - -static int krb5_encode(void *app_data, const void *from, int length, int level, void **to) { gss_ctx_id_t *context = app_data; @@ -305,7 +295,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn) break; } - if(output_buffer.length != 0) { + if(output_buffer.length) { char *cmd; result = Curl_base64_encode(data, (char *)output_buffer.value, @@ -392,7 +382,7 @@ static struct Curl_sec_client_mech Curl_krb5_client_mech = { krb5_auth, krb5_end, krb5_check_prot, - krb5_overhead, + krb5_encode, krb5_decode }; @@ -412,7 +402,7 @@ name_to_level(const char *name) { int i; for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++) - if(checkprefix(name, level_names[i].name)) + if(curl_strequal(name, level_names[i].name)) return level_names[i].level; return PROT_NONE; } @@ -657,8 +647,6 @@ static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn, { ssize_t tx = 0, len = conn->buffer_size; - len -= conn->mech->overhead(conn->app_data, conn->data_prot, - curlx_sztosi(len)); if(len <= 0) len = length; while(length) { @@ -760,7 +748,7 @@ static int sec_set_protection_level(struct Curl_easy *data) if(level) { char *pbsz; - static unsigned int buffer_size = 1 << 20; /* 1048576 */ + unsigned int buffer_size = 1 << 20; /* 1048576 */ code = ftp_send_command(data, "PBSZ %u", buffer_size); if(code < 0) @@ -817,7 +805,7 @@ static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn) const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech; tmp_allocation = realloc(conn->app_data, mech->size); - if(tmp_allocation == NULL) { + if(!tmp_allocation) { failf(data, "Failed realloc of size %zu", mech->size); mech = NULL; return CURLE_OUT_OF_MEMORY; diff --git a/libs/libcurl/src/ldap.c b/libs/libcurl/src/ldap.c index 860a4a851a..ed16423026 100644 --- a/libs/libcurl/src/ldap.c +++ b/libs/libcurl/src/ldap.c @@ -149,6 +149,7 @@ const struct Curl_handler Curl_handler_ldap = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_LDAP, /* defport */ CURLPROTO_LDAP, /* protocol */ CURLPROTO_LDAP, /* family */ @@ -176,6 +177,7 @@ const struct Curl_handler Curl_handler_ldaps = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_LDAPS, /* defport */ CURLPROTO_LDAPS, /* protocol */ CURLPROTO_LDAP, /* family */ @@ -303,7 +305,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) #else rc = _ldap_url_parse(data, conn, &ludp); #endif - if(rc != 0) { + if(rc) { failf(data, "LDAP local: %s", ldap_err2string(rc)); result = CURLE_LDAP_INVALID_URL; goto quit; @@ -387,7 +389,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } server = ldapssl_init(host, (int)conn->port, 1); - if(server == NULL) { + if(!server) { failf(data, "LDAP local: Cannot connect to %s:%ld", conn->host.dispname, conn->port); result = CURLE_COULDNT_CONNECT; @@ -428,7 +430,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } server = ldap_init(host, (int)conn->port); - if(server == NULL) { + if(!server) { failf(data, "LDAP local: Cannot connect to %s:%ld", conn->host.dispname, conn->port); result = CURLE_COULDNT_CONNECT; @@ -464,7 +466,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) } else { server = ldap_init(host, (int)conn->port); - if(server == NULL) { + if(!server) { failf(data, "LDAP local: Cannot connect to %s:%ld", conn->host.dispname, conn->port); result = CURLE_COULDNT_CONNECT; @@ -477,7 +479,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) #else rc = ldap_simple_bind_s(server, user, passwd); #endif - if(!ldap_ssl && rc != 0) { + if(!ldap_ssl && rc) { ldap_proto = LDAP_VERSION2; ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); #ifdef USE_WIN32_LDAP @@ -486,7 +488,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) rc = ldap_simple_bind_s(server, user, passwd); #endif } - if(rc != 0) { + if(rc) { #ifdef USE_WIN32_LDAP failf(data, "LDAP local: bind via ldap_win_bind %s", ldap_err2string(rc)); @@ -501,7 +503,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg); - if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) { + if(rc && rc != LDAP_SIZELIMIT_EXCEEDED) { failf(data, "LDAP remote: %s", ldap_err2string(rc)); result = CURLE_LDAP_SEARCH_FAILED; goto quit; @@ -581,7 +583,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) result = CURLE_OUT_OF_MEMORY; goto quit; - } + } #else char *attr = attribute; #endif @@ -1061,13 +1063,23 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp) if(!ludp) return; +#if defined(USE_WIN32_LDAP) + curlx_unicodefree(ludp->lud_dn); + curlx_unicodefree(ludp->lud_filter); +#else free(ludp->lud_dn); free(ludp->lud_filter); +#endif if(ludp->lud_attrs) { size_t i; - for(i = 0; i < ludp->lud_attrs_dups; i++) + for(i = 0; i < ludp->lud_attrs_dups; i++) { +#if defined(USE_WIN32_LDAP) + curlx_unicodefree(ludp->lud_attrs[i]); +#else free(ludp->lud_attrs[i]); +#endif + } free(ludp->lud_attrs); } diff --git a/libs/libcurl/src/libcurl.plist b/libs/libcurl/src/libcurl.plist index f787761ced..b3afa9f8a2 100644 --- a/libs/libcurl/src/libcurl.plist +++ b/libs/libcurl/src/libcurl.plist @@ -15,7 +15,7 @@ <string>se.curl.libcurl</string> <key>CFBundleVersion</key> - <string>7.76.1</string> + <string>7.77.0</string> <key>CFBundleName</key> <string>libcurl</string> @@ -27,9 +27,9 @@ <string>????</string> <key>CFBundleShortVersionString</key> - <string>libcurl 7.76.1</string> + <string>libcurl 7.77.0</string> <key>CFBundleGetInfoString</key> - <string>libcurl.plist 7.76.1</string> + <string>libcurl.plist 7.77.0</string> </dict> </plist> diff --git a/libs/libcurl/src/llist.c b/libs/libcurl/src/llist.c index 17a7be1667..e0ec7393d2 100644 --- a/libs/libcurl/src/llist.c +++ b/libs/libcurl/src/llist.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -94,13 +94,13 @@ Curl_llist_remove(struct Curl_llist *list, struct Curl_llist_element *e, void *user) { void *ptr; - if(e == NULL || list->size == 0) + if(!e || list->size == 0) return; if(e == list->head) { list->head = e->next; - if(list->head == NULL) + if(!list->head) list->tail = NULL; else e->next->prev = NULL; diff --git a/libs/libcurl/src/md4.c b/libs/libcurl/src/md4.c index e731e123d3..c651ddf669 100644 --- a/libs/libcurl/src/md4.c +++ b/libs/libcurl/src/md4.c @@ -174,7 +174,7 @@ static void MD4_Init(MD4_CTX *ctx) static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) { - if(ctx->data == NULL) { + if(!ctx->data) { ctx->data = malloc(size); if(ctx->data != NULL) { memcpy(ctx->data, data, size); diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c index abadcb02cb..0bf1b46a4c 100644 --- a/libs/libcurl/src/mime.c +++ b/libs/libcurl/src/mime.c @@ -152,14 +152,14 @@ curl_off_t VmsRealFileSize(const char *name, FILE * file; file = fopen(name, FOPEN_READTEXT); /* VMS */ - if(file == NULL) + if(!file) return 0; count = 0; ret_stat = 1; while(ret_stat > 0) { ret_stat = fread(buffer, 1, sizeof(buffer), file); - if(ret_stat != 0) + if(ret_stat) count += ret_stat; } fclose(file); diff --git a/libs/libcurl/src/mprintf.c b/libs/libcurl/src/mprintf.c index c681248dee..5292026861 100644 --- a/libs/libcurl/src/mprintf.c +++ b/libs/libcurl/src/mprintf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1999 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1999 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -815,7 +815,7 @@ static int dprintf_formatf( size_t len; str = (char *) p->data.str; - if(str == NULL) { + if(!str) { /* Write null[] if there's space. */ if(prec == -1 || prec >= (long) sizeof(null) - 1) { str = null; diff --git a/libs/libcurl/src/mqtt.c b/libs/libcurl/src/mqtt.c index 2134409cda..d88fa737df 100644 --- a/libs/libcurl/src/mqtt.c +++ b/libs/libcurl/src/mqtt.c @@ -86,6 +86,7 @@ const struct Curl_handler Curl_handler_mqtt = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_MQTT, /* defport */ CURLPROTO_MQTT, /* protocol */ CURLPROTO_MQTT, /* family */ diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c index be3e41f8bb..1b3e261c68 100644 --- a/libs/libcurl/src/multi.c +++ b/libs/libcurl/src/multi.c @@ -381,6 +381,11 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ multi->max_concurrent_streams = 100; multi->ipv6_works = Curl_ipv6works(NULL); +#ifdef USE_WINSOCK + multi->wsa_event = WSACreateEvent(); + if(multi->wsa_event == WSA_INVALID_EVENT) + goto error; +#else #ifdef ENABLE_WAKEUP if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) { multi->wakeup_pair[0] = CURL_SOCKET_BAD; @@ -394,6 +399,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ multi->wakeup_pair[1] = CURL_SOCKET_BAD; } #endif +#endif return multi; @@ -872,8 +878,10 @@ bool Curl_multiplex_wanted(const struct Curl_multi *multi) void Curl_detach_connnection(struct Curl_easy *data) { struct connectdata *conn = data->conn; - if(conn) + if(conn) { Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL); + Curl_ssl_detach_conn(data, conn); + } data->conn = NULL; } @@ -890,6 +898,9 @@ void Curl_attach_connnection(struct Curl_easy *data, data->conn = conn; Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data, &data->conn_queue); + if(conn->handler->attach) + conn->handler->attach(data, conn); + Curl_ssl_associate_conn(data, conn); } static int waitconnect_getsock(struct connectdata *conn, @@ -930,10 +941,8 @@ static int waitproxyconnect_getsock(struct connectdata *conn, { sock[0] = conn->sock[FIRSTSOCKET]; - /* when we've sent a CONNECT to a proxy, we should rather wait for the - socket to become readable to be able to get the response headers */ if(conn->connect_state) - return GETSOCK_READSOCK(0); + return Curl_connect_getsock(conn); return GETSOCK_WRITESOCK(0); } @@ -1083,6 +1092,10 @@ static CURLMcode multi_wait(struct Curl_multi *multi, struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK]; struct pollfd *ufds = &a_few_on_stack[0]; bool ufds_malloc = FALSE; +#ifdef USE_WINSOCK + WSANETWORKEVENTS wsa_events; + DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT); +#endif if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -1101,11 +1114,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi, for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { curl_socket_t s = CURL_SOCKET_BAD; - if(bitmap & GETSOCK_READSOCK(i)) { + if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) { ++nfds; s = sockbunch[i]; } - if(bitmap & GETSOCK_WRITESOCK(i)) { + if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) { ++nfds; s = sockbunch[i]; } @@ -1128,7 +1141,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi, nfds += extra_nfds; /* add the externally provided ones */ #ifdef ENABLE_WAKEUP +#ifdef USE_WINSOCK + if(use_wakeup) { +#else if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) { +#endif ++nfds; } #endif @@ -1156,22 +1173,40 @@ static CURLMcode multi_wait(struct Curl_multi *multi, for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) { curl_socket_t s = CURL_SOCKET_BAD; - +#ifdef USE_WINSOCK + long mask = 0; +#endif if(bitmap & GETSOCK_READSOCK(i)) { - ufds[nfds].fd = sockbunch[i]; + s = sockbunch[i]; +#ifdef USE_WINSOCK + mask |= FD_READ|FD_ACCEPT|FD_CLOSE; +#endif + ufds[nfds].fd = s; ufds[nfds].events = POLLIN; ++nfds; - s = sockbunch[i]; } if(bitmap & GETSOCK_WRITESOCK(i)) { - ufds[nfds].fd = sockbunch[i]; + s = sockbunch[i]; +#ifdef USE_WINSOCK + mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; + send(s, NULL, 0, 0); /* reset FD_WRITE */ +#endif + ufds[nfds].fd = s; ufds[nfds].events = POLLOUT; ++nfds; - s = sockbunch[i]; } + /* s is only set if either being readable or writable is checked */ if(s == CURL_SOCKET_BAD) { + /* break on entry not checked for being readable or writable */ break; } +#ifdef USE_WINSOCK + if(WSAEventSelect(s, multi->wsa_event, mask) != 0) { + if(ufds_malloc) + free(ufds); + return CURLM_INTERNAL_ERROR; + } +#endif } data = data->next; /* check next handle */ @@ -1180,6 +1215,22 @@ static CURLMcode multi_wait(struct Curl_multi *multi, /* Add external file descriptions from poll-like struct curl_waitfd */ for(i = 0; i < extra_nfds; i++) { +#ifdef USE_WINSOCK + long mask = 0; + if(extra_fds[i].events & CURL_WAIT_POLLIN) + mask |= FD_READ|FD_ACCEPT|FD_CLOSE; + if(extra_fds[i].events & CURL_WAIT_POLLPRI) + mask |= FD_OOB; + if(extra_fds[i].events & CURL_WAIT_POLLOUT) { + mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; + send(extra_fds[i].fd, NULL, 0, 0); /* reset FD_WRITE */ + } + if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) { + if(ufds_malloc) + free(ufds); + return CURLM_INTERNAL_ERROR; + } +#endif ufds[nfds].fd = extra_fds[i].fd; ufds[nfds].events = 0; if(extra_fds[i].events & CURL_WAIT_POLLIN) @@ -1192,25 +1243,62 @@ static CURLMcode multi_wait(struct Curl_multi *multi, } #ifdef ENABLE_WAKEUP +#ifndef USE_WINSOCK if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) { ufds[nfds].fd = multi->wakeup_pair[0]; ufds[nfds].events = POLLIN; ++nfds; } #endif +#endif +#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK) + if(nfds || use_wakeup) { +#else if(nfds) { - /* wait... */ - int pollrc = Curl_poll(ufds, nfds, timeout_ms); +#endif + int pollrc; +#ifdef USE_WINSOCK + if(nfds) + pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */ + else + pollrc = 0; + if(pollrc <= 0) /* now wait... if not ready during the pre-check above */ + WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE); +#else + pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */ +#endif + if(pollrc > 0) { retcode = pollrc; +#ifdef USE_WINSOCK + } + /* With WinSock, we have to run the following section unconditionally + to call WSAEventSelect(fd, event, 0) on all the sockets */ + { +#endif /* copy revents results from the poll to the curl_multi_wait poll struct, the bit values of the actual underlying poll() implementation may not be the same as the ones in the public libcurl API! */ for(i = 0; i < extra_nfds; i++) { - unsigned short mask = 0; unsigned r = ufds[curlfds + i].revents; - + unsigned short mask = 0; +#ifdef USE_WINSOCK + wsa_events.lNetworkEvents = 0; + if(WSAEnumNetworkEvents(extra_fds[i].fd, NULL, &wsa_events) == 0) { + if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE)) + mask |= CURL_WAIT_POLLIN; + if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE)) + mask |= CURL_WAIT_POLLOUT; + if(wsa_events.lNetworkEvents & FD_OOB) + mask |= CURL_WAIT_POLLPRI; + if(ret && pollrc <= 0 && wsa_events.lNetworkEvents) + retcode++; + } + WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0); + if(pollrc <= 0) + continue; +#endif if(r & POLLIN) mask |= CURL_WAIT_POLLIN; if(r & POLLOUT) @@ -1220,6 +1308,35 @@ static CURLMcode multi_wait(struct Curl_multi *multi, extra_fds[i].revents = mask; } +#ifdef USE_WINSOCK + /* Count up all our own sockets that had activity, + and remove them from the event. */ + if(curlfds) { + data = multi->easyp; + while(data) { + bitmap = multi_getsock(data, sockbunch); + + for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) { + if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) { + wsa_events.lNetworkEvents = 0; + if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) { + if(ret && pollrc <= 0 && wsa_events.lNetworkEvents) + retcode++; + } + WSAEventSelect(sockbunch[i], multi->wsa_event, 0); + } + else { + /* break on entry not checked for being readable or writable */ + break; + } + } + + data = data->next; + } + } + + WSAResetEvent(multi->wsa_event); +#else #ifdef ENABLE_WAKEUP if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) { if(ufds[curlfds + extra_nfds].revents & POLLIN) { @@ -1232,10 +1349,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi, when there is no more data, breaking the loop. */ nread = sread(multi->wakeup_pair[0], buf, sizeof(buf)); if(nread <= 0) { -#ifndef USE_WINSOCK if(nread < 0 && EINTR == SOCKERRNO) continue; -#endif break; } } @@ -1244,6 +1359,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi, } } #endif +#endif } } @@ -1251,10 +1367,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi, free(ufds); if(ret) *ret = retcode; - if(!extrawait || nfds) - /* if any socket was checked */ - ; - else { +#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK) + if(extrawait && !nfds && !use_wakeup) { +#else + if(extrawait && !nfds) { +#endif long sleep_ms = 0; /* Avoid busy-looping when there's nothing particular to wait for */ @@ -1303,6 +1420,10 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi) return CURLM_BAD_HANDLE; #ifdef ENABLE_WAKEUP +#ifdef USE_WINSOCK + if(WSASetEvent(multi->wsa_event)) + return CURLM_OK; +#else /* the wakeup_pair variable is only written during init and cleanup, making it safe to access from another thread after the init part and before cleanup */ @@ -1336,6 +1457,7 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi) } } #endif +#endif return CURLM_WAKEUP_FAILURE; } @@ -2153,12 +2275,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } } else if((CURLE_HTTP2_STREAM == result) && - Curl_h2_http_1_1_error(data->conn)) { + Curl_h2_http_1_1_error(data)) { CURLcode ret = Curl_retry_request(data, &newurl); if(!ret) { infof(data, "Downgrades to HTTP/1.1!\n"); - connclose(data->conn, "Disconnect HTTP/2 for HTTP/1"); + streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1"); data->state.httpwant = CURL_HTTP_VERSION_1_1; /* clear the error message bit too as we ignore the one we got */ data->state.errorbuf = FALSE; @@ -2478,10 +2600,14 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) Curl_hash_destroy(&multi->hostcache); Curl_psl_destroy(&multi->psl); +#ifdef USE_WINSOCK + WSACloseEvent(multi->wsa_event); +#else #ifdef ENABLE_WAKEUP sclose(multi->wakeup_pair[0]); sclose(multi->wakeup_pair[1]); #endif +#endif free(multi); return CURLM_OK; diff --git a/libs/libcurl/src/multihandle.h b/libs/libcurl/src/multihandle.h index edf790132a..96b84749fc 100644 --- a/libs/libcurl/src/multihandle.h +++ b/libs/libcurl/src/multihandle.h @@ -140,10 +140,14 @@ struct Curl_multi { previous callback */ unsigned int max_concurrent_streams; +#ifdef USE_WINSOCK + WSAEVENT wsa_event; /* winsock event used for waits */ +#else #ifdef ENABLE_WAKEUP curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup 0 is used for read, 1 is used for write */ #endif +#endif /* multiplexing wanted */ bool multiplexing; bool recheckstate; /* see Curl_multi_connchanged */ diff --git a/libs/libcurl/src/non-ascii.c b/libs/libcurl/src/non-ascii.c index 30c240b637..932cf89eef 100644 --- a/libs/libcurl/src/non-ascii.c +++ b/libs/libcurl/src/non-ascii.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -127,7 +127,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, &output_ptr, &out_bytes); if(!data) iconv_close(tmpcd); - if((rc == ICONV_ERROR) || (in_bytes != 0)) { + if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "The Curl_convert_to_network iconv call failed with errno %i: %s", errno, strerror(errno)); @@ -193,7 +193,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data, &output_ptr, &out_bytes); if(!data) iconv_close(tmpcd); - if((rc == ICONV_ERROR) || (in_bytes != 0)) { + if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "Curl_convert_from_network iconv call failed with errno %i: %s", errno, strerror(errno)); @@ -260,7 +260,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data, &output_ptr, &out_bytes); if(!data) iconv_close(tmpcd); - if((rc == ICONV_ERROR) || (in_bytes != 0)) { + if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "The Curl_convert_from_utf8 iconv call failed with errno %i: %s", errno, strerror(errno)); diff --git a/libs/libcurl/src/openldap.c b/libs/libcurl/src/openldap.c index b6980c5900..0b8bc34a03 100644 --- a/libs/libcurl/src/openldap.c +++ b/libs/libcurl/src/openldap.c @@ -76,16 +76,16 @@ extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, LDAP **ld); #endif -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 CURLcode oldap_setup_connection(struct Curl_easy *data, + struct connectdata *conn); +static CURLcode oldap_do(struct Curl_easy *data, bool *done); +static CURLcode oldap_done(struct Curl_easy *data, CURLcode, bool); +static CURLcode oldap_connect(struct Curl_easy *data, bool *done); +static CURLcode oldap_connecting(struct Curl_easy *data, bool *done); +static CURLcode oldap_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); -static Curl_recv ldap_recv; +static Curl_recv oldap_recv; /* * LDAP protocol handler. @@ -93,20 +93,21 @@ static Curl_recv ldap_recv; const struct Curl_handler Curl_handler_ldap = { "LDAP", /* scheme */ - ldap_setup_connection, /* setup_connection */ - ldap_do, /* do_it */ - ldap_done, /* done */ + oldap_setup_connection, /* setup_connection */ + oldap_do, /* do_it */ + oldap_done, /* done */ ZERO_NULL, /* do_more */ - ldap_connect, /* connect_it */ - ldap_connecting, /* connecting */ + oldap_connect, /* connect_it */ + oldap_connecting, /* connecting */ ZERO_NULL, /* doing */ ZERO_NULL, /* proto_getsock */ ZERO_NULL, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* perform_getsock */ - ldap_disconnect, /* disconnect */ + oldap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_LDAP, /* defport */ CURLPROTO_LDAP, /* protocol */ CURLPROTO_LDAP, /* family */ @@ -120,20 +121,21 @@ const struct Curl_handler Curl_handler_ldap = { const struct Curl_handler Curl_handler_ldaps = { "LDAPS", /* scheme */ - ldap_setup_connection, /* setup_connection */ - ldap_do, /* do_it */ - ldap_done, /* done */ + oldap_setup_connection, /* setup_connection */ + oldap_do, /* do_it */ + oldap_done, /* done */ ZERO_NULL, /* do_more */ - ldap_connect, /* connect_it */ - ldap_connecting, /* connecting */ + oldap_connect, /* connect_it */ + oldap_connecting, /* connecting */ ZERO_NULL, /* doing */ ZERO_NULL, /* proto_getsock */ ZERO_NULL, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* perform_getsock */ - ldap_disconnect, /* disconnect */ + oldap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_LDAPS, /* defport */ CURLPROTO_LDAPS, /* protocol */ CURLPROTO_LDAP, /* family */ @@ -171,8 +173,8 @@ struct ldapreqinfo { int nument; }; -static CURLcode ldap_setup_connection(struct Curl_easy *data, - struct connectdata *conn) +static CURLcode oldap_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { struct ldapconninfo *li; LDAPURLDesc *lud; @@ -207,7 +209,7 @@ static CURLcode ldap_setup_connection(struct Curl_easy *data, static Sockbuf_IO ldapsb_tls; #endif -static CURLcode ldap_connect(struct Curl_easy *data, bool *done) +static CURLcode oldap_connect(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; @@ -255,7 +257,7 @@ static CURLcode ldap_connect(struct Curl_easy *data, bool *done) return CURLE_OK; } -static CURLcode ldap_connecting(struct Curl_easy *data, bool *done) +static CURLcode oldap_connecting(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; @@ -354,25 +356,28 @@ static CURLcode ldap_connecting(struct Curl_easy *data, bool *done) if(info) ldap_memfree(info); - conn->recv[FIRSTSOCKET] = ldap_recv; + conn->recv[FIRSTSOCKET] = oldap_recv; *done = TRUE; return CURLE_OK; } -static CURLcode ldap_disconnect(struct Curl_easy *data, - struct connectdata *conn, bool dead_connection) +static CURLcode oldap_disconnect(struct Curl_easy *data, + struct connectdata *conn, + bool dead_connection) { struct ldapconninfo *li = conn->proto.ldapc; (void) dead_connection; if(li) { if(li->ld) { +#ifdef USE_SSL if(conn->ssl[FIRSTSOCKET].use) { Sockbuf *sb; ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data); } +#endif ldap_unbind_ext(li->ld, NULL, NULL); li->ld = NULL; } @@ -382,7 +387,7 @@ static CURLcode ldap_disconnect(struct Curl_easy *data, return CURLE_OK; } -static CURLcode ldap_do(struct Curl_easy *data, bool *done) +static CURLcode oldap_do(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; @@ -427,8 +432,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) return CURLE_OK; } -static CURLcode ldap_done(struct Curl_easy *data, CURLcode res, - bool premature) +static CURLcode oldap_done(struct Curl_easy *data, CURLcode res, + bool premature) { struct connectdata *conn = data->conn; struct ldapreqinfo *lr = data->req.p.ldap; @@ -450,8 +455,8 @@ static CURLcode ldap_done(struct Curl_easy *data, CURLcode res, return CURLE_OK; } -static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, - size_t len, CURLcode *err) +static ssize_t oldap_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; @@ -547,7 +552,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) { int i; - if(bv.bv_val == NULL) + if(!bv.bv_val) break; if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) @@ -555,7 +560,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, else binary = 0; - if(bvals == NULL) { + if(!bvals) { writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1); if(writeerr) { *err = writeerr; @@ -664,7 +669,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, data->req.bytecount += bvals[i].bv_len + 1; } - writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(writeerr) { *err = writeerr; return -1; @@ -673,14 +678,14 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, data->req.bytecount++; } ber_memfree(bvals); - writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(writeerr) { *err = writeerr; return -1; } data->req.bytecount++; } - writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(writeerr) { *err = writeerr; return -1; diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c index ccfebd02af..9b6ea64804 100644 --- a/libs/libcurl/src/pop3.c +++ b/libs/libcurl/src/pop3.c @@ -131,6 +131,7 @@ const struct Curl_handler Curl_handler_pop3 = { pop3_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_POP3, /* defport */ CURLPROTO_POP3, /* protocol */ CURLPROTO_POP3, /* family */ @@ -159,6 +160,7 @@ const struct Curl_handler Curl_handler_pop3s = { pop3_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_POP3S, /* defport */ CURLPROTO_POP3S, /* protocol */ CURLPROTO_POP3, /* family */ @@ -709,7 +711,7 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code, for(;;) { size_t llen; size_t wordlen; - unsigned int mechbit; + unsigned short mechbit; while(len && (*line == ' ' || *line == '\t' || @@ -1515,8 +1517,17 @@ CURLcode Curl_pop3_write(struct Curl_easy *data, 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(data, CLIENTWRITE_BODY, (char *)POP3_EOB, - strip_dot ? prev - 1 : prev); + if(strip_dot && prev - 1 > 0) { + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB, + prev - 1); + } + else if(!strip_dot) { + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB, + prev); + } + else { + result = CURLE_OK; + } if(result) return result; diff --git a/libs/libcurl/src/progress.c b/libs/libcurl/src/progress.c index cc040a8733..4bcd615eba 100644 --- a/libs/libcurl/src/progress.c +++ b/libs/libcurl/src/progress.c @@ -241,6 +241,8 @@ void Curl_pgrsStartNow(struct Curl_easy *data) data->progress.is_t_startransfer_set = false; data->progress.ul_limit_start = data->progress.start; data->progress.dl_limit_start = data->progress.start; + data->progress.ul_limit_size = 0; + data->progress.dl_limit_size = 0; data->progress.downloaded = 0; data->progress.uploaded = 0; /* clear all bits except HIDE and HEADERS_OUT */ @@ -369,94 +371,82 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size) } } +/* returns the average speed in bytes / second */ +static curl_off_t trspeed(curl_off_t size, /* number of bytes */ + curl_off_t us) /* microseconds */ +{ + if(us < 1) + return size * 1000000; + return (curl_off_t)((long double)size/us * 1000000); +} + /* returns TRUE if it's time to show the progress meter */ static bool progress_calc(struct Curl_easy *data, struct curltime now) { - curl_off_t timespent; - curl_off_t timespent_ms; /* milliseconds */ - curl_off_t dl = data->progress.downloaded; - curl_off_t ul = data->progress.uploaded; bool timetoshow = FALSE; + struct Progress * const p = &data->progress; - /* The time spent so far (from the start) */ - data->progress.timespent = Curl_timediff_us(now, data->progress.start); - timespent = (curl_off_t)data->progress.timespent/1000000; /* seconds */ - timespent_ms = (curl_off_t)data->progress.timespent/1000; /* ms */ - - /* The average download speed this far */ - if(dl < CURL_OFF_T_MAX/1000) - data->progress.dlspeed = (dl * 1000 / (timespent_ms>0?timespent_ms:1)); - else - data->progress.dlspeed = (dl / (timespent>0?timespent:1)); - - /* The average upload speed this far */ - if(ul < CURL_OFF_T_MAX/1000) - data->progress.ulspeed = (ul * 1000 / (timespent_ms>0?timespent_ms:1)); - else - data->progress.ulspeed = (ul / (timespent>0?timespent:1)); + /* The time spent so far (from the start) in microseconds */ + p->timespent = Curl_timediff_us(now, p->start); + p->dlspeed = trspeed(p->downloaded, p->timespent); + p->ulspeed = trspeed(p->uploaded, p->timespent); /* Calculations done at most once a second, unless end is reached */ - if(data->progress.lastshow != now.tv_sec) { + if(p->lastshow != now.tv_sec) { int countindex; /* amount of seconds stored in the speeder array */ - int nowindex = data->progress.speeder_c% CURR_TIME; - data->progress.lastshow = now.tv_sec; + int nowindex = p->speeder_c% CURR_TIME; + p->lastshow = now.tv_sec; timetoshow = TRUE; /* Let's do the "current speed" thing, with the dl + ul speeds combined. Store the speed at entry 'nowindex'. */ - data->progress.speeder[ nowindex ] = - data->progress.downloaded + data->progress.uploaded; + p->speeder[ nowindex ] = p->downloaded + p->uploaded; /* remember the exact time for this moment */ - data->progress.speeder_time [ nowindex ] = now; + p->speeder_time [ nowindex ] = now; /* advance our speeder_c counter, which is increased every time we get here and we expect it to never wrap as 2^32 is a lot of seconds! */ - data->progress.speeder_c++; + p->speeder_c++; /* figure out how many index entries of data we have stored in our speeder array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of transfer. Imagine, after one second we have filled in two entries, after two seconds we've filled in three entries etc. */ - countindex = ((data->progress.speeder_c >= CURR_TIME)? - CURR_TIME:data->progress.speeder_c) - 1; + countindex = ((p->speeder_c >= CURR_TIME)? CURR_TIME:p->speeder_c) - 1; /* first of all, we don't do this if there's no counted seconds yet */ if(countindex) { int checkindex; timediff_t span_ms; + curl_off_t amount; /* Get the index position to compare with the 'nowindex' position. Get the oldest entry possible. While we have less than CURR_TIME entries, the first entry will remain the oldest. */ - checkindex = (data->progress.speeder_c >= CURR_TIME)? - data->progress.speeder_c%CURR_TIME:0; + checkindex = (p->speeder_c >= CURR_TIME)? p->speeder_c%CURR_TIME:0; /* Figure out the exact time for the time span */ - span_ms = Curl_timediff(now, data->progress.speeder_time[checkindex]); + span_ms = Curl_timediff(now, p->speeder_time[checkindex]); if(0 == span_ms) span_ms = 1; /* at least one millisecond MUST have passed */ /* Calculate the average speed the last 'span_ms' milliseconds */ - { - curl_off_t amount = data->progress.speeder[nowindex]- - data->progress.speeder[checkindex]; - - if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */) - /* the 'amount' value is bigger than would fit in 32 bits if - multiplied with 1000, so we use the double math for this */ - data->progress.current_speed = (curl_off_t) - ((double)amount/((double)span_ms/1000.0)); - else - /* the 'amount' value is small enough to fit within 32 bits even - when multiplied with 1000 */ - data->progress.current_speed = amount*CURL_OFF_T_C(1000)/span_ms; - } + amount = p->speeder[nowindex]- p->speeder[checkindex]; + + if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */) + /* the 'amount' value is bigger than would fit in 32 bits if + multiplied with 1000, so we use the double math for this */ + p->current_speed = (curl_off_t) + ((double)amount/((double)span_ms/1000.0)); + else + /* the 'amount' value is small enough to fit within 32 bits even + when multiplied with 1000 */ + p->current_speed = amount*CURL_OFF_T_C(1000)/span_ms; } else /* the first second we use the average */ - data->progress.current_speed = - data->progress.ulspeed + data->progress.dlspeed; + p->current_speed = p->ulspeed + p->dlspeed; } /* Calculations end */ return timetoshow; diff --git a/libs/libcurl/src/rtsp.c b/libs/libcurl/src/rtsp.c index 3029ff5264..007d5c50b6 100644 --- a/libs/libcurl/src/rtsp.c +++ b/libs/libcurl/src/rtsp.c @@ -109,6 +109,7 @@ const struct Curl_handler Curl_handler_rtsp = { rtsp_disconnect, /* disconnect */ rtsp_rtp_readwrite, /* readwrite */ rtsp_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTSP, /* defport */ CURLPROTO_RTSP, /* protocol */ CURLPROTO_RTSP, /* family */ @@ -680,7 +681,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, } } - if(rtp_dataleft != 0 && rtp[0] == '$') { + if(rtp_dataleft && rtp[0] == '$') { DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft, *readmore ? "(READMORE)" : "")); @@ -824,7 +825,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header) /* Copy the id substring into a new buffer */ data->set.str[STRING_RTSP_SESSION_ID] = malloc(idlen + 1); - if(data->set.str[STRING_RTSP_SESSION_ID] == NULL) + if(!data->set.str[STRING_RTSP_SESSION_ID]) return CURLE_OUT_OF_MEMORY; memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen); (data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0'; diff --git a/libs/libcurl/src/select.c b/libs/libcurl/src/select.c index d7346b195f..52dca5a2c0 100644 --- a/libs/libcurl/src/select.c +++ b/libs/libcurl/src/select.c @@ -442,7 +442,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) if(ufds[i].events & POLLPRI) ufds[i].revents |= POLLPRI; } - if(ufds[i].revents != 0) + if(ufds[i].revents) r++; } diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c index b57b7878c2..e41bb805f5 100644 --- a/libs/libcurl/src/sendf.c +++ b/libs/libcurl/src/sendf.c @@ -65,7 +65,7 @@ static size_t convert_lineends(struct Curl_easy *data, char *inPtr, *outPtr; /* sanity check */ - if((startPtr == NULL) || (size < 1)) { + if(!startPtr || (size < 1)) { return size; } @@ -309,6 +309,18 @@ CURLcode Curl_write(struct Curl_easy *data, conn = data->conn; num = (sockfd == conn->sock[SECONDARYSOCKET]); +#ifdef CURLDEBUG + { + /* Allow debug builds to override this logic to force short sends + */ + char *p = getenv("CURL_SMALLSENDS"); + if(p) { + size_t altsize = (size_t)strtoul(p, NULL, 10); + if(altsize) + len = CURLMIN(len, altsize); + } + } +#endif bytes_written = conn->send[num](data, num, mem, len, &result); *written = bytes_written; @@ -604,7 +616,7 @@ static CURLcode chop_write(struct Curl_easy *data, /* Curl_client_write() sends data to the write callback(s) The bit pattern defines to what "streams" to write to. Body and/or header. - The defines are in sendf.h of course. + The defines are in sendf.h of course. "len" is not allowed to be 0. If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the local character encoding. This is a problem and should be changed in @@ -616,9 +628,8 @@ CURLcode Curl_client_write(struct Curl_easy *data, size_t len) { struct connectdata *conn = data->conn; - if(0 == len) - len = strlen(ptr); + DEBUGASSERT(len); DEBUGASSERT(type <= 3); /* FTP data may need conversion. */ diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c index 022dd38003..fb8b86d474 100644 --- a/libs/libcurl/src/setopt.c +++ b/libs/libcurl/src/setopt.c @@ -426,6 +426,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) version_max = C_SSLVERSION_MAX_VALUE(arg); if(version < CURL_SSLVERSION_DEFAULT || + version == CURL_SSLVERSION_SSLv2 || + version == CURL_SSLVERSION_SSLv3 || version >= CURL_SSLVERSION_LAST || version_max < CURL_SSLVERSION_MAX_NONE || version_max >= CURL_SSLVERSION_MAX_LAST) @@ -752,6 +754,20 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) } data->state.cookielist = cl; /* store the list for later use */ } + else { + /* clear the list of cookie files */ + curl_slist_free_all(data->state.cookielist); + data->state.cookielist = NULL; + + if(!data->share || !data->share->cookies) { + /* throw away all existing cookies if this isn't a shared cookie + container */ + Curl_cookie_clearall(data->cookies); + Curl_cookie_cleanup(data->cookies); + } + /* disable the cookie engine */ + data->cookies = NULL; + } break; case CURLOPT_COOKIEJAR: @@ -797,7 +813,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_COOKIELIST: argptr = va_arg(param, char *); - if(argptr == NULL) + if(!argptr) break; if(strcasecompare(argptr, "ALL")) { @@ -2025,6 +2041,20 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE], va_arg(param, char *)); break; + case CURLOPT_CAINFO_BLOB: + /* + * Blob that holds CA info for SSL connection. + * Specify entire PEM of the CA certificate + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB) + result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO], + va_arg(param, struct curl_blob *)); + else +#endif + return CURLE_NOT_BUILT_IN; + + break; #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXY_CAINFO: /* @@ -2034,6 +2064,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY], va_arg(param, char *)); break; + case CURLOPT_PROXY_CAINFO_BLOB: + /* + * Blob that holds CA info for SSL connection proxy. + * Specify entire PEM of the CA certificate + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB) + result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY], + va_arg(param, struct curl_blob *)); + else +#endif + return CURLE_NOT_BUILT_IN; + break; #endif case CURLOPT_CAPATH: /* @@ -2155,7 +2198,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) else if(arg < UPLOADBUFFER_MIN) arg = UPLOADBUFFER_MIN; - data->set.upload_buffer_size = arg; + data->set.upload_buffer_size = (unsigned int)arg; Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */ break; @@ -2268,12 +2311,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_SSL_OPTIONS: arg = va_arg(param, long); - data->set.ssl.enable_beast = - (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST); data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN); data->set.ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT); data->set.ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA); + data->set.ssl.auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT); /* If a setting is added here it should also be added in dohprobe() which sets its own CURLOPT_SSL_OPTIONS based on these settings. */ break; @@ -2281,13 +2324,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXY_SSL_OPTIONS: arg = va_arg(param, long); - data->set.proxy_ssl.enable_beast = - (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.proxy_ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST); data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN); - data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA); data->set.proxy_ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT); + data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA); + data->set.proxy_ssl.auto_client_cert = + !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT); break; #endif @@ -2895,7 +2939,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.trailer_data = va_arg(param, void *); #endif break; -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS case CURLOPT_HSTSREADFUNCTION: data->set.hsts_read = va_arg(param, curl_hstsread_callback); break; diff --git a/libs/libcurl/src/setup-vms.h b/libs/libcurl/src/setup-vms.h index ba75dc295b..a6710d9076 100644 --- a/libs/libcurl/src/setup-vms.h +++ b/libs/libcurl/src/setup-vms.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -87,7 +87,7 @@ static char *vms_translate_path(const char *path) /* See if the result is in VMS format, if not, we are done */ /* Assume that this is a PATH, not just some data */ test_str = strpbrk(path, ":[<^"); - if(test_str == NULL) { + if(!test_str) { return (char *)path; } @@ -119,7 +119,7 @@ static char *vms_getenv(const char *envvar) /* first use the DECC getenv() function */ result = decc$getenv(envvar); - if(result == NULL) { + if(!result) { return result; } @@ -154,7 +154,7 @@ static struct passwd *vms_getpwuid(uid_t uid) #endif my_passwd = decc_getpwuid(uid); - if(my_passwd == NULL) { + if(!my_passwd) { return my_passwd; } diff --git a/libs/libcurl/src/share.c b/libs/libcurl/src/share.c index 4f1804dbd2..9c43c8f705 100644 --- a/libs/libcurl/src/share.c +++ b/libs/libcurl/src/share.c @@ -235,7 +235,7 @@ Curl_share_lock(struct Curl_easy *data, curl_lock_data type, { struct Curl_share *share = data->share; - if(share == NULL) + if(!share) return CURLSHE_INVALID; if(share->specifier & (1<<type)) { @@ -252,7 +252,7 @@ Curl_share_unlock(struct Curl_easy *data, curl_lock_data type) { struct Curl_share *share = data->share; - if(share == NULL) + if(!share) return CURLSHE_INVALID; if(share->specifier & (1<<type)) { diff --git a/libs/libcurl/src/sigpipe.h b/libs/libcurl/src/sigpipe.h index 430cfc6489..d6ec5fca3c 100644 --- a/libs/libcurl/src/sigpipe.h +++ b/libs/libcurl/src/sigpipe.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,7 +24,7 @@ #include "curl_setup.h" #if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && \ - (defined(USE_OPENSSL) || defined(USE_MBEDTLS)) + (defined(USE_OPENSSL) || defined(USE_MBEDTLS) || defined(USE_WOLFSSL)) #include <signal.h> struct sigpipe_ignore { diff --git a/libs/libcurl/src/smb.c b/libs/libcurl/src/smb.c index 183bc12a51..39facb267d 100644 --- a/libs/libcurl/src/smb.c +++ b/libs/libcurl/src/smb.c @@ -88,6 +88,7 @@ const struct Curl_handler Curl_handler_smb = { smb_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SMB, /* defport */ CURLPROTO_SMB, /* protocol */ CURLPROTO_SMB, /* family */ @@ -114,6 +115,7 @@ const struct Curl_handler Curl_handler_smbs = { smb_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SMBS, /* defport */ CURLPROTO_SMBS, /* protocol */ CURLPROTO_SMB, /* family */ @@ -627,9 +629,8 @@ static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg) /* Check if there is data in the transfer buffer */ if(!smbc->send_size && smbc->upload_size) { - size_t nread = smbc->upload_size > data->set.upload_buffer_size ? - data->set.upload_buffer_size : - smbc->upload_size; + size_t nread = smbc->upload_size > (size_t)data->set.upload_buffer_size ? + (size_t)data->set.upload_buffer_size : smbc->upload_size; data->req.upload_fromhere = data->state.ulbuf; result = Curl_fillreadbuffer(data, nread, &nread); if(result && result != CURLE_AGAIN) diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c index be4cd675ca..feffc05bc9 100644 --- a/libs/libcurl/src/smtp.c +++ b/libs/libcurl/src/smtp.c @@ -136,6 +136,7 @@ const struct Curl_handler Curl_handler_smtp = { smtp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SMTP, /* defport */ CURLPROTO_SMTP, /* protocol */ CURLPROTO_SMTP, /* family */ @@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_smtps = { smtp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SMTPS, /* defport */ CURLPROTO_SMTPS, /* protocol */ CURLPROTO_SMTP, /* family */ @@ -894,7 +896,7 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data, for(;;) { size_t llen; size_t wordlen; - unsigned int mechbit; + unsigned short mechbit; while(len && (*line == ' ' || *line == '\t' || @@ -1821,7 +1823,7 @@ CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread) return CURLE_OUT_OF_MEMORY; } } - DEBUGASSERT(data->set.upload_buffer_size >= (size_t)nread); + DEBUGASSERT((size_t)data->set.upload_buffer_size >= (size_t)nread); /* Have we already sent part of the EOB? */ eob_sent = smtp->eob; diff --git a/libs/libcurl/src/socks.c b/libs/libcurl/src/socks.c index d1c2a2ed14..5cde4a46a1 100644 --- a/libs/libcurl/src/socks.c +++ b/libs/libcurl/src/socks.c @@ -426,7 +426,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, */ /* wrong version ? */ - if(socksreq[0] != 0) { + if(socksreq[0]) { failf(data, "SOCKS4 reply has wrong version, version should be 0."); return CURLPX_BAD_VERSION; @@ -742,7 +742,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, return CURLPX_OK; } /* ignore the first (VER) byte */ - else if(socksreq[1] != 0) { /* status */ + else if(socksreq[1]) { /* status */ failf(data, "User was rejected by the SOCKS5 server (%d %d).", socksreq[0], socksreq[1]); return CURLPX_USER_REJECTED; @@ -927,7 +927,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, "SOCKS5 reply has wrong version, version should be 5."); return CURLPX_BAD_VERSION; } - else if(socksreq[1] != 0) { /* Anything besides 0 is an error */ + else if(socksreq[1]) { /* Anything besides 0 is an error */ CURLproxycode rc = CURLPX_REPLY_UNASSIGNED; int code = socksreq[1]; failf(data, "Can't complete SOCKS5 connection to %s. (%d)", diff --git a/libs/libcurl/src/socks_gssapi.c b/libs/libcurl/src/socks_gssapi.c index 3ab786d0bd..10b942a984 100644 --- a/libs/libcurl/src/socks_gssapi.c +++ b/libs/libcurl/src/socks_gssapi.c @@ -195,7 +195,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - if(gss_send_token.length != 0) { + if(gss_send_token.length) { socksreq[0] = 1; /* GSS-API subnegotiation version */ socksreq[1] = 1; /* authentication message type */ us_length = htons((short)gss_send_token.length); diff --git a/libs/libcurl/src/socks_sspi.c b/libs/libcurl/src/socks_sspi.c index b343538f0c..813c6be574 100644 --- a/libs/libcurl/src/socks_sspi.c +++ b/libs/libcurl/src/socks_sspi.c @@ -198,7 +198,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - if(sspi_send_token.cbBuffer != 0) { + if(sspi_send_token.cbBuffer) { socksreq[0] = 1; /* GSS-API subnegotiation version */ socksreq[1] = 1; /* authentication message type */ us_length = htons((short)sspi_send_token.cbBuffer); diff --git a/libs/libcurl/src/splay.c b/libs/libcurl/src/splay.c index 98baf5d871..a94e2c85e9 100644 --- a/libs/libcurl/src/splay.c +++ b/libs/libcurl/src/splay.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1997 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1997 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -42,7 +42,7 @@ struct Curl_tree *Curl_splay(struct curltime i, { struct Curl_tree N, *l, *r, *y; - if(t == NULL) + if(!t) return t; N.smaller = N.larger = NULL; l = r = &N; @@ -50,14 +50,14 @@ struct Curl_tree *Curl_splay(struct curltime i, for(;;) { long comp = compare(i, t->key); if(comp < 0) { - if(t->smaller == NULL) + if(!t->smaller) break; if(compare(i, t->smaller->key) < 0) { y = t->smaller; /* rotate smaller */ t->smaller = y->larger; y->larger = t; t = y; - if(t->smaller == NULL) + if(!t->smaller) break; } r->smaller = t; /* link smaller */ @@ -65,14 +65,14 @@ struct Curl_tree *Curl_splay(struct curltime i, t = t->smaller; } else if(comp > 0) { - if(t->larger == NULL) + if(!t->larger) break; if(compare(i, t->larger->key) > 0) { y = t->larger; /* rotate larger */ t->larger = y->smaller; y->smaller = t; t = y; - if(t->larger == NULL) + if(!t->larger) break; } l->larger = t; /* link larger */ @@ -104,7 +104,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i, (time_t)-1, (unsigned int)-1 }; /* will *NEVER* appear */ - if(node == NULL) + if(!node) return t; if(t != NULL) { @@ -125,7 +125,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i, } } - if(t == NULL) { + if(!t) { node->smaller = node->larger = NULL; } else if(compare(i, t->key) < 0) { @@ -262,7 +262,7 @@ int Curl_splayremove(struct Curl_tree *t, } else { /* Remove the root node */ - if(t->smaller == NULL) + if(!t->smaller) x = t->larger; else { x = Curl_splay(removenode->key, t->smaller); diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c index 3862aabd6f..5298a0d76c 100644 --- a/libs/libcurl/src/strerror.c +++ b/libs/libcurl/src/strerror.c @@ -320,9 +320,12 @@ curl_easy_strerror(CURLcode error) case CURLE_QUIC_CONNECT_ERROR: return "QUIC connection error"; - case CURLE_PROXY: + case CURLE_PROXY: return "proxy handshake error"; + case CURLE_SSL_CLIENTCERT: + return "SSL Client Certificate required"; + /* error codes not used by current libcurl */ case CURLE_OBSOLETE20: case CURLE_OBSOLETE24: diff --git a/libs/libcurl/src/system_win32.c b/libs/libcurl/src/system_win32.c index 2132f43ef7..2939fd0d74 100644 --- a/libs/libcurl/src/system_win32.c +++ b/libs/libcurl/src/system_win32.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>. + * Copyright (C) 2016 - 2021, Steve Holme, <steve_holme@hotmail.com>. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -58,7 +58,7 @@ CURLcode Curl_win32_init(long flags) wVersionRequested = MAKEWORD(2, 2); res = WSAStartup(wVersionRequested, &wsaData); - if(res != 0) + if(res) /* Tell the user that we couldn't find a usable */ /* winsock.dll. */ return CURLE_FAILED_INIT; diff --git a/libs/libcurl/src/telnet.c b/libs/libcurl/src/telnet.c index f96a4cb4c5..fdd137fb0c 100644 --- a/libs/libcurl/src/telnet.c +++ b/libs/libcurl/src/telnet.c @@ -185,6 +185,7 @@ const struct Curl_handler Curl_handler_telnet = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_TELNET, /* defport */ CURLPROTO_TELNET, /* protocol */ CURLPROTO_TELNET, /* family */ @@ -921,7 +922,7 @@ static void suboption(struct Curl_easy *data) size_t tmplen = (strlen(v->data) + 1); /* Add the variable only if it fits */ if(len + tmplen < (int)sizeof(temp)-6) { - if(sscanf(v->data, "%127[^,],%127s", varname, varval)) { + if(sscanf(v->data, "%127[^,],%127s", varname, varval) == 2) { msnprintf((char *)&temp[len], sizeof(temp) - len, "%c%s%c%s", CURL_NEW_ENV_VAR, varname, CURL_NEW_ENV_VALUE, varval); diff --git a/libs/libcurl/src/tftp.c b/libs/libcurl/src/tftp.c index 76d3ff4515..11150af361 100644 --- a/libs/libcurl/src/tftp.c +++ b/libs/libcurl/src/tftp.c @@ -182,6 +182,7 @@ const struct Curl_handler Curl_handler_tftp = { tftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_TFTP, /* defport */ CURLPROTO_TFTP, /* protocol */ CURLPROTO_TFTP, /* family */ @@ -319,7 +320,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state, const char *option, *value; tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value); - if(tmp == NULL) { + if(!tmp) { failf(data, "Malformed ACK packet, rejecting"); return CURLE_TFTP_ILLEGAL; } @@ -776,7 +777,7 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event) return result; state->sbytes += (int)cb; state->data->req.upload_fromhere += cb; - } while(state->sbytes < state->blksize && cb != 0); + } while(state->sbytes < state->blksize && cb); sbytes = sendto(state->sockfd, (void *) state->spacket.data, 4 + state->sbytes, SEND_4TH_ARG, @@ -1256,7 +1257,7 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done) failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer))); state->event = TFTP_EVENT_ERROR; } - else if(rc != 0) { + else if(rc) { result = tftp_receive_packet(data); if(result) return result; diff --git a/libs/libcurl/src/timeval.c b/libs/libcurl/src/timeval.c index 8523dad400..ca98fe50e5 100644 --- a/libs/libcurl/src/timeval.c +++ b/libs/libcurl/src/timeval.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -78,14 +78,16 @@ struct curltime Curl_now(void) ** code compiles but fails during run-time if clock_gettime() is ** called on unsupported OS version. */ -#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1) +#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ + (HAVE_BUILTIN_AVAILABLE == 1) bool have_clock_gettime = FALSE; if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) have_clock_gettime = TRUE; #endif if( -#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1) +#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ + (HAVE_BUILTIN_AVAILABLE == 1) have_clock_gettime && #endif (0 == clock_gettime(CLOCK_MONOTONIC, &tsnow))) { diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c index 56ad5e612e..bca4e548fa 100644 --- a/libs/libcurl/src/transfer.c +++ b/libs/libcurl/src/transfer.c @@ -99,6 +99,8 @@ char *Curl_checkheaders(const struct Curl_easy *data, { struct curl_slist *head; size_t thislen = strlen(thisheader); + DEBUGASSERT(thislen); + DEBUGASSERT(thisheader[thislen-1] != ':'); for(head = data->set.headers; head; head = head->next) { if(strncasecompare(head->data, thisheader, thislen) && @@ -495,11 +497,13 @@ static int data_pending(const struct Curl_easy *data) return Curl_quic_data_pending(data); #endif + if(conn->handler->protocol&PROTO_FAMILY_FTP) + return Curl_ssl_data_pending(conn, SECONDARYSOCKET); + /* in the case of libssh2, we can never be really sure that we have emptied its internal buffers so we MUST always try until we get EAGAIN back */ return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) || #if defined(USE_NGHTTP2) - Curl_ssl_data_pending(conn, FIRSTSOCKET) || /* For HTTP/2, we may read up everything including response body with header fields in Curl_http_readwrite_headers. If no content-length is provided, curl waits for the connection @@ -507,10 +511,9 @@ static int data_pending(const struct Curl_easy *data) TRUE. The thing is if we read everything, then http2_recv won't be called and we cannot signal the HTTP/2 stream has closed. As a workaround, we return nonzero here to call http2_recv. */ - ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20); -#else - Curl_ssl_data_pending(conn, FIRSTSOCKET); + ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20) || #endif + Curl_ssl_data_pending(conn, FIRSTSOCKET); } /* @@ -830,7 +833,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, Make sure that ALL_CONTENT_ENCODINGS contains all the encodings handled here. */ if(data->set.http_ce_skip || !k->writer_stack) { - if(!k->ignorebody) { + if(!k->ignorebody && nread) { #ifndef CURL_DISABLE_POP3 if(conn->handler->protocol & PROTO_FAMILY_POP3) result = Curl_pop3_write(data, k->str, nread); @@ -840,7 +843,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, nread); } } - else if(!k->ignorebody) + else if(!k->ignorebody && nread) result = Curl_unencode_write(data, k->writer_stack, k->str, nread); } k->badheader = HEADER_NORMAL; /* taken care of now */ diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c index 19fcfb842c..1ee38af0d5 100644 --- a/libs/libcurl/src/url.c +++ b/libs/libcurl/src/url.c @@ -292,6 +292,7 @@ static const struct Curl_handler Curl_handler_dummy = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ 0, /* defport */ 0, /* protocol */ 0, /* family */ @@ -923,14 +924,14 @@ socks_proxy_info_matches(const struct proxy_info *data, /* the user information is case-sensitive or at least it is not defined as case-insensitive see https://tools.ietf.org/html/rfc3986#section-3.2.1 */ - if((data->user == NULL) != (needle->user == NULL)) + if(!data->user != !needle->user) return FALSE; /* curl_strequal does a case insentive comparison, so do not use it here! */ if(data->user && needle->user && strcmp(data->user, needle->user) != 0) return FALSE; - if((data->passwd == NULL) != (needle->passwd == NULL)) + if(!data->passwd != !needle->passwd) return FALSE; /* curl_strequal does a case insentive comparison, so do not use it here! */ if(data->passwd && @@ -1171,6 +1172,12 @@ ConnectionExists(struct Curl_easy *data, continue; } + if(data->set.ipver != CURL_IPRESOLVE_WHATEVER + && data->set.ipver != check->ip_version) { + /* skip because the connection is not via the requested IP version */ + continue; + } + if(bundle->multiuse == BUNDLE_MULTIPLEX) multiplexed = CONN_INUSE(check); @@ -1315,6 +1322,13 @@ ConnectionExists(struct Curl_easy *data, } } + /* If multiplexing isn't enabled on the h2 connection and h1 is + explicitly requested, handle it: */ + if((needle->handler->protocol & PROTO_FAMILY_HTTP) && + (check->httpversion >= 20) && + (data->state.httpwant < CURL_HTTP_VERSION_2_0)) + continue; + if((needle->handler->flags&PROTOPT_SSL) #ifndef CURL_DISABLE_PROXY || !needle->bits.httpproxy || needle->bits.tunnel_proxy @@ -1944,7 +1958,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS if(data->hsts && strcasecompare("http", data->state.up.scheme)) { if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) { char *url; @@ -3556,7 +3570,7 @@ static CURLcode create_conn(struct Curl_easy *data, #ifdef USE_UNIX_SOCKETS if(data->set.str[STRING_UNIX_SOCKET_PATH]) { conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); - if(conn->unix_domain_socket == NULL) { + if(!conn->unix_domain_socket) { result = CURLE_OUT_OF_MEMORY; goto out; } @@ -3731,6 +3745,7 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.ssl.primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT]; + data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO]; data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES]; #ifndef CURL_DISABLE_PROXY @@ -3746,6 +3761,8 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.proxy_ssl.primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]; data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY]; + data->set.proxy_ssl.primary.ca_info_blob = + data->set.blobs[BLOB_CAINFO_PROXY]; data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY]; data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY]; data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c index e3a788221b..6483208ec7 100644 --- a/libs/libcurl/src/urlapi.c +++ b/libs/libcurl/src/urlapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -667,6 +667,94 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname) #define HOSTNAME_END(x) (((x) == '/') || ((x) == '?') || ((x) == '#')) +/* + * Handle partial IPv4 numerical addresses and different bases, like + * '16843009', '0x7f', '0x7f.1' '0177.1.1.1' etc. + * + * If the given input string is syntactically wrong or any part for example is + * too big, this function returns FALSE and doesn't create any output. + * + * Output the "normalized" version of that input string in plain quad decimal + * integers and return TRUE. + */ +static bool ipv4_normalize(const char *hostname, char *outp, size_t olen) +{ + bool done = FALSE; + int n = 0; + const char *c = hostname; + unsigned long parts[4] = {0, 0, 0, 0}; + + while(!done) { + char *endp; + unsigned long l; + if((*c < '0') || (*c > '9')) + /* most importantly this doesn't allow a leading plus or minus */ + return FALSE; + l = strtoul(c, &endp, 0); + + /* overflow or nothing parsed at all */ + if(((l == ULONG_MAX) && (errno == ERANGE)) || (endp == c)) + return FALSE; + +#if SIZEOF_LONG > 4 + /* a value larger than 32 bits */ + if(l > UINT_MAX) + return FALSE; +#endif + + parts[n] = l; + c = endp; + + switch (*c) { + case '.' : + if(n == 3) + return FALSE; + n++; + c++; + break; + + case '\0': + done = TRUE; + break; + + default: + return FALSE; + } + } + + /* this is deemed a valid IPv4 numerical address */ + + switch(n) { + case 0: /* a -- 32 bits */ + msnprintf(outp, olen, "%u.%u.%u.%u", + parts[0] >> 24, (parts[0] >> 16) & 0xff, + (parts[0] >> 8) & 0xff, parts[0] & 0xff); + break; + case 1: /* a.b -- 8.24 bits */ + if((parts[0] > 0xff) || (parts[1] > 0xffffff)) + return FALSE; + msnprintf(outp, olen, "%u.%u.%u.%u", + parts[0], (parts[1] >> 16) & 0xff, + (parts[1] >> 8) & 0xff, parts[1] & 0xff); + break; + case 2: /* a.b.c -- 8.8.16 bits */ + if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xffff)) + return FALSE; + msnprintf(outp, olen, "%u.%u.%u.%u", + parts[0], parts[1], (parts[2] >> 8) & 0xff, + parts[2] & 0xff); + break; + case 3: /* a.b.c.d -- 8.8.8.8 bits */ + if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff) || + (parts[3] > 0xff)) + return FALSE; + msnprintf(outp, olen, "%u.%u.%u.%u", + parts[0], parts[1], parts[2], parts[3]); + break; + } + return TRUE; +} + static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) { char *path; @@ -899,6 +987,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) } if(hostname) { + char normalized_ipv4[sizeof("255.255.255.255") + 1]; /* * Parse the login details and strip them out of the host name. */ @@ -922,7 +1011,10 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) return result; } - u->host = strdup(hostname); + if(ipv4_normalize(hostname, normalized_ipv4, sizeof(normalized_ipv4))) + u->host = strdup(normalized_ipv4); + else + u->host = strdup(hostname); if(!u->host) return CURLUE_OUT_OF_MEMORY; diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h index fec875652c..fb905c36c5 100644 --- a/libs/libcurl/src/urldata.h +++ b/libs/libcurl/src/urldata.h @@ -253,6 +253,7 @@ struct ssl_primary_config { char *cipher_list13; /* list of TLS 1.3 cipher suites to use */ char *pinned_key; struct curl_blob *cert_blob; + struct curl_blob *ca_info_blob; char *curves; /* list of curves to use */ BIT(verifypeer); /* set TRUE if this is desired */ BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */ @@ -286,6 +287,8 @@ struct ssl_config_data { BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation list errors */ BIT(native_ca_store); /* use the native ca store of operating system */ + BIT(auto_client_cert); /* automatically locate and use a client + certificate for authentication (Schannel) */ }; struct ssl_general_config { @@ -791,12 +794,16 @@ struct Curl_handler { struct connectdata *conn, unsigned int checks_to_perform); + /* attach() attaches this transfer to this connection */ + void (*attach)(struct Curl_easy *data, struct connectdata *conn); + 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 non-TLS name of the protocol this is */ unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */ + }; #define PROTOPT_NONE 0 /* nothing extra */ @@ -855,25 +862,8 @@ struct proxy_info { char *passwd; /* proxy password string, allocated */ }; -/* struct for HTTP CONNECT state data */ -struct http_connect_state { - struct dynbuf rcvbuf; - enum keeponval { - KEEPON_DONE, - KEEPON_CONNECT, - KEEPON_IGNORE - } keepon; - curl_off_t cl; /* size of content to read and ignore */ - enum { - TUNNEL_INIT, /* init/default/no tunnel state */ - TUNNEL_CONNECT, /* CONNECT has been sent off */ - TUNNEL_COMPLETE /* CONNECT response received completely */ - } tunnel_state; - BIT(chunked_encoding); - BIT(close_connection); -}; - struct ldapconninfo; +struct http_connect_state; /* for the (SOCKS) connect state machine */ enum connect_t { @@ -1602,6 +1592,8 @@ enum dupblob { BLOB_KEY_PROXY, BLOB_SSL_ISSUERCERT, BLOB_SSL_ISSUERCERT_PROXY, + BLOB_CAINFO, + BLOB_CAINFO_PROXY, BLOB_LAST }; @@ -1664,7 +1656,7 @@ struct UserDefined { curl_conv_callback convtonetwork; /* function to convert from UTF-8 encoding: */ curl_conv_callback convfromutf8; -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS curl_hstsread_callback hsts_read; void *hsts_read_userp; curl_hstswrite_callback hsts_write; @@ -1717,8 +1709,8 @@ struct UserDefined { struct ssl_general_config general_ssl; /* general user defined SSL stuff */ 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 */ + unsigned int 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 */ unsigned char ipver; /* the CURL_IPRESOLVE_* defines in the public header @@ -1926,7 +1918,7 @@ struct Curl_easy { NOTE that the 'cookie' field in the UserDefined struct defines if the "engine" is to be used or not. */ -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS struct hsts *hsts; #endif #ifndef CURL_DISABLE_ALTSVC diff --git a/libs/libcurl/src/vauth/cleartext.c b/libs/libcurl/src/vauth/cleartext.c index 620dba03ef..d17e16f108 100644 --- a/libs/libcurl/src/vauth/cleartext.c +++ b/libs/libcurl/src/vauth/cleartext.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,7 +32,6 @@ #include "urldata.h" #include "vauth/vauth.h" -#include "curl_base64.h" #include "curl_md5.h" #include "warnless.h" #include "strtok.h" @@ -51,31 +50,24 @@ * * Parameters: * - * data [in] - The session handle. * authzid [in] - The authorization identity. * authcid [in] - The authentication identity. * passwd [in] - The password. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, - const char *authzid, +CURLcode Curl_auth_create_plain_message(const char *authzid, const char *authcid, const char *passwd, - char **outptr, size_t *outlen) + struct bufref *out) { - CURLcode result; char *plainauth; + size_t plainlen; size_t zlen; size_t clen; size_t plen; - size_t plainlen; - *outlen = 0; - *outptr = NULL; zlen = (authzid == NULL ? 0 : strlen(authzid)); clen = strlen(authcid); plen = strlen(passwd); @@ -86,23 +78,20 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; plainlen = zlen + clen + plen + 2; - plainauth = malloc(plainlen); + plainauth = malloc(plainlen + 1); if(!plainauth) return CURLE_OUT_OF_MEMORY; /* Calculate the reply */ - if(zlen != 0) + if(zlen) memcpy(plainauth, authzid, zlen); plainauth[zlen] = '\0'; memcpy(plainauth + zlen + 1, authcid, clen); plainauth[zlen + clen + 1] = '\0'; memcpy(plainauth + zlen + clen + 2, passwd, plen); - - /* Base64 encode the reply */ - result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen); - free(plainauth); - - return result; + plainauth[plainlen] = '\0'; + Curl_bufref_set(out, plainauth, plainlen, curl_free); + return CURLE_OK; } /* @@ -113,34 +102,15 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, * * Parameters: * - * data [in] - The session handle. * valuep [in] - The user name or user's password. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_login_message(struct Curl_easy *data, - const char *valuep, char **outptr, - size_t *outlen) +CURLcode Curl_auth_create_login_message(const char *valuep, struct bufref *out) { - size_t vlen = strlen(valuep); - - if(!vlen) { - /* Calculate an empty reply */ - *outptr = strdup("="); - if(*outptr) { - *outlen = (size_t) 1; - return CURLE_OK; - } - - *outlen = 0; - return CURLE_OUT_OF_MEMORY; - } - - /* Base64 encode the value */ - return Curl_base64_encode(data, valuep, vlen, outptr, outlen); + Curl_bufref_set(out, valuep, strlen(valuep), NULL); + return CURLE_OK; } /* @@ -151,20 +121,16 @@ CURLcode Curl_auth_create_login_message(struct Curl_easy *data, * * Parameters: * - * data [in] - The session handle. * user [in] - The user name. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_external_message(struct Curl_easy *data, - const char *user, char **outptr, - size_t *outlen) +CURLcode Curl_auth_create_external_message(const char *user, + struct bufref *out) { /* This is the same formatting as the login message */ - return Curl_auth_create_login_message(data, user, outptr, outlen); + return Curl_auth_create_login_message(user, out); } #endif /* if no users */ diff --git a/libs/libcurl/src/vauth/cram.c b/libs/libcurl/src/vauth/cram.c index 1a376259a8..9ddb0ac379 100644 --- a/libs/libcurl/src/vauth/cram.c +++ b/libs/libcurl/src/vauth/cram.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,7 +30,6 @@ #include "urldata.h" #include "vauth/vauth.h" -#include "curl_base64.h" #include "curl_hmac.h" #include "curl_md5.h" #include "warnless.h" @@ -40,69 +39,31 @@ #include "curl_memory.h" #include "memdebug.h" -/* - * Curl_auth_decode_cram_md5_message() - * - * This is used to decode an already encoded CRAM-MD5 challenge message. - * - * Parameters: - * - * chlg64 [in] - The base64 encoded challenge message. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. - * - * Returns CURLE_OK on success. - */ -CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, - size_t *outlen) -{ - CURLcode result = CURLE_OK; - size_t chlg64len = strlen(chlg64); - - *outptr = NULL; - *outlen = 0; - - /* Decode the challenge if necessary */ - if(chlg64len && *chlg64 != '=') - result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen); - - return result; -} /* * Curl_auth_create_cram_md5_message() * - * This is used to generate an already encoded CRAM-MD5 response message ready - * for sending to the recipient. + * This is used to generate a CRAM-MD5 response message ready for sending to + * the recipient. * * Parameters: * - * data [in] - The session handle. * chlg [in] - The challenge. * userp [in] - The user name. * passwdp [in] - The user's password. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, - const char *chlg, +CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg, const char *userp, const char *passwdp, - char **outptr, size_t *outlen) + struct bufref *out) { - CURLcode result = CURLE_OK; - size_t chlglen = 0; struct HMAC_context *ctxt; unsigned char digest[MD5_DIGEST_LEN]; char *response; - if(chlg) - chlglen = strlen(chlg); - /* Compute the digest using the password as the key */ ctxt = Curl_HMAC_init(Curl_HMAC_MD5, (const unsigned char *) passwdp, @@ -111,9 +72,9 @@ CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; /* Update the digest with the given challenge */ - if(chlglen > 0) - Curl_HMAC_update(ctxt, (const unsigned char *) chlg, - curlx_uztoui(chlglen)); + if(Curl_bufref_len(chlg)) + Curl_HMAC_update(ctxt, Curl_bufref_ptr(chlg), + curlx_uztoui(Curl_bufref_len(chlg))); /* Finalise the digest */ Curl_HMAC_final(ctxt, digest); @@ -127,12 +88,8 @@ CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, if(!response) return CURLE_OUT_OF_MEMORY; - /* Base64 encode the response */ - result = Curl_base64_encode(data, response, 0, outptr, outlen); - - free(response); - - return result; + Curl_bufref_set(out, response, strlen(response), curl_free); + return CURLE_OK; } #endif /* !CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libs/libcurl/src/vauth/digest.c b/libs/libcurl/src/vauth/digest.c index 559852fcba..a04ffab6fb 100644 --- a/libs/libcurl/src/vauth/digest.c +++ b/libs/libcurl/src/vauth/digest.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -254,7 +254,7 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value) * * Parameters: * - * chlg64 [in] - The base64 encoded challenge message. + * chlgref [in] - The challenge message. * nonce [in/out] - The buffer where the nonce will be stored. * nlen [in] - The length of the nonce buffer. * realm [in/out] - The buffer where the realm will be stored. @@ -266,55 +266,35 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value) * * Returns CURLE_OK on success. */ -static CURLcode auth_decode_digest_md5_message(const char *chlg64, +static CURLcode auth_decode_digest_md5_message(const struct bufref *chlgref, char *nonce, size_t nlen, char *realm, size_t rlen, char *alg, size_t alen, char *qop, size_t qlen) { - CURLcode result = CURLE_OK; - unsigned char *chlg = NULL; - size_t chlglen = 0; - size_t chlg64len = strlen(chlg64); - - /* Decode the base-64 encoded challenge message */ - if(chlg64len && *chlg64 != '=') { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } + const char *chlg = (const char *) Curl_bufref_ptr(chlgref); /* Ensure we have a valid challenge message */ - if(!chlg) + if(!Curl_bufref_len(chlgref)) return CURLE_BAD_CONTENT_ENCODING; /* Retrieve nonce string from the challenge */ - if(!auth_digest_get_key_value((char *) chlg, "nonce=\"", nonce, nlen, - '\"')) { - free(chlg); + if(!auth_digest_get_key_value(chlg, "nonce=\"", nonce, nlen, '\"')) return CURLE_BAD_CONTENT_ENCODING; - } /* Retrieve realm string from the challenge */ - if(!auth_digest_get_key_value((char *) chlg, "realm=\"", realm, rlen, - '\"')) { + if(!auth_digest_get_key_value(chlg, "realm=\"", realm, rlen, '\"')) { /* Challenge does not have a realm, set empty string [RFC2831] page 6 */ strcpy(realm, ""); } /* Retrieve algorithm string from the challenge */ - if(!auth_digest_get_key_value((char *) chlg, "algorithm=", alg, alen, ',')) { - free(chlg); + if(!auth_digest_get_key_value(chlg, "algorithm=", alg, alen, ',')) return CURLE_BAD_CONTENT_ENCODING; - } /* Retrieve qop-options string from the challenge */ - if(!auth_digest_get_key_value((char *) chlg, "qop=\"", qop, qlen, '\"')) { - free(chlg); + if(!auth_digest_get_key_value(chlg, "qop=\"", qop, qlen, '\"')) return CURLE_BAD_CONTENT_ENCODING; - } - - free(chlg); return CURLE_OK; } @@ -342,22 +322,20 @@ bool Curl_auth_is_digest_supported(void) * Parameters: * * data [in] - The session handle. - * chlg64 [in] - The base64 encoded challenge message. + * chlg [in] - The challenge message. * userp [in] - The user name. * passwdp [in] - The user's password. * service [in] - The service type such as http, smtp, pop or imap. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, const char *userp, const char *passwdp, const char *service, - char **outptr, size_t *outlen) + struct bufref *out) { size_t i; struct MD5_context *ctxt; @@ -378,9 +356,10 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, char *spn = NULL; /* Decode the challenge message */ - CURLcode result = auth_decode_digest_md5_message(chlg64, nonce, - sizeof(nonce), realm, - sizeof(realm), algorithm, + CURLcode result = auth_decode_digest_md5_message(chlg, + nonce, sizeof(nonce), + realm, sizeof(realm), + algorithm, sizeof(algorithm), qop_options, sizeof(qop_options)); @@ -500,11 +479,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(!response) return CURLE_OUT_OF_MEMORY; - /* Base64 encode the response */ - result = Curl_base64_encode(data, response, 0, outptr, outlen); - - free(response); - + /* Return the response. */ + Curl_bufref_set(out, response, strlen(response), curl_free); return result; } diff --git a/libs/libcurl/src/vauth/digest_sspi.c b/libs/libcurl/src/vauth/digest_sspi.c index dad947a37e..2602ffd363 100644 --- a/libs/libcurl/src/vauth/digest_sspi.c +++ b/libs/libcurl/src/vauth/digest_sspi.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2014 - 2016, Steve Holme, <steve_holme@hotmail.com>. - * Copyright (C) 2015 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2015 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,7 +32,6 @@ #include "vauth/vauth.h" #include "vauth/digest.h" #include "urldata.h" -#include "curl_base64.h" #include "warnless.h" #include "curl_multibyte.h" #include "sendf.h" @@ -79,28 +78,24 @@ bool Curl_auth_is_digest_supported(void) * Parameters: * * data [in] - The session handle. - * chlg64 [in] - The base64 encoded challenge message. + * chlg [in] - The challenge message. * userp [in] - The user name in the format User or Domain\User. * passwdp [in] - The user's password. * service [in] - The service type such as http, smtp, pop or imap. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, const char *userp, const char *passwdp, const char *service, - char **outptr, size_t *outlen) + struct bufref *out) { CURLcode result = CURLE_OK; TCHAR *spn = NULL; - size_t chlglen = 0; size_t token_max = 0; - unsigned char *input_token = NULL; unsigned char *output_token = NULL; CredHandle credentials; CtxtHandle context; @@ -115,17 +110,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, unsigned long attrs; TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ - /* Decode the base-64 encoded challenge message */ - if(strlen(chlg64) && *chlg64 != '=') { - result = Curl_base64_decode(chlg64, &input_token, &chlglen); - if(result) - return result; - } - /* Ensure we have a valid challenge message */ - if(!input_token) { + if(!Curl_bufref_len(chlg)) { infof(data, "DIGEST-MD5 handshake failure (empty challenge message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } @@ -133,8 +120,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), &SecurityPackage); if(status != SEC_E_OK) { - free(input_token); - failf(data, "SSPI: couldn't get auth info"); return CURLE_AUTH_ERROR; } @@ -146,18 +131,13 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, /* Allocate our response buffer */ output_token = malloc(token_max); - if(!output_token) { - free(input_token); - + if(!output_token) return CURLE_OUT_OF_MEMORY; - } /* Generate our SPN */ spn = Curl_auth_build_spn(service, data->conn->host.name, NULL); if(!spn) { free(output_token); - free(input_token); - return CURLE_OUT_OF_MEMORY; } @@ -167,8 +147,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(result) { free(spn); free(output_token); - free(input_token); - return result; } @@ -190,8 +168,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, Curl_sspi_free_identity(p_identity); free(spn); free(output_token); - free(input_token); - return CURLE_LOGIN_DENIED; } @@ -200,8 +176,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, chlg_desc.cBuffers = 1; chlg_desc.pBuffers = &chlg_buf; chlg_buf.BufferType = SECBUFFER_TOKEN; - chlg_buf.pvBuffer = input_token; - chlg_buf.cbBuffer = curlx_uztoul(chlglen); + chlg_buf.pvBuffer = (void *) Curl_bufref_ptr(chlg); + chlg_buf.cbBuffer = curlx_uztoul(Curl_bufref_len(chlg)); /* Setup the response "output" security buffer */ resp_desc.ulVersion = SECBUFFER_VERSION; @@ -227,7 +203,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, Curl_sspi_free_identity(p_identity); free(spn); free(output_token); - free(input_token); if(status == SEC_E_INSUFFICIENT_MEMORY) return CURLE_OUT_OF_MEMORY; @@ -238,9 +213,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, return CURLE_AUTH_ERROR; } - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) output_token, resp_buf.cbBuffer, - outptr, outlen); + /* Return the response. */ + Curl_bufref_set(out, output_token, resp_buf.cbBuffer, curl_free); /* Free our handles */ s_pSecFn->DeleteSecurityContext(&context); @@ -252,12 +226,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, /* Free the SPN */ free(spn); - /* Free the response buffer */ - free(output_token); - - /* Free the decoded challenge message */ - free(input_token); - return result; } diff --git a/libs/libcurl/src/vauth/gsasl.c b/libs/libcurl/src/vauth/gsasl.c index 02a06357f0..40fef53c93 100644 --- a/libs/libcurl/src/vauth/gsasl.c +++ b/libs/libcurl/src/vauth/gsasl.c @@ -28,7 +28,6 @@ #include <curl/curl.h> -#include "curl_base64.h" #include "vauth/vauth.h" #include "urldata.h" #include "sendf.h" @@ -94,42 +93,24 @@ CURLcode Curl_auth_gsasl_start(struct Curl_easy *data, } CURLcode Curl_auth_gsasl_token(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, struct gsasldata *gsasl, - char **outptr, size_t *outlen) + struct bufref *out) { - unsigned char *chlg = NULL; - size_t chlglen = 0; - CURLcode result = CURLE_OK; int res; char *response; - - if(chlg64) { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } + size_t outlen; res = gsasl_step(gsasl->client, - (const char *)chlg, chlglen, &response, outlen); + (const char *) Curl_bufref_ptr(chlg), Curl_bufref_len(chlg), + &response, &outlen); if(res != GSASL_OK && res != GSASL_NEEDS_MORE) { - if(chlg64) - free(chlg); failf(data, "GSASL step: %s\n", gsasl_strerror(res)); return CURLE_BAD_CONTENT_ENCODING; } - if(*outlen > 0) { - result = Curl_base64_encode(data, response, 0, outptr, outlen); - gsasl_free(response); - } - else { - *outptr = strdup(""); - if(!*outptr) - result = CURLE_OUT_OF_MEMORY; - } - - return result; + Curl_bufref_set(out, response, outlen, gsasl_free); + return CURLE_OK; } void Curl_auth_gsasl_cleanup(struct gsasldata *gsasl) diff --git a/libs/libcurl/src/vauth/krb5_gssapi.c b/libs/libcurl/src/vauth/krb5_gssapi.c index 0412815e93..b43982b9bd 100644 --- a/libs/libcurl/src/vauth/krb5_gssapi.c +++ b/libs/libcurl/src/vauth/krb5_gssapi.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2014 - 2019, Steve Holme, <steve_holme@hotmail.com>. - * Copyright (C) 2015 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2015 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,7 +32,6 @@ #include "vauth/vauth.h" #include "curl_sasl.h" #include "urldata.h" -#include "curl_base64.h" #include "curl_gssapi.h" #include "sendf.h" #include "curl_printf.h" @@ -70,12 +69,9 @@ bool Curl_auth_is_gssapi_supported(void) * host [in[ - The host name. * mutual_auth [in] - Flag specifying whether or not mutual authentication * is enabled. - * chlg64 [in] - Pointer to the optional base64 encoded challenge - * message. + * chlg [in] - Optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -85,13 +81,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, const char *service, const char *host, const bool mutual_auth, - const char *chlg64, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, size_t *outlen) + struct bufref *out) { CURLcode result = CURLE_OK; - size_t chlglen = 0; - unsigned char *chlg = NULL; OM_uint32 major_status; OM_uint32 minor_status; OM_uint32 unused_status; @@ -127,24 +121,13 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, free(spn); } - if(chlg64 && *chlg64) { - /* Decode the base-64 encoded challenge message */ - if(*chlg64 != '=') { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } - - /* Ensure we have a valid challenge message */ - if(!chlg) { + if(chlg) { + if(!Curl_bufref_len(chlg)) { infof(data, "GSSAPI handshake failure (empty challenge message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } - - /* Setup the challenge "input" security buffer */ - input_token.value = chlg; - input_token.length = chlglen; + input_token.value = (void *) Curl_bufref_ptr(chlg); + input_token.length = Curl_bufref_len(chlg); } major_status = Curl_gss_init_sec_context(data, @@ -158,9 +141,6 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, mutual_auth, NULL); - /* Free the decoded challenge as it is not required anymore */ - free(input_token.value); - if(GSS_ERROR(major_status)) { if(output_token.value) gss_release_buffer(&unused_status, &output_token); @@ -172,17 +152,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, } if(output_token.value && output_token.length) { - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) output_token.value, - output_token.length, outptr, outlen); - + result = Curl_bufref_memdup(out, output_token.value, output_token.length); gss_release_buffer(&unused_status, &output_token); } - else if(mutual_auth) { - *outptr = strdup(""); - if(!*outptr) - result = CURLE_OUT_OF_MEMORY; - } + else + Curl_bufref_set(out, mutual_auth? "": NULL, 0, NULL); return result; } @@ -196,24 +170,19 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, * Parameters: * * data [in] - The session handle. - * chlg64 [in] - Pointer to the optional base64 encoded challenge message. + * chlg [in] - Optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, - size_t *outlen) + struct bufref *out) { CURLcode result = CURLE_OK; - size_t chlglen = 0; size_t messagelen = 0; - unsigned char *chlg = NULL; unsigned char *message = NULL; OM_uint32 major_status; OM_uint32 minor_status; @@ -228,17 +197,9 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, gss_name_t username = GSS_C_NO_NAME; gss_buffer_desc username_token; - /* Decode the base-64 encoded input message */ - if(strlen(chlg64) && *chlg64 != '=') { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } - /* Ensure we have a valid challenge message */ - if(!chlg) { + if(!Curl_bufref_len(chlg)) { infof(data, "GSSAPI handshake failure (empty security message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } @@ -249,9 +210,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_inquire_context() failed: ", major_status, minor_status); - - free(chlg); - return CURLE_AUTH_ERROR; } @@ -261,15 +219,12 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_display_name() failed: ", major_status, minor_status); - - free(chlg); - return CURLE_AUTH_ERROR; } /* Setup the challenge "input" security buffer */ - input_token.value = chlg; - input_token.length = chlglen; + input_token.value = (void *) Curl_bufref_ptr(chlg); + input_token.length = Curl_bufref_len(chlg); /* Decrypt the inbound challenge and obtain the qop */ major_status = gss_unwrap(&minor_status, krb5->context, &input_token, @@ -277,27 +232,20 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_unwrap() failed: ", major_status, minor_status); - gss_release_buffer(&unused_status, &username_token); - free(chlg); - return CURLE_BAD_CONTENT_ENCODING; } /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ if(output_token.length != 4) { infof(data, "GSSAPI handshake failure (invalid security data)\n"); - gss_release_buffer(&unused_status, &username_token); - free(chlg); - return CURLE_BAD_CONTENT_ENCODING; } /* Copy the data out and free the challenge as it is not required anymore */ memcpy(&indata, output_token.value, 4); gss_release_buffer(&unused_status, &output_token); - free(chlg); /* Extract the security layer */ sec_layer = indata & 0x000000FF; @@ -305,7 +253,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, infof(data, "GSSAPI handshake failure (invalid security layer)\n"); gss_release_buffer(&unused_status, &username_token); - return CURLE_BAD_CONTENT_ENCODING; } @@ -323,7 +270,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, message = malloc(messagelen); if(!message) { gss_release_buffer(&unused_status, &username_token); - return CURLE_OUT_OF_MEMORY; } @@ -352,16 +298,12 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_wrap() failed: ", major_status, minor_status); - free(message); - return CURLE_AUTH_ERROR; } - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) output_token.value, - output_token.length, outptr, outlen); - + /* Return the response. */ + result = Curl_bufref_memdup(out, output_token.value, output_token.length); /* Free the output buffer */ gss_release_buffer(&unused_status, &output_token); diff --git a/libs/libcurl/src/vauth/krb5_sspi.c b/libs/libcurl/src/vauth/krb5_sspi.c index b2d1635343..e110644225 100644 --- a/libs/libcurl/src/vauth/krb5_sspi.c +++ b/libs/libcurl/src/vauth/krb5_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2014 - 2020, Steve Holme, <steve_holme@hotmail.com>. + * Copyright (C) 2014 - 2021, Steve Holme, <steve_holme@hotmail.com>. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,7 +30,6 @@ #include "vauth/vauth.h" #include "urldata.h" -#include "curl_base64.h" #include "warnless.h" #include "curl_multibyte.h" #include "sendf.h" @@ -81,11 +80,9 @@ bool Curl_auth_is_gssapi_supported(void) * host [in] - The host name. * mutual_auth [in] - Flag specifying whether or not mutual authentication * is enabled. - * chlg64 [in] - The optional base64 encoded challenge message. + * chlg [in] - Optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -95,13 +92,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, const char *service, const char *host, const bool mutual_auth, - const char *chlg64, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, size_t *outlen) + struct bufref *out) { CURLcode result = CURLE_OK; - size_t chlglen = 0; - unsigned char *chlg = NULL; CtxtHandle context; PSecPkgInfo SecurityPackage; SecBuffer chlg_buf; @@ -176,18 +171,9 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } - if(chlg64 && *chlg64) { - /* Decode the base-64 encoded challenge message */ - if(*chlg64 != '=') { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } - - /* Ensure we have a valid challenge message */ - if(!chlg) { + if(chlg) { + if(!Curl_bufref_len(chlg)) { infof(data, "GSSAPI handshake failure (empty challenge message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } @@ -196,8 +182,8 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, chlg_desc.cBuffers = 1; chlg_desc.pBuffers = &chlg_buf; chlg_buf.BufferType = SECBUFFER_TOKEN; - chlg_buf.pvBuffer = chlg; - chlg_buf.cbBuffer = curlx_uztoul(chlglen); + chlg_buf.pvBuffer = (void *) Curl_bufref_ptr(chlg); + chlg_buf.cbBuffer = curlx_uztoul(Curl_bufref_len(chlg)); } /* Setup the response "output" security buffer */ @@ -220,16 +206,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, &resp_desc, &attrs, &expiry); - /* Free the decoded challenge as it is not required anymore */ - free(chlg); - - if(status == SEC_E_INSUFFICIENT_MEMORY) { + if(status == SEC_E_INSUFFICIENT_MEMORY) return CURLE_OUT_OF_MEMORY; - } - if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) return CURLE_AUTH_ERROR; - } if(memcmp(&context, krb5->context, sizeof(context))) { s_pSecFn->DeleteSecurityContext(krb5->context); @@ -238,15 +219,12 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, } if(resp_buf.cbBuffer) { - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) resp_buf.pvBuffer, - resp_buf.cbBuffer, outptr, outlen); - } - else if(mutual_auth) { - *outptr = strdup(""); - if(!*outptr) - result = CURLE_OUT_OF_MEMORY; + result = Curl_bufref_memdup(out, resp_buf.pvBuffer, resp_buf.cbBuffer); } + else if(mutual_auth) + Curl_bufref_set(out, "", 0, NULL); + else + Curl_bufref_set(out, NULL, 0, NULL); return result; } @@ -260,26 +238,20 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, * Parameters: * * data [in] - The session handle. - * chlg64 [in] - The optional base64 encoded challenge message. + * chlg [in] - The optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, - size_t *outlen) + struct bufref *out) { - CURLcode result = CURLE_OK; size_t offset = 0; - size_t chlglen = 0; size_t messagelen = 0; size_t appdatalen = 0; - unsigned char *chlg = NULL; unsigned char *trailer = NULL; unsigned char *message = NULL; unsigned char *padding = NULL; @@ -298,17 +270,9 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, SECURITY_STATUS status; char *user_name; - /* Decode the base-64 encoded input message */ - if(strlen(chlg64) && *chlg64 != '=') { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } - /* Ensure we have a valid challenge message */ - if(!chlg) { + if(!Curl_bufref_len(chlg)) { infof(data, "GSSAPI handshake failure (empty security message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } @@ -316,35 +280,31 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, status = s_pSecFn->QueryContextAttributes(krb5->context, SECPKG_ATTR_SIZES, &sizes); - if(status != SEC_E_OK) { - free(chlg); - if(status == SEC_E_INSUFFICIENT_MEMORY) - return CURLE_OUT_OF_MEMORY; + if(status == SEC_E_INSUFFICIENT_MEMORY) + return CURLE_OUT_OF_MEMORY; + if(status != SEC_E_OK) return CURLE_AUTH_ERROR; - } /* Get the fully qualified username back from the context */ status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials, SECPKG_CRED_ATTR_NAMES, &names); - if(status != SEC_E_OK) { - free(chlg); - if(status == SEC_E_INSUFFICIENT_MEMORY) - return CURLE_OUT_OF_MEMORY; + if(status == SEC_E_INSUFFICIENT_MEMORY) + return CURLE_OUT_OF_MEMORY; + if(status != SEC_E_OK) return CURLE_AUTH_ERROR; - } /* Setup the "input" security buffer */ input_desc.ulVersion = SECBUFFER_VERSION; input_desc.cBuffers = 2; input_desc.pBuffers = input_buf; input_buf[0].BufferType = SECBUFFER_STREAM; - input_buf[0].pvBuffer = chlg; - input_buf[0].cbBuffer = curlx_uztoul(chlglen); + input_buf[0].pvBuffer = (void *) Curl_bufref_ptr(chlg); + input_buf[0].cbBuffer = curlx_uztoul(Curl_bufref_len(chlg)); input_buf[1].BufferType = SECBUFFER_DATA; input_buf[1].pvBuffer = NULL; input_buf[1].cbBuffer = 0; @@ -353,31 +313,23 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop); if(status != SEC_E_OK) { infof(data, "GSSAPI handshake failure (empty security message)\n"); - - free(chlg); - return CURLE_BAD_CONTENT_ENCODING; } /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ if(input_buf[1].cbBuffer != 4) { infof(data, "GSSAPI handshake failure (invalid security data)\n"); - - free(chlg); - return CURLE_BAD_CONTENT_ENCODING; } /* Copy the data out and free the challenge as it is not required anymore */ memcpy(&indata, input_buf[1].pvBuffer, 4); s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer); - free(chlg); /* Extract the security layer */ sec_layer = indata & 0x000000FF; if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) { infof(data, "GSSAPI handshake failure (invalid security layer)\n"); - return CURLE_BAD_CONTENT_ENCODING; } @@ -479,17 +431,14 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, offset += wrap_buf[1].cbBuffer; memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer); - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) appdata, appdatalen, outptr, - outlen); - /* Free all of our local buffers */ - free(appdata); free(padding); free(message); free(trailer); - return result; + /* Return the response. */ + Curl_bufref_set(out, appdata, appdatalen, curl_free); + return CURLE_OK; } /* diff --git a/libs/libcurl/src/vauth/ntlm.c b/libs/libcurl/src/vauth/ntlm.c index 4adf49704f..47e53572cb 100644 --- a/libs/libcurl/src/vauth/ntlm.c +++ b/libs/libcurl/src/vauth/ntlm.c @@ -36,7 +36,6 @@ #include "urldata.h" #include "non-ascii.h" #include "sendf.h" -#include "curl_base64.h" #include "curl_ntlm_core.h" #include "curl_gethostname.h" #include "curl_multibyte.h" @@ -157,31 +156,31 @@ static void ntlm_print_hex(FILE *handle, const char *buf, size_t len) * Parameters: * * data [in] - The session handle. - * buffer [in] - The decoded type-2 message. - * size [in] - The input buffer size, at least 32 bytes. + * type2ref [in] - The type-2 message. * ntlm [in/out] - The NTLM data struct being used and modified. * * Returns CURLE_OK on success. */ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, - unsigned char *buffer, - size_t size, + const struct bufref *type2ref, struct ntlmdata *ntlm) { unsigned short target_info_len = 0; unsigned int target_info_offset = 0; + const unsigned char *type2 = Curl_bufref_ptr(type2ref); + size_t type2len = Curl_bufref_len(type2ref); #if defined(CURL_DISABLE_VERBOSE_STRINGS) (void) data; #endif - if(size >= 48) { - target_info_len = Curl_read16_le(&buffer[40]); - target_info_offset = Curl_read32_le(&buffer[44]); + if(type2len >= 48) { + target_info_len = Curl_read16_le(&type2[40]); + target_info_offset = Curl_read32_le(&type2[44]); if(target_info_len > 0) { - if((target_info_offset >= size) || - ((target_info_offset + target_info_len) > size) || - (target_info_offset < 48)) { + if((target_info_offset > type2len) || + (target_info_offset + target_info_len) > type2len || + target_info_offset < 48) { infof(data, "NTLM handshake failure (bad type-2 message). " "Target Info Offset Len is set incorrect by the peer\n"); return CURLE_BAD_CONTENT_ENCODING; @@ -192,7 +191,7 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, if(!ntlm->target_info) return CURLE_OUT_OF_MEMORY; - memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len); + memcpy(ntlm->target_info, &type2[target_info_offset], target_info_len); } } @@ -234,21 +233,20 @@ bool Curl_auth_is_ntlm_supported(void) /* * Curl_auth_decode_ntlm_type2_message() * - * This is used to decode an already encoded NTLM type-2 message. The message - * is first decoded from a base64 string into a raw NTLM message and checked - * for validity before the appropriate data for creating a type-3 message is - * written to the given NTLM data structure. + * This is used to decode an NTLM type-2 message. The raw NTLM message is + * checked * for validity before the appropriate data for creating a type-3 + * message is * written to the given NTLM data structure. * * Parameters: * * data [in] - The session handle. - * type2msg [in] - The base64 encoded type-2 message. + * type2ref [in] - The type-2 message. * ntlm [in/out] - The NTLM data struct being used and modified. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, - const char *type2msg, + const struct bufref *type2ref, struct ntlmdata *ntlm) { static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; @@ -270,8 +268,8 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, */ CURLcode result = CURLE_OK; - unsigned char *type2 = NULL; - size_t type2_len = 0; + const unsigned char *type2 = Curl_bufref_ptr(type2ref); + size_t type2len = Curl_bufref_len(type2ref); #if defined(NTLM_NEEDS_NSS_INIT) /* Make sure the crypto backend is initialized */ @@ -282,26 +280,12 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, (void)data; #endif - /* Decode the base-64 encoded type-2 message */ - if(strlen(type2msg) && *type2msg != '=') { - result = Curl_base64_decode(type2msg, &type2, &type2_len); - if(result) - return result; - } - - /* Ensure we have a valid type-2 message */ - if(!type2) { - infof(data, "NTLM handshake failure (empty type-2 message)\n"); - return CURLE_BAD_CONTENT_ENCODING; - } - ntlm->flags = 0; - if((type2_len < 32) || + if((type2len < 32) || (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) || (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) { /* This was not a good enough type-2 message */ - free(type2); infof(data, "NTLM handshake failure (bad type-2 message)\n"); return CURLE_BAD_CONTENT_ENCODING; } @@ -310,9 +294,8 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, memcpy(ntlm->nonce, &type2[24], 8); if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) { - result = ntlm_decode_type2_target(data, type2, type2_len, ntlm); + result = ntlm_decode_type2_target(data, type2ref, ntlm); if(result) { - free(type2); infof(data, "NTLM handshake failure (bad type-2 message)\n"); return result; } @@ -327,8 +310,6 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, fprintf(stderr, "**** Header %s\n ", header); }); - free(type2); - return result; } @@ -346,8 +327,8 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length) /* * Curl_auth_create_ntlm_type1_message() * - * This is used to generate an already encoded NTLM type-1 message ready for - * sending to the recipient using the appropriate compile time crypto API. + * This is used to generate an NTLM type-1 message ready for sending to the + * recipient using the appropriate compile time crypto API. * * Parameters: * @@ -357,9 +338,7 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length) * service [in] - The service type such as http, smtp, pop or imap. * host [in] - The host name. * ntlm [in/out] - The NTLM data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -369,7 +348,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, const char *service, const char *hostname, struct ntlmdata *ntlm, - char **outptr, size_t *outlen) + struct bufref *out) { /* NTLM type-1 message structure: @@ -387,7 +366,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, size_t size; - unsigned char ntlmbuf[NTLM_BUFSIZE]; + char *ntlmbuf; const char *host = ""; /* empty */ const char *domain = ""; /* empty */ size_t hostlen = 0; @@ -395,6 +374,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, size_t hostoff = 0; size_t domoff = hostoff + hostlen; /* This is 0: remember that host and domain are empty */ + (void)data; (void)userp; (void)passwdp; (void)service, @@ -409,38 +389,40 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, #else #define NTLM2FLAG 0 #endif - msnprintf((char *)ntlmbuf, NTLM_BUFSIZE, - NTLMSSP_SIGNATURE "%c" - "\x01%c%c%c" /* 32-bit type = 1 */ - "%c%c%c%c" /* 32-bit NTLM flag field */ - "%c%c" /* domain length */ - "%c%c" /* domain allocated space */ - "%c%c" /* domain name offset */ - "%c%c" /* 2 zeroes */ - "%c%c" /* host length */ - "%c%c" /* host allocated space */ - "%c%c" /* host name offset */ - "%c%c" /* 2 zeroes */ - "%s" /* host name */ - "%s", /* domain string */ - 0, /* trailing zero */ - 0, 0, 0, /* part of type-1 long */ - - LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | - NTLMFLAG_REQUEST_TARGET | - NTLMFLAG_NEGOTIATE_NTLM_KEY | - NTLM2FLAG | - NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), - SHORTPAIR(domlen), - SHORTPAIR(domlen), - SHORTPAIR(domoff), - 0, 0, - SHORTPAIR(hostlen), - SHORTPAIR(hostlen), - SHORTPAIR(hostoff), - 0, 0, - host, /* this is empty */ - domain /* this is empty */); + ntlmbuf = aprintf(NTLMSSP_SIGNATURE "%c" + "\x01%c%c%c" /* 32-bit type = 1 */ + "%c%c%c%c" /* 32-bit NTLM flag field */ + "%c%c" /* domain length */ + "%c%c" /* domain allocated space */ + "%c%c" /* domain name offset */ + "%c%c" /* 2 zeroes */ + "%c%c" /* host length */ + "%c%c" /* host allocated space */ + "%c%c" /* host name offset */ + "%c%c" /* 2 zeroes */ + "%s" /* host name */ + "%s", /* domain string */ + 0, /* trailing zero */ + 0, 0, 0, /* part of type-1 long */ + + LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), + SHORTPAIR(domlen), + SHORTPAIR(domlen), + SHORTPAIR(domoff), + 0, 0, + SHORTPAIR(hostlen), + SHORTPAIR(hostlen), + SHORTPAIR(hostoff), + 0, 0, + host, /* this is empty */ + domain /* this is empty */); + + if(!ntlmbuf) + return CURLE_OUT_OF_MEMORY; /* Initial packet length */ size = 32 + hostlen + domlen; @@ -467,8 +449,8 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, fprintf(stderr, "\n****\n"); }); - /* Return with binary blob encoded into base64 */ - return Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen); + Curl_bufref_set(out, ntlmbuf, size, curl_free); + return CURLE_OK; } /* @@ -483,9 +465,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, * userp [in] - The user name in the format User or Domain\User. * passwdp [in] - The user's password. * ntlm [in/out] - The NTLM data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -493,7 +473,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, const char *userp, const char *passwdp, struct ntlmdata *ntlm, - char **outptr, size_t *outlen) + struct bufref *out) { /* NTLM type-3 message structure: @@ -847,8 +827,8 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, if(result) return CURLE_CONV_FAILED; - /* Return with binary blob encoded into base64 */ - result = Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen); + /* Return the binary blob. */ + result = Curl_bufref_memdup(out, ntlmbuf, size); Curl_auth_cleanup_ntlm(ntlm); diff --git a/libs/libcurl/src/vauth/ntlm_sspi.c b/libs/libcurl/src/vauth/ntlm_sspi.c index 07dc97398e..1b1a176301 100644 --- a/libs/libcurl/src/vauth/ntlm_sspi.c +++ b/libs/libcurl/src/vauth/ntlm_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,7 +28,6 @@ #include "vauth/vauth.h" #include "urldata.h" -#include "curl_base64.h" #include "curl_ntlm_core.h" #include "warnless.h" #include "curl_multibyte.h" @@ -78,9 +77,7 @@ bool Curl_auth_is_ntlm_supported(void) * service [in] - The service type such as http, smtp, pop or imap. * host [in] - The host name. * ntlm [in/out] - The NTLM data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -90,7 +87,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, const char *service, const char *host, struct ntlmdata *ntlm, - char **outptr, size_t *outlen) + struct bufref *out) { PSecPkgInfo SecurityPackage; SecBuffer type_1_buf; @@ -181,9 +178,9 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) return CURLE_AUTH_ERROR; - /* Base64 encode the response */ - return Curl_base64_encode(data, (char *) ntlm->output_token, - type_1_buf.cbBuffer, outptr, outlen); + /* Return the response. */ + Curl_bufref_set(out, ntlm->output_token, type_1_buf.cbBuffer, NULL); + return CURLE_OK; } /* @@ -194,42 +191,34 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, * Parameters: * * data [in] - The session handle. - * type2msg [in] - The base64 encoded type-2 message. + * type2 [in] - The type-2 message. * ntlm [in/out] - The NTLM data struct being used and modified. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, - const char *type2msg, + const struct bufref *type2, struct ntlmdata *ntlm) { - CURLcode result = CURLE_OK; - unsigned char *type2 = NULL; - size_t type2_len = 0; - #if defined(CURL_DISABLE_VERBOSE_STRINGS) (void) data; #endif - /* Decode the base-64 encoded type-2 message */ - if(strlen(type2msg) && *type2msg != '=') { - result = Curl_base64_decode(type2msg, &type2, &type2_len); - if(result) - return result; - } - /* Ensure we have a valid type-2 message */ - if(!type2) { + if(!Curl_bufref_len(type2)) { infof(data, "NTLM handshake failure (empty type-2 message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } - /* Simply store the challenge for use later */ - ntlm->input_token = type2; - ntlm->input_token_len = type2_len; + /* Store the challenge for later use */ + ntlm->input_token = malloc(Curl_bufref_len(type2) + 1); + if(!ntlm->input_token) + return CURLE_OUT_OF_MEMORY; + memcpy(ntlm->input_token, Curl_bufref_ptr(type2), Curl_bufref_len(type2)); + ntlm->input_token[Curl_bufref_len(type2)] = '\0'; + ntlm->input_token_len = Curl_bufref_len(type2); - return result; + return CURLE_OK; } /* @@ -245,9 +234,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, * userp [in] - The user name in the format User or Domain\User. * passwdp [in] - The user's password. * ntlm [in/out] - The NTLM data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -255,7 +242,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, const char *userp, const char *passwdp, struct ntlmdata *ntlm, - char **outptr, size_t *outlen) + struct bufref *out) { CURLcode result = CURLE_OK; SecBuffer type_2_bufs[2]; @@ -331,12 +318,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, return CURLE_AUTH_ERROR; } - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) ntlm->output_token, - type_3_buf.cbBuffer, outptr, outlen); - + /* Return the response. */ + result = Curl_bufref_memdup(out, ntlm->output_token, type_3_buf.cbBuffer); Curl_auth_cleanup_ntlm(ntlm); - return result; } diff --git a/libs/libcurl/src/vauth/oauth2.c b/libs/libcurl/src/vauth/oauth2.c index ca5842a7c0..a5f16a0bf4 100644 --- a/libs/libcurl/src/vauth/oauth2.c +++ b/libs/libcurl/src/vauth/oauth2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -31,7 +31,6 @@ #include "urldata.h" #include "vauth/vauth.h" -#include "curl_base64.h" #include "warnless.h" #include "curl_printf.h" @@ -42,31 +41,26 @@ /* * Curl_auth_create_oauth_bearer_message() * - * This is used to generate an already encoded OAuth 2.0 message ready for - * sending to the recipient. + * This is used to generate an OAuth 2.0 message ready for sending to the + * recipient. * * Parameters: * - * data[in] - The session handle. * user[in] - The user name. * host[in] - The host name. * port[in] - The port(when not Port 80). * bearer[in] - The bearer token. - * outptr[in / out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen[out] - The length of the output message. + * out[out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, - const char *user, +CURLcode Curl_auth_create_oauth_bearer_message(const char *user, const char *host, const long port, const char *bearer, - char **outptr, size_t *outlen) + struct bufref *out) { - CURLcode result = CURLE_OK; - char *oauth = NULL; + char *oauth; /* Generate the message */ if(port == 0 || port == 80) @@ -78,49 +72,34 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, if(!oauth) return CURLE_OUT_OF_MEMORY; - /* Base64 encode the reply */ - result = Curl_base64_encode(data, oauth, strlen(oauth), outptr, outlen); - - free(oauth); - - return result; + Curl_bufref_set(out, oauth, strlen(oauth), curl_free); + return CURLE_OK; } /* * Curl_auth_create_xoauth_bearer_message() * - * This is used to generate an already encoded XOAuth 2.0 message ready for - * sending to the recipient. + * This is used to generate a XOAuth 2.0 message ready for * sending to the + * recipient. * * Parameters: * - * data[in] - The session handle. * user[in] - The user name. * bearer[in] - The bearer token. - * outptr[in / out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen[out] - The length of the output message. + * out[out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data, - const char *user, +CURLcode Curl_auth_create_xoauth_bearer_message(const char *user, const char *bearer, - char **outptr, size_t *outlen) + struct bufref *out) { - CURLcode result = CURLE_OK; - /* Generate the message */ char *xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer); if(!xoauth) return CURLE_OUT_OF_MEMORY; - /* Base64 encode the reply */ - result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen); - - free(xoauth); - - return result; + Curl_bufref_set(out, xoauth, strlen(xoauth), curl_free); + return CURLE_OK; } #endif /* disabled, no users */ - diff --git a/libs/libcurl/src/vauth/vauth.c b/libs/libcurl/src/vauth/vauth.c index 129b8f8b57..3624fb0c4a 100644 --- a/libs/libcurl/src/vauth/vauth.c +++ b/libs/libcurl/src/vauth/vauth.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2014 - 2020, Steve Holme, <steve_holme@hotmail.com>. + * Copyright (C) 2014 - 2021, Steve Holme, <steve_holme@hotmail.com>. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -72,6 +72,7 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host, { char *utf8_spn = NULL; TCHAR *tchar_spn = NULL; + TCHAR *dupe_tchar_spn = NULL; (void) realm; @@ -84,23 +85,19 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host, /* Generate our UTF8 based SPN */ utf8_spn = aprintf("%s/%s", service, host); - if(!utf8_spn) { + if(!utf8_spn) return NULL; - } - /* Allocate our TCHAR based SPN */ + /* Allocate and return a TCHAR based SPN. Since curlx_convert_UTF8_to_tchar + must be freed by curlx_unicodefree we'll dupe the result so that the + pointer this function returns can be normally free'd. */ tchar_spn = curlx_convert_UTF8_to_tchar(utf8_spn); - if(!tchar_spn) { - free(utf8_spn); - + free(utf8_spn); + if(!tchar_spn) return NULL; - } - - /* Release the UTF8 variant when operating with Unicode */ - curlx_unicodefree(utf8_spn); - - /* Return our newly allocated SPN */ - return tchar_spn; + dupe_tchar_spn = _tcsdup(tchar_spn); + curlx_unicodefree(tchar_spn); + return dupe_tchar_spn; } #endif /* USE_WINDOWS_SSPI */ diff --git a/libs/libcurl/src/vauth/vauth.h b/libs/libcurl/src/vauth/vauth.h index 03a5f8adb5..ec5b0007f5 100644 --- a/libs/libcurl/src/vauth/vauth.h +++ b/libs/libcurl/src/vauth/vauth.h @@ -24,6 +24,8 @@ #include <curl/curl.h> +#include "bufref.h" + struct Curl_easy; #if !defined(CURL_DISABLE_CRYPTO_AUTH) @@ -62,45 +64,37 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host, /* This is used to test if the user contains a Windows domain name */ bool Curl_auth_user_contains_domain(const char *user); -/* This is used to generate a base64 encoded PLAIN cleartext message */ -CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, - const char *authzid, +/* This is used to generate a PLAIN cleartext message */ +CURLcode Curl_auth_create_plain_message(const char *authzid, const char *authcid, const char *passwd, - char **outptr, size_t *outlen); + struct bufref *out); -/* This is used to generate a base64 encoded LOGIN cleartext message */ -CURLcode Curl_auth_create_login_message(struct Curl_easy *data, - const char *valuep, char **outptr, - size_t *outlen); +/* This is used to generate a LOGIN cleartext message */ +CURLcode Curl_auth_create_login_message(const char *value, + struct bufref *out); -/* This is used to generate a base64 encoded EXTERNAL cleartext message */ -CURLcode Curl_auth_create_external_message(struct Curl_easy *data, - const char *user, char **outptr, - size_t *outlen); +/* This is used to generate an EXTERNAL cleartext message */ +CURLcode Curl_auth_create_external_message(const char *user, + struct bufref *out); #if !defined(CURL_DISABLE_CRYPTO_AUTH) -/* This is used to decode a CRAM-MD5 challenge message */ -CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, - size_t *outlen); - /* This is used to generate a CRAM-MD5 response message */ -CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, - const char *chlg, +CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg, const char *userp, const char *passwdp, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to evaluate if DIGEST is supported */ bool Curl_auth_is_digest_supported(void); /* This is used to generate a base64 encoded DIGEST-MD5 response message */ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, const char *userp, const char *passwdp, const char *service, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to decode a HTTP DIGEST challenge message */ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, @@ -132,9 +126,9 @@ CURLcode Curl_auth_gsasl_start(struct Curl_easy *data, /* This is used to process and generate a new SASL token */ CURLcode Curl_auth_gsasl_token(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, struct gsasldata *gsasl, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to clean up the gsasl specific data */ void Curl_auth_gsasl_cleanup(struct gsasldata *digest); @@ -151,12 +145,11 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, const char *service, const char *host, struct ntlmdata *ntlm, - char **outptr, - size_t *outlen); + struct bufref *out); /* This is used to decode a base64 encoded NTLM type-2 message */ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, - const char *type2msg, + const struct bufref *type2, struct ntlmdata *ntlm); /* This is used to generate a base64 encoded NTLM type-3 message */ @@ -164,25 +157,23 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, const char *userp, const char *passwdp, struct ntlmdata *ntlm, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to clean up the NTLM specific data */ void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm); #endif /* USE_NTLM */ /* This is used to generate a base64 encoded OAuth 2.0 message */ -CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, - const char *user, +CURLcode Curl_auth_create_oauth_bearer_message(const char *user, const char *host, const long port, const char *bearer, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to generate a base64 encoded XOAuth 2.0 message */ -CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data, - const char *user, +CURLcode Curl_auth_create_xoauth_bearer_message(const char *user, const char *bearer, - char **outptr, size_t *outlen); + struct bufref *out); #if defined(USE_KERBEROS5) /* This is used to evaluate if GSSAPI (Kerberos V5) is supported */ @@ -196,17 +187,16 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, const char *service, const char *host, const bool mutual, - const char *chlg64, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security token message */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, - const char *input, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, - size_t *outlen); + struct bufref *out); /* This is used to clean up the GSSAPI specific data */ void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5); diff --git a/libs/libcurl/src/version.c b/libs/libcurl/src/version.c index b33f2fe83b..b67b9a4660 100644 --- a/libs/libcurl/src/version.c +++ b/libs/libcurl/src/version.c @@ -66,6 +66,14 @@ #include <zstd.h> #endif +#ifdef USE_GSASL +#include <gsasl.h> +#endif + +#ifdef USE_OPENLDAP +#include <ldap.h> +#endif + #ifdef HAVE_BROTLI static size_t brotli_version(char *buf, size_t bufsz) { @@ -100,7 +108,7 @@ static size_t zstd_version(char *buf, size_t bufsz) * zeros in the data. */ -#define VERSION_PARTS 16 /* number of substrings we can concatenate */ +#define VERSION_PARTS 17 /* number of substrings we can concatenate */ char *curl_version(void) { @@ -150,6 +158,9 @@ char *curl_version(void) #ifdef USE_GSASL char gsasl_buf[30]; #endif +#ifdef USE_OPENLDAP + char ldap_buf[30]; +#endif int i = 0; int j; @@ -243,6 +254,24 @@ char *curl_version(void) gsasl_check_version(NULL)); src[i++] = gsasl_buf; #endif +#ifdef USE_OPENLDAP + { + LDAPAPIInfo api; + api.ldapai_info_version = LDAP_API_INFO_VERSION; + + if(ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) == LDAP_OPT_SUCCESS) { + unsigned int patch = api.ldapai_vendor_version % 100; + unsigned int major = api.ldapai_vendor_version / 10000; + unsigned int minor = + ((api.ldapai_vendor_version - major * 10000) - patch) / 100; + msnprintf(ldap_buf, sizeof(ldap_buf), "%s/%u.%u.%u", + api.ldapai_vendor_name, major, minor, patch); + src[i++] = ldap_buf; + ldap_memfree(api.ldapai_vendor_name); + ber_memvfree((void **)api.ldapai_extensions); + } + } +#endif DEBUGASSERT(i <= VERSION_PARTS); @@ -436,7 +465,7 @@ static curl_version_info_data version_info = { #ifndef CURL_DISABLE_ALTSVC | CURL_VERSION_ALTSVC #endif -#if defined(USE_HSTS) +#ifndef CURL_DISABLE_HSTS | CURL_VERSION_HSTS #endif #if defined(USE_GSASL) @@ -469,7 +498,8 @@ static curl_version_info_data version_info = { #endif 0, /* zstd_ver_num */ NULL, /* zstd version */ - NULL /* Hyper version */ + NULL, /* Hyper version */ + NULL /* gsasl version */ }; curl_version_info_data *curl_version_info(CURLversion stamp) @@ -573,6 +603,12 @@ curl_version_info_data *curl_version_info(CURLversion stamp) } #endif +#ifdef USE_GSASL + { + version_info.gsasl_version = gsasl_check_version(NULL); + } +#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 3d64519987..7f076759b8 100644 --- a/libs/libcurl/src/vquic/ngtcp2.c +++ b/libs/libcurl/src/vquic/ngtcp2.c @@ -226,7 +226,7 @@ static int write_client_handshake(struct quicsocket *qs, int rv; crypto_data = &qs->crypto_data[level]; - if(crypto_data->buf == NULL) { + if(!crypto_data->buf) { crypto_data->buf = malloc(4096); if(!crypto_data->buf) return 0; @@ -603,7 +603,7 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags, static int cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, - uint64_t offset, size_t datalen, void *user_data, + uint64_t offset, uint64_t datalen, void *user_data, void *stream_user_data) { struct quicsocket *qs = (struct quicsocket *)user_data; @@ -615,7 +615,7 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; rv = nghttp3_conn_add_ack_offset(qs->h3conn, stream_id, datalen); - if(rv != 0) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -634,7 +634,7 @@ 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) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -653,7 +653,7 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id); - if(rv != 0) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -682,7 +682,7 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; rv = nghttp3_conn_unblock_stream(qs->h3conn, stream_id); - if(rv != 0) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -934,6 +934,7 @@ static const struct Curl_handler Curl_handler_http3 = { ng_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ng_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTP, /* defport */ CURLPROTO_HTTPS, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -1309,7 +1310,7 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id, if(stream->h3out->used == 0) { int rv = nghttp3_conn_resume_stream(conn, stream_id); - if(rv != 0) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } } @@ -1545,7 +1546,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem, } /* :authority must come before non-pseudo header fields */ - if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) { + if(authority_idx && authority_idx != AUTHORITY_DST_IDX) { nghttp3_nv authority = nva[authority_idx]; for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) { nva[i] = nva[i - 1]; @@ -1741,7 +1742,7 @@ static CURLcode ng_process_ingress(struct Curl_easy *data, remote_addrlen); rv = ngtcp2_conn_read_pkt(qs->qconn, &path, &pi, buf, recvd, ts); - if(rv != 0) { + if(rv) { /* TODO Send CONNECTION_CLOSE if possible */ return CURLE_RECV_ERROR; } @@ -1785,7 +1786,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, } rv = ngtcp2_conn_handle_expiry(qs->qconn, ts); - if(rv != 0) { + if(rv) { failf(data, "ngtcp2_conn_handle_expiry returned error: %s", ngtcp2_strerror(rv)); return CURLE_SEND_ERROR; @@ -1821,7 +1822,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, outlen == NGTCP2_ERR_STREAM_SHUT_WR) { assert(ndatalen == -1); rv = nghttp3_conn_block_stream(qs->h3conn, stream_id); - if(rv != 0) { + if(rv) { failf(data, "nghttp3_conn_block_stream returned error: %s\n", nghttp3_strerror(rv)); return CURLE_SEND_ERROR; @@ -1831,7 +1832,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, else if(outlen == NGTCP2_ERR_WRITE_MORE) { assert(ndatalen >= 0); rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen); - if(rv != 0) { + if(rv) { failf(data, "nghttp3_conn_add_write_offset returned error: %s\n", nghttp3_strerror(rv)); return CURLE_SEND_ERROR; @@ -1847,7 +1848,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, } else if(ndatalen >= 0) { rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen); - if(rv != 0) { + if(rv) { failf(data, "nghttp3_conn_add_write_offset returned error: %s\n", nghttp3_strerror(rv)); return CURLE_SEND_ERROR; diff --git a/libs/libcurl/src/vquic/quiche.c b/libs/libcurl/src/vquic/quiche.c index a3870749b5..b62d88437a 100644 --- a/libs/libcurl/src/vquic/quiche.c +++ b/libs/libcurl/src/vquic/quiche.c @@ -157,6 +157,7 @@ static const struct Curl_handler Curl_handler_http3 = { quiche_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ quiche_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTP, /* defport */ CURLPROTO_HTTPS, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -225,7 +226,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, quiche_config_log_keys(qs->cfg); qs->conn = quiche_connect(conn->host.name, (const uint8_t *) qs->scid, - sizeof(qs->scid), qs->cfg); + sizeof(qs->scid), addr, addrlen, qs->cfg); if(!qs->conn) { failf(data, "can't create quiche connection"); return CURLE_OUT_OF_MEMORY; @@ -359,6 +360,9 @@ static CURLcode process_ingress(struct Curl_easy *data, int sockfd, ssize_t recvd; uint8_t *buf = (uint8_t *)data->state.buffer; size_t bufsize = data->set.buffer_size; + struct sockaddr_storage from; + socklen_t from_len; + quiche_recv_info recv_info; DEBUGASSERT(qs->conn); @@ -366,17 +370,24 @@ static CURLcode process_ingress(struct Curl_easy *data, int sockfd, quiche_conn_on_timeout(qs->conn); do { - recvd = recv(sockfd, buf, bufsize, 0); + from_len = sizeof(from); + + recvd = recvfrom(sockfd, buf, bufsize, 0, + (struct sockaddr *)&from, &from_len); + if((recvd < 0) && ((SOCKERRNO == EAGAIN) || (SOCKERRNO == EWOULDBLOCK))) break; if(recvd < 0) { - failf(data, "quiche: recv() unexpectedly returned %zd " + failf(data, "quiche: recvfrom() unexpectedly returned %zd " "(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd); return CURLE_RECV_ERROR; } - recvd = quiche_conn_recv(qs->conn, buf, recvd); + recv_info.from = (struct sockaddr *) &from; + recv_info.from_len = from_len; + + recvd = quiche_conn_recv(qs->conn, buf, recvd, &recv_info); if(recvd == QUICHE_ERR_DONE) break; @@ -399,9 +410,10 @@ static CURLcode flush_egress(struct Curl_easy *data, int sockfd, ssize_t sent; uint8_t out[1200]; int64_t timeout_ns; + quiche_send_info send_info; do { - sent = quiche_conn_send(qs->conn, out, sizeof(out)); + sent = quiche_conn_send(qs->conn, out, sizeof(out), &send_info); if(sent == QUICHE_ERR_DONE) break; @@ -410,9 +422,10 @@ static CURLcode flush_egress(struct Curl_easy *data, int sockfd, return CURLE_SEND_ERROR; } - sent = send(sockfd, out, sent, 0); + sent = sendto(sockfd, out, sent, 0, + (struct sockaddr *)&send_info.to, send_info.to_len); if(sent < 0) { - failf(data, "send() returned %zd", sent); + failf(data, "sendto() returned %zd", sent); return CURLE_SEND_ERROR; } } while(1); @@ -750,7 +763,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem, } /* :authority must come before non-pseudo header fields */ - if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) { + if(authority_idx && authority_idx != AUTHORITY_DST_IDX) { quiche_h3_header authority = nva[authority_idx]; for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) { nva[i] = nva[i - 1]; diff --git a/libs/libcurl/src/vssh/libssh.c b/libs/libcurl/src/vssh/libssh.c index 4644f4cb96..d146d15fdf 100644 --- a/libs/libcurl/src/vssh/libssh.c +++ b/libs/libcurl/src/vssh/libssh.c @@ -159,6 +159,7 @@ const struct Curl_handler Curl_handler_scp = { scp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SSH, /* defport */ CURLPROTO_SCP, /* protocol */ CURLPROTO_SCP, /* family */ @@ -185,6 +186,7 @@ const struct Curl_handler Curl_handler_sftp = { sftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SSH, /* defport */ CURLPROTO_SFTP, /* protocol */ CURLPROTO_SFTP, /* family */ @@ -549,49 +551,48 @@ cleanup: return rc; } -#define MOVE_TO_ERROR_STATE(_r) { \ - state(data, SSH_SESSION_DISCONNECT); \ - sshc->actualcode = _r; \ - rc = SSH_ERROR; \ - break; \ -} +#define MOVE_TO_ERROR_STATE(_r) do { \ + state(data, SSH_SESSION_DISCONNECT); \ + sshc->actualcode = _r; \ + rc = SSH_ERROR; \ + } while(0) -#define MOVE_TO_SFTP_CLOSE_STATE() { \ - state(data, SSH_SFTP_CLOSE); \ - sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \ - rc = SSH_ERROR; \ - break; \ -} +#define MOVE_TO_SFTP_CLOSE_STATE() do { \ + state(data, SSH_SFTP_CLOSE); \ + sshc->actualcode = \ + sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \ + rc = SSH_ERROR; \ + } while(0) -#define MOVE_TO_LAST_AUTH \ - if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \ - rc = SSH_OK; \ - state(data, SSH_AUTH_PASS_INIT); \ - break; \ - } \ - else { \ - MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \ - } +#define MOVE_TO_LAST_AUTH do { \ + if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \ + rc = SSH_OK; \ + state(data, SSH_AUTH_PASS_INIT); \ + } \ + else { \ + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \ + } \ + } while(0) -#define MOVE_TO_TERTIARY_AUTH \ - if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \ - rc = SSH_OK; \ - state(data, SSH_AUTH_KEY_INIT); \ - break; \ - } \ - else { \ - MOVE_TO_LAST_AUTH; \ - } +#define MOVE_TO_TERTIARY_AUTH do { \ + if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \ + rc = SSH_OK; \ + state(data, SSH_AUTH_KEY_INIT); \ + } \ + else { \ + MOVE_TO_LAST_AUTH; \ + } \ + } while(0) -#define MOVE_TO_SECONDARY_AUTH \ - if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \ - rc = SSH_OK; \ - state(data, SSH_AUTH_GSSAPI); \ - break; \ - } \ - else { \ - MOVE_TO_TERTIARY_AUTH; \ - } +#define MOVE_TO_SECONDARY_AUTH do { \ + if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \ + rc = SSH_OK; \ + state(data, SSH_AUTH_GSSAPI); \ + } \ + else { \ + MOVE_TO_TERTIARY_AUTH; \ + } \ + } while(0) static int myssh_auth_interactive(struct connectdata *conn) @@ -629,7 +630,7 @@ restart: rc = SSH_OK; else if(rc == SSH_AUTH_INFO) { nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session); - if(nprompts != 0) + if(nprompts) return SSH_ERROR; sshc->kbd_state = 2; @@ -704,6 +705,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(rc != SSH_OK) { failf(data, "Failure establishing ssh session"); MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT); + break; } state(data, SSH_HOSTKEY); @@ -714,6 +716,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) rc = myssh_is_known(data); if(rc != SSH_OK) { MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION); + break; } state(data, SSH_AUTHLIST); @@ -735,6 +738,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } else if(rc == SSH_AUTH_ERROR) { MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + break; } sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL); @@ -753,6 +757,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } else { /* unsupported authentication method */ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + break; } break; @@ -760,6 +765,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_AUTH_PKEY_INIT: if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) { MOVE_TO_SECONDARY_AUTH; + break; } /* Two choices, (1) private key was given on CMD, @@ -775,6 +781,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(rc != SSH_OK) { MOVE_TO_SECONDARY_AUTH; + break; } } @@ -833,6 +840,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_AUTH_GSSAPI: if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) { MOVE_TO_TERTIARY_AUTH; + break; } rc = ssh_userauth_gssapi(sshc->ssh_session); @@ -879,6 +887,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) { /* Host key authentication is intentionally not implemented */ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + break; } state(data, SSH_AUTH_PASS); /* FALLTHROUGH */ @@ -951,8 +960,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) * Get the "home" directory */ sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, "."); - if(sshc->homedir == NULL) { + if(!sshc->homedir) { MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); + break; } data->state.most_recent_ftp_entrypath = sshc->homedir; @@ -1025,7 +1035,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_SETSTAT: rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2, sshc->quote_attrs); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Attempt to set SFTP stats failed: %s", @@ -1044,7 +1054,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_SYMLINK: rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2, sshc->quote_path1); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "symlink command failed: %s", @@ -1060,7 +1070,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_MKDIR: rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1, (mode_t)data->set.new_directory_perms); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); failf(data, "mkdir command failed: %s", ssh_get_error(sshc->ssh_session)); @@ -1075,7 +1085,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_RENAME: rc = sftp_rename(sshc->sftp_session, sshc->quote_path1, sshc->quote_path2); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "rename command failed: %s", @@ -1090,7 +1100,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_RMDIR: rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); failf(data, "rmdir command failed: %s", ssh_get_error(sshc->ssh_session)); @@ -1104,7 +1114,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_UNLINK: rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); failf(data, "rm command failed: %s", ssh_get_error(sshc->ssh_session)); @@ -1179,7 +1189,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) sftp_attributes attrs; attrs = sftp_stat(sshc->sftp_session, protop->path); - if(attrs != 0) { + if(attrs) { data->info.filetime = attrs->mtime; sftp_attributes_free(attrs); } @@ -1203,16 +1213,17 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) { int flags; - if(data->state.resume_from != 0) { + if(data->state.resume_from) { sftp_attributes attrs; if(data->state.resume_from < 0) { attrs = sftp_stat(sshc->sftp_session, protop->path); - if(attrs != 0) { + if(attrs) { curl_off_t size = attrs->size; if(size < 0) { failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME); + break; } data->state.resume_from = attrs->size; @@ -1254,6 +1265,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } else { MOVE_TO_SFTP_CLOSE_STATE(); + break; } } @@ -1292,8 +1304,11 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) CURL_READFUNC_ABORT return code still aborts */ failf(data, "Failed to read data"); MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST); + break; } } while(passed < data->state.resume_from); + if(rc) + break; } /* now, decrease the size of the read */ @@ -1304,8 +1319,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } rc = sftp_seek64(sshc->sftp_file, data->state.resume_from); - if(rc != 0) { + if(rc) { MOVE_TO_SFTP_CLOSE_STATE(); + break; } } if(data->state.infilesize > 0) { @@ -1375,6 +1391,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) (err != SSH_FX_FAILURE) && (err != SSH_FX_PERMISSION_DENIED)) { MOVE_TO_SFTP_CLOSE_STATE(); + break; } rc = 0; /* clear rc and continue */ } @@ -1398,6 +1415,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) failf(data, "Could not open directory for reading: %s", ssh_get_error(sshc->ssh_session)); MOVE_TO_SFTP_CLOSE_STATE(); + break; } state(data, SSH_SFTP_READDIR); break; @@ -1417,7 +1435,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) char *tmpLine; tmpLine = aprintf("%s\n", sshc->readdir_filename); - if(tmpLine == NULL) { + if(!tmpLine) { state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; @@ -1456,7 +1474,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) sshc->readdir_linkPath = aprintf("%s%s", protop->path, sshc->readdir_filename); - if(sshc->readdir_linkPath == NULL) { + if(!sshc->readdir_linkPath) { state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; @@ -1491,12 +1509,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) failf(data, "Could not read symlink for reading: %s", ssh_get_error(sshc->ssh_session)); MOVE_TO_SFTP_CLOSE_STATE(); + break; } - if(sshc->readdir_link_attrs->name == NULL) { + if(!sshc->readdir_link_attrs->name) { sshc->readdir_tmp = sftp_readlink(sshc->sftp_session, sshc->readdir_linkPath); - if(sshc->readdir_filename == NULL) + if(!sshc->readdir_filename) sshc->readdir_len = 0; else sshc->readdir_len = strlen(sshc->readdir_tmp); @@ -1586,6 +1605,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) ssh_get_error(sshc->ssh_session)); MOVE_TO_SFTP_CLOSE_STATE(); + break; } state(data, SSH_SFTP_DOWNLOAD_STAT); @@ -1661,8 +1681,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } rc = sftp_seek64(sshc->sftp_file, from); - if(rc != 0) { + if(rc) { MOVE_TO_SFTP_CLOSE_STATE(); + break; } } data->req.size = size; @@ -1699,8 +1720,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) size - data->state.resume_from); rc = sftp_seek64(sshc->sftp_file, data->state.resume_from); - if(rc != 0) { + if(rc) { MOVE_TO_SFTP_CLOSE_STATE(); + break; } } } @@ -1795,6 +1817,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) failf(data, "SCP requires a known file size for upload"); sshc->actualcode = CURLE_UPLOAD_FAILED; MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + break; } sshc->scp_session = @@ -1822,6 +1845,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) err_msg = ssh_get_error(sshc->ssh_session); failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + break; } rc = ssh_scp_push_file(sshc->scp_session, protop->path, @@ -1831,6 +1855,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) err_msg = ssh_get_error(sshc->ssh_session); failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + break; } /* upload data */ @@ -1859,6 +1884,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) err_msg = ssh_get_error(sshc->ssh_session); failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); + break; } state(data, SSH_SCP_DOWNLOAD); /* FALLTHROUGH */ @@ -2163,7 +2189,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done) ssh = &conn->proto.sshc; ssh->ssh_session = ssh_new(); - if(ssh->ssh_session == NULL) { + if(!ssh->ssh_session) { failf(data, "Failure initialising ssh session"); return CURLE_FAILED_INIT; } @@ -2661,7 +2687,7 @@ static void sftp_quote(struct Curl_easy *data) * command with a space so we can check for it unconditionally */ cp = strchr(cmd, ' '); - if(cp == NULL) { + if(!cp) { failf(data, "Syntax error in SFTP command. Supply parameter(s)!"); state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; @@ -2810,7 +2836,7 @@ static void sftp_quote_stat(struct Curl_easy *data) if(sshc->quote_attrs) sftp_attributes_free(sshc->quote_attrs); sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2); - if(sshc->quote_attrs == NULL) { + if(!sshc->quote_attrs) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Attempt to get SFTP stats failed: %d", diff --git a/libs/libcurl/src/vssh/libssh2.c b/libs/libcurl/src/vssh/libssh2.c index 9d188d0582..8a6345b948 100644 --- a/libs/libcurl/src/vssh/libssh2.c +++ b/libs/libcurl/src/vssh/libssh2.c @@ -121,6 +121,7 @@ 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); +static void ssh_attach(struct Curl_easy *data, struct connectdata *conn); /* * SCP protocol handler. @@ -142,6 +143,7 @@ const struct Curl_handler Curl_handler_scp = { scp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ssh_attach, PORT_SSH, /* defport */ CURLPROTO_SCP, /* protocol */ CURLPROTO_SCP, /* family */ @@ -170,6 +172,7 @@ const struct Curl_handler Curl_handler_sftp = { sftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ssh_attach, PORT_SSH, /* defport */ CURLPROTO_SFTP, /* protocol */ CURLPROTO_SFTP, /* family */ @@ -956,7 +959,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) out_of_memory = TRUE; } - if(out_of_memory || sshc->rsa == NULL) { + if(out_of_memory || !sshc->rsa) { Curl_safefree(sshc->rsa); Curl_safefree(sshc->rsa_pub); state(data, SSH_SESSION_FREE); @@ -1359,7 +1362,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) * command with a space so we can check for it unconditionally */ cp = strchr(cmd, ' '); - if(cp == NULL) { + if(!cp) { failf(data, "Syntax error command '%s'. Missing parameter!", cmd); state(data, SSH_SFTP_CLOSE); @@ -1534,7 +1537,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { /* get those attributes */ + if(rc && !sshc->acceptfail) { /* get those attributes */ sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1633,7 +1636,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1656,7 +1659,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1677,7 +1680,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "mkdir command failed: %s", @@ -1702,7 +1705,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1722,7 +1725,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "rmdir command failed: %s", @@ -1741,7 +1744,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr)); @@ -1764,7 +1767,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "statvfs command failed: %s", @@ -1857,7 +1860,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) * same name as the last directory in the path. */ - if(data->state.resume_from != 0) { + if(data->state.resume_from) { LIBSSH2_SFTP_ATTRIBUTES attrs; if(data->state.resume_from < 0) { rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, @@ -2931,7 +2934,7 @@ static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done) static CURLcode ssh_block_statemach(struct Curl_easy *data, struct connectdata *conn, - bool duringconnect) + bool disconnect) { struct ssh_conn *sshc = &conn->proto.sshc; CURLcode result = CURLE_OK; @@ -2945,17 +2948,19 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data, if(result) break; - if(Curl_pgrsUpdate(data)) - return CURLE_ABORTED_BY_CALLBACK; + if(!disconnect) { + if(Curl_pgrsUpdate(data)) + return CURLE_ABORTED_BY_CALLBACK; - result = Curl_speedcheck(data, now); - if(result) - break; + result = Curl_speedcheck(data, now); + if(result) + break; - left = Curl_timeleft(data, NULL, duringconnect); - if(left < 0) { - failf(data, "Operation timed out"); - return CURLE_OPERATION_TIMEDOUT; + left = Curl_timeleft(data, NULL, FALSE); + if(left < 0) { + failf(data, "Operation timed out"); + return CURLE_OPERATION_TIMEDOUT; + } } if(block) { @@ -3054,17 +3059,15 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) #ifdef CURL_LIBSSH2_DEBUG curl_socket_t sock; #endif - struct SSHPROTO *sshp = data->req.p.ssh; struct ssh_conn *sshc; CURLcode result; struct connectdata *conn = data->conn; /* initialize per-handle data if not already */ - if(!sshp) { + if(!data->req.p.ssh) { 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 @@ -3086,7 +3089,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc, my_libssh2_free, my_libssh2_realloc, data); - if(sshc->ssh_session == NULL) { + if(!sshc->ssh_session) { failf(data, "Failure initialising ssh session"); return CURLE_FAILED_INIT; } @@ -3280,10 +3283,8 @@ static CURLcode scp_disconnect(struct Curl_easy *data, if(sshc->ssh_session) { /* only if there's a session still around to use! */ - state(data, SSH_SESSION_DISCONNECT); - - result = ssh_block_statemach(data, conn, FALSE); + result = ssh_block_statemach(data, conn, TRUE); } return result; @@ -3297,10 +3298,9 @@ static CURLcode ssh_done(struct Curl_easy *data, CURLcode status) struct SSHPROTO *sshp = data->req.p.ssh; struct connectdata *conn = data->conn; - if(!status) { + if(!status) /* run the state-machine */ result = ssh_block_statemach(data, conn, FALSE); - } else result = status; @@ -3440,7 +3440,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, if(sshc->ssh_session) { /* only if there's a session still around to use! */ state(data, SSH_SFTP_SHUTDOWN); - result = ssh_block_statemach(data, conn, FALSE); + result = ssh_block_statemach(data, conn, TRUE); } DEBUGF(infof(data, "SSH DISCONNECT is done\n")); @@ -3607,4 +3607,21 @@ size_t Curl_ssh_version(char *buffer, size_t buflen) return msnprintf(buffer, buflen, "libssh2/%s", LIBSSH2_VERSION); } +/* The SSH session is associated with the *CONNECTION* but the callback user + * pointer is an easy handle pointer. This function allows us to reassign the + * user pointer to the *CURRENT* (new) easy handle. + */ +static void ssh_attach(struct Curl_easy *data, struct connectdata *conn) +{ + DEBUGASSERT(data); + DEBUGASSERT(conn); + if(conn->handler->protocol & PROTO_FAMILY_SSH) { + struct ssh_conn *sshc = &conn->proto.sshc; + if(sshc->ssh_session) { + /* only re-attach if the session already exists */ + void **abstract = libssh2_session_abstract(sshc->ssh_session); + *abstract = data; + } + } +} #endif /* USE_LIBSSH2 */ diff --git a/libs/libcurl/src/vssh/ssh.h b/libs/libcurl/src/vssh/ssh.h index 52e1ee6c20..505b0787c5 100644 --- a/libs/libcurl/src/vssh/ssh.h +++ b/libs/libcurl/src/vssh/ssh.h @@ -263,9 +263,12 @@ extern const struct Curl_handler Curl_handler_sftp; CURLcode Curl_ssh_init(void); void Curl_ssh_cleanup(void); size_t Curl_ssh_version(char *buffer, size_t buflen); +void Curl_ssh_attach(struct Curl_easy *data, + struct connectdata *conn); #else /* for non-SSH builds */ #define Curl_ssh_cleanup() +#define Curl_ssh_attach(x,y) #endif #endif /* HEADER_CURL_SSH_H */ diff --git a/libs/libcurl/src/vssh/wolfssh.c b/libs/libcurl/src/vssh/wolfssh.c index de0b1c7776..9f3266a24d 100644 --- a/libs/libcurl/src/vssh/wolfssh.c +++ b/libs/libcurl/src/vssh/wolfssh.c @@ -91,6 +91,7 @@ const struct Curl_handler Curl_handler_scp = { wscp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SSH, /* defport */ CURLPROTO_SCP, /* protocol */ PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION @@ -119,6 +120,7 @@ const struct Curl_handler Curl_handler_sftp = { wsftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SSH, /* defport */ CURLPROTO_SFTP, /* protocol */ CURLPROTO_SFTP, /* family */ @@ -388,7 +390,7 @@ static CURLcode wssh_connect(struct Curl_easy *data, bool *done) } sshc->ssh_session = wolfSSH_new(sshc->ctx); - if(sshc->ssh_session == NULL) { + if(!sshc->ssh_session) { failf(data, "No wolfSSH session"); goto error; } @@ -861,7 +863,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) char *line = aprintf("%s\n", data->set.list_only ? name->fName : name->lName); - if(line == NULL) { + if(!line) { state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c index a63056d4ef..7f729713d8 100644 --- a/libs/libcurl/src/vtls/bearssl.c +++ b/libs/libcurl/src/vtls/bearssl.c @@ -300,12 +300,7 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); -#ifndef CURL_DISABLE_PROXY - const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - const char *hostname = conn->host.name; -#endif + const char * const hostname = SSL_HOST_NAME(); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const bool verifyhost = SSL_CONN_CONFIG(verifyhost); CURLcode ret; @@ -390,14 +385,14 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, * protocols array in `struct ssl_backend_data`. */ -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2 #ifndef CURL_DISABLE_PROXY && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) #endif ) { - backend->protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + backend->protocols[cur++] = ALPN_H2; + infof(data, "ALPN, offering %s\n", ALPN_H2); } #endif @@ -545,8 +540,8 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data, if(protocol) { infof(data, "ALPN, server accepted to use %s\n", protocol); -#ifdef USE_NGHTTP2 - if(!strcmp(protocol, NGHTTP2_PROTO_VERSION_ID)) +#ifdef USE_HTTP2 + if(!strcmp(protocol, ALPN_H2)) conn->negnpn = CURL_HTTP_VERSION_2; else #endif diff --git a/libs/libcurl/src/vtls/gskit.c b/libs/libcurl/src/vtls/gskit.c index b0c73437bb..ca953769d1 100644 --- a/libs/libcurl/src/vtls/gskit.c +++ b/libs/libcurl/src/vtls/gskit.c @@ -101,8 +101,10 @@ struct ssl_backend_data { gsk_handle handle; int iocport; +#ifndef CURL_DISABLE_PROXY int localfd; int remotefd; +#endif }; #define BACKEND connssl->backend @@ -302,8 +304,9 @@ static CURLcode set_callback(struct Curl_easy *data, static CURLcode set_ciphers(struct Curl_easy *data, - gsk_handle h, unsigned int *protoflags) + gsk_handle h, unsigned int *protoflags) { + struct connectdata *conn = data->conn; const char *cipherlist = SSL_CONN_CONFIG(cipher_list); const char *clp; const struct gskit_cipher *ctp; @@ -515,6 +518,7 @@ static void close_async_handshake(struct ssl_connect_data *connssl) static int pipe_ssloverssl(struct connectdata *conn, int sockindex, int directions) { +#ifndef CURL_DISABLE_PROXY struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex]; fd_set fds_read; @@ -583,6 +587,9 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex, } return ret; /* OK */ +#else + return 0; +#endif } @@ -596,6 +603,7 @@ static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data, while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) ; BACKEND->handle = (gsk_handle) NULL; +#ifndef CURL_DISABLE_PROXY if(BACKEND->localfd >= 0) { close(BACKEND->localfd); BACKEND->localfd = -1; @@ -604,6 +612,7 @@ static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data, close(BACKEND->remotefd); BACKEND->remotefd = -1; } +#endif } if(BACKEND->iocport >= 0) close_async_handshake(connssl); @@ -665,6 +674,7 @@ static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf, static CURLcode set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data) { + struct connectdata *conn = data->conn; long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); long i = ssl_version; @@ -705,20 +715,23 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, const char * const keyringlabel = SSL_SET_OPTION(primary.clientcert); const long int ssl_version = SSL_CONN_CONFIG(version); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); - const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: - conn->host.name; + const char * const hostname = SSL_HOST_NAME(); const char *sni; unsigned int protoflags = 0; Qso_OverlappedIO_t commarea; +#ifndef CURL_DISABLE_PROXY int sockpair[2]; static const int sobufsize = CURL_MAX_WRITE_SIZE; +#endif /* Create SSL environment, start (preferably asynchronous) handshake. */ BACKEND->handle = (gsk_handle) NULL; BACKEND->iocport = -1; +#ifndef CURL_DISABLE_PROXY BACKEND->localfd = -1; BACKEND->remotefd = -1; +#endif /* GSKit supports two ways of specifying an SSL context: either by * application identifier (that should have been defined at the system @@ -757,6 +770,7 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, if(result) return result; +#ifndef CURL_DISABLE_PROXY /* Establish a pipelining socket pair for SSL over SSL. */ if(conn->proxy_ssl[sockindex].use) { if(Curl_socketpair(0, 0, 0, sockpair)) @@ -774,6 +788,7 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, curlx_nonblock(BACKEND->localfd, TRUE); curlx_nonblock(BACKEND->remotefd, TRUE); } +#endif /* Determine which SSL/TLS version should be enabled. */ sni = hostname; @@ -826,8 +841,13 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, if(!result) result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1); if(!result) +#ifndef CURL_DISABLE_PROXY result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0? BACKEND->localfd: conn->sock[sockindex]); +#else + result = set_numeric(data, BACKEND->handle, GSK_FD, + conn->sock[sockindex]); +#endif if(!result) result = set_ciphers(data, BACKEND->handle, &protoflags); if(!protoflags) { @@ -896,10 +916,12 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, else if(errno != ENOBUFS) result = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0); +#ifndef CURL_DISABLE_PROXY else if(conn->proxy_ssl[sockindex].use) { /* Cannot pipeline while handshaking synchronously. */ result = CURLE_SSL_CONNECT_ERROR; } +#endif else { /* No more completion port available. Use synchronous IO. */ result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle), @@ -1035,8 +1057,7 @@ static CURLcode gskit_connect_step3(struct Curl_easy *data, } /* Check pinned public key. */ - ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + ptr = SSL_PINNED_PUB_KEY(); if(!result && ptr) { curl_X509certificate x509; curl_asn1Element *p; @@ -1158,7 +1179,9 @@ static void gskit_close(struct Curl_easy *data, struct connectdata *conn, int sockindex) { close_one(&conn->ssl[sockindex], data, conn, sockindex); +#ifndef CURL_DISABLE_PROXY close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex); +#endif } @@ -1281,7 +1304,9 @@ 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 */ - NULL /* sha256sum */ + NULL, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_GSKIT */ diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c index e3fad7fe02..ecde5c44de 100644 --- a/libs/libcurl/src/vtls/gtls.c +++ b/libs/libcurl/src/vtls/gtls.c @@ -263,7 +263,7 @@ static CURLcode handshake(struct Curl_easy *data, strerr = gnutls_alert_get_name(alert); } - if(strerr == NULL) + if(!strerr) strerr = gnutls_strerror(rc); infof(data, "gnutls_handshake() warning: %s\n", strerr); @@ -277,7 +277,7 @@ static CURLcode handshake(struct Curl_easy *data, strerr = gnutls_alert_get_name(alert); } - if(strerr == NULL) + if(!strerr) strerr = gnutls_strerror(rc); failf(data, "gnutls_handshake() failed: %s", strerr); @@ -308,15 +308,29 @@ 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 Curl_easy *data) +set_ssl_version_min_max(struct Curl_easy *data, + const char **prioritylist, + const char *tls13support) { struct connectdata *conn = data->conn; long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); - if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) { + if((ssl_version == CURL_SSLVERSION_DEFAULT) || + (ssl_version == CURL_SSLVERSION_TLSv1)) + ssl_version = CURL_SSLVERSION_TLSv1_0; + if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT; + if(!tls13support) { + /* If the running GnuTLS doesn't support TLS 1.3, we must not specify a + prioritylist involving that since it will make GnuTLS return an en + error back at us */ + if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) || + (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) { + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + } } + switch(ssl_version | ssl_version_max) { case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" @@ -395,6 +409,7 @@ gtls_connect_step1(struct Curl_easy *data, const char *err = NULL; const char * const hostname = SSL_HOST_NAME(); long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult); + const char *tls13support; if(connssl->state == ssl_connection_complete) /* to make us tolerant against being called more than once for the @@ -542,36 +557,34 @@ gtls_connect_step1(struct Curl_easy *data, if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; + /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */ + tls13support = gnutls_check_version("3.6.5"); + /* Ensure +SRP comes at the *end* of all relevant strings so that it can be * removed if a run-time error indicates that SRP is not supported by this * GnuTLS version */ switch(SSL_CONN_CONFIG(version)) { - case CURL_SSLVERSION_SSLv3: - prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; - break; + case CURL_SSLVERSION_TLSv1_3: + if(!tls13support) { + failf(data, "This GnuTLS installation does not support TLS 1.3"); + return CURLE_SSL_CONNECT_ERROR; + } + /* FALLTHROUGH */ case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: - prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0" -#ifdef HAS_TLS13 - ":+VERS-TLS1.3" -#endif - ; - break; case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: - case CURL_SSLVERSION_TLSv1_2: - case CURL_SSLVERSION_TLSv1_3: - { - CURLcode result = set_ssl_version_min_max(&prioritylist, data); - if(result != CURLE_OK) - return result; - break; - } + case CURL_SSLVERSION_TLSv1_2: { + CURLcode result = set_ssl_version_min_max(data, &prioritylist, + tls13support); + if(result) + return result; + break; + } case CURL_SSLVERSION_SSLv2: - failf(data, "GnuTLS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv3: default: - failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + failf(data, "GnuTLS does not support SSLv2 or SSLv3"); return CURLE_SSL_CONNECT_ERROR; } @@ -586,7 +599,6 @@ gtls_connect_step1(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; strcpy(prioritysrp, prioritylist); strcpy(prioritysrp + len, ":" GNUTLS_SRP); - rc = gnutls_priority_set_direct(session, prioritysrp, &err); free(prioritysrp); @@ -611,16 +623,16 @@ gtls_connect_step1(struct Curl_easy *data, int cur = 0; gnutls_datum_t protocols[2]; -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2 #ifndef CURL_DISABLE_PROXY && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) #endif ) { - protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; - protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN; + protocols[cur].data = (unsigned char *)ALPN_H2; + protocols[cur].size = ALPN_H2_LENGTH; cur++; - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + infof(data, "ALPN, offering %.*s\n", ALPN_H2_LENGTH, ALPN_H2); } #endif @@ -1178,8 +1190,7 @@ gtls_connect_step3(struct Curl_easy *data, infof(data, "\t server certificate activation date OK\n"); } - ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + ptr = SSL_PINNED_PUB_KEY(); if(ptr) { result = pkp_pin_peer_pubkey(data, x509_cert, ptr); if(result != CURLE_OK) { @@ -1243,10 +1254,10 @@ gtls_connect_step3(struct Curl_easy *data, infof(data, "ALPN, server accepted to use %.*s\n", proto.size, proto.data); -#ifdef USE_NGHTTP2 - if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data, - NGHTTP2_PROTO_VERSION_ID_LEN)) { +#ifdef USE_HTTP2 + if(proto.size == ALPN_H2_LENGTH && + !memcmp(ALPN_H2, proto.data, + ALPN_H2_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -1645,7 +1656,9 @@ const struct Curl_ssl Curl_ssl_gnutls = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - gtls_sha256sum /* sha256sum */ + gtls_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_GNUTLS */ diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c index 4b36f2d20c..3a0be0f04b 100644 --- a/libs/libcurl/src/vtls/mbedtls.c +++ b/libs/libcurl/src/vtls/mbedtls.c @@ -251,22 +251,16 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, const char * const ssl_capath = SSL_CONN_CONFIG(CApath); char * const ssl_cert = SSL_SET_OPTION(primary.clientcert); const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#else - const char * const hostname = conn->host.name; - const long int port = conn->remote_port; -#endif + const char * const hostname = SSL_HOST_NAME(); + const long int port = SSL_HOST_PORT(); int ret = -1; char errorbuf[128]; errorbuf[0] = 0; - /* mbedTLS only supports SSLv3 and TLSv1 */ - if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { - failf(data, "mbedTLS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; + if((SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) || + (SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)) { + failf(data, "Not supported SSL version"); + return CURLE_NOT_BUILT_IN; } #ifdef THREADING_SUPPORT @@ -414,13 +408,6 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); break; - case CURL_SSLVERSION_SSLv3: - mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_0); - mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_0); - infof(data, "mbedTLS: Set SSL version to SSLv3\n"); - break; case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: @@ -549,14 +536,7 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; const mbedtls_x509_crt *peercert; -#ifndef CURL_DISABLE_PROXY - const char * const pinnedpubkey = SSL_IS_PROXY() ? - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; -#else - const char * const pinnedpubkey = - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; -#endif + const char * const pinnedpubkey = SSL_PINNED_PUB_KEY(); conn->recv[sockindex] = mbed_recv; conn->send[sockindex] = mbed_send; @@ -1113,7 +1093,9 @@ const struct Curl_ssl Curl_ssl_mbedtls = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - mbedtls_sha256sum /* sha256sum */ + mbedtls_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_MBEDTLS */ diff --git a/libs/libcurl/src/vtls/mesalink.c b/libs/libcurl/src/vtls/mesalink.c index 5d6a1495d7..bf8600d323 100644 --- a/libs/libcurl/src/vtls/mesalink.c +++ b/libs/libcurl/src/vtls/mesalink.c @@ -98,8 +98,7 @@ mesalink_connect_step1(struct Curl_easy *data, #ifdef ENABLE_IPV6 struct in6_addr addr6; #endif - const char *const hostname = - SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; + const char * const hostname = SSL_HOST_NAME(); size_t hostname_len = strlen(hostname); SSL_METHOD *req_method = NULL; @@ -667,7 +666,9 @@ const struct Curl_ssl Curl_ssl_mesalink = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - NULL /* sha256sum */ + NULL, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif diff --git a/libs/libcurl/src/vtls/nss.c b/libs/libcurl/src/vtls/nss.c index a9f6959e3b..1582b1e580 100644 --- a/libs/libcurl/src/vtls/nss.c +++ b/libs/libcurl/src/vtls/nss.c @@ -139,9 +139,15 @@ static const struct cipher_s cipherlist[] = { {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA}, {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA}, {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA}, + {"dhe_rsa_3des_sha", SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA}, + {"dhe_dss_3des_sha", SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA}, + {"dhe_rsa_des_sha", SSL_DHE_RSA_WITH_DES_CBC_SHA}, + {"dhe_dss_des_sha", SSL_DHE_DSS_WITH_DES_CBC_SHA}, /* TLS 1.0: Exportable 56-bit Cipher Suites. */ {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA}, {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, + /* Ephemeral DH with RC4 bulk encryption */ + {"dhe_dss_rc4_128_sha", TLS_DHE_DSS_WITH_RC4_128_SHA}, /* AES ciphers. */ {"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA}, {"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA}, @@ -219,6 +225,25 @@ static const struct cipher_s cipherlist[] = { {"aes_256_gcm_sha_384", TLS_AES_256_GCM_SHA384}, {"chacha20_poly1305_sha_256", TLS_CHACHA20_POLY1305_SHA256}, #endif +#ifdef TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 + /* AES CBC cipher suites in RFC 5246. Introduced in NSS release 3.20 */ + {"dhe_dss_aes_128_sha_256", TLS_DHE_DSS_WITH_AES_128_CBC_SHA256}, + {"dhe_dss_aes_256_sha_256", TLS_DHE_DSS_WITH_AES_256_CBC_SHA256}, +#endif +#ifdef TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + /* Camellia cipher suites in RFC 4132/5932. + Introduced in NSS release 3.12 */ + {"dhe_rsa_camellia_128_sha", TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA}, + {"dhe_dss_camellia_128_sha", TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA}, + {"dhe_rsa_camellia_256_sha", TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA}, + {"dhe_dss_camellia_256_sha", TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA}, + {"rsa_camellia_128_sha", TLS_RSA_WITH_CAMELLIA_128_CBC_SHA}, + {"rsa_camellia_256_sha", TLS_RSA_WITH_CAMELLIA_256_CBC_SHA}, +#endif +#ifdef TLS_RSA_WITH_SEED_CBC_SHA + /* SEED cipher suite in RFC 4162. Introduced in NSS release 3.12.3 */ + {"rsa_seed_sha", TLS_RSA_WITH_SEED_CBC_SHA}, +#endif }; #if defined(WIN32) @@ -312,7 +337,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, while((*cipher) && (ISSPACE(*cipher))) ++cipher; - cipher_list = strchr(cipher, ','); + cipher_list = strpbrk(cipher, ":, "); if(cipher_list) { *cipher_list++ = '\0'; } @@ -380,7 +405,7 @@ static int is_file(const char *filename) { struct_stat st; - if(filename == NULL) + if(!filename) return 0; if(stat(filename, &st) == 0) @@ -845,8 +870,8 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) } #ifdef USE_NGHTTP2 - if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) { + if(buflen == ALPN_H2_LENGTH && + !memcmp(ALPN_H2, buf, ALPN_H2_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -1423,7 +1448,7 @@ static CURLcode nss_setup(struct Curl_easy *data) static int nss_init(void) { /* curl_global_init() is not thread-safe so this test is ok */ - if(nss_initlock == NULL) { + if(!nss_initlock) { PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); nss_initlock = PR_NewLock(); nss_crllock = PR_NewLock(); @@ -1699,8 +1724,7 @@ static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version) return CURLE_OK; case CURL_SSLVERSION_SSLv3: - *nssver = SSL_LIBRARY_VERSION_3_0; - return CURLE_OK; + return CURLE_NOT_BUILT_IN; case CURL_SSLVERSION_TLSv1_0: *nssver = SSL_LIBRARY_VERSION_TLS_1_0; @@ -1806,7 +1830,7 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl, struct Curl_easy *data, bool blocking) { - static PRSocketOptionData sock_opt; + PRSocketOptionData sock_opt; struct ssl_backend_data *backend = connssl->backend; sock_opt.option = PR_SockOpt_Nonblocking; sock_opt.value.non_blocking = !blocking; @@ -2079,16 +2103,15 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, int cur = 0; unsigned char protocols[128]; -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2 #ifndef CURL_DISABLE_PROXY && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) #endif ) { - protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; - memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, - NGHTTP2_PROTO_VERSION_ID_LEN); - cur += NGHTTP2_PROTO_VERSION_ID_LEN; + protocols[cur++] = ALPN_H2_LENGTH; + memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH); + cur += ALPN_H2_LENGTH; } #endif protocols[cur++] = ALPN_HTTP_1_1_LENGTH; @@ -2442,7 +2465,9 @@ const struct Curl_ssl Curl_ssl_nss = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ nss_false_start, /* false_start */ - nss_sha256sum /* sha256sum */ + nss_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_NSS */ diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c index 6583300b3c..ebd7abc3b4 100644 --- a/libs/libcurl/src/vtls/openssl.c +++ b/libs/libcurl/src/vtls/openssl.c @@ -122,12 +122,6 @@ #define HAVE_ERR_REMOVE_THREAD_STATE 1 #endif -#if !defined(HAVE_SSLV2_CLIENT_METHOD) || \ - OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0+ has no SSLv2 */ -#undef OPENSSL_NO_SSL2 /* undef first to avoid compiler warnings */ -#define OPENSSL_NO_SSL2 -#endif - #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \ !(defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) @@ -246,6 +240,10 @@ struct ssl_backend_data { #endif }; +static void ossl_associate_connection(struct Curl_easy *data, + struct connectdata *conn, + int sockindex); + /* * Number of bytes to read from the random number seed file. This must be * a finite value (because some entropy "files" like /dev/urandom have @@ -625,7 +623,7 @@ SSL_CTX_use_certificate_blob(SSL_CTX *ctx, const struct curl_blob *blob, goto end; } - if(x == NULL) { + if(!x) { ret = 0; goto end; } @@ -656,7 +654,7 @@ SSL_CTX_use_PrivateKey_blob(SSL_CTX *ctx, const struct curl_blob *blob, ret = 0; goto end; } - if(pkey == NULL) { + if(!pkey) { ret = 0; goto end; } @@ -669,7 +667,7 @@ SSL_CTX_use_PrivateKey_blob(SSL_CTX *ctx, const struct curl_blob *blob, static int SSL_CTX_use_certificate_chain_blob(SSL_CTX *ctx, const struct curl_blob *blob, - const char *key_passwd) + const char *key_passwd) { /* SSL_CTX_add1_chain_cert introduced in OpenSSL 1.0.2 */ #if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* OpenSSL 1.0.2 or later */ \ @@ -687,7 +685,7 @@ SSL_CTX_use_certificate_chain_blob(SSL_CTX *ctx, const struct curl_blob *blob, x = PEM_read_bio_X509_AUX(in, NULL, passwd_callback, (void *)key_passwd); - if(x == NULL) { + if(!x) { ret = 0; goto end; } @@ -731,7 +729,7 @@ SSL_CTX_use_certificate_chain_blob(SSL_CTX *ctx, const struct curl_blob *blob, return ret; #else (void)ctx; /* unused */ - (void)in; /* unused */ + (void)blob; /* unused */ (void)key_passwd; /* unused */ return 0; #endif @@ -875,7 +873,7 @@ int cert_stuff(struct Curl_easy *data, STACK_OF(X509) *ca = NULL; if(cert_blob) { cert_bio = BIO_new_mem_buf(cert_blob->data, (int)(cert_blob->len)); - if(cert_bio == NULL) { + if(!cert_bio) { failf(data, "BIO_new_mem_buf NULL, " OSSL_PACKAGE " error %s", @@ -886,7 +884,7 @@ int cert_stuff(struct Curl_easy *data, } else { cert_bio = BIO_new(BIO_s_file()); - if(cert_bio == NULL) { + if(!cert_bio) { failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s", @@ -2262,12 +2260,10 @@ select_next_proto_cb(SSL *ssl, struct connectdata *conn = data->conn; (void)ssl; -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2 && - !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID, - NGHTTP2_PROTO_VERSION_ID_LEN)) { - infof(data, "NPN, negotiated HTTP2 (%s)\n", - NGHTTP2_PROTO_VERSION_ID); + !select_next_protocol(out, outlen, in, inlen, ALPN_H2, ALPN_H2_LENGTH)) { + infof(data, "NPN, negotiated HTTP2 (%s)\n", ALPN_H2); conn->negnpn = CURL_HTTP_VERSION_2; return SSL_TLSEXT_ERR_OK; } @@ -2518,6 +2514,67 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) return res; } +static CURLcode load_cacert_from_memory(SSL_CTX *ctx, + const struct curl_blob *ca_info_blob) +{ + /* these need freed at the end */ + BIO *cbio = NULL; + STACK_OF(X509_INFO) *inf = NULL; + + /* everything else is just a reference */ + int i, count = 0; + X509_STORE *cts = NULL; + X509_INFO *itmp = NULL; + + if(ca_info_blob->len > (size_t)INT_MAX) + return CURLE_SSL_CACERT_BADFILE; + + cts = SSL_CTX_get_cert_store(ctx); + if(!cts) + return CURLE_OUT_OF_MEMORY; + + cbio = BIO_new_mem_buf(ca_info_blob->data, (int)ca_info_blob->len); + if(!cbio) + return CURLE_OUT_OF_MEMORY; + + inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL); + if(!inf) { + BIO_free(cbio); + return CURLE_SSL_CACERT_BADFILE; + } + + /* add each entry from PEM file to x509_store */ + for(i = 0; i < (int)sk_X509_INFO_num(inf); ++i) { + itmp = sk_X509_INFO_value(inf, i); + if(itmp->x509) { + if(X509_STORE_add_cert(cts, itmp->x509)) { + ++count; + } + else { + /* set count to 0 to return an error */ + count = 0; + break; + } + } + if(itmp->crl) { + if(X509_STORE_add_crl(cts, itmp->crl)) { + ++count; + } + else { + /* set count to 0 to return an error */ + count = 0; + break; + } + } + } + + sk_X509_INFO_pop_free(inf, X509_INFO_free); + BIO_free(cbio); + + /* if we didn't end up importing anything, treat that as an error */ + return (count > 0 ? CURLE_OK : CURLE_SSL_CACERT_BADFILE); +} + static CURLcode ossl_connect_step1(struct Curl_easy *data, struct connectdata *conn, int sockindex) { @@ -2528,6 +2585,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ctx_option_t ctx_options = 0; + void *ssl_sessionid = NULL; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME bool sni; @@ -2545,8 +2603,11 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif char * const ssl_cert = SSL_SET_OPTION(primary.clientcert); const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob); + const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob); const char * const ssl_cert_type = SSL_SET_OPTION(cert_type); - const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const char * const ssl_cafile = + /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ + (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile)); const char * const ssl_capath = SSL_CONN_CONFIG(CApath); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); @@ -2581,31 +2642,11 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, use_sni(TRUE); break; case CURL_SSLVERSION_SSLv2: -#ifdef OPENSSL_NO_SSL2 - failf(data, OSSL_PACKAGE " was built without SSLv2 support"); + failf(data, "No SSLv2 support"); return CURLE_NOT_BUILT_IN; -#else -#ifdef USE_OPENSSL_SRP - if(ssl_authtype == CURL_TLSAUTH_SRP) - return CURLE_SSL_CONNECT_ERROR; -#endif - req_method = SSLv2_client_method(); - use_sni(FALSE); - break; -#endif case CURL_SSLVERSION_SSLv3: -#ifdef OPENSSL_NO_SSL3_METHOD - failf(data, OSSL_PACKAGE " was built without SSLv3 support"); + failf(data, "No SSLv3 support"); return CURLE_NOT_BUILT_IN; -#else -#ifdef USE_OPENSSL_SRP - if(ssl_authtype == CURL_TLSAUTH_SRP) - return CURLE_SSL_CONNECT_ERROR; -#endif - req_method = SSLv3_client_method(); - use_sni(FALSE); - break; -#endif default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; @@ -2693,41 +2734,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif switch(ssl_version) { - /* "--sslv2" option means SSLv2 only, disable all others */ case CURL_SSLVERSION_SSLv2: -#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */ - SSL_CTX_set_min_proto_version(backend->ctx, SSL2_VERSION); - SSL_CTX_set_max_proto_version(backend->ctx, SSL2_VERSION); -#else - ctx_options |= SSL_OP_NO_SSLv3; - ctx_options |= SSL_OP_NO_TLSv1; -# if OPENSSL_VERSION_NUMBER >= 0x1000100FL - ctx_options |= SSL_OP_NO_TLSv1_1; - ctx_options |= SSL_OP_NO_TLSv1_2; -# ifdef TLS1_3_VERSION - ctx_options |= SSL_OP_NO_TLSv1_3; -# endif -# endif -#endif - break; - - /* "--sslv3" option means SSLv3 only, disable all others */ case CURL_SSLVERSION_SSLv3: -#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */ - SSL_CTX_set_min_proto_version(backend->ctx, SSL3_VERSION); - SSL_CTX_set_max_proto_version(backend->ctx, SSL3_VERSION); -#else - ctx_options |= SSL_OP_NO_SSLv2; - ctx_options |= SSL_OP_NO_TLSv1; -# if OPENSSL_VERSION_NUMBER >= 0x1000100FL - ctx_options |= SSL_OP_NO_TLSv1_1; - ctx_options |= SSL_OP_NO_TLSv1_2; -# ifdef TLS1_3_VERSION - ctx_options |= SSL_OP_NO_TLSv1_3; -# endif -# endif -#endif - break; + return CURLE_NOT_BUILT_IN; /* "--tlsv<x.y>" options mean TLS >= version <x.y> */ case CURL_SSLVERSION_DEFAULT: @@ -2768,18 +2777,17 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, int cur = 0; unsigned char protocols[128]; -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2 #ifndef CURL_DISABLE_PROXY && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) #endif ) { - protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; + protocols[cur++] = ALPN_H2_LENGTH; - memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, - NGHTTP2_PROTO_VERSION_ID_LEN); - cur += NGHTTP2_PROTO_VERSION_ID_LEN; - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH); + cur += ALPN_H2_LENGTH; + infof(data, "ALPN, offering %s\n", ALPN_H2); } #endif @@ -2885,8 +2893,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) && (SSL_SET_OPTION(native_ca_store))) { X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx); - HCERTSTORE hStore = CertOpenSystemStore((HCRYPTPROV_LEGACY)NULL, - TEXT("ROOT")); + HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT")); if(hStore) { PCCERT_CONTEXT pContext = NULL; @@ -3023,6 +3030,19 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, } #endif + if(ca_info_blob) { + result = load_cacert_from_memory(backend->ctx, ca_info_blob); + if(result) { + if(result == CURLE_OUT_OF_MEMORY || + (verifypeer && !imported_native_ca)) { + failf(data, "error importing CA certificate blob"); + return result; + } + /* Only warning if no certificate verification is required. */ + infof(data, "error importing CA certificate blob, continuing anyway\n"); + } + } + #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */ { @@ -3079,7 +3099,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif #ifdef CURL_CA_FALLBACK - if(verifypeer && !ssl_cafile && !ssl_capath && !imported_native_ca) { + if(verifypeer && + !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) { /* verifying the peer without any CA certificates won't work so use openssl's built in default as fallback */ SSL_CTX_set_default_verify_paths(backend->ctx); @@ -3209,46 +3230,23 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, } #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(); - int proxy_idx = ossl_get_proxy_index(); + ossl_associate_connection(data, conn, sockindex); - if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 && - proxy_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); -#ifndef CURL_DISABLE_PROXY - SSL_set_ex_data(backend->handle, proxy_idx, SSL_IS_PROXY() ? (void *) 1: - NULL); -#else - SSL_set_ex_data(backend->handle, proxy_idx, NULL); -#endif - - } - - Curl_ssl_sessionid_lock(data); - if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE, - &ssl_sessionid, NULL, sockindex)) { - /* we got a session id, use it! */ - if(!SSL_set_session(backend->handle, ssl_sessionid)) { - Curl_ssl_sessionid_unlock(data); - failf(data, "SSL: SSL_set_session failed: %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); - return CURLE_SSL_CONNECT_ERROR; - } - /* Informational message */ - infof(data, "SSL re-using session ID\n"); + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE, + &ssl_sessionid, NULL, sockindex)) { + /* we got a session id, use it! */ + if(!SSL_set_session(backend->handle, ssl_sessionid)) { + Curl_ssl_sessionid_unlock(data); + failf(data, "SSL: SSL_set_session failed: %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + return CURLE_SSL_CONNECT_ERROR; } - Curl_ssl_sessionid_unlock(data); + /* Informational message */ + infof(data, "SSL re-using session ID\n"); } + Curl_ssl_sessionid_unlock(data); #ifndef CURL_DISABLE_PROXY if(conn->proxy_ssl[sockindex].use) { @@ -3353,6 +3351,19 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, error_buffer */ strcpy(error_buffer, "SSL certificate verification failed"); } +#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \ + !defined(LIBRESSL_VERSION_NUMBER) && \ + !defined(OPENSSL_IS_BORINGSSL)) + /* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on + OpenSSL version above v1.1.1, not Libre SSL nor BoringSSL */ + else if((lib == ERR_LIB_SSL) && + (reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) { + /* If client certificate is required, communicate the + error to client */ + result = CURLE_SSL_CLIENTCERT; + ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)); + } +#endif else { result = CURLE_SSL_CONNECT_ERROR; ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)); @@ -3366,11 +3377,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, */ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { const char * const hostname = SSL_HOST_NAME(); -#ifndef CURL_DISABLE_PROXY - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#else - const long int port = conn->remote_port; -#endif + const long int port = SSL_HOST_PORT(); char extramsg[80]=""; int sockerr = SOCKERRNO; if(sockerr && detail == SSL_ERROR_SYSCALL) @@ -3404,12 +3411,12 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, const unsigned char *neg_protocol; unsigned int len; SSL_get0_alpn_selected(backend->handle, &neg_protocol, &len); - if(len != 0) { + if(len) { infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol); -#ifdef USE_NGHTTP2 - if(len == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len)) { +#ifdef USE_HTTP2 + if(len == ALPN_H2_LENGTH && + !memcmp(ALPN_H2, neg_protocol, len)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -3896,7 +3903,7 @@ static CURLcode servercert(struct Curl_easy *data, (int)SSL_SET_OPTION(issuercert_blob)->len); else { fp = BIO_new(BIO_s_file()); - if(fp == NULL) { + if(!fp) { failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s", @@ -3983,8 +3990,7 @@ static CURLcode servercert(struct Curl_easy *data, /* when not strict, we don't bother about the verify cert problems */ result = CURLE_OK; - ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + ptr = SSL_PINNED_PUB_KEY(); if(!result && ptr) { result = pkp_pin_peer_pubkey(data, backend->server_cert, ptr); if(result) @@ -4474,10 +4480,95 @@ static void *ossl_get_internals(struct ssl_connect_data *connssl, (void *)backend->ctx : (void *)backend->handle; } +static void ossl_associate_connection(struct Curl_easy *data, + struct connectdata *conn, + int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; + + /* If we don't have SSL context, do nothing. */ + if(!backend->handle) + return; + + if(SSL_SET_OPTION(primary.sessionid)) { + int data_idx = ossl_get_ssl_data_index(); + int connectdata_idx = ossl_get_ssl_conn_index(); + int sockindex_idx = ossl_get_ssl_sockindex_index(); + int proxy_idx = ossl_get_proxy_index(); + + if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 && + proxy_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); +#ifndef CURL_DISABLE_PROXY + SSL_set_ex_data(backend->handle, proxy_idx, SSL_IS_PROXY() ? (void *) 1: + NULL); +#else + SSL_set_ex_data(backend->handle, proxy_idx, NULL); +#endif + } + } +} + +/* + * Starting with TLS 1.3, the ossl_new_session_cb callback gets called after + * the handshake. If the transfer that sets up the callback gets killed before + * this callback arrives, we must make sure to properly clear the data to + * avoid UAF problems. A future optimization could be to instead store another + * transfer that might still be using the same connection. + */ + +static void ossl_disassociate_connection(struct Curl_easy *data, + int sockindex) +{ + struct connectdata *conn = data->conn; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; + + /* If we don't have SSL context, do nothing. */ + if(!backend->handle) + return; + + if(SSL_SET_OPTION(primary.sessionid)) { + bool isproxy = FALSE; + bool incache; + void *old_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(); + int proxy_idx = ossl_get_proxy_index(); + + if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 && + proxy_idx >= 0) { + /* Invalidate the session cache entry, if any */ + isproxy = SSL_get_ex_data(backend->handle, proxy_idx) ? TRUE : FALSE; + + /* Disable references to data in "new session" callback to avoid + * accessing a stale pointer. */ + SSL_set_ex_data(backend->handle, data_idx, NULL); + SSL_set_ex_data(backend->handle, connectdata_idx, NULL); + SSL_set_ex_data(backend->handle, sockindex_idx, NULL); + SSL_set_ex_data(backend->handle, proxy_idx, NULL); + } + + Curl_ssl_sessionid_lock(data); + incache = !(Curl_ssl_getsessionid(data, conn, isproxy, + &old_ssl_sessionid, NULL, sockindex)); + if(incache) + Curl_ssl_delsessionid(data, old_ssl_sessionid); + Curl_ssl_sessionid_unlock(data); + } +} + const struct Curl_ssl Curl_ssl_openssl = { { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */ SSLSUPP_CA_PATH | + SSLSUPP_CAINFO_BLOB | SSLSUPP_CERTINFO | SSLSUPP_PINNEDPUBKEY | SSLSUPP_SSL_CTX | @@ -4508,10 +4599,12 @@ const struct Curl_ssl Curl_ssl_openssl = { ossl_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) - ossl_sha256sum /* sha256sum */ + ossl_sha256sum, /* sha256sum */ #else - NULL /* sha256sum */ + NULL, /* sha256sum */ #endif + ossl_associate_connection, /* associate_connection */ + ossl_disassociate_connection /* disassociate_connection */ }; #endif /* USE_OPENSSL */ diff --git a/libs/libcurl/src/vtls/rustls.c b/libs/libcurl/src/vtls/rustls.c index e4f589de57..d5247f936a 100644 --- a/libs/libcurl/src/vtls/rustls.c +++ b/libs/libcurl/src/vtls/rustls.c @@ -37,16 +37,11 @@ #include "multiif.h" -/* Per https://www.bearssl.org/api1.html, max TLS record size plus max - per-record overhead. */ -#define TLSBUF_SIZE (16384 + 325) - struct ssl_backend_data { const struct rustls_client_config *config; - struct rustls_client_session *session; + struct rustls_connection *conn; bool data_pending; - uint8_t *tlsbuf; }; /* For a given rustls_result error code, return the best-matching CURLcode. */ @@ -82,6 +77,28 @@ cr_connect(struct Curl_easy *data UNUSED_PARAM, return CURLE_SSL_CONNECT_ERROR; } +static int +read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n) +{ + ssize_t n = sread(*(int *)userdata, buf, len); + if(n < 0) { + return SOCKERRNO; + } + *out_n = n; + return 0; +} + +static int +write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n) +{ + ssize_t n = swrite(*(int *)userdata, buf, len); + if(n < 0) { + return SOCKERRNO; + } + *out_n = n; + return 0; +} + /* * On each run: * - Read a chunk of bytes from the socket into rustls' TLS input buffer. @@ -101,65 +118,44 @@ cr_recv(struct Curl_easy *data, int sockindex, struct connectdata *conn = data->conn; struct ssl_connect_data *const connssl = &conn->ssl[sockindex]; struct ssl_backend_data *const backend = connssl->backend; - struct rustls_client_session *const session = backend->session; - curl_socket_t sockfd = conn->sock[sockindex]; + struct rustls_connection *const rconn = backend->conn; size_t n = 0; - ssize_t tls_bytes_read = 0; - size_t tls_bytes_processed = 0; + size_t tls_bytes_read = 0; size_t plain_bytes_copied = 0; rustls_result rresult = 0; char errorbuf[255]; + rustls_io_result io_error; - tls_bytes_read = sread(sockfd, backend->tlsbuf, TLSBUF_SIZE); - if(tls_bytes_read == 0) { - failf(data, "connection closed without TLS close_notify alert"); + io_error = rustls_connection_read_tls(rconn, read_cb, + &conn->sock[sockindex], &tls_bytes_read); + if(io_error == EAGAIN || io_error == EWOULDBLOCK) { + infof(data, "sread: EAGAIN or EWOULDBLOCK\n"); + } + else if(io_error) { + failf(data, "reading from socket: %s", strerror(io_error)); *err = CURLE_READ_ERROR; return -1; } - else if(tls_bytes_read < 0) { - if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) { - infof(data, "sread: EAGAIN or EWOULDBLOCK\n"); - *err = CURLE_AGAIN; - return -1; - } - failf(data, "reading from socket: %s", strerror(SOCKERRNO)); + else if(tls_bytes_read == 0) { + failf(data, "connection closed without TLS close_notify alert"); *err = CURLE_READ_ERROR; return -1; } - /* - * Now pull those bytes from the buffer into ClientSession. - */ - DEBUGASSERT(tls_bytes_read > 0); - while(tls_bytes_processed < (size_t)tls_bytes_read) { - rresult = rustls_client_session_read_tls(session, - backend->tlsbuf + tls_bytes_processed, - tls_bytes_read - tls_bytes_processed, - &n); - if(rresult != RUSTLS_RESULT_OK) { - failf(data, "error in rustls_client_session_read_tls"); - *err = CURLE_READ_ERROR; - return -1; - } - else if(n == 0) { - infof(data, "EOF from rustls_client_session_read_tls\n"); - break; - } + infof(data, "cr_recv read %ld bytes from the network\n", tls_bytes_read); - rresult = rustls_client_session_process_new_packets(session); - if(rresult != RUSTLS_RESULT_OK) { - rustls_error(rresult, errorbuf, sizeof(errorbuf), &n); - failf(data, "%.*s", n, errorbuf); - *err = map_error(rresult); - return -1; - } - - tls_bytes_processed += n; - backend->data_pending = TRUE; + rresult = rustls_connection_process_new_packets(rconn); + if(rresult != RUSTLS_RESULT_OK) { + rustls_error(rresult, errorbuf, sizeof(errorbuf), &n); + failf(data, "%.*s", n, errorbuf); + *err = map_error(rresult); + return -1; } + backend->data_pending = TRUE; + while(plain_bytes_copied < plainlen) { - rresult = rustls_client_session_read(session, + rresult = rustls_connection_read(rconn, (uint8_t *)plainbuf + plain_bytes_copied, plainlen - plain_bytes_copied, &n); @@ -168,20 +164,21 @@ cr_recv(struct Curl_easy *data, int sockindex, return 0; } else if(rresult != RUSTLS_RESULT_OK) { - failf(data, "error in rustls_client_session_read"); + failf(data, "error in rustls_connection_read"); *err = CURLE_READ_ERROR; return -1; } else if(n == 0) { - /* rustls returns 0 from client_session_read to mean "all currently + /* rustls returns 0 from connection_read to mean "all currently available data has been read." If we bring in more ciphertext with read_tls, more plaintext will become available. So don't tell curl this is an EOF. Instead, say "come back later." */ - infof(data, "EOF from rustls_client_session_read\n"); + infof(data, "cr_recv got 0 bytes of plaintext\n"); backend->data_pending = FALSE; break; } else { + infof(data, "cr_recv copied out %ld bytes of plaintext\n", n); plain_bytes_copied += n; } } @@ -214,68 +211,50 @@ cr_send(struct Curl_easy *data, int sockindex, struct connectdata *conn = data->conn; struct ssl_connect_data *const connssl = &conn->ssl[sockindex]; struct ssl_backend_data *const backend = connssl->backend; - struct rustls_client_session *const session = backend->session; - curl_socket_t sockfd = conn->sock[sockindex]; - ssize_t n = 0; + struct rustls_connection *const rconn = backend->conn; size_t plainwritten = 0; - size_t tlslen = 0; size_t tlswritten = 0; + size_t tlswritten_total = 0; rustls_result rresult; + rustls_io_result io_error; + + infof(data, "cr_send %ld bytes of plaintext\n", plainlen); if(plainlen > 0) { - rresult = rustls_client_session_write(session, - plainbuf, plainlen, &plainwritten); + rresult = rustls_connection_write(rconn, plainbuf, plainlen, + &plainwritten); if(rresult != RUSTLS_RESULT_OK) { - failf(data, "error in rustls_client_session_write"); + failf(data, "error in rustls_connection_write"); *err = CURLE_WRITE_ERROR; return -1; } else if(plainwritten == 0) { - failf(data, "EOF in rustls_client_session_write"); + failf(data, "EOF in rustls_connection_write"); *err = CURLE_WRITE_ERROR; return -1; } } - while(rustls_client_session_wants_write(session)) { - rresult = rustls_client_session_write_tls( - session, backend->tlsbuf, TLSBUF_SIZE, &tlslen); - if(rresult != RUSTLS_RESULT_OK) { - failf(data, "error in rustls_client_session_write_tls"); - *err = CURLE_WRITE_ERROR; + while(rustls_connection_wants_write(rconn)) { + io_error = rustls_connection_write_tls(rconn, write_cb, + &conn->sock[sockindex], &tlswritten); + if(io_error == EAGAIN || io_error == EWOULDBLOCK) { + infof(data, "swrite: EAGAIN after %ld bytes\n", tlswritten_total); + *err = CURLE_AGAIN; return -1; } - else if(tlslen == 0) { - failf(data, "EOF in rustls_client_session_write_tls"); + else if(io_error) { + failf(data, "writing to socket: %s", strerror(io_error)); *err = CURLE_WRITE_ERROR; return -1; } - - tlswritten = 0; - - while(tlswritten < tlslen) { - n = swrite(sockfd, backend->tlsbuf + tlswritten, tlslen - tlswritten); - if(n < 0) { - if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) { - /* Since recv is called from poll, there should be room to - write at least some bytes before hitting EAGAIN. */ - infof(data, "swrite: EAGAIN after %ld bytes\n", tlswritten); - DEBUGASSERT(tlswritten > 0); - break; - } - failf(data, "error in swrite"); - *err = CURLE_WRITE_ERROR; - return -1; - } - if(n == 0) { - failf(data, "EOF in swrite"); - *err = CURLE_WRITE_ERROR; - return -1; - } - tlswritten += n; + if(tlswritten == 0) { + failf(data, "EOF in swrite"); + *err = CURLE_WRITE_ERROR; + return -1; } - - DEBUGASSERT(tlswritten <= tlslen); + infof(data, "cr_send wrote %ld bytes to network\n", tlswritten); + tlswritten_total += tlswritten; } return plainwritten; @@ -310,7 +289,7 @@ static CURLcode cr_init_backend(struct Curl_easy *data, struct connectdata *conn, struct ssl_backend_data *const backend) { - struct rustls_client_session *session = backend->session; + struct rustls_connection *rconn = backend->conn; struct rustls_client_config_builder *config_builder = NULL; const char *const ssl_cafile = SSL_CONN_CONFIG(CAfile); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); @@ -318,19 +297,26 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn, char errorbuf[256]; size_t errorlen; int result; - - backend->tlsbuf = calloc(TLSBUF_SIZE, 1); - if(backend->tlsbuf == NULL) { - return CURLE_OUT_OF_MEMORY; - } + rustls_slice_bytes alpn[2] = { + { (const uint8_t *)ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH }, + { (const uint8_t *)ALPN_H2, ALPN_H2_LENGTH }, + }; config_builder = rustls_client_config_builder_new(); +#ifdef USE_HTTP2 + infof(data, "offering ALPN for HTTP/1.1 and HTTP/2\n"); + rustls_client_config_builder_set_protocols(config_builder, alpn, 2); +#else + infof(data, "offering ALPN for HTTP/1.1 only\n"); + rustls_client_config_builder_set_protocols(config_builder, alpn, 1); +#endif if(!verifypeer) { rustls_client_config_builder_dangerous_set_certificate_verifier( - config_builder, cr_verify_none, NULL); + config_builder, cr_verify_none); /* rustls doesn't support IP addresses (as of 0.19.0), and will reject - * sessions created with an IP address, even when certificate verification - * is turned off. Set a placeholder hostname and disable SNI. */ + * connections created with an IP address, even when certificate + * verification is turned off. Set a placeholder hostname and disable + * SNI. */ if(cr_hostname_is_ip(hostname)) { rustls_client_config_builder_set_enable_sni(config_builder, false); hostname = "example.invalid"; @@ -357,18 +343,51 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn, } backend->config = rustls_client_config_builder_build(config_builder); - DEBUGASSERT(session == NULL); - result = rustls_client_session_new( - backend->config, hostname, &session); + DEBUGASSERT(rconn == NULL); + result = rustls_client_connection_new(backend->config, hostname, &rconn); if(result != RUSTLS_RESULT_OK) { rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen); - failf(data, "failed to create client session: %.*s", errorlen, errorbuf); + failf(data, "rustls_client_connection_new: %.*s", errorlen, errorbuf); return CURLE_COULDNT_CONNECT; } - backend->session = session; + rustls_connection_set_userdata(rconn, backend); + backend->conn = rconn; return CURLE_OK; } +static void +cr_set_negotiated_alpn(struct Curl_easy *data, struct connectdata *conn, + const struct rustls_connection *rconn) +{ + const uint8_t *protocol = NULL; + size_t len = 0; + + rustls_connection_get_alpn_protocol(rconn, &protocol, &len); + if(NULL == protocol) { + infof(data, "ALPN, server did not agree to a protocol\n"); + return; + } + +#ifdef USE_HTTP2 + if(len == ALPN_H2_LENGTH && 0 == memcmp(ALPN_H2, protocol, len)) { + infof(data, "ALPN, negotiated h2\n"); + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(len == ALPN_HTTP_1_1_LENGTH && + 0 == memcmp(ALPN_HTTP_1_1, protocol, len)) { + infof(data, "ALPN, negotiated http/1.1\n"); + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + else { + infof(data, "ALPN, negotiated an unrecognized protocol\n"); + } + + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); +} + static CURLcode cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, int sockindex, bool *done) @@ -376,7 +395,7 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, struct ssl_connect_data *const connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_backend_data *const backend = connssl->backend; - struct rustls_client_session *session = NULL; + struct rustls_connection *rconn = NULL; CURLcode tmperr = CURLE_OK; int result; int what; @@ -393,7 +412,7 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, connssl->state = ssl_connection_negotiating; } - session = backend->session; + rconn = backend->conn; /* Read/write data until the handshake is done or the socket would block. */ for(;;) { @@ -404,18 +423,21 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, * then becomes true when we first write data, then becomes false again * once the handshake is done. */ - if(!rustls_client_session_is_handshaking(session)) { + if(!rustls_connection_is_handshaking(rconn)) { infof(data, "Done handshaking\n"); /* Done with the handshake. Set up callbacks to send/receive data. */ connssl->state = ssl_connection_complete; + + cr_set_negotiated_alpn(data, conn, rconn); + conn->recv[sockindex] = cr_recv; conn->send[sockindex] = cr_send; *done = TRUE; return CURLE_OK; } - wants_read = rustls_client_session_wants_read(session); - wants_write = rustls_client_session_wants_write(session); + wants_read = rustls_connection_wants_read(rconn); + wants_write = rustls_connection_wants_write(rconn); DEBUGASSERT(wants_read || wants_write); writefd = wants_write?sockfd:CURL_SOCKET_BAD; readfd = wants_read?sockfd:CURL_SOCKET_BAD; @@ -439,7 +461,7 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, /* socket is readable or writable */ if(wants_write) { - infof(data, "ClientSession wants us to write_tls.\n"); + infof(data, "rustls_connection wants us to write_tls.\n"); cr_send(data, sockindex, NULL, 0, &tmperr); if(tmperr == CURLE_AGAIN) { infof(data, "writing would block\n"); @@ -451,7 +473,7 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, } if(wants_read) { - infof(data, "ClientSession wants us to read_tls.\n"); + infof(data, "rustls_connection wants us to read_tls.\n"); cr_recv(data, sockindex, NULL, 0, &tmperr); if(tmperr == CURLE_AGAIN) { @@ -482,13 +504,13 @@ cr_getsock(struct connectdata *conn, curl_socket_t *socks) struct ssl_connect_data *const connssl = &conn->ssl[FIRSTSOCKET]; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; struct ssl_backend_data *const backend = connssl->backend; - struct rustls_client_session *session = backend->session; + struct rustls_connection *rconn = backend->conn; - if(rustls_client_session_wants_write(session)) { + if(rustls_connection_wants_write(rconn)) { socks[0] = sockfd; return GETSOCK_WRITESOCK(0); } - if(rustls_client_session_wants_read(session)) { + if(rustls_connection_wants_read(rconn)) { socks[0] = sockfd; return GETSOCK_READSOCK(0); } @@ -501,7 +523,7 @@ cr_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { struct ssl_backend_data *backend = connssl->backend; - return &backend->session; + return &backend->conn; } static void @@ -513,21 +535,20 @@ cr_close(struct Curl_easy *data, struct connectdata *conn, CURLcode tmperr = CURLE_OK; ssize_t n = 0; - if(backend->session) { - rustls_client_session_send_close_notify(backend->session); + if(backend->conn) { + rustls_connection_send_close_notify(backend->conn); n = cr_send(data, sockindex, NULL, 0, &tmperr); if(n < 0) { failf(data, "error sending close notify: %d", tmperr); } - rustls_client_session_free(backend->session); - backend->session = NULL; + rustls_connection_free(backend->conn); + backend->conn = NULL; } if(backend->config) { rustls_client_config_free(backend->config); backend->config = NULL; } - free(backend->tlsbuf); } const struct Curl_ssl Curl_ssl_rustls = { @@ -554,7 +575,9 @@ const struct Curl_ssl Curl_ssl_rustls = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - NULL /* sha256sum */ + NULL, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_RUSTLS */ diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c index 961a71f6d5..2bcf11db25 100644 --- a/libs/libcurl/src/vtls/schannel.c +++ b/libs/libcurl/src/vtls/schannel.c @@ -117,6 +117,10 @@ #define SP_PROT_TLS1_2_CLIENT 0x00000800 #endif +#ifndef SCH_USE_STRONG_CRYPTO +#define SCH_USE_STRONG_CRYPTO 0x00400000 +#endif + #ifndef SECBUFFER_ALERT #define SECBUFFER_ALERT 17 #endif @@ -324,17 +328,22 @@ get_alg_id_by_name(char *name) } static CURLcode -set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers) +set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers, + ALG_ID *algIds) { char *startCur = ciphers; int algCount = 0; - static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/ - while(startCur && (0 != *startCur) && (algCount < 45)) { + while(startCur && (0 != *startCur) && (algCount < NUMOF_CIPHERS)) { long alg = strtol(startCur, 0, 0); if(!alg) alg = get_alg_id_by_name(startCur); if(alg) algIds[algCount++] = alg; + else if(!strncmp(startCur, "USE_STRONG_CRYPTO", + sizeof("USE_STRONG_CRYPTO") - 1) || + !strncmp(startCur, "SCH_USE_STRONG_CRYPTO", + sizeof("SCH_USE_STRONG_CRYPTO") - 1)) + schannel_cred->dwFlags |= SCH_USE_STRONG_CRYPTO; else return CURLE_SSL_CIPHER; startCur = strchr(startCur, ':'); @@ -358,7 +367,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, size_t store_name_len; sep = _tcschr(path, TEXT('\\')); - if(sep == NULL) + if(!sep) return CURLE_SSL_CERTPROBLEM; store_name_len = sep - path; @@ -388,7 +397,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, store_path_start = sep + 1; sep = _tcschr(store_path_start, TEXT('\\')); - if(sep == NULL) + if(!sep) return CURLE_SSL_CERTPROBLEM; *thumbprint = sep + 1; @@ -398,7 +407,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, *sep = TEXT('\0'); *store_path = _tcsdup(store_path_start); *sep = TEXT('\\'); - if(*store_path == NULL) + if(!*store_path) return CURLE_OUT_OF_MEMORY; return CURLE_OK; @@ -428,12 +437,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #endif TCHAR *host_name; CURLcode result; -#ifndef CURL_DISABLE_PROXY - char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - char * const hostname = conn->host.name; -#endif + char * const hostname = SSL_HOST_NAME(); DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", @@ -469,7 +473,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #endif #else #ifdef HAS_MANUAL_VERIFY_API - if(SSL_CONN_CONFIG(CAfile)) { + if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) { if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_GREATER_THAN_EQUAL)) { BACKEND->use_manual_cred_validation = true; @@ -483,7 +487,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, else BACKEND->use_manual_cred_validation = false; #else - if(SSL_CONN_CONFIG(CAfile)) { + if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) { failf(data, "schannel: CA cert support not built in"); return CURLE_NOT_BUILT_IN; } @@ -558,6 +562,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, "names in server certificates.\n")); } + if(!SSL_SET_OPTION(auto_client_cert)) { + schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS; + schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; + infof(data, "schannel: disabled automatic use of client certificate\n"); + } + else + infof(data, "schannel: enabled automatic use of client certificate\n"); + switch(conn->ssl_config.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: @@ -572,18 +584,17 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, break; } case CURL_SSLVERSION_SSLv3: - schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; - break; case CURL_SSLVERSION_SSLv2: - schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; - break; + failf(data, "SSL versions not supported"); + return CURLE_NOT_BUILT_IN; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } if(SSL_CONN_CONFIG(cipher_list)) { - result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list)); + result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list), + BACKEND->algIds); if(CURLE_OK != result) { failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG"); return result; @@ -700,7 +711,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, } if(!blob) free(certdata); - if(cert_store == NULL) { + if(!cert_store) { DWORD errorcode = GetLastError(); if(errorcode == ERROR_INVALID_PASSWORD) failf(data, "schannel: Failed to import cert file %s, " @@ -717,7 +728,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); - if(client_certs[0] == NULL) { + if(!client_certs[0]) { failf(data, "schannel: Failed to get certificate from file %s" ", last error is 0x%x", cert_showfilename_error, GetLastError()); @@ -861,11 +872,11 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, list_start_index = cur; -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2) { - memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN); - cur += NGHTTP2_PROTO_ALPN_LEN; - infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH); + cur += ALPN_H2_LENGTH; + infof(data, "schannel: ALPN, offering %s\n", ALPN_H2); } #endif @@ -893,11 +904,15 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); InitSecBufferDesc(&outbuf_desc, &outbuf, 1); - /* setup request flags */ + /* security request flags */ BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; + if(!SSL_SET_OPTION(auto_client_cert)) { + BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; + } + /* allocate memory for the security context handle */ BACKEND->ctxt = (struct Curl_schannel_ctxt *) calloc(1, sizeof(struct Curl_schannel_ctxt)); @@ -997,12 +1012,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, SECURITY_STATUS sspi_status = SEC_E_OK; CURLcode result; bool doread; -#ifndef CURL_DISABLE_PROXY - char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - char * const hostname = conn->host.name; -#endif + char * const hostname = SSL_HOST_NAME(); const char *pubkey_ptr; doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; @@ -1015,23 +1025,23 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; /* buffer to store previously received and decrypted data */ - if(BACKEND->decdata_buffer == NULL) { + if(!BACKEND->decdata_buffer) { BACKEND->decdata_offset = 0; BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; BACKEND->decdata_buffer = malloc(BACKEND->decdata_length); - if(BACKEND->decdata_buffer == NULL) { + if(!BACKEND->decdata_buffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; } } /* buffer to store previously received and encrypted data */ - if(BACKEND->encdata_buffer == NULL) { + if(!BACKEND->encdata_buffer) { BACKEND->encdata_is_incomplete = false; BACKEND->encdata_offset = 0; BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; BACKEND->encdata_buffer = malloc(BACKEND->encdata_length); - if(BACKEND->encdata_buffer == NULL) { + if(!BACKEND->encdata_buffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; } @@ -1046,7 +1056,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, reallocated_buffer = realloc(BACKEND->encdata_buffer, reallocated_length); - if(reallocated_buffer == NULL) { + if(!reallocated_buffer) { failf(data, "schannel: unable to re-allocate memory"); return CURLE_OUT_OF_MEMORY; } @@ -1101,7 +1111,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0); InitSecBufferDesc(&outbuf_desc, outbuf, 3); - if(inbuf[0].pvBuffer == NULL) { + if(!inbuf[0].pvBuffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; } @@ -1251,9 +1261,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n")); } - pubkey_ptr = SSL_IS_PROXY() ? - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + pubkey_ptr = SSL_PINNED_PUB_KEY(); if(pubkey_ptr) { result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr); if(result) { @@ -1340,8 +1348,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, CERT_CONTEXT *ccert_context = NULL; bool isproxy = SSL_IS_PROXY(); #ifdef DEBUGBUILD - const char * const hostname = isproxy ? conn->http_proxy.host.name : - conn->host.name; + const char * const hostname = SSL_HOST_NAME(); #endif #ifdef HAS_ALPN SecPkgContext_ApplicationProtocol alpn_result; @@ -1389,10 +1396,9 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, infof(data, "schannel: ALPN, server accepted to use %.*s\n", alpn_result.ProtocolIdSize, alpn_result.ProtocolId); -#ifdef USE_NGHTTP2 - if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId, - NGHTTP2_PROTO_VERSION_ID_LEN)) { +#ifdef USE_HTTP2 + if(alpn_result.ProtocolIdSize == ALPN_H2_LENGTH && + !memcmp(ALPN_H2, alpn_result.ProtocolId, ALPN_H2_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -1453,7 +1459,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context); - if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) { + if((sspi_status != SEC_E_OK) || !ccert_context) { failf(data, "schannel: failed to retrieve remote cert context"); return CURLE_PEER_FAILED_VERIFICATION; } @@ -1805,7 +1811,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, } reallocated_buffer = realloc(BACKEND->encdata_buffer, reallocated_length); - if(reallocated_buffer == NULL) { + if(!reallocated_buffer) { *err = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); goto cleanup; @@ -1894,7 +1900,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, } reallocated_buffer = realloc(BACKEND->decdata_buffer, reallocated_length); - if(reallocated_buffer == NULL) { + if(!reallocated_buffer) { *err = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); goto cleanup; @@ -2128,12 +2134,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn, * Shutting Down an Schannel Connection */ struct ssl_connect_data *connssl = &conn->ssl[sockindex]; -#ifndef CURL_DISABLE_PROXY - char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - char * const hostname = conn->host.name; -#endif + char * const hostname = SSL_HOST_NAME(); DEBUGASSERT(data); @@ -2296,7 +2297,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &pCertContextServer); - if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + if((sspi_status != SEC_E_OK) || !pCertContextServer) { char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); @@ -2406,6 +2407,9 @@ const struct Curl_ssl Curl_ssl_schannel = { { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ SSLSUPP_CERTINFO | +#ifdef HAS_MANUAL_VERIFY_API + SSLSUPP_CAINFO_BLOB | +#endif SSLSUPP_PINNEDPUBKEY, sizeof(struct ssl_backend_data), @@ -2429,7 +2433,9 @@ const struct Curl_ssl Curl_ssl_schannel = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - schannel_sha256sum /* sha256sum */ + schannel_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_SCHANNEL */ diff --git a/libs/libcurl/src/vtls/schannel.h b/libs/libcurl/src/vtls/schannel.h index 2952caa1a5..77853aa30f 100644 --- a/libs/libcurl/src/vtls/schannel.h +++ b/libs/libcurl/src/vtls/schannel.h @@ -71,6 +71,8 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data, #endif #endif +#define NUMOF_CIPHERS 45 /* There are 45 listed in the MS headers */ + struct Curl_schannel_cred { CredHandle cred_handle; TimeStamp time_stamp; @@ -102,6 +104,7 @@ struct ssl_backend_data { #ifdef HAS_MANUAL_VERIFY_API bool use_manual_cred_validation; /* true if manual cred validation is used */ #endif + ALG_ID algIds[NUMOF_CIPHERS]; }; #endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */ diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c index e0fdbd5b63..25d47b8087 100644 --- a/libs/libcurl/src/vtls/schannel_verify.c +++ b/libs/libcurl/src/vtls/schannel_verify.c @@ -77,21 +77,156 @@ static int is_cr_or_lf(char c) return c == '\r' || c == '\n'; } -static CURLcode add_certs_to_store(HCERTSTORE trust_store, - const char *ca_file, - struct Curl_easy *data) +/* Search the substring needle,needlelen into string haystack,haystacklen + * Strings don't need to be terminated by a '\0'. + * Similar of OSX/Linux memmem (not available on Visual Studio). + * Return position of beginning of first occurence or NULL if not found + */ +static const char *c_memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen) +{ + const char *p; + char first; + const char *str_limit = (const char *)haystack + haystacklen; + if(!needlelen || needlelen > haystacklen) + return NULL; + first = *(const char *)needle; + for(p = (const char *)haystack; p <= (str_limit - needlelen); p++) + if(((*p) == first) && (memcmp(p, needle, needlelen) == 0)) + return p; + + return NULL; +} + +static CURLcode add_certs_data_to_store(HCERTSTORE trust_store, + const char *ca_buffer, + size_t ca_buffer_size, + const char *ca_file_text, + struct Curl_easy *data) +{ + const size_t begin_cert_len = strlen(BEGIN_CERT); + const size_t end_cert_len = strlen(END_CERT); + CURLcode result = CURLE_OK; + int num_certs = 0; + bool more_certs = 1; + const char *current_ca_file_ptr = ca_buffer; + const char *ca_buffer_limit = ca_buffer + ca_buffer_size; + + while(more_certs && (current_ca_file_ptr<ca_buffer_limit)) { + const char *begin_cert_ptr = c_memmem(current_ca_file_ptr, + ca_buffer_limit-current_ca_file_ptr, + BEGIN_CERT, + begin_cert_len); + if(!begin_cert_ptr || !is_cr_or_lf(begin_cert_ptr[begin_cert_len])) { + more_certs = 0; + } + else { + const char *end_cert_ptr = c_memmem(begin_cert_ptr, + ca_buffer_limit-begin_cert_ptr, + END_CERT, + end_cert_len); + if(!end_cert_ptr) { + failf(data, + "schannel: CA file '%s' is not correctly formatted", + ca_file_text); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + CERT_BLOB cert_blob; + CERT_CONTEXT *cert_context = NULL; + BOOL add_cert_result = FALSE; + DWORD actual_content_type = 0; + DWORD cert_size = (DWORD) + ((end_cert_ptr + end_cert_len) - begin_cert_ptr); + + cert_blob.pbData = (BYTE *)begin_cert_ptr; + cert_blob.cbData = cert_size; + if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, + &cert_blob, + CERT_QUERY_CONTENT_FLAG_CERT, + CERT_QUERY_FORMAT_FLAG_ALL, + 0, + NULL, + &actual_content_type, + NULL, + NULL, + NULL, + (const void **)&cert_context)) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to extract certificate from CA file " + "'%s': %s", + ca_file_text, + Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + current_ca_file_ptr = begin_cert_ptr + cert_size; + + /* Sanity check that the cert_context object is the right type */ + if(CERT_QUERY_CONTENT_CERT != actual_content_type) { + failf(data, + "schannel: unexpected content type '%d' when extracting " + "certificate from CA file '%s'", + actual_content_type, ca_file_text); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + add_cert_result = + CertAddCertificateContextToStore(trust_store, + cert_context, + CERT_STORE_ADD_ALWAYS, + NULL); + CertFreeCertificateContext(cert_context); + if(!add_cert_result) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to add certificate from CA file '%s' " + "to certificate store: %s", + ca_file_text, + Curl_winapi_strerror(GetLastError(), buffer, + sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + num_certs++; + } + } + } + } + } + } + + if(result == CURLE_OK) { + if(!num_certs) { + infof(data, + "schannel: did not add any certificates from CA file '%s'\n", + ca_file_text); + } + else { + infof(data, + "schannel: added %d certificate(s) from CA file '%s'\n", + num_certs, ca_file_text); + } + } + return result; +} + +static CURLcode add_certs_file_to_store(HCERTSTORE trust_store, + const char *ca_file, + struct Curl_easy *data) { CURLcode result; HANDLE ca_file_handle = INVALID_HANDLE_VALUE; LARGE_INTEGER file_size; char *ca_file_buffer = NULL; - char *current_ca_file_ptr = NULL; TCHAR *ca_file_tstr = NULL; size_t ca_file_bufsize = 0; DWORD total_bytes_read = 0; - bool more_certs = 0; - int num_certs = 0; - size_t END_CERT_LEN; ca_file_tstr = curlx_convert_UTF8_to_tchar((char *)ca_file); if(!ca_file_tstr) { @@ -181,106 +316,10 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, if(result != CURLE_OK) { goto cleanup; } - - END_CERT_LEN = strlen(END_CERT); - - more_certs = 1; - current_ca_file_ptr = ca_file_buffer; - while(more_certs && *current_ca_file_ptr != '\0') { - char *begin_cert_ptr = strstr(current_ca_file_ptr, BEGIN_CERT); - if(!begin_cert_ptr || !is_cr_or_lf(begin_cert_ptr[strlen(BEGIN_CERT)])) { - more_certs = 0; - } - else { - char *end_cert_ptr = strstr(begin_cert_ptr, END_CERT); - if(!end_cert_ptr) { - failf(data, - "schannel: CA file '%s' is not correctly formatted", - ca_file); - result = CURLE_SSL_CACERT_BADFILE; - more_certs = 0; - } - else { - CERT_BLOB cert_blob; - CERT_CONTEXT *cert_context = NULL; - BOOL add_cert_result = FALSE; - DWORD actual_content_type = 0; - DWORD cert_size = (DWORD) - ((end_cert_ptr + END_CERT_LEN) - begin_cert_ptr); - - cert_blob.pbData = (BYTE *)begin_cert_ptr; - cert_blob.cbData = cert_size; - if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, - &cert_blob, - CERT_QUERY_CONTENT_FLAG_CERT, - CERT_QUERY_FORMAT_FLAG_ALL, - 0, - NULL, - &actual_content_type, - NULL, - NULL, - NULL, - (const void **)&cert_context)) { - char buffer[STRERROR_LEN]; - failf(data, - "schannel: failed to extract certificate from CA file " - "'%s': %s", - ca_file, - Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); - result = CURLE_SSL_CACERT_BADFILE; - more_certs = 0; - } - else { - current_ca_file_ptr = begin_cert_ptr + cert_size; - - /* Sanity check that the cert_context object is the right type */ - if(CERT_QUERY_CONTENT_CERT != actual_content_type) { - failf(data, - "schannel: unexpected content type '%d' when extracting " - "certificate from CA file '%s'", - actual_content_type, ca_file); - result = CURLE_SSL_CACERT_BADFILE; - more_certs = 0; - } - else { - add_cert_result = - CertAddCertificateContextToStore(trust_store, - cert_context, - CERT_STORE_ADD_ALWAYS, - NULL); - CertFreeCertificateContext(cert_context); - if(!add_cert_result) { - char buffer[STRERROR_LEN]; - failf(data, - "schannel: failed to add certificate from CA file '%s' " - "to certificate store: %s", - ca_file, - Curl_winapi_strerror(GetLastError(), buffer, - sizeof(buffer))); - result = CURLE_SSL_CACERT_BADFILE; - more_certs = 0; - } - else { - num_certs++; - } - } - } - } - } - } - - if(result == CURLE_OK) { - if(!num_certs) { - infof(data, - "schannel: did not add any certificates from CA file '%s'\n", - ca_file); - } - else { - infof(data, - "schannel: added %d certificate(s) from CA file '%s'\n", - num_certs, ca_file); - } - } + result = add_certs_data_to_store(trust_store, + ca_file_buffer, ca_file_bufsize, + ca_file, + data); cleanup: if(ca_file_handle != INVALID_HANDLE_VALUE) { @@ -389,7 +428,7 @@ static DWORD cert_get_name_string(struct Curl_easy *data, if(entry->dwAltNameChoice != CERT_ALT_NAME_DNS_NAME) { continue; } - if(entry->pwszDNSName == NULL) { + if(!entry->pwszDNSName) { infof(data, "schannel: Empty DNS name."); continue; } @@ -536,27 +575,22 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data, const CERT_CHAIN_CONTEXT *pChainContext = NULL; HCERTCHAINENGINE cert_chain_engine = NULL; HCERTSTORE trust_store = NULL; -#ifndef CURL_DISABLE_PROXY - const char * const conn_hostname = SSL_IS_PROXY() ? - conn->http_proxy.host.name : - conn->host.name; -#else - const char * const conn_hostname = conn->host.name; -#endif + const char * const conn_hostname = SSL_HOST_NAME(); sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &pCertContextServer); - if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + if((sspi_status != SEC_E_OK) || !pCertContextServer) { char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); result = CURLE_PEER_FAILED_VERIFICATION; } - if(result == CURLE_OK && SSL_CONN_CONFIG(CAfile) && + if(result == CURLE_OK && + (SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) && BACKEND->use_manual_cred_validation) { /* * Create a chain engine that uses the certificates in the CA file as @@ -582,8 +616,19 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data, result = CURLE_SSL_CACERT_BADFILE; } else { - result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile), - data); + const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob); + if(ca_info_blob) { + result = add_certs_data_to_store(trust_store, + (const char *)ca_info_blob->data, + ca_info_blob->len, + "(memory blob)", + data); + } + else { + result = add_certs_file_to_store(trust_store, + SSL_CONN_CONFIG(CAfile), + data); + } } } diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c index 9d637da2ec..edd375ea7d 100644 --- a/libs/libcurl/src/vtls/sectransp.c +++ b/libs/libcurl/src/vtls/sectransp.c @@ -67,6 +67,7 @@ #define CURL_BUILD_IOS_7 0 #define CURL_BUILD_IOS_9 0 #define CURL_BUILD_IOS_11 0 +#define CURL_BUILD_IOS_13 0 #define CURL_BUILD_MAC 1 /* This is the maximum API level we are allowed to use when building: */ #define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 @@ -76,6 +77,7 @@ #define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 #define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 #define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 +#define CURL_BUILD_MAC_10_15 MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 /* These macros mean "the following code is present to allow runtime backward compatibility with at least this cat or earlier": (You set this at build-time using the compiler command line option @@ -91,6 +93,7 @@ #define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 #define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 #define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 +#define CURL_BUILD_IOS_13 __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 #define CURL_BUILD_MAC 0 #define CURL_BUILD_MAC_10_5 0 #define CURL_BUILD_MAC_10_6 0 @@ -99,6 +102,7 @@ #define CURL_BUILD_MAC_10_9 0 #define CURL_BUILD_MAC_10_11 0 #define CURL_BUILD_MAC_10_13 0 +#define CURL_BUILD_MAC_10_15 0 #define CURL_SUPPORT_MAC_10_5 0 #define CURL_SUPPORT_MAC_10_6 0 #define CURL_SUPPORT_MAC_10_7 0 @@ -138,6 +142,636 @@ struct ssl_backend_data { size_t ssl_write_buffered_length; }; +struct st_cipher { + const char *name; /* Cipher suite IANA name. It starts with "TLS_" prefix */ + const char *alias_name; /* Alias name is the same as OpenSSL cipher name */ + SSLCipherSuite num; /* Cipher suite code/number defined in IANA registry */ + bool weak; /* Flag to mark cipher as weak based on previous implementation + of Secure Transport back-end by CURL */ +}; + +/* Macro to initialize st_cipher data structure: stringify id to name, cipher + number/id, 'weak' suite flag + */ +#define CIPHER_DEF(num, alias, weak) \ + { #num, alias, num, weak } + +/* + Macro to initialize st_cipher data structure with name, code (IANA cipher + number/id value), and 'weak' suite flag. The first 28 cipher suite numbers + have the same IANA code for both SSL and TLS standards: numbers 0x0000 to + 0x001B. They have different names though. The first 4 letters of the cipher + suite name are the protocol name: "SSL_" or "TLS_", rest of the IANA name is + the same for both SSL and TLS cipher suite name. + The second part of the problem is that macOS/iOS SDKs don't define all TLS + codes but only 12 of them. The SDK defines all SSL codes though, i.e. SSL_NUM + constant is always defined for those 28 ciphers while TLS_NUM is defined only + for 12 of the first 28 ciphers. Those 12 TLS cipher codes match to + corresponding SSL enum value and represent the same cipher suite. Therefore + we'll use the SSL enum value for those cipher suites because it is defined + for all 28 of them. + We make internal data consistent and based on TLS names, i.e. all st_cipher + item names start with the "TLS_" prefix. + Summarizing all the above, those 28 first ciphers are presented in our table + with both TLS and SSL names. Their cipher numbers are assigned based on the + SDK enum value for the SSL cipher, which matches to IANA TLS number. + */ +#define CIPHER_DEF_SSLTLS(num_wo_prefix, alias, weak) \ + { "TLS_" #num_wo_prefix, alias, SSL_##num_wo_prefix, weak } + +/* + Cipher suites were marked as weak based on the following: + RC4 encryption - rfc7465, the document contains a list of deprecated ciphers. + Marked in the code below as weak. + RC2 encryption - many mentions, was found vulnerable to a relatively easy + attack https://link.springer.com/chapter/10.1007%2F3-540-69710-1_14 + Marked in the code below as weak. + DES and IDEA encryption - rfc5469, has a list of deprecated ciphers. + Marked in the code below as weak. + Anonymous Diffie-Hellman authentication and anonymous elliptic curve + Diffie-Hellman - vulnerable to a man-in-the-middle attack. Deprecated by + RFC 4346 aka TLS 1.1 (section A.5, page 60) + Null bulk encryption suites - not encrypted communication + Export ciphers, i.e. ciphers with restrictions to be used outside the US for + software exported to some countries, they were excluded from TLS 1.1 + version. More precisely, they were noted as ciphers which MUST NOT be + negotiated in RFC 4346 aka TLS 1.1 (section A.5, pages 60 and 61). + All of those filters were considered weak because they contain a weak + algorithm like DES, RC2 or RC4, and already considered weak by other + criteria. + 3DES - NIST deprecated it and is going to retire it by 2023 + https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA + OpenSSL https://www.openssl.org/blog/blog/2016/08/24/sweet32/ also + deprecated those ciphers. Some other libraries also consider it + vulnerable or at least not strong enough. + + CBC ciphers are vulnerable with SSL3.0 and TLS1.0: + https://www.cisco.com/c/en/us/support/docs/security/email-security-appliance + /118518-technote-esa-00.html + We don't take care of this issue because it is resolved by later TLS + versions and for us, it requires more complicated checks, we need to + check a protocol version also. Vulnerability doesn't look very critical + and we do not filter out those cipher suites. + */ + +#define CIPHER_WEAK_NOT_ENCRYPTED TRUE +#define CIPHER_WEAK_RC_ENCRYPTION TRUE +#define CIPHER_WEAK_DES_ENCRYPTION TRUE +#define CIPHER_WEAK_IDEA_ENCRYPTION TRUE +#define CIPHER_WEAK_ANON_AUTH TRUE +#define CIPHER_WEAK_3DES_ENCRYPTION TRUE +#define CIPHER_STRONG_ENOUGH FALSE + +/* Please do not change the order of the first ciphers available for SSL. + Do not insert and do not delete any of them. Code below + depends on their order and continuity. + If you add a new cipher, please maintain order by number, i.e. + insert in between existing items to appropriate place based on + cipher suite IANA number +*/ +const static struct st_cipher ciphertable[] = { + /* SSL version 3.0 and initial TLS 1.0 cipher suites. + Defined since SDK 10.2.8 */ + CIPHER_DEF_SSLTLS(NULL_WITH_NULL_NULL, /* 0x0000 */ + NULL, + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF_SSLTLS(RSA_WITH_NULL_MD5, /* 0x0001 */ + "NULL-MD5", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF_SSLTLS(RSA_WITH_NULL_SHA, /* 0x0002 */ + "NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_RC4_40_MD5, /* 0x0003 */ + "EXP-RC4-MD5", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_WITH_RC4_128_MD5, /* 0x0004 */ + "RC4-MD5", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_WITH_RC4_128_SHA, /* 0x0005 */ + "RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* 0x0006 */ + "EXP-RC2-CBC-MD5", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_WITH_IDEA_CBC_SHA, /* 0x0007 */ + "IDEA-CBC-SHA", + CIPHER_WEAK_IDEA_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x0008 */ + "EXP-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_WITH_DES_CBC_SHA, /* 0x0009 */ + "DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_WITH_3DES_EDE_CBC_SHA, /* 0x000A */ + "DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_DSS_EXPORT_WITH_DES40_CBC_SHA, /* 0x000B */ + "EXP-DH-DSS-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_DSS_WITH_DES_CBC_SHA, /* 0x000C */ + "DH-DSS-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_DSS_WITH_3DES_EDE_CBC_SHA, /* 0x000D */ + "DH-DSS-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x000E */ + "EXP-DH-RSA-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_RSA_WITH_DES_CBC_SHA, /* 0x000F */ + "DH-RSA-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x0010 */ + "DH-RSA-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, /* 0x0011 */ + "EXP-EDH-DSS-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_DSS_WITH_DES_CBC_SHA, /* 0x0012 */ + "EDH-DSS-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* 0x0013 */ + "DHE-DSS-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x0014 */ + "EXP-EDH-RSA-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_RSA_WITH_DES_CBC_SHA, /* 0x0015 */ + "EDH-RSA-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x0016 */ + "DHE-RSA-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_anon_EXPORT_WITH_RC4_40_MD5, /* 0x0017 */ + "EXP-ADH-RC4-MD5", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF_SSLTLS(DH_anon_WITH_RC4_128_MD5, /* 0x0018 */ + "ADH-RC4-MD5", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF_SSLTLS(DH_anon_EXPORT_WITH_DES40_CBC_SHA, /* 0x0019 */ + "EXP-ADH-DES-CBC-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF_SSLTLS(DH_anon_WITH_DES_CBC_SHA, /* 0x001A */ + "ADH-DES-CBC-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF_SSLTLS(DH_anon_WITH_3DES_EDE_CBC_SHA, /* 0x001B */ + "ADH-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* 0x001C */ + NULL, + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* 0x001D */ + NULL, + CIPHER_STRONG_ENOUGH), + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* RFC 4785 - Pre-Shared Key (PSK) Ciphersuites with NULL Encryption */ + CIPHER_DEF(TLS_PSK_WITH_NULL_SHA, /* 0x002C */ + "PSK-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA, /* 0x002D */ + "DHE-PSK-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA, /* 0x002E */ + "RSA-PSK-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + + /* TLS addenda using AES, per RFC 3268. Defined since SDK 10.4u */ + CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA, /* 0x002F */ + "AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_CBC_SHA, /* 0x0030 */ + "DH-DSS-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_CBC_SHA, /* 0x0031 */ + "DH-RSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* 0x0032 */ + "DHE-DSS-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* 0x0033 */ + "DHE-RSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_128_CBC_SHA, /* 0x0034 */ + "ADH-AES128-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA, /* 0x0035 */ + "AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_CBC_SHA, /* 0x0036 */ + "DH-DSS-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_CBC_SHA, /* 0x0037 */ + "DH-RSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* 0x0038 */ + "DHE-DSS-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* 0x0039 */ + "DHE-RSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_256_CBC_SHA, /* 0x003A */ + "ADH-AES256-SHA", + CIPHER_WEAK_ANON_AUTH), + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* TLS 1.2 addenda, RFC 5246 */ + /* Server provided RSA certificate for key exchange. */ + CIPHER_DEF(TLS_RSA_WITH_NULL_SHA256, /* 0x003B */ + "NULL-SHA256", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA256, /* 0x003C */ + "AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA256, /* 0x003D */ + "AES256-SHA256", + CIPHER_STRONG_ENOUGH), + /* Server-authenticated (and optionally client-authenticated) + Diffie-Hellman. */ + CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_CBC_SHA256, /* 0x003E */ + "DH-DSS-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_CBC_SHA256, /* 0x003F */ + "DH-RSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, /* 0x0040 */ + "DHE-DSS-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + + /* TLS 1.2 addenda, RFC 5246 */ + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, /* 0x0067 */ + "DHE-RSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_CBC_SHA256, /* 0x0068 */ + "DH-DSS-AES256-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_CBC_SHA256, /* 0x0069 */ + "DH-RSA-AES256-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, /* 0x006A */ + "DHE-DSS-AES256-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, /* 0x006B */ + "DHE-RSA-AES256-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_128_CBC_SHA256, /* 0x006C */ + "ADH-AES128-SHA256", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_256_CBC_SHA256, /* 0x006D */ + "ADH-AES256-SHA256", + CIPHER_WEAK_ANON_AUTH), +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* Addendum from RFC 4279, TLS PSK */ + CIPHER_DEF(TLS_PSK_WITH_RC4_128_SHA, /* 0x008A */ + "PSK-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x008B */ + "PSK-3DES-EDE-CBC-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_PSK_WITH_AES_128_CBC_SHA, /* 0x008C */ + "PSK-AES128-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_PSK_WITH_AES_256_CBC_SHA, /* 0x008D */ + "PSK-AES256-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_RC4_128_SHA, /* 0x008E */ + "DHE-PSK-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x008F */ + "DHE-PSK-3DES-EDE-CBC-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_CBC_SHA, /* 0x0090 */ + "DHE-PSK-AES128-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_CBC_SHA, /* 0x0091 */ + "DHE-PSK-AES256-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_RC4_128_SHA, /* 0x0092 */ + "RSA-PSK-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x0093 */ + "RSA-PSK-3DES-EDE-CBC-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_CBC_SHA, /* 0x0094 */ + "RSA-PSK-AES128-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_CBC_SHA, /* 0x0095 */ + "RSA-PSK-AES256-CBC-SHA", + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* Addenda from rfc 5288 AES Galois Counter Mode (GCM) Cipher Suites + for TLS. */ + CIPHER_DEF(TLS_RSA_WITH_AES_128_GCM_SHA256, /* 0x009C */ + "AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_WITH_AES_256_GCM_SHA384, /* 0x009D */ + "AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, /* 0x009E */ + "DHE-RSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, /* 0x009F */ + "DHE-RSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_GCM_SHA256, /* 0x00A0 */ + "DH-RSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_GCM_SHA384, /* 0x00A1 */ + "DH-RSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, /* 0x00A2 */ + "DHE-DSS-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, /* 0x00A3 */ + "DHE-DSS-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_GCM_SHA256, /* 0x00A4 */ + "DH-DSS-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_GCM_SHA384, /* 0x00A5 */ + "DH-DSS-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_128_GCM_SHA256, /* 0x00A6 */ + "ADH-AES128-GCM-SHA256", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_256_GCM_SHA384, /* 0x00A7 */ + "ADH-AES256-GCM-SHA384", + CIPHER_WEAK_ANON_AUTH), +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* RFC 5487 - PSK with SHA-256/384 and AES GCM */ + CIPHER_DEF(TLS_PSK_WITH_AES_128_GCM_SHA256, /* 0x00A8 */ + "PSK-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_PSK_WITH_AES_256_GCM_SHA384, /* 0x00A9 */ + "PSK-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, /* 0x00AA */ + "DHE-PSK-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, /* 0x00AB */ + "DHE-PSK-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, /* 0x00AC */ + "RSA-PSK-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, /* 0x00AD */ + "RSA-PSK-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_PSK_WITH_AES_128_CBC_SHA256, /* 0x00AE */ + "PSK-AES128-CBC-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_PSK_WITH_AES_256_CBC_SHA384, /* 0x00AF */ + "PSK-AES256-CBC-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_PSK_WITH_NULL_SHA256, /* 0x00B0 */ + "PSK-NULL-SHA256", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_PSK_WITH_NULL_SHA384, /* 0x00B1 */ + "PSK-NULL-SHA384", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, /* 0x00B2 */ + "DHE-PSK-AES128-CBC-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, /* 0x00B3 */ + "DHE-PSK-AES256-CBC-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA256, /* 0x00B4 */ + "DHE-PSK-NULL-SHA256", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA384, /* 0x00B5 */ + "DHE-PSK-NULL-SHA384", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, /* 0x00B6 */ + "RSA-PSK-AES128-CBC-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, /* 0x00B7 */ + "RSA-PSK-AES256-CBC-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA256, /* 0x00B8 */ + "RSA-PSK-NULL-SHA256", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA384, /* 0x00B9 */ + "RSA-PSK-NULL-SHA384", + CIPHER_WEAK_NOT_ENCRYPTED), +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + + /* RFC 5746 - Secure Renegotiation. This is not a real suite, + it is a response to initiate negotiation again */ + CIPHER_DEF(TLS_EMPTY_RENEGOTIATION_INFO_SCSV, /* 0x00FF */ + NULL, + CIPHER_STRONG_ENOUGH), + +#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 + /* TLS 1.3 standard cipher suites for ChaCha20+Poly1305. + Note: TLS 1.3 ciphersuites do not specify the key exchange + algorithm -- they only specify the symmetric ciphers. + Cipher alias name matches to OpenSSL cipher name, and for + TLS 1.3 ciphers */ + CIPHER_DEF(TLS_AES_128_GCM_SHA256, /* 0x1301 */ + NULL, /* The OpenSSL cipher name matches to the IANA name */ + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_AES_256_GCM_SHA384, /* 0x1302 */ + NULL, /* The OpenSSL cipher name matches to the IANA name */ + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_CHACHA20_POLY1305_SHA256, /* 0x1303 */ + NULL, /* The OpenSSL cipher name matches to the IANA name */ + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_AES_128_CCM_SHA256, /* 0x1304 */ + NULL, /* The OpenSSL cipher name matches to the IANA name */ + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_AES_128_CCM_8_SHA256, /* 0x1305 */ + NULL, /* The OpenSSL cipher name matches to the IANA name */ + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* ECDSA addenda, RFC 4492 */ + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_NULL_SHA, /* 0xC001 */ + "ECDH-ECDSA-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_RC4_128_SHA, /* 0xC002 */ + "ECDH-ECDSA-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC003 */ + "ECDH-ECDSA-DES-CBC3-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC004 */ + "ECDH-ECDSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC005 */ + "ECDH-ECDSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_NULL_SHA, /* 0xC006 */ + "ECDHE-ECDSA-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, /* 0xC007 */ + "ECDHE-ECDSA-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC008 */ + "ECDHE-ECDSA-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC009 */ + "ECDHE-ECDSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC00A */ + "ECDHE-ECDSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_NULL_SHA, /* 0xC00B */ + "ECDH-RSA-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_ECDH_RSA_WITH_RC4_128_SHA, /* 0xC00C */ + "ECDH-RSA-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC00D */ + "ECDH-RSA-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* 0xC00E */ + "ECDH-RSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* 0xC00F */ + "ECDH-RSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_NULL_SHA, /* 0xC010 */ + "ECDHE-RSA-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_RC4_128_SHA, /* 0xC011 */ + "ECDHE-RSA-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC012 */ + "ECDHE-RSA-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* 0xC013 */ + "ECDHE-RSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, /* 0xC014 */ + "ECDHE-RSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_anon_WITH_NULL_SHA, /* 0xC015 */ + "AECDH-NULL-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_ECDH_anon_WITH_RC4_128_SHA, /* 0xC016 */ + "AECDH-RC4-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, /* 0xC017 */ + "AECDH-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_ECDH_anon_WITH_AES_128_CBC_SHA, /* 0xC018 */ + "AECDH-AES128-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_ECDH_anon_WITH_AES_256_CBC_SHA, /* 0xC019 */ + "AECDH-AES256-SHA", + CIPHER_WEAK_ANON_AUTH), +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with + HMAC SHA-256/384. */ + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC023 */ + "ECDHE-ECDSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC024 */ + "ECDHE-ECDSA-AES256-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC025 */ + "ECDH-ECDSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC026 */ + "ECDH-ECDSA-AES256-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, /* 0xC027 */ + "ECDHE-RSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, /* 0xC028 */ + "ECDHE-RSA-AES256-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, /* 0xC029 */ + "ECDH-RSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, /* 0xC02A */ + "ECDH-RSA-AES256-SHA384", + CIPHER_STRONG_ENOUGH), + /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with + SHA-256/384 and AES Galois Counter Mode (GCM) */ + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02B */ + "ECDHE-ECDSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02C */ + "ECDHE-ECDSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02D */ + "ECDH-ECDSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02E */ + "ECDH-ECDSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, /* 0xC02F */ + "ECDHE-RSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, /* 0xC030 */ + "ECDHE-RSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, /* 0xC031 */ + "ECDH-RSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, /* 0xC032 */ + "ECDH-RSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + +#if CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 + /* ECDHE_PSK Cipher Suites for Transport Layer Security (TLS), RFC 5489 */ + CIPHER_DEF(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, /* 0xC035 */ + "ECDHE-PSK-AES128-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, /* 0xC036 */ + "ECDHE-PSK-AES256-CBC-SHA", + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 */ + +#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 + /* Addenda from rfc 7905 ChaCha20-Poly1305 Cipher Suites for + Transport Layer Security (TLS). */ + CIPHER_DEF(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA8 */ + "ECDHE-RSA-CHACHA20-POLY1305", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA9 */ + "ECDHE-ECDSA-CHACHA20-POLY1305", + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + +#if CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 + /* ChaCha20-Poly1305 Cipher Suites for Transport Layer Security (TLS), + RFC 7905 */ + CIPHER_DEF(TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCAB */ + "PSK-CHACHA20-POLY1305", + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 */ + + /* Tags for SSL 2 cipher kinds which are not specified for SSL 3. + Defined since SDK 10.2.8 */ + CIPHER_DEF(SSL_RSA_WITH_RC2_CBC_MD5, /* 0xFF80 */ + NULL, + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(SSL_RSA_WITH_IDEA_CBC_MD5, /* 0xFF81 */ + NULL, + CIPHER_WEAK_IDEA_ENCRYPTION), + CIPHER_DEF(SSL_RSA_WITH_DES_CBC_MD5, /* 0xFF82 */ + NULL, + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF(SSL_RSA_WITH_3DES_EDE_CBC_MD5, /* 0xFF83 */ + NULL, + CIPHER_WEAK_3DES_ENCRYPTION), +}; + +#define NUM_OF_CIPHERS sizeof(ciphertable)/sizeof(ciphertable[0]) + + /* pinned public key support tests */ /* version 1 supports macOS 10.12+ and iOS 10+ */ @@ -295,586 +929,23 @@ static OSStatus SocketWrite(SSLConnectionRef connection, } #ifndef CURL_DISABLE_VERBOSE_STRINGS -CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) -{ - switch(cipher) { - /* SSL version 3.0 */ - case SSL_RSA_WITH_NULL_MD5: - return "SSL_RSA_WITH_NULL_MD5"; - break; - case SSL_RSA_WITH_NULL_SHA: - return "SSL_RSA_WITH_NULL_SHA"; - break; - case SSL_RSA_EXPORT_WITH_RC4_40_MD5: - return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; - break; - case SSL_RSA_WITH_RC4_128_MD5: - return "SSL_RSA_WITH_RC4_128_MD5"; - break; - case SSL_RSA_WITH_RC4_128_SHA: - return "SSL_RSA_WITH_RC4_128_SHA"; - break; - case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: - return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; - break; - case SSL_RSA_WITH_IDEA_CBC_SHA: - return "SSL_RSA_WITH_IDEA_CBC_SHA"; - break; - case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_RSA_WITH_DES_CBC_SHA: - return "SSL_RSA_WITH_DES_CBC_SHA"; - break; - case SSL_RSA_WITH_3DES_EDE_CBC_SHA: - return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DH_DSS_WITH_DES_CBC_SHA: - return "SSL_DH_DSS_WITH_DES_CBC_SHA"; - break; - case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: - return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DH_RSA_WITH_DES_CBC_SHA: - return "SSL_DH_RSA_WITH_DES_CBC_SHA"; - break; - case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: - return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DHE_DSS_WITH_DES_CBC_SHA: - return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; - break; - case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DHE_RSA_WITH_DES_CBC_SHA: - return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; - break; - case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: - return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; - break; - case SSL_DH_anon_WITH_RC4_128_MD5: - return "SSL_DH_anon_WITH_RC4_128_MD5"; - break; - case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DH_anon_WITH_DES_CBC_SHA: - return "SSL_DH_anon_WITH_DES_CBC_SHA"; - break; - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: - return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_FORTEZZA_DMS_WITH_NULL_SHA: - return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; - break; - case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: - return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; - break; - /* TLS 1.0 with AES (RFC 3268) - (Apparently these are used in SSLv3 implementations as well.) */ - case TLS_RSA_WITH_AES_128_CBC_SHA: - return "TLS_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - return "TLS_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_256_CBC_SHA: - return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; - break; - /* SSL version 2.0 */ - case SSL_RSA_WITH_RC2_CBC_MD5: - return "SSL_RSA_WITH_RC2_CBC_MD5"; - break; - case SSL_RSA_WITH_IDEA_CBC_MD5: - return "SSL_RSA_WITH_IDEA_CBC_MD5"; - break; - case SSL_RSA_WITH_DES_CBC_MD5: - return "SSL_RSA_WITH_DES_CBC_MD5"; - break; - case SSL_RSA_WITH_3DES_EDE_CBC_MD5: - return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; - break; - } - return "SSL_NULL_WITH_NULL_NULL"; -} - CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) { - switch(cipher) { - /* TLS 1.0 with AES (RFC 3268) */ - case TLS_RSA_WITH_AES_128_CBC_SHA: - return "TLS_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - return "TLS_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_256_CBC_SHA: - return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; - break; -#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS - /* TLS 1.0 with ECDSA (RFC 4492) */ - case TLS_ECDH_ECDSA_WITH_NULL_SHA: - return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_NULL_SHA: - return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDH_RSA_WITH_NULL_SHA: - return "TLS_ECDH_RSA_WITH_NULL_SHA"; - break; - case TLS_ECDH_RSA_WITH_RC4_128_SHA: - return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDHE_RSA_WITH_NULL_SHA: - return "TLS_ECDHE_RSA_WITH_NULL_SHA"; - break; - case TLS_ECDHE_RSA_WITH_RC4_128_SHA: - return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDH_anon_WITH_NULL_SHA: - return "TLS_ECDH_anon_WITH_NULL_SHA"; - break; - case TLS_ECDH_anon_WITH_RC4_128_SHA: - return "TLS_ECDH_anon_WITH_RC4_128_SHA"; - break; - case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: - return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: - return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; - break; -#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ -#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS - /* TLS 1.2 (RFC 5246) */ - case TLS_RSA_WITH_NULL_MD5: - return "TLS_RSA_WITH_NULL_MD5"; - break; - case TLS_RSA_WITH_NULL_SHA: - return "TLS_RSA_WITH_NULL_SHA"; - break; - case TLS_RSA_WITH_RC4_128_MD5: - return "TLS_RSA_WITH_RC4_128_MD5"; - break; - case TLS_RSA_WITH_RC4_128_SHA: - return "TLS_RSA_WITH_RC4_128_SHA"; - break; - case TLS_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_RSA_WITH_NULL_SHA256: - return "TLS_RSA_WITH_NULL_SHA256"; - break; - case TLS_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA256: - return "TLS_RSA_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DH_anon_WITH_RC4_128_MD5: - return "TLS_DH_anon_WITH_RC4_128_MD5"; - break; - case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA256: - return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DH_anon_WITH_AES_256_CBC_SHA256: - return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; - break; - /* TLS 1.2 with AES GCM (RFC 5288) */ - case TLS_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DH_anon_WITH_AES_128_GCM_SHA256: - return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DH_anon_WITH_AES_256_GCM_SHA384: - return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; - break; - /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */ - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: - return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; - break; -#else - case SSL_RSA_WITH_NULL_MD5: - return "TLS_RSA_WITH_NULL_MD5"; - break; - case SSL_RSA_WITH_NULL_SHA: - return "TLS_RSA_WITH_NULL_SHA"; - break; - case SSL_RSA_WITH_RC4_128_MD5: - return "TLS_RSA_WITH_RC4_128_MD5"; - break; - case SSL_RSA_WITH_RC4_128_SHA: - return "TLS_RSA_WITH_RC4_128_SHA"; - break; - case SSL_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_anon_WITH_RC4_128_MD5: - return "TLS_DH_anon_WITH_RC4_128_MD5"; - break; - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; - break; -#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ -#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 - /* TLS PSK (RFC 4279): */ - case TLS_PSK_WITH_RC4_128_SHA: - return "TLS_PSK_WITH_RC4_128_SHA"; - break; - case TLS_PSK_WITH_3DES_EDE_CBC_SHA: - return "TLS_PSK_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_PSK_WITH_AES_128_CBC_SHA: - return "TLS_PSK_WITH_AES_128_CBC_SHA"; - break; - case TLS_PSK_WITH_AES_256_CBC_SHA: - return "TLS_PSK_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_PSK_WITH_RC4_128_SHA: - return "TLS_DHE_PSK_WITH_RC4_128_SHA"; - break; - case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"; - break; - case TLS_RSA_PSK_WITH_RC4_128_SHA: - return "TLS_RSA_PSK_WITH_RC4_128_SHA"; - break; - case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"; - break; - case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"; - break; - /* More TLS PSK (RFC 4785): */ - case TLS_PSK_WITH_NULL_SHA: - return "TLS_PSK_WITH_NULL_SHA"; - break; - case TLS_DHE_PSK_WITH_NULL_SHA: - return "TLS_DHE_PSK_WITH_NULL_SHA"; - break; - case TLS_RSA_PSK_WITH_NULL_SHA: - return "TLS_RSA_PSK_WITH_NULL_SHA"; - break; - /* Even more TLS PSK (RFC 5487): */ - case TLS_PSK_WITH_AES_128_GCM_SHA256: - return "TLS_PSK_WITH_AES_128_GCM_SHA256"; - break; - case TLS_PSK_WITH_AES_256_GCM_SHA384: - return "TLS_PSK_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; - break; - case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"; - break; - case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - return "TLS_PSK_WITH_AES_256_GCM_SHA384"; - break; - case TLS_PSK_WITH_AES_128_CBC_SHA256: - return "TLS_PSK_WITH_AES_128_CBC_SHA256"; - break; - case TLS_PSK_WITH_AES_256_CBC_SHA384: - return "TLS_PSK_WITH_AES_256_CBC_SHA384"; - break; - case TLS_PSK_WITH_NULL_SHA256: - return "TLS_PSK_WITH_NULL_SHA256"; - break; - case TLS_PSK_WITH_NULL_SHA384: - return "TLS_PSK_WITH_NULL_SHA384"; - break; - case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; - break; - case TLS_DHE_PSK_WITH_NULL_SHA256: - return "TLS_DHE_PSK_WITH_NULL_SHA256"; - break; - case TLS_DHE_PSK_WITH_NULL_SHA384: - return "TLS_RSA_PSK_WITH_NULL_SHA384"; - break; - case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"; - break; - case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"; - break; - case TLS_RSA_PSK_WITH_NULL_SHA256: - return "TLS_RSA_PSK_WITH_NULL_SHA256"; - break; - case TLS_RSA_PSK_WITH_NULL_SHA384: - return "TLS_RSA_PSK_WITH_NULL_SHA384"; - break; -#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ -#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 - /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */ - case TLS_AES_128_GCM_SHA256: - return "TLS_AES_128_GCM_SHA256"; - break; - case TLS_AES_256_GCM_SHA384: - return "TLS_AES_256_GCM_SHA384"; - break; - case TLS_CHACHA20_POLY1305_SHA256: - return "TLS_CHACHA20_POLY1305_SHA256"; - break; - case TLS_AES_128_CCM_SHA256: - return "TLS_AES_128_CCM_SHA256"; - break; - case TLS_AES_128_CCM_8_SHA256: - return "TLS_AES_128_CCM_8_SHA256"; - break; - case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; - break; - case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"; - break; -#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + /* The first ciphers in the ciphertable are continuos. Here we do small + optimization and instead of loop directly get SSL name by cipher number. + */ + if(cipher <= SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA) { + return ciphertable[cipher].name; + } + /* Iterate through the rest of the ciphers */ + for(size_t i = SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA + 1; + i < NUM_OF_CIPHERS; + ++i) { + if(ciphertable[i].num == cipher) { + return ciphertable[i].name; + } } - return "TLS_NULL_WITH_NULL_NULL"; + return ciphertable[SSL_NULL_WITH_NULL_NULL].name; } #endif /* !CURL_DISABLE_VERBOSE_STRINGS */ @@ -1087,12 +1158,14 @@ static OSStatus CopyIdentityWithLabel(char *label, (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i); err = SecIdentityCopyCertificate(identity, &cert); if(err == noErr) { + OSStatus copy_status = noErr; #if CURL_BUILD_IOS common_name = SecCertificateCopySubjectSummary(cert); #elif CURL_BUILD_MAC_10_7 - SecCertificateCopyCommonName(cert, &common_name); + copy_status = SecCertificateCopyCommonName(cert, &common_name); #endif - if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) { + if(copy_status == noErr && + CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) { CFRelease(cert); CFRelease(common_name); CFRetain(identity); @@ -1253,7 +1326,7 @@ CF_INLINE bool is_file(const char *filename) { struct_stat st; - if(filename == NULL) + if(!filename) return false; if(stat(filename, &st) == 0) @@ -1386,6 +1459,200 @@ set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } +static bool is_cipher_suite_strong(SSLCipherSuite suite_num) +{ + for(size_t i = 0; i < NUM_OF_CIPHERS; ++i) { + if(ciphertable[i].num == suite_num) { + return !ciphertable[i].weak; + } + } + /* If the cipher is not in our list, assume it is a new one + and therefore strong. Previous implementation was the same, + if cipher suite is not in the list, it was considered strong enough */ + return true; +} + +static bool is_separator(char c) +{ + /* Return whether character is a cipher list separator. */ + switch(c) { + case ' ': + case '\t': + case ':': + case ',': + case ';': + return true; + } + return false; +} + +static CURLcode sectransp_set_default_ciphers(struct Curl_easy *data, + SSLContextRef ssl_ctx) +{ + size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; + SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; + OSStatus err = noErr; + +#if CURL_BUILD_MAC + int darwinver_maj = 0, darwinver_min = 0; + + GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); +#endif /* CURL_BUILD_MAC */ + + /* Disable cipher suites that ST supports but are not safe. These ciphers + are unlikely to be used in any case since ST gives other ciphers a much + higher priority, but it's probably better that we not connect at all than + to give the user a false sense of security if the server only supports + insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ + err = SSLGetNumberSupportedCiphers(ssl_ctx, &all_ciphers_count); + if(err != noErr) { + failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d", + err); + return CURLE_SSL_CIPHER; + } + all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(!all_ciphers) { + failf(data, "SSL: Failed to allocate memory for all ciphers"); + return CURLE_OUT_OF_MEMORY; + } + allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(!allowed_ciphers) { + Curl_safefree(all_ciphers); + failf(data, "SSL: Failed to allocate memory for allowed ciphers"); + return CURLE_OUT_OF_MEMORY; + } + err = SSLGetSupportedCiphers(ssl_ctx, all_ciphers, + &all_ciphers_count); + if(err != noErr) { + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + return CURLE_SSL_CIPHER; + } + for(i = 0UL ; i < all_ciphers_count ; i++) { +#if CURL_BUILD_MAC + /* There's a known bug in early versions of Mountain Lion where ST's ECC + ciphers (cipher suite 0xC001 through 0xC032) simply do not work. + Work around the problem here by disabling those ciphers if we are + running in an affected version of OS X. */ + if(darwinver_maj == 12 && darwinver_min <= 3 && + all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { + continue; + } +#endif /* CURL_BUILD_MAC */ + if(is_cipher_suite_strong(all_ciphers[i])) { + allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; + } + } + err = SSLSetEnabledCiphers(ssl_ctx, allowed_ciphers, + allowed_ciphers_count); + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + if(err != noErr) { + failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + return CURLE_SSL_CIPHER; + } + return CURLE_OK; +} + +static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data, + SSLContextRef ssl_ctx, + const char *ciphers) +{ + size_t ciphers_count = 0; + const char *cipher_start = ciphers; + OSStatus err = noErr; + SSLCipherSuite selected_ciphers[NUM_OF_CIPHERS]; + + if(!ciphers) + return CURLE_OK; + + while(is_separator(*ciphers)) /* Skip initial separators. */ + ciphers++; + if(!*ciphers) + return CURLE_OK; + + cipher_start = ciphers; + while(*cipher_start && ciphers_count < NUM_OF_CIPHERS) { + bool cipher_found = FALSE; + size_t cipher_len = 0; + const char *cipher_end = NULL; + bool tls_name = FALSE; + + /* Skip separators */ + while(is_separator(*cipher_start)) + cipher_start++; + if(*cipher_start == '\0') { + break; + } + /* Find last position of a cipher in the ciphers string */ + cipher_end = cipher_start; + while (*cipher_end != '\0' && !is_separator(*cipher_end)) { + ++cipher_end; + } + + /* IANA cipher names start with the TLS_ or SSL_ prefix. + If the 4th symbol of the cipher is '_' we look for a cipher in the + table by its (TLS) name. + Otherwise, we try to match cipher by an alias. */ + if(cipher_start[3] == '_') { + tls_name = TRUE; + } + /* Iterate through the cipher table and look for the cipher, starting + the cipher number 0x01 because the 0x00 is not the real cipher */ + cipher_len = cipher_end - cipher_start; + for(size_t i = 1; i < NUM_OF_CIPHERS; ++i) { + const char *table_cipher_name = NULL; + if(tls_name) { + table_cipher_name = ciphertable[i].name; + } + else if(ciphertable[i].alias_name != NULL) { + table_cipher_name = ciphertable[i].alias_name; + } + else { + continue; + } + /* Compare a part of the string between separators with a cipher name + in the table and make sure we matched the whole cipher name */ + if(strncmp(cipher_start, table_cipher_name, cipher_len) == 0 + && table_cipher_name[cipher_len] == '\0') { + selected_ciphers[ciphers_count] = ciphertable[i].num; + ++ciphers_count; + cipher_found = TRUE; + break; + } + } + if(!cipher_found) { + /* It would be more human-readable if we print the wrong cipher name + but we don't want to allocate any additional memory and copy the name + into it, then add it into logs. + Also, we do not modify an original cipher list string. We just point + to positions where cipher starts and ends in the cipher list string. + The message is a bit cryptic and longer than necessary but can be + understood by humans. */ + failf(data, "SSL: cipher string \"%s\" contains unsupported cipher name" + " starting position %d and ending position %d", + ciphers, + cipher_start - ciphers, + cipher_end - ciphers); + return CURLE_SSL_CIPHER; + } + if(*cipher_end) { + cipher_start = cipher_end + 1; + } + else { + break; + } + } + /* All cipher suites in the list are found. Report to logs as-is */ + infof(data, "SSL: Setting cipher suites list \"%s\"\n", ciphers); + + err = SSLSetEnabledCiphers(ssl_ctx, selected_ciphers, ciphers_count); + if(err != noErr) { + failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + return CURLE_SSL_CIPHER; + } + return CURLE_OK; +} static CURLcode sectransp_connect_step1(struct Curl_easy *data, struct connectdata *conn, @@ -1394,28 +1661,22 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; - const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); - const struct curl_blob *ssl_cablob = NULL; + const struct curl_blob *ssl_cablob = SSL_CONN_CONFIG(ca_info_blob); + const char * const ssl_cafile = + /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ + (ssl_cablob ? NULL : SSL_CONN_CONFIG(CAfile)); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); char * const ssl_cert = SSL_SET_OPTION(primary.clientcert); const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob); -#ifndef CURL_DISABLE_PROXY bool isproxy = SSL_IS_PROXY(); - const char * const hostname = isproxy ? conn->http_proxy.host.name : - conn->host.name; - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#else - const isproxy = FALSE; - const char * const hostname = conn->host.name; - const long int port = conn->remote_port; -#endif + const char * const hostname = SSL_HOST_NAME(); + const long int port = SSL_HOST_PORT(); #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif /* ENABLE_IPV6 */ - size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; - SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; + char *ciphers; OSStatus err = noErr; #if CURL_BUILD_MAC int darwinver_maj = 0, darwinver_min = 0; @@ -1486,21 +1747,9 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, break; } case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol3); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol3); - break; case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol2); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol2); - break; + failf(data, "SSL versions not supported"); + return CURLE_NOT_BUILT_IN; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; @@ -1535,23 +1784,9 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, break; } case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, - kSSLProtocol3, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - break; case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, - kSSLProtocol2, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - break; + failf(data, "SSL versions not supported"); + return CURLE_NOT_BUILT_IN; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; @@ -1583,23 +1818,9 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, failf(data, "Your version of the OS does not support TLSv1.3"); return CURLE_SSL_CONNECT_ERROR; case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, - kSSLProtocol2, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - break; case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, - kSSLProtocol3, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - break; + failf(data, "SSL versions not supported"); + return CURLE_NOT_BUILT_IN; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; @@ -1612,14 +1833,14 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2 #ifndef CURL_DISABLE_PROXY && (!isproxy || !conn->bits.tunnel_proxy) #endif ) { - CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID)); - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2)); + infof(data, "ALPN, offering %s\n", ALPN_H2); } #endif @@ -1790,7 +2011,8 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, bool is_cert_file = (!is_cert_data) && is_file(ssl_cafile); if(!(is_cert_file || is_cert_data)) { - failf(data, "SSL: can't load CA certificate file %s", ssl_cafile); + failf(data, "SSL: can't load CA certificate file %s", + ssl_cafile ? ssl_cafile : "(blob memory)"); return CURLE_SSL_CACERT_BADFILE; } } @@ -1820,121 +2042,16 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, infof(data, "WARNING: disabling hostname validation also disables SNI.\n"); } - /* Disable cipher suites that ST supports but are not safe. These ciphers - are unlikely to be used in any case since ST gives other ciphers a much - higher priority, but it's probably better that we not connect at all than - to give the user a false sense of security if the server only supports - insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ - err = SSLGetNumberSupportedCiphers(backend->ssl_ctx, &all_ciphers_count); - if(err != noErr) { - failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d", - err); - return CURLE_SSL_CIPHER; - } - all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); - if(!all_ciphers) { - failf(data, "SSL: Failed to allocate memory for all ciphers"); - return CURLE_OUT_OF_MEMORY; - } - allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); - if(!allowed_ciphers) { - Curl_safefree(all_ciphers); - failf(data, "SSL: Failed to allocate memory for allowed ciphers"); - return CURLE_OUT_OF_MEMORY; - } - err = SSLGetSupportedCiphers(backend->ssl_ctx, all_ciphers, - &all_ciphers_count); - if(err != noErr) { - Curl_safefree(all_ciphers); - Curl_safefree(allowed_ciphers); - return CURLE_SSL_CIPHER; + ciphers = SSL_CONN_CONFIG(cipher_list); + if(ciphers) { + err = sectransp_set_selected_ciphers(data, backend->ssl_ctx, ciphers); } - for(i = 0UL ; i < all_ciphers_count ; i++) { -#if CURL_BUILD_MAC - /* There's a known bug in early versions of Mountain Lion where ST's ECC - ciphers (cipher suite 0xC001 through 0xC032) simply do not work. - Work around the problem here by disabling those ciphers if we are - running in an affected version of OS X. */ - if(darwinver_maj == 12 && darwinver_min <= 3 && - all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { - continue; - } -#endif /* CURL_BUILD_MAC */ - switch(all_ciphers[i]) { - /* Disable NULL ciphersuites: */ - case SSL_NULL_WITH_NULL_NULL: - case SSL_RSA_WITH_NULL_MD5: - case SSL_RSA_WITH_NULL_SHA: - case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ - case SSL_FORTEZZA_DMS_WITH_NULL_SHA: - case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ - case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ - case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ - case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */ - case 0x002C: /* TLS_PSK_WITH_NULL_SHA */ - case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */ - case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */ - case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */ - case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */ - case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */ - case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */ - case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */ - case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */ - /* Disable anonymous ciphersuites: */ - case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: - case SSL_DH_anon_WITH_RC4_128_MD5: - case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DH_anon_WITH_DES_CBC_SHA: - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - case TLS_DH_anon_WITH_AES_256_CBC_SHA: - case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */ - case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */ - case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ - case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ - case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ - case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */ - case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */ - case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */ - case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */ - /* Disable weak key ciphersuites: */ - case SSL_RSA_EXPORT_WITH_RC4_40_MD5: - case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: - case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: - case SSL_RSA_WITH_DES_CBC_SHA: - case SSL_DH_DSS_WITH_DES_CBC_SHA: - case SSL_DH_RSA_WITH_DES_CBC_SHA: - case SSL_DHE_DSS_WITH_DES_CBC_SHA: - case SSL_DHE_RSA_WITH_DES_CBC_SHA: - /* Disable IDEA: */ - case SSL_RSA_WITH_IDEA_CBC_SHA: - case SSL_RSA_WITH_IDEA_CBC_MD5: - /* Disable RC4: */ - case SSL_RSA_WITH_RC4_128_MD5: - case SSL_RSA_WITH_RC4_128_SHA: - case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ - case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/ - case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ - case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ - case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */ - case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */ - case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */ - break; - default: /* enable everything else */ - allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; - break; - } + else { + err = sectransp_set_default_ciphers(data, backend->ssl_ctx); } - err = SSLSetEnabledCiphers(backend->ssl_ctx, allowed_ciphers, - allowed_ciphers_count); - Curl_safefree(all_ciphers); - Curl_safefree(allowed_ciphers); if(err != noErr) { - failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + failf(data, "SSL: Unable to set ciphers for SSL/TLS handshake. " + "Error code: %d", err); return CURLE_SSL_CIPHER; } @@ -1972,7 +2089,8 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, else { CURLcode result; ssl_sessionid = - aprintf("%s:%d:%d:%s:%ld", ssl_cafile, + aprintf("%s:%d:%d:%s:%ld", + ssl_cafile ? ssl_cafile : "(blob memory)", verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); ssl_sessionid_len = strlen(ssl_sessionid); @@ -2023,21 +2141,21 @@ static long pem_to_der(const char *in, unsigned char **out, size_t *outlen) /* Jump through the separators at the beginning of the certificate. */ sep_start = strstr(in, "-----"); - if(sep_start == NULL) + if(!sep_start) return 0; cert_start = strstr(sep_start + 1, "-----"); - if(cert_start == NULL) + if(!cert_start) return -1; cert_start += 5; /* Find separator after the end of the certificate. */ cert_end = strstr(cert_start, "-----"); - if(cert_end == NULL) + if(!cert_end) return -1; sep_end = strstr(cert_end + 1, "-----"); - if(sep_end == NULL) + if(!sep_end) return -1; sep_end += 5; @@ -2112,7 +2230,7 @@ static int read_cert(const char *file, unsigned char **out, size_t *outlen) } static int append_cert_to_array(struct Curl_easy *data, - unsigned char *buf, size_t buflen, + const unsigned char *buf, size_t buflen, CFMutableArrayRef array) { CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); @@ -2150,18 +2268,14 @@ static int append_cert_to_array(struct Curl_easy *data, return CURLE_OK; } -static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, - SSLContextRef ctx) +static CURLcode verify_cert_buf(struct Curl_easy *data, + const unsigned char *certbuf, size_t buflen, + SSLContextRef ctx) { int n = 0, rc; long res; - unsigned char *certbuf, *der; - size_t buflen, derlen, offset = 0; - - if(read_cert(cafile, &certbuf, &buflen) < 0) { - failf(data, "SSL: failed to read or invalid CA certificate"); - return CURLE_SSL_CACERT_BADFILE; - } + unsigned char *der; + size_t derlen, offset = 0; /* * Certbuf now contains the contents of the certificate file, which can be @@ -2174,8 +2288,7 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, */ CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - if(array == NULL) { - free(certbuf); + if(!array) { failf(data, "SSL: out of memory creating CA certificate array"); return CURLE_OUT_OF_MEMORY; } @@ -2189,7 +2302,6 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, */ res = pem_to_der((const char *)certbuf + offset, &der, &derlen); if(res < 0) { - free(certbuf); CFRelease(array); failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle", n, offset); @@ -2200,7 +2312,6 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, if(res == 0 && offset == 0) { /* This is not a PEM file, probably a certificate in DER format. */ rc = append_cert_to_array(data, certbuf, buflen, array); - free(certbuf); if(rc != CURLE_OK) { CFRelease(array); return rc; @@ -2209,14 +2320,12 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, } else if(res == 0) { /* No more certificates in the bundle. */ - free(certbuf); break; } rc = append_cert_to_array(data, der, derlen, array); free(der); if(rc != CURLE_OK) { - free(certbuf); CFRelease(array); return rc; } @@ -2224,7 +2333,7 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, SecTrustRef trust; OSStatus ret = SSLCopyPeerTrust(ctx, &trust); - if(trust == NULL) { + if(!trust) { failf(data, "SSL: error getting certificate chain"); CFRelease(array); return CURLE_PEER_FAILED_VERIFICATION; @@ -2273,6 +2382,38 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, } } +static CURLcode verify_cert(struct Curl_easy *data, const char *cafile, + const struct curl_blob *ca_info_blob, + SSLContextRef ctx) +{ + int result; + unsigned char *certbuf; + size_t buflen; + + if(ca_info_blob) { + certbuf = (unsigned char *)malloc(ca_info_blob->len + 1); + if(!certbuf) { + return CURLE_OUT_OF_MEMORY; + } + buflen = ca_info_blob->len; + memcpy(certbuf, ca_info_blob->data, ca_info_blob->len); + certbuf[ca_info_blob->len]='\0'; + } + else if(cafile) { + if(read_cert(cafile, &certbuf, &buflen) < 0) { + failf(data, "SSL: failed to read or invalid CA certificate"); + return CURLE_SSL_CACERT_BADFILE; + } + } + else + return CURLE_SSL_CACERT_BADFILE; + + result = verify_cert_buf(data, certbuf, buflen, ctx); + free(certbuf); + return result; +} + + #ifdef SECTRANSP_PINNEDPUBKEY static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, SSLContextRef ctx, @@ -2297,19 +2438,19 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, do { SecTrustRef trust; OSStatus ret = SSLCopyPeerTrust(ctx, &trust); - if(ret != noErr || trust == NULL) + if(ret != noErr || !trust) break; SecKeyRef keyRef = SecTrustCopyPublicKey(trust); CFRelease(trust); - if(keyRef == NULL) + if(!keyRef) break; #ifdef SECTRANSP_PINNEDPUBKEY_V1 publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); CFRelease(keyRef); - if(publicKeyBits == NULL) + if(!publicKeyBits) break; #elif SECTRANSP_PINNEDPUBKEY_V2 @@ -2317,7 +2458,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, &publicKeyBits); CFRelease(keyRef); - if(success != errSecSuccess || publicKeyBits == NULL) + if(success != errSecSuccess || !publicKeyBits) break; #endif /* SECTRANSP_PINNEDPUBKEY_V2 */ @@ -2389,12 +2530,7 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, OSStatus err; SSLCipherSuite cipher; SSLProtocol protocol = 0; -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - const char * const hostname = conn->host.name; -#endif + const char * const hostname = SSL_HOST_NAME(); DEBUGASSERT(ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state @@ -2413,8 +2549,10 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, /* The below is errSSLServerAuthCompleted; it's not defined in Leopard's headers */ case -9841: - if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { - CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data, + if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) && + SSL_CONN_CONFIG(verifypeer)) { + CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile), + SSL_CONN_CONFIG(ca_info_blob), backend->ssl_ctx); if(result) return result; @@ -2601,8 +2739,9 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, #if CURL_BUILD_MAC_10_6 /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */ case errSSLClientCertRequested: - failf(data, "The server has requested a client certificate"); - break; + failf(data, "Server requested a client certificate during the " + "handshake"); + return CURLE_SSL_CLIENTCERT; #endif #if CURL_BUILD_MAC_10_9 /* Alias for errSSLLast, end of error range */ @@ -2640,11 +2779,11 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, switch(protocol) { case kSSLProtocol2: infof(data, "SSL 2.0 connection using %s\n", - SSLCipherNameForNumber(cipher)); + TLSCipherNameForNumber(cipher)); break; case kSSLProtocol3: infof(data, "SSL 3.0 connection using %s\n", - SSLCipherNameForNumber(cipher)); + TLSCipherNameForNumber(cipher)); break; case kTLSProtocol1: infof(data, "TLS 1.0 connection using %s\n", @@ -2681,10 +2820,9 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1) chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0); -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(chosenProtocol && - !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID), - 0)) { + !CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -3258,8 +3396,10 @@ static ssize_t sectransp_recv(struct Curl_easy *data, /* The below is errSSLPeerAuthCompleted; it's not defined in Leopard's headers */ case -9841: - if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { - CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data, + if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) && + SSL_CONN_CONFIG(verifypeer)) { + CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile), + SSL_CONN_CONFIG(ca_info_blob), backend->ssl_ctx); if(result) return result; @@ -3286,6 +3426,7 @@ static void *sectransp_get_internals(struct ssl_connect_data *connssl, const struct Curl_ssl Curl_ssl_sectransp = { { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */ + SSLSUPP_CAINFO_BLOB | #ifdef SECTRANSP_PINNEDPUBKEY SSLSUPP_PINNEDPUBKEY, #else @@ -3313,7 +3454,9 @@ const struct Curl_ssl Curl_ssl_sectransp = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ sectransp_false_start, /* false_start */ - sectransp_sha256sum /* sha256sum */ + sectransp_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #ifdef __clang__ diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c index 2e07df0a04..65f4f773dd 100644 --- a/libs/libcurl/src/vtls/vtls.c +++ b/libs/libcurl/src/vtls/vtls.c @@ -135,6 +135,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, (data->verifyhost == needle->verifyhost) && (data->verifystatus == needle->verifystatus) && blobcmp(data->cert_blob, needle->cert_blob) && + blobcmp(data->ca_info_blob, needle->ca_info_blob) && Curl_safe_strcasecompare(data->CApath, needle->CApath) && Curl_safe_strcasecompare(data->CAfile, needle->CAfile) && Curl_safe_strcasecompare(data->clientcert, needle->clientcert) && @@ -161,6 +162,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source, dest->sessionid = source->sessionid; CLONE_BLOB(cert_blob); + CLONE_BLOB(ca_info_blob); CLONE_STRING(CApath); CLONE_STRING(CAfile); CLONE_STRING(clientcert); @@ -185,6 +187,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) Curl_safefree(sslc->cipher_list13); Curl_safefree(sslc->pinned_key); Curl_safefree(sslc->cert_blob); + Curl_safefree(sslc->ca_info_blob); Curl_safefree(sslc->curves); } @@ -315,6 +318,8 @@ Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn, if(!result) Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */ + else + conn->ssl[sockindex].use = FALSE; return result; } @@ -338,7 +343,9 @@ Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, /* mark this is being ssl requested from here on. */ conn->ssl[sockindex].use = TRUE; result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done); - if(!result && *done) + if(result) + conn->ssl[sockindex].use = FALSE; + else if(*done) Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */ return result; } @@ -579,6 +586,25 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, return CURLE_OK; } +void Curl_ssl_associate_conn(struct Curl_easy *data, + struct connectdata *conn) +{ + if(Curl_ssl->associate_connection) { + Curl_ssl->associate_connection(data, conn, FIRSTSOCKET); + if(conn->sock[SECONDARYSOCKET] && conn->bits.sock_accepted) + Curl_ssl->associate_connection(data, conn, SECONDARYSOCKET); + } +} + +void Curl_ssl_detach_conn(struct Curl_easy *data, + struct connectdata *conn) +{ + if(Curl_ssl->disassociate_connection) { + Curl_ssl->disassociate_connection(data, FIRSTSOCKET); + if(conn->sock[SECONDARYSOCKET] && conn->bits.sock_accepted) + Curl_ssl->disassociate_connection(data, SECONDARYSOCKET); + } +} void Curl_ssl_close_all(struct Curl_easy *data) { @@ -1207,7 +1233,9 @@ static const struct Curl_ssl Curl_ssl_multi = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - NULL /* sha256sum */ + NULL, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; const struct Curl_ssl *Curl_ssl = diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h index 2b43e7744b..7f93e7aedb 100644 --- a/libs/libcurl/src/vtls/vtls.h +++ b/libs/libcurl/src/vtls/vtls.h @@ -32,6 +32,7 @@ struct ssl_connect_data; #define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */ #define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */ #define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */ +#define SSLSUPP_CAINFO_BLOB (1<<6) struct Curl_ssl { /* @@ -83,6 +84,11 @@ struct Curl_ssl { bool (*false_start)(void); CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen, unsigned char *sha256sum, size_t sha256sumlen); + + void (*associate_connection)(struct Curl_easy *data, + struct connectdata *conn, + int sockindex); + void (*disassociate_connection)(struct Curl_easy *data, int sockindex); }; #ifdef USE_SSL @@ -126,9 +132,11 @@ bool Curl_ssl_tls13_ciphersuites(void); #define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */ #endif -/* see https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */ +/* see https://www.iana.org/assignments/tls-extensiontype-values/ */ #define ALPN_HTTP_1_1_LENGTH 8 #define ALPN_HTTP_1_1 "http/1.1" +#define ALPN_H2_LENGTH 2 +#define ALPN_H2 "h2" /* set of helper macros for the backends to access the correct fields. For the proxy or for the remote host - to properly support HTTPS proxy */ @@ -148,6 +156,8 @@ bool Curl_ssl_tls13_ciphersuites(void); (SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name) #define SSL_HOST_DISPNAME() \ (SSL_IS_PROXY() ? conn->http_proxy.host.dispname : conn->host.dispname) +#define SSL_HOST_PORT() \ + (SSL_IS_PROXY() ? conn->port : conn->remote_port) #define SSL_PINNED_PUB_KEY() (SSL_IS_PROXY() \ ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] \ : data->set.str[STRING_SSL_PINNEDPUBLICKEY]) @@ -158,6 +168,7 @@ bool Curl_ssl_tls13_ciphersuites(void); #define SSL_CONN_CONFIG(var) conn->ssl_config.var #define SSL_HOST_NAME() conn->host.name #define SSL_HOST_DISPNAME() conn->host.dispname +#define SSL_HOST_PORT() conn->remote_port #define SSL_PINNED_PUB_KEY() \ data->set.str[STRING_SSL_PINNEDPUBLICKEY] #endif @@ -277,6 +288,11 @@ bool Curl_ssl_cert_status_request(void); bool Curl_ssl_false_start(void); +void Curl_ssl_associate_conn(struct Curl_easy *data, + struct connectdata *conn); +void Curl_ssl_detach_conn(struct Curl_easy *data, + struct connectdata *conn); + #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ #else /* if not USE_SSL */ @@ -303,6 +319,8 @@ bool Curl_ssl_false_start(void); #define Curl_ssl_cert_status_request() FALSE #define Curl_ssl_false_start() FALSE #define Curl_ssl_tls13_ciphersuites() FALSE +#define Curl_ssl_associate_conn(a,b) Curl_nop_stmt +#define Curl_ssl_detach_conn(a,b) Curl_nop_stmt #endif #endif /* HEADER_CURL_VTLS_H */ diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index c6f428034f..60e27e3662 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -47,16 +47,6 @@ #endif #endif -/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in - options.h, but is only seen in >= 3.6.6 since that's when they started - disabling SSLv3 by default. */ -#ifndef WOLFSSL_ALLOW_SSLV3 -#if (LIBWOLFSSL_VERSION_HEX < 0x03006006) || \ - defined(HAVE_WOLFSSLV3_CLIENT_METHOD) -#define WOLFSSL_ALLOW_SSLV3 -#endif -#endif - #include <limits.h> #include "urldata.h" @@ -285,18 +275,6 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, failf(data, "wolfSSL: TLS 1.3 is not yet supported"); return CURLE_SSL_CONNECT_ERROR; #endif - case CURL_SSLVERSION_SSLv3: -#ifdef WOLFSSL_ALLOW_SSLV3 - req_method = SSLv3_client_method(); - use_sni(FALSE); -#else - failf(data, "wolfSSL does not support SSLv3"); - return CURLE_NOT_BUILT_IN; -#endif - break; - case CURL_SSLVERSION_SSLv2: - failf(data, "wolfSSL does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; @@ -418,12 +396,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, #ifdef ENABLE_IPV6 struct in6_addr addr6; #endif -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - const char * const hostname = conn->host.name; -#endif + const char * const hostname = SSL_HOST_NAME(); size_t hostname_len = strlen(hostname); if((hostname_len < USHRT_MAX) && (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) && @@ -474,10 +447,10 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, /* wolfSSL's ALPN protocol name list format is a comma separated string of protocols in descending order of preference, eg: "h2,http/1.1" */ -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2) { - strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ","); - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + strcpy(protocols + strlen(protocols), ALPN_H2 ","); + infof(data, "ALPN, offering %s\n", ALPN_H2); } #endif @@ -552,20 +525,9 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, int ret = -1; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const char * const dispname = SSL_IS_PROXY() ? - conn->http_proxy.host.dispname : conn->host.dispname; - const char * const pinnedpubkey = SSL_IS_PROXY() ? - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; -#else - const char * const hostname = conn->host.name; - const char * const dispname = conn->host.dispname; - const char * const pinnedpubkey = - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; -#endif + const char * const hostname = SSL_HOST_NAME(); + const char * const dispname = SSL_HOST_DISPNAME(); + const char * const pinnedpubkey = SSL_PINNED_PUB_KEY(); conn->recv[sockindex] = wolfssl_recv; conn->send[sockindex] = wolfssl_send; @@ -725,11 +687,10 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, if(protocol_len == ALPN_HTTP_1_1_LENGTH && !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) conn->negnpn = CURL_HTTP_VERSION_1_1; -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 else if(data->state.httpwant >= CURL_HTTP_VERSION_2 && - protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID, - NGHTTP2_PROTO_VERSION_ID_LEN)) + protocol_len == ALPN_H2_LENGTH && + !memcmp(protocol, ALPN_H2, ALPN_H2_LENGTH)) conn->negnpn = CURL_HTTP_VERSION_2; #endif else @@ -820,7 +781,7 @@ static ssize_t wolfssl_send(struct Curl_easy *data, int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; int rc = SSL_write(backend->handle, mem, memlen); - if(rc < 0) { + if(rc <= 0) { int err = SSL_get_error(backend->handle, rc); switch(err) { @@ -1164,7 +1125,9 @@ const struct Curl_ssl Curl_ssl_wolfssl = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - wolfssl_sha256sum /* sha256sum */ + wolfssl_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif diff --git a/libs/libcurl/src/x509asn1.c b/libs/libcurl/src/x509asn1.c index f29aa05b87..281c97248b 100644 --- a/libs/libcurl/src/x509asn1.c +++ b/libs/libcurl/src/x509asn1.c @@ -1145,10 +1145,8 @@ CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn, int matched = -1; size_t addrlen = (size_t) -1; ssize_t len; - const char *const hostname = SSL_IS_PROXY()? - conn->http_proxy.host.name : conn->host.name; - const char *const dispname = SSL_IS_PROXY()? - conn->http_proxy.host.dispname : conn->host.dispname; + const char * const hostname = SSL_HOST_NAME(); + const char * const dispname = SSL_HOST_DISPNAME(); #ifdef ENABLE_IPV6 struct in6_addr addr; #else |