summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2023-09-16 22:53:10 +0300
committerdartraiden <wowemuh@gmail.com>2023-09-16 22:53:10 +0300
commit47346b568cae68439c3d39f06f8c4ab14911475d (patch)
tree617c91959e8c606a315a1aaaf13a38f5b7333e9a
parentcb1787afbb67184321f206f13f836b63cd06740a (diff)
libcurl: update to 8.3.0
-rw-r--r--libs/libcurl/docs/CHANGES5501
-rw-r--r--libs/libcurl/docs/THANKS49
-rw-r--r--libs/libcurl/include/curl/curl.h25
-rw-r--r--libs/libcurl/include/curl/curlver.h10
-rw-r--r--libs/libcurl/include/curl/mprintf.h38
-rw-r--r--libs/libcurl/include/curl/multi.h2
-rw-r--r--libs/libcurl/include/curl/system.h18
-rw-r--r--libs/libcurl/include/curl/urlapi.h3
-rw-r--r--libs/libcurl/libcurl.vcxproj14
-rw-r--r--libs/libcurl/libcurl.vcxproj.filters18
-rw-r--r--libs/libcurl/src/CMakeLists.txt214
-rw-r--r--libs/libcurl/src/Makefile.in270
-rw-r--r--libs/libcurl/src/Makefile.inc8
-rw-r--r--libs/libcurl/src/altsvc.c82
-rw-r--r--libs/libcurl/src/amigaos.h1
-rw-r--r--libs/libcurl/src/asyn-ares.c16
-rw-r--r--libs/libcurl/src/asyn-thread.c8
-rw-r--r--libs/libcurl/src/base64.c5
-rw-r--r--libs/libcurl/src/c-hyper.c114
-rw-r--r--libs/libcurl/src/c-hyper.h1
-rw-r--r--libs/libcurl/src/cf-h1-proxy.c54
-rw-r--r--libs/libcurl/src/cf-h2-proxy.c374
-rw-r--r--libs/libcurl/src/cf-haproxy.c10
-rw-r--r--libs/libcurl/src/cf-https-connect.c38
-rw-r--r--libs/libcurl/src/cf-socket.c201
-rw-r--r--libs/libcurl/src/cfilters.c3
-rw-r--r--libs/libcurl/src/config-amigaos.h1
-rw-r--r--libs/libcurl/src/config-mac.h2
-rw-r--r--libs/libcurl/src/config-os400.h12
-rw-r--r--libs/libcurl/src/config-riscos.h9
-rw-r--r--libs/libcurl/src/config-win32.h10
-rw-r--r--libs/libcurl/src/config-win32ce.h3
-rw-r--r--libs/libcurl/src/connect.c66
-rw-r--r--libs/libcurl/src/curl_base64.h9
-rw-r--r--libs/libcurl/src/curl_config.h.cmake47
-rw-r--r--libs/libcurl/src/curl_config.h.in42
-rw-r--r--libs/libcurl/src/curl_des.c11
-rw-r--r--libs/libcurl/src/curl_des.h11
-rw-r--r--libs/libcurl/src/curl_hmac.h3
-rw-r--r--libs/libcurl/src/curl_log.h121
-rw-r--r--libs/libcurl/src/curl_md4.h9
-rw-r--r--libs/libcurl/src/curl_md5.h4
-rw-r--r--libs/libcurl/src/curl_ntlm_core.c86
-rw-r--r--libs/libcurl/src/curl_ntlm_core.h9
-rw-r--r--libs/libcurl/src/curl_sasl.c8
-rw-r--r--libs/libcurl/src/curl_setup.h37
-rw-r--r--libs/libcurl/src/curl_sha256.h4
-rw-r--r--libs/libcurl/src/curl_trc.c (renamed from libs/libcurl/src/curl_log.c)83
-rw-r--r--libs/libcurl/src/curl_trc.h150
-rw-r--r--libs/libcurl/src/easy.c32
-rw-r--r--libs/libcurl/src/formdata.c4
-rw-r--r--libs/libcurl/src/formdata.h7
-rw-r--r--libs/libcurl/src/ftp.c9
-rw-r--r--libs/libcurl/src/gopher.c4
-rw-r--r--libs/libcurl/src/headers.c13
-rw-r--r--libs/libcurl/src/hmac.c5
-rw-r--r--libs/libcurl/src/hostip.c30
-rw-r--r--libs/libcurl/src/http.c176
-rw-r--r--libs/libcurl/src/http.h18
-rw-r--r--libs/libcurl/src/http1.c2
-rw-r--r--libs/libcurl/src/http2.c598
-rw-r--r--libs/libcurl/src/http_aws_sigv4.c249
-rw-r--r--libs/libcurl/src/http_digest.c2
-rw-r--r--libs/libcurl/src/http_digest.h4
-rw-r--r--libs/libcurl/src/http_proxy.c12
-rw-r--r--libs/libcurl/src/idn.c120
-rw-r--r--libs/libcurl/src/idn.h6
-rw-r--r--libs/libcurl/src/if2ip.c4
-rw-r--r--libs/libcurl/src/imap.c103
-rw-r--r--libs/libcurl/src/inet_ntop.c5
-rw-r--r--libs/libcurl/src/krb5.c13
-rw-r--r--libs/libcurl/src/ldap.c4
-rw-r--r--libs/libcurl/src/libcurl.plist6
-rw-r--r--libs/libcurl/src/macos.c17
-rw-r--r--libs/libcurl/src/macos.h3
-rw-r--r--libs/libcurl/src/md4.c42
-rw-r--r--libs/libcurl/src/md5.c8
-rw-r--r--libs/libcurl/src/mime.c18
-rw-r--r--libs/libcurl/src/mqtt.c4
-rw-r--r--libs/libcurl/src/multi.c152
-rw-r--r--libs/libcurl/src/multiif.h5
-rw-r--r--libs/libcurl/src/pingpong.c12
-rw-r--r--libs/libcurl/src/pop3.c13
-rw-r--r--libs/libcurl/src/rand.c3
-rw-r--r--libs/libcurl/src/rand.h14
-rw-r--r--libs/libcurl/src/sendf.c81
-rw-r--r--libs/libcurl/src/sendf.h9
-rw-r--r--libs/libcurl/src/setopt.c17
-rw-r--r--libs/libcurl/src/setup-os400.h91
-rw-r--r--libs/libcurl/src/setup-vms.h1
-rw-r--r--libs/libcurl/src/sha256.c21
-rw-r--r--libs/libcurl/src/smb.c10
-rw-r--r--libs/libcurl/src/smtp.c3
-rw-r--r--libs/libcurl/src/strerror.c2
-rw-r--r--libs/libcurl/src/system_win32.h5
-rw-r--r--libs/libcurl/src/telnet.c8
-rw-r--r--libs/libcurl/src/transfer.c22
-rw-r--r--libs/libcurl/src/url.c80
-rw-r--r--libs/libcurl/src/urlapi.c52
-rw-r--r--libs/libcurl/src/urldata.h75
-rw-r--r--libs/libcurl/src/vauth/cram.c4
-rw-r--r--libs/libcurl/src/vauth/digest.c6
-rw-r--r--libs/libcurl/src/vauth/digest.h2
-rw-r--r--libs/libcurl/src/vauth/digest_sspi.c4
-rw-r--r--libs/libcurl/src/vauth/ntlm.c13
-rw-r--r--libs/libcurl/src/vauth/vauth.h6
-rw-r--r--libs/libcurl/src/vquic/curl_msh3.c64
-rw-r--r--libs/libcurl/src/vquic/curl_ngtcp2.c310
-rw-r--r--libs/libcurl/src/vquic/curl_quiche.c382
-rw-r--r--libs/libcurl/src/vquic/vquic.c88
-rw-r--r--libs/libcurl/src/vquic/vquic_int.h3
-rw-r--r--libs/libcurl/src/vssh/libssh.c5
-rw-r--r--libs/libcurl/src/vssh/libssh2.c12
-rw-r--r--libs/libcurl/src/vssh/wolfssh.c2
-rw-r--r--libs/libcurl/src/vtls/bearssl.c89
-rw-r--r--libs/libcurl/src/vtls/gskit.c1329
-rw-r--r--libs/libcurl/src/vtls/gskit.h40
-rw-r--r--libs/libcurl/src/vtls/gtls.c2
-rw-r--r--libs/libcurl/src/vtls/hostcheck.c5
-rw-r--r--libs/libcurl/src/vtls/mbedtls.c10
-rw-r--r--libs/libcurl/src/vtls/nss.c2551
-rw-r--r--libs/libcurl/src/vtls/nssg.h41
-rw-r--r--libs/libcurl/src/vtls/openssl.c80
-rw-r--r--libs/libcurl/src/vtls/rustls.c18
-rw-r--r--libs/libcurl/src/vtls/schannel.c74
-rw-r--r--libs/libcurl/src/vtls/schannel.h3
-rw-r--r--libs/libcurl/src/vtls/schannel_int.h52
-rw-r--r--libs/libcurl/src/vtls/schannel_verify.c49
-rw-r--r--libs/libcurl/src/vtls/sectransp.c64
-rw-r--r--libs/libcurl/src/vtls/vtls.c59
-rw-r--r--libs/libcurl/src/vtls/vtls.h2
-rw-r--r--libs/libcurl/src/vtls/vtls_int.h2
-rw-r--r--libs/libcurl/src/vtls/wolfssl.c176
-rw-r--r--libs/libcurl/src/vtls/x509asn1.c21
-rw-r--r--libs/libcurl/src/vtls/x509asn1.h7
135 files changed, 6360 insertions, 9223 deletions
diff --git a/libs/libcurl/docs/CHANGES b/libs/libcurl/docs/CHANGES
index c18d77996a..45791b0d92 100644
--- a/libs/libcurl/docs/CHANGES
+++ b/libs/libcurl/docs/CHANGES
@@ -6,6 +6,2741 @@
Changelog
+Version 8.3.0 (13 Sep 2023)
+
+Daniel Stenberg (13 Sep 2023)
+
+- RELEASE-NOTES: syn ced
+
+ curl 8.3.0 release
+
+- THANKS: contributors from 8.3.0
+
+Thorsten Klein (12 Sep 2023)
+
+- cmake: set SIZEOF_LONG_LONG in curl_config.h
+
+ in order to support 32bit builds regarding wolfssl CTC_SETTINGS
+
+ Closes #11839
+
+Jay Satiro (12 Sep 2023)
+
+- curl_ngtcp2: fix error message
+
+- http_aws_sigv4: handle no-value user header entries
+
+ - Handle user headers in format 'name:' and 'name;' with no value.
+
+ The former is used when the user wants to remove an internal libcurl
+ header and the latter is used when the user actually wants to send a
+ no-value header in the format 'name:' (note the semi-colon is converted
+ by libcurl to a colon).
+
+ Prior to this change the AWS header import code did not special case
+ either of those and the generated AWS SignedHeaders would be incorrect.
+
+ Reported-by: apparentorder@users.noreply.github.com
+
+ Ref: https://curl.se/docs/manpage.html#-H
+
+ Fixes https://github.com/curl/curl/issues/11664
+ Closes https://github.com/curl/curl/pull/11668
+
+Dan Fandrich (11 Sep 2023)
+
+- CI: run pytest with the -v option
+
+ This lists of the test cases being run so it can be tracked over time.
+
+ Closes #11824
+
+Daniel Stenberg (11 Sep 2023)
+
+- HTTP3: the msquic backend is not functional
+
+ I ask that we do not submit bugs for this backend just yet as we know it
+ does not fully work.
+
+ Closes #11831
+ Closes #11819
+
+- aws_sigv4: the query canon code miscounted URL encoded input
+
+ Added some extra ampersands to test 439 to verify "blank" query parts
+
+ Follow-up to fc76a24c53b08cdf
+
+ Closes #11829
+
+vvb2060 (11 Sep 2023)
+
+- quic: don't set SNI if hostname is an IP address
+
+ We already do this for TLS connections.
+
+ RFC 6066 says: Literal IPv4 and IPv6 addresses are not permitted in
+ "HostName".
+
+ Ref: https://www.rfc-editor.org/rfc/rfc6066#section-3
+
+ Fixes https://github.com/curl/curl/issues/11827
+ Closes https://github.com/curl/curl/pull/11828
+
+Daniel Stenberg (10 Sep 2023)
+
+- RELEASE-NOTES: synced
+
+Benoit Pierre (10 Sep 2023)
+
+- configure: fix `HAVE_TIME_T_UNSIGNED` check
+
+ The syntax was incorrect (need a proper main body), and the test
+ condition was wrong (resulting in a signed `time_t` detected as
+ unsigned).
+
+ Closes #11825
+
+Daniel Stenberg (9 Sep 2023)
+
+- THANKS-filter: pszlazak on github
+
+pszlazak (9 Sep 2023)
+
+- include.d: explain headers not printed with --fail before 7.75.0
+
+ Prior to 7.75.0 response headers were not printed if -f/--fail was used
+ and an error was reported by server. This was fixed in ab525c0
+ (precedes 7.75.0).
+
+ Closes #11822
+
+Daniel Stenberg (8 Sep 2023)
+
+- http_aws_sigv4: skip the op if the query pair is zero bytes
+
+ Follow-up to fc76a24c53b08cdf
+
+ Spotted by OSS-Fuzz
+
+ Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=62175
+ Closes #11823
+
+- cmdline-docs: use present tense, not future
+
+ + some smaller cleanups
+
+ Closes #11821
+
+- cmdline-docs: make sure to phrase it as "added in ...."
+
+ References to things that were added or changed in a specific version
+ should be specified as "(added in [version]) for two reasons:
+
+ 1 - consistency
+
+ 2 - to allow gen.pl to strip them out if deemed referring to too old
+ versions
+
+ Closes #11821
+
+Jay Satiro (8 Sep 2023)
+
+- docs: mark --ssl-revoke-best-effort as Schannel specific
+
+ Closes https://github.com/curl/curl/pull/11760
+
+Nathan Moinvaziri (8 Sep 2023)
+
+- schannel: fix ordering of cert chain info
+
+ - Use CERT_CONTEXT's pbCertEncoded to determine chain order.
+
+ CERT_CONTEXT from SECPKG_ATTR_REMOTE_CERT_CONTEXT contains
+ end-entity/server certificate in pbCertEncoded. We can use this pointer
+ to determine the order of certificates when enumerating hCertStore using
+ CertEnumCertificatesInStore.
+
+ This change is to help ensure that the ordering of the certificate chain
+ requested by the user via CURLINFO_CERTINFO has the same ordering on all
+ versions of Windows.
+
+ Prior to this change Schannel certificate order was reversed in 8986df80
+ but that was later reverted in f540a39b when it was discovered that
+ Windows 11 22H2 does the reversal on its own.
+
+ Ref: https://github.com/curl/curl/issues/9706
+
+ Closes https://github.com/curl/curl/pull/11632
+
+Chris Talbot (8 Sep 2023)
+
+- digest: Use hostname to generate spn instead of realm
+
+ In https://www.rfc-editor.org/rfc/rfc2831#section-2.1.2
+
+ digest-uri-value should be serv-type "/" host , where host is:
+
+ The DNS host name or IP address for the service requested. The
+ DNS host name must be the fully-qualified canonical name of the
+ host. The DNS host name is the preferred form; see notes on server
+ processing of the digest-uri.
+
+ Realm may not be the host, so we must specify the host explicitly.
+
+ Note this change only affects the non-SSPI digest code. The digest code
+ used by SSPI builds already uses the hostname to generate the spn.
+
+ Ref: https://github.com/curl/curl/issues/11369
+
+ Closes https://github.com/curl/curl/pull/11395
+
+Daniel Stenberg (7 Sep 2023)
+
+- docs: remove use of the word 'very'
+
+ It is mostly superfluous. proselint would complain.
+
+ Closes #11818
+
+- curl_multi_remove_handle.3: clarify what happens with connection
+
+ Closes #11817
+
+- RELEASE-NOTES: synced
+
+- test439: verify query canonization for aws-sigv4
+
+- tool_operate: make aws-sigv4 not require TLS to be used
+
+ Maybe not used too often, but we want it for testing and it should work.
+
+- http_aws_sigv4: canonicalize the query
+
+ Percent encoding needs to be done using uppercase, and most
+ non-alphanumerical must be percent-encoded.
+
+ Fixes #11794
+ Reported-by: John Walker
+ Closes #11806
+
+Wyatt O'Day (7 Sep 2023)
+
+- lib: add ability to disable auths individually
+
+ Both with configure and cmake
+
+ Closes #11490
+
+Stefan Eissing (7 Sep 2023)
+
+- ngtcp2: fix handling of large requests
+
+ - requests >64K are send in parts to the filter
+ - fix parsing of the request to assemble it correctly
+ from several sends
+ - open a QUIC stream only when the complete request has
+ been collected
+
+ Closes #11815
+
+- openssl: when CURLOPT_SSL_CTX_FUNCTION is registered, init x509 store before
+
+ - we delay loading the x509 store to shorten the handshake time.
+ However an application callback installed via CURLOPT_SSL_CTX_FUNCTION
+ may need to have the store loaded and try to manipulate it.
+ - load the x509 store before invoking the app callback
+
+ Fixes #11800
+ Reported-by: guoxinvmware on github
+ Cloes #11805
+
+Daniel Stenberg (7 Sep 2023)
+
+- krb5: fix "implicit conversion loses integer precision" warnings
+
+ conversions to/from enum and unsigned chars
+
+ Closes #11814
+
+Stefan Eissing (7 Sep 2023)
+
+- pytest: improvements
+
+ - set CURL_CI for pytest runs in CI environments
+ - exclude timing sensitive tests from CI runs
+ - for failed results, list only the log and stat of
+ the failed transfer
+
+ - fix type in http.c comment
+
+ Closes #11812
+
+- CI: move on to ngtcp2 v0.19.1
+
+ Closes #11809
+
+Dan Fandrich (5 Sep 2023)
+
+- CI: run Circle macOS builds on x86 for now
+
+ The ARM machines aren't ready for us and requesting them now causes
+ warnings e-mails to be sent to some PR pushers.
+
+ Ref: #11771
+
+Viktor Szakats (5 Sep 2023)
+
+- http3: adjust cast for ngtcp2 v0.19.0
+
+ ngtcp2 v0.19.0 made size of `ecn` member of `ngtcp2_pkt_info`
+ an `uint8_t` (was: `uint32_t`). Adjust our local cast accordingly.
+
+ Fixes:
+ ```
+ ./curl/lib/vquic/curl_ngtcp2.c:1912:12: warning: implicit conversion loses in
+ teger precision: 'uint32_t' (aka 'unsigned int') to 'uint8_t' (aka 'unsigned
+ char') [-Wimplicit-int-conversion]
+ pi.ecn = (uint32_t)ecn;
+ ~ ^~~~~~~~~~~~~
+ ```
+
+ Also bump ngtcp2, nghttp3 and nghttp2 to their latest versions in our
+ docs and CI.
+
+ Ref: https://github.com/ngtcp2/ngtcp2/commit/80447281bbc94af53f8aa7a4cfc19175
+ 782894a3
+ Ref: https://github.com/ngtcp2/ngtcp2/pull/877
+ Closes #11798
+
+Stefan Eissing (5 Sep 2023)
+
+- http: fix sending of large requests
+
+ - refs #11342 where errors with git https interactions
+ were observed
+ - problem was caused by 1st sends of size larger than 64KB
+ which resulted in later retries of 64KB only
+ - limit sending of 1st block to 64KB
+ - adjust h2/h3 filters to cope with parsing the HTTP/1.1
+ formatted request in chunks
+
+ - introducing Curl_nwrite() as companion to Curl_write()
+ for the many cases where the sockindex is already known
+
+ Fixes #11342 (again)
+ Closes #11803
+
+- pytest: fix check for slow_network skips to only apply when intended
+
+ Closes #11801
+
+Daniel Stenberg (5 Sep 2023)
+
+- curl_url_get/set.3: add missing semicolon in SYNOPSIS
+
+- CURLOPT_URL.3: explain curl_url_set() uses the same parser
+
+- CURLOPT_URL.3: add two URL API calls in the see-also section
+
+Dan Fandrich (4 Sep 2023)
+
+- CI: add a 32-bit i686 Linux build
+
+ This is done by cross-compiling under regular x86_64 Linux. Since the
+ kernel offers backwards compatibility, the binaries can be tested as
+ normal.
+
+ Closes #11799
+
+- tests: fix a type warning on 32-bit x86
+
+Viktor Szakats (4 Sep 2023)
+
+- tests: delete stray `.orig` file
+
+ Follow-up to 331b89a319d0067fa1e6441719307cfef9c7960f
+ Closes #11797
+
+Daniel Stenberg (4 Sep 2023)
+
+- RELEASE-NOTES: synced
+
+Viktor Szakats (4 Sep 2023)
+
+- lib: silence compiler warning in inet_ntop6
+
+ ```
+ ./curl/lib/inet_ntop.c:121:21: warning: possible misuse of comma operator her
+ e [-Wcomma]
+ cur.base = i, cur.len = 1;
+ ^
+ ./curl/lib/inet_ntop.c:121:9: note: cast expression to void to silence warnin
+ g
+ cur.base = i, cur.len = 1;
+ ^~~~~~~~~~~~
+ (void)( )
+ ```
+
+ Closes #11790
+
+Daniel Stenberg (4 Sep 2023)
+
+- transfer: also stop the sending on closed connection
+
+ Previously this cleared the receiving bit only but in some cases it is
+ also still sending (like a request-body) when disconnected and neither
+ direction can continue then.
+
+ Fixes #11769
+ Reported-by: Oleg Jukovec
+ Closes #11795
+
+John Bampton (4 Sep 2023)
+
+- docs: change `sub-domain` to `subdomain`
+
+ https://en.wikipedia.org/wiki/Subdomain
+
+ Closes #11793
+
+Stefan Eissing (4 Sep 2023)
+
+- multi: more efficient pollfd count for poll
+
+ - do not use separate pollfds for sockets that have POLLIN+POLLOUT
+
+ Closes #11792
+
+- http2: polish things around POST
+
+ - added test cases for various code paths
+ - fixed handling of blocked write when stream had
+ been closed inbetween attempts
+ - re-enabled DEBUGASSERT on send with smaller data size
+
+ - in debug builds, environment variables can be set to simulate a slow
+ network when sending data. cf-socket.c and vquic.c support
+ * CURL_DBG_SOCK_WBLOCK: percentage of send() calls that should be
+ answered with a EAGAIN. TCP/UNIX sockets.
+ This is chosen randomly.
+ * CURL_DBG_SOCK_WPARTIAL: percentage of data that shall be written
+ to the network. TCP/UNIX sockets.
+ Example: 80 means a send with 1000 bytes would only send 800
+ This is applied to every send.
+ * CURL_DBG_QUIC_WBLOCK: percentage of send() calls that should be
+ answered with EAGAIN. QUIC only.
+ This is chosen randomly.
+
+ Closes #11756
+
+Daniel Stenberg (4 Sep 2023)
+
+- docs: add curl_global_trace to some SEE ALSO sections
+
+ Closes #11791
+
+- os400: fix checksrc nits
+
+ Closes #11789
+
+Nicholas Nethercote (3 Sep 2023)
+
+- hyper: remove `hyptransfer->endtask`
+
+ `Curl_hyper_stream` needs to distinguish between two kinds of
+ `HYPER_TASK_EMPTY` tasks: (a) the `foreach` tasks it creates itself, and
+ (b) background tasks that hyper produces. It does this by recording the
+ address of any `foreach` task in `hyptransfer->endtask` before pushing
+ it into the executor, and then comparing that against the address of
+ tasks later polled out of the executor.
+
+ This works right now, but there is no guarantee from hyper that the
+ addresses are stable. `hyper_executor_push` says "The executor takes
+ ownership of the task, which should not be accessed again unless
+ returned back to the user with `hyper_executor_poll`". That wording is a
+ bit ambiguous but with my Rust programmer's hat on I read it as meaning
+ the task returned with `hyper_executor_poll` may be conceptually the
+ same as a task that was pushed, but that there are no other guarantees
+ and comparing addresses is a bad idea.
+
+ This commit instead uses `hyper_task_set_userdata` to mark the `foreach`
+ task with a `USERDATA_RESP_BODY` value which can then be checked for,
+ removing the need for `hyptransfer->endtask`. This makes the code look
+ more like that hyper C API examples, which use userdata for every task
+ and never look at task addresses.
+
+ Closes #11779
+
+Dave Cottlehuber (3 Sep 2023)
+
+- ws: fix spelling mistakes in examples and tests
+
+ Closes #11784
+
+Daniel Stenberg (3 Sep 2023)
+
+- tool_filetime: make -z work with file dates before 1970
+
+ Fixes #11785
+ Reported-by: Harry Sintonen
+ Closes #11786
+
+Dan Fandrich (1 Sep 2023)
+
+- build: fix portability of mancheck and checksrc targets
+
+ At least FreeBSD preserves cwd across makefile lines, so rules
+ consisting of more than one "cd X; do_something" must be explicitly run
+ in a subshell to avoid this. This problem caused the Cirrus FreeBSD
+ build to fail when parallel make jobs were enabled.
+
+- CI: adjust labeler match patterns for new & obsolete files
+
+- configure: trust pkg-config when it's used for zlib
+
+ The library flags retrieved from pkg-config were later thrown out and
+ harded-coded, which negates the whole reason to use pkg-config.
+ Also, previously, the assumption was made that --libs-only-l and
+ --libs-only-L are the full decomposition of --libs, which is untrue and
+ would not allow linking against a static zlib. The new approach is
+ better in that it uses --libs, although only if --libs-only-l returns
+ nothing.
+
+ Bug: https://curl.se/mail/lib-2023-08/0081.html
+ Reported-by: Randall
+ Closes #11778
+
+Stefan Eissing (1 Sep 2023)
+
+- CI/ngtcp2: clear wolfssl for when cache is ignored
+
+ Closes #11783
+
+Daniel Stenberg (1 Sep 2023)
+
+- RELEASE-NOTES: synced
+
+Nicholas Nethercote (1 Sep 2023)
+
+- hyper: fix a progress upload counter bug
+
+ `Curl_pgrsSetUploadCounter` should be a passed a total count, not an
+ increment.
+
+ This changes the failing diff for test 579 with hyper from this:
+ ```
+ Progress callback called with UL 0 out of 0[LF]
+ -Progress callback called with UL 8 out of 0[LF]
+ -Progress callback called with UL 16 out of 0[LF]
+ -Progress callback called with UL 26 out of 0[LF]
+ -Progress callback called with UL 61 out of 0[LF]
+ -Progress callback called with UL 66 out of 0[LF]
+ +Progress callback called with UL 29 out of 0[LF]
+ ```
+ to this:
+ ```
+ Progress callback called with UL 0 out of 0[LF]
+ -Progress callback called with UL 8 out of 0[LF]
+ -Progress callback called with UL 16 out of 0[LF]
+ -Progress callback called with UL 26 out of 0[LF]
+ -Progress callback called with UL 61 out of 0[LF]
+ -Progress callback called with UL 66 out of 0[LF]
+ +Progress callback called with UL 40 out of 0[LF]
+ ```
+ Presumably a step in the right direction.
+
+ Closes #11780
+
+Daniel Stenberg (1 Sep 2023)
+
+- awssiv4: avoid freeing the date pointer on error
+
+ Since it was not allocated, don't free it even if it was wrong syntax
+
+ Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61908
+
+ Follow-up to b137634ba3adb
+
+ Closes #11782
+
+Stefan Eissing (1 Sep 2023)
+
+- CI: ngtcp2-linux: use separate caches for tls libraries
+
+ allow ever changing master for wolfssl
+
+ Closes #11766
+
+- replace `master` as wolfssl-version with recent commit
+
+- wolfssl, use master again in CI
+
+ - with the shared session update fix landed in master, it
+ is time to use that in our CI again
+
+Nicholas Nethercote (31 Aug 2023)
+
+- tests: fix formatting errors in `FILEFORMAT.md`.
+
+ Without the surrounding backticks, these tags get swallowed when the
+ markdown is rendered.
+
+ Closes #11777
+
+Viktor Szakats (31 Aug 2023)
+
+- cmake: add support for `CURL_DEFAULT_SSL_BACKEND`
+
+ Allow overriding the default TLS backend via a CMake setting.
+
+ E.g.:
+ `cmake [...] -DCURL_DEFAULT_SSL_BACKEND=mbedtls`
+
+ Accepted values: bearssl, gnutls, mbedtls, openssl, rustls,
+ schannel, secure-transport, wolfssl
+
+ The passed string is baked into the curl/libcurl binaries.
+ The value is case-insensitive.
+
+ We added a similar option to autotools in 2017 via
+ c7170e20d0a18ec8a514b4daa53bcdbb4dcb3a05.
+
+ TODO: Convert to lowercase to improve reproducibility.
+
+ Closes #11774
+
+- sectransp: fix compiler warnings
+
+ https://github.com/curl/curl-for-win/actions/runs/6037489221/job/16381860220#
+ step:3:11046
+ ```
+ /Users/runner/work/curl-for-win/curl-for-win/curl/lib/vtls/sectransp.c:2435:1
+ 4: warning: unused variable 'success' [-Wunused-variable]
+ OSStatus success;
+ ^
+ /Users/runner/work/curl-for-win/curl-for-win/curl/lib/vtls/sectransp.c:3300:4
+ 4: warning: unused parameter 'sha256len' [-Wunused-parameter]
+ size_t sha256len)
+ ^
+ ```
+
+ Closes #11773
+
+- tidy-up: mostly whitespace nits
+
+ - delete completed TODO from `./CMakeLists.txt`.
+ - convert a C++ comment to C89 in `./CMake/CurlTests.c`.
+ - delete duplicate EOLs from EOF.
+ - add missing EOL at EOF.
+ - delete whitespace at EOL (except from expected test results).
+ - convert tabs to spaces.
+ - convert CRLF EOLs to LF in GHA yaml.
+ - text casing fixes in `./CMakeLists.txt`.
+ - fix a codespell typo in `packages/OS400/initscript.sh`.
+
+ Closes #11772
+
+Dan Fandrich (31 Aug 2023)
+
+- CI: remove Windows builds from Cirrus, without replacement
+
+ If we don't do this, all coverage on Cirrus will cease in a few days. By
+ removing the Windows builds, the FreeBSD one should still continue
+ as before. The Windows builds will need be moved to another service to
+ maintain test coverage.
+
+ Closes #11771
+
+- CI: switch macOS ARM build from Cirrus to Circle CI
+
+ Cirrus is drastically reducing their free tier on Sept. 1, so they will
+ no longer perform all these builds for us. All but one build has been
+ moved, with the LibreSSL one being dropped because of linking problems
+ on Circle.
+
+ One important note about this change is that Circle CI is currently
+ directing all these builds to x86_64 hardware, despite them requesting
+ ARM. This is because ARM nodes are scheduled to be available on the
+ free tier only in December. This reduces our architectural diversity
+ until then but it should automatically come back once those machines are
+ enabled.
+
+- CI: use the right variable for BSD make
+
+ BSD uses MAKEFLAGS instead of MAKE_FLAGS so it wasn't doing parallel
+ builds before.
+
+- CI: drop the FreeBSD 12.X build
+
+ Cirrus' new free tier won't let us have many builds, so drop the
+ nonessential ones. The FreeBSD 13.X build will still give us the most
+ relevant FreeBSD coverage.
+
+- CI: move the Alpine build from Cirrus to GHA
+
+ Cirrus is reducing their free tier to next to nothing, so we must move
+ builds elsewhere.
+
+Stefan Eissing (30 Aug 2023)
+
+- test_07_upload.py: fix test_07_34 curl args
+
+ - Pass correct filename to --data-binary.
+
+ Prior to this change --data-binary was passed an incorrect filename due
+ to a missing separator in the arguments list. Since aacbeae7 curl will
+ error on incorrect filenames for POST.
+
+ Fixes https://github.com/curl/curl/issues/11761
+ Closes https://github.com/curl/curl/pull/11763
+
+Nicholas Nethercote (30 Aug 2023)
+
+- tests: document which tests fail due to hyper's lack of trailer support.
+
+ Closes #11762
+
+- docs: removing "pausing transfers" from HYPER.md.
+
+ It's a reference to #8600, which was fixed by #9070.
+
+ Closes #11764
+
+Patrick Monnerat (30 Aug 2023)
+
+- os400: handle CURL_TEMP_PRINTF() while building bind source
+
+ Closes #11547
+
+- os400: build test servers
+
+ Also fix a non-compliant main prototype in disabled.c.
+
+ Closes #11547
+
+- tests: fix compilation error for os400
+
+ OS400 uses BSD 4.3 setsockopt() prototype by default: this does not
+ define parameter as const, resulting in an error if actual parameter is
+ const. Remove the const keyword from the actual parameter cast: this
+ works in all conditions, even if the formal parameter uses it.
+
+ Closes #11547
+
+- os400: make programs and command name configurable
+
+ Closes #11547
+
+- os400: move build configuration parameters to a separate script
+
+ They can then easily be overriden in a script named "config400.override"
+ that is not part of the distribution.
+
+ Closes #11547
+
+- os400: implement CLI tool
+
+ This is provided as a QADRT (ascii) program, a link to it in the IFS and
+ a minimal CL command.
+
+ Closes #11547
+
+Matthias Gatto (30 Aug 2023)
+
+- lib: fix aws-sigv4 having date header twice in some cases
+
+ When the user was providing the header X-XXX-Date, the header was
+ re-added during signature computation, and we had it twice in the
+ request.
+
+ Reported-by: apparentorder@users.noreply.github.com
+
+ Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com>
+
+ Fixes: https://github.com/curl/curl/issues/11738
+ Closes: https://github.com/curl/curl/pull/11754
+
+Jay Satiro (30 Aug 2023)
+
+- multi: remove 'processing: <url>' debug message
+
+ - Remove debug message added by e024d566.
+
+ Closes https://github.com/curl/curl/pull/11759
+
+- ftp: fix temp write of ipv6 address
+
+ - During the check to differentiate between a port and IPv6 address
+ without brackets, write the binary IPv6 address to an in6_addr.
+
+ Prior to this change the binary IPv6 address was erroneously written to
+ a sockaddr_in6 'sa6' when it should have been written to its in6_addr
+ member 'sin6_addr'. There's no fallout because no members of 'sa6' are
+ accessed before it is later overwritten.
+
+ Closes https://github.com/curl/curl/pull/11747
+
+- tool: change some fopen failures from warnings to errors
+
+ - Error on missing input file for --data, --data-binary,
+ --data-urlencode, --header, --variable, --write-out.
+
+ Prior to this change if a user of the curl tool specified an input file
+ for one of the above options and that file could not be opened then it
+ would be treated as zero length data instead of an error. For example, a
+ POST using `--data @filenametypo` would cause a zero length POST which
+ is probably not what the user intended.
+
+ Closes https://github.com/curl/curl/pull/11677
+
+- hostip: fix typo
+
+Davide Masserut (29 Aug 2023)
+
+- tool: avoid including leading spaces in the Location hyperlink
+
+ Co-authored-by: Dan Fandrich <dan@coneharvesters.com>
+
+ Closes #11735
+
+Daniel Stenberg (29 Aug 2023)
+
+- SECURITY-PROCESS.md: not a sec issue: Tricking user to run a cmdline
+
+ Closes #11757
+
+- connect: stop halving the remaining timeout when less than 600 ms left
+
+ When curl wants to connect to a host, it always has a TIMEOUT. The
+ maximum time it is allowed to spend until a connect is confirmed.
+
+ curl will try to connect to each of the IP adresses returned for the
+ host. Two loops, one for each IP family.
+
+ During the connect loop, while curl has more than one IP address left to
+ try within a single address family, curl has traditionally allowed (time
+ left/2) for *this* connect attempt. This, to not get stuck on the
+ initial addresses in case the timeout but still allow later addresses to
+ get attempted.
+
+ This has the downside that when users set a very short timeout and the
+ host has a large number of IP addresses, the effective result might be
+ that every attempt gets a little too short time.
+
+ This change stop doing the divided-by-two if the total time left is
+ below a threshold. This threshold is 600 milliseconds.
+
+ Closes #11693
+
+- asyn-ares: reduce timeout to 2000ms
+
+ When UDP packets get lost this makes for slightly faster retries. This
+ lower timeout is used by @c-ares itself by default starting next
+ release.
+
+ Closes #11753
+
+John Bampton (29 Aug 2023)
+
+- misc: remove duplicate words
+
+ Closes #11740
+
+Daniel Stenberg (29 Aug 2023)
+
+- RELEASE-NOTES: synced
+
+- wolfSSL: avoid the OpenSSL compat API when not needed
+
+ ... and instead call wolfSSL functions directly.
+
+ Closes #11752
+
+Viktor Szakats (28 Aug 2023)
+
+- lib: fix null ptr derefs and uninitialized vars (h2/h3)
+
+ Fixing compiler warnings with gcc 13.2.0 in unity builds.
+
+ Assisted-by: Jay Satiro
+ Assisted-by: Stefan Eissing
+ Closes #11739
+
+Jay Satiro (28 Aug 2023)
+
+- secureserver.pl: fix stunnel version parsing
+
+ - Allow the stunnel minor-version version part to be zero.
+
+ Prior to this change with the stunnel version scheme of <major>.<minor>
+ if either part was 0 then version parsing would fail, causing
+ secureserver.pl to fail with error "No stunnel", causing tests that use
+ the SSL protocol to be skipped. As a practical matter this bug can only
+ be caused by a minor-version part of 0, since the major-version part is
+ always greater than 0.
+
+ Closes https://github.com/curl/curl/pull/11722
+
+- secureserver.pl: fix stunnel path quoting
+
+ - Store the stunnel path in the private variable $stunnel unquoted and
+ instead quote it in the command strings.
+
+ Prior to this change the quoted stunnel path was passed to perl's file
+ operators which cannot handle quoted paths. For example:
+
+ $stunnel = "\"/C/Program Files (x86)/stunnel/bin/tstunnel\"";
+ if(-x $stunnel or -x "$stunnel")
+ # false even if path exists and is executable
+
+ Our other test scripts written in perl, unlike this one, use servers.pm
+ which has a global $stunnel variable with the path stored unquoted and
+ therefore those scripts don't have this problem.
+
+ Closes https://github.com/curl/curl/pull/11721
+
+Daniel Stenberg (28 Aug 2023)
+
+- altsvc: accept and parse IPv6 addresses in response headers
+
+ Store numerical IPv6 addresses in the alt-svc file with the brackets
+ present.
+
+ Verify with test 437 and 438
+
+ Fixes #11737
+ Reported-by: oliverpool on github
+ Closes #11743
+
+- libtest: use curl_free() to free libcurl allocated data
+
+ In several test programs. These mistakes are not detected or a problem
+ as long as memdebug.h is included, as that provides the debug wrappers
+ for all memory functions in the same style libcurl internals do it,
+ which makes curl_free and free effectively the same call.
+
+ Reported-by: Nicholas Nethercote
+ Closes #11746
+
+Jay Satiro (28 Aug 2023)
+
+- disable.d: explain --disable not implemented prior to 7.50.0
+
+ Option -q/--disable was added in 5.0 but only -q was actually
+ implemented. Later --disable was implemented in e200034 (precedes
+ 7.49.0), but incorrectly, and fixed in 6dbc23c (precedes 7.50.0).
+
+ Reported-by: pszlazak@users.noreply.github.com
+
+ Fixes https://github.com/curl/curl/issues/11710
+ Closes #11712
+
+Nicholas Nethercote (28 Aug 2023)
+
+- hyper: fix ownership problems
+
+ Some of these changes come from comparing `Curl_http` and
+ `start_CONNECT`, which are similar, and adding things to them that are
+ present in one and missing in another.
+
+ The most important changes:
+ - In `start_CONNECT`, add a missing `hyper_clientconn_free` call on the
+ happy path.
+ - In `start_CONNECT`, add a missing `hyper_request_free` on the error
+ path.
+ - In `bodysend`, add a missing `hyper_body_free` on an early-exit path.
+ - In `bodysend`, remove an unnecessary `hyper_body_free` on a different
+ error path that would cause a double-free.
+ https://docs.rs/hyper/latest/hyper/ffi/fn.hyper_request_set_body.html
+ says of `hyper_request_set_body`: "This takes ownership of the
+ hyper_body *, you must not use it or free it after setting it on the
+ request." This is true even if `hyper_request_set_body` returns an
+ error; I confirmed this by looking at the hyper source code.
+
+ Other changes are minor but make things slightly nicer.
+
+ Closes #11745
+
+Daniel Stenberg (28 Aug 2023)
+
+- multi.h: the 'revents' field of curl_waitfd is supported
+
+ Since 6d30f8ebed34e7276
+
+ Reported-by: Nicolás Ojeda Bär
+ Ref: #11748
+ Closes #11749
+
+Gerome Fournier (27 Aug 2023)
+
+- tool_paramhlp: improve str2num(): avoid unnecessary call to strlen()
+
+ Closes #11742
+
+Daniel Stenberg (27 Aug 2023)
+
+- docs: mention critical files in same directories as curl saves
+
+ ... cannot be fully protected. Don't do it.
+
+ Co-authored-by: Jay Satiro
+ Reported-by: Harry Sintonen
+ Fixes #11530
+ Closes #11701
+
+John Hawthorn (26 Aug 2023)
+
+- OpenSSL: clear error queue after SSL_shutdown
+
+ We've seen errors left in the OpenSSL error queue (specifically,
+ "shutdown while in init") by adding some logging it revealed that the
+ source was this file.
+
+ Since we call SSL_read and SSL_shutdown here, but don't check the return
+ code for an error, we should clear the OpenSSL error queue in case one
+ was raised.
+
+ This didn't affect curl because we call ERR_clear_error before every
+ write operation (a0dd9df9ab35528eb9eb669e741a5df4b1fb833c), but when
+ libcurl is used in a process with other OpenSSL users, they may detect
+ an OpenSSL error pushed by libcurl's SSL_shutdown as if it was their
+ own.
+
+ Co-authored-by: Satana de Sant'Ana <satana@skylittlesystem.org>
+
+ Closes #11736
+
+Alexander Kanavin (25 Aug 2023)
+
+- tests: update cookie expiry dates to far in the future
+
+ This allows testing Y2038 with system time set to after that, so that
+ actual Y2038 issues can be exposed, and not masked by expiry errors.
+
+ Fixes #11576
+ Closes #11610
+
+John Bampton (25 Aug 2023)
+
+- misc: fix spelling
+
+ Closes #11733
+
+Daniel Stenberg (25 Aug 2023)
+
+- cmdline-opts/page-header: clarify stronger that !opt == URL
+
+ Everything provided on the command line that is not an option (or an
+ argument to an option) is treated as a URL.
+
+ Closes #11734
+
+- tests/runner: fix %else handling
+
+ Getting the show state proper for %else and %endif did not properly work
+ in nested cases.
+
+ Follow-up to 3d089c41ea9
+
+ Closes #11731
+
+Nicholas Nethercote (25 Aug 2023)
+
+- docs: Remove mention of #10803 from `KNOWN_BUGS`.
+
+ Because the leaks have been fixed.
+
+- c-hyper: fix another memory leak in `Curl_http`.
+
+ There is a `hyper_clientconn_free` call on the happy path, but not one
+ on the error path. This commit adds one.
+
+ Fixes the second memory leak reported by Valgrind in #10803.
+
+ Fixes #10803
+ Closes #11729
+
+- c-hyper: fix a memory leak in `Curl_http`.
+
+ A request created with `hyper_request_new` must be consumed by either
+ `hyper_clientconn_send` or `hyper_request_free`.
+
+ This is not terrifically clear from the hyper docs --
+ `hyper_request_free` is documented only with "Free an HTTP request if
+ not going to send it on a client" -- but a perusal of the hyper code
+ confirms it.
+
+ This commit adds a `hyper_request_free` to the `error:` path in
+ `Curl_http` so that the request is consumed when an error occurs after
+ the request is created but before it is sent.
+
+ Fixes the first memory leak reported by Valgrind in #10803.
+
+ Closes #11729
+
+Daniel Stenberg (25 Aug 2023)
+
+- RELEASE-NOTES: synced
+
+John Bampton (25 Aug 2023)
+
+- misc: spellfixes
+
+ Closes #11730
+
+Daniel Stenberg (25 Aug 2023)
+
+- tests: add support for nested %if conditions
+
+ Provides more flexiblity to test cases.
+
+ Also warn and bail out if there is an '%else' or %endif' without a
+ preceeding '%if'.
+
+ Ref: #11610
+ Closes #11728
+
+- time-cond.d: mention what happens on a missing file
+
+ Closes #11727
+
+Christian Hesse (24 Aug 2023)
+
+- docs/cmdline-opts: match the current output
+
+ The release date has been added in output, reflect that in documentation.
+
+ Closes #11723
+
+Daniel Stenberg (24 Aug 2023)
+
+- lib: minor comment corrections
+
+- docs: rewrite to present tense
+
+ ... instead of using future tense.
+
+ + numerous cleanups and improvements
+ + stick to "reuse" not "re-use"
+ + fewer contractions
+
+ Closes #11713
+
+- urlapi: setting a blank URL ("") is not an ok URL
+
+ Test it in 1560
+ Fixes #11714
+ Reported-by: ad0p on github
+ Closes #11715
+
+- spelling: use 'reuse' not 're-use' in code and elsewhere
+
+ Unify the spelling as both versions were previously used intermittently
+
+ Closes #11717
+
+Michael Osipov (23 Aug 2023)
+
+- system.h: add CURL_OFF_T definitions on HP-UX with HP aCC
+
+ HP-UX on IA64 provides two modes: 32 and 64 bit while 32 bit being the
+ default one. Use "long long" in 32 bit mode and just "long" in 64 bit
+ mode.
+
+ Closes #11718
+
+Dan Fandrich (22 Aug 2023)
+
+- tests: don't call HTTP errors OK in test cases
+
+ Some HTTP errors codes were accompanied by the text OK, which causes
+ some cognitive dissonance when reading them.
+
+- http: close the connection after a late 417 is received
+
+ In this situation, only part of the data has been sent before aborting
+ so the connection is no longer usable.
+
+ Assisted-by: Jay Satiro
+ Fixes #11678
+ Closes #11679
+
+- runtests: slightly increase the longest log file displayed
+
+ The new limit provides enough space for a 64 KiB data block to be logged
+ in a trace file, plus a few lines at the start and end for context. This
+ happens to be the amount of data sent at a time in a PUT request.
+
+- tests: add delay command to the HTTP server
+
+ This adds a delay after client connect.
+
+Daniel Stenberg (22 Aug 2023)
+
+- cirrus: install everthing with pkg, avoid pip
+
+ Assisted-by: Sevan Janiyan
+
+ Closes #11711
+
+- curl_url*.3: update function descriptions
+
+ - expand and clarify several descriptions
+ - avoid using future tense all over
+
+ Closes #11708
+
+- RELEASE-NOTES: synced
+
+Stefan Eissing (21 Aug 2023)
+
+- CI/cirrus: disable python install on FreeBSD
+
+ - python cryptography package does not build build FreeBSD
+ - install just mentions "error"
+ - this gets the build and the main test suite going again
+
+ Closes #11705
+
+- test2600: fix flakiness on low cpu
+
+ - refs #11355 where failures to to low cpu resources in CI
+ are reported
+ - vastly extend CURLOPT_CONNECTTIMEOUT_MS and max durations
+ to test cases
+ - trigger Curl_expire() in test filter to allow re-checks before
+ the usual 1second interval
+
+ Closes #11690
+
+Maksim Sciepanienka (20 Aug 2023)
+
+- tool_urlglob: use the correct format specifier for curl_off_t in msnprintf
+
+ Closes #11698
+
+Daniel Stenberg (20 Aug 2023)
+
+- test687/688: two more basic --xattr tests
+
+ Closes #11697
+
+- cmdline-opts/docs: mentioned the negative option part
+
+ ... for --no-alpn and --no-buffer in the same style done for other --no-
+ options:
+
+ "Note that this is the negated option name documented."
+
+ Closes #11695
+
+Emanuele Torre (19 Aug 2023)
+
+- tool/var: also error when expansion result starts with NUL
+
+ Expansions whose output starts with NUL were being expanded to the empty
+ string, and not being recognised as values that contain a NUL byte, and
+ should error.
+
+ Closes #11694
+
+Daniel Stenberg (19 Aug 2023)
+
+- tests: add 'large-time' as a testable feature
+
+ This allows test cases to require this feature to run and to be used in
+ %if conditions.
+
+ Large here means larger than 32 bits. Ie does not suffer from y2038.
+
+ Closes #11696
+
+- tests/Makefile: add check-translatable-options.pl to tarball
+
+ Used in test 1544
+
+ Follow-up to ae806395abc8c
+
+- gen.pl: fix a long version generation mistake
+
+ Too excessive escaping made the parsing not find the correct long names
+ later and instead add "wrong" links.
+
+ Follow-up to 439ff2052e219
+
+ Reported-by: Lukas Tribus
+ Fixes #11688
+ Closes #11689
+
+- lib: move mimepost data from ->req.p.http to ->state
+
+ When the legacy CURLOPT_HTTPPOST option is used, it gets converted into
+ the modem mimpost struct at first use. This data is (now) kept for the
+ entire transfer and not only per single HTTP request. This re-enables
+ rewind in the beginning of the second request instead of in end of the
+ first, as brought by 1b39731.
+
+ The request struct is per-request data only.
+
+ Extend test 650 to verify.
+
+ Fixes #11680
+ Reported-by: yushicheng7788 on github
+ Closes #11682
+
+Patrick Monnerat (17 Aug 2023)
+
+- os400: do not check translatable options at build time
+
+ Now that there is a test for this, the build time check is not needed
+ anymore.
+
+ Closes #11650
+
+- test1554: check translatable string options in OS400 wrapper
+
+ This test runs a perl script that checks all string options are properly
+ translated by the OS400 character code conversion wrapper. It also
+ verifies these options are listed in alphanumeric order in the wrapper
+ switch statement.
+
+ Closes #11650
+
+Daniel Stenberg (17 Aug 2023)
+
+- unit3200: skip testing if function is not present
+
+ Fake a successful run since we have no easy mechanism to skip this test
+ for this advanced condition.
+
+- unit2600: fix build warning if built without verbose messages
+
+- test1608: make it build and get skipped without shuffle DNS support
+
+- lib: --disable-bindlocal builds curl without local binding support
+
+- test1304: build and skip without netrc support
+
+- lib: build fixups when built with most things disabled
+
+ Closes #11687
+
+- workflows/macos.yml: disable zstd and alt-svc in the http-only build
+
+ Closes #11683
+
+Stefan Eissing (17 Aug 2023)
+
+- bearssl: handshake fix, provide proper get_select_socks() implementation
+
+ - bring bearssl handshake times down from +200ms down to other TLS backends
+ - vtls: improve generic get_select_socks() implementation
+ - tests: provide Apache with a suitable ssl session cache
+
+ Closes #11675
+
+- tests: TLS session sharing test
+
+ - test TLS session sharing with special test client
+ - expect failure with wolfSSL
+ - disable flaky wolfSSL test_02_07b
+
+ Closes #11675
+
+Daniel Stenberg (17 Aug 2023)
+
+- CURLOPT_*TIMEOUT*: extend and clarify
+
+ Closes #11686
+
+- urlapi: return CURLUE_BAD_HOSTNAME if puny2idn encoding fails
+
+ And document it. Only return out of memory when it actually is a memory
+ problem.
+
+ Pointed-out-by: Jacob Mealey
+ Closes #11674
+
+Mathew Benson (17 Aug 2023)
+
+- cmake: add GnuTLS option
+
+ - Option to use GNUTLS was missing. Hence was not able to use GNUTLS
+ with ngtcp2 for http3.
+
+ Closes #11685
+
+Daniel Stenberg (16 Aug 2023)
+
+- RELEASE-NOTES: synced
+
+- http: remove the p_pragma struct field
+
+ unused since 40e8b4e52 (2008)
+
+ Closes #11681
+
+Jay Satiro (16 Aug 2023)
+
+- CURLINFO_CERTINFO.3: better explain curl_certinfo struct
+
+ Closes https://github.com/curl/curl/pull/11666
+
+- CURLINFO_TLS_SSL_PTR.3: clarify a recommendation
+
+ - Remove the out-of-date SSL backend list supported by
+ CURLOPT_SSL_CTX_FUNCTION.
+
+ It makes more sense to just refer to that document instead of having
+ a separate list that has to be kept in sync.
+
+ Closes https://github.com/curl/curl/pull/11665
+
+- write-out.d: clarify %{time_starttransfer}
+
+ sync it up with CURLINFO_STARTTRANSFER_TIME_T
+
+Daniel Stenberg (15 Aug 2023)
+
+- transfer: don't set TIMER_STARTTRANSFER on first send
+
+ The time stamp is for measuring the first *received* byte
+
+ Fixes #11669
+ Reported-by: JazJas on github
+ Closes #11670
+
+trrui-huawei (15 Aug 2023)
+
+- quiche: enable quiche to handle timeout events
+
+ In parallel with ngtcp2, quiche also offers the `quiche_conn_on_timeout`
+ interface for the application to invoke upon timer
+ expiration. Therefore, invoking the `on_timeout` function of the
+ Connection is crucial to ensure seamless functionality of quiche with
+ timeout events.
+
+ Closes #11654
+
+- quiche: adjust quiche `QUIC_IDLE_TIMEOUT` to 60s
+
+ Set the `QUIC_IDLE_TIMEOUT` parameter to match ngtcp2 for consistency.
+
+Daniel Stenberg (15 Aug 2023)
+
+- KNOWN_BUGS: LDAPS requests to ActiveDirectory server hang
+
+ Closes #9580
+
+- imap: add a check for failing strdup()
+
+- imap: remove the only sscanf() call in the IMAP code
+
+ Avoids the use of a stack buffer.
+
+ Closes #11673
+
+- imap: use a dynbuf in imap_atom
+
+ Avoid a calculation + malloc. Build the output in a dynbuf.
+
+ Closes #11672
+
+Marin Hannache (14 Aug 2023)
+
+- http: do not require a user name when using CURLAUTH_NEGOTIATE
+
+ In order to get Negotiate (SPNEGO) authentication to work in HTTP you
+ used to be required to provide a (fake) user name (this concerned both
+ curl and the lib) because the code wrongly only considered
+ authentication if there was a user name provided, as in:
+
+ curl -u : --negotiate https://example.com/
+
+ This commit leverages the `struct auth` want member to figure out if the
+ user enabled CURLAUTH_NEGOTIATE, effectively removing the requirement of
+ setting a user name both in curl and the lib.
+
+ Signed-off-by: Marin Hannache <git@mareo.fr>
+ Reported-by: Enrico Scholz
+ Fixes https://sourceforge.net/p/curl/bugs/440/
+ Fixes #1161
+ Closes #9047
+
+Viktor Szakats (13 Aug 2023)
+
+- build: streamline non-UWP wincrypt detections
+
+ - with CMake, use the variable `WINDOWS_STORE` to detect an UWP build
+ and disable our non-UWP-compatible use the Windows crypto API. This
+ allows to drop two dynamic feature checks.
+
+ `WINDOWS_STORE` is true when invoking CMake with
+ `CMAKE_SYSTEM_NAME` == `WindowsStore`. Introduced in CMake v3.1.
+
+ Ref: https://cmake.org/cmake/help/latest/variable/WINDOWS_STORE.html
+
+ - with autotools, drop the separate feature check for `wincrypt.h`. On
+ one hand this header has been present for long (even Borland C 5.5 had
+ it from year 2000), on the other we used the check result solely to
+ enable another check for certain crypto functions. This fails anyway
+ with the header not present. We save one dynamic feature check at the
+ configure stage.
+
+ Reviewed-by: Marcel Raad
+ Closes #11657
+
+Nicholas Nethercote (13 Aug 2023)
+
+- docs/HYPER.md: update hyper build instructions
+
+ Nightly Rust and `-Z unstable-options` are not needed.
+
+ The instructions here now match the hyper docs exactly:
+ https://github.com/hyperium/hyper/commit/bd7928f3dd6a8461f0f0fdf7ee0fd95c2f15
+ 6f88
+
+ Closes #11662
+
+Daniel Stenberg (13 Aug 2023)
+
+- RELEASE-NOTES: synced
+
+- urlapi: CURLU_PUNY2IDN - convert from punycode to IDN name
+
+ Asssisted-by: Jay Satiro
+ Closes #11655
+
+- spellcheck: adapt to backslashed minuses
+
+ As the curl.1 has more backslashed minus, the cleanup sed lines xneed to
+ adapt.
+
+ Adjusted some docs slighly.
+
+ Follow-up to 439ff2052e
+
+ Closes #11663
+
+- gen: escape more minus
+
+ Detected since it was still hard to search for option names using dashes
+ in the middle in the man page.
+
+ Closes #11660
+
+- cookie-jar.d: enphasize that this option is ONLY writing cookies
+
+ Reported-by: Dan Jacobson
+ Tweaked-by: Jay Satiro
+ Ref: #11642
+ Closes #11661
+
+Nicholas Nethercote (11 Aug 2023)
+
+- docs/HYPER.md: document a workaround for a link error
+
+ Closes #11653
+
+Jay Satiro (11 Aug 2023)
+
+- schannel: verify hostname independent of verify cert
+
+ Prior to this change when CURLOPT_SSL_VERIFYPEER (verifypeer) was off
+ and CURLOPT_SSL_VERIFYHOST (verifyhost) was on we did not verify the
+ hostname in schannel code.
+
+ This fixes KNOWN_BUG 2.8 "Schannel disable CURLOPT_SSL_VERIFYPEER and
+ verify hostname". We discussed a fix several years ago in #3285 but it
+ went stale.
+
+ Assisted-by: Daniel Stenberg
+
+ Bug: https://curl.haxx.se/mail/lib-2018-10/0113.html
+ Reported-by: Martin Galvan
+
+ Ref: https://github.com/curl/curl/pull/3285
+
+ Fixes https://github.com/curl/curl/issues/3284
+ Closes https://github.com/curl/curl/pull/10056
+
+Daniel Stenberg (11 Aug 2023)
+
+- curl_quiche: remove superfluous NULL check
+
+ 'stream' is always non-NULL at this point
+
+ Pointed out by Coverity
+
+ Closes #11656
+
+- curl/urlapi.h: tiny typo
+
+- github/labeler: make HYPER.md set Hyper and not TLS
+
+- docs/cmdline-opts/gen.pl: hide "added in" before 7.50.0
+
+ 7.50.0 shipped on Jul 21 2016, over seven years ago. We no longer need
+ to specify version changes for earlier releases in the generated output.
+
+ This ups the limit from the previous 7.30.0 (Apr 12 2013)
+
+ This hides roughly 35 "added in" mentions.
+
+ Closes #11651
+
+Jay Satiro (10 Aug 2023)
+
+- bug_report: require reporters to specify curl and os versions
+
+ - Change curl version and os sections from single-line input to
+ multi-line textarea.
+
+ - Require curl version and os sections to be filled out before report
+ can be submitted.
+
+ Closes https://github.com/curl/curl/pull/11636
+
+Daniel Stenberg (9 Aug 2023)
+
+- gen.pl: replace all single quotes with aq
+
+ - this prevents man from using a unicode sequence for them
+ - which then allows search to work properly
+
+ Closes #11645
+
+Viktor Szakats (9 Aug 2023)
+
+- cmake: fix to use variable for the curl namespace
+
+ Replace (wrong) literal with a variable to specify the curl
+ namespace.
+
+ Follow-up to 1199308dbc902c52be67fc805c72dd2582520d30 #11505
+
+ Reported-by: balikalina on Github
+ Fixes https://github.com/curl/curl/commit/1199308dbc902c52be67fc805c72dd25825
+ 20d30#r123923098
+ Closes #11629
+
+- cmake: allow `SHARE_LIB_OBJECT=ON` on all platforms
+
+ 2ebc74c36a19a1700af394c16855ce144d9878e3 #11546 introduced sharing
+ libcurl objects for shared and static targets.
+
+ The above automatically enabled for Windows builds, with an option to
+ disable with `SHARE_LIB_OBJECT=OFF`.
+
+ This patch extend this feature to all platforms as a manual option.
+ You can enable it by setting `SHARE_LIB_OBJECT=ON`. Then shared objects
+ are built in PIC mode, meaning the static lib will also have PIC code.
+
+ [EXPERIMENTAL]
+
+ Closes #11627
+
+- cmake: assume `wldap32` availability on Windows
+
+ This system library first shipped with Windows ME, available as an extra
+ install for some older releases (according to [1]). The import library
+ was present already in old MinGW 3.4.2 (year 2007).
+
+ Drop the feature check and its associated `HAVE_WLDAP32` variable.
+
+ To manually disable `wldap32`, you can use the `USE_WIN32_LDAP=OFF`
+ CMake option, like before.
+
+ [1]: https://dlcdn.apache.org/httpd/binaries/win32/LEGACY.html
+
+ Reviewed-by: Jay Satiro
+ Closes #11624
+
+Daniel Stenberg (9 Aug 2023)
+
+- page-header: move up a URL paragraph from GLOBBING to URL
+
+- variable.d: output the function names table style
+
+ Also correct the url function name in the header
+
+ Closes #11641
+
+- haproxy-clientip.d: remove backticks
+
+ This is not markdown
+
+ Follow-up to 0a75964d0d94a4
+
+ Closes #11639
+
+- RELEASE-NOTES: synced
+
+- gen.pl: escape all dashes (ascii minus) to avoid unicode hyphens
+
+ Reported-by: FC Stegerman
+ Fixes #11635
+ Closes #11637
+
+- cmdline-opts/page-header: reorder, clean up
+
+ - removed some unnecessary blurb to focus
+ - moved up the more important URL details
+ - put "globbing" into its own subtitle and moved down a little
+ - mention the online man page in the version section
+
+ Closes #11638
+
+- c-hyper: adjust the hyper to curlcode conversion
+
+ Closes #11621
+
+- test2306: make it use a persistent connection
+
+ + enable verbose already from the start
+
+ Closes #11621
+
+eppesuig (8 Aug 2023)
+
+- list-only.d: mention SFTP as supported protocol
+
+ Closes #11628
+
+Daniel Stenberg (8 Aug 2023)
+
+- request.d: use .TP for protocol "labels"
+
+ To render the section nicer in man page.
+
+ Closes #11630
+
+- cf-haproxy: make CURLOPT_HAPROXY_CLIENT_IP set the *source* IP
+
+ ... as documented.
+
+ Update test 3201 and 3202 accordingly.
+
+ Reported-by: Markus Sommer
+ Fixes #11619
+ Closes #11626
+
+- page-footer: QLOGDIR works with ngtcp2 and quiche
+
+ It previously said "both" backends which is confusing as we currently
+ have three...
+
+ Closes #11631
+
+Stefan Eissing (8 Aug 2023)
+
+- http3: quiche, handshake optimization, trace cleanup
+
+ - load x509 store after clienthello
+ - cleanup of tracing
+
+ Closes #11618
+
+Daniel Stenberg (8 Aug 2023)
+
+- ngtcp2: remove dead code
+
+ 'result' is always zero (CURLE_OK) at this point
+
+ Detected by Coverity
+
+ Closes #11622
+
+Viktor Szakats (8 Aug 2023)
+
+- openssl: auto-detect `SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED`
+
+ OpenSSL 1.1.1 defines this macro, but no ealier version, or any of the
+ popular forks (yet). Use the macro itself to detect its presence,
+ replacing the hard-wired fork-specific conditions.
+
+ This way the feature will enable automatically when forks implement it,
+ while also shorter and possibly requiring less future maintenance.
+
+ Follow-up to 94241a9e78397a2aaf89a213e6ada61e7de7ee02 #6721
+
+ Reviewed-by: Jay Satiro
+ Closes #11617
+
+- openssl: use `SSL_CTX_set_ciphersuites` with LibreSSL 3.4.1
+
+ LibreSSL 3.4.1 (2021-10-14) added support for
+ `SSL_CTX_set_ciphersuites`.
+
+ Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.4.1-relnotes.txt
+
+ Reviewed-by: Jay Satiro
+ Closes #11616
+
+- openssl: use `SSL_CTX_set_keylog_callback` with LibreSSL 3.5.0
+
+ LibreSSL 3.5.0 (2022-02-24) added support for
+ `SSL_CTX_set_keylog_callback`.
+
+ Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.5.0-relnotes.txt
+
+ Reviewed-by: Jay Satiro
+ Closes #11615
+
+- cmake: drop `HAVE_LIBWINMM` and `HAVE_LIBWS2_32` feature checks
+
+ - `HAVE_LIBWINMM` was detected but unused. The `winmm` system library is
+ also not used by curl, but it is by its optional dependency `librtmp`.
+ Change the logic to always add `winmm` when `USE_LIBRTMP` is set. This
+ library has been available since the early days of Windows.
+
+ - `HAVE_LIBWS2_32` detected `ws2_32` lib on Windows. This lib is present
+ since Windows 95 OSR2 (AFAIR). Winsock1 already wasn't supported and
+ other existing logic already assumed this lib being present, so delete
+ the check and replace the detection variable with `WIN32` and always
+ add `ws2_32` on Windows.
+
+ Closes #11612
+
+Daniel Gustafsson (8 Aug 2023)
+
+- crypto: ensure crypto initialization works
+
+ Make sure that context initialization during hash setup works to avoid
+ going forward with the risk of a null pointer dereference.
+
+ Reported-by: Philippe Antoine on HackerOne
+ Assisted-by: Jay Satiro
+ Assisted-by: Daniel Stenberg
+
+ Closes #11614
+
+Viktor Szakats (7 Aug 2023)
+
+- openssl: switch to modern init for LibreSSL 2.7.0+
+
+ LibreSSL 2.7.0 (2018-03-21) introduced automatic initialization,
+ `OPENSSL_init_ssl()` function and deprecated the old, manual init
+ method, as seen in OpenSSL 1.1.0. Switch to the modern method when
+ available.
+
+ Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.7.0-relnotes.txt
+
+ Reviewed-by: Daniel Stenberg
+ Closes #11611
+
+Daniel Stenberg (7 Aug 2023)
+
+- gskit: remove
+
+ We remove support for building curl with gskit.
+
+ - This is a niche TLS library, only running on some IBM systems
+ - no regular curl contributors use this backend
+ - no CI builds use or verify this backend
+ - gskit, or the curl adaption for it, lacks many modern TLS features
+ making it an inferior solution
+ - build breakages in this code take weeks or more to get detected
+ - fixing gskit code is mostly done "flying blind"
+
+ This removal has been advertized in DEPRECATED in Jan 2, 2023 and it has
+ been mentioned on the curl-library mailing list.
+
+ It could be brought back, this is not a ban. Given proper effort and
+ will, gskit support is welcome back into the curl TLS backend family.
+
+ Closes #11460
+
+- RELEASE-NOTES: synced
+
+Dan Fandrich (7 Aug 2023)
+
+- THANKS-filter: add a name typo
+
+Stefan Eissing (7 Aug 2023)
+
+- http3/ngtcp2: shorten handshake, trace cleanup
+
+ - shorten handshake timing by delayed x509 store load (OpenSSL)
+ as we do for HTTP/2
+ - cleanup of trace output, align with HTTP/2 output
+
+ Closes #11609
+
+Daniel Stenberg (7 Aug 2023)
+
+- headers: accept leading whitespaces on first response header
+
+ This is a bad header fold but since the popular browsers accept this
+ violation, so does curl now. Unless built with hyper.
+
+ Add test 1473 to verify and adjust test 2306.
+
+ Reported-by: junsik on github
+ Fixes #11605
+ Closes #11607
+
+- include/curl/mprintf.h: add __attribute__ for the prototypes
+
+ - if gcc or clang is used
+ - if __STDC_VERSION__ >= 199901L, which means greater than C90
+ - if not using mingw
+ - if CURL_NO_FMT_CHECKS is not defined
+
+ Closes #11589
+
+- tests: fix bad printf format flags in test code
+
+- tests: fix header scan tools for attribute edits in mprintf.h
+
+- cf-socket: log successful interface bind
+
+ When the setsockopt SO_BINDTODEVICE operation succeeds, output that in
+ the verbose output.
+
+ Ref: #11599
+ Closes #11608
+
+- CURLOPT_SSL_VERIFYPEER.3: mention it does not load CA certs when disabled
+
+ Ref: #11457
+ Closes #11606
+
+- CURLOPT_SSL_VERIFYPEER.3: add two more see also options
+
+ CURLINFO_CAINFO and CURLINFO_CAPATH
+
+ Closes #11603
+
+- KNOWN_BUGS: aws-sigv4 does not behave well with AWS VPC Lattice
+
+ Closes #11007
+
+Graham Campbell (6 Aug 2023)
+
+- CI: use openssl 3.0.10+quic, nghttp3 0.14.0, ngtcp2 0.18.0
+
+ Closes #11585
+
+Daniel Stenberg (6 Aug 2023)
+
+- TODO: add *5* entries for aws-sigv4
+
+ Closes #7559
+ Closes #8107
+ Closes #8810
+ Closes #9717
+ Closes #10129
+
+- TODO: LDAP Certificate-Based Authentication
+
+ Closes #9641
+
+Stefan Eissing (6 Aug 2023)
+
+- http2: cleanup trace messages
+
+ - more compact format with bracketed stream id
+ - all frames traced in and out
+
+ Closes #11592
+
+Daniel Stenberg (6 Aug 2023)
+
+- tests/tftpd+mqttd: make variables static to silence picky warnings
+
+ Closes #11594
+
+- docs/cmdline: remove repeated working for negotiate + ntlm
+
+ The extra wording is added automatically by the gen.pl tool
+
+ Closes #11597
+
+- docs/cmdline: add small "warning" to verbose options
+
+ "Note that verbose output of curl activities and network traffic might
+ contain sensitive data, including user names, credentials or secret data
+ content. Be aware and be careful when sharing trace logs with others."
+
+ Closes #11596
+
+- RELEASE-NOTES: synced
+
+- pingpong: don't use *bump_headersize
+
+ We use that for HTTP(S) only.
+
+ Follow-up to 3ee79c1674fd6
+
+ Closes #11590
+
+- urldata: remove spurious parenthesis to unbreak no-proxy build
+
+ Follow-up to e12b39e13382
+
+ Closes #11591
+
+- easy: don't call Curl_trc_opt() in disabled-verbose builds
+
+ Follow-up to e12b39e133822c6a0
+
+ Closes #11588
+
+- http: use %u for printfing int
+
+ Follow-up to 3ee79c1674fd6f99e8efca5
+
+ Closes #11587
+
+Goro FUJI (3 Aug 2023)
+
+- vquic: show stringified messages for errno
+
+ Closes #11584
+
+Stefan Eissing (3 Aug 2023)
+
+- trace: make tracing available in non-debug builds
+
+ Add --trace-config to curl
+
+ Add curl_global_trace() to libcurl
+
+ Closes #11421
+
+Daniel Stenberg (3 Aug 2023)
+
+- TODO: remove "Support intermediate & root pinning for PINNEDPUBLICKEY"
+
+ See also https://github.com/curl/curl/pull/7507
+
+- TODO: add "WebSocket read callback"
+
+ remove "Upgrade to websockets" as we already have this
+
+ Closes #11402
+
+- test497: verify rejecting too large incoming headers
+
+- http: return error when receiving too large header set
+
+ To avoid abuse. The limit is set to 300 KB for the accumulated size of
+ all received HTTP headers for a single response. Incomplete research
+ suggests that Chrome uses a 256-300 KB limit, while Firefox allows up to
+ 1MB.
+
+ Closes #11582
+
+Stefan Eissing (3 Aug 2023)
+
+- http2: upgrade tests and add fix for non-existing stream
+
+ - check in h2 filter recv that stream actually exists
+ and return error if not
+ - add test for parallel, extreme h2 upgrades that fail if
+ connections get reused before fully switched
+ - add h2 upgrade upload test just for completeness
+
+ Closes #11563
+
+Viktor Szakats (3 Aug 2023)
+
+- tests: ensure `libcurl.def` contains all exports
+
+ Add `test1279` to verify that `libcurl.def` lists all exported API
+ functions found in libcurl headers.
+
+ Also:
+
+ - extend test suite XML `stdout` tag with the `loadfile` attribute.
+
+ - fix `tests/extern-scan.pl` and `test1135` to include websocket API.
+
+ - use all headers (sorted) in `test1135` instead of a manual list.
+
+ - add options `--sort`, `--heading=` to `tests/extern-scan.pl`.
+
+ - add `libcurl.def` to the auto-labeler GHA task.
+
+ Follow-up to 2ebc74c36a19a1700af394c16855ce144d9878e3
+
+ Closes #11570
+
+Daniel Stenberg (2 Aug 2023)
+
+- url: change default value for CURLOPT_MAXREDIRS to 30
+
+ It was previously unlimited by default, but that's not a sensible
+ default. While changing this has a remote risk of breaking an existing
+ use case, I figure it is more likely to actually save users from loops.
+
+ Closes #11581
+
+- lib: fix a few *printf() flag mistakes
+
+ Reported-by: Gisle Vanem
+ Ref: #11574
+ Closes #11579
+
+Samuel Chiang (2 Aug 2023)
+
+- openssl: make aws-lc version support OCSP
+
+ And bump version in CI
+
+ Closes #11568
+
+Daniel Stenberg (2 Aug 2023)
+
+- tool: make the length argument an int for printf()-.* flags
+
+ Closes #11578
+
+- tool_operate: fix memory leak when SSL_CERT_DIR is used
+
+ Detected by Coverity
+
+ Follow-up to 29bce9857a12b6cfa726a5
+
+ Closes #11577
+
+- tool/var: free memory on OOM
+
+ Coverity detected this memory leak in OOM situation
+
+ Follow-up to 2e160c9c652504e
+
+ Closes #11575
+
+Viktor Szakats (2 Aug 2023)
+
+- gha: bump libressl and mbedtls versions
+
+ Closes #11573
+
+Jay Satiro (2 Aug 2023)
+
+- schannel: fix user-set legacy algorithms in Windows 10 & 11
+
+ - If the user set a legacy algorithm list (CURLOPT_SSL_CIPHER_LIST) then
+ use the SCHANNEL_CRED legacy structure to pass the list to Schannel.
+
+ - If the user set both a legacy algorithm list and a TLS 1.3 cipher list
+ then abort.
+
+ Although MS doesn't document it, Schannel will not negotiate TLS 1.3
+ when SCHANNEL_CRED is used. That means setting a legacy algorithm list
+ limits the user to earlier versions of TLS.
+
+ Prior to this change, since 8beff435 (precedes 7.85.0), libcurl would
+ ignore legacy algorithms in Windows 10 1809 and later.
+
+ Reported-by: zhihaoy@users.noreply.github.com
+
+ Fixes https://github.com/curl/curl/pull/10741
+ Closes https://github.com/curl/curl/pull/10746
+
+Daniel Stenberg (2 Aug 2023)
+
+- variable.d: setting a variable again overwrites it
+
+ Reported-by: Niall McGee
+ Bug: https://twitter.com/niallmcgee/status/1686523075423322113
+ Closes #11571
+
+Jay Satiro (2 Aug 2023)
+
+- CURLOPT_PROXY_SSL_OPTIONS.3: sync formatting
+
+ - Re-wrap CURLSSLOPT_ALLOW_BEAST description.
+
+Daniel Stenberg (2 Aug 2023)
+
+- RELEASE-NOTES: synced
+
+- resolve: use PF_INET6 family lookups when CURL_IPRESOLVE_V6 is set
+
+ Previously it would always do PF_UNSPEC if CURL_IPRESOLVE_V4 is not
+ used, thus unnecessarily asking for addresses that will not be used.
+
+ Reported-by: Joseph Tharayil
+ Fixes #11564
+ Closes #11565
+
+- docs: link to the website versions instead of markdowns
+
+ ... to make the links work when the markdown is converted to webpages on
+ https://curl.se
+
+ Reported-by: Maurício Meneghini Fauth
+ Fixes https://github.com/curl/curl-www/issues/272
+ Closes #11569
+
+Viktor Szakats (1 Aug 2023)
+
+- cmake: cache more config and delete unused ones
+
+ - cache more Windows config results for faster initialization.
+
+ - delete unused config macros `HAVE_SYS_UTSNAME_H`, `HAVE_SSL_H`.
+
+ - delete dead references to `sys/utsname.h`.
+
+ Closes #11551
+
+- egd: delete feature detection and related source code
+
+ EGD is Entropy Gathering Daemon, a socket-based entropy source supported
+ by pre-OpenSSL v1.1 versions and now deprecated. curl also deprecated it
+ a while ago.
+
+ Its detection in CMake was broken all along because OpenSSL libs were
+ not linked at the point of feature check.
+
+ Delete detection from both cmake and autotools, along with the related
+ source snippet, and the `--with-egd-socket=` `./configure` option.
+
+ Closes #11556
+
+Stefan Eissing (1 Aug 2023)
+
+- tests: fix h3 server check and parallel instances
+
+ - fix check for availability of nghttpx server
+ - add `tcp` frontend config for same port as quic, as
+ without this, port 3000 is bound which clashes for parallel
+ testing
+
+ Closes #11553
+
+Daniel Stenberg (1 Aug 2023)
+
+- docs/cmdline-opts: spellfixes, typos and polish
+
+ To make them accepted by the spell checker
+
+ Closes #11562
+
+- CI/spellcheck: build curl.1 and spellcheck it
+
+ Added acceptable words
+
+ Closes #11562
+
+Alexander Jaeger (1 Aug 2023)
+
+- misc: fix various typos
+
+ Closes #11561
+
+Daniel Stenberg (1 Aug 2023)
+
+- http2: avoid too early connection re-use/multiplexing
+
+ HTTP/1 connections that are upgraded to HTTP/2 should not be picked up
+ for reuse and multiplexing by other handles until the 101 switching
+ process is completed.
+
+ Lots-of-debgging-by: Stefan Eissing
+ Reported-by: Richard W.M. Jones
+ Bug: https://curl.se/mail/lib-2023-07/0045.html
+ Closes #11557
+
+- Revert "KNOWN_BUGS: build for iOS simulator on macOS 13.2 with Xcode 14"
+
+ This reverts commit 2e8a3d7cb73c85a9aa151e263315f8a496dbb9d4.
+
+ It's a user error for supplying incomplete information to the build system.
+
+ Reported-by: Ryan Schmidt
+ Ref: https://github.com/curl/curl/issues/11215#issuecomment-1658729367
+
+Viktor Szakats (1 Aug 2023)
+
+- cmake: add support for single libcurl compilation pass
+
+ Before this patch CMake builds used two separate compilation passes to
+ build the shared and static libcurl respectively. This patch allows to
+ reduce that to a single pass if the target platform and build settings
+ allow it.
+
+ This reduces CMake build times when building both static and shared
+ libcurl at the same time, making these dual builds an almost zero-cost
+ option.
+
+ Enable this feature for Windows builds, where the difference between the
+ two passes was the use of `__declspec(dllexport)` attribute for exported
+ API functions for the shared builds. This patch replaces this method
+ with the use of `libcurl.def` at DLL link time.
+
+ Also update `Makefile.mk` to use `libcurl.def` to export libcurl API
+ symbols on Windows. This simplifies (or fixes) this build method (e.g.
+ in curl-for-win, which generated a `libcurl.def` from `.h` files using
+ an elaborate set of transformations).
+
+ `libcurl.def` has the maintenance cost of keeping the list of public
+ libcurl API symbols up-to-date. This list seldom changes, so the cost
+ is low.
+
+ Closes #11546
+
+- cmake: detect `SSL_set0_wbio` in OpenSSL
+
+ Present in OpenSSL 1.1.0 and BoringSSL.
+ Missing from LibreSSL 3.8.0.
+
+ Follow-up to f39472ea9f4f4e12cfbc0500c4580a8d52ce4a59
+
+ While here, also fix `RAND_egd()` detection which was broken, likely all
+ along. This feature is probably broken with CMake builds and also
+ requires a sufficiently obsolete OpenSSL version, so this part of the
+ update was not tested.
+
+ Closes #11555
+
+- cmake: fixup H2 duplicate symbols for unity builds
+
+ Closes #11550
+
+Pablo Busse (1 Aug 2023)
+
+- openssl: Support async cert verify callback
+
+ - Update the OpenSSL connect state machine to handle
+ SSL_ERROR_WANT_RETRY_VERIFY.
+
+ This allows libcurl users that are using custom certificate validation
+ to suspend processing while waiting for external I/O during certificate
+ validation.
+
+ Closes https://github.com/curl/curl/pull/11499
+
+Jay Satiro (1 Aug 2023)
+
+- tool_cb_wrt: fix invalid unicode for windows console
+
+ - Suppress an incomplete UTF-8 sequence at the end of the buffer.
+
+ - Attempt to reconstruct incomplete UTF-8 sequence from prior call(s)
+ in current call.
+
+ Prior to this change, in Windows console UTF-8 sequences split between
+ two or more calls to the write callback would cause invalid "replacement
+ characters" U+FFFD to be printed instead of the actual Unicode
+ character. This is because in Windows only UTF-16 encoded characters are
+ printed to the console, therefore we convert the UTF-8 contents to
+ UTF-16, which cannot be done with partial UTF-8 sequences.
+
+ Reported-by: Maksim Arhipov
+
+ Fixes https://github.com/curl/curl/issues/9841
+ Closes https://github.com/curl/curl/pull/10890
+
+Daniel Stenberg (1 Aug 2023)
+
+- sectransp: prevent CFRelease() of NULL
+
+ When SecCertificateCopyCommonName() returns NULL, the common_name
+ pointer remains set to NULL which apparently when calling CFRelease() on
+ (sometimes?) crashes.
+
+ Reported-by: Guillaume Algis
+ Fixes #9194
+ Closes #11554
+
+Jay Satiro (1 Aug 2023)
+
+- vtls: clarify "ALPN: offers" message
+
+ Before:
+ * ALPN: offers h2,http/1.1
+
+ After:
+ * ALPN: curl offers h2,http/1.1
+
+ Bug: https://curl.se/mail/lib-2023-07/0041.html
+ Reported-by: Richard W.M. Jones
+ Closes #11544
+
+Daniel Stenberg (1 Aug 2023)
+
+- urlapi: make sure zoneid is also duplicated in curl_url_dup
+
+ Add several curl_url_dup() tests to the general lib1560 test.
+
+ Reported-by: Rutger Broekhoff
+ Bug: https://curl.se/mail/lib-2023-07/0047.html
+ Closes #11549
+
+Sergey (1 Aug 2023)
+
+- urlapi: fix heap buffer overflow
+
+ `u->path = Curl_memdup(path, pathlen + 1);` accesses bytes after the null-ter
+ minator.
+
+ ```
+ ==2676==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x04d48c75 a
+ t pc 0x0112708a bp 0x006fb7e0 sp 0x006fb3c4
+ READ of size 78 at 0x04d48c75 thread T0
+ #0 0x1127089 in __asan_wrap_memcpy D:\a\_work\1\s\src\vctools\asan\llvm\c
+ ompiler-rt\lib\sanitizer_common\sanitizer_common_interceptors.inc:840
+ #1 0x1891a0e in Curl_memdup C:\actions-runner\_work\client\client\third_p
+ arty\curl\lib\strdup.c:97
+ #2 0x18db4b0 in parseurl C:\actions-runner\_work\client\client\third_part
+ y\curl\lib\urlapi.c:1297
+ #3 0x18db819 in parseurl_and_replace C:\actions-runner\_work\client\clien
+ t\third_party\curl\lib\urlapi.c:1342
+ #4 0x18d6e39 in curl_url_set C:\actions-runner\_work\client\client\third_
+ party\curl\lib\urlapi.c:1790
+ #5 0x1877d3e in parseurlandfillconn C:\actions-runner\_work\client\client
+ \third_party\curl\lib\url.c:1768
+ #6 0x1871acf in create_conn C:\actions-runner\_work\client\client\third_p
+ arty\curl\lib\url.c:3403
+ #7 0x186d8dc in Curl_connect C:\actions-runner\_work\client\client\third_
+ party\curl\lib\url.c:3888
+ #8 0x1856b78 in multi_runsingle C:\actions-runner\_work\client\client\thi
+ rd_party\curl\lib\multi.c:1982
+ #9 0x18531e3 in curl_multi_perform C:\actions-runner\_work\client\client\
+ third_party\curl\lib\multi.c:2756
+ ```
+
+ Closes #11560
+
+Daniel Stenberg (31 Jul 2023)
+
+- curl: make %output{} in -w specify a file to write to
+
+ It can be used multiple times. Use %output{>>name} to append.
+
+ Add docs. Test 990 and 991 verify.
+
+ Idea: #11400
+ Suggested-by: ed0d2b2ce19451f2
+ Closes #11416
+
+- RELEASE-NOTES: synced
+
+- tool: add "variable" support
+
+ Add support for command line variables. Set variables with --variable
+ name=content or --variable name@file (where "file" can be stdin if set
+ to a single dash (-)).
+
+ Variable content is expanded in option parameters using "{{name}}"
+ (without the quotes) if the option name is prefixed with
+ "--expand-". This gets the contents of the variable "name" inserted, or
+ a blank if the name does not exist as a variable. Insert "{{" verbatim
+ in the string by prefixing it with a backslash, like "\\{{".
+
+ Import an environment variable with --variable %name. It makes curl exit
+ with an error if the environment variable is not set. It can also rather
+ get a default value if the variable does not exist, using =content or
+ @file like shown above.
+
+ Example: get the USER environment variable into the URL:
+
+ --variable %USER
+ --expand-url = "https://example.com/api/{{USER}}/method"
+
+ When expanding variables, curl supports a set of functions that can make
+ the variable contents more convenient to use. It can trim leading and
+ trailing white space with "trim", output the contents as a JSON quoted
+ string with "json", URL encode it with "url" and base 64 encode it with
+ "b64". To apply functions to a variable expansion, add them colon
+ separated to the right side of the variable. They are then performed in
+ a left to right order.
+
+ Example: get the contents of a file called $HOME/.secret into a variable
+ called "fix". Make sure that the content is trimmed and percent-encoded
+ sent as POST data:
+
+ --variable %HOME=/home/default
+ --expand-variable fix@{{HOME}}/.secret
+ --expand-data "{{fix:trim:url}}"
+ https://example.com/
+
+ Documented. Many new test cases.
+
+ Co-brainstormed-by: Emanuele Torre
+ Assisted-by: Jat Satiro
+ Closes #11346
+
+- KNOWN_BUGS: cygwin: make install installs curl-config.1 twice
+
+ Closes #8839
+
+- KNOWN_BUGS: build for iOS simulator on macOS 13.2 with Xcode 14
+
+ Closes #11215
+
+- KNOWN_BUGS: cmake outputs: no version information available
+
+ Closes #11158
+
+- KNOWN_BUGS: APOP authentication fails on POP3
+
+ Closes #10073
+
+- KNOWN_BUGS: hyper is slow
+
+ Closes #11203
+
+Patrick Monnerat (31 Jul 2023)
+
+- configure, cmake, lib: more form api deprecation
+
+ Introduce a --enable-form-api configure option to control its inclusion
+ in builds. The condition name defined for it is CURL_DISABLE_FORM_API.
+
+ Form api code is dependent of MIME: configure and CMake handle this
+ dependency automatically: CMake by making it a dependent option
+ explicitly, configure by inheriting the MIME value by default and
+ rejecting explicit incompatible values.
+
+ "form-api" is now a new hidden test feature.
+
+ Update libcurl modules to respect this option and adjust tests
+ accordingly.
+
+ Closes #9621
+
+Daniel Stenberg (31 Jul 2023)
+
+- mailmap: add Derzsi Dániel
+
+Derzsi Dániel (31 Jul 2023)
+
+- wolfssl: support loading system CA certificates
+
+ Closes #11452
+
+Viktor Szakats (30 Jul 2023)
+
+- nss: delete more NSS references
+
+ Fix the distcheck CI failure and delete more NSS references.
+
+ Follow-up to 7c8bae0d9c9b2dfeeb008b9a316117d7b9675175
+
+ Reviewed-by: Marcel Raad
+ Reviewed-by: Daniel Stenberg
+ Closes #11548
+
+Daniel Stenberg (29 Jul 2023)
+
+- nss: remove support for this TLS library
+
+ Closes #11459
+
+Ryan Schmidt (29 Jul 2023)
+
+- macOS: fix target detection more
+
+ Now SCDynamicStoreCopyProxies is called (and the required frameworks are
+ linked in) on all versions of macOS and only on macOS. Fixes crash due
+ to undefined symbol when built with the macOS 10.11 SDK or earlier.
+
+ CURL_OSX_CALL_COPYPROXIES is renamed to CURL_MACOS_CALL_COPYPROXIES and
+ is now only defined when SCDynamicStoreCopyProxies will actually be
+ called. Previously, it was defined when ENABLE_IPV6 was not defined but
+ SCDynamicStoreCopyProxies is not called in that case.
+
+ TARGET_OS_OSX is only defined in the macOS 10.12 SDK and later and only
+ when dynamic targets are enabled. TARGET_OS_MAC is always defined but
+ means any Mac OS or derivative including macOS, iOS, tvOS, and watchOS.
+ TARGET_OS_IPHONE means any Darwin OS other than macOS.
+
+ Follow-up to c73b2f82
+
+ Fixes #11502
+ Closes #11516
+
+Daniel Stenberg (29 Jul 2023)
+
+- tool_operate: allow SSL_CERT_FILE and SSL_CERT_DIR
+
+ ... used at once.
+
+ Reported-by: Gabriel Corona
+ Fixes #11325
+ Closes #11531
+
+Thomas M. DuBuisson (29 Jul 2023)
+
+- CI: remove Lift's configuration
+
+ The Lift tool is being retired. Their site reads:
+
+ "Sonatype Lift will be retiring on Sep 12, 2023, with its analysis
+ stopping on Aug 12, 2023."
+
+ Closes #11541
+
+Nathan Moinvaziri (29 Jul 2023)
+
+- Revert "schannel: reverse the order of certinfo insertions"
+
+ This reverts commit 8986df802db9b5338d9d50a54232ebae4dbcf6dd.
+
+ Windows does not guarantee a particular certificate ordering, even
+ though TLS may have its own ordering/relationship guarantees. Recent
+ versions of Windows 11 reversed the ordering of ceritifcates returned by
+ CertEnumCertificatesInStore, therefore this commit no longer works as
+ initially intended. libcurl makes no guarantees about certificate
+ ordering if the operating system can't.
+
+ Ref: https://github.com/curl/curl/issues/9706
+
+ Closes https://github.com/curl/curl/pull/11536
+
+wangzhikun (29 Jul 2023)
+
+- winbuild: improve check for static zlib
+
+ - Check for zlib static library name zlibstatic.lib.
+
+ zlib's static library has a different name depending on how it was
+ built. zlibstatic.lib is output by cmake. zlibstat.lib is output by
+ their pre-generated Visual Studio project files (in the contrib
+ directory) and defines ZLIB_WINAPI (ie it's meant to use stdcall
+ instead of cdecl if you end up exporting the zlib functions).
+
+ Prior to this change the makefile only checked for the latter.
+
+ Closes https://github.com/curl/curl/pull/11521
+
+Daniel Stenberg (29 Jul 2023)
+
+- configure: use the pkg-config --libs-only-l flag for libssh2
+
+ ... instead of --libs, as that one also returns -L flags.
+
+ Reported-by: Wilhelm von Thiele
+ Fixes #11538
+ Closes #11539
+
+Viktor Szakats (29 Jul 2023)
+
+- cmake: support building static and shared libcurl in one go
+
+ This patch adds the ability to build a static and shared libcurl library
+ in a single build session. It also adds an option to select which one to
+ use when building the curl executable.
+
+ New build options:
+ - `BUILD_STATIC_LIBS`. Default: `OFF`.
+ Enabled automatically if `BUILD_SHARED_LIBS` is `OFF`.
+ - `BUILD_STATIC_CURL`. Default: `OFF`.
+ Requires `BUILD_STATIC_LIBS` enabled.
+ Enabled automatically if building static libcurl only.
+ - `STATIC_LIB_SUFFIX`. Default: empty.
+ - `IMPORT_LIB_SUFFIX`. Default: `_imp` if implib filename would collide
+ with static lib name (typically with MSVC) in Windows builds.
+ Otherwise empty.
+
+ Also:
+
+ - Stop setting the `CURL_STATICLIB` macro via `curl_config.h`, and pass
+ it directly to the compiler. This also allows to delete a condition
+ from `tests/server/CMakeLists.txt`.
+
+ - Complete a TODO by following the logic used in autotools (also for
+ `LIBCURL_NO_SHARED`), and set `-DCURL_STATICLIB` in `Cflags:` of
+ `libcurl.pc` for _static-only_ curl builds.
+
+ - Convert an existing CI test to build both shared and static libcurl.
+
+ Closes #11505
+
+Stefan Eissing (28 Jul 2023)
+
+- CI/awslc: add cache for build awslc library
+
+ Closes #11535
+
+- GHA/linux.yml: add caching
+
+ Closes #11532
+
+Daniel Stenberg (27 Jul 2023)
+
+- RELEASE-NOTES: synced
+
+ Bump working version to 8.3.0
+
+- url: remove infof() output for "still name resolving"
+
+ The message does not help and might get spewed a lot during times.
+
+ Reported-by: yushicheng7788 on github
+ Fixes #11394
+ Closes #11529
+
+- KNOWN_BUGS: cygwin: "WARNING: UNPROTECTED PRIVATE KEY FILE!"
+
+ Closes #11244
+
+Stefan Eissing (27 Jul 2023)
+
+- CI: quiche updates
+
+ - remove quiche from standard `linux` workflow
+ - add mod_h2 caching to quiche workflow
+ - rename quiche to quiche-linux
+ - move version definitions into env section
+
+ Closes #11528
+
+- http2: disable asssertion blocking OSSFuzz testing
+
+ - not clear how this triggers and it blocks OSSFuzz testing other
+ things. Since we handle the case with an error return, disabling the
+ assertion for now seems the best way forward.
+
+ Fixes #11500
+ Closes #11519
+
+- http2: fix in h2 proxy tunnel: progress in ingress on sending
+
+ - depending on what is tunneled, the proxy may never get invoked for
+ receiving data explicitly. Not progressing ingress may lead to stalls
+ due to missed WINDOW_UPDATEs.
+
+ CI:
+ - add a chache for building mod_h2
+
+ Closes #11527
+
+- CI ngtcp2+quictls: use nghttpx cache as in quiche build
+
+Jay Satiro (27 Jul 2023)
+
+- bearssl: don't load CA certs when peer verification is disabled
+
+ We already do this for other SSL backends.
+
+ Bug: https://github.com/curl/curl/pull/11457#issuecomment-1644587473
+ Reported-by: kyled-dell@users.noreply.github.com
+
+ Closes https://github.com/curl/curl/pull/11497
+
+Daniel Stenberg (26 Jul 2023)
+
+- easy: remove #ifdefs to make code easier on the eye
+
+ Closes #11525
+
+Stefan Eissing (26 Jul 2023)
+
+- GHA: adding quiche workflow
+
+ - adding separate quiche workflow to also build nghttpx server for testing
+
+ Closes #11517
+
Version 8.2.1 (26 Jul 2023)
Daniel Stenberg (26 Jul 2023)
@@ -6246,2769 +8981,3 @@ Grisha Levit (6 Mar 2023)
See #10079
Closes #10675
-
-Jay Satiro (6 Mar 2023)
-
-- tests: fix gnutls-serv check
-
- - If gnutls-serv doesn't exist then don't try to execute it.
-
- Follow-up to 2fdc1d81.
-
- Closes https://github.com/curl/curl/pull/10688
-
-Daniel Stenberg (6 Mar 2023)
-
-- lib1560: fix enumerated type mixed with another type
-
- Follow-up to c84c0f9aa3bb006
-
- Closes #10684
-
-Viktor Szakats (5 Mar 2023)
-
-- cmake: fix enabling LDAPS on Windows
-
- Before this patch, enabling LDAPS required a manual C flag:
- https://github.com/curl/curl-for-win/blob/c1cfc31cfc04f24f7a4f946564d6f0e1b4d
- 7dd36/curl-cmake.sh#L105
-
- Fix this and enable LDAPS automatically when using `wldap32` (and
- when not explicitly disabled). This matches autotools and `Makefile.mk`
- behavior. Also remove issue from KNOWN_BUGS.
-
- Add workaround for MSVS 2010 warning triggered by LDAPS now enabled
- in more CI tests:
- `ldap.c(360): warning C4306: 'type cast' : conversion from 'int' to 'void *'
- of greater size`
- Ref: https://ci.appveyor.com/project/curlorg/curl/builds/46408284/job/v8mwl9y
- fbmoeqwlr#L312
-
- Reported-by: JackBoosY on github
- Reviewed-by: Jay Satiro
- Reviewed-by: Marcel Raad
- Fixes #6284
- Closes #10674
-
-- Makefile.mk: delete redundant `HAVE_LDAP_SSL` macro [ci skip]
-
- Since abebb2b8939c6b3e0f951eb2d9ec3729b569aa2c, we set this macro for
- all Windows `wldap32` builds using `Makefile.mk`.
-
- For OpenLDAP builds this macro is not enough to enable LDAPS, and
- OpenLDAP is not an option in `Makefile.mk`. For Novell LDAP it might
- have helped, but it's also not an option anymore in `Makefile.mk`.
-
- The future for LDAPS is that we should enable it by default without
- extra build knobs.
-
- Reviewed-by: Marcel Raad
- Closes #10681
-
-- cmake: skip CA-path/bundle auto-detection in cross-builds
-
- Also remove issue from KNOWN_BUGS.
-
- Reported-by: Cristian Morales Vega
- Reviewed-by: Marcel Raad
- Fixes #6178
- Closes #10676
-
-Daniel Stenberg (3 Mar 2023)
-
-- schannel: loop over the algos to pick the selected one
-
- Avoid using the funny macro and the extra buffer copy.
-
- Closes #10647
-
-- wildcard: remove files and move functions into ftplistparser.c
-
-- ftp: allocate the wildcard struct on demand
-
- The feature is rarely used so this frees up data for the vast majority
- of easy handles that don't use it.
-
- Rename "protdata" to "ftpwc" since it is always an FTP wildcard struct
- pointer. Made the state struct field an unsigned char to save space.
-
- Closes #10639
-
-- lib1560: test parsing URLs with ridiculously large fields
-
- In the order of 120K.
-
- Closes #10665
-
-Brad Spencer (3 Mar 2023)
-
-- urlapi: parse IPv6 literals without ENABLE_IPV6
-
- This makes the URL parser API stable and working the same way
- independently of libcurl supporting IPv6 transfers or not.
-
- Closes #10660
-
-Jan Engelhardt (3 Mar 2023)
-
-- build: drop the use of XC_AMEND_DISTCLEAN
-
- Because automake used to delete depdirs at once (.deps) and there was an issu
- e
- with portability, curl's XC_AMEND_DISTCLEAN greps the Makefiles in an attempt
- to build a list of all depfiles and delete them individually instead.
-
- Since commit 08849db866b44510f6b8fd49e313c91a43a3dfd3, automake switched from
- deleting directories to individual files. curl's custom logic now finds a lot
- more results with the grep (the filtering of these results isn't great), whic
- h
- causes a massive bloating of the Makefile in the order of O(n^2).
-
- Also remove now-unused XC_AMEND_DISTCLEAN macro group
-
- References: https://github.com/curl/curl/issues/9843
- References: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=59288
-
- Reported-by: Ilmari Lauhakangas
- Fixes #9843
- Closes #10661
-
-Balakrishnan Balasubramanian (3 Mar 2023)
-
-- test1470: test socks proxy using unix sockets and connect to https
-
- Similar to test1468 except using https instead of http
-
- Closes #10662
-
-Daniel Stenberg (3 Mar 2023)
-
-- test1960: verify CURL_SOCKOPT_ALREADY_CONNECTED
-
- When returned from the CURLOPT_SOCKOPTFUNCTION, like when we have a
- custom socket connected in the app, passed in to libcurl.
-
- Verifies the fix in #10648
-
- Closes #10651
-
-Stefan Eissing (2 Mar 2023)
-
-- tests: rename tests/tests-httpd to tests/http
-
- - httpd is only one server we test with
- - the suite coveres the HTTP protocol in general where
- the default test cases need a more beefy environment
-
- Closes #10654
-
-- socket: detect "dead" connections better, e.g. not fit for reuse
-
- - refs #10646 where reuse was attempted on closed connections in the
- cache, leading to an exhaustion of retries on a transfer
- - the mistake was that poll events like POLLHUP, POLLERR, etc
- were regarded as "not dead".
- - change cf-socket filter check to regard such events as inidication
- of corpsiness.
- - vtls filter checks: fixed interpretation of backend check result
- when inconclusive to interrogate status further down the filter
- chain.
-
- Reported-by: SendSonS on github
- Fixes #10646
- Closes #10652
-
-- lib: give source files cf-http.* better fitting names
-
- Closes #10656
-
-- http2: fix code indent
-
- Closes https://github.com/curl/curl/pull/10655
-
-Shankar Jadhavar (1 Mar 2023)
-
-- cf-socket: if socket is already connected, return CURLE_OK
-
- In 7.87.0, if callback method for CURLOPT_SOCKOPTFUNCTION returns
- CURL_SOCKOPT_ALREADY_CONNECTED then curl library used to return
- CURLE_OK. n 7.88.0, now even if callback returns
- CURL_SOCKOPT_ALREADY_CONNECTED, curl library still tries to connect to
- socket by invoking method do_connect().
-
- This is regression caused by commit
- https://github.com/curl/curl/commit/71b7e0161032927cdfb
-
- Fix: Check if we are already connected and return CURLE_OK.
-
- Fixes #10626
- Closes #10648
-
-Jay Satiro (1 Mar 2023)
-
-- DYNBUF.md: note Curl_dyn_add* calls Curl_dyn_free on failure
-
- This is the existing behavior and it has been widely assumed in the
- codebase.
-
- Closes https://github.com/curl/curl/pull/10645
-
-Stefan Eissing (1 Mar 2023)
-
-- http2: fix upload busy loop
-
- - Set KEEP_SEND_PAUSE when exhausting remote HTTP/2 window size of a
- stream.
-
- - Clear KEEP_SEND_PAUSE when receiving HTTP/2 window updates on a paused
- stream.
-
- - Also fix http2 send compiler warnings reported in #10449.
-
- Prior to this change, starting in 71b7e016 which precedes 7.88.0,
- libcurl may eat CPU during HTTP/2 upload.
-
- Reported-by: Jay Satiro
-
- Fixes https://github.com/curl/curl/issues/10449
- Fixes https://github.com/curl/curl/issues/10618
- Closes https://github.com/curl/curl/pull/10627
-
-Daniel Stenberg (1 Mar 2023)
-
-- sectransp: make read_cert() use a dynbuf when loading
-
- Closes #10632
-
-Jay Satiro (1 Mar 2023)
-
-- transfer: limit Windows SO_SNDBUF updates to once a second
-
- - Change readwrite_upload() to call win_update_buffer_size() no more
- than once a second to update SO_SNDBUF (send buffer limit).
-
- Prior to this change during an upload readwrite_upload() could call
- win_update_buffer_size() anywhere from hundreds of times per second to
- an extreme test case of 100k per second (which is likely due to a bug,
- see #10618). In the latter case WPA profiler showed
- win_update_buffer_size was the highest capture count in
- readwrite_upload. In any case the calls were excessive and unnecessary.
-
- Ref: https://github.com/curl/curl/pull/2762
-
- Closes https://github.com/curl/curl/pull/10611
-
-Daniel Stenberg (28 Feb 2023)
-
-- RELEASE-NOTES: synced
-
-Stefan Eissing (28 Feb 2023)
-
-- http2: fix for http2-prior-knowledge when reusing connections
-
- - refs #10634 where errors in the HTTP/2 framing layer are observed.
- - the bug was that on connection reuse, the code attempted to switch
- in yet another layer of HTTP/2 handling instead of detecting that
- this was already in place.
- - added pytest testcase reproducing the issue.
-
- Reported-by: rwmjones on github
- Fixes #10634
- Closes #10643
-
-- cf-socket: fix handling of remote addr for accepted tcp sockets
-
- - do not try to determine the remote address of a listen socket. There
- is none.
- - Update remote address of an accepted socket by getpeername() if
- available.
-
- Reported-by: Harry Sintonen
- Fixes #10622
- Closes #10642
-
-- http: fix unix domain socket use in https connects
-
- - when h2/h3 eyeballing was involved, unix domain socket
- configurations were not honoured
- - configuring --unix-socket will disable HTTP/3 as candidate for eyeballing
- - combinatino of --unix-socket and --http3-only will fail during initialisati
- on
- - adding pytest test_11 to reproduce
-
- Reported-by: Jelle van der Waa
- Fixes #10633
- Closes #10641
-
-Daniel Stenberg (28 Feb 2023)
-
-- setopt: move the CURLOPT_CHUNK_DATA pointer to the set struct
-
- To make duphandle work etc
-
- Closes #10635
-
-Viktor Szakats (28 Feb 2023)
-
-- quic/schannel: fix compiler warnings
-
- Fixes #10603
- Closes #10616
-
-Daniel Stenberg (28 Feb 2023)
-
-- page-footer: add explanation for three missing exit codes
-
- Added in 7.73.0, 7.77.0 and 7.84.0
-
- Closes #10630
-
-積丹尼 Dan Jacobson (28 Feb 2023)
-
-- rate.c: single URLs make no sense in --rate example
-
- Here somehow you need to put more than one URL in these examples, else
- they will make no sense, as --rate only affects the second and beyond
- URLs. The first URL will always finish the same time no matter what
- --rate is given.
-
- Closes #10638
-
-Daniel Stenberg (28 Feb 2023)
-
-- libcurl-errors.3: add the CURLHcode errors from curl_easy_header.3
-
- Closes #10629
-
-- mqtt: on send error, return error
-
- Reported-by: Maciej Domanski
-
- Closes #10623
-
-- ws: keep the socket non-blocking
-
- Reported-by: marski on github
- Fixes #10615
- Closes #10625
-
-- hostip: avoid sscanf and extra buffer copies
-
- Also made create_hostcache_id() return the id length.
-
- Closes #10601
-
-- PARALLEL-TRANSFERS.md: not "early days" for this anymore
-
- Refresh the language as the support is now over three years old
-
- Closes #10624
-
-- easy: remove infof() debug leftover from curl_easy_recv
-
- It said "reached [path]/easy.c:1231"
-
- Closes #10628
-
-- idn: return error if the conversion ends up with a blank host
-
- Some IDN sequences are converted into "" (nothing), which can make this
- function end up with a zero length host name and we cannot consider that
- a valid host to continue with.
-
- Reported-by: Maciej Domanski
- Closes #10617
-
-- examples/http3.c: use CURL_HTTP_VERSION_3
-
- and update the comment
-
- Closes #10619
-
-- x509asn1.c: use correct format specifier for infof() call
-
- Detected by Coverity
-
- Closes #10614
-
-- Revert "GHA: add Microsoft C++ Code Analysis"
-
- This reverts commit e0db842b2a082dffad4a9fbe31321e9a75c74041.
-
- This tool seems very restricted in how often it might be used by a
- project and thus very quickly start to report fails simply because it
- refuses to run when "there are more runs than allowed".
-
- Closes #10613
-
-Patrick Monnerat (25 Feb 2023)
-
-- tests: test secure mail protocols with explicit SSL requests
-
- New tests 987, 988 and 989, disabled for rustls (hanging).
-
- Closes #10077
-
-- tests: support for imaps/pop3s/smtps protocols
-
- Closes #10077
-
-- runtests: use a hash table for server port numbers
-
- Closes #10077
-
-Andy Alt (25 Feb 2023)
-
-- INTERNALS.md: grammar
-
- Closes #10607
-
-Daniel Stenberg (25 Feb 2023)
-
-- RELEASE-NOTES: synced
-
-Philip Heiduck (25 Feb 2023)
-
-- .cirrus.yml: Bump to FreeBSD 13.2
-
- Closes #10270
-
-- ngtcp2-gnutls.yml: bump to gnutls 3.8.0
-
- Closes #10507
-
-- CI: update ngtcp2 and nghttp2 for pytest
-
- Follow-up: https://github.com/curl/curl/commit/5c9ee8cef4b351a085b440f8178500
- 124647f8e6
-
- Closes #10508
-
-Andy Alt (25 Feb 2023)
-
-- GHA: use same flags for Slackbuild as Slack package
-
- Closes #10526
-
-Daniel Stenberg (24 Feb 2023)
-
-- rtsp: avoid sscanf for parsing
-
- Closes #10605
-
-- http_proxy: parse the status line without sscanf
-
- Closes #10602
-
-- telnet: error correctly for WS set to "x[num]"
-
- Follow-up to e4f93be9d587
- Reported-by: Harry Sintonen
- Closes #10606
-
-- krb5: avoid sscanf for parsing
-
- Closes #10599
-
-- misc: remove support for curl_off_t < 8 bytes
-
- Closes #10597
-
-- telnet: parse NEW_ENVIRON without sscanf
-
- Closes #10596
-
-- telnet: parse the WS= argument without sscanf
-
- Closes #10596
-
-- telnet: parse telnet options without sscanf
-
- Closes #10596
-
-- ftp: replace sscanf for MDTM 213 response parsing
-
- Closes #10590
-
-- ftp: replace sscanf for PASV parsing
-
- Closes #10590
-
-- ftp: make the EPSV response parser not use sscanf
-
- Closes #10590
-
-Stefan Eissing (24 Feb 2023)
-
-- ngtcp2: fix unwanted close of file descriptor 0
-
- ... causing macOS to hand out 0 as next socket handle and failing on
- further operations.
-
- Reported-by: Sergey Fionov
- Fixes #10593
- Closes #10595
-
-Daniel Stenberg (23 Feb 2023)
-
-- select: stop treating POLLRDBAND as an error
-
- POLLRDBAND does not seem to be an general error and on Windows the value
- for POLLIN is 768 and the value for POLLRDBAND is 512.
-
- Fixes #10501
- Reported-by: opensslonzos-github on github
- Closes #10592
-
-- test978: mark file as text mode
-
- Follow-up to 4ea5702980cb
-
- To fix test failures on Windows
-
- Closes #10594
-
-- http: rewrite the status line parser without sscanf
-
- Closes #10585
-
-- test978: verify that --stderr works for -w's stderr as well
-
-Jay Satiro (23 Feb 2023)
-
-- curl: make -w's %{stderr} use the file set with --stderr
-
- Reported-by: u20221022 on github
- Fixes #10491
- Closes #10569
-
-- winbuild: fix makefile clean
-
- - Fix and move 'clean' code that removes the output and obj directories
- trees from MakefileBuild.vc to Makefile.vc.
-
- Prior to this change the 'clean' code did not work right because the
- variables containing the directory names were not fully initialized and
- the rmdir syntax was sometimes incorrect (typos). DIRDIST for example
- was set to ..\builds\ and not ..\builds\$(CONFIG_NAME_LIB)\ so it would
- remove the former and not the latter. If WITH_PREFIX was set then that
- directory was removed instead.
-
- Also, DIRDIST (the output directory) even if initialized should not be
- removed by MakefileBuild.vc because by that time it could be set to a
- user directory that may contain other files if WITH_PREFIX is set (eg we
- don't want rmdir /s /q C:\usr\local). Therefore we remove from
- Makefile.vc before any of that happens. I added a comment in both
- makefiles explaining this.
-
- Closes https://github.com/curl/curl/pull/10576
-
-- sectransp: fix compiler warning c89 mixed code/declaration
-
- Since cbf57176 the Cirrus CI 'macOS arm64 SecureTransport http2' has
- been failing due to c89 warnings mixed code/declaration. That commit is
- not the cause so I assume something has changed in the CI outside of our
- configuration. Anyway, we don't mix code/declaration so this is the fix
- for that.
-
- Closes https://github.com/curl/curl/pull/10574
-
-Philipp Engel (22 Feb 2023)
-
-- BINDINGS: add Fortran binding
-
- Closes #10589
-
-Stefan Eissing (22 Feb 2023)
-
-- test2600: detect when ALARM_TIMEOUT is in use and adjust
-
- - use higher timeout values > 1s
- - skip duration checks
-
- Assisted-by: Marcel Raad
- Closes #10513
-
-Daniel Stenberg (22 Feb 2023)
-
-- RELEASE-NOTES: synced
-
-- test686: verify return code for no URL after --next
-
-- tool_operate: propagate error codes for missing URL after --next
-
- Fixes #10558
- Reported-by: u20221022 on github
- Closes #10580
-
-- test1278: verify that an extra --no-remote-name cause no warning
-
-- tool_getparam: don't add a new node for just --no-remote-name
-
- Unless --remote-name-all is used.
-
- Fixes #10564
- Reported-by: u20221022 on github
- Closes #10582
-
-- gen.pl: add '%GLOBALS' as a variable for mainpage
-
- And use it in page-header to list all global command line options.
-
-- docs/cmdline-opts: mark all global options
-
- gen.pl now outputs a generic explanations for them for each option
-
- Fixes #10566
- Reported-by: u20221022 on github
- Closes #10584
-
-- GHA: add Microsoft C++ Code Analysis
-
- Closes #10583
-
-- tool_progress: shut off progress meter for --silent in parallel
-
- Reported-by: finkjsc on github
- Fixes #10573
- Closes #10579
-
-- lib1560: add a test using %25 in the userinfo in a URL
-
- Closes #10578
-
-Stefan Eissing (21 Feb 2023)
-
-- CURLOPT_PIPEWAIT: allow waited reuse also for subsequent connections
-
- As tested in test_02_07, when firing off 200 urls with --parallel, 199
- wait for the first connection to be established. if that is multiuse,
- urls are added up to its capacity.
-
- The first url over capacity opens another connection. But subsequent
- urls found the same situation and open a connection too. They should
- have waited for the second connection to actually connect and make its
- capacity known.
-
- This change fixes that by
-
- - setting `connkeep()` early in the HTTP setup handler. as otherwise
- a new connection is marked as closeit by default and not considered
- for multiuse at all
- - checking the "connected" status for a candidate always and continuing
- to PIPEWAIT if no alternative is found.
-
- pytest:
- - removed "skip" from test_02_07
- - added test_02_07b to check that http/1.1 continues to work as before
-
- Closes #10456
-
-Daniel Stenberg (21 Feb 2023)
-
-- test419: verify --dump-header to file that cannot be created
-
- Closes #10571
-
-- tool_operate: avoid fclose(NULL) on bad header dump file
-
- Fixes #10570
- Reported-by: Jérémy Rabasco
- Closes #10571
-
-- RELEASE-NOTES: synced
-
- Starting the journey towards 8.0.0
-
-- cookie: parse without sscanf()
-
- Saves us from using 2*4096 bytes buffers on stack, the extra copies and
- more.
-
- Closes #10550
-
-- lib517: verify time stamps without leading zeroes plus some more
-
-- parsedate: replace sscanf( for time stamp parsing
-
- Closes #10547
-
-- parsedate: parse strings without using sscanf()
-
- - sscanf is slow and complex, avoid it
- - give up already if the string is 12 bytes or longer as no valid string
- can be that long
- - this can now be done without copy
-
- Closes #10547
-
-Matt Jolly (20 Feb 2023)
-
-- tests: HTTP server fixups
-
- - httpserver.pl -> http-server.pl for consistency
- - add http3-server.pl to EXTRA_DIST; alphabetise for maintainability
- - nghttpx proxy invocation scripts should not use getcwd
-
- Closes #10568
-
-Version 7.88.1 (20 Feb 2023)
-
-Daniel Stenberg (20 Feb 2023)
-
-- RELEASE-NOTES: synced
-
- 7.88.1 release
-
-- THANKS: add contributors from 7.88.1
-
-- socketpair: allow EWOULDBLOCK when reading the pair check bytes
-
- Reported-by: Gunamoi Software
- Co-authored-by: Jay Satiro
- Fixes #10561
- Closes #10562
-
-Jay Satiro (18 Feb 2023)
-
-- tool_operate: fix scanbuild compiler warning
-
- Prior to this change Azure CI scanbuild warned of a potential NULL
- pointer string passed to strtol when CURLDEBUG enabled, even though the
- way the code was written it wouldn't have happened.
-
- Bug: https://github.com/curl/curl/commit/5479d991#r101159711
- Reported-by: Marcel Raad
-
- Closes https://github.com/curl/curl/pull/10559
-
-- curl_setup: Suppress OpenSSL 3 deprecation warnings
-
- - Define OPENSSL_SUPPRESS_DEPRECATED.
-
- OpenSSL 3 has deprecated some of the functions libcurl uses such as
- those with DES, MD5 and ENGINE prefix. We don't have replacements for
- those functions so the warnings were disabled in autotools and cmake
- builds, but still showed in other builds.
-
- Closes https://github.com/curl/curl/pull/10543
-
-- build-openssl.bat: keep OpenSSL 3 engine binaries
-
- Prior to this change copying the OpenSSL 3 engine binaries failed
- because 'engines-1_1' (OpenSSL 1.1.x folder name) was erroneously used
- instead of 'engines-3'. The OpenSSL 3 builds would complete successfully
- but without the engine binaries.
-
- Closes https://github.com/curl/curl/pull/10542
-
-ALittleDruid (18 Feb 2023)
-
-- cmake: fix Windows check for CryptAcquireContext
-
- Check for CryptAcquireContext in windows.h and wincrypt.h only, since
- otherwise this check may fail due to third party headers not found.
-
- Closes https://github.com/curl/curl/pull/10353
-
-Daniel Stenberg (19 Feb 2023)
-
-- remote-header-name.d: mention that filename* is not supported
-
- and that you can use --clobber to allow overwriting.
-
- Ref: #10533
- Closes #10555
-
- Co-authored-by: Jay Satiro <raysatiro@yahoo.com>
-
-Pierrick Charron (18 Feb 2023)
-
-- CURLOPT_WS_OPTIONS.3: fix the availability version
-
- Closes #10557
-
-Jacob Hoffman-Andrews (18 Feb 2023)
-
-- GHA: update rustls dependency to 0.9.2
-
- This allows re-enabling test 312 for the rustls backend.
-
- Closes #10553
-
-Philip Heiduck (18 Feb 2023)
-
-- HTTP3.md: update git branches
-
- Closes #10554
-
-Stefan Eissing (17 Feb 2023)
-
-- urldata: remove `now` from struct SingleRequest - not needed
-
- Closes #10549
-
-Daniel Stenberg (17 Feb 2023)
-
-- lib1560: add IPv6 canonicalization tests
-
- Closes #10552
-
-- RELEASE-NOTES: synced
-
-- urlapi: do the port number extraction without using sscanf()
-
- - sscanf() is rather complex and slow, strchr() much simpler
-
- - the port number function does not need to fully verify the IPv6 address
- anyway as it is done later in the hostname_check() function and doing
- it twice is unnecessary.
-
- Closes #10541
-
-Stefan Eissing (17 Feb 2023)
-
-- setopt: allow HTTP3 when HTTP2 is not defined
-
- Reported-by: Karthikdasari0423 on github
- Fixes #10538
- Closes #10544
-
-Jon Rumsey (17 Feb 2023)
-
-- os400: correct Curl_os400_sendto()
-
- Add const qualifier to 5th argument of Curl_os400_sendto()
-
- Make OS400 wrapper for sendto match the normal prototype of sendto()
- with a const qualifier.
-
- Fixes #10539
- Closes #10548
-
-Stefan Eissing (17 Feb 2023)
-
-- tests-httpd: add proxy tests
-
- for direct and tunneling checks on http: and https:
-
- Closes #10519
-
-Daniel Stenberg (17 Feb 2023)
-
-- curl: make --silent work stand-alone
-
- - renamed the struct field to 'silent' to match the cmdline option
- - make --show-error toggle independently of --silent
- - make --silent independent of ->noprogress as well
-
- By doing this, the three options --silent, --no-progress-meter and
- --show-error should work independently of each other and also work with
- and without '--no-' prefix as documented.
-
- Reported-by: u20221022 on github
- Fixes #10535
- Closes #10536
-
-- socks: allow using DoH to resolve host names
-
- For SOCKS modes where a local host resolve is done.
-
- It was previously disabled in 12d655d4561, but a few local tests seem to
- indicate that it works fine. Works now because of the SOCKS refactor of
- 4a4b63daaa01ef59 that made it non-blocking.
-
- Reported-by: roughtex on github
- Fixes #10537
- Closes #10540
-
-Stefan Eissing (17 Feb 2023)
-
-- test: add test for HTTP/2 corruption as reported in #10525
-
- - adding test_02_20 for reproducing the situation
- - using recently released mod_h2 Apache module
- - skipping test if an older version is installed
- - adding installation of current mod_h2 to github pytest workflow
-
- This reproduces the error reliable (for me) on the lib/http2.c version
- of curl 7.88.0. And passes with the recent curl master.
-
- Closes #10534
-
-Daniel Stenberg (16 Feb 2023)
-
-- tool_operate: allow debug builds to set buffersize
-
- Using the CURL_BUFFERSIZE environment variable.
-
- Closes #10532
-
-Stefan Eissing (16 Feb 2023)
-
-- connnect: fix timeout handling to use full duration
-
- - connect timeout was used at half the configured value, if the
- destination had 1 ip version 4 and other version 6 addresses
- (or the other way around)
- - extended test2600 to reproduce these cases
-
- Reported-by: Michael Kaufmann
- Fixes #10514
- Closes #10517
-
-Daniel Stenberg (16 Feb 2023)
-
-- tool_getparam: make --get a true boolean
-
- To match how it is documented in the man page.
-
- Fixes #10527
- Reported-by: u20221022 on github
- Closes #10531
-
-Harry Sintonen (16 Feb 2023)
-
-- http:: include stdint.h more readily
-
- Closes #10516
-
-Stefan Eissing (16 Feb 2023)
-
-- tests: make the telnet server shut down a socket gracefully
-
- - test 1452 failed occasionally with ECONNRESET errnos in curl when the
- server closed the connection in an unclean state.
-
- Closes #10509
-
-Harry Sintonen (16 Feb 2023)
-
-- http2: set drain on stream end
-
- Ensure that on_frame_recv() stream end will trigger a read if there is
- pending data. Without this it could happen that the pending data is
- never consumed.
-
- This combined with https://github.com/curl/curl/pull/10529 should fix
- https://github.com/curl/curl/issues/10525
-
- Ref: https://github.com/curl/curl/issues/10525
- Closes #10530
-
-Stefan Eissing (16 Feb 2023)
-
-- http2: buffer/pausedata and output flush fix.
-
- * do not process pending input data when copying pausedata to the
- caller
- * return CURLE_AGAIN if the output buffer could not be completely
- written out.
-
- Ref: #10525
- Closes #10529
-
-Marcel Raad (16 Feb 2023)
-
-- krb5: silence cast-align warning
-
- Add an intermediate cast to `void *`, as done everywhere else when
- casting from `sockaddr *` to `sockaddr_in *`.
-
- Closes https://github.com/curl/curl/pull/10528
-
-Daniel Stenberg (15 Feb 2023)
-
-- RELEASE-NOTES: synced
-
- bumped to 7.88.1
-
-- tests: make sure gnuserv-tls has SRP support before using it
-
- Reported-by: fundawang on github
- Fixes #10522
- Closes #10524
-
-- runtests: fix "uninitialized value $port"
-
- by using a more appropriate variable
-
- Reported-by: fundawang on github
- Fixes #10518
- Closes #10520
-
-Version 7.88.0 (15 Feb 2023)
-
-Daniel Stenberg (15 Feb 2023)
-
-- RELEASE-NOTES: synced
-
- 7.88.0 release
-
-- THANKS: added contributors from 7.88.0
-
-- openssl: rename 'errcode_t' to 'sslerr_t'
-
- Turns out "/usr/include/et/com_err.h" typedefs this type (without proper
- variable scoping).
-
- comerr is the "common error description library" that apparently might be use
- d
- by krb5 code, which then makes this header get used in a curl build.
-
- Reported-by: Bruno Henrique Batista Cruz da Silva
- Fixed #10502
- Closes #10500
-
-Dan Fandrich (13 Feb 2023)
-
-- CONTRIBUTE: More formally specify the commit description
-
- This codifies what people have actually used in git commits over the
- past 6 years. I've left off some lesser-used headers that appear to
- duplicate others and tried to describe a consistent use for several
- others that were used more arbitrarily.
-
- This makes it easier for new committers to find out the kinds of things
- we want to acknowledge, makes it easier to perform statistical analysis
- on commits, and opens the possibility of performing lint checks on
- descriptions before submission.
-
- Reviewed-by: Daniel Stenberg
- Reviewed-by: Jay Satiro
-
- Closes #10478
-
-Stefan Eissing (13 Feb 2023)
-
-- openssl: test and fix for forward proxy handling (non-tunneling).
-
- - adding pytest test_10 cases for proxy httpd setup tests
- - fixing openssl bug in https: proxy hostname verification that
- used the hostname of the request and not the proxy name.
-
- Closes #10498
-
-Daniel Stenberg (13 Feb 2023)
-
-- cmdline-opts/Makefile: on error, do not leave a partial
-
- And support 'make V=1' to show the full command line
-
- Closes #10497
-
-- curl.1: make help, version and manual sections "custom"
-
- Instead of using "multi: boolean", as these are slightly special as in
- they do are not enable/disable ones.
-
- Fixes #10490
- Reported-by: u20221022 on github
- Closes #10497
-
-Stefan Eissing (13 Feb 2023)
-
-- tests: add tests for HTTP/2 and HTTP/3 to verify the header API
-
- Test 2403 and 2503 check "header_json" output and therefore use of
- header-api
-
- Closes #10495
-
-Philip Heiduck (13 Feb 2023)
-
-- CI: update wolfssl / wolfssh to 5.5.4 / 1.4.12
-
- Closes #10493
-
-Daniel Stenberg (13 Feb 2023)
-
-- KNOW_BUGS: cleanups with some changed to TODOs
-
- - remove "Excessive HTTP/2 packets with TCP_NODELAY"
-
- This is not a bug. Rather room for improvement.
-
- I believe these have been fixed:
-
- - 17.4 Connection failures with parallel HTTP/2
- - 17.5 HTTP/2 connections through HTTPS proxy frequently stall
-
- - remove "FTPS needs session reuse"
-
- That is still true, but curl should also do session reuse now.
-
- - remove "ASCII FTP"
-
- It is documented behavior, and not single user has asked for extended
- functionality here the last decade or so.
-
- - remove "Passive transfer tries only one IP address"
-
- add as a TODO
-
- - remove "DoH leaks memory after followlocation"
-
- With a recipe on how to reproduce, this is pointless to keep around
-
- - remove "DoH does not inherit all transfer options"
-
- add it as a TODO
-
- Closes #10487
-
-Tatsuhiro Tsujikawa (13 Feb 2023)
-
-- GHA: bump ngtcp2 workflow dependencies
-
- Closes #10494
-
-Patrick Monnerat (13 Feb 2023)
-
-- content_encoding: do not reset stage counter for each header
-
- Test 418 verifies
-
- Closes #10492
-
-Daniel Stenberg (13 Feb 2023)
-
-- RELEASE-NOTES: synced
-
-Jay Satiro (13 Feb 2023)
-
-- multi: stop sending empty HTTP/3 UDP datagrams on Windows
-
- - Limit the 0-sized send procedure that is used to reset a SOCKET's
- FD_WRITE to TCP sockets only.
-
- Prior to this change the reset was used on UDP sockets as well, but
- unlike TCP sockets a 0-sized send actually sends out a datagram.
-
- Assisted-by: Marc Hörsken
-
- Ref: https://github.com/curl/curl/pull/9203
-
- Fixes https://github.com/curl/curl/issues/9086
- Closes https://github.com/curl/curl/pull/10430
-
-Viktor Szakats (12 Feb 2023)
-
-- h3: silence compiler warnings
-
- Reviewed-by: Daniel Stenberg
- Fixes #10485
- Closes #10486
-
-Daniel Stenberg (12 Feb 2023)
-
-- smb: return error on upload without size
-
- The protocol needs to know the size ahead of time, this is now a known
- restriction and not a bug.
-
- Also output a clearer error if the URL path does not contain proper
- share.
-
- Ref: #7896
- Closes #10484
-
-Viktor Szakats (12 Feb 2023)
-
-- windows: always use curl's basename() implementation
-
- The `basename()` [1][2] implementation provided by mingw-w64 [3] makes
- assumptions about input encoding and may break with non-ASCII strings.
-
- `basename()` was auto-detected with CMake, autotools and since
- 68fa9bf3f5d7b4fcbb57619f70cb4aabb79a51f6 (2022-10-13), also in
- `Makefile.mk` after syncing its behaviour with the mainline build
- methods. A similar patch for curl-for-win broke official Windows
- builds earlier, in release 7.83.1_4 (2022-06-15).
-
- This patch forces all Windows builds to use curl's internal
- `basename()` implementation to avoid such problems.
-
- [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/basename.html
- [2]: https://www.man7.org/linux/man-pages/man3/basename.3.html
- [3]: https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-c
- rt/misc/basename.c
-
- Reported-by: UnicornZhang on Github
- Assisted-by: Cherish98 on Github
- Reviewed-by: Daniel Stenberg
-
- Fixes #10261
- Closes #10475
-
-Philip Heiduck (12 Feb 2023)
-
-- Linux CI: Bump rustls-ffi to v0.9.1
-
- Closes #10476
-
-Daniel Stenberg (12 Feb 2023)
-
-- libtest: build lib2305 with multibyte as well
-
- Fixes a build regression.
-
- Follow-up to 5a9a04d5567
- Reported-by: Viktor Szakats
- Ref: https://github.com/curl/curl/pull/10475#issuecomment-1426831800
-
- Closes #10477
-
-Dmitry Atamanov (12 Feb 2023)
-
-- cmake: fix dev warning due to mismatched arg
-
- The package name passed to find_package_handle_standard_args (BROTLI)
- does not match the name of the calling package (Brotli). This can lead
- to problems in calling code that expects find_package result variables
- (e.g., _FOUND) to follow a certain pattern.
-
- Closes https://github.com/curl/curl/pull/10471
-
-James Keast (11 Feb 2023)
-
-- setopt: Address undefined behaviour by checking for null
-
- This addresses undefined behaviour found using clang's UBsan:
-
- curl/lib/setopt.c:177:14: runtime error: applying non-zero offset 1 to null p
- ointer
- SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior curl/lib/setopt.c:177
- :14 in
-
- Closes #10472
-
-Jacob Hoffman-Andrews (11 Feb 2023)
-
-- rustls: improve error messages
-
- Changes numeric error codes into verbose error codes in two places.
- Adds a prefix indicating that the error came from rustls, and in some
- places which function it came from.
-
- Adds special handling for RUSTLS_RESULT_UNEXPECTED_EOF, since the
- default message of "Unexpected EOF" is insufficiently explanatory.
-
- Closes #10463
-
-Daniel Stenberg (11 Feb 2023)
-
-- openssl: remove dead code
-
- Follow-up to e8b00fcd6a
-
- Due to the new 'if(!nonblocking)' check on the block a level above,
- there is no need to check for it again within the same conditional.
-
- Detected by Coverity
-
- Closes #10473
-
-- ngtcp2: replace removed define and stop using removed function
-
- They were removed upstream.
-
- Reported-by: Karthikdasari0423 on github
- Fixes #10469
- Closes #10474
-
-- scripts/delta: show percent of number of files changed since last tag
-
-- RELEASE-NOTES: synced
-
-Stefan Eissing (10 Feb 2023)
-
-- pytest: add a test case for PUSH related things.
-
- - checking that "103 Early Hints" are visible in curl's header dump file
-
- Closes #10452
-
-Gregory Panakkal (10 Feb 2023)
-
-- WEBSOCKET.md: typo
-
- Fixing missing slash for ws protocol scheme
-
- Closes #10464
-
-Stefan Eissing (10 Feb 2023)
-
-- vquic: stabilization and improvements
-
- vquic stabilization
- - udp send code shared between ngtcp2 and quiche
- - quiche handling of data and events improved
-
- ngtcp2 and pytest improvements
- - fixes handling of "drain" situations, discovered in scorecard
- tests with the Caddy server.
- - improvements in handling transfers that have already data or
- are already closed to make an early return on recv
-
- pytest
- - adding caddy tests when available
-
- scorecard improvemnts.
- - using correct caddy port
- - allowing tests for only httpd or caddy
-
- Closes #10451
-
-Philip Heiduck (10 Feb 2023)
-
-- Linux CI: update some dependecies to latest tag
-
- Closes #10458
-
-Daniel Stenberg (10 Feb 2023)
-
-- test2305: send 3 frames, 4097 bytes each, as one message
-
- Receive them using a 256 bytes buffer in a loop.
-
-- ws: fix recv of larger frames
-
- + remove 'oleft' from the struct
- + deal with "overflow data" in a separate dynbuf
-
- Reported-by: Mike Duglas
- Fixes #10438
- Closes #10447
-
-- curl/websockets.h: extend the websocket frame struct
-
-- sws: fix typo, indentation add more ws logging
-
-- test2304: remove stdout verification
-
- This cripples the test somewhat but the check was bad since depending on
- timing it could exit before the output was done, making the test flaky.
-
-Dan Fandrich (9 Feb 2023)
-
-- CI: Add more labeler match patterns
-
-- CI: Retry failed downloads to reduce spurious failures
-
- A temporary error with a remote server shouldn't cause a CI run to fail.
- Also, put a cap on the time to download to fail faster on a misbehaving
- server or connection and use HTTP compression where possible to reduce
- download times.
-
-Daniel Stenberg (9 Feb 2023)
-
-- no-clobber.d: only use long form options in man page text
-
- ... since they are expanded and the short-form gets mentioned
- automatically so if the short form is mentioned as well, it gets
- repeated.
-
- Fixes #10461
- Closes #10462
- Reported-by: Dan Fandrich
-
-- GHA: enable websockets in the torture job
-
- Closes #10448
-
-- header.d: add a header file example
-
- Closes #10455
-
-Stefan Eissing (9 Feb 2023)
-
-- HTTP/[23]: continue upload when state.drain is set
-
- - as reported in #10433, HTTP/2 uploads may stall when a response is
- received before the upload is done. This happens when the
- data->state.drain is set for such a transfer, as the special handling
- in transfer.c from then on only cared about downloads.
- - add continuation of uploads, if applicable, in this case.
- - add pytest case test_07_12_upload_seq_large to reproduce this scenario
- (although, current nghttp2 implementation is using drain less often)
-
- Reported-by: Lucas Pardue
-
- Fixes #10433
- Closes #10443
-
-- http2: minor buffer and error path fixes
-
- - use memory buffer in full available size
- - fail receive of reset/errored streams early
-
- pytest:
- - make test_05 error cases more reliable
-
- Closes #10444
-
-Federico Pellegrin (9 Feb 2023)
-
-- openldap: fix missing sasl symbols at build in specific configs
-
- If curl is built with openldap support (USE_OPENLDAP=1) but does not
- have also some other protocol (IMAP/SMTP/POP3) enabled that brings
- in Curl_sasl_* functions, then the build will fail with undefined
- references to various symbols:
-
- ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_decode_mech'
- ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_parse_url_auth
- _option'
- ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_cleanup'
- ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_can_authentica
- te'
- ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_continue'
- ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_start'
- ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_init'
-
- This was tracked down to these functions bein used in openldap.c but
- defined in curl_sasl.c and then forward in two vauth/ files to have
- a guard against a set of #define configurations that was now extended
- to cover also this case.
-
- Example configuration targeted that could reproduce the problem:
-
- curl 7.87.1-DEV () libcurl/7.87.1-DEV .... OpenLDAP/2.6.3
- Protocols: file ftp ftps http https ldap ldaps
-
- Closes #10445
-
-Daniel Stenberg (9 Feb 2023)
-
-- ws: use %Ou for outputting curl_off_t with info()
-
- Reported-by: Mike Duglas
- Fixes #10439
- Closes #10441
-
-Jay Satiro (9 Feb 2023)
-
-- curl_setup: Disable by default recv-before-send in Windows
-
- Prior to this change a workaround for Windows to recv before every send
- was enabled by default. The way it works is a recv is called before
- every send and saves the received data, in case send fails because in
- Windows apparently that can wipe out the socket's internal received
- data buffer.
-
- This feature has led to several bugs because the way libcurl operates
- it waits on a socket to read or to write, and may not at all times
- check for buffered receive data.
-
- Two recent significant bugs this workaround caused:
- - Broken Schannel TLS 1.3 connections (#9431)
- - HTTP/2 arbitrary hangs (#10253)
-
- The actual code remains though it is disabled by default. Though future
- changes to connection filter buffering could improve the situation IMO
- it's just not tenable to manage this workaround.
-
- Ref: https://github.com/curl/curl/issues/657
- Ref: https://github.com/curl/curl/pull/668
- Ref: https://github.com/curl/curl/pull/720
-
- Ref: https://github.com/curl/curl/issues/9431
- Ref: https://github.com/curl/curl/issues/10253
-
- Closes https://github.com/curl/curl/pull/10409
-
-Stefan Eissing (8 Feb 2023)
-
-- http2: aggregate small SETTINGS/PRIO/WIN_UPDATE frames
-
- add a small buffer to nghttp2 session sending in order to aggregate
- small SETTINGS/PRIO/WIN_UPDATE frames that nghttp2 "writes" to the
- callback individually.
-
- Ref: #10389
- Closes #10432
-
-- openssl: store the CA after first send (ClientHello)
-
- move Curl_ssl_setup_x509_store() call after the first send (ClientHello)
- this gives time to parse CA anchors while waiting on the server reply
-
- Ref: #10389
- Closes #10432
-
-Daniel Stenberg (8 Feb 2023)
-
-- RELEASE-NOTES: synced
-
-Anthony Hu (8 Feb 2023)
-
-- wolfssl: remove deprecated post-quantum algorithms
-
- Closes #10440
-
-John Bampton (8 Feb 2023)
-
-- misc: fix spelling
-
- Closes #10437
-
-Daniel Stenberg (7 Feb 2023)
-
-- man pages: call the custom user pointer 'clientp' consistently
-
- The variable had a few different names. Now try to use 'clientp'
- consistently for all man pages using a custom pointer set by the
- application.
-
- Reported-by: Gerrit Renker
-
- Fixes #10434
- Closes #10435
-
-- vtls: infof using %.*s needs to provide the length as int
-
- Fixes a Coverity warning.
-
- Closes #10436
-
-Stefan Eissing (7 Feb 2023)
-
-- vrls: addressing issues reported by coverity
-
- I believe the code was secure before this, but limiting the accepted
- name length to what is used in the structures should help Coverity's
- analysis.
-
- Closes #10431
-
-Daniel Stenberg (7 Feb 2023)
-
-- tool_operate: move the 'updated' variable
-
- This was already done by Dan Fandrich in the previous PR but somehow I
- lost that fixup.
-
- Follow-up to 349c5391f2121e
-
-Dan Fandrich (7 Feb 2023)
-
-- tool_operate: Fix error codes during DOS filename sanitize
-
- It would return CURLE_URL_MALFORMAT in an OOM condition.
-
- Closes #10414
-
-- tool_operate: Fix error codes on bad URL & OOM
-
- curl would erroneously report CURLE_OUT_OF_MEMORY in some cases instead
- of CURLE_URL_MALFORMAT. In other cases, it would erroneously return
- CURLE_URL_MALFORMAT instead of CURLE_OUT_OF_MEMORY. Add a test case to
- test the former condition.
-
- Fixes #10130
- Closes #10414
-
-Daniel Stenberg (6 Feb 2023)
-
-- setopt: use >, not >=, when checking if uarg is larger than uint-max
-
- Closes #10421
-
-- vtls: fix failf() format argument type for %.*s handling
-
- Reported by Coverity
-
- Closes #10422
-
-- openssl: fix "Improper use of negative value"
-
- By getting the socket first and returning error in case of bad socket.
-
- Detected by Coverity.
-
- Closes #10423
-
-Dan Fandrich (6 Feb 2023)
-
-- packages: Remove Android.mk from makefile
-
- This was missed in commit #44141512
-
- Ref: #10418
-
-Daniel Stenberg (6 Feb 2023)
-
-- curl_ws_send.3: clarify how to send multi-frame messages
-
-Mike Duglas (6 Feb 2023)
-
-- ws: fix multiframe send handling
-
- Fixes #10413
- Closes #10420
-
-Daniel Stenberg (6 Feb 2023)
-
-- unit2600: make sure numerical curl_easy_setopt sets long
-
- Follow-up to 671158242db3203
-
- Reported-by: Marcel Raad
- Fixes #10410
- Closes #10419
-
-Andy Alt (6 Feb 2023)
-
-- GHA: move Slackware test into matrix
-
- Closes #10412
-
-Pronyushkin Petr (6 Feb 2023)
-
-- urlapi: fix part of conditional expression is always true: qlen
-
- Closes #10408
-
-- url: fix part of conditional expression is always true
-
- Closes #10407
-
-Daniel Stenberg (6 Feb 2023)
-
-- RELEASE-NOTES: synced
-
-Philip Heiduck (6 Feb 2023)
-
-- GHA/macos.yml: bump to gcc-12
-
- Closes #10415
-
-Daniel Stenberg (6 Feb 2023)
-
-- packages: remove Android, update README
-
- - Nobody builds curl for Android using this anymore
- - Refreshed the README and converted to markdown
-
- Reported-by: John Porter
- Fixes #10416
- Closes #10418
-
-Kvarec Lezki (5 Feb 2023)
-
-- fopen: remove unnecessary assignment
-
- [CWE-1164] V1048: The '* tempname' variable was assigned the same value.
-
- Ref: https://pvs-studio.com/en/docs/warnings/v1048/
-
- Closes https://github.com/curl/curl/pull/10398
-
-Gisle Vanem (5 Feb 2023)
-
-- libtest: add a sleep macro for Windows
-
- .. because sleep() is used in some libtests.
-
- Closes https://github.com/curl/curl/pull/10295
-
-Kvarec Lezki (3 Feb 2023)
-
-- http_aws_sigv4: remove typecasts from HMAC_SHA256 macro
-
- V220: Suspicious sequence of types castings: memsize -> 32-bit integer -> mem
- size.
-
- https://pvs-studio.com/en/docs/warnings/v220/
-
- Closes #10400
-
-Daniel Stenberg (3 Feb 2023)
-
-- mailmap: Thomas1664 on github
-
-Thomas1664 on github (3 Feb 2023)
-
-- CURLOPT_WRITEFUNCTION.3: fix memory leak in example
-
- Closes #10390
-
-Kvarec Lezki (3 Feb 2023)
-
-- doh: ifdef IPv6 code
-
- For disabled IPv6 a condition (conn->ip_version != CURL_IPRESOLVE_V4) is
- always false. https://pvs-studio.com/en/docs/warnings/v560/
-
- Closes #10397
-
-Daniel Stenberg (3 Feb 2023)
-
-- urlapi: remove pathlen assignment
-
- "Value stored to 'pathlen' is never read"
-
- Follow-up to 804d5293f89
-
- Reported-by: Kvarec Lezki
-
- Closes #10405
-
-Kvarec Lezki (3 Feb 2023)
-
-- http: fix "part of conditional expression is always false"
-
- [CWE-570] V560: A part of conditional expression is always false: conn->bits.
- authneg.
- [CWE-570] V560: A part of conditional expression is always false: conn->handl
- er->protocol & (0 | 0).
-
- https://pvs-studio.com/en/docs/warnings/v560/
-
- Closes #10399
-
-Daniel Stenberg (2 Feb 2023)
-
-- urlapi: skip the extra dedotdot alloc if no dot in path
-
- Saves an allocation for many/most URLs.
-
- Updates test 1395 accordingly
-
- Closes #10403
-
-Stefan Eissing (2 Feb 2023)
-
-- connections: introduce http/3 happy eyeballs
-
- New cfilter HTTP-CONNECT for h3/h2/http1.1 eyeballing.
- - filter is installed when `--http3` in the tool is used (or
- the equivalent CURLOPT_ done in the library)
- - starts a QUIC/HTTP/3 connect right away. Should that not
- succeed after 100ms (subject to change), a parallel attempt
- is started for HTTP/2 and HTTP/1.1 via TCP
- - both attempts are subject to IPv6/IPv4 eyeballing, same
- as happens for other connections
- - tie timeout to the ip-version HAPPY_EYEBALLS_TIMEOUT
- - use a `soft` timeout at half the value. When the soft timeout
- expires, the HTTPS-CONNECT filter checks if the QUIC filter
- has received any data from the server. If not, it will start
- the HTTP/2 attempt.
-
- HTTP/3(ngtcp2) improvements.
- - setting call_data in all cfilter calls similar to http/2 and vtls filters
- for use in callback where no stream data is available.
- - returning CURLE_PARTIAL_FILE for prematurely terminated transfers
- - enabling pytest test_05 for h3
- - shifting functionality to "connect" UDP sockets from ngtcp2
- implementation into the udp socket cfilter. Because unconnected
- UDP sockets are weird. For example they error when adding to a
- pollset.
-
- HTTP/3(quiche) improvements.
- - fixed upload bug in quiche implementation, now passes 251 and pytest
- - error codes on stream RESET
- - improved debug logs
- - handling of DRAIN during connect
- - limiting pending event queue
-
- HTTP/2 cfilter improvements.
- - use LOG_CF macros for dynamic logging in debug build
- - fix CURLcode on RST streams to be CURLE_PARTIAL_FILE
- - enable pytest test_05 for h2
- - fix upload pytests and improve parallel transfer performance.
-
- GOAWAY handling for ngtcp2/quiche
- - during connect, when the remote server refuses to accept new connections
- and closes immediately (so the local conn goes into DRAIN phase), the
- connection is torn down and a another attempt is made after a short grace
- period.
- This is the behaviour observed with nghttpx when we tell it to shut
- down gracefully. Tested in pytest test_03_02.
-
- TLS improvements
- - ALPN selection for SSL/SSL-PROXY filters in one vtls set of functions, repl
- aces
- copy of logic in all tls backends.
- - standardized the infof logging of offered ALPNs
- - ALPN negotiated: have common function for all backends that sets alpn propr
- ty
- and connection related things based on the negotiated protocol (or lack the
- reof).
-
- - new tests/tests-httpd/scorecard.py for testing h3/h2 protocol implementatio
- n.
- Invoke:
- python3 tests/tests-httpd/scorecard.py --help
- for usage.
-
- Improvements on gathering connect statistics and socket access.
- - new CF_CTRL_CONN_REPORT_STATS cfilter control for having cfilters
- report connection statistics. This is triggered when the connection
- has completely connected.
- - new void Curl_pgrsTimeWas(..) method to report a timer update with
- a timestamp of when it happend. This allows for updating timers
- "later", e.g. a connect statistic after full connectivity has been
- reached.
- - in case of HTTP eyeballing, the previous changes will update
- statistics only from the filter chain that "won" the eyeballing.
- - new cfilter query CF_QUERY_SOCKET for retrieving the socket used
- by a filter chain.
- Added methods Curl_conn_cf_get_socket() and Curl_conn_get_socket()
- for convenient use of this query.
- - Change VTLS backend to query their sub-filters for the socket when
- checks during the handshake are made.
-
- HTTP/3 documentation on how https eyeballing works.
-
- TLS improvements
- - ALPN selection for SSL/SSL-PROXY filters in one vtls set of functions, repl
- aces
- copy of logic in all tls backends.
- - standardized the infof logging of offered ALPNs
- - ALPN negotiated: have common function for all backends that sets alpn propr
- ty
- and connection related things based on the negotiated protocol (or lack the
- reof).
-
- Scorecard with Caddy.
- - configure can be run with `--with-test-caddy=path` to specify which caddy t
- o use for testing
- - tests/tests-httpd/scorecard.py now measures download speeds with caddy
-
- pytest improvements
- - adding Makfile to clean gen dir
- - adding nghttpx rundir creation on start
- - checking httpd version 2.4.55 for test_05 cases where it is needed. Skippin
- g with message if too old.
- - catch exception when checking for caddy existance on system.
-
- Closes #10349
-
-Daniel Stenberg (2 Feb 2023)
-
-- CODEOWNERS: remove the peeps mentioned as CI owners
-
- These owners do not have the bandwidth/energy to do the reviews which
- makes PRs stall and this ownership claim flawed. We can bring people
- back when the situation is different.
-
- Follow-up to c04c78ac87c4d46737934345a
-
- Closes #10386
-
-Martin D'Aloia (2 Feb 2023)
-
-- write-out.d: add 'since version' to %{header_json} documentation
-
- The documentation of `%{header_json}` missed to mention since which
- version this variable for `--write-out` is present.
-
- Based on commit https://github.com/curl/curl/commit/4133a69f2daa476bb
- we can determine from the tags were this commit is present that the
- first version to include it was `7.83.0`.
- This could be also checked with:
- `git tag --contains 4133a69f2daa476bb6d902687f1dd6660ea9c3c5`
-
- Closes #10395
-
-Daniel Stenberg (1 Feb 2023)
-
-- urlapi: avoid Curl_dyn_addf() for hex outputs
-
- Inspired by the recent fixes to escape.c, we should avoid calling
- Curl_dyn_addf() in loops, perhaps in particular when adding something so
- simple as %HH codes - for performance reasons. This change makes the
- same thing for the URL parser's two URL-encoding loops.
-
- Closes #10384
-
-- urlapi: skip path checks if path is just "/"
-
- As a miniscule optimization, treat a path of the length 1 as the same as
- non-existing, as it can only be a single leading slash, and that's what
- we do for no paths as well.
-
- Closes #10385
-
-Philip Heiduck (1 Feb 2023)
-
-- GHA/macos: use Xcode_14.0.1 for cmake builds
-
- Fixes #10356
- Closes #10381
-
-Viktor Szakats (1 Feb 2023)
-
-- tls: fixes for wolfssl + openssl combo builds
-
- 1. Add `USE_WOLFSSL` to the TLS backend priority list in
- `lib/curl_ntlm_core.c`.
-
- 2. Fix `lib/curl_ntlm_core.h` to respect TLS backend priority, bringing
- it in sync with the above list and `lib/curl_ntlm_core.c` itself.
-
- Reported-by: Mark Roszko
- Ref: https://github.com/curl/curl/issues/10321
-
- 3. Allow enabling both wolfSSL and OpenSSL at the same time in
- `lib/Makefile.mk` bringing this in line with cmake/autotools builds.
- Update logic to select the crypto-specific lib for `ngtcp2`, which
- supports a single TLS backend at the same time.
-
- Closes #10322
-
-Daniel Stenberg (1 Feb 2023)
-
-- RELEASE-NOTES: synced
-
-- docs/INSTALL: document how to use multiple TLS backends
-
- And document how OpenSSL forks and wolfSSL cannot be used at the same
- time.
-
- Reported-by: Mark Roszko
- Fixes #10321
- Closes #10382
-
-Kvarec Lezki (1 Feb 2023)
-
-- cookies: fp is always not NULL
-
- Closes #10383
-
-Daniel Stenberg (31 Jan 2023)
-
-- escape: use table lookup when adding %-codes to output
-
- On my dev host, this code runs 7.8 times faster.
-
- Closes #10377
-
-- unit2600: avoid error: ‘TEST_CASES’ defined but not used
-
- Follow-up to d55de24dce9d51
-
- Closes #10379
-
-- escape: hex decode with a lookup-table
-
- Makes the decoding 2.8 times faster in my tests.
-
- Closes #10376
-
-- cf-socket: fix build error wo TCP_FASTOPEN_CONNECT
-
- Follow-up to 5651a36d1a
-
- Closes #10378
-
- Reviewed-by: Stefan Eissing
-
-Stefan Eissing (31 Jan 2023)
-
-- CI: add pytest github workflow to CI test/tests-httpd on a HTTP/3 setup
-
- Closes #10317
-
-- connect: fix strategy testing for attempts, timeouts and happy-eyeball
-
- - add test2600 as a unit test that triggers various connect conditions
- and monitors behaviour, available in a debug build only.
-
- - this exposed edge cases in connect.c that have been fixed
-
- Closes #10312
-
-- cf-socket: improvements in socket I/O handling
-
- - Curl_write_plain/Curl_read_plain have been eliminated. Last code use
- now uses Curl_conn_send/recv so that requests use conn->send/revc
- callbacks which defaults to cfilters use.
- - Curl_recv_plain/Curl_send_plain have been internalized in cf-socket.c.
- - USE_RECV_BEFORE_SEND_WORKAROUND (active on Windows) has been moved
- into cf-socket.c. The pre_recv buffer is held at the socket filter
- context. `postponed_data` structures have been removed from
- `connectdata`.
- - the hanger in HTTP/2 request handling was a result of read buffering
- on all sends and the multi handling is not prepared for this. The
- following happens:
-
- - multi preforms on a HTTP/2 easy handle
- - h2 reads and processes data
- - this leads to a send of h2 data
- - which receives and buffers before the send
- - h2 returns
- - multi selects on the socket, but no data arrives (its in the buffer alre
- ady)
- the workaround now receives data in a loop as long as there is something i
- n
- the buffer. The real fix would be for multi to change, so that `data_pendi
- ng`
- is evaluated before deciding to wait on the socket.
-
- io_buffer, optional, in cf-socket.c, http/2 sets state.drain if lower
- filter have pending data.
-
- This io_buffer is only available/used when the
- -DUSE_RECV_BEFORE_SEND_WORKAROUND is active, e.g. on Windows
- configurations. It also maintains the original checks on protocol
- handler being HTTP and conn->send/recv not being replaced.
-
- The HTTP/2 (nghttp2) cfilter now sets data->state.drain when it finds
- out that the "lower" filter chain has still pending data at the end of
- its IO operation. This prevents the processing from becoming stalled.
-
- Closes #10280
-
-Daniel Stenberg (31 Jan 2023)
-
-- openssl: only use CA_BLOB if verifying peer
-
- Reported-by: Paul Groke
- Bug: https://curl.se/mail/lib-2023-01/0070.html
- Fixes #10351
- Closes #10359
-
-Thomas1664 on github (31 Jan 2023)
-
-- curl_free.3: fix return type of `curl_free`
-
- Fixes #10373
- Closes #10374
-
-Daniel Stenberg (30 Jan 2023)
-
-- zuul: stop using this CI service
-
- The important jobs have already transitioned. The remaining ones we can
- skip for now.
-
- Closes #10368
-
-- copyright: remove "m4/ax_compile_check_sizeof.m4" from skips
-
- and report if skipped files do not exist.
-
- Follow-up to 9e11c2791fb960758 which removed the file.
-
- Closes #10369
-
-- ws: unstick connect-only shutdown
-
- As this mode uses blocking sockets, it must set them back to
- non-blocking in disconnect to avoid the risk of getting stuck.
-
- Closes #10366
-
-- ws: remove bad assert
-
- Reported-by: Stanley Wucw
- Fixes #10347
- Closes #10366
-
-- openssl: adapt to boringssl's error code type
-
- BoringSSL uses uint32_t, OpenSSL uses 'unsigned 'long'
-
- Closes #10360
-
-- tool_operate: repair --rate
-
- Regression from a55256cfb242 (7.87.0)
- Reported-by: highmtworks on github
- Fixes #10357
- Closes #10358
-
-- dict: URL decode the entire path always
-
- Reported-by: dekerser on github
- Fixes #10298
- Closes #10354
-
-Stefan Eissing (29 Jan 2023)
-
-- vtls: do not null-check when we already assume cf-ctx exists
-
- Fixes #10361
- Closes #10362
-
-Daniel Stenberg (29 Jan 2023)
-
-- RELEASE-NOTES: synced
-
-- CURLOPT_READFUNCTION.3: the callback 'size' arg is always 1
-
- Reported-by: Brian Green
- Fixes #10328
- Closes #10355
-
-- copyright.pl: cease doing year verifications
-
- As we have (mostly) removed the copyright year ranges.
-
- Reported-by: Ryan Schmidt
- Fixes #10345
- Closes #10352
-
-Dan Fandrich (28 Jan 2023)
-
-- CI: Work around a labeler bug that removes labels
-
-Jay Satiro (26 Jan 2023)
-
-- write-out.d: clarify Windows % symbol escaping
-
- - Clarify that in Windows batch files the % must be escaped as %%, and
- at the command prompt it cannot be escaped which could lead to
- incorrect expansion.
-
- Prior to this change the doc implied % must be escaped as %% in win32
- always.
-
- ---
-
- Examples showing how a write-out argument is received by curl:
-
- If curl --write-out "%{http_code}" is executed in a batch file:
- {http_code}
-
- If curl --write-out "%%{http_code}" is executed in a batch file:
- %{http_code}
-
- If curl --write-out "%{http_code}" is executed from the command prompt:
- %{http_code}
-
- If curl --write-out "%%{http_code}" is executed from the command prompt:
- %%{http_code}
-
- At the command prompt something like "%{speed_download}%{http_code}"
- would first be parsed by the command interpreter as %{speed_download}%
- and would be expanded as environment variable {speed_download} if it
- existed, though that's highly unlikely since Windows environment names
- don't use braces.
-
- ---
-
- Reported-by: Muhammad Hussein Ammari
-
- Ref: https://github.com/bagder/everything-curl/pull/279
-
- Fixes https://github.com/curl/curl/issues/10323
- Closes https://github.com/curl/curl/pull/10337
-
-Ryan Schmidt (26 Jan 2023)
-
-- connect: Fix build when not ENABLE_IPV6
-
- Check for ENABLE_IPV6 before accessing AF_INET6. Fixes build failure
- introduced in 1c5d8ac.
-
- Closes https://github.com/curl/curl/pull/10344
-
-- cf-socket: Fix build when not HAVE_GETPEERNAME
-
- Remove remaining references to conn and sockfd, which were removed from
- the function signature when conninfo_remote was renamed to
- conn_set_primary_ip in 6a8d7ef.
-
- Closes https://github.com/curl/curl/pull/10343
-
-Stefan Eissing (26 Jan 2023)
-
-- vtls: Manage current easy handle in nested cfilter calls
-
- The previous implementation cleared `data` so the outer invocation lost
- its data, which could lead to a crash.
-
- Bug: https://github.com/curl/curl/issues/10336
- Reported-by: Fujii Hironori
-
- Closes https://github.com/curl/curl/pull/10340
-
-Dan Fandrich (25 Jan 2023)
-
-- CI: Add even more paths to the labeler config (#10326)
-
-- scripts: Fix Appveyor job detection in cijobs.pl
-
- The reorganization in #9769 broke the script. This should probably be
- rewritten to use a YAML parser for better upward compatibility.
-
-- CI: Add a few more paths to the labeler config (#10326)
-
-- CI: Switch the labeler event to pull_request_target
-
- Otherwise, the action won't work on PRs from forked repositories
- (#10326).
-
-Viktor Szakats (25 Jan 2023)
-
-- cmake: delete redundant macro definition `SECURITY_WIN32`
-
- Stop explicitly defining `SECURITY_WIN32` in CMake builds.
-
- No other build systems define this macro, because it's unconditionally
- defined in `lib/curl_sspi.h` already. This is the only curl source using
- the `sspi.h` and `security.h` Win32 headers, and no other Win32 headers
- need this macro.
-
- Reviewed-by: Jay Satiro
- Closes #10341
-
-Fredrik (24 Jan 2023)
-
-- winbuild: document that arm64 is supported
-
- Building an arm64 version works flawlessly with the VS arm64 toolset.
-
- Closes https://github.com/curl/curl/pull/10332
-
-Cherish98 (24 Jan 2023)
-
-- openssl: don't log raw record headers
-
- - Skip content type SSL3_RT_HEADER in verbose TLS output.
-
- This commit prevents bogus and misleading verbose TLS header messages as
- discussed in #10299.
-
- Assisted-by: Peter Wu
-
- Closes https://github.com/curl/curl/pull/10299
-
-Marc Aldorasi (24 Jan 2023)
-
-- cmake: use list APPEND syntax for CMAKE_REQUIRED_DEFINITIONS
-
- - Use list() instead of set() for CMAKE_REQUIRED_DEFINITIONS list since
- the former is clearer.
-
- Closes https://github.com/curl/curl/pull/10272
-
-Dan Fandrich (23 Jan 2023)
-
-- CI: Add a workflow to automatically label pull requests
-
- The labeler language is quite restrictive right now so labels are added
- quite conservatively, meaning that many PRs won't get labels when it's
- "obvious" they should. It will still save some manual work on those
- that it can label.
-
-Jay Satiro (21 Jan 2023)
-
-- system.h: assume OS400 is always built with ILEC compiler
-
- Prior to this change the OS400 types were only defined when __ILEC400__.
- That symbol is only defined by IBM's C compiler and not their C++
- compiler, which led to missing types when users on OS400 would compile a
- C++ application that included curl.
-
- The IBM C and C++ compilers are the only native compilers on the
- platform.
-
- Assisted-by: Jon Rumsey
- Reported-by: John Sherrill
-
- Fixes https://github.com/curl/curl/issues/10305
- Closes https://github.com/curl/curl/pull/10329
-
-xgladius (20 Jan 2023)
-
-- cmake: Remove deprecated symbols check
-
- curl stopped use of CMAKE_USE_ as a prefix for its own build symbols in
- 2021 and added a check, meant to last 1 year, to fatally error on those
- symbols. This commit removes that check.
-
- Closes https://github.com/curl/curl/pull/10314
-
-Dan Fandrich (20 Jan 2023)
-
-- docs: POSTFIELDSIZE must be set to -1 with read function
-
- Reported-by: RanBarLavie on github
-
- Closes #10313
-
-Stefan Eissing (20 Jan 2023)
-
-- vtls: fix hostname handling in filters
-
- - Copy the hostname and dispname to ssl_connect_data.
-
- Use a copy instead of referencing the `connectdata` instance since this
- may get free'ed on connection reuse.
-
- Reported-by: Stefan Talpalaru
- Reported-by: sergio-nsk@users.noreply.github.com
-
- Fixes https://github.com/curl/curl/issues/10273
- Fixes https://github.com/curl/curl/issues/10309
-
- Closes https://github.com/curl/curl/pull/10310
-
-Sergey Bronnikov (17 Jan 2023)
-
-- lib: fix typos
-
- Closes https://github.com/curl/curl/pull/10307
-
-- curl_version_info.3: fix typo
-
- Closes https://github.com/curl/curl/pull/10306
-
-Jay Satiro (17 Jan 2023)
-
-- openssl: Don't ignore CA paths when using Windows CA store (redux)
-
- .. and remove 'experimental' designation from CURLSSLOPT_NATIVE_CA.
-
- This commit restores the behavior of CURLSSLOPT_NATIVE_CA so that it
- does not override CURLOPT_CAINFO / CURLOPT_CAPATH, or the hardcoded
- default locations. Instead the native Windows CA store can be used at
- the same time.
-
- ---
-
- This behavior was originally added over two years ago in abbc5d60
- (#5585) but then 83393b1a (#7892) broke it over a year ago, I assume
- inadvertently.
-
- The CURLSSLOPT_NATIVE_CA feature was marked experimental and likely
- rarely used.
-
- Ref: https://github.com/curl/curl/pull/5585
- Ref: https://github.com/curl/curl/pull/7892
- Ref: https://curl.se/mail/lib-2023-01/0019.html
-
- Closes https://github.com/curl/curl/pull/10244
-
-Daniel Stenberg (13 Jan 2023)
-
-- RELEASE-NOTES: synced
-
-- ws: fix autoping handling
-
- Reported-by: Alexey Savchuk
- Fixes #10289
- Closes #10294
-
-- curl_log: avoid printf() format checking with mingw
-
- Since it does not seem to like %zu and more
-
- Follow-up to db91dbbf2
-
- Fixes #10291
- Closes #10292
-
-- tool_getparam: fix compiler warning when !HAVE_WRITABLE_ARGV
-
- Follow-up to 2ed0e1f70ee176edf3d2
-
- Closes #10286
-
-Stefan Eissing (12 Jan 2023)
-
-- openssl: make the BIO_METHOD a local variable in the connection filter
-
- This avoids UAF issues when `curl_global_cleanup()` is called before all
- transfers have been completely handled. Unfortunately this seems to be a
- more common pattern than we like.
-
- Closes #10285
-
-Daniel Stenberg (12 Jan 2023)
-
-- curl: output warning at --verbose output for debug-enabled version
-
- + a libcurl warning in the debug output
-
- Assisted-by: Jay Satiro
-
- Ref: https://curl.se/mail/lib-2023-01/0039.html
- Closes #10278
-
-- src: add --http3-only
-
- Warning: --http3 and --http3-only are subject to change again (or be
- removed) before HTTP/3 support goes non-experimental.
-
- Closes #10264
-
-- curl.h: add CURL_HTTP_VERSION_3ONLY
-
- As the previous CURL_HTTP_VERSION_3 option gets a slightly altered meaning.
-
- Closes #10264
-
-- connect: fix access of pointer before NULL check
-
- Detected by Coverity CID 1518992
-
- Closes #10284
-
-Daniel Gustafsson (12 Jan 2023)
-
-- easyoptions: Fix header printing in generation script
-
- The optiontable.pl script prints the header comment when generating
- easyoptions.c, but it wasn't escaping all characters which jumbled the
- curl ascii logo. Fix by escaping.
-
- Cloes #10275
-
-Harry Sintonen (12 Jan 2023)
-
-- tool_getparam: fix hiding of command line secrets
-
- Closes #10276
-
-Stefan Eissing (12 Jan 2023)
-
-- tests: document the cfilter debug logging options
-
- Closes #10283
-
-- curl_log: for failf/infof and debug logging implementations
-
- - new functions and macros for cfilter debugging
- - set CURL_DEBUG with names of cfilters where debug logging should be
- enabled
- - use GNUC __attribute__ to enable printf format checks during compile
-
- Closes #10271
-
-Daniel Stenberg (10 Jan 2023)
-
-- RELEASE-NOTES: synced
-
-Nick Banks (10 Jan 2023)
-
-- msh3: update to v0.6
-
- Closes #10192
-
-Stefan Eissing (10 Jan 2023)
-
-- ngtcp2: add CURLOPT_SSL_CTX_FUNCTION support for openssl+wolfssl
-
- Using common method for SSL_CTX initialization of verfiy peer and CA
- settings. This also provides X509_STORE sharing to become available for
- ngtcp2+openssl HTTP/3.
-
- Reported-by: violetlige on github
-
- Fixes #10222
- Closes #10239
-
-Daniel Stenberg (10 Jan 2023)
-
-- cf-socket: make infof() call use %zu for size_t output
-
- Detected by Coverity CID 1518986 and CID 1518984
-
- Closes #10268
-
-Jon Rumsey (10 Jan 2023)
-
-- os400: fixes to make-lib.sh and initscript.sh
-
- Adjust how exports list is generated from header files to account for
- declarations across multiple lines and CURL_DEPRECATED(...) tags.
-
- Update initscript.sh
-
- Specify qadrt_use_inline to prevent unistd.h in ASCII runtime defining
- close(a) -> close_a(a)
-
- Fixes #10266
- Closes #10267
-
-Stefan Eissing (9 Jan 2023)
-
-- tests-httpd: basic infra to run curl against an apache httpd plus nghttpx for
- h3
-
- - adding '--with-test-httpd=<path>' to configure non-standard apache2
- install
- - python env and base classes for running httpd
- - basic tests for connectivity with h1/h2/h3
- - adding test cases for truncated responses in http versions.
- - adding goaway test for HTTP/3.
- - adding "stuttering" tests with parallel downloads in chunks with
- varying delays between chunks.
-
- - adding a curltest module to the httpd server, adding GOAWAY test.
- - mod_curltest now installs 2 handlers
- - 'echo': writing as response body what came as request body
- - 'tweak': with query parameters to tweak response behaviour
- - marked known fails as skip for now
-
- Closes #10175
-
-- quic: improve connect error message, debugging info, fix false connect report
-
- - ECONNECTREFUSED has not its own fail message in quic filters
- - Debug logging in connect eyballing improved
- - Fix bug in ngtcp2/quiche that could lead to false success reporting.
-
- Reported-by: Divy Le Ray
-
- Fixes #10245
- Closes #10248
-
-- quiche: fix build without any HTTP/2 implementation
-
- Fixes #10260
- Closes #10263
-
-Daniel Stenberg (9 Jan 2023)
-
-- .github/workflows/linux.yml: add a quiche CI job
-
- Move over from zuul
-
- Closes #10241
-
-- curl.h: allow up to 10M buffer size
-
- Bump the limit from 512K. There might be reasons for applications using
- h3 to set larger buffers and there is no strong reason for curl to have
- a very small maximum.
-
- Ref: https://curl.se/mail/lib-2023-01/0026.html
-
- Closes #10256
-
-Tatsuhiro Tsujikawa (8 Jan 2023)
-
-- GHA: use designated ngtcp2 and its dependencies versions
-
- Designate ngtcp2 and its dependency versions so that the CI build does
- not fail without our control.
-
- Closes #10257
-
-Daniel Stenberg (8 Jan 2023)
-
-- docs/cmdline-opts/hsts.d: explain hsts more
-
- Closes #10258
-
-Stefan Eissing (8 Jan 2023)
-
-- msh3: run again in its cfilter
-
- - test 2500, single GET works
- - test 2501, single POST stalls
- - test 2502, multiple, sequential GETs each use a new connection since
- MsH3ConnectionGetState(qconn) no longer reports CONNECTED after one
- GET.
-
- Closes #10204
-
-Jay Satiro (8 Jan 2023)
-
-- sendf: fix build for Linux TCP fastopen
-
- - Fix the remote addr struct dereference.
-
- - Include cf-socket.h in urldata.h.
-
- Follow-up to 6a8d7ef9 which changed conn->ipaddr (Curl_addrinfo* )
- member to conn->remote_addr (Curl_sockaddr_ex *) several days ago.
-
- Reported-by: Stephan Guilloux
-
- Fixes https://github.com/curl/curl/issues/10249
- Closes https://github.com/curl/curl/pull/10250
-
-Daniel Stenberg (7 Jan 2023)
-
-- RELEASE-NOTES: synced
-
-- setopt: move the SHA256 opt within #ifdef libssh2
-
- Because only the libssh2 backend not supports it and thus this should
- return error if this option is used other backends.
-
- Reported-by: Harry Sintonen
-
- Closes #10255
-
-Patrick Monnerat (7 Jan 2023)
-
-- nss: implement data_pending method
-
- NSS currently uses the default Curl_none_data_pending() method which
- always returns false, causing TLS buffered input data to be missed.
-
- The current commit implements the nss_data_pending() method that properly
- monitors the presence of available TLS data.
-
- Ref:#10077
-
- Closes #10225
-
-Jay Satiro (6 Jan 2023)
-
-- CURLOPT_HEADERDATA.3: warn DLL users must set write function
-
- - Warn that in Windows if libcurl is running from a DLL and if
- CURLOPT_HEADERDATA is set then CURLOPT_WRITEFUNCTION or
- CURLOPT_HEADERFUNCTION must be set as well, otherwise the user may
- experience crashes.
-
- We already have a similar warning in CURLOPT_WRITEDATA. Basically, in
- Windows libcurl could crash writing a FILE pointer that was created by
- a different C runtime. In Windows each DLL that is part of a program may
- or may not have its own C runtime.
-
- Ref: https://github.com/curl/curl/issues/10231
-
- Closes https://github.com/curl/curl/pull/10233
-
-Jon Rumsey (5 Jan 2023)
-
-- x509asn1: fix compile errors and warnings
-
- Various small issues when built for GSKit
-
- Closes #10238
-
-Patrick Monnerat (5 Jan 2023)
-
-- runtests: fix detection of TLS backends
-
- Built-in TLS backends are detected at test time by scanning for their
- names in the version string line returned by the cli tool: as this line
- may also list the libssh configuration that mentions its own backend,
- the curl backend may be wrongly determined.
-
- In example, if the version line contains "libssh/0.10.4/openssl/zlib",
- OpenSSL is detected as a curl-configured backend even if not.
-
- This fix requires the backend names to appear as full words preceded by
- spacing in the version line to be recognized as curl TLS backends.
-
- Closes #10236
-
-Andy Alt (5 Jan 2023)
-
-- GHA: add job on Slackware 15.0
-
- Closes #10230
-
-Daniel Stenberg (5 Jan 2023)
-
-- test363: make even smaller writes to loop more
-
-- http_proxy: do not assign data->req.p.http use local copy
-
- Avoid the tricky reusing of the data->req.p.http pointer for http proxy
- tunneling.
-
- Fixes #10194
- Closes #10234
-
-Stefan Eissing (5 Jan 2023)
-
-- quic: rename vquic implementations, fix for quiche build.
-
- - quiche in debug mode did not build, fixed.
- - moved all vquic implementation files to prefix curl_* to avoid
- the potential mixups between provided .h files and our own.
- - quich passes test 2500 and 2502. 2501, the POST, fail with
- the body being rejected. Quich bug?
-
- Closes #10242
-
-- sectransp: fix for incomplete read/writes
-
- SecureTransport expects result code errSSLWouldBlock when the requested
- length could not be sent/recieved in full. The previous code returned
- noErr, which let SecureTransport to believe that the IO had terminated
- prematurely.
-
- Fixes #10227
- Closes #10235
-
-Andy Alt (5 Jan 2023)
-
-- GHA: Hacktoberfest CI: Update deprecated 'set-output' command
-
- Closes #10221
-
-Jay Satiro (5 Jan 2023)
-
-- scripts: set file mode +x on all perl and shell scripts
-
- - Set all scripts +x, ie 644 => 755.
-
- Prior to this change some scripts were not executable and therefore
- could not be called directly.
-
- ~~~
- git ls-files -s \*.{sh,pl,py} | grep -v 100755
- ~~~
-
- Closes https://github.com/curl/curl/pull/10219
-
-Stefan Eissing (4 Jan 2023)
-
-- tool_operate: fix headerfile writing
-
- Do not rely on the first transfer started to be the first to get a
- response (remember -Z). All transfers now write the headefile (-D) in
- append mode, making sure that the order of transfer responses does not
- lead to overwrites of previous data.
-
- Closes #10224
-
-Daniel Stenberg (4 Jan 2023)
-
-- misc: reduce struct and struct field sizes
-
- - by using BIT() instead of bool
- - imap: shrink struct
- - ftp: make state 'unsigned char'
- - ftp: sort ftp_conn struct entries on size
- - urldata: use smaller fields for SSL version info storage
- - pop3: reduce the pop3_conn struct size
- - smtp: reduce the size of the smtp structs
-
- Closes #10186
-
-- noproxy: support for space-separated names is deprecated
-
- To be removed in July 2024.
-
- Assisted-by: Michael Osipov
- Fixes #10209
- Closes #10215
-
-Andrei Rybak (4 Jan 2023)
-
-- lib: fix typos in comments which repeat a word
-
- Remove erroneously duplicated words in code comments of files
- `lib.connect.c` and `lib/url.c`.
-
- Closes #10220
-
-Radek Brich (3 Jan 2023)
-
-- cmake: set SOVERSION also for macOS
-
- Closes #10214
-
-Jay Satiro (3 Jan 2023)
-
-- http2: fix compiler warning due to uninitialized variable
-
- Prior to this change http2_cfilter_add could return an uninitialized
- cfilter pointer in an OOM condition. In this case though, the pointer
- is discarded and not dereferenced so there was no risk of a crash.
diff --git a/libs/libcurl/docs/THANKS b/libs/libcurl/docs/THANKS
index beca5197e1..08983c38a6 100644
--- a/libs/libcurl/docs/THANKS
+++ b/libs/libcurl/docs/THANKS
@@ -94,6 +94,7 @@ Alexander Beedie
Alexander Chuykov
Alexander Dyagilev
Alexander Elgert
+Alexander Jaeger
Alexander Kanavin
Alexander Klauer
Alexander Kourakos
@@ -226,6 +227,7 @@ Antoni Villalonga
Antonio Larrosa
Antony74 on github
Antti Hätälä
+apparentorder on github
April King
arainchik on github
Archangel_SDY on github
@@ -269,6 +271,7 @@ Balaji S Rao
Balaji Salunke
Balakrishnan Balasubramanian
Balazs Kovacsics
+balikalina on Github
Balint Szilakszi
Barry Abrahamson
Barry Pollard
@@ -303,6 +306,7 @@ Benjamin Riefenstahl
Benjamin Ritcey
Benjamin Sergeant
Benoit Neil
+Benoit Pierre
Benoit Sigoure
Bernard Leak
Bernard Spil
@@ -595,6 +599,7 @@ Darryl House
Darshan Mody
Darío Hereñú
dasimx on github
+Dave Cottlehuber
Dave Dribin
Dave Halbakken
Dave Hamilton
@@ -648,6 +653,7 @@ David Woodhouse
David Wright
David Yan
Davide Cassioli
+Davide Masserut
davidedec on github
dbrowndan on github
dEajL3kA on github
@@ -757,6 +763,7 @@ Ebe Janchivdorj
ebejan on github
Ebenezer Ikonne
Ed Morley
+ed0d2b2ce19451f2
Eddie Lumpkin
Edgaras Janušauskas
Edin Kadribasic
@@ -796,6 +803,7 @@ Emilio López
Emmanuel Tychon
Enrico Scholz
Enrik Berkhan
+eppesuig
Eramoto Masaya
Eric Cooper
Eric Curtin
@@ -857,6 +865,7 @@ Faizur Rahman
Farzin on github
Fata Nugraha
Fawad Mirza
+FC Stegerman
fds242 on github
Federico Bianchi
Federico Pellegrin
@@ -915,6 +924,7 @@ FuccDucc on github
Fujii Hironori
fullincome on github
fundawang on github
+Gabriel Corona
Gabriel Kuri
Gabriel Simmer
Gabriel Sjoberg
@@ -944,6 +954,7 @@ George Liu
Gerd v. Egidy
Gergely Nagy
Gerhard Herre
+Gerome Fournier
Gerrit Bruchhäuser
Gerrit Renker
Ghennadi Procopciuc
@@ -973,6 +984,7 @@ Godwin Stewart
Google Inc.
Gordon Marler
Gorilla Maguila
+Goro FUJI
Gou Lingfeng
Graham Campbell
Grant Erickson
@@ -994,10 +1006,12 @@ Grigory Entin
Grisha Levit
Guenole Bescon
Guido Berhoerster
+Guillaume Algis
Guillaume Arluison
guitared on github
Gunamoi Software
Gunter Knauf
+guoxinvmware on github
Gustaf Hui
Gustavo Grieco
Guy Poizat
@@ -1129,6 +1143,7 @@ JackBoosY on github
Jacky Lam
Jacob Barthelmeh
Jacob Hoffman-Andrews
+Jacob Mealey
Jacob Meuser
Jacob Moshenko
Jacob Tolar
@@ -1198,6 +1213,7 @@ Jay Austin
Jay Dommaschk
Jayesh A Shah
Jaz Fresh
+JazJas on github
jbgoog on github
Jean Fabrice
Jean Gressmann
@@ -1307,6 +1323,7 @@ John Gardiner Myers
John H. Ayad
John Hascall
John Haugabook
+John Hawthorn
John Janssen
John Joseph Bachir
John Kelly
@@ -1325,6 +1342,7 @@ John Simpson
John Starks
John Suprock
John V. Chow
+John Walker
John Wanghui
John Weismiller
John Wilkinson
@@ -1366,6 +1384,7 @@ Jose Alf
Jose Kahan
Josef Wolf
Joseph Chen
+Joseph Tharayil
Josh Bialkowski
Josh Brobst
Josh Kapell
@@ -1403,6 +1422,7 @@ Jun-ichiro itojun Hagino
Jun-ya Kato
jungle-boogie on github
Junho Choi
+junsik on github
Jurij Smakov
jurisuk on github
Juro Bystricky
@@ -1520,6 +1540,7 @@ Kyle Edwards
Kyle J. McKay
Kyle L. Huff
Kyle Sallee
+kyled-dell on github
Kyohei Kadota
Kyselgov E.N
l00p3r on Hackerone
@@ -1606,6 +1627,7 @@ Ludek Finstrle
Ludovico Cavedon
Ludwig Nussel
Lukas Ruzicka
+Lukas Tribus
Lukasz Czekierda
lukaszgn on github
Luke Amery
@@ -1629,7 +1651,9 @@ madblobfish on github
MaeIsBad on github
Mahmoud Samir Fayed
Maks Naumov
+Maksim Arhipov
Maksim Kuzevanov
+Maksim Sciepanienka
Maksim Stsepanenka
Malik Idrees Hasan Khan
Mamoru Tasaka
@@ -1669,6 +1693,7 @@ Marcus T
Marcus Webster
Margu
Marian Klymov
+Marin Hannache
Mario Schroeder
Mark Brand
Mark Butler
@@ -1695,6 +1720,7 @@ Markus Koetter
Markus Moeller
Markus Oberhumer
Markus Olsson
+Markus Sommer
Markus Westerlind
Maros Priputen
Marquis de Muesli
@@ -1736,6 +1762,7 @@ Massimo Callegari
Master Inspire
MasterInQuestion on github
Mateusz Loskot
+Mathew Benson
Mathias Axelsson
Mathias Gumz
Mathieu Carbonneaux
@@ -1770,6 +1797,7 @@ Matus Uzak
Maurice Barnum
Mauro Iorio
Mauro Rappa
+Maurício Meneghini Fauth
Max Dymond
Max Katsev
Max Kellermann
@@ -1884,6 +1912,7 @@ Mischa Salle
Mitz Wark
mkzero on github
modbw on github
+Mohamed Daahir
Mohamed Lrhazi
Mohamed Osama
Mohammad AlSaleh
@@ -1933,12 +1962,14 @@ Neil Kolban
Neil Spring
neutric on github
nevv on HackerOne/curl
+Niall McGee
Niall O'Reilly
niallor on github
nian6324 on github
nianxuejie on github
Nic Roets
Nicholas Maniscalco
+Nicholas Nethercote
Nick Banks
Nick Coghlan
Nick Draffen
@@ -1956,7 +1987,9 @@ Nicolas François
Nicolas Grekas
Nicolas Guillier
Nicolas Morey-Chaisemartin
+Nicolas Noben
Nicolas Sterchele
+Nicolás Ojeda Bär
Niels Martignène
Niels van Tongeren
Nikita Schmidt
@@ -2007,6 +2040,7 @@ Oliver Kuckertz
Oliver Roberts
Oliver Schindler
Oliver Urbann
+oliverpool on github
Olivier Berger
Olivier Brunel
Omar Ramadan
@@ -2030,6 +2064,7 @@ Oskar Sigvardsson
Oumph on github
ovidiu-benea on github
P R Schaffner
+Pablo Busse
Palo Markovic
pandada8 on github
Paolo Mossino
@@ -2152,6 +2187,7 @@ Philip Sanetra
Philipp Engel
Philipp Klaus Krause
Philipp Waehnert
+Philippe Antoine on HackerOne
Philippe Hameau
Philippe Marguinaud
Philippe Raoult
@@ -2181,6 +2217,7 @@ ProceduralMan on github
Pronyushkin Petr
Przemysław Tomaszewski
pszemus on github
+pszlazak on github
puckipedia on github
Puneet Pawaia
qiandu2006 on github
@@ -2277,6 +2314,7 @@ Richard Moore
Richard Prescott
Richard Silverman
Richard van den Berg
+Richard W.M. Jones
Richard Whitehouse
Richy Kim
Rici Lake
@@ -2365,6 +2403,7 @@ Rui Pinheiro
Rune Kleveland
Ruslan Baratov
Ruslan Gazizov
+Rutger Broekhoff
Rutger Hofman
Ruurd Beerstra
RuurdBeerstra on github
@@ -2395,6 +2434,7 @@ Sam Roth
Sam Schanken
Samanta Navarro
Sampo Kellomaki
+Samuel Chiang
Samuel Díaz García
Samuel Henrique
Samuel Listopad
@@ -2414,6 +2454,7 @@ Saran Neti
Sascha Swiercy
Sascha Zengler
Satadru Pramanik
+Satana de Sant'Ana
Saul good
Saurav Babu
sayrer on github
@@ -2440,6 +2481,7 @@ SendSonS on github
Senthil Raja Velu
Sergei Kuzmin
Sergei Nikulov
+Sergey
Sergey Alirzaev
Sergey Bronnikov
Sergey Fionov
@@ -2643,6 +2685,7 @@ Thomas van Hesteren
Thomas Vegas
Thomas Weißschuh
Thomas1664 on github
+Thorsten Klein
Thorsten Schöning
Tiit Pikma
Till Maas
@@ -2743,6 +2786,7 @@ Travis Obenhaus
Trivikram Kamat
Troels Walsted Hansen
Troy Engel
+trrui-huawei
Tseng Jun
Tuomas Siipola
Tuomo Rinne
@@ -2812,12 +2856,14 @@ Vojtěch Král
Volker Schmid
Vsevolod Novikov
vshmuk on hackerone
+vvb2060
vvb2060 on github
Vyron Tsingaras
Vítor Galvão
W. Mark Kubacki
Waldek Kozba
Walter J. Mack
+wangzhikun
Ward Willats
Warren Menzer
Wayne Haigh
@@ -2833,6 +2879,7 @@ Wesley Miaw
Wez Furlong
Wham Bang
Wilfredo Sanchez
+Wilhelm von Thiele
Will Dietz
Will Roberts
Willem Hoek
@@ -2892,6 +2939,7 @@ Yuri Slobodyanyuk
Yurii Rashkovskii
Yuriy Chernyshov
Yuriy Sosov
+yushicheng7788 on github
Yusuke Nakamura
Yves Arrouye
Yves Lejeune
@@ -2910,6 +2958,7 @@ zhanghu on xiaomi
Zhao Yisha
Zhaoyang Wu
Zhibiao Wu
+zhihaoy on github
Zhouyihai Ding
ZimCodes on github
zloi-user on github
diff --git a/libs/libcurl/include/curl/curl.h b/libs/libcurl/include/curl/curl.h
index b6cc8e8795..0432a2cdd7 100644
--- a/libs/libcurl/include/curl/curl.h
+++ b/libs/libcurl/include/curl/curl.h
@@ -161,7 +161,7 @@ typedef enum {
CURLSSLBACKEND_GNUTLS = 2,
CURLSSLBACKEND_NSS = 3,
CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */
- CURLSSLBACKEND_GSKIT = 5,
+ CURLSSLBACKEND_GSKIT CURL_DEPRECATED(8.3.0, "") = 5,
CURLSSLBACKEND_POLARSSL CURL_DEPRECATED(7.69.0, "") = 6,
CURLSSLBACKEND_WOLFSSL = 7,
CURLSSLBACKEND_SCHANNEL = 8,
@@ -2731,6 +2731,20 @@ CURL_EXTERN CURLcode curl_global_init_mem(long flags,
*/
CURL_EXTERN void curl_global_cleanup(void);
+/*
+ * NAME curl_global_trace()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_trace() can be invoked at application start to
+ * configure which components in curl should participate in tracing.
+
+ * This function is thread-safe if CURL_VERSION_THREADSAFE is set in the
+ * curl_version_info_data.features flag (fetch by curl_version_info()).
+
+ */
+CURL_EXTERN CURLcode curl_global_trace(const char *config);
+
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist {
char *data;
@@ -2810,13 +2824,14 @@ CURL_EXTERN void curl_slist_free_all(struct curl_slist *list);
*/
CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
-/* info about the certificate chain, only for OpenSSL, GnuTLS, Schannel, NSS
- and GSKit builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+/* info about the certificate chain, for SSL backends that support it. Asked
+ for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
struct curl_certinfo {
int num_of_certs; /* number of certificates with information */
struct curl_slist **certinfo; /* for each index in this array, there's a
- linked list with textual information in the
- format "name: value" */
+ linked list with textual information for a
+ certificate in the format "name:content".
+ eg "Subject:foo", "Issuer:bar", etc. */
};
/* Information about the SSL library used and the respective internal SSL
diff --git a/libs/libcurl/include/curl/curlver.h b/libs/libcurl/include/curl/curlver.h
index b85f767b2f..ac9fd9673d 100644
--- a/libs/libcurl/include/curl/curlver.h
+++ b/libs/libcurl/include/curl/curlver.h
@@ -32,13 +32,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "8.2.1"
+#define LIBCURL_VERSION "8.3.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 8
-#define LIBCURL_VERSION_MINOR 2
-#define LIBCURL_VERSION_PATCH 1
+#define LIBCURL_VERSION_MINOR 3
+#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
@@ -59,7 +59,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x080201
+#define LIBCURL_VERSION_NUM 0x080300
/*
* This is the date and time when the full source package was created. The
@@ -70,7 +70,7 @@
*
* "2007-11-23"
*/
-#define LIBCURL_TIMESTAMP "2023-07-26"
+#define LIBCURL_TIMESTAMP "2023-09-13"
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
#define CURL_AT_LEAST_VERSION(x,y,z) \
diff --git a/libs/libcurl/include/curl/mprintf.h b/libs/libcurl/include/curl/mprintf.h
index 93be4e1f62..b344c8c830 100644
--- a/libs/libcurl/include/curl/mprintf.h
+++ b/libs/libcurl/include/curl/mprintf.h
@@ -32,18 +32,36 @@
extern "C" {
#endif
-CURL_EXTERN int curl_mprintf(const char *format, ...);
-CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
-CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
+#if (defined(__GNUC__) || defined(__clang__)) && \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+ !defined(__MINGW32__) && !defined(CURL_NO_FMT_CHECKS)
+#define CURL_TEMP_PRINTF(a,b) __attribute__ ((format(printf, a, b)))
+#else
+#define CURL_TEMP_PRINTF(a,b)
+#endif
+
+CURL_EXTERN int curl_mprintf(const char *format, ...) CURL_TEMP_PRINTF(1, 2);
+CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...)
+ CURL_TEMP_PRINTF(2, 3);
+CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...)
+ CURL_TEMP_PRINTF(2, 3);
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
- const char *format, ...);
-CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
-CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
-CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
+ const char *format, ...) CURL_TEMP_PRINTF(3, 4);
+CURL_EXTERN int curl_mvprintf(const char *format, va_list args)
+ CURL_TEMP_PRINTF(1, 0);
+CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args)
+ CURL_TEMP_PRINTF(2, 0);
+CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args)
+ CURL_TEMP_PRINTF(2, 0);
CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
- const char *format, va_list args);
-CURL_EXTERN char *curl_maprintf(const char *format, ...);
-CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
+ const char *format, va_list args)
+ CURL_TEMP_PRINTF(3, 0);
+CURL_EXTERN char *curl_maprintf(const char *format, ...)
+ CURL_TEMP_PRINTF(1, 2);
+CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args)
+ CURL_TEMP_PRINTF(1, 0);
+
+#undef CURL_TEMP_PRINTF
#ifdef __cplusplus
} /* end of extern "C" */
diff --git a/libs/libcurl/include/curl/multi.h b/libs/libcurl/include/curl/multi.h
index 7a7a1ec229..caa948953c 100644
--- a/libs/libcurl/include/curl/multi.h
+++ b/libs/libcurl/include/curl/multi.h
@@ -118,7 +118,7 @@ typedef struct CURLMsg CURLMsg;
struct curl_waitfd {
curl_socket_t fd;
short events;
- short revents; /* not supported yet */
+ short revents;
};
/*
diff --git a/libs/libcurl/include/curl/system.h b/libs/libcurl/include/curl/system.h
index 556ffa9c9b..9a32e26d63 100644
--- a/libs/libcurl/include/curl/system.h
+++ b/libs/libcurl/include/curl/system.h
@@ -347,6 +347,24 @@
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
+#elif defined(__hpux) /* HP aCC compiler */
+# if !defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
/* ===================================== */
/* KEEP MSVC THE PENULTIMATE ENTRY */
/* ===================================== */
diff --git a/libs/libcurl/include/curl/urlapi.h b/libs/libcurl/include/curl/urlapi.h
index 2440c1affc..1c9b11fec5 100644
--- a/libs/libcurl/include/curl/urlapi.h
+++ b/libs/libcurl/include/curl/urlapi.h
@@ -96,7 +96,8 @@ typedef enum {
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
scheme is unknown. */
#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */
-#define CURLU_PUNYCODE (1<<12) /* get the host name in pynycode */
+#define CURLU_PUNYCODE (1<<12) /* get the host name in punycode */
+#define CURLU_PUNY2IDN (1<<13) /* punycode => IDN conversion */
typedef struct Curl_URL CURLU;
diff --git a/libs/libcurl/libcurl.vcxproj b/libs/libcurl/libcurl.vcxproj
index e07dc059cd..32801244aa 100644
--- a/libs/libcurl/libcurl.vcxproj
+++ b/libs/libcurl/libcurl.vcxproj
@@ -101,9 +101,6 @@
<ClCompile Include="src\curl_gssapi.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
- <ClCompile Include="src\curl_log.c">
- <PrecompiledHeader>NotUsing</PrecompiledHeader>
- </ClCompile>
<ClCompile Include="src\curl_memrchr.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
@@ -134,6 +131,9 @@
<ClCompile Include="src\curl_threads.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="src\curl_trc.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
<ClCompile Include="src\dict.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
@@ -434,9 +434,6 @@
<ClCompile Include="src\vtls\bearssl.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
- <ClCompile Include="src\vtls\gskit.c">
- <PrecompiledHeader>NotUsing</PrecompiledHeader>
- </ClCompile>
<ClCompile Include="src\vtls\gtls.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
@@ -452,9 +449,6 @@
<ClCompile Include="src\vtls\mbedtls_threadlock.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
- <ClCompile Include="src\vtls\nss.c">
- <PrecompiledHeader>NotUsing</PrecompiledHeader>
- </ClCompile>
<ClCompile Include="src\vtls\openssl.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
@@ -520,7 +514,6 @@
<ClInclude Include="src\curl_hmac.h" />
<ClInclude Include="src\curl_krb5.h" />
<ClInclude Include="src\curl_ldap.h" />
- <ClInclude Include="src\curl_log.h" />
<ClInclude Include="src\curl_md4.h" />
<ClInclude Include="src\curl_md5.h" />
<ClInclude Include="src\curl_memory.h" />
@@ -538,6 +531,7 @@
<ClInclude Include="src\curl_sha256.h" />
<ClInclude Include="src\curl_sspi.h" />
<ClInclude Include="src\curl_threads.h" />
+ <ClInclude Include="src\curl_trc.h" />
<ClInclude Include="src\dict.h" />
<ClInclude Include="src\doh.h" />
<ClInclude Include="src\dotdot.h" />
diff --git a/libs/libcurl/libcurl.vcxproj.filters b/libs/libcurl/libcurl.vcxproj.filters
index 6828329cc8..aced79ad6c 100644
--- a/libs/libcurl/libcurl.vcxproj.filters
+++ b/libs/libcurl/libcurl.vcxproj.filters
@@ -77,9 +77,6 @@
<ClCompile Include="src\curl_gssapi.c">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\curl_log.c">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="src\curl_memrchr.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -110,6 +107,9 @@
<ClCompile Include="src\curl_threads.c">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\curl_trc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="src\dict.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -407,9 +407,6 @@
<ClCompile Include="src\vtls\bearssl.c">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\vtls\gskit.c">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="src\vtls\gtls.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -422,9 +419,6 @@
<ClCompile Include="src\vtls\mbedtls_threadlock.c">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\vtls\nss.c">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="src\vtls\openssl.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -607,9 +601,6 @@
<ClInclude Include="src\curl_ldap.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="src\curl_log.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="src\curl_md4.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -661,6 +652,9 @@
<ClInclude Include="src\curl_threads.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="src\curl_trc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="src\dict.h">
<Filter>Header Files</Filter>
</ClInclude>
diff --git a/libs/libcurl/src/CMakeLists.txt b/libs/libcurl/src/CMakeLists.txt
index f55c3449a2..0f6bce9759 100644
--- a/libs/libcurl/src/CMakeLists.txt
+++ b/libs/libcurl/src/CMakeLists.txt
@@ -25,14 +25,6 @@ set(LIB_NAME libcurl)
set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library")
add_definitions(-DBUILDING_LIBCURL)
-if(BUILD_SHARED_LIBS)
- set(CURL_STATICLIB NO)
-else()
- set(CURL_STATICLIB YES)
-endif()
-
-# Use:
-# * CURL_STATICLIB
configure_file(curl_config.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
@@ -43,10 +35,6 @@ list(APPEND HHEADERS
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h
)
-if(WIN32 AND NOT CURL_STATICLIB)
- list(APPEND CSOURCES libcurl.rc)
-endif()
-
# The rest of the build
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include)
@@ -60,11 +48,6 @@ if(USE_ARES)
endif()
add_library(
- ${LIB_NAME}
- ${HHEADERS} ${CSOURCES}
- )
-
-add_library(
curlu # special libcurlu library just for unittests
STATIC
EXCLUDE_FROM_ALL
@@ -72,32 +55,16 @@ add_library(
)
target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
-add_library(
- ${PROJECT_NAME}::${LIB_NAME}
- ALIAS ${LIB_NAME}
- )
-
if(ENABLE_CURLDEBUG)
# We must compile memdebug.c separately to avoid memdebug.h redefinitions
# being applied to memdebug.c itself.
set_source_files_properties(memdebug.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
endif()
-
-if(NOT BUILD_SHARED_LIBS)
- set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
-endif()
-
-target_link_libraries(${LIB_NAME} PRIVATE ${CURL_LIBS})
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake)
-set_target_properties(${LIB_NAME} PROPERTIES
- COMPILE_DEFINITIONS BUILDING_LIBCURL
- OUTPUT_NAME ${LIBCURL_OUTPUT_NAME}
- )
-
if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
@@ -114,39 +81,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
math(EXPR CMAKESONAME "${VERSIONCHANGE} - ${VERSIONDEL}")
set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}")
-
- set_target_properties(${LIB_NAME} PROPERTIES
- VERSION ${CMAKEVERSION}
- SOVERSION ${CMAKESONAME}
- )
-
-endif()
-
-
-if(HIDES_CURL_PRIVATE_SYMBOLS)
- set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
- set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE})
-endif()
-
-# Remove the "lib" prefix since the library is already named "libcurl".
-set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
-set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")
-
-if(CURL_HAS_LTO)
- set_target_properties(${LIB_NAME} PROPERTIES
- INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
- INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+else()
+ unset(CMAKESONAME)
endif()
-if(WIN32)
- if(BUILD_SHARED_LIBS)
- if(MSVC)
- # Add "_imp" as a suffix before the extension to avoid conflicting with
- # the statically linked "libcurl.lib"
- set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
- endif()
- endif()
-elseif(NOT CMAKE_CROSSCOMPILING)
+if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
# on not-Windows and not-crosscompiling, check for writable argv[]
include(CheckCSourceRuns)
check_c_source_runs("
@@ -159,19 +98,146 @@ int main(int argc, char **argv)
HAVE_WRITABLE_ARGV)
endif()
-target_include_directories(${LIB_NAME} INTERFACE
- $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
- $<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
+## Library definition
+
+# Add "_imp" as a suffix before the extension to avoid conflicting with
+# the statically linked "libcurl.lib" (typically with MSVC)
+if(WIN32 AND
+ NOT IMPORT_LIB_SUFFIX AND
+ CMAKE_STATIC_LIBRARY_SUFFIX STREQUAL CMAKE_IMPORT_LIBRARY_SUFFIX)
+ set(IMPORT_LIB_SUFFIX "_imp")
+endif()
+
+# Whether to do a single compilation pass for libcurl sources and reuse these
+# objects to generate both static and shared target.
+if(NOT DEFINED SHARE_LIB_OBJECT)
+ # Enable it by default on platforms where PIC is the default for both shared
+ # and static and there is a way to tell the linker which libcurl symbols it
+ # should export (vs. marking these symbols exportable at compile-time).
+ if(WIN32)
+ set(SHARE_LIB_OBJECT ON)
+ else()
+ # On other platforms, make it an option disabled by default
+ set(SHARE_LIB_OBJECT OFF)
+ endif()
+endif()
+
+if(SHARE_LIB_OBJECT)
+ set(LIB_OBJECT "libcurl_object")
+ add_library(${LIB_OBJECT} OBJECT ${HHEADERS} ${CSOURCES})
+ target_link_libraries(${LIB_OBJECT} PRIVATE ${CURL_LIBS})
+ set_target_properties(${LIB_OBJECT} PROPERTIES
+ COMPILE_DEFINITIONS "BUILDING_LIBCURL"
+ INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB"
+ POSITION_INDEPENDENT_CODE ON)
+ if(HIDES_CURL_PRIVATE_SYMBOLS)
+ set_target_properties(${LIB_OBJECT} PROPERTIES
+ COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS"
+ COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
+ endif()
+ if(CURL_HAS_LTO)
+ set_target_properties(${LIB_OBJECT} PROPERTIES
+ INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
+ INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+ endif()
+
+ target_include_directories(${LIB_OBJECT} INTERFACE
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ $<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
+
+ set(LIB_SOURCE $<TARGET_OBJECTS:${LIB_OBJECT}>)
+else()
+ set(LIB_SOURCE ${HHEADERS} ${CSOURCES})
+endif()
+
+# we want it to be called libcurl on all platforms
+if(BUILD_STATIC_LIBS)
+ list(APPEND libcurl_export ${LIB_STATIC})
+ add_library(${LIB_STATIC} STATIC ${LIB_SOURCE})
+ add_library(${PROJECT_NAME}::${LIB_STATIC} ALIAS ${LIB_STATIC})
+ target_link_libraries(${LIB_STATIC} PRIVATE ${CURL_LIBS})
+ # Remove the "lib" prefix since the library is already named "libcurl".
+ set_target_properties(${LIB_STATIC} PROPERTIES
+ PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
+ SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ COMPILE_DEFINITIONS "BUILDING_LIBCURL"
+ INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB")
+ if(HIDES_CURL_PRIVATE_SYMBOLS)
+ set_target_properties(${LIB_STATIC} PROPERTIES
+ COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS"
+ COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
+ endif()
+ if(CURL_HAS_LTO)
+ set_target_properties(${LIB_STATIC} PROPERTIES
+ INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
+ INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+ endif()
+ if(CMAKEVERSION AND CMAKESONAME)
+ set_target_properties(${LIB_STATIC} PROPERTIES
+ VERSION ${CMAKEVERSION} SOVERSION ${CMAKESONAME})
+ endif()
+
+ target_include_directories(${LIB_STATIC} INTERFACE
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ $<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
+endif()
+
+if(BUILD_SHARED_LIBS)
+ list(APPEND libcurl_export ${LIB_SHARED})
+ add_library(${LIB_SHARED} SHARED ${LIB_SOURCE})
+ add_library(${PROJECT_NAME}::${LIB_SHARED} ALIAS ${LIB_SHARED})
+ if(WIN32)
+ set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES libcurl.rc ${CURL_SOURCE_DIR}/libcurl.def)
+ endif()
+ target_link_libraries(${LIB_SHARED} PRIVATE ${CURL_LIBS})
+ # Remove the "lib" prefix since the library is already named "libcurl".
+ set_target_properties(${LIB_SHARED} PROPERTIES
+ PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
+ IMPORT_PREFIX "" IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}"
+ COMPILE_DEFINITIONS "BUILDING_LIBCURL"
+ POSITION_INDEPENDENT_CODE ON)
+ if(HIDES_CURL_PRIVATE_SYMBOLS)
+ set_target_properties(${LIB_SHARED} PROPERTIES
+ COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS"
+ COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
+ endif()
+ if(CURL_HAS_LTO)
+ set_target_properties(${LIB_SHARED} PROPERTIES
+ INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
+ INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+ endif()
+ if(CMAKEVERSION AND CMAKESONAME)
+ set_target_properties(${LIB_SHARED} PROPERTIES
+ VERSION ${CMAKEVERSION} SOVERSION ${CMAKESONAME})
+ endif()
+
+ target_include_directories(${LIB_SHARED} INTERFACE
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ $<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
+endif()
+
+add_library(${LIB_NAME} ALIAS ${LIB_SELECTED})
+add_library(${PROJECT_NAME}::${LIB_NAME} ALIAS ${LIB_SELECTED})
if(CURL_ENABLE_EXPORT_TARGET)
- install(TARGETS ${LIB_NAME}
- EXPORT ${TARGETS_EXPORT_NAME}
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
- )
+ if(BUILD_STATIC_LIBS)
+ install(TARGETS ${LIB_STATIC}
+ EXPORT ${TARGETS_EXPORT_NAME}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ )
+ endif()
+ if(BUILD_SHARED_LIBS)
+ install(TARGETS ${LIB_SHARED}
+ EXPORT ${TARGETS_EXPORT_NAME}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ )
+ endif()
- export(TARGETS ${LIB_NAME}
+ export(TARGETS ${libcurl_export}
FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
NAMESPACE ${PROJECT_NAME}::
)
diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in
index aced171048..32f1887592 100644
--- a/libs/libcurl/src/Makefile.in
+++ b/libs/libcurl/src/Makefile.in
@@ -154,7 +154,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/curl-amissl.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-nss.m4 \
+ $(top_srcdir)/m4/curl-mbedtls.m4 \
$(top_srcdir)/m4/curl-openssl.m4 \
$(top_srcdir)/m4/curl-override.m4 \
$(top_srcdir)/m4/curl-reentrant.m4 \
@@ -216,69 +216,68 @@ am__libcurl_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \
cf-h2-proxy.c cf-haproxy.c cf-https-connect.c cf-socket.c \
cfilters.c conncache.c connect.c content_encoding.c cookie.c \
curl_addrinfo.c curl_des.c curl_endian.c curl_fnmatch.c \
- curl_get_line.c curl_gethostname.c curl_gssapi.c curl_log.c \
+ curl_get_line.c curl_gethostname.c curl_gssapi.c \
curl_memrchr.c curl_multibyte.c curl_ntlm_core.c \
curl_ntlm_wb.c curl_path.c curl_range.c curl_rtmp.c \
- curl_sasl.c curl_sspi.c curl_threads.c dict.c doh.c dynbuf.c \
- dynhds.c easy.c easygetopt.c easyoptions.c escape.c file.c \
- fileinfo.c fopen.c formdata.c ftp.c ftplistparser.c getenv.c \
- getinfo.c gopher.c hash.c headers.c hmac.c hostasyn.c hostip.c \
- hostip4.c hostip6.c hostsyn.c hsts.c http.c http1.c http2.c \
- http_chunks.c http_digest.c http_negotiate.c http_ntlm.c \
- http_proxy.c http_aws_sigv4.c idn.c if2ip.c imap.c inet_ntop.c \
- inet_pton.c krb5.c ldap.c llist.c macos.c md4.c md5.c \
- memdebug.c mime.c mprintf.c mqtt.c multi.c netrc.c nonblock.c \
- noproxy.c openldap.c parsedate.c pingpong.c pop3.c progress.c \
- psl.c rand.c rename.c rtsp.c select.c sendf.c setopt.c \
- sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \
- socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c \
- strdup.c strerror.c strtok.c strtoofft.c system_win32.c \
- telnet.c tftp.c timediff.c timeval.c transfer.c url.c urlapi.c \
- version.c version_win32.c warnless.c ws.c vauth/cleartext.c \
- vauth/cram.c vauth/digest.c vauth/digest_sspi.c vauth/gsasl.c \
- vauth/krb5_gssapi.c vauth/krb5_sspi.c vauth/ntlm.c \
- vauth/ntlm_sspi.c vauth/oauth2.c vauth/spnego_gssapi.c \
- vauth/spnego_sspi.c vauth/vauth.c vtls/bearssl.c vtls/gskit.c \
- vtls/gtls.c vtls/hostcheck.c vtls/keylog.c vtls/mbedtls.c \
- vtls/mbedtls_threadlock.c vtls/nss.c vtls/openssl.c \
- vtls/rustls.c vtls/schannel.c vtls/schannel_verify.c \
- vtls/sectransp.c vtls/vtls.c vtls/wolfssl.c vtls/x509asn1.c \
- vquic/curl_msh3.c vquic/curl_ngtcp2.c vquic/curl_quiche.c \
- vquic/vquic.c vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c \
- altsvc.h amigaos.h arpa_telnet.h asyn.h bufq.h bufref.h \
- c-hyper.h cf-h1-proxy.h cf-h2-proxy.h cf-haproxy.h \
- cf-https-connect.h cf-socket.h cfilters.h conncache.h \
- connect.h content_encoding.h cookie.h curl_addrinfo.h \
- curl_base64.h curl_ctype.h curl_des.h curl_endian.h \
- curl_fnmatch.h curl_get_line.h curl_gethostname.h \
- curl_gssapi.h curl_hmac.h curl_krb5.h curl_ldap.h curl_log.h \
- curl_md4.h curl_md5.h curl_memory.h curl_memrchr.h \
+ curl_sasl.c curl_sspi.c curl_threads.c curl_trc.c dict.c doh.c \
+ dynbuf.c dynhds.c easy.c easygetopt.c easyoptions.c escape.c \
+ file.c fileinfo.c fopen.c formdata.c ftp.c ftplistparser.c \
+ getenv.c getinfo.c gopher.c hash.c headers.c hmac.c hostasyn.c \
+ hostip.c hostip4.c hostip6.c hostsyn.c hsts.c http.c http1.c \
+ http2.c http_chunks.c http_digest.c http_negotiate.c \
+ http_ntlm.c http_proxy.c http_aws_sigv4.c idn.c if2ip.c imap.c \
+ inet_ntop.c inet_pton.c krb5.c ldap.c llist.c macos.c md4.c \
+ md5.c memdebug.c mime.c mprintf.c mqtt.c multi.c netrc.c \
+ nonblock.c noproxy.c openldap.c parsedate.c pingpong.c pop3.c \
+ progress.c psl.c rand.c rename.c rtsp.c select.c sendf.c \
+ setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c \
+ socks.c socks_gssapi.c socks_sspi.c speedcheck.c splay.c \
+ strcase.c strdup.c strerror.c strtok.c strtoofft.c \
+ system_win32.c telnet.c tftp.c timediff.c timeval.c transfer.c \
+ url.c urlapi.c version.c version_win32.c warnless.c ws.c \
+ vauth/cleartext.c vauth/cram.c vauth/digest.c \
+ vauth/digest_sspi.c vauth/gsasl.c vauth/krb5_gssapi.c \
+ vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c \
+ vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \
+ vauth/vauth.c vtls/bearssl.c vtls/gtls.c vtls/hostcheck.c \
+ vtls/keylog.c vtls/mbedtls.c vtls/mbedtls_threadlock.c \
+ vtls/openssl.c vtls/rustls.c vtls/schannel.c \
+ vtls/schannel_verify.c vtls/sectransp.c vtls/vtls.c \
+ vtls/wolfssl.c vtls/x509asn1.c vquic/curl_msh3.c \
+ vquic/curl_ngtcp2.c vquic/curl_quiche.c vquic/vquic.c \
+ vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c altsvc.h amigaos.h \
+ arpa_telnet.h asyn.h bufq.h bufref.h c-hyper.h cf-h1-proxy.h \
+ cf-h2-proxy.h cf-haproxy.h cf-https-connect.h cf-socket.h \
+ cfilters.h conncache.h connect.h content_encoding.h cookie.h \
+ curl_addrinfo.h curl_base64.h curl_ctype.h curl_des.h \
+ curl_endian.h curl_fnmatch.h curl_get_line.h \
+ curl_gethostname.h curl_gssapi.h curl_hmac.h curl_krb5.h \
+ curl_ldap.h curl_md4.h curl_md5.h curl_memory.h curl_memrchr.h \
curl_multibyte.h curl_ntlm_core.h curl_ntlm_wb.h curl_path.h \
curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h \
curl_setup.h curl_setup_once.h curl_sha256.h curl_sspi.h \
- curl_threads.h curlx.h dict.h doh.h dynbuf.h dynhds.h \
- easy_lock.h easyif.h easyoptions.h escape.h file.h fileinfo.h \
- fopen.h formdata.h functypes.h ftp.h ftplistparser.h getinfo.h \
- gopher.h hash.h headers.h hostip.h hsts.h http.h http1.h \
- http2.h http_chunks.h http_digest.h http_negotiate.h \
- http_ntlm.h http_proxy.h http_aws_sigv4.h idn.h if2ip.h imap.h \
- inet_ntop.h inet_pton.h llist.h macos.h memdebug.h mime.h \
- mqtt.h multihandle.h multiif.h netrc.h nonblock.h noproxy.h \
- parsedate.h pingpong.h pop3.h progress.h psl.h rand.h rename.h \
- rtsp.h select.h sendf.h setopt.h setup-vms.h share.h sigpipe.h \
- slist.h smb.h smtp.h sockaddr.h socketpair.h socks.h \
- speedcheck.h splay.h strcase.h strdup.h strerror.h strtok.h \
- strtoofft.h system_win32.h telnet.h tftp.h timediff.h \
- timeval.h transfer.h url.h urlapi-int.h urldata.h \
+ curl_threads.h curl_trc.h curlx.h dict.h doh.h dynbuf.h \
+ dynhds.h easy_lock.h easyif.h easyoptions.h escape.h file.h \
+ fileinfo.h fopen.h formdata.h functypes.h ftp.h \
+ ftplistparser.h getinfo.h gopher.h hash.h headers.h hostip.h \
+ hsts.h http.h http1.h http2.h http_chunks.h http_digest.h \
+ http_negotiate.h http_ntlm.h http_proxy.h http_aws_sigv4.h \
+ idn.h if2ip.h imap.h inet_ntop.h inet_pton.h llist.h macos.h \
+ memdebug.h mime.h mqtt.h multihandle.h multiif.h netrc.h \
+ nonblock.h noproxy.h parsedate.h pingpong.h pop3.h progress.h \
+ psl.h rand.h rename.h rtsp.h select.h sendf.h setopt.h \
+ setup-vms.h share.h sigpipe.h slist.h smb.h smtp.h sockaddr.h \
+ socketpair.h socks.h speedcheck.h splay.h strcase.h strdup.h \
+ strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h \
+ timediff.h timeval.h transfer.h url.h urlapi-int.h urldata.h \
version_win32.h warnless.h ws.h vauth/digest.h vauth/ntlm.h \
- vauth/vauth.h vtls/bearssl.h vtls/gskit.h vtls/gtls.h \
- vtls/hostcheck.h vtls/keylog.h vtls/mbedtls.h \
- vtls/mbedtls_threadlock.h vtls/nssg.h vtls/openssl.h \
- vtls/rustls.h vtls/schannel.h vtls/schannel_int.h \
- vtls/sectransp.h vtls/vtls.h vtls/vtls_int.h vtls/wolfssl.h \
- vtls/x509asn1.h vquic/curl_msh3.h vquic/curl_ngtcp2.h \
- vquic/curl_quiche.h vquic/vquic.h vquic/vquic_int.h vssh/ssh.h \
- libcurl.rc
+ vauth/vauth.h vtls/bearssl.h vtls/gtls.h vtls/hostcheck.h \
+ vtls/keylog.h vtls/mbedtls.h vtls/mbedtls_threadlock.h \
+ vtls/openssl.h vtls/rustls.h vtls/schannel.h \
+ vtls/schannel_int.h vtls/sectransp.h vtls/vtls.h \
+ vtls/vtls_int.h vtls/wolfssl.h vtls/x509asn1.h \
+ vquic/curl_msh3.h vquic/curl_ngtcp2.h vquic/curl_quiche.h \
+ vquic/vquic.h vquic/vquic_int.h vssh/ssh.h libcurl.rc
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-bufq.lo libcurl_la-bufref.lo \
@@ -291,17 +290,16 @@ am__objects_1 = libcurl_la-altsvc.lo libcurl_la-amigaos.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_log.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-dynbuf.lo libcurl_la-dynhds.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-fopen.lo \
- libcurl_la-formdata.lo libcurl_la-ftp.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-curl_trc.lo libcurl_la-dict.lo libcurl_la-doh.lo \
+ libcurl_la-dynbuf.lo libcurl_la-dynhds.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-fopen.lo libcurl_la-formdata.lo libcurl_la-ftp.lo \
libcurl_la-ftplistparser.lo libcurl_la-getenv.lo \
libcurl_la-getinfo.lo libcurl_la-gopher.lo libcurl_la-hash.lo \
libcurl_la-headers.lo libcurl_la-hmac.lo \
@@ -344,10 +342,10 @@ am__objects_2 = vauth/libcurl_la-cleartext.lo vauth/libcurl_la-cram.lo \
vauth/libcurl_la-ntlm_sspi.lo vauth/libcurl_la-oauth2.lo \
vauth/libcurl_la-spnego_gssapi.lo \
vauth/libcurl_la-spnego_sspi.lo vauth/libcurl_la-vauth.lo
-am__objects_3 = vtls/libcurl_la-bearssl.lo vtls/libcurl_la-gskit.lo \
- vtls/libcurl_la-gtls.lo vtls/libcurl_la-hostcheck.lo \
- vtls/libcurl_la-keylog.lo vtls/libcurl_la-mbedtls.lo \
- vtls/libcurl_la-mbedtls_threadlock.lo vtls/libcurl_la-nss.lo \
+am__objects_3 = vtls/libcurl_la-bearssl.lo vtls/libcurl_la-gtls.lo \
+ vtls/libcurl_la-hostcheck.lo vtls/libcurl_la-keylog.lo \
+ vtls/libcurl_la-mbedtls.lo \
+ vtls/libcurl_la-mbedtls_threadlock.lo \
vtls/libcurl_la-openssl.lo vtls/libcurl_la-rustls.lo \
vtls/libcurl_la-schannel.lo vtls/libcurl_la-schannel_verify.lo \
vtls/libcurl_la-sectransp.lo vtls/libcurl_la-vtls.lo \
@@ -387,12 +385,12 @@ am__objects_11 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \
libcurlu_la-curl_addrinfo.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_log.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-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-curl_trc.lo \
libcurlu_la-dict.lo libcurlu_la-doh.lo libcurlu_la-dynbuf.lo \
libcurlu_la-dynhds.lo libcurlu_la-easy.lo \
libcurlu_la-easygetopt.lo libcurlu_la-easyoptions.lo \
@@ -444,10 +442,10 @@ am__objects_12 = vauth/libcurlu_la-cleartext.lo \
vauth/libcurlu_la-ntlm_sspi.lo vauth/libcurlu_la-oauth2.lo \
vauth/libcurlu_la-spnego_gssapi.lo \
vauth/libcurlu_la-spnego_sspi.lo vauth/libcurlu_la-vauth.lo
-am__objects_13 = vtls/libcurlu_la-bearssl.lo vtls/libcurlu_la-gskit.lo \
- vtls/libcurlu_la-gtls.lo vtls/libcurlu_la-hostcheck.lo \
- vtls/libcurlu_la-keylog.lo vtls/libcurlu_la-mbedtls.lo \
- vtls/libcurlu_la-mbedtls_threadlock.lo vtls/libcurlu_la-nss.lo \
+am__objects_13 = vtls/libcurlu_la-bearssl.lo vtls/libcurlu_la-gtls.lo \
+ vtls/libcurlu_la-hostcheck.lo vtls/libcurlu_la-keylog.lo \
+ vtls/libcurlu_la-mbedtls.lo \
+ vtls/libcurlu_la-mbedtls_threadlock.lo \
vtls/libcurlu_la-openssl.lo vtls/libcurlu_la-rustls.lo \
vtls/libcurlu_la-schannel.lo \
vtls/libcurlu_la-schannel_verify.lo \
@@ -506,7 +504,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurl_la-curl_get_line.Plo \
./$(DEPDIR)/libcurl_la-curl_gethostname.Plo \
./$(DEPDIR)/libcurl_la-curl_gssapi.Plo \
- ./$(DEPDIR)/libcurl_la-curl_log.Plo \
./$(DEPDIR)/libcurl_la-curl_memrchr.Plo \
./$(DEPDIR)/libcurl_la-curl_multibyte.Plo \
./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo \
@@ -517,6 +514,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurl_la-curl_sasl.Plo \
./$(DEPDIR)/libcurl_la-curl_sspi.Plo \
./$(DEPDIR)/libcurl_la-curl_threads.Plo \
+ ./$(DEPDIR)/libcurl_la-curl_trc.Plo \
./$(DEPDIR)/libcurl_la-dict.Plo ./$(DEPDIR)/libcurl_la-doh.Plo \
./$(DEPDIR)/libcurl_la-dynbuf.Plo \
./$(DEPDIR)/libcurl_la-dynhds.Plo \
@@ -632,7 +630,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurlu_la-curl_get_line.Plo \
./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo \
./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo \
- ./$(DEPDIR)/libcurlu_la-curl_log.Plo \
./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo \
./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo \
./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo \
@@ -643,6 +640,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurlu_la-curl_sasl.Plo \
./$(DEPDIR)/libcurlu_la-curl_sspi.Plo \
./$(DEPDIR)/libcurlu_la-curl_threads.Plo \
+ ./$(DEPDIR)/libcurlu_la-curl_trc.Plo \
./$(DEPDIR)/libcurlu_la-dict.Plo \
./$(DEPDIR)/libcurlu_la-doh.Plo \
./$(DEPDIR)/libcurlu_la-dynbuf.Plo \
@@ -778,13 +776,11 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
vssh/$(DEPDIR)/libcurlu_la-libssh2.Plo \
vssh/$(DEPDIR)/libcurlu_la-wolfssh.Plo \
vtls/$(DEPDIR)/libcurl_la-bearssl.Plo \
- vtls/$(DEPDIR)/libcurl_la-gskit.Plo \
vtls/$(DEPDIR)/libcurl_la-gtls.Plo \
vtls/$(DEPDIR)/libcurl_la-hostcheck.Plo \
vtls/$(DEPDIR)/libcurl_la-keylog.Plo \
vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo \
vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Plo \
- vtls/$(DEPDIR)/libcurl_la-nss.Plo \
vtls/$(DEPDIR)/libcurl_la-openssl.Plo \
vtls/$(DEPDIR)/libcurl_la-rustls.Plo \
vtls/$(DEPDIR)/libcurl_la-schannel.Plo \
@@ -794,13 +790,11 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo \
vtls/$(DEPDIR)/libcurl_la-x509asn1.Plo \
vtls/$(DEPDIR)/libcurlu_la-bearssl.Plo \
- vtls/$(DEPDIR)/libcurlu_la-gskit.Plo \
vtls/$(DEPDIR)/libcurlu_la-gtls.Plo \
vtls/$(DEPDIR)/libcurlu_la-hostcheck.Plo \
vtls/$(DEPDIR)/libcurlu_la-keylog.Plo \
vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo \
vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Plo \
- vtls/$(DEPDIR)/libcurlu_la-nss.Plo \
vtls/$(DEPDIR)/libcurlu_la-openssl.Plo \
vtls/$(DEPDIR)/libcurlu_la-rustls.Plo \
vtls/$(DEPDIR)/libcurlu_la-schannel.Plo \
@@ -966,7 +960,6 @@ MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
NROFF = @NROFF@
-NSS_LIBS = @NSS_LIBS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
@@ -1013,7 +1006,6 @@ USE_NGTCP2 = @USE_NGTCP2@
USE_NGTCP2_CRYPTO_GNUTLS = @USE_NGTCP2_CRYPTO_GNUTLS@
USE_NGTCP2_CRYPTO_QUICTLS = @USE_NGTCP2_CRYPTO_QUICTLS@
USE_NGTCP2_CRYPTO_WOLFSSL = @USE_NGTCP2_CRYPTO_WOLFSSL@
-USE_NSS = @USE_NSS@
USE_OPENLDAP = @USE_OPENLDAP@
USE_QUICHE = @USE_QUICHE@
USE_RUSTLS = @USE_RUSTLS@
@@ -1160,13 +1152,11 @@ LIB_VAUTH_HFILES = \
LIB_VTLS_CFILES = \
vtls/bearssl.c \
- vtls/gskit.c \
vtls/gtls.c \
vtls/hostcheck.c \
vtls/keylog.c \
vtls/mbedtls.c \
vtls/mbedtls_threadlock.c \
- vtls/nss.c \
vtls/openssl.c \
vtls/rustls.c \
vtls/schannel.c \
@@ -1178,13 +1168,11 @@ LIB_VTLS_CFILES = \
LIB_VTLS_HFILES = \
vtls/bearssl.h \
- vtls/gskit.h \
vtls/gtls.h \
vtls/hostcheck.h \
vtls/keylog.h \
vtls/mbedtls.h \
vtls/mbedtls_threadlock.h \
- vtls/nssg.h \
vtls/openssl.h \
vtls/rustls.h \
vtls/schannel.h \
@@ -1242,7 +1230,6 @@ LIB_CFILES = \
curl_get_line.c \
curl_gethostname.c \
curl_gssapi.c \
- curl_log.c \
curl_memrchr.c \
curl_multibyte.c \
curl_ntlm_core.c \
@@ -1253,6 +1240,7 @@ LIB_CFILES = \
curl_sasl.c \
curl_sspi.c \
curl_threads.c \
+ curl_trc.c \
dict.c \
doh.c \
dynbuf.c \
@@ -1378,7 +1366,6 @@ LIB_HFILES = \
curl_hmac.h \
curl_krb5.h \
curl_ldap.h \
- curl_log.h \
curl_md4.h \
curl_md5.h \
curl_memory.h \
@@ -1396,6 +1383,7 @@ LIB_HFILES = \
curl_sha256.h \
curl_sspi.h \
curl_threads.h \
+ curl_trc.h \
curlx.h \
dict.h \
doh.h \
@@ -1651,8 +1639,6 @@ vtls/$(DEPDIR)/$(am__dirstamp):
@: > vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-bearssl.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
-vtls/libcurl_la-gskit.lo: vtls/$(am__dirstamp) \
- vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-gtls.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-hostcheck.lo: vtls/$(am__dirstamp) \
@@ -1663,8 +1649,6 @@ vtls/libcurl_la-mbedtls.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-mbedtls_threadlock.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
-vtls/libcurl_la-nss.lo: vtls/$(am__dirstamp) \
- vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-openssl.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurl_la-rustls.lo: vtls/$(am__dirstamp) \
@@ -1738,8 +1722,6 @@ vauth/libcurlu_la-vauth.lo: vauth/$(am__dirstamp) \
vauth/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-bearssl.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
-vtls/libcurlu_la-gskit.lo: vtls/$(am__dirstamp) \
- vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-gtls.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-hostcheck.lo: vtls/$(am__dirstamp) \
@@ -1750,8 +1732,6 @@ vtls/libcurlu_la-mbedtls.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-mbedtls_threadlock.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
-vtls/libcurlu_la-nss.lo: vtls/$(am__dirstamp) \
- vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-openssl.lo: vtls/$(am__dirstamp) \
vtls/$(DEPDIR)/$(am__dirstamp)
vtls/libcurlu_la-rustls.lo: vtls/$(am__dirstamp) \
@@ -1825,7 +1805,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_get_line.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_gethostname.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_gssapi.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_log.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_memrchr.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_multibyte.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo@am__quote@ # am--include-marker
@@ -1836,6 +1815,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_sasl.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_sspi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_threads.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_trc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-dict.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-doh.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-dynbuf.Plo@am__quote@ # am--include-marker
@@ -1955,7 +1935,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_get_line.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_log.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo@am__quote@ # am--include-marker
@@ -1966,6 +1945,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_sasl.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_sspi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_threads.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_trc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-dict.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-doh.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-dynbuf.Plo@am__quote@ # am--include-marker
@@ -2101,13 +2081,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@vssh/$(DEPDIR)/libcurlu_la-libssh2.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vssh/$(DEPDIR)/libcurlu_la-wolfssh.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-bearssl.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-gskit.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-gtls.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-hostcheck.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-keylog.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-nss.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-openssl.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-rustls.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-schannel.Plo@am__quote@ # am--include-marker
@@ -2117,13 +2095,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-x509asn1.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-bearssl.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-gskit.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-gtls.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-hostcheck.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-keylog.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-nss.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-openssl.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-rustls.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-schannel.Plo@am__quote@ # am--include-marker
@@ -2338,13 +2314,6 @@ libcurl_la-curl_gssapi.lo: curl_gssapi.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-curl_gssapi.lo `test -f 'curl_gssapi.c' || echo '$(srcdir)/'`curl_gssapi.c
-libcurl_la-curl_log.lo: curl_log.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-curl_log.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_log.Tpo -c -o libcurl_la-curl_log.lo `test -f 'curl_log.c' || echo '$(srcdir)/'`curl_log.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_log.Tpo $(DEPDIR)/libcurl_la-curl_log.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_log.c' object='libcurl_la-curl_log.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-curl_log.lo `test -f 'curl_log.c' || echo '$(srcdir)/'`curl_log.c
-
libcurl_la-curl_memrchr.lo: curl_memrchr.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-curl_memrchr.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_memrchr.Tpo -c -o libcurl_la-curl_memrchr.lo `test -f 'curl_memrchr.c' || echo '$(srcdir)/'`curl_memrchr.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_memrchr.Tpo $(DEPDIR)/libcurl_la-curl_memrchr.Plo
@@ -2415,6 +2384,13 @@ libcurl_la-curl_threads.lo: curl_threads.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-curl_threads.lo `test -f 'curl_threads.c' || echo '$(srcdir)/'`curl_threads.c
+libcurl_la-curl_trc.lo: curl_trc.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-curl_trc.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_trc.Tpo -c -o libcurl_la-curl_trc.lo `test -f 'curl_trc.c' || echo '$(srcdir)/'`curl_trc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_trc.Tpo $(DEPDIR)/libcurl_la-curl_trc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_trc.c' object='libcurl_la-curl_trc.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-curl_trc.lo `test -f 'curl_trc.c' || echo '$(srcdir)/'`curl_trc.c
+
libcurl_la-dict.lo: dict.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-dict.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dict.Tpo -c -o libcurl_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dict.Tpo $(DEPDIR)/libcurl_la-dict.Plo
@@ -3171,13 +3147,6 @@ vtls/libcurl_la-bearssl.lo: vtls/bearssl.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 vtls/libcurl_la-bearssl.lo `test -f 'vtls/bearssl.c' || echo '$(srcdir)/'`vtls/bearssl.c
-vtls/libcurl_la-gskit.lo: vtls/gskit.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 vtls/libcurl_la-gskit.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-gskit.Tpo -c -o vtls/libcurl_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-gskit.Tpo vtls/$(DEPDIR)/libcurl_la-gskit.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/gskit.c' object='vtls/libcurl_la-gskit.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 vtls/libcurl_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c
-
vtls/libcurl_la-gtls.lo: vtls/gtls.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 vtls/libcurl_la-gtls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-gtls.Tpo -c -o vtls/libcurl_la-gtls.lo `test -f 'vtls/gtls.c' || echo '$(srcdir)/'`vtls/gtls.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-gtls.Tpo vtls/$(DEPDIR)/libcurl_la-gtls.Plo
@@ -3213,13 +3182,6 @@ vtls/libcurl_la-mbedtls_threadlock.lo: vtls/mbedtls_threadlock.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 vtls/libcurl_la-mbedtls_threadlock.lo `test -f 'vtls/mbedtls_threadlock.c' || echo '$(srcdir)/'`vtls/mbedtls_threadlock.c
-vtls/libcurl_la-nss.lo: vtls/nss.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 vtls/libcurl_la-nss.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-nss.Tpo -c -o vtls/libcurl_la-nss.lo `test -f 'vtls/nss.c' || echo '$(srcdir)/'`vtls/nss.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-nss.Tpo vtls/$(DEPDIR)/libcurl_la-nss.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/nss.c' object='vtls/libcurl_la-nss.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 vtls/libcurl_la-nss.lo `test -f 'vtls/nss.c' || echo '$(srcdir)/'`vtls/nss.c
-
vtls/libcurl_la-openssl.lo: vtls/openssl.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 vtls/libcurl_la-openssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-openssl.Tpo -c -o vtls/libcurl_la-openssl.lo `test -f 'vtls/openssl.c' || echo '$(srcdir)/'`vtls/openssl.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-openssl.Tpo vtls/$(DEPDIR)/libcurl_la-openssl.Plo
@@ -3500,13 +3462,6 @@ libcurlu_la-curl_gssapi.lo: curl_gssapi.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-curl_gssapi.lo `test -f 'curl_gssapi.c' || echo '$(srcdir)/'`curl_gssapi.c
-libcurlu_la-curl_log.lo: curl_log.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-curl_log.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_log.Tpo -c -o libcurlu_la-curl_log.lo `test -f 'curl_log.c' || echo '$(srcdir)/'`curl_log.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_log.Tpo $(DEPDIR)/libcurlu_la-curl_log.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_log.c' object='libcurlu_la-curl_log.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-curl_log.lo `test -f 'curl_log.c' || echo '$(srcdir)/'`curl_log.c
-
libcurlu_la-curl_memrchr.lo: curl_memrchr.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-curl_memrchr.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_memrchr.Tpo -c -o libcurlu_la-curl_memrchr.lo `test -f 'curl_memrchr.c' || echo '$(srcdir)/'`curl_memrchr.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_memrchr.Tpo $(DEPDIR)/libcurlu_la-curl_memrchr.Plo
@@ -3577,6 +3532,13 @@ libcurlu_la-curl_threads.lo: curl_threads.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-curl_threads.lo `test -f 'curl_threads.c' || echo '$(srcdir)/'`curl_threads.c
+libcurlu_la-curl_trc.lo: curl_trc.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-curl_trc.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_trc.Tpo -c -o libcurlu_la-curl_trc.lo `test -f 'curl_trc.c' || echo '$(srcdir)/'`curl_trc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_trc.Tpo $(DEPDIR)/libcurlu_la-curl_trc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_trc.c' object='libcurlu_la-curl_trc.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-curl_trc.lo `test -f 'curl_trc.c' || echo '$(srcdir)/'`curl_trc.c
+
libcurlu_la-dict.lo: dict.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-dict.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dict.Tpo -c -o libcurlu_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dict.Tpo $(DEPDIR)/libcurlu_la-dict.Plo
@@ -4333,13 +4295,6 @@ vtls/libcurlu_la-bearssl.lo: vtls/bearssl.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 vtls/libcurlu_la-bearssl.lo `test -f 'vtls/bearssl.c' || echo '$(srcdir)/'`vtls/bearssl.c
-vtls/libcurlu_la-gskit.lo: vtls/gskit.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 vtls/libcurlu_la-gskit.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-gskit.Tpo -c -o vtls/libcurlu_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-gskit.Tpo vtls/$(DEPDIR)/libcurlu_la-gskit.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/gskit.c' object='vtls/libcurlu_la-gskit.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 vtls/libcurlu_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c
-
vtls/libcurlu_la-gtls.lo: vtls/gtls.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 vtls/libcurlu_la-gtls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-gtls.Tpo -c -o vtls/libcurlu_la-gtls.lo `test -f 'vtls/gtls.c' || echo '$(srcdir)/'`vtls/gtls.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-gtls.Tpo vtls/$(DEPDIR)/libcurlu_la-gtls.Plo
@@ -4375,13 +4330,6 @@ vtls/libcurlu_la-mbedtls_threadlock.lo: vtls/mbedtls_threadlock.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 vtls/libcurlu_la-mbedtls_threadlock.lo `test -f 'vtls/mbedtls_threadlock.c' || echo '$(srcdir)/'`vtls/mbedtls_threadlock.c
-vtls/libcurlu_la-nss.lo: vtls/nss.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 vtls/libcurlu_la-nss.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-nss.Tpo -c -o vtls/libcurlu_la-nss.lo `test -f 'vtls/nss.c' || echo '$(srcdir)/'`vtls/nss.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-nss.Tpo vtls/$(DEPDIR)/libcurlu_la-nss.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/nss.c' object='vtls/libcurlu_la-nss.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 vtls/libcurlu_la-nss.lo `test -f 'vtls/nss.c' || echo '$(srcdir)/'`vtls/nss.c
-
vtls/libcurlu_la-openssl.lo: vtls/openssl.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 vtls/libcurlu_la-openssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-openssl.Tpo -c -o vtls/libcurlu_la-openssl.lo `test -f 'vtls/openssl.c' || echo '$(srcdir)/'`vtls/openssl.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-openssl.Tpo vtls/$(DEPDIR)/libcurlu_la-openssl.Plo
@@ -4658,7 +4606,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurl_la-curl_get_line.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_gethostname.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_gssapi.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-curl_log.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_memrchr.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_multibyte.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo
@@ -4669,6 +4616,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurl_la-curl_sasl.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_sspi.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_threads.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-curl_trc.Plo
-rm -f ./$(DEPDIR)/libcurl_la-dict.Plo
-rm -f ./$(DEPDIR)/libcurl_la-doh.Plo
-rm -f ./$(DEPDIR)/libcurl_la-dynbuf.Plo
@@ -4788,7 +4736,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurlu_la-curl_get_line.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-curl_log.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo
@@ -4799,6 +4746,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurlu_la-curl_sasl.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_sspi.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_threads.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-curl_trc.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-dict.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-doh.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-dynbuf.Plo
@@ -4934,13 +4882,11 @@ distclean: distclean-am
-rm -f vssh/$(DEPDIR)/libcurlu_la-libssh2.Plo
-rm -f vssh/$(DEPDIR)/libcurlu_la-wolfssh.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-bearssl.Plo
- -rm -f vtls/$(DEPDIR)/libcurl_la-gskit.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-gtls.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-hostcheck.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-keylog.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Plo
- -rm -f vtls/$(DEPDIR)/libcurl_la-nss.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-openssl.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-rustls.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-schannel.Plo
@@ -4950,13 +4896,11 @@ distclean: distclean-am
-rm -f vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-x509asn1.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-bearssl.Plo
- -rm -f vtls/$(DEPDIR)/libcurlu_la-gskit.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-gtls.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-hostcheck.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-keylog.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Plo
- -rm -f vtls/$(DEPDIR)/libcurlu_la-nss.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-openssl.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-rustls.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-schannel.Plo
@@ -5035,7 +4979,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurl_la-curl_get_line.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_gethostname.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_gssapi.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-curl_log.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_memrchr.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_multibyte.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo
@@ -5046,6 +4989,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurl_la-curl_sasl.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_sspi.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_threads.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-curl_trc.Plo
-rm -f ./$(DEPDIR)/libcurl_la-dict.Plo
-rm -f ./$(DEPDIR)/libcurl_la-doh.Plo
-rm -f ./$(DEPDIR)/libcurl_la-dynbuf.Plo
@@ -5165,7 +5109,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurlu_la-curl_get_line.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-curl_log.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo
@@ -5176,6 +5119,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurlu_la-curl_sasl.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_sspi.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_threads.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-curl_trc.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-dict.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-doh.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-dynbuf.Plo
@@ -5311,13 +5255,11 @@ maintainer-clean: maintainer-clean-am
-rm -f vssh/$(DEPDIR)/libcurlu_la-libssh2.Plo
-rm -f vssh/$(DEPDIR)/libcurlu_la-wolfssh.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-bearssl.Plo
- -rm -f vtls/$(DEPDIR)/libcurl_la-gskit.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-gtls.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-hostcheck.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-keylog.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-mbedtls_threadlock.Plo
- -rm -f vtls/$(DEPDIR)/libcurl_la-nss.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-openssl.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-rustls.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-schannel.Plo
@@ -5327,13 +5269,11 @@ maintainer-clean: maintainer-clean-am
-rm -f vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo
-rm -f vtls/$(DEPDIR)/libcurl_la-x509asn1.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-bearssl.Plo
- -rm -f vtls/$(DEPDIR)/libcurlu_la-gskit.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-gtls.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-hostcheck.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-keylog.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls_threadlock.Plo
- -rm -f vtls/$(DEPDIR)/libcurlu_la-nss.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-openssl.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-rustls.Plo
-rm -f vtls/$(DEPDIR)/libcurlu_la-schannel.Plo
diff --git a/libs/libcurl/src/Makefile.inc b/libs/libcurl/src/Makefile.inc
index 996a2b8cae..ee4ba45b4b 100644
--- a/libs/libcurl/src/Makefile.inc
+++ b/libs/libcurl/src/Makefile.inc
@@ -44,13 +44,11 @@ LIB_VAUTH_HFILES = \
LIB_VTLS_CFILES = \
vtls/bearssl.c \
- vtls/gskit.c \
vtls/gtls.c \
vtls/hostcheck.c \
vtls/keylog.c \
vtls/mbedtls.c \
vtls/mbedtls_threadlock.c \
- vtls/nss.c \
vtls/openssl.c \
vtls/rustls.c \
vtls/schannel.c \
@@ -62,13 +60,11 @@ LIB_VTLS_CFILES = \
LIB_VTLS_HFILES = \
vtls/bearssl.h \
- vtls/gskit.h \
vtls/gtls.h \
vtls/hostcheck.h \
vtls/keylog.h \
vtls/mbedtls.h \
vtls/mbedtls_threadlock.h \
- vtls/nssg.h \
vtls/openssl.h \
vtls/rustls.h \
vtls/schannel.h \
@@ -126,7 +122,6 @@ LIB_CFILES = \
curl_get_line.c \
curl_gethostname.c \
curl_gssapi.c \
- curl_log.c \
curl_memrchr.c \
curl_multibyte.c \
curl_ntlm_core.c \
@@ -137,6 +132,7 @@ LIB_CFILES = \
curl_sasl.c \
curl_sspi.c \
curl_threads.c \
+ curl_trc.c \
dict.c \
doh.c \
dynbuf.c \
@@ -262,7 +258,6 @@ LIB_HFILES = \
curl_hmac.h \
curl_krb5.h \
curl_ldap.h \
- curl_log.h \
curl_md4.h \
curl_md5.h \
curl_memory.h \
@@ -280,6 +275,7 @@ LIB_HFILES = \
curl_sha256.h \
curl_sspi.h \
curl_threads.h \
+ curl_trc.h \
curlx.h \
dict.h \
doh.h \
diff --git a/libs/libcurl/src/altsvc.c b/libs/libcurl/src/altsvc.c
index 724bf17cd8..ce2324a3d0 100644
--- a/libs/libcurl/src/altsvc.c
+++ b/libs/libcurl/src/altsvc.c
@@ -38,6 +38,8 @@
#include "warnless.h"
#include "fopen.h"
#include "rename.h"
+#include "strdup.h"
+#include "inet_pton.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -97,19 +99,39 @@ static struct altsvc *altsvc_createid(const char *srchost,
{
struct altsvc *as = calloc(sizeof(struct altsvc), 1);
size_t hlen;
+ size_t dlen;
if(!as)
return NULL;
hlen = strlen(srchost);
+ dlen = strlen(dsthost);
DEBUGASSERT(hlen);
- as->src.host = strdup(srchost);
+ DEBUGASSERT(dlen);
+ if(!hlen || !dlen)
+ /* bad input */
+ return NULL;
+ if((hlen > 2) && srchost[0] == '[') {
+ /* IPv6 address, strip off brackets */
+ srchost++;
+ hlen -= 2;
+ }
+ else if(srchost[hlen - 1] == '.')
+ /* strip off trailing dot */
+ hlen--;
+ if((dlen > 2) && dsthost[0] == '[') {
+ /* IPv6 address, strip off brackets */
+ dsthost++;
+ dlen -= 2;
+ }
+
+ as->src.host = Curl_memdup(srchost, hlen + 1);
if(!as->src.host)
goto error;
- if(hlen && (srchost[hlen - 1] == '.'))
- /* strip off trailing any dot */
- as->src.host[--hlen] = 0;
- as->dst.host = strdup(dsthost);
+ as->src.host[hlen] = 0;
+
+ as->dst.host = Curl_memdup(dsthost, dlen + 1);
if(!as->dst.host)
goto error;
+ as->dst.host[dlen] = 0;
as->src.alpnid = srcalpnid;
as->dst.alpnid = dstalpnid;
@@ -231,18 +253,40 @@ fail:
static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
{
struct tm stamp;
+ const char *dst6_pre = "";
+ const char *dst6_post = "";
+ const char *src6_pre = "";
+ const char *src6_post = "";
CURLcode result = Curl_gmtime(as->expires, &stamp);
if(result)
return result;
-
+#ifdef ENABLE_IPV6
+ else {
+ char ipv6_unused[16];
+ if(1 == Curl_inet_pton(AF_INET6, as->dst.host, ipv6_unused)) {
+ dst6_pre = "[";
+ dst6_post = "]";
+ }
+ if(1 == Curl_inet_pton(AF_INET6, as->src.host, ipv6_unused)) {
+ src6_pre = "[";
+ src6_post = "]";
+ }
+ }
+#endif
fprintf(fp,
- "%s %s %u "
- "%s %s %u "
+ "%s %s%s%s %u "
+ "%s %s%s%s %u "
"\"%d%02d%02d "
"%02d:%02d:%02d\" "
"%u %d\n",
- Curl_alpnid2str(as->src.alpnid), as->src.host, as->src.port,
- Curl_alpnid2str(as->dst.alpnid), as->dst.host, as->dst.port,
+ Curl_alpnid2str(as->src.alpnid),
+ src6_pre, as->src.host, src6_post,
+ as->src.port,
+
+ Curl_alpnid2str(as->dst.alpnid),
+ dst6_pre, as->dst.host, dst6_post,
+ as->dst.port,
+
stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
stamp.tm_hour, stamp.tm_min, stamp.tm_sec,
as->persist, as->prio);
@@ -500,9 +544,21 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
if(*p != ':') {
/* host name starts here */
const char *hostp = p;
- while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
- p++;
- len = p - hostp;
+ if(*p == '[') {
+ /* pass all valid IPv6 letters - does not handle zone id */
+ len = strspn(++p, "0123456789abcdefABCDEF:.");
+ if(p[len] != ']')
+ /* invalid host syntax, bail out */
+ break;
+ /* we store the IPv6 numerical address *with* brackets */
+ len += 2;
+ p = &p[len-1];
+ }
+ else {
+ while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
+ p++;
+ len = p - hostp;
+ }
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
infof(data, "Excessive alt-svc host name, ignoring.");
valid = FALSE;
diff --git a/libs/libcurl/src/amigaos.h b/libs/libcurl/src/amigaos.h
index e094d40d20..4ef364eeb1 100644
--- a/libs/libcurl/src/amigaos.h
+++ b/libs/libcurl/src/amigaos.h
@@ -39,4 +39,3 @@ void Curl_amiga_cleanup(void);
#endif
#endif /* HEADER_CURL_AMIGAOS_H */
-
diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c
index cb2412aca3..ffb4ecd367 100644
--- a/libs/libcurl/src/asyn-ares.c
+++ b/libs/libcurl/src/asyn-ares.c
@@ -110,7 +110,7 @@ struct thread_data {
};
/* How long we are willing to wait for additional parallel responses after
- obtaining a "definitive" one.
+ obtaining a "definitive" one. For old c-ares without getaddrinfo.
This is intended to equal the c-ares default timeout. cURL always uses that
default value. Unfortunately, c-ares doesn't expose its default timeout in
@@ -120,6 +120,8 @@ struct thread_data {
*/
#define HAPPY_EYEBALLS_DNS_TIMEOUT 5000
+#define CARES_TIMEOUT_PER_ATTEMPT 2000
+
/*
* Curl_resolver_global_init() - the generic low-level asynchronous name
* resolve API. Called from curl_global_init() to initialize global resolver
@@ -173,6 +175,9 @@ CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
int optmask = ARES_OPT_SOCK_STATE_CB;
options.sock_state_cb = sock_state_cb;
options.sock_state_cb_data = easy;
+ options.timeout = CARES_TIMEOUT_PER_ATTEMPT;
+ optmask |= ARES_OPT_TIMEOUTMS;
+
status = ares_init_options((ares_channel*)resolver, &options, optmask);
if(status != ARES_SUCCESS) {
if(status == ARES_ENOMEM)
@@ -770,9 +775,14 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
int pf = PF_INET;
memset(&hints, 0, sizeof(hints));
#ifdef CURLRES_IPV6
- if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) &&
+ Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
- pf = PF_UNSPEC;
+ if(data->conn->ip_version == CURL_IPRESOLVE_V6)
+ pf = PF_INET6;
+ else
+ pf = PF_UNSPEC;
+ }
#endif /* CURLRES_IPV6 */
hints.ai_family = pf;
hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c
index 8a2628f6b7..5019fa44d9 100644
--- a/libs/libcurl/src/asyn-thread.c
+++ b/libs/libcurl/src/asyn-thread.c
@@ -696,9 +696,13 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
*waitp = 0; /* default to synchronous response */
#ifdef CURLRES_IPV6
- if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
- pf = PF_UNSPEC;
+ if(data->conn->ip_version == CURL_IPRESOLVE_V6)
+ pf = PF_INET6;
+ else
+ pf = PF_UNSPEC;
+ }
#endif /* CURLRES_IPV6 */
memset(&hints, 0, sizeof(hints));
diff --git a/libs/libcurl/src/base64.c b/libs/libcurl/src/base64.c
index 7e5531e737..5223b86c58 100644
--- a/libs/libcurl/src/base64.c
+++ b/libs/libcurl/src/base64.c
@@ -32,13 +32,14 @@
!defined(CURL_DISABLE_POP3) || \
!defined(CURL_DISABLE_IMAP) || \
!defined(CURL_DISABLE_DOH) || defined(USE_SSL)
-
-#include "urldata.h" /* for the Curl_easy definition */
+#include "curl/curl.h"
#include "warnless.h"
#include "curl_base64.h"
/* The last 2 #include files should be in this order */
+#ifdef BUILDING_LIBCURL
#include "curl_memory.h"
+#endif
#include "memdebug.h"
/* ---- Base64 Encoding/Decoding Table --- */
diff --git a/libs/libcurl/src/c-hyper.c b/libs/libcurl/src/c-hyper.c
index ea8d2248f3..6f3eb794f7 100644
--- a/libs/libcurl/src/c-hyper.c
+++ b/libs/libcurl/src/c-hyper.c
@@ -61,6 +61,11 @@
#include "curl_memory.h"
#include "memdebug.h"
+typedef enum {
+ USERDATA_NOT_SET = 0, /* for tasks with no userdata set; must be zero */
+ USERDATA_RESP_BODY
+} userdata_t;
+
size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
uint8_t *buf, size_t buflen)
{
@@ -182,8 +187,11 @@ static int hyper_each_header(void *userdata,
}
}
- data->info.header_size += (curl_off_t)len;
- data->req.headerbytecount += (curl_off_t)len;
+ result = Curl_bump_headersize(data, len, FALSE);
+ if(result) {
+ data->state.hresult = result;
+ return HYPER_ITER_BREAK;
+ }
return HYPER_ITER_CONTINUE;
}
@@ -313,9 +321,8 @@ static CURLcode status_line(struct Curl_easy *data,
if(result)
return result;
}
- data->info.header_size += (curl_off_t)len;
- data->req.headerbytecount += (curl_off_t)len;
- return CURLE_OK;
+ result = Curl_bump_headersize(data, len, FALSE);
+ return result;
}
/*
@@ -348,7 +355,6 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
struct hyptransfer *h = &data->hyp;
hyper_task *task;
hyper_task *foreach;
- hyper_error *hypererr = NULL;
const uint8_t *reasonp;
size_t reason_len;
CURLcode result = CURLE_OK;
@@ -391,19 +397,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
break;
}
t = hyper_task_type(task);
- switch(t) {
- case HYPER_TASK_ERROR:
- hypererr = hyper_task_value(task);
- break;
- case HYPER_TASK_RESPONSE:
- resp = hyper_task_value(task);
- break;
- default:
- break;
- }
- hyper_task_free(task);
-
if(t == HYPER_TASK_ERROR) {
+ hyper_error *hypererr = hyper_task_value(task);
+ hyper_task_free(task);
if(data->state.hresult) {
/* override Hyper's view, might not even be an error */
result = data->state.hresult;
@@ -414,36 +410,55 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
hyper_code code = hyper_error_code(hypererr);
failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
- if(code == HYPERE_ABORTED_BY_CALLBACK)
+ switch(code) {
+ case HYPERE_ABORTED_BY_CALLBACK:
result = CURLE_OK;
- else if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount)
- result = CURLE_GOT_NOTHING;
- else if(code == HYPERE_INVALID_PEER_MESSAGE)
+ break;
+ case HYPERE_UNEXPECTED_EOF:
+ if(!data->req.bytecount)
+ result = CURLE_GOT_NOTHING;
+ else
+ result = CURLE_RECV_ERROR;
+ break;
+ case HYPERE_INVALID_PEER_MESSAGE:
+ /* bump headerbytecount to avoid the count remaining at zero and
+ appearing to not having read anything from the peer at all */
+ data->req.headerbytecount++;
result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */
- else
+ break;
+ default:
result = CURLE_RECV_ERROR;
+ break;
+ }
}
*done = TRUE;
hyper_error_free(hypererr);
break;
}
- else if(h->endtask == task) {
- /* end of transfer, forget the task handled, we might get a
- * new one with the same address in the future. */
- *done = TRUE;
- h->endtask = NULL;
- infof(data, "hyperstream is done");
- if(!k->bodywrites) {
- /* hyper doesn't always call the body write callback */
- bool stilldone;
- result = Curl_http_firstwrite(data, data->conn, &stilldone);
+ else if(t == HYPER_TASK_EMPTY) {
+ void *userdata = hyper_task_userdata(task);
+ hyper_task_free(task);
+ if((userdata_t)userdata == USERDATA_RESP_BODY) {
+ /* end of transfer */
+ *done = TRUE;
+ infof(data, "hyperstream is done");
+ if(!k->bodywrites) {
+ /* hyper doesn't always call the body write callback */
+ bool stilldone;
+ result = Curl_http_firstwrite(data, data->conn, &stilldone);
+ }
+ break;
+ }
+ else {
+ /* A background task for hyper; ignore */
+ continue;
}
- break;
- }
- else if(t != HYPER_TASK_RESPONSE) {
- continue;
}
- /* HYPER_TASK_RESPONSE */
+
+ DEBUGASSERT(HYPER_TASK_RESPONSE);
+
+ resp = hyper_task_value(task);
+ hyper_task_free(task);
*didwhat = KEEP_RECV;
if(!resp) {
@@ -523,13 +538,12 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
result = CURLE_OUT_OF_MEMORY;
break;
}
- DEBUGASSERT(hyper_task_type(foreach) == HYPER_TASK_EMPTY);
+ hyper_task_set_userdata(foreach, (void *)USERDATA_RESP_BODY);
if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
failf(data, "Couldn't hyper_executor_push the body-foreach");
result = CURLE_OUT_OF_MEMORY;
break;
}
- h->endtask = foreach;
hyper_response_free(resp);
resp = NULL;
@@ -757,7 +771,7 @@ static int uploadstreamed(void *userdata, hyper_context *ctx,
/* increasing the writebytecount here is a little premature but we
don't know exactly when the body is sent */
data->req.writebytecount += fillcount;
- Curl_pgrsSetUploadCounter(data, fillcount);
+ Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
}
return HYPER_POLL_READY;
}
@@ -794,15 +808,16 @@ static CURLcode bodysend(struct Curl_easy *data,
hyper_body_set_data_func(body, uploadpostfields);
else {
result = Curl_get_upload_buffer(data);
- if(result)
+ if(result) {
+ hyper_body_free(body);
return result;
+ }
/* init the "upload from here" pointer */
data->req.upload_fromhere = data->state.ulbuf;
hyper_body_set_data_func(body, uploadstreamed);
}
if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
/* fail */
- hyper_body_free(body);
result = CURLE_OUT_OF_MEMORY;
}
}
@@ -1194,14 +1209,17 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
result = CURLE_OUT_OF_MEMORY;
goto error;
}
+ req = NULL;
if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
failf(data, "Couldn't hyper_executor_push the send");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
+ sendtask = NULL; /* ownership passed on */
hyper_clientconn_free(client);
+ client = NULL;
if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
/* HTTP GET/HEAD download */
@@ -1214,8 +1232,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
the full request has been sent. */
data->req.start100 = Curl_now();
- /* clear userpwd and proxyuserpwd to avoid re-using old credentials
- * from re-used connections */
+ /* clear userpwd and proxyuserpwd to avoid reusing old credentials
+ * from reused connections */
Curl_safefree(data->state.aptr.userpwd);
Curl_safefree(data->state.aptr.proxyuserpwd);
return CURLE_OK;
@@ -1230,6 +1248,12 @@ error:
if(handshake)
hyper_task_free(handshake);
+ if(client)
+ hyper_clientconn_free(client);
+
+ if(req)
+ hyper_request_free(req);
+
return result;
}
diff --git a/libs/libcurl/src/c-hyper.h b/libs/libcurl/src/c-hyper.h
index aea0c44782..244427f9e7 100644
--- a/libs/libcurl/src/c-hyper.h
+++ b/libs/libcurl/src/c-hyper.h
@@ -34,7 +34,6 @@ struct hyptransfer {
hyper_waker *write_waker;
hyper_waker *read_waker;
const hyper_executor *exec;
- hyper_task *endtask;
hyper_waker *exp100_waker;
hyper_waker *send_body_waker;
};
diff --git a/libs/libcurl/src/cf-h1-proxy.c b/libs/libcurl/src/cf-h1-proxy.c
index 0c3aa3c020..e2b5da42fd 100644
--- a/libs/libcurl/src/cf-h1-proxy.c
+++ b/libs/libcurl/src/cf-h1-proxy.c
@@ -41,7 +41,7 @@
#include "cfilters.h"
#include "cf-h1-proxy.h"
#include "connect.h"
-#include "curl_log.h"
+#include "curl_trc.h"
#include "curlx.h"
#include "vtls/vtls.h"
#include "transfer.h"
@@ -175,36 +175,36 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
/* entering this one */
switch(new_state) {
case H1_TUNNEL_INIT:
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'init'"));
+ CURL_TRC_CF(data, cf, "new tunnel state 'init'");
tunnel_reinit(ts, cf->conn, data);
break;
case H1_TUNNEL_CONNECT:
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'connect'"));
+ CURL_TRC_CF(data, cf, "new tunnel state 'connect'");
ts->tunnel_state = H1_TUNNEL_CONNECT;
ts->keepon = KEEPON_CONNECT;
Curl_dyn_reset(&ts->rcvbuf);
break;
case H1_TUNNEL_RECEIVE:
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'receive'"));
+ CURL_TRC_CF(data, cf, "new tunnel state 'receive'");
ts->tunnel_state = H1_TUNNEL_RECEIVE;
break;
case H1_TUNNEL_RESPONSE:
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'response'"));
+ CURL_TRC_CF(data, cf, "new tunnel state 'response'");
ts->tunnel_state = H1_TUNNEL_RESPONSE;
break;
case H1_TUNNEL_ESTABLISHED:
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'established'"));
+ CURL_TRC_CF(data, cf, "new tunnel state 'established'");
infof(data, "CONNECT phase completed");
data->state.authproxy.done = TRUE;
data->state.authproxy.multipass = FALSE;
/* FALLTHROUGH */
case H1_TUNNEL_FAILED:
if(new_state == H1_TUNNEL_FAILED)
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'failed'"));
+ CURL_TRC_CF(data, cf, "new tunnel state 'failed'");
ts->tunnel_state = new_state;
Curl_dyn_reset(&ts->rcvbuf);
Curl_dyn_reset(&ts->req);
@@ -416,7 +416,7 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf,
if(!auth)
return CURLE_OUT_OF_MEMORY;
- DEBUGF(LOG_CF(data, cf, "CONNECT: fwd auth header '%s'", header));
+ CURL_TRC_CF(data, cf, "CONNECT: fwd auth header '%s'", header);
result = Curl_http_input_auth(data, proxy, auth);
free(auth);
@@ -587,7 +587,9 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
return result;
}
- data->info.header_size += (long)perline;
+ result = Curl_bump_headersize(data, perline, TRUE);
+ if(result)
+ return result;
/* Newlines are CRLF, so the CR is ignored as the line isn't
really terminated until the LF comes. Treat a following CR
@@ -636,7 +638,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
/* without content-length or chunked encoding, we
can't keep the connection alive since the close is
the end signal so we bail out at once instead */
- DEBUGF(LOG_CF(data, cf, "CONNECT: no content-length or chunked"));
+ CURL_TRC_CF(data, cf, "CONNECT: no content-length or chunked");
ts->keepon = KEEPON_DONE;
}
}
@@ -713,14 +715,13 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
}
options = hyper_clientconn_options_new();
- hyper_clientconn_options_set_preserve_header_case(options, 1);
- hyper_clientconn_options_set_preserve_header_order(options, 1);
-
if(!options) {
failf(data, "Couldn't create hyper client options");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
+ hyper_clientconn_options_set_preserve_header_case(options, 1);
+ hyper_clientconn_options_set_preserve_header_order(options, 1);
hyper_clientconn_options_exec(options, h->exec);
@@ -751,6 +752,7 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
client = hyper_task_value(task);
hyper_task_free(task);
+
req = hyper_request_new();
if(!req) {
failf(data, "Couldn't hyper_request_new");
@@ -859,12 +861,17 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
result = CURLE_OUT_OF_MEMORY;
goto error;
}
+ req = NULL;
if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
failf(data, "Couldn't hyper_executor_push the send");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
+ sendtask = NULL; /* ownership passed on */
+
+ hyper_clientconn_free(client);
+ client = NULL;
error:
free(host);
@@ -877,6 +884,9 @@ error:
hyper_task_free(handshake);
if(client)
hyper_clientconn_free(client);
+ if(req)
+ hyper_request_free(req);
+
return result;
}
@@ -975,7 +985,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
switch(ts->tunnel_state) {
case H1_TUNNEL_INIT:
/* Prepare the CONNECT request and make a first attempt to send. */
- DEBUGF(LOG_CF(data, cf, "CONNECT start"));
+ CURL_TRC_CF(data, cf, "CONNECT start");
result = start_CONNECT(cf, data, ts);
if(result)
goto out;
@@ -984,7 +994,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
case H1_TUNNEL_CONNECT:
/* see that the request is completely sent */
- DEBUGF(LOG_CF(data, cf, "CONNECT send"));
+ CURL_TRC_CF(data, cf, "CONNECT send");
result = send_CONNECT(data, cf->conn, ts, &done);
if(result || !done)
goto out;
@@ -993,7 +1003,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
case H1_TUNNEL_RECEIVE:
/* read what is there */
- DEBUGF(LOG_CF(data, cf, "CONNECT receive"));
+ CURL_TRC_CF(data, cf, "CONNECT receive");
result = recv_CONNECT_resp(cf, data, ts, &done);
if(Curl_pgrsUpdate(data)) {
result = CURLE_ABORTED_BY_CALLBACK;
@@ -1007,7 +1017,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
/* FALLTHROUGH */
case H1_TUNNEL_RESPONSE:
- DEBUGF(LOG_CF(data, cf, "CONNECT response"));
+ CURL_TRC_CF(data, cf, "CONNECT response");
if(data->req.newurl) {
/* not the "final" response, we need to do a follow up request.
* If the other side indicated a connection close, or if someone
@@ -1019,7 +1029,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
* reset our tunnel state. To avoid recursion, we return
* and expect to be called again.
*/
- DEBUGF(LOG_CF(data, cf, "CONNECT need to close+open"));
+ CURL_TRC_CF(data, cf, "CONNECT need to close+open");
infof(data, "Connect me again please");
Curl_conn_cf_close(cf, data);
connkeep(conn, "HTTP proxy CONNECT");
@@ -1043,7 +1053,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
if(data->info.httpproxycode/100 != 2) {
/* a non-2xx response and we have no next url to try. */
Curl_safefree(data->req.newurl);
- /* failure, close this connection to avoid re-use */
+ /* failure, close this connection to avoid reuse */
streamclose(conn, "proxy CONNECT failure");
h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
failf(data, "CONNECT tunnel failed, response %d", data->req.httpcode);
@@ -1073,7 +1083,7 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
return CURLE_OK;
}
- DEBUGF(LOG_CF(data, cf, "connect"));
+ CURL_TRC_CF(data, cf, "connect");
result = cf->next->cft->do_connect(cf->next, data, blocking, done);
if(result || !*done)
return result;
@@ -1133,14 +1143,14 @@ static int cf_h1_proxy_get_select_socks(struct Curl_cfilter *cf,
static void cf_h1_proxy_destroy(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- DEBUGF(LOG_CF(data, cf, "destroy"));
+ CURL_TRC_CF(data, cf, "destroy");
tunnel_free(cf, data);
}
static void cf_h1_proxy_close(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- DEBUGF(LOG_CF(data, cf, "close"));
+ CURL_TRC_CF(data, cf, "close");
cf->connected = FALSE;
if(cf->ctx) {
h1_tunnel_go_state(cf, cf->ctx, H1_TUNNEL_INIT, data);
diff --git a/libs/libcurl/src/cf-h2-proxy.c b/libs/libcurl/src/cf-h2-proxy.c
index 5248660fc8..c18e1e0cf7 100644
--- a/libs/libcurl/src/cf-h2-proxy.c
+++ b/libs/libcurl/src/cf-h2-proxy.c
@@ -30,11 +30,12 @@
#include "urldata.h"
#include "cfilters.h"
#include "connect.h"
-#include "curl_log.h"
+#include "curl_trc.h"
#include "bufq.h"
#include "dynbuf.h"
#include "dynhds.h"
#include "http1.h"
+#include "http2.h"
#include "http_proxy.h"
#include "multiif.h"
#include "cf-h2-proxy.h"
@@ -44,16 +45,16 @@
#include "curl_memory.h"
#include "memdebug.h"
-#define H2_CHUNK_SIZE (16*1024)
+#define PROXY_H2_CHUNK_SIZE (16*1024)
#define PROXY_HTTP2_HUGE_WINDOW_SIZE (100 * 1024 * 1024)
#define H2_TUNNEL_WINDOW_SIZE (10 * 1024 * 1024)
-#define PROXY_H2_NW_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / H2_CHUNK_SIZE)
+#define PROXY_H2_NW_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / PROXY_H2_CHUNK_SIZE)
#define PROXY_H2_NW_SEND_CHUNKS 1
-#define H2_TUNNEL_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / H2_CHUNK_SIZE)
-#define H2_TUNNEL_SEND_CHUNKS ((128 * 1024) / H2_CHUNK_SIZE)
+#define H2_TUNNEL_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / PROXY_H2_CHUNK_SIZE)
+#define H2_TUNNEL_SEND_CHUNKS ((128 * 1024) / PROXY_H2_CHUNK_SIZE)
typedef enum {
@@ -87,9 +88,9 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
ts->state = H2_TUNNEL_INIT;
ts->stream_id = -1;
- Curl_bufq_init2(&ts->recvbuf, H2_CHUNK_SIZE, H2_TUNNEL_RECV_CHUNKS,
+ Curl_bufq_init2(&ts->recvbuf, PROXY_H2_CHUNK_SIZE, H2_TUNNEL_RECV_CHUNKS,
BUFQ_OPT_SOFT_LIMIT);
- Curl_bufq_init(&ts->sendbuf, H2_CHUNK_SIZE, H2_TUNNEL_SEND_CHUNKS);
+ Curl_bufq_init(&ts->sendbuf, PROXY_H2_CHUNK_SIZE, H2_TUNNEL_SEND_CHUNKS);
if(cf->conn->bits.conn_to_host)
hostname = cf->conn->conn_to_host.name;
@@ -146,29 +147,30 @@ static void h2_tunnel_go_state(struct Curl_cfilter *cf,
/* entering this one */
switch(new_state) {
case H2_TUNNEL_INIT:
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'init'"));
+ CURL_TRC_CF(data, cf, "[%d] new tunnel state 'init'", ts->stream_id);
tunnel_stream_clear(ts);
break;
case H2_TUNNEL_CONNECT:
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'connect'"));
+ CURL_TRC_CF(data, cf, "[%d] new tunnel state 'connect'", ts->stream_id);
ts->state = H2_TUNNEL_CONNECT;
break;
case H2_TUNNEL_RESPONSE:
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'response'"));
+ CURL_TRC_CF(data, cf, "[%d] new tunnel state 'response'", ts->stream_id);
ts->state = H2_TUNNEL_RESPONSE;
break;
case H2_TUNNEL_ESTABLISHED:
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'established'"));
+ CURL_TRC_CF(data, cf, "[%d] new tunnel state 'established'",
+ ts->stream_id);
infof(data, "CONNECT phase completed");
data->state.authproxy.done = TRUE;
data->state.authproxy.multipass = FALSE;
/* FALLTHROUGH */
case H2_TUNNEL_FAILED:
if(new_state == H2_TUNNEL_FAILED)
- DEBUGF(LOG_CF(data, cf, "new tunnel state 'failed'"));
+ CURL_TRC_CF(data, cf, "[%d] new tunnel state 'failed'", ts->stream_id);
ts->state = new_state;
/* If a proxy-authorization header was used for the proxy, then we should
make sure that it isn't accidentally used for the document request
@@ -231,9 +233,9 @@ static void drain_tunnel(struct Curl_cfilter *cf,
bits = CURL_CSELECT_IN;
if(!tunnel->closed && !tunnel->reset && tunnel->upload_blocked_len)
bits |= CURL_CSELECT_OUT;
- if(data->state.dselect_bits != bits) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] DRAIN dselect_bits=%x",
- tunnel->stream_id, bits));
+ if(data->state.dselect_bits != bits || 1) {
+ CURL_TRC_CF(data, cf, "[%d] DRAIN dselect_bits=%x",
+ tunnel->stream_id, bits);
data->state.dselect_bits = bits;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
@@ -244,12 +246,17 @@ static ssize_t proxy_nw_in_reader(void *reader_ctx,
CURLcode *err)
{
struct Curl_cfilter *cf = reader_ctx;
- struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nread;
- nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, err);
- DEBUGF(LOG_CF(data, cf, "nw_in_reader(len=%zu) -> %zd, %d",
- buflen, nread, *err));
+ if(cf) {
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, err);
+ CURL_TRC_CF(data, cf, "[0] nw_in_reader(len=%zu) -> %zd, %d",
+ buflen, nread, *err);
+ }
+ else {
+ nread = 0;
+ }
return nread;
}
@@ -258,12 +265,18 @@ static ssize_t proxy_h2_nw_out_writer(void *writer_ctx,
CURLcode *err)
{
struct Curl_cfilter *cf = writer_ctx;
- struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
- nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
- DEBUGF(LOG_CF(data, cf, "nw_out_writer(len=%zu) -> %zd, %d",
- buflen, nwritten, *err));
+ if(cf) {
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen,
+ err);
+ CURL_TRC_CF(data, cf, "[0] nw_out_writer(len=%zu) -> %zd, %d",
+ buflen, nwritten, *err);
+ }
+ else {
+ nwritten = 0;
+ }
return nwritten;
}
@@ -295,6 +308,10 @@ static ssize_t on_session_send(nghttp2_session *h2,
static int proxy_h2_on_frame_recv(nghttp2_session *session,
const nghttp2_frame *frame,
void *userp);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
+ void *userp);
+#endif
static int proxy_h2_on_stream_close(nghttp2_session *session,
int32_t stream_id,
uint32_t error_code, void *userp);
@@ -322,8 +339,8 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
DEBUGASSERT(!ctx->h2);
memset(&ctx->tunnel, 0, sizeof(ctx->tunnel));
- Curl_bufq_init(&ctx->inbufq, H2_CHUNK_SIZE, PROXY_H2_NW_RECV_CHUNKS);
- Curl_bufq_init(&ctx->outbufq, H2_CHUNK_SIZE, PROXY_H2_NW_SEND_CHUNKS);
+ Curl_bufq_init(&ctx->inbufq, PROXY_H2_CHUNK_SIZE, PROXY_H2_NW_RECV_CHUNKS);
+ Curl_bufq_init(&ctx->outbufq, PROXY_H2_CHUNK_SIZE, PROXY_H2_NW_SEND_CHUNKS);
if(tunnel_stream_init(cf, &ctx->tunnel))
goto out;
@@ -337,6 +354,9 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
nghttp2_session_callbacks_set_send_callback(cbs, on_session_send);
nghttp2_session_callbacks_set_on_frame_recv_callback(
cbs, proxy_h2_on_frame_recv);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ nghttp2_session_callbacks_set_on_frame_send_callback(cbs, on_frame_send);
+#endif
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
cbs, tunnel_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
@@ -384,11 +404,11 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
out:
if(cbs)
nghttp2_session_callbacks_del(cbs);
- DEBUGF(LOG_CF(data, cf, "init proxy ctx -> %d", result));
+ CURL_TRC_CF(data, cf, "[0] init proxy ctx -> %d", result);
return result;
}
-static int should_close_session(struct cf_h2_proxy_ctx *ctx)
+static int proxy_h2_should_close_session(struct cf_h2_proxy_ctx *ctx)
{
return !nghttp2_session_want_read(ctx->h2) &&
!nghttp2_session_want_write(ctx->h2);
@@ -409,13 +429,13 @@ static CURLcode proxy_h2_nw_out_flush(struct Curl_cfilter *cf,
&result);
if(nwritten < 0) {
if(result == CURLE_AGAIN) {
- DEBUGF(LOG_CF(data, cf, "flush nw send buffer(%zu) -> EAGAIN",
- Curl_bufq_len(&ctx->outbufq)));
+ CURL_TRC_CF(data, cf, "[0] flush nw send buffer(%zu) -> EAGAIN",
+ Curl_bufq_len(&ctx->outbufq));
ctx->nw_out_blocked = 1;
}
return result;
}
- DEBUGF(LOG_CF(data, cf, "nw send buffer flushed"));
+ CURL_TRC_CF(data, cf, "[0] nw send buffer flushed");
return Curl_bufq_is_empty(&ctx->outbufq)? CURLE_OK: CURLE_AGAIN;
}
@@ -436,8 +456,7 @@ static int proxy_h2_process_pending_input(struct Curl_cfilter *cf,
while(Curl_bufq_peek(&ctx->inbufq, &buf, &blen)) {
rv = nghttp2_session_mem_recv(ctx->h2, (const uint8_t *)buf, blen);
- DEBUGF(LOG_CF(data, cf,
- "fed %zu bytes from nw to nghttp2 -> %zd", blen, rv));
+ CURL_TRC_CF(data, cf, "[0] %zu bytes to nghttp2 -> %zd", blen, rv);
if(rv < 0) {
failf(data,
"process_pending_input: nghttp2_session_mem_recv() returned "
@@ -447,12 +466,12 @@ static int proxy_h2_process_pending_input(struct Curl_cfilter *cf,
}
Curl_bufq_skip(&ctx->inbufq, (size_t)rv);
if(Curl_bufq_is_empty(&ctx->inbufq)) {
- DEBUGF(LOG_CF(data, cf, "all data in connection buffer processed"));
+ CURL_TRC_CF(data, cf, "[0] all data in connection buffer processed");
break;
}
else {
- DEBUGF(LOG_CF(data, cf, "process_pending_input: %zu bytes left "
- "in connection buffer", Curl_bufq_len(&ctx->inbufq)));
+ CURL_TRC_CF(data, cf, "[0] process_pending_input: %zu bytes left "
+ "in connection buffer", Curl_bufq_len(&ctx->inbufq));
}
}
@@ -468,8 +487,8 @@ static CURLcode proxy_h2_progress_ingress(struct Curl_cfilter *cf,
/* Process network input buffer fist */
if(!Curl_bufq_is_empty(&ctx->inbufq)) {
- DEBUGF(LOG_CF(data, cf, "Process %zu bytes in connection buffer",
- Curl_bufq_len(&ctx->inbufq)));
+ CURL_TRC_CF(data, cf, "[0] process %zu bytes in connection buffer",
+ Curl_bufq_len(&ctx->inbufq));
if(proxy_h2_process_pending_input(cf, data, &result) < 0)
return result;
}
@@ -482,8 +501,8 @@ static CURLcode proxy_h2_progress_ingress(struct Curl_cfilter *cf,
!Curl_bufq_is_full(&ctx->tunnel.recvbuf)) {
nread = Curl_bufq_slurp(&ctx->inbufq, proxy_nw_in_reader, cf, &result);
- DEBUGF(LOG_CF(data, cf, "read %zu bytes nw data -> %zd, %d",
- Curl_bufq_len(&ctx->inbufq), nread, result));
+ CURL_TRC_CF(data, cf, "[0] read %zu bytes nw data -> %zd, %d",
+ Curl_bufq_len(&ctx->inbufq), nread, result);
if(nread < 0) {
if(result != CURLE_AGAIN) {
failf(data, "Failed receiving HTTP2 data");
@@ -518,8 +537,8 @@ static CURLcode proxy_h2_progress_egress(struct Curl_cfilter *cf,
rv = nghttp2_session_send(ctx->h2);
if(nghttp2_is_fatal(rv)) {
- DEBUGF(LOG_CF(data, cf, "nghttp2_session_send error (%s)%d",
- nghttp2_strerror(rv), rv));
+ CURL_TRC_CF(data, cf, "[0] nghttp2_session_send error (%s)%d",
+ nghttp2_strerror(rv), rv);
return CURLE_SEND_ERROR;
}
return proxy_h2_nw_out_flush(cf, data);
@@ -555,6 +574,97 @@ static ssize_t on_session_send(nghttp2_session *h2,
return nwritten;
}
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen)
+{
+ switch(frame->hd.type) {
+ case NGHTTP2_DATA: {
+ return msnprintf(buffer, blen,
+ "FRAME[DATA, len=%d, eos=%d, padlen=%d]",
+ (int)frame->hd.length,
+ !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM),
+ (int)frame->data.padlen);
+ }
+ case NGHTTP2_HEADERS: {
+ return msnprintf(buffer, blen,
+ "FRAME[HEADERS, len=%d, hend=%d, eos=%d]",
+ (int)frame->hd.length,
+ !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS),
+ !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM));
+ }
+ case NGHTTP2_PRIORITY: {
+ return msnprintf(buffer, blen,
+ "FRAME[PRIORITY, len=%d, flags=%d]",
+ (int)frame->hd.length, frame->hd.flags);
+ }
+ case NGHTTP2_RST_STREAM: {
+ return msnprintf(buffer, blen,
+ "FRAME[RST_STREAM, len=%d, flags=%d, error=%u]",
+ (int)frame->hd.length, frame->hd.flags,
+ frame->rst_stream.error_code);
+ }
+ case NGHTTP2_SETTINGS: {
+ if(frame->hd.flags & NGHTTP2_FLAG_ACK) {
+ return msnprintf(buffer, blen, "FRAME[SETTINGS, ack=1]");
+ }
+ return msnprintf(buffer, blen,
+ "FRAME[SETTINGS, len=%d]", (int)frame->hd.length);
+ }
+ case NGHTTP2_PUSH_PROMISE: {
+ return msnprintf(buffer, blen,
+ "FRAME[PUSH_PROMISE, len=%d, hend=%d]",
+ (int)frame->hd.length,
+ !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS));
+ }
+ case NGHTTP2_PING: {
+ return msnprintf(buffer, blen,
+ "FRAME[PING, len=%d, ack=%d]",
+ (int)frame->hd.length,
+ frame->hd.flags&NGHTTP2_FLAG_ACK);
+ }
+ case NGHTTP2_GOAWAY: {
+ char scratch[128];
+ size_t s_len = sizeof(scratch)/sizeof(scratch[0]);
+ size_t len = (frame->goaway.opaque_data_len < s_len)?
+ frame->goaway.opaque_data_len : s_len-1;
+ if(len)
+ memcpy(scratch, frame->goaway.opaque_data, len);
+ scratch[len] = '\0';
+ return msnprintf(buffer, blen, "FRAME[GOAWAY, error=%d, reason='%s', "
+ "last_stream=%d]", frame->goaway.error_code,
+ scratch, frame->goaway.last_stream_id);
+ }
+ case NGHTTP2_WINDOW_UPDATE: {
+ return msnprintf(buffer, blen,
+ "FRAME[WINDOW_UPDATE, incr=%d]",
+ frame->window_update.window_size_increment);
+ }
+ default:
+ return msnprintf(buffer, blen, "FRAME[%d, len=%d, flags=%d]",
+ frame->hd.type, (int)frame->hd.length,
+ frame->hd.flags);
+ }
+}
+
+static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
+ void *userp)
+{
+ struct Curl_cfilter *cf = userp;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+
+ (void)session;
+ DEBUGASSERT(data);
+ if(data && Curl_trc_cf_is_verbose(cf, data)) {
+ char buffer[256];
+ int len;
+ len = fr_print(frame, buffer, sizeof(buffer)-1);
+ buffer[len] = 0;
+ CURL_TRC_CF(data, cf, "[%d] -> %s", frame->hd.stream_id, buffer);
+ }
+ return 0;
+}
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+
static int proxy_h2_on_frame_recv(nghttp2_session *session,
const nghttp2_frame *frame,
void *userp)
@@ -566,75 +676,74 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
(void)session;
DEBUGASSERT(data);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ if(Curl_trc_cf_is_verbose(cf, data)) {
+ char buffer[256];
+ int len;
+ len = fr_print(frame, buffer, sizeof(buffer)-1);
+ buffer[len] = 0;
+ CURL_TRC_CF(data, cf, "[%d] <- %s",frame->hd.stream_id, buffer);
+ }
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+
if(!stream_id) {
/* stream ID zero is for connection-oriented stuff */
DEBUGASSERT(data);
switch(frame->hd.type) {
case NGHTTP2_SETTINGS:
- /* we do not do anything with this for now */
+ /* Since the initial stream window is 64K, a request might be on HOLD,
+ * due to exhaustion. The (initial) SETTINGS may announce a much larger
+ * window and *assume* that we treat this like a WINDOW_UPDATE. Some
+ * servers send an explicit WINDOW_UPDATE, but not all seem to do that.
+ * To be safe, we UNHOLD a stream in order not to stall. */
+ if((data->req.keepon & KEEP_SEND_HOLD) &&
+ (data->req.keepon & KEEP_SEND)) {
+ data->req.keepon &= ~KEEP_SEND_HOLD;
+ drain_tunnel(cf, data, &ctx->tunnel);
+ CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
+ stream_id);
+ }
break;
case NGHTTP2_GOAWAY:
- infof(data, "recveived GOAWAY, error=%d, last_stream=%u",
- frame->goaway.error_code, frame->goaway.last_stream_id);
ctx->goaway = TRUE;
break;
- case NGHTTP2_WINDOW_UPDATE:
- DEBUGF(LOG_CF(data, cf, "recv frame WINDOW_UPDATE"));
- break;
default:
- DEBUGF(LOG_CF(data, cf, "recv frame %x on 0", frame->hd.type));
+ break;
}
return 0;
}
if(stream_id != ctx->tunnel.stream_id) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] rcvd FRAME not for tunnel",
- stream_id));
+ CURL_TRC_CF(data, cf, "[%d] rcvd FRAME not for tunnel", stream_id);
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
switch(frame->hd.type) {
- case NGHTTP2_DATA:
- /* If body started on this stream, then receiving DATA is illegal. */
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv frame DATA", stream_id));
- break;
case NGHTTP2_HEADERS:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv frame HEADERS", stream_id));
-
/* nghttp2 guarantees that :status is received, and we store it to
stream->status_code. Fuzzing has proven this can still be reached
without status code having been set. */
if(!ctx->tunnel.resp)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* Only final status code signals the end of header */
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] got http status: %d",
- stream_id, ctx->tunnel.resp->status));
+ CURL_TRC_CF(data, cf, "[%d] got http status: %d",
+ stream_id, ctx->tunnel.resp->status);
if(!ctx->tunnel.has_final_response) {
if(ctx->tunnel.resp->status / 100 != 1) {
ctx->tunnel.has_final_response = TRUE;
}
}
break;
- case NGHTTP2_PUSH_PROMISE:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv PUSH_PROMISE", stream_id));
- return NGHTTP2_ERR_CALLBACK_FAILURE;
- case NGHTTP2_RST_STREAM:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv RST", stream_id));
- ctx->tunnel.reset = TRUE;
- break;
case NGHTTP2_WINDOW_UPDATE:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv WINDOW_UPDATE", stream_id));
if((data->req.keepon & KEEP_SEND_HOLD) &&
(data->req.keepon & KEEP_SEND)) {
data->req.keepon &= ~KEEP_SEND_HOLD;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] unpausing after win update",
- stream_id));
+ CURL_TRC_CF(data, cf, "[%d] unpausing after win update",
+ stream_id);
}
break;
default:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv frame %x",
- stream_id, frame->hd.type));
break;
}
return 0;
@@ -658,10 +767,9 @@ static int proxy_h2_on_header(nghttp2_session *session,
(void)session;
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
if(stream_id != ctx->tunnel.stream_id) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] header for non-tunnel stream: "
- "%.*s: %.*s", stream_id,
- (int)namelen, name,
- (int)valuelen, value));
+ CURL_TRC_CF(data, cf, "[%d] header for non-tunnel stream: "
+ "%.*s: %.*s", stream_id,
+ (int)namelen, name, (int)valuelen, value);
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
@@ -689,8 +797,8 @@ static int proxy_h2_on_header(nghttp2_session *session,
return NGHTTP2_ERR_CALLBACK_FAILURE;
resp->prev = ctx->tunnel.resp;
ctx->tunnel.resp = resp;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] status: HTTP/2 %03d",
- stream_id, ctx->tunnel.resp->status));
+ CURL_TRC_CF(data, cf, "[%d] status: HTTP/2 %03d",
+ stream_id, ctx->tunnel.resp->status);
return 0;
}
@@ -703,10 +811,8 @@ static int proxy_h2_on_header(nghttp2_session *session,
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] header: %.*s: %.*s",
- stream_id,
- (int)namelen, name,
- (int)valuelen, value));
+ CURL_TRC_CF(data, cf, "[%d] header: %.*s: %.*s",
+ stream_id, (int)namelen, name, (int)valuelen, value);
return 0; /* 0 is successful */
}
@@ -746,8 +852,8 @@ static ssize_t tunnel_send_callback(nghttp2_session *session,
if(ts->closed && Curl_bufq_is_empty(&ts->sendbuf))
*data_flags = NGHTTP2_DATA_FLAG_EOF;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] tunnel_send_callback -> %zd",
- ts->stream_id, nread));
+ CURL_TRC_CF(data, cf, "[%d] tunnel_send_callback -> %zd",
+ ts->stream_id, nread);
return nread;
}
@@ -791,8 +897,8 @@ static int proxy_h2_on_stream_close(nghttp2_session *session,
if(stream_id != ctx->tunnel.stream_id)
return 0;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] proxy_h2_on_stream_close, %s (err %d)",
- stream_id, nghttp2_http2_strerror(error_code), error_code));
+ CURL_TRC_CF(data, cf, "[%d] proxy_h2_on_stream_close, %s (err %d)",
+ stream_id, nghttp2_http2_strerror(error_code), error_code);
ctx->tunnel.closed = TRUE;
ctx->tunnel.error = error_code;
@@ -910,8 +1016,8 @@ static CURLcode submit_CONNECT(struct Curl_cfilter *cf,
result = proxy_h2_submit(&ts->stream_id, cf, data, ctx->h2, req,
NULL, ts, tunnel_send_callback, cf);
if(result) {
- DEBUGF(LOG_CF(data, cf, "send: nghttp2_submit_request error (%s)%u",
- nghttp2_strerror(ts->stream_id), ts->stream_id));
+ CURL_TRC_CF(data, cf, "[%d] send, nghttp2_submit_request error: %s",
+ ts->stream_id, nghttp2_strerror(ts->stream_id));
}
out:
@@ -945,8 +1051,8 @@ static CURLcode inspect_response(struct Curl_cfilter *cf,
}
if(auth_reply) {
- DEBUGF(LOG_CF(data, cf, "CONNECT: fwd auth header '%s'",
- auth_reply->value));
+ CURL_TRC_CF(data, cf, "[0] CONNECT: fwd auth header '%s'",
+ auth_reply->value);
result = Curl_http_input_auth(data, ts->resp->status == 407,
auth_reply->value);
if(result)
@@ -976,7 +1082,7 @@ static CURLcode H2_CONNECT(struct Curl_cfilter *cf,
switch(ts->state) {
case H2_TUNNEL_INIT:
/* Prepare the CONNECT request and make a first attempt to send. */
- DEBUGF(LOG_CF(data, cf, "CONNECT start for %s", ts->authority));
+ CURL_TRC_CF(data, cf, "[0] CONNECT start for %s", ts->authority);
result = submit_CONNECT(cf, data, ts);
if(result)
goto out;
@@ -1143,8 +1249,8 @@ static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf,
ssize_t rv = 0;
if(ctx->tunnel.error == NGHTTP2_REFUSED_STREAM) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] REFUSED_STREAM, try again on a new "
- "connection", ctx->tunnel.stream_id));
+ CURL_TRC_CF(data, cf, "[%d] REFUSED_STREAM, try again on a new "
+ "connection", ctx->tunnel.stream_id);
connclose(cf->conn, "REFUSED_STREAM"); /* don't use this anymore */
*err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
return -1;
@@ -1164,7 +1270,8 @@ static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf,
*err = CURLE_OK;
rv = 0;
- DEBUGF(LOG_CF(data, cf, "handle_tunnel_close -> %zd, %d", rv, *err));
+ CURL_TRC_CF(data, cf, "[%d] handle_tunnel_close -> %zd, %d",
+ ctx->tunnel.stream_id, rv, *err);
return rv;
}
@@ -1200,8 +1307,8 @@ static ssize_t tunnel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
}
out:
- DEBUGF(LOG_CF(data, cf, "tunnel_recv(len=%zu) -> %zd, %d",
- len, nread, *err));
+ CURL_TRC_CF(data, cf, "[%d] tunnel_recv(len=%zu) -> %zd, %d",
+ ctx->tunnel.stream_id, len, nread, *err);
return nread;
}
@@ -1229,13 +1336,22 @@ static ssize_t cf_h2_proxy_recv(struct Curl_cfilter *cf,
nread = tunnel_recv(cf, data, buf, len, err);
if(nread > 0) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] increase window by %zd",
- ctx->tunnel.stream_id, nread));
+ CURL_TRC_CF(data, cf, "[%d] increase window by %zd",
+ ctx->tunnel.stream_id, nread);
nghttp2_session_consume(ctx->h2, ctx->tunnel.stream_id, (size_t)nread);
}
result = proxy_h2_progress_egress(cf, data);
- if(result && result != CURLE_AGAIN) {
+ if(result == CURLE_AGAIN) {
+ /* pending data to send, need to be called again. Ideally, we'd
+ * monitor the socket for POLLOUT, but we might not be in SENDING
+ * transfer state any longer and are unable to make this happen.
+ */
+ CURL_TRC_CF(data, cf, "[%d] egress blocked, DRAIN",
+ ctx->tunnel.stream_id);
+ drain_tunnel(cf, data, &ctx->tunnel);
+ }
+ else if(result) {
*err = result;
nread = -1;
}
@@ -1247,8 +1363,8 @@ out:
* draining to avoid stalling when no socket events happen. */
drain_tunnel(cf, data, &ctx->tunnel);
}
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] cf_recv(len=%zu) -> %zd %d",
- ctx->tunnel.stream_id, len, nread, *err));
+ CURL_TRC_CF(data, cf, "[%d] cf_recv(len=%zu) -> %zd %d",
+ ctx->tunnel.stream_id, len, nread, *err);
CF_DATA_RESTORE(cf, save);
return nread;
}
@@ -1276,12 +1392,12 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
goto out;
}
else if(ctx->tunnel.upload_blocked_len) {
- /* the data in `buf` has alread been submitted or added to the
+ /* the data in `buf` has already been submitted or added to the
* buffers, but have been EAGAINed on the last invocation. */
DEBUGASSERT(len >= ctx->tunnel.upload_blocked_len);
if(len < ctx->tunnel.upload_blocked_len) {
/* Did we get called again with a smaller `len`? This should not
- * happend. We are not prepared to handle that. */
+ * happen. We are not prepared to handle that. */
failf(data, "HTTP/2 proxy, send again with decreased length");
*err = CURLE_HTTP2;
nwritten = -1;
@@ -1289,6 +1405,7 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
}
nwritten = (ssize_t)ctx->tunnel.upload_blocked_len;
ctx->tunnel.upload_blocked_len = 0;
+ *err = CURLE_OK;
}
else {
nwritten = Curl_bufq_write(&ctx->tunnel.sendbuf, buf, len, err);
@@ -1309,6 +1426,13 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
}
}
+ result = proxy_h2_progress_ingress(cf, data);
+ if(result) {
+ *err = result;
+ nwritten = -1;
+ goto out;
+ }
+
/* Call the nghttp2 send loop and flush to write ALL buffered data,
* headers and/or request body completely out to the network */
result = proxy_h2_progress_egress(cf, data);
@@ -1339,24 +1463,25 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
* proxy connection AND to UNHOLD all of them again when the
* window increases.
* We *could* iterate over all data on this conn maybe? */
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] remote flow "
- "window is exhausted", ctx->tunnel.stream_id));
+ CURL_TRC_CF(data, cf, "[%d] remote flow "
+ "window is exhausted", ctx->tunnel.stream_id);
}
/* Whatever the cause, we need to return CURL_EAGAIN for this call.
* We have unwritten state that needs us being invoked again and EAGAIN
* is the only way to ensure that. */
ctx->tunnel.upload_blocked_len = nwritten;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) BLOCK: win %u/%zu "
- "blocked_len=%zu",
- ctx->tunnel.stream_id, len,
- nghttp2_session_get_remote_window_size(ctx->h2), rwin,
- nwritten));
+ CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) BLOCK: win %u/%zu "
+ "blocked_len=%zu",
+ ctx->tunnel.stream_id, len,
+ nghttp2_session_get_remote_window_size(ctx->h2), rwin,
+ nwritten);
+ drain_tunnel(cf, data, &ctx->tunnel);
*err = CURLE_AGAIN;
nwritten = -1;
goto out;
}
- else if(should_close_session(ctx)) {
+ else if(proxy_h2_should_close_session(ctx)) {
/* nghttp2 thinks this session is done. If the stream has not been
* closed, this is an error state for out transfer */
if(ctx->tunnel.closed) {
@@ -1364,22 +1489,27 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
nwritten = -1;
}
else {
- DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
+ CURL_TRC_CF(data, cf, "[0] send: nothing to do in this session");
*err = CURLE_HTTP2;
nwritten = -1;
}
}
out:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) -> %zd, %d, "
- "h2 windows %d-%d (stream-conn), "
- "buffers %zu-%zu (stream-conn)",
- ctx->tunnel.stream_id, len, nwritten, *err,
- nghttp2_session_get_stream_remote_window_size(
+ if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf) &&
+ (nwritten >= 0 || *err == CURLE_AGAIN)) {
+ /* data pending and no fatal error to report. Need to trigger
+ * draining to avoid stalling when no socket events happen. */
+ drain_tunnel(cf, data, &ctx->tunnel);
+ }
+ CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) -> %zd, %d, "
+ "h2 windows %d-%d (stream-conn), buffers %zu-%zu (stream-conn)",
+ ctx->tunnel.stream_id, len, nwritten, *err,
+ nghttp2_session_get_stream_remote_window_size(
ctx->h2, ctx->tunnel.stream_id),
- nghttp2_session_get_remote_window_size(ctx->h2),
- Curl_bufq_len(&ctx->tunnel.sendbuf),
- Curl_bufq_len(&ctx->outbufq)));
+ nghttp2_session_get_remote_window_size(ctx->h2),
+ Curl_bufq_len(&ctx->tunnel.sendbuf),
+ Curl_bufq_len(&ctx->outbufq));
CF_DATA_RESTORE(cf, save);
return nwritten;
}
@@ -1409,7 +1539,7 @@ static bool proxy_h2_connisalive(struct Curl_cfilter *cf,
/* immediate error, considered dead */
alive = FALSE;
else {
- alive = !should_close_session(ctx);
+ alive = !proxy_h2_should_close_session(ctx);
}
}
else if(result != CURLE_AGAIN) {
@@ -1431,8 +1561,8 @@ static bool cf_h2_proxy_is_alive(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data);
result = (ctx && ctx->h2 && proxy_h2_connisalive(cf, data, input_pending));
- DEBUGF(LOG_CF(data, cf, "conn alive -> %d, input_pending=%d",
- result, *input_pending));
+ CURL_TRC_CF(data, cf, "[0] conn alive -> %d, input_pending=%d",
+ result, *input_pending);
CF_DATA_RESTORE(cf, save);
return result;
}
@@ -1440,7 +1570,7 @@ static bool cf_h2_proxy_is_alive(struct Curl_cfilter *cf,
struct Curl_cftype Curl_cft_h2_proxy = {
"H2-PROXY",
CF_TYPE_IP_CONNECT,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
cf_h2_proxy_destroy,
cf_h2_proxy_connect,
cf_h2_proxy_close,
diff --git a/libs/libcurl/src/cf-haproxy.c b/libs/libcurl/src/cf-haproxy.c
index c970552a15..8ca38823c6 100644
--- a/libs/libcurl/src/cf-haproxy.c
+++ b/libs/libcurl/src/cf-haproxy.c
@@ -30,7 +30,7 @@
#include "urldata.h"
#include "cfilters.h"
#include "cf-haproxy.h"
-#include "curl_log.h"
+#include "curl_trc.h"
#include "multiif.h"
/* The last 3 #include files should be in this order */
@@ -86,12 +86,12 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
if(data->set.str[STRING_HAPROXY_CLIENT_IP])
client_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
else
- client_ip = data->info.conn_primary_ip;
+ client_ip = data->info.conn_local_ip;
result = Curl_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
tcp_version,
- data->info.conn_local_ip,
client_ip,
+ data->info.conn_primary_ip,
data->info.conn_local_port,
data->info.conn_primary_port);
@@ -157,14 +157,14 @@ static void cf_haproxy_destroy(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
(void)data;
- DEBUGF(LOG_CF(data, cf, "destroy"));
+ CURL_TRC_CF(data, cf, "destroy");
cf_haproxy_ctx_free(cf->ctx);
}
static void cf_haproxy_close(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- DEBUGF(LOG_CF(data, cf, "close"));
+ CURL_TRC_CF(data, cf, "close");
cf->connected = FALSE;
cf_haproxy_ctx_reset(cf->ctx);
if(cf->next)
diff --git a/libs/libcurl/src/cf-https-connect.c b/libs/libcurl/src/cf-https-connect.c
index 76251d94c8..5fe93e9c31 100644
--- a/libs/libcurl/src/cf-https-connect.c
+++ b/libs/libcurl/src/cf-https-connect.c
@@ -28,7 +28,7 @@
#include "urldata.h"
#include <curl/curl.h>
-#include "curl_log.h"
+#include "curl_trc.h"
#include "cfilters.h"
#include "connect.h"
#include "multiif.h"
@@ -165,9 +165,9 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
if(winner != &ctx->h21_baller)
cf_hc_baller_reset(&ctx->h21_baller, data);
- DEBUGF(LOG_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
- winner->name, (int)Curl_timediff(Curl_now(), winner->started),
- cf_hc_baller_reply_ms(winner, data)));
+ CURL_TRC_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
+ winner->name, (int)Curl_timediff(Curl_now(), winner->started),
+ cf_hc_baller_reply_ms(winner, data));
cf->next = winner->cf;
winner->cf = NULL;
@@ -218,16 +218,16 @@ static bool time_to_start_h21(struct Curl_cfilter *cf,
elapsed_ms = Curl_timediff(now, ctx->started);
if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) {
- DEBUGF(LOG_CF(data, cf, "hard timeout of %dms reached, starting h21",
- ctx->hard_eyeballs_timeout_ms));
+ CURL_TRC_CF(data, cf, "hard timeout of %dms reached, starting h21",
+ ctx->hard_eyeballs_timeout_ms);
return TRUE;
}
if(elapsed_ms >= ctx->soft_eyeballs_timeout_ms) {
if(cf_hc_baller_reply_ms(&ctx->h3_baller, data) < 0) {
- DEBUGF(LOG_CF(data, cf, "soft timeout of %dms reached, h3 has not "
- "seen any data, starting h21",
- ctx->soft_eyeballs_timeout_ms));
+ CURL_TRC_CF(data, cf, "soft timeout of %dms reached, h3 has not "
+ "seen any data, starting h21",
+ ctx->soft_eyeballs_timeout_ms);
return TRUE;
}
/* set the effective hard timeout again */
@@ -258,7 +258,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
DEBUGASSERT(!ctx->h3_baller.cf);
DEBUGASSERT(!ctx->h21_baller.cf);
DEBUGASSERT(!cf->next);
- DEBUGF(LOG_CF(data, cf, "connect, init"));
+ CURL_TRC_CF(data, cf, "connect, init");
ctx->started = now;
if(ctx->h3_baller.enabled) {
cf_hc_baller_init(&ctx->h3_baller, cf, data, "h3", TRNSPRT_QUIC);
@@ -286,7 +286,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
}
if(cf_hc_baller_is_active(&ctx->h21_baller)) {
- DEBUGF(LOG_CF(data, cf, "connect, check h21"));
+ CURL_TRC_CF(data, cf, "connect, check h21");
result = cf_hc_baller_connect(&ctx->h21_baller, cf, data, done);
if(!result && *done) {
result = baller_connected(cf, data, &ctx->h21_baller);
@@ -297,7 +297,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
if((!ctx->h3_baller.enabled || ctx->h3_baller.result) &&
(!ctx->h21_baller.enabled || ctx->h21_baller.result)) {
/* both failed or disabled. we give up */
- DEBUGF(LOG_CF(data, cf, "connect, all failed"));
+ CURL_TRC_CF(data, cf, "connect, all failed");
result = ctx->result = ctx->h3_baller.enabled?
ctx->h3_baller.result : ctx->h21_baller.result;
ctx->state = CF_HC_FAILURE;
@@ -321,7 +321,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
}
out:
- DEBUGF(LOG_CF(data, cf, "connect -> %d, done=%d", result, *done));
+ CURL_TRC_CF(data, cf, "connect -> %d, done=%d", result, *done);
return result;
}
@@ -345,7 +345,7 @@ static int cf_hc_get_select_socks(struct Curl_cfilter *cf,
if(!cf_hc_baller_is_active(b))
continue;
brc = Curl_conn_cf_get_select_socks(b->cf, data, bsocks);
- DEBUGF(LOG_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc));
+ CURL_TRC_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc);
if(!brc)
continue;
for(j = 0; j < MAX_SOCKSPEREASYHANDLE && s < MAX_SOCKSPEREASYHANDLE; ++j) {
@@ -359,7 +359,7 @@ static int cf_hc_get_select_socks(struct Curl_cfilter *cf,
}
}
}
- DEBUGF(LOG_CF(data, cf, "get_selected_socks -> %x", rc));
+ CURL_TRC_CF(data, cf, "get_selected_socks -> %x", rc);
return rc;
}
@@ -371,7 +371,7 @@ static bool cf_hc_data_pending(struct Curl_cfilter *cf,
if(cf->connected)
return cf->next->cft->has_data_pending(cf->next, data);
- DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data_pending"));
+ CURL_TRC_CF((struct Curl_easy *)data, cf, "data_pending");
return cf_hc_baller_data_pending(&ctx->h3_baller, data)
|| cf_hc_baller_data_pending(&ctx->h21_baller, data);
}
@@ -427,7 +427,7 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf,
static void cf_hc_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- DEBUGF(LOG_CF(data, cf, "close"));
+ CURL_TRC_CF(data, cf, "close");
cf_hc_reset(cf, data);
cf->connected = FALSE;
@@ -442,7 +442,7 @@ static void cf_hc_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
struct cf_hc_ctx *ctx = cf->ctx;
(void)data;
- DEBUGF(LOG_CF(data, cf, "destroy"));
+ CURL_TRC_CF(data, cf, "destroy");
cf_hc_reset(cf, data);
Curl_safefree(ctx);
}
@@ -450,7 +450,7 @@ static void cf_hc_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
struct Curl_cftype Curl_cft_http_connect = {
"HTTPS-CONNECT",
0,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
cf_hc_destroy,
cf_hc_connect,
cf_hc_close,
diff --git a/libs/libcurl/src/cf-socket.c b/libs/libcurl/src/cf-socket.c
index 78b0c48fcb..00fb06b2ff 100644
--- a/libs/libcurl/src/cf-socket.c
+++ b/libs/libcurl/src/cf-socket.c
@@ -71,6 +71,7 @@
#include "warnless.h"
#include "conncache.h"
#include "multihandle.h"
+#include "rand.h"
#include "share.h"
#include "version_win32.h"
@@ -390,6 +391,7 @@ void Curl_sndbufset(curl_socket_t sockfd)
}
#endif
+#ifndef CURL_DISABLE_BINDLOCAL
static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sockfd, int af, unsigned int scope)
{
@@ -444,29 +446,24 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
/* interface */
if(!is_host) {
#ifdef SO_BINDTODEVICE
- /* I am not sure any other OSs than Linux that provide this feature,
- * and at the least I cannot test. --Ben
- *
- * This feature allows one to tightly bind the local socket to a
- * particular interface. This will force even requests to other
- * local interfaces to go out the external interface.
- *
- *
- * Only bind to the interface when specified as interface, not just
- * as a hostname or ip address.
+ /*
+ * This binds the local socket to a particular interface. This will
+ * force even requests to other local interfaces to go out the external
+ * interface. Only bind to the interface when specified as interface,
+ * not just as a hostname or ip address.
*
- * interface might be a VRF, eg: vrf-blue, which means it cannot be
- * converted to an IP address and would fail Curl_if2ip. Simply try
- * to use it straight away.
+ * The interface might be a VRF, eg: vrf-blue, which means it cannot be
+ * converted to an IP address and would fail Curl_if2ip. Simply try to
+ * use it straight away.
*/
if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
dev, (curl_socklen_t)strlen(dev) + 1) == 0) {
- /* This is typically "errno 1, error: Operation not permitted" if
- * you're not running as root or another suitable privileged
- * user.
- * If it succeeds it means the parameter was a valid interface and
- * not an IP address. Return immediately.
+ /* This is often "errno 1, error: Operation not permitted" if you're
+ * not running as root or another suitable privileged user. If it
+ * succeeds it means the parameter was a valid interface and not an IP
+ * address. Return immediately.
*/
+ infof(data, "socket successfully bound to interface '%s'", dev);
return CURLE_OK;
}
#endif
@@ -632,8 +629,8 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
port++; /* try next port */
if(port == 0)
break;
- infof(data, "Bind to local port %hu failed, trying next", port - 1);
- /* We re-use/clobber the port variable here below */
+ infof(data, "Bind to local port %d failed, trying next", port - 1);
+ /* We reuse/clobber the port variable here below */
if(sock->sa_family == AF_INET)
si4->sin_port = ntohs(port);
#ifdef ENABLE_IPV6
@@ -653,6 +650,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
return CURLE_INTERFACE_FAILED;
}
+#endif
/*
* verifyconnect() returns TRUE if the connect really has happened.
@@ -727,8 +725,6 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
static CURLcode socket_connect_result(struct Curl_easy *data,
const char *ipaddress, int error)
{
- char buffer[STRERROR_LEN];
-
switch(error) {
case EINPROGRESS:
case EWOULDBLOCK:
@@ -745,8 +741,15 @@ static CURLcode socket_connect_result(struct Curl_easy *data,
default:
/* unknown error, fallthrough and try another address! */
- infof(data, "Immediate connect fail for %s: %s",
- ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)ipaddress;
+#else
+ {
+ char buffer[STRERROR_LEN];
+ infof(data, "Immediate connect fail for %s: %s",
+ ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
+ }
+#endif
data->state.os_errno = error;
/* connect failed */
return CURLE_COULDNT_CONNECT;
@@ -775,6 +778,10 @@ struct cf_socket_ctx {
struct curltime connected_at; /* when socket connected/got first byte */
struct curltime first_byte_at; /* when first byte was recvd */
int error; /* errno of last failure or 0 */
+#ifdef DEBUGBUILD
+ int wblock_percent; /* percent of writes doing EAGAIN */
+ int wpartial_percent; /* percent of bytes written in send */
+#endif
BIT(got_first_byte); /* if first byte was received */
BIT(accepted); /* socket was accepted, not connected */
BIT(active);
@@ -790,6 +797,22 @@ static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
ctx->transport = transport;
Curl_sock_assign_addr(&ctx->addr, ai, transport);
Curl_bufq_init(&ctx->recvbuf, NW_RECV_CHUNK_SIZE, NW_RECV_CHUNKS);
+#ifdef DEBUGBUILD
+ {
+ char *p = getenv("CURL_DBG_SOCK_WBLOCK");
+ if(p) {
+ long l = strtol(p, NULL, 10);
+ if(l >= 0 && l <= 100)
+ ctx->wblock_percent = (int)l;
+ }
+ p = getenv("CURL_DBG_SOCK_WPARTIAL");
+ if(p) {
+ long l = strtol(p, NULL, 10);
+ if(l >= 0 && l <= 100)
+ ctx->wpartial_percent = (int)l;
+ }
+ }
+#endif
}
struct reader_ctx {
@@ -836,8 +859,8 @@ static ssize_t nw_in_read(void *reader_ctx,
nread = -1;
}
}
- DEBUGF(LOG_CF(rctx->data, rctx->cf, "nw_in_read(len=%zu) -> %d, err=%d",
- len, (int)nread, *err));
+ CURL_TRC_CF(rctx->data, rctx->cf, "nw_in_read(len=%zu) -> %d, err=%d",
+ len, (int)nread, *err);
return nread;
}
@@ -852,14 +875,14 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
* closed it) and we just forget about it.
*/
if(ctx->sock == cf->conn->sock[cf->sockindex]) {
- DEBUGF(LOG_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
- ", active)", ctx->sock));
+ CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
+ ", active)", ctx->sock);
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
}
else {
- DEBUGF(LOG_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
- ") no longer at conn->sock[], discarding", ctx->sock));
+ CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
+ ") no longer at conn->sock[], discarding", ctx->sock);
/* TODO: we do not want this to happen. Need to check which
* code is messing with conn->sock[cf->sockindex] */
}
@@ -869,8 +892,8 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
}
else {
/* this is our local socket, we did never publish it */
- DEBUGF(LOG_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
- ", not active)", ctx->sock));
+ CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
+ ", not active)", ctx->sock);
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
ctx->sock = CURL_SOCKET_BAD;
}
@@ -889,7 +912,7 @@ static void cf_socket_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
struct cf_socket_ctx *ctx = cf->ctx;
cf_socket_close(cf, data);
- DEBUGF(LOG_CF(data, cf, "destroy"));
+ CURL_TRC_CF(data, cf, "destroy");
Curl_bufq_free(&ctx->recvbuf);
free(ctx);
cf->ctx = NULL;
@@ -957,7 +980,6 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
bool isconnected = FALSE;
CURLcode result = CURLE_COULDNT_CONNECT;
bool is_tcp;
- const char *ipmsg;
(void)data;
DEBUGASSERT(ctx->sock == CURL_SOCKET_BAD);
@@ -970,15 +992,20 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
if(result)
goto out;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ {
+ const char *ipmsg;
#ifdef ENABLE_IPV6
- if(ctx->addr.family == AF_INET6) {
- set_ipv6_v6only(ctx->sock, 0);
- ipmsg = " Trying [%s]:%d...";
+ if(ctx->addr.family == AF_INET6) {
+ set_ipv6_v6only(ctx->sock, 0);
+ ipmsg = " Trying [%s]:%d...";
+ }
+ else
+#endif
+ ipmsg = " Trying %s:%d...";
+ infof(data, ipmsg, ctx->r_ip, ctx->r_port);
}
- else
#endif
- ipmsg = " Trying %s:%d...";
- infof(data, ipmsg, ctx->r_ip, ctx->r_port);
#ifdef ENABLE_IPV6
is_tcp = (ctx->addr.family == AF_INET
@@ -1014,6 +1041,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
}
}
+#ifndef CURL_DISABLE_BINDLOCAL
/* possibly bind the local end to an IP, interface or port */
if(ctx->addr.family == AF_INET
#ifdef ENABLE_IPV6
@@ -1031,6 +1059,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
goto out;
}
}
+#endif
/* set socket non-blocking */
(void)curlx_nonblock(ctx->sock, TRUE);
@@ -1047,8 +1076,8 @@ out:
ctx->connected_at = Curl_now();
cf->connected = TRUE;
}
- DEBUGF(LOG_CF(data, cf, "cf_socket_open() -> %d, fd=%" CURL_FORMAT_SOCKET_T,
- result, ctx->sock));
+ CURL_TRC_CF(data, cf, "cf_socket_open() -> %d, fd=%" CURL_FORMAT_SOCKET_T,
+ result, ctx->sock);
return result;
}
@@ -1155,7 +1184,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
rc = SOCKET_WRITABLE(ctx->sock, 0);
if(rc == 0) { /* no connection yet */
- DEBUGF(LOG_CF(data, cf, "not connected yet"));
+ CURL_TRC_CF(data, cf, "not connected yet");
return CURLE_OK;
}
else if(rc == CURL_CSELECT_OUT || cf->conn->bits.tcp_fastopen) {
@@ -1165,7 +1194,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
set_local_ip(cf, data);
*done = TRUE;
cf->connected = TRUE;
- DEBUGF(LOG_CF(data, cf, "connected"));
+ CURL_TRC_CF(data, cf, "connected");
return CURLE_OK;
}
}
@@ -1245,11 +1274,34 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
struct cf_socket_ctx *ctx = cf->ctx;
curl_socket_t fdsave;
ssize_t nwritten;
+ size_t orig_len = len;
*err = CURLE_OK;
fdsave = cf->conn->sock[cf->sockindex];
cf->conn->sock[cf->sockindex] = ctx->sock;
+#ifdef DEBUGBUILD
+ /* simulate network blocking/partial writes */
+ if(ctx->wblock_percent > 0) {
+ unsigned char c;
+ Curl_rand(data, &c, 1);
+ if(c >= ((100-ctx->wblock_percent)*256/100)) {
+ CURL_TRC_CF(data, cf, "send(len=%zu) SIMULATE EWOULDBLOCK", orig_len);
+ *err = CURLE_AGAIN;
+ nwritten = -1;
+ cf->conn->sock[cf->sockindex] = fdsave;
+ return nwritten;
+ }
+ }
+ if(cf->cft != &Curl_cft_udp && ctx->wpartial_percent > 0 && len > 8) {
+ len = len * ctx->wpartial_percent / 100;
+ if(!len)
+ len = 1;
+ CURL_TRC_CF(data, cf, "send(len=%zu) SIMULATE partial write of %zu bytes",
+ orig_len, len);
+ }
+#endif
+
#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
if(cf->conn->bits.tcp_fastopen) {
nwritten = sendto(ctx->sock, buf, len, MSG_FASTOPEN,
@@ -1288,8 +1340,8 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
}
}
- DEBUGF(LOG_CF(data, cf, "send(len=%zu) -> %d, err=%d",
- len, (int)nwritten, *err));
+ CURL_TRC_CF(data, cf, "send(len=%zu) -> %d, err=%d",
+ orig_len, (int)nwritten, *err);
cf->conn->sock[cf->sockindex] = fdsave;
return nwritten;
}
@@ -1307,7 +1359,7 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
cf->conn->sock[cf->sockindex] = ctx->sock;
if(ctx->buffer_recv && !Curl_bufq_is_empty(&ctx->recvbuf)) {
- DEBUGF(LOG_CF(data, cf, "recv from buffer"));
+ CURL_TRC_CF(data, cf, "recv from buffer");
nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
}
else {
@@ -1324,7 +1376,7 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
if(nwritten < 0 && !Curl_bufq_is_empty(&ctx->recvbuf)) {
/* we have a partial read with an error. need to deliver
* what we got, return the error later. */
- DEBUGF(LOG_CF(data, cf, "partial read: empty buffer first"));
+ CURL_TRC_CF(data, cf, "partial read: empty buffer first");
nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
}
else if(nwritten < 0) {
@@ -1337,7 +1389,7 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
nread = 0;
}
else {
- DEBUGF(LOG_CF(data, cf, "buffered %zd additional bytes", nwritten));
+ CURL_TRC_CF(data, cf, "buffered %zd additional bytes", nwritten);
nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
}
}
@@ -1347,8 +1399,8 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
}
out:
- DEBUGF(LOG_CF(data, cf, "recv(len=%zu) -> %d, err=%d", len, (int)nread,
- *err));
+ CURL_TRC_CF(data, cf, "recv(len=%zu) -> %d, err=%d", len, (int)nread,
+ *err);
if(nread > 0 && !ctx->got_first_byte) {
ctx->first_byte_at = Curl_now();
ctx->got_first_byte = TRUE;
@@ -1455,19 +1507,19 @@ static bool cf_socket_conn_is_alive(struct Curl_cfilter *cf,
r = Curl_poll(pfd, 1, 0);
if(r < 0) {
- DEBUGF(LOG_CF(data, cf, "is_alive: poll error, assume dead"));
+ CURL_TRC_CF(data, cf, "is_alive: poll error, assume dead");
return FALSE;
}
else if(r == 0) {
- DEBUGF(LOG_CF(data, cf, "is_alive: poll timeout, assume alive"));
+ CURL_TRC_CF(data, cf, "is_alive: poll timeout, assume alive");
return TRUE;
}
else if(pfd[0].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL)) {
- DEBUGF(LOG_CF(data, cf, "is_alive: err/hup/etc events, assume dead"));
+ CURL_TRC_CF(data, cf, "is_alive: err/hup/etc events, assume dead");
return FALSE;
}
- DEBUGF(LOG_CF(data, cf, "is_alive: valid events, looks alive"));
+ CURL_TRC_CF(data, cf, "is_alive: valid events, looks alive");
*input_pending = TRUE;
return TRUE;
}
@@ -1520,7 +1572,7 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
struct Curl_cftype Curl_cft_tcp = {
"TCP",
CF_TYPE_IP_CONNECT,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
cf_socket_destroy,
cf_tcp_connect,
cf_socket_close,
@@ -1581,10 +1633,10 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
return socket_connect_result(data, ctx->r_ip, SOCKERRNO);
}
set_local_ip(cf, data);
- DEBUGF(LOG_CF(data, cf, "%s socket %" CURL_FORMAT_SOCKET_T
- " connected: [%s:%d] -> [%s:%d]",
- (ctx->transport == TRNSPRT_QUIC)? "QUIC" : "UDP",
- ctx->sock, ctx->l_ip, ctx->l_port, ctx->r_ip, ctx->r_port));
+ CURL_TRC_CF(data, cf, "%s socket %" CURL_FORMAT_SOCKET_T
+ " connected: [%s:%d] -> [%s:%d]",
+ (ctx->transport == TRNSPRT_QUIC)? "QUIC" : "UDP",
+ ctx->sock, ctx->l_ip, ctx->l_port, ctx->r_ip, ctx->r_port);
(void)curlx_nonblock(ctx->sock, TRUE);
switch(ctx->addr.family) {
@@ -1624,7 +1676,7 @@ static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
if(ctx->sock == CURL_SOCKET_BAD) {
result = cf_socket_open(cf, data);
if(result) {
- DEBUGF(LOG_CF(data, cf, "cf_udp_connect(), open failed -> %d", result));
+ CURL_TRC_CF(data, cf, "cf_udp_connect(), open failed -> %d", result);
goto out;
}
@@ -1632,13 +1684,13 @@ static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
result = cf_udp_setup_quic(cf, data);
if(result)
goto out;
- DEBUGF(LOG_CF(data, cf, "cf_udp_connect(), opened socket=%"
- CURL_FORMAT_SOCKET_T " (%s:%d)",
- ctx->sock, ctx->l_ip, ctx->l_port));
+ CURL_TRC_CF(data, cf, "cf_udp_connect(), opened socket=%"
+ CURL_FORMAT_SOCKET_T " (%s:%d)",
+ ctx->sock, ctx->l_ip, ctx->l_port);
}
else {
- DEBUGF(LOG_CF(data, cf, "cf_udp_connect(), opened socket=%"
- CURL_FORMAT_SOCKET_T " (unconnected)", ctx->sock));
+ CURL_TRC_CF(data, cf, "cf_udp_connect(), opened socket=%"
+ CURL_FORMAT_SOCKET_T " (unconnected)", ctx->sock);
}
*done = TRUE;
cf->connected = TRUE;
@@ -1650,7 +1702,7 @@ out:
struct Curl_cftype Curl_cft_udp = {
"UDP",
CF_TYPE_IP_CONNECT,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
cf_socket_destroy,
cf_udp_connect,
cf_socket_close,
@@ -1701,7 +1753,7 @@ out:
struct Curl_cftype Curl_cft_unix = {
"UNIX",
CF_TYPE_IP_CONNECT,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
cf_socket_destroy,
cf_tcp_connect,
cf_socket_close,
@@ -1765,7 +1817,7 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
struct Curl_cftype Curl_cft_tcp_accept = {
"TCP-ACCEPT",
CF_TYPE_IP_CONNECT,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
cf_socket_destroy,
cf_tcp_accept_connect,
cf_socket_close,
@@ -1810,8 +1862,8 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
ctx->active = TRUE;
ctx->connected_at = Curl_now();
cf->connected = TRUE;
- DEBUGF(LOG_CF(data, cf, "Curl_conn_tcp_listen_set(%"
- CURL_FORMAT_SOCKET_T ")", ctx->sock));
+ CURL_TRC_CF(data, cf, "Curl_conn_tcp_listen_set(%"
+ CURL_FORMAT_SOCKET_T ")", ctx->sock);
out:
if(result) {
@@ -1875,9 +1927,9 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
ctx->accepted = TRUE;
ctx->connected_at = Curl_now();
cf->connected = TRUE;
- DEBUGF(LOG_CF(data, cf, "accepted_set(sock=%" CURL_FORMAT_SOCKET_T
- ", remote=%s port=%d)",
- ctx->sock, ctx->r_ip, ctx->r_port));
+ CURL_TRC_CF(data, cf, "accepted_set(sock=%" CURL_FORMAT_SOCKET_T
+ ", remote=%s port=%d)",
+ ctx->sock, ctx->r_ip, ctx->r_port);
return CURLE_OK;
}
@@ -1922,4 +1974,3 @@ CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
}
return CURLE_FAILED_INIT;
}
-
diff --git a/libs/libcurl/src/cfilters.c b/libs/libcurl/src/cfilters.c
index e12aa2019a..3121673ed1 100644
--- a/libs/libcurl/src/cfilters.c
+++ b/libs/libcurl/src/cfilters.c
@@ -238,7 +238,7 @@ void Curl_conn_cf_add(struct Curl_easy *data,
cf->conn = conn;
cf->sockindex = index;
conn->cfilter[index] = cf;
- DEBUGF(LOG_CF(data, cf, "added"));
+ CURL_TRC_CF(data, cf, "added");
}
void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
@@ -646,4 +646,3 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
&n, NULL) : CURLE_UNKNOWN_OPTION;
return (result || n <= 0)? 1 : (size_t)n;
}
-
diff --git a/libs/libcurl/src/config-amigaos.h b/libs/libcurl/src/config-amigaos.h
index 72ee0c0f9c..2d86531ffc 100644
--- a/libs/libcurl/src/config-amigaos.h
+++ b/libs/libcurl/src/config-amigaos.h
@@ -40,7 +40,6 @@
#define HAVE_NETINET_IN_H 1
#define HAVE_NET_IF_H 1
#define HAVE_PWD_H 1
-#define HAVE_RAND_EGD 1
#define HAVE_SELECT 1
#define HAVE_SETJMP_H 1
#define HAVE_SIGNAL 1
diff --git a/libs/libcurl/src/config-mac.h b/libs/libcurl/src/config-mac.h
index 2febf69878..bd457187db 100644
--- a/libs/libcurl/src/config-mac.h
+++ b/libs/libcurl/src/config-mac.h
@@ -77,8 +77,6 @@
#define CURL_DISABLE_LDAP 1
-#define HAVE_RAND_EGD 1
-
#define HAVE_IOCTL_FIONBIO 1
#define SIZEOF_INT 4
diff --git a/libs/libcurl/src/config-os400.h b/libs/libcurl/src/config-os400.h
index a15a9854bb..35e95018a9 100644
--- a/libs/libcurl/src/config-os400.h
+++ b/libs/libcurl/src/config-os400.h
@@ -68,9 +68,6 @@
/* Define this as a suitable file to read random data from */
#undef RANDOM_FILE
-/* Define this to your Entropy Gathering Daemon socket pathname */
-#undef EGD_SOCKET
-
/* Define to 1 if you have the alarm function. */
#define HAVE_ALARM 1
@@ -143,9 +140,6 @@
/* Define if you have the <pwd.h> header file. */
#define HAVE_PWD_H
-/* Define if you have the `RAND_egd' function. */
-#undef HAVE_RAND_EGD
-
/* Define if you have the `select' function. */
#define HAVE_SELECT
@@ -161,9 +155,6 @@
/* Define if you have the `socket' function. */
#define HAVE_SOCKET
-/* Define if you have the <ssl.h> header file. */
-#undef HAVE_SSL_H
-
/* Define if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
@@ -347,9 +338,6 @@
/* Define to the function return type for send. */
#define SEND_TYPE_RETV int
-/* Define to use the GSKit package. */
-#define USE_GSKIT
-
/* Define to use the OS/400 crypto library. */
#define USE_OS400CRYPTO
diff --git a/libs/libcurl/src/config-riscos.h b/libs/libcurl/src/config-riscos.h
index e855f90b10..fdd22e2723 100644
--- a/libs/libcurl/src/config-riscos.h
+++ b/libs/libcurl/src/config-riscos.h
@@ -66,9 +66,6 @@
/* Define this as a suitable file to read random data from */
#undef RANDOM_FILE
-/* Define this to your Entropy Gathering Daemon socket pathname */
-#undef EGD_SOCKET
-
/* Define if you want to enable IPv6 support */
#undef ENABLE_IPV6
@@ -135,9 +132,6 @@
/* Define if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
-/* Define if you have the `RAND_egd' function. */
-#undef HAVE_RAND_EGD
-
/* Define if you have the `select' function. */
#define HAVE_SELECT
@@ -153,9 +147,6 @@
/* Define if you have the `socket' function. */
#define HAVE_SOCKET
-/* Define if you have the <ssl.h> header file. */
-#undef HAVE_SSL_H
-
/* Define if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h
index 5536ebfa7a..96ca1547d3 100644
--- a/libs/libcurl/src/config-win32.h
+++ b/libs/libcurl/src/config-win32.h
@@ -71,9 +71,6 @@
/* Define if you have the <signal.h> header file. */
#define HAVE_SIGNAL_H 1
-/* Define if you have the <ssl.h> header file. */
-/* #define HAVE_SSL_H 1 */
-
/* Define to 1 if you have the <stdbool.h> header file. */
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || \
defined(__MINGW64_VERSION_MAJOR)
@@ -205,10 +202,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
@@ -627,9 +620,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 c5bc28543e..2b072d060f 100644
--- a/libs/libcurl/src/config-win32ce.h
+++ b/libs/libcurl/src/config-win32ce.h
@@ -53,9 +53,6 @@
/* Define if you have the <signal.h> header file. */
#define HAVE_SIGNAL_H 1
-/* Define if you have the <ssl.h> header file. */
-/* #define HAVE_SSL_H 1 */
-
/* Define if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c
index 52739b9783..696bd8483b 100644
--- a/libs/libcurl/src/connect.c
+++ b/libs/libcurl/src/connect.c
@@ -381,6 +381,11 @@ struct cf_he_ctx {
struct curltime started;
};
+/* when there are more than one IP address left to use, this macro returns how
+ much of the given timeout to spend on *this* attempt */
+#define TIMEOUT_LARGE 600
+#define USETIME(ms) ((ms > TIMEOUT_LARGE) ? (ms / 2) : ms)
+
static CURLcode eyeballer_new(struct eyeballer **pballer,
cf_ip_connect_create *cf_create,
const struct Curl_addrinfo *addr,
@@ -408,7 +413,7 @@ static CURLcode eyeballer_new(struct eyeballer **pballer,
baller->primary = primary;
baller->delay_ms = delay_ms;
baller->timeoutms = addr_next_match(baller->addr, baller->ai_family)?
- timeout_ms / 2 : timeout_ms;
+ USETIME(timeout_ms) : timeout_ms;
baller->timeout_id = timeout_id;
baller->result = CURLE_COULDNT_CONNECT;
@@ -475,7 +480,7 @@ static void baller_initiate(struct Curl_cfilter *cf,
out:
if(result) {
- DEBUGF(LOG_CF(data, cf, "%s failed", baller->name));
+ CURL_TRC_CF(data, cf, "%s failed", baller->name);
baller_close(baller, data);
}
if(cf_prev)
@@ -501,7 +506,7 @@ static CURLcode baller_start(struct Curl_cfilter *cf,
while(baller->addr) {
baller->started = Curl_now();
baller->timeoutms = addr_next_match(baller->addr, baller->ai_family) ?
- timeoutms / 2 : timeoutms;
+ USETIME(timeoutms) : timeoutms;
baller_initiate(cf, data, baller);
if(!baller->result)
break;
@@ -601,8 +606,8 @@ evaluate:
continue;
}
baller->result = baller_connect(cf, data, baller, &now, connected);
- DEBUGF(LOG_CF(data, cf, "%s connect -> %d, connected=%d",
- baller->name, baller->result, *connected));
+ CURL_TRC_CF(data, cf, "%s connect -> %d, connected=%d",
+ baller->name, baller->result, *connected);
if(!baller->result) {
if(*connected) {
@@ -623,11 +628,11 @@ evaluate:
}
baller_start_next(cf, data, baller, Curl_timeleft(data, &now, TRUE));
if(baller->is_done) {
- DEBUGF(LOG_CF(data, cf, "%s done", baller->name));
+ CURL_TRC_CF(data, cf, "%s done", baller->name);
}
else {
/* next attempt was started */
- DEBUGF(LOG_CF(data, cf, "%s trying next", baller->name));
+ CURL_TRC_CF(data, cf, "%s trying next", baller->name);
++ongoing;
}
}
@@ -661,12 +666,12 @@ evaluate:
Curl_timediff(now, ctx->started) >= baller->delay_ms) {
baller_start(cf, data, baller, Curl_timeleft(data, &now, TRUE));
if(baller->is_done) {
- DEBUGF(LOG_CF(data, cf, "%s done", baller->name));
+ CURL_TRC_CF(data, cf, "%s done", baller->name);
}
else {
- DEBUGF(LOG_CF(data, cf, "%s starting (timeout=%"
- CURL_FORMAT_TIMEDIFF_T "ms)",
- baller->name, baller->timeoutms));
+ CURL_TRC_CF(data, cf, "%s starting (timeout=%"
+ CURL_FORMAT_TIMEDIFF_T "ms)",
+ baller->name, baller->timeoutms);
++ongoing;
++added;
}
@@ -683,14 +688,14 @@ evaluate:
}
/* all ballers have failed to connect. */
- DEBUGF(LOG_CF(data, cf, "all eyeballers failed"));
+ CURL_TRC_CF(data, cf, "all eyeballers failed");
result = CURLE_COULDNT_CONNECT;
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
struct eyeballer *baller = ctx->baller[i];
- DEBUGF(LOG_CF(data, cf, "%s assess started=%d, result=%d",
- baller?baller->name:NULL,
- baller?baller->has_started:0,
- baller?baller->result:0));
+ CURL_TRC_CF(data, cf, "%s assess started=%d, result=%d",
+ baller?baller->name:NULL,
+ baller?baller->has_started:0,
+ baller?baller->result:0);
if(baller && baller->has_started && baller->result) {
result = baller->result;
break;
@@ -803,9 +808,9 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
timeout_ms, EXPIRE_DNS_PER_NAME);
if(result)
return result;
- DEBUGF(LOG_CF(data, cf, "created %s (timeout %"
- CURL_FORMAT_TIMEDIFF_T "ms)",
- ctx->baller[0]->name, ctx->baller[0]->timeoutms));
+ CURL_TRC_CF(data, cf, "created %s (timeout %"
+ CURL_FORMAT_TIMEDIFF_T "ms)",
+ ctx->baller[0]->name, ctx->baller[0]->timeoutms);
if(addr1) {
/* second one gets a delayed start */
result = eyeballer_new(&ctx->baller[1], ctx->cf_create, addr1, ai_family1,
@@ -815,9 +820,9 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
timeout_ms, EXPIRE_DNS_PER_NAME2);
if(result)
return result;
- DEBUGF(LOG_CF(data, cf, "created %s (timeout %"
- CURL_FORMAT_TIMEDIFF_T "ms)",
- ctx->baller[1]->name, ctx->baller[1]->timeoutms));
+ CURL_TRC_CF(data, cf, "created %s (timeout %"
+ CURL_FORMAT_TIMEDIFF_T "ms)",
+ ctx->baller[1]->name, ctx->baller[1]->timeoutms);
}
Curl_expire(data, data->set.happy_eyeballs_timeout,
@@ -931,7 +936,7 @@ static void cf_he_close(struct Curl_cfilter *cf,
{
struct cf_he_ctx *ctx = cf->ctx;
- DEBUGF(LOG_CF(data, cf, "close"));
+ CURL_TRC_CF(data, cf, "close");
cf_he_ctx_clear(cf, data);
cf->connected = FALSE;
ctx->state = SCFST_INIT;
@@ -1007,7 +1012,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf,
}
}
*pres1 = reply_ms;
- DEBUGF(LOG_CF(data, cf, "query connect reply: %dms", *pres1));
+ CURL_TRC_CF(data, cf, "query connect reply: %dms", *pres1);
return CURLE_OK;
}
case CF_QUERY_TIMER_CONNECT: {
@@ -1034,7 +1039,7 @@ static void cf_he_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_he_ctx *ctx = cf->ctx;
- DEBUGF(LOG_CF(data, cf, "destroy"));
+ CURL_TRC_CF(data, cf, "destroy");
if(ctx) {
cf_he_ctx_clear(cf, data);
}
@@ -1045,7 +1050,7 @@ static void cf_he_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
struct Curl_cftype Curl_cft_happy_eyeballs = {
"HAPPY-EYEBALLS",
0,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
cf_he_destroy,
cf_he_connect,
cf_he_close,
@@ -1148,7 +1153,7 @@ static CURLcode cf_he_insert_after(struct Curl_cfilter *cf_at,
DEBUGASSERT(cf_at);
cf_create = get_cf_create(transport);
if(!cf_create) {
- DEBUGF(LOG_CF(data, cf_at, "unsupported transport type %d", transport));
+ CURL_TRC_CF(data, cf_at, "unsupported transport type %d", transport);
return CURLE_UNSUPPORTED_PROTOCOL;
}
result = cf_happy_eyeballs_create(&cf, data, cf_at->conn,
@@ -1286,7 +1291,7 @@ static void cf_setup_close(struct Curl_cfilter *cf,
{
struct cf_setup_ctx *ctx = cf->ctx;
- DEBUGF(LOG_CF(data, cf, "close"));
+ CURL_TRC_CF(data, cf, "close");
cf->connected = FALSE;
ctx->state = CF_SETUP_INIT;
@@ -1301,7 +1306,7 @@ static void cf_setup_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
struct cf_setup_ctx *ctx = cf->ctx;
(void)data;
- DEBUGF(LOG_CF(data, cf, "destroy"));
+ CURL_TRC_CF(data, cf, "destroy");
Curl_safefree(ctx);
}
@@ -1309,7 +1314,7 @@ static void cf_setup_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
struct Curl_cftype Curl_cft_setup = {
"SETUP",
0,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
cf_setup_destroy,
cf_setup_connect,
cf_setup_close,
@@ -1441,4 +1446,3 @@ CURLcode Curl_conn_setup(struct Curl_easy *data,
out:
return result;
}
-
diff --git a/libs/libcurl/src/curl_base64.h b/libs/libcurl/src/curl_base64.h
index 70b6447dbb..6f9d341ae4 100644
--- a/libs/libcurl/src/curl_base64.h
+++ b/libs/libcurl/src/curl_base64.h
@@ -24,11 +24,18 @@
*
***************************************************************************/
+#ifndef BUILDING_LIBCURL
+/* this renames functions so that the tool code can use the same code
+ without getting symbol collisions */
+#define Curl_base64_encode(a,b,c,d) curlx_base64_encode(a,b,c,d)
+#define Curl_base64url_encode(a,b,c,d) curlx_base64url_encode(a,b,c,d)
+#define Curl_base64_decode(a,b,c) curlx_base64_decode(a,b,c)
+#endif
+
CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
char **outptr, size_t *outlen);
CURLcode Curl_base64url_encode(const char *inputbuff, size_t insize,
char **outptr, size_t *outlen);
CURLcode Curl_base64_decode(const char *src,
unsigned char **outptr, size_t *outlen);
-
#endif /* HEADER_CURL_BASE64_H */
diff --git a/libs/libcurl/src/curl_config.h.cmake b/libs/libcurl/src/curl_config.h.cmake
index 1b8490a578..c335aba6cf 100644
--- a/libs/libcurl/src/curl_config.h.cmake
+++ b/libs/libcurl/src/curl_config.h.cmake
@@ -32,14 +32,32 @@
/* Location of default ca path */
#cmakedefine CURL_CA_PATH "${CURL_CA_PATH}"
+/* Default SSL backend */
+#cmakedefine CURL_DEFAULT_SSL_BACKEND "${CURL_DEFAULT_SSL_BACKEND}"
+
/* disables alt-svc */
#cmakedefine CURL_DISABLE_ALTSVC 1
/* disables cookies support */
#cmakedefine CURL_DISABLE_COOKIES 1
-/* disables cryptographic authentication */
-#cmakedefine CURL_DISABLE_CRYPTO_AUTH 1
+/* disables Basic authentication */
+#cmakedefine CURL_DISABLE_BASIC_AUTH 1
+
+/* disables Bearer authentication */
+#cmakedefine CURL_DISABLE_BEARER_AUTH 1
+
+/* disables Digest authentication */
+#cmakedefine CURL_DISABLE_DIGEST_AUTH 1
+
+/* disables Kerberos authentication */
+#cmakedefine CURL_DISABLE_KERBEROS_AUTH 1
+
+/* disables negotiate authentication */
+#cmakedefine CURL_DISABLE_NEGOTIATE_AUTH 1
+
+/* disables AWS-SIG4 */
+#cmakedefine CURL_DISABLE_AWS 1
/* disables DICT */
#cmakedefine CURL_DISABLE_DICT 1
@@ -50,6 +68,9 @@
/* disables FILE */
#cmakedefine CURL_DISABLE_FILE 1
+/* disables form api */
+#cmakedefine CURL_DISABLE_FORM_API 1
+
/* disables FTP */
#cmakedefine CURL_DISABLE_FTP 1
@@ -132,12 +153,6 @@
/* Use Windows LDAP implementation */
#cmakedefine USE_WIN32_LDAP 1
-/* when not building a shared library */
-#cmakedefine CURL_STATICLIB 1
-
-/* your Entropy Gathering Daemon socket pathname */
-#cmakedefine EGD_SOCKET ${EGD_SOCKET}
-
/* Define if you want to enable IPv6 support */
#cmakedefine ENABLE_IPV6 1
@@ -397,8 +412,8 @@
/* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H 1
-/* Define to 1 if you have the `RAND_egd' function. */
-#cmakedefine HAVE_RAND_EGD 1
+/* Define to 1 if OpenSSL has the `SSL_set0_wbio` function. */
+#cmakedefine HAVE_SSL_SET0_WBIO 1
/* Define to 1 if you have the recv function. */
#cmakedefine HAVE_RECV 1
@@ -460,9 +475,6 @@
/* Define to 1 if you have the socketpair function. */
#cmakedefine HAVE_SOCKETPAIR 1
-/* Define to 1 if you have the <ssl.h> header file. */
-#cmakedefine HAVE_SSL_H 1
-
/* Define to 1 if you have the <stdatomic.h> header file. */
#cmakedefine HAVE_STDATOMIC_H 1
@@ -637,6 +649,9 @@ ${SIZEOF_INT_CODE}
/* The size of `long', as computed by sizeof. */
${SIZEOF_LONG_CODE}
+/* The size of `long long', as computed by sizeof. */
+${SIZEOF_LONG_LONG_CODE}
+
/* The size of `off_t', as computed by sizeof. */
${SIZEOF_OFF_T_CODE}
@@ -691,12 +706,6 @@ ${SIZEOF_TIME_T_CODE}
/* If you want to build curl with the built-in manual */
#cmakedefine USE_MANUAL 1
-/* if NSS is enabled */
-#cmakedefine USE_NSS 1
-
-/* if you have the PK11_CreateManagedGenericObject function */
-#cmakedefine HAVE_PK11_CREATEMANAGEDGENERICOBJECT 1
-
/* if you want to use OpenLDAP code instead of legacy ldap implementation */
#cmakedefine USE_OPENLDAP 1
diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in
index 6600a64fe3..d7b28336e8 100644
--- a/libs/libcurl/src/curl_config.h.in
+++ b/libs/libcurl/src/curl_config.h.in
@@ -18,21 +18,36 @@
/* disable alt-svc */
#undef CURL_DISABLE_ALTSVC
+/* to disable AWS sig support */
+#undef CURL_DISABLE_AWS
+
+/* to disable basic authentication */
+#undef CURL_DISABLE_BASIC_AUTH
+
+/* to disable bearer authentication */
+#undef CURL_DISABLE_BEARER_AUTH
+
+/* disable local binding support */
+#undef CURL_DISABLE_BINDLOCAL
+
/* to disable cookies support */
#undef CURL_DISABLE_COOKIES
-/* to disable cryptographic authentication */
-#undef CURL_DISABLE_CRYPTO_AUTH
-
/* to disable DICT */
#undef CURL_DISABLE_DICT
+/* to disable digest authentication */
+#undef CURL_DISABLE_DIGEST_AUTH
+
/* disable DoH */
#undef CURL_DISABLE_DOH
/* to disable FILE */
#undef CURL_DISABLE_FILE
+/* disable form API */
+#undef CURL_DISABLE_FORM_API
+
/* to disable FTP */
#undef CURL_DISABLE_FTP
@@ -57,6 +72,9 @@
/* to disable IMAP */
#undef CURL_DISABLE_IMAP
+/* to disable kerberos authentication */
+#undef CURL_DISABLE_KERBEROS_AUTH
+
/* to disable LDAP */
#undef CURL_DISABLE_LDAP
@@ -72,6 +90,9 @@
/* to disable MQTT */
#undef CURL_DISABLE_MQTT
+/* to disable negotiate authentication */
+#undef CURL_DISABLE_NEGOTIATE_AUTH
+
/* disable netrc parsing */
#undef CURL_DISABLE_NETRC
@@ -129,9 +150,6 @@
/* enable debug build options */
#undef DEBUGBUILD
-/* your Entropy Gathering Daemon socket pathname */
-#undef EGD_SOCKET
-
/* Define if you want to enable IPv6 support */
#undef ENABLE_IPV6
@@ -497,9 +515,6 @@
/* Define to 1 if you have the `pipe' function. */
#undef HAVE_PIPE
-/* if you have the PK11_CreateManagedGenericObject function */
-#undef HAVE_PK11_CREATEMANAGEDGENERICOBJECT
-
/* If you have a fine poll */
#undef HAVE_POLL_FINE
@@ -524,9 +539,6 @@
/* Define to 1 if you have the <quiche.h> header file. */
#undef HAVE_QUICHE_H
-/* Define to 1 if you have the `RAND_egd' function. */
-#undef HAVE_RAND_EGD
-
/* Define to 1 if you have the recv function. */
#undef HAVE_RECV
@@ -722,9 +734,6 @@
/* Define to 1 if compiler supports old gcc variadic macro style. */
#undef HAVE_VARIADIC_MACROS_GCC
-/* Define to 1 if you have the wincrypt.h header file. */
-#undef HAVE_WINCRYPT_H
-
/* Define to 1 if you have the windows.h header file. */
#undef HAVE_WINDOWS_H
@@ -895,9 +904,6 @@
/* if ngtcp2_crypto_wolfssl is in use */
#undef USE_NGTCP2_CRYPTO_WOLFSSL
-/* if NSS is enabled */
-#undef USE_NSS
-
/* Use OpenLDAP-specific code */
#undef USE_OPENLDAP
diff --git a/libs/libcurl/src/curl_des.c b/libs/libcurl/src/curl_des.c
index 36a6986e25..c92b1de174 100644
--- a/libs/libcurl/src/curl_des.c
+++ b/libs/libcurl/src/curl_des.c
@@ -24,12 +24,11 @@
#include "curl_setup.h"
-#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
- (defined(USE_GNUTLS) || \
- defined(USE_NSS) || \
- defined(USE_SECTRANSP) || \
- defined(USE_OS400CRYPTO) || \
- defined(USE_WIN32_CRYPTO))
+#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
+ (defined(USE_GNUTLS) || \
+ defined(USE_SECTRANSP) || \
+ defined(USE_OS400CRYPTO) || \
+ defined(USE_WIN32_CRYPTO))
#include "curl_des.h"
diff --git a/libs/libcurl/src/curl_des.h b/libs/libcurl/src/curl_des.h
index 01481c6945..520faf800a 100644
--- a/libs/libcurl/src/curl_des.h
+++ b/libs/libcurl/src/curl_des.h
@@ -26,12 +26,11 @@
#include "curl_setup.h"
-#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
- (defined(USE_GNUTLS) || \
- defined(USE_NSS) || \
- defined(USE_SECTRANSP) || \
- defined(USE_OS400CRYPTO) || \
- defined(USE_WIN32_CRYPTO))
+#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
+ (defined(USE_GNUTLS) || \
+ defined(USE_SECTRANSP) || \
+ defined(USE_OS400CRYPTO) || \
+ defined(USE_WIN32_CRYPTO))
/* Applies odd parity to the given byte array */
void Curl_des_set_odd_parity(unsigned char *bytes, size_t length);
diff --git a/libs/libcurl/src/curl_hmac.h b/libs/libcurl/src/curl_hmac.h
index 5d16ba6cde..6fe497554c 100644
--- a/libs/libcurl/src/curl_hmac.h
+++ b/libs/libcurl/src/curl_hmac.h
@@ -24,7 +24,8 @@
*
***************************************************************************/
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
+ || !defined(CURL_DISABLE_AWS)
#include <curl/curl.h>
diff --git a/libs/libcurl/src/curl_log.h b/libs/libcurl/src/curl_log.h
deleted file mode 100644
index 6ac4aac159..0000000000
--- a/libs/libcurl/src/curl_log.h
+++ /dev/null
@@ -1,121 +0,0 @@
-#ifndef HEADER_CURL_LOG_H
-#define HEADER_CURL_LOG_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 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.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-struct Curl_easy;
-struct Curl_cfilter;
-
-/**
- * Init logging, return != 0 on failure.
- */
-CURLcode Curl_log_init(void);
-
-
-void Curl_infof(struct Curl_easy *, const char *fmt, ...);
-void Curl_failf(struct Curl_easy *, const char *fmt, ...);
-
-#if defined(CURL_DISABLE_VERBOSE_STRINGS)
-
-#if defined(HAVE_VARIADIC_MACROS_C99)
-#define infof(...) Curl_nop_stmt
-#elif defined(HAVE_VARIADIC_MACROS_GCC)
-#define infof(x...) Curl_nop_stmt
-#else
-#error "missing VARIADIC macro define, fix and rebuild!"
-#endif
-
-#else /* CURL_DISABLE_VERBOSE_STRINGS */
-
-#define infof Curl_infof
-
-#endif /* CURL_DISABLE_VERBOSE_STRINGS */
-
-#define failf Curl_failf
-
-
-#define CURL_LOG_DEFAULT 0
-#define CURL_LOG_DEBUG 1
-#define CURL_LOG_TRACE 2
-
-
-/* the function used to output verbose information */
-void Curl_debug(struct Curl_easy *data, curl_infotype type,
- char *ptr, size_t size);
-
-#ifdef DEBUGBUILD
-
-/* explainer: we have some mix configuration and werror settings
- * that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
- * on gnuc and some other compiler. Need to treat carefully.
- */
-#if defined(HAVE_VARIADIC_MACROS_C99) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-
-#define LOG_CF(data, cf, ...) \
- do { if(Curl_log_cf_is_debug(cf, data)) \
- Curl_log_cf_debug(data, cf, __VA_ARGS__); } while(0)
-#else
-#define LOG_CF Curl_log_cf_debug
-#endif
-
-void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
-#if defined(__GNUC__) && !defined(printf) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
- !defined(__MINGW32__)
- const char *fmt, ...)
- __attribute__((format(printf, 3, 4)));
-#else
- const char *fmt, ...);
-#endif
-
-#define Curl_log_cf_is_debug(cf, data) \
- ((data) && (data)->set.verbose && \
- (cf) && (cf)->cft->log_level >= CURL_LOG_DEBUG)
-
-
-#else /* !DEBUGBUILD */
-
-#if defined(HAVE_VARIADIC_MACROS_C99) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-#define LOG_CF(...) Curl_nop_stmt
-#define Curl_log_cf_debug(...) Curl_nop_stmt
-#elif defined(HAVE_VARIADIC_MACROS_GCC) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-#define LOG_CF(x...) Curl_nop_stmt
-#define Curl_log_cf_debug(x...) Curl_nop_stmt
-#else
-#define LOG_CF Curl_log_cf_debug
-/* without c99, we seem unable to completely define away this function. */
-void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
- const char *fmt, ...);
-#endif
-
-#define Curl_log_cf_is_debug(x,y) ((void)(x), (void)(y), FALSE)
-
-#endif /* !DEBUGBUILD */
-
-#define LOG_CF_IS_DEBUG(cf, data) Curl_log_cf_is_debug(cf, data)
-
-#endif /* HEADER_CURL_LOG_H */
diff --git a/libs/libcurl/src/curl_md4.h b/libs/libcurl/src/curl_md4.h
index 948a4e5798..0cc9f2c9dd 100644
--- a/libs/libcurl/src/curl_md4.h
+++ b/libs/libcurl/src/curl_md4.h
@@ -25,14 +25,15 @@
***************************************************************************/
#include "curl_setup.h"
+#include <curl/curl.h>
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if defined(USE_CURL_NTLM_CORE)
#define MD4_DIGEST_LENGTH 16
-void Curl_md4it(unsigned char *output, const unsigned char *input,
- const size_t len);
+CURLcode Curl_md4it(unsigned char *output, const unsigned char *input,
+ const size_t len);
-#endif /* !defined(CURL_DISABLE_CRYPTO_AUTH) */
+#endif /* defined(USE_CURL_NTLM_CORE) */
#endif /* HEADER_CURL_MD4_H */
diff --git a/libs/libcurl/src/curl_md5.h b/libs/libcurl/src/curl_md5.h
index 356d5d3a78..7772b00eec 100644
--- a/libs/libcurl/src/curl_md5.h
+++ b/libs/libcurl/src/curl_md5.h
@@ -24,7 +24,9 @@
*
***************************************************************************/
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
+ || !defined(CURL_DISABLE_DIGEST_AUTH)
+
#include "curl_hmac.h"
#define MD5_DIGEST_LEN 16
diff --git a/libs/libcurl/src/curl_ntlm_core.c b/libs/libcurl/src/curl_ntlm_core.c
index 368b0e429c..d9c3acb7d8 100644
--- a/libs/libcurl/src/curl_ntlm_core.c
+++ b/libs/libcurl/src/curl_ntlm_core.c
@@ -38,7 +38,7 @@
1. USE_OPENSSL
2. USE_WOLFSSL
3. USE_GNUTLS
- 4. USE_NSS
+ 4. -
5. USE_MBEDTLS
6. USE_SECTRANSP
7. USE_OS400CRYPTO
@@ -47,7 +47,7 @@
This ensures that:
- the same SSL branch gets activated throughout this source
file even if multiple backends are enabled at the same time.
- - OpenSSL and NSS have higher priority than Windows Crypt, due
+ - OpenSSL has higher priority than Windows Crypt, due
to issues with the latter supporting NTLM2Session responses
in NTLM type-3 messages.
*/
@@ -96,12 +96,6 @@
# include <nettle/des.h>
-#elif defined(USE_NSS)
-
-# include <nss.h>
-# include <pk11pub.h>
-# include <hasht.h>
-
#elif defined(USE_MBEDTLS)
# include <mbedtls/des.h>
@@ -188,70 +182,6 @@ static void setup_des_key(const unsigned char *key_56,
des_set_key(des, (const uint8_t *) key);
}
-#elif defined(USE_NSS)
-
-/*
- * encrypt_des() expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of
- * data, using the expanded key. IN should point to 64 bits of source data,
- * OUT to a 64 bit output buffer.
- */
-static bool encrypt_des(const unsigned char *in, unsigned char *out,
- const unsigned char *key_56)
-{
- const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
- char key[8]; /* expanded 64 bit key */
- SECItem key_item;
- PK11SymKey *symkey = NULL;
- SECItem *param = NULL;
- PK11Context *ctx = NULL;
- int out_len; /* not used, required by NSS */
- bool rv = FALSE;
-
- /* use internal slot for DES encryption (requires NSS to be initialized) */
- PK11SlotInfo *slot = PK11_GetInternalKeySlot();
- if(!slot)
- return FALSE;
-
- /* Expand the 56-bit key to 64-bits */
- extend_key_56_to_64(key_56, key);
-
- /* Set the key parity to odd */
- Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
-
- /* Import the key */
- key_item.data = (unsigned char *)key;
- key_item.len = sizeof(key);
- symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
- &key_item, NULL);
- if(!symkey)
- goto fail;
-
- /* Create the DES encryption context */
- param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
- if(!param)
- goto fail;
- ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
- if(!ctx)
- goto fail;
-
- /* Perform the encryption */
- if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
- (unsigned char *)in, /* inbuflen */ 8)
- && SECSuccess == PK11_Finalize(ctx))
- rv = /* all OK */ TRUE;
-
-fail:
- /* cleanup */
- if(ctx)
- PK11_DestroyContext(ctx, PR_TRUE);
- if(symkey)
- PK11_FreeSymKey(symkey);
- if(param)
- SECITEM_FreeItem(param, PR_TRUE);
- PK11_FreeSlot(slot);
- return rv;
-}
-
#elif defined(USE_MBEDTLS)
static bool encrypt_des(const unsigned char *in, unsigned char *out,
@@ -402,7 +332,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
des_encrypt(&des, 8, results + 8, plaintext);
setup_des_key(keys + 14, &des);
des_encrypt(&des, 8, results + 16, plaintext);
-#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
+#elif defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(plaintext, results, keys);
encrypt_des(plaintext, results + 8, keys + 7);
@@ -444,7 +374,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
des_encrypt(&des, 8, lmbuffer, magic);
setup_des_key(pw + 7, &des);
des_encrypt(&des, 8, lmbuffer + 8, magic);
-#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
+#elif defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(magic, lmbuffer, pw);
encrypt_des(magic, lmbuffer + 8, pw + 7);
@@ -489,6 +419,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(const char *password,
{
size_t len = strlen(password);
unsigned char *pw;
+ CURLcode result;
if(len > SIZE_T_MAX/2) /* avoid integer overflow */
return CURLE_OUT_OF_MEMORY;
pw = len ? malloc(len * 2) : (unsigned char *)strdup("");
@@ -498,12 +429,13 @@ CURLcode Curl_ntlm_core_mk_nt_hash(const char *password,
ascii_to_unicode_le(pw, password, len);
/* Create NT hashed password. */
- Curl_md4it(ntbuffer, pw, 2 * len);
- memset(ntbuffer + 16, 0, 21 - 16);
+ result = Curl_md4it(ntbuffer, pw, 2 * len);
+ if(!result)
+ memset(ntbuffer + 16, 0, 21 - 16);
free(pw);
- return CURLE_OK;
+ return result;
}
#if !defined(USE_WINDOWS_SSPI)
diff --git a/libs/libcurl/src/curl_ntlm_core.h b/libs/libcurl/src/curl_ntlm_core.h
index f7a9ec1a3b..2df668c42f 100644
--- a/libs/libcurl/src/curl_ntlm_core.h
+++ b/libs/libcurl/src/curl_ntlm_core.h
@@ -28,15 +28,6 @@
#if defined(USE_CURL_NTLM_CORE)
-/* If NSS is the first available SSL backend (see order in curl_ntlm_core.c)
- then it must be initialized to be used by NTLM. */
-#if !defined(USE_OPENSSL) && \
- !defined(USE_WOLFSSL) && \
- !defined(USE_GNUTLS) && \
- defined(USE_NSS)
-#define NTLM_NEEDS_NSS_INIT
-#endif
-
#if defined(USE_OPENSSL)
# include <openssl/ssl.h>
#elif defined(USE_WOLFSSL)
diff --git a/libs/libcurl/src/curl_sasl.c b/libs/libcurl/src/curl_sasl.c
index ff05f250da..42de215900 100644
--- a/libs/libcurl/src/curl_sasl.c
+++ b/libs/libcurl/src/curl_sasl.c
@@ -420,7 +420,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
}
else
#endif
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifndef CURL_DISABLE_DIGEST_AUTH
if((enabledmechs & SASL_MECH_DIGEST_MD5) &&
Curl_auth_is_digest_supported()) {
mech = SASL_MECH_STRING_DIGEST_MD5;
@@ -530,8 +530,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
struct bufref resp;
const char *hostname, *disp_hostname;
int port;
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_NTLM)
+#if defined(USE_KERBEROS5) || defined(USE_NTLM) \
+ || !defined(CURL_DISABLE_DIGEST_AUTH)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
@@ -577,7 +577,6 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
case SASL_EXTERNAL:
result = Curl_auth_create_external_message(conn->user, &resp);
break;
-#ifndef CURL_DISABLE_CRYPTO_AUTH
#ifdef USE_GSASL
case SASL_GSASL:
result = get_server_message(sasl, data, &serverdata);
@@ -587,6 +586,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
newstate = SASL_GSASL;
break;
#endif
+#ifndef CURL_DISABLE_DIGEST_AUTH
case SASL_CRAMMD5:
result = get_server_message(sasl, data, &serverdata);
if(!result)
diff --git a/libs/libcurl/src/curl_setup.h b/libs/libcurl/src/curl_setup.h
index dd77b783f4..c85275d3c6 100644
--- a/libs/libcurl/src/curl_setup.h
+++ b/libs/libcurl/src/curl_setup.h
@@ -61,6 +61,16 @@
# ifndef NOGDI
# define NOGDI
# endif
+/* Detect Windows App environment which has a restricted access
+ * to the Win32 APIs. */
+# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
+ defined(WINAPI_FAMILY)
+# include <winapifamily.h>
+# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+ !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+# define CURL_WINDOWS_APP
+# endif
+# endif
#endif
/*
@@ -248,8 +258,9 @@
#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
+# if TARGET_OS_MAC && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && \
+ defined(ENABLE_IPV6)
+# define CURL_MACOS_CALL_COPYPROXIES 1
# endif
#endif
@@ -634,32 +645,30 @@
#define LIBIDN_REQUIRED_VERSION "0.4.1"
-#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
- defined(USE_MBEDTLS) || \
- defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \
- defined(USE_SECTRANSP) || defined(USE_GSKIT) || \
- defined(USE_BEARSSL) || defined(USE_RUSTLS)
+#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
+ defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
+ defined(USE_BEARSSL) || defined(USE_RUSTLS)
#define USE_SSL /* SSL support has been enabled */
#endif
/* Single point where USE_SPNEGO definition might be defined */
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
+#if !defined(CURL_DISABLE_NEGOTIATE_AUTH) && \
(defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
#define USE_SPNEGO
#endif
/* Single point where USE_KERBEROS5 definition might be defined */
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
+#if !defined(CURL_DISABLE_KERBEROS_AUTH) && \
(defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
#define USE_KERBEROS5
#endif
/* Single point where USE_NTLM definition might be defined */
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(CURL_DISABLE_NTLM)
-# if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
- defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
- defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
- (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
+#if !defined(CURL_DISABLE_NTLM)
+# if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
+ defined(USE_GNUTLS) || defined(USE_SECTRANSP) || \
+ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
+ (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
# define USE_CURL_NTLM_CORE
# endif
# if defined(USE_CURL_NTLM_CORE) || defined(USE_WINDOWS_SSPI)
diff --git a/libs/libcurl/src/curl_sha256.h b/libs/libcurl/src/curl_sha256.h
index 4c255f1baf..1f9d561386 100644
--- a/libs/libcurl/src/curl_sha256.h
+++ b/libs/libcurl/src/curl_sha256.h
@@ -25,7 +25,9 @@
*
***************************************************************************/
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
+ || defined(USE_LIBSSH2)
+
#include <curl/curl.h>
#include "curl_hmac.h"
diff --git a/libs/libcurl/src/curl_log.c b/libs/libcurl/src/curl_trc.c
index d6f2423cca..5cc56353a4 100644
--- a/libs/libcurl/src/curl_log.c
+++ b/libs/libcurl/src/curl_trc.c
@@ -26,7 +26,7 @@
#include <curl/curl.h>
-#include "curl_log.h"
+#include "curl_trc.h"
#include "urldata.h"
#include "easyif.h"
#include "cfilters.h"
@@ -124,13 +124,13 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
}
}
-#ifdef DEBUGBUILD
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
-void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
+void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...)
{
DEBUGASSERT(cf);
- if(data && Curl_log_cf_is_debug(cf, data)) {
+ if(data && Curl_trc_cf_is_verbose(cf, data)) {
va_list ap;
int len;
char buffer[MAXINFO + 2];
@@ -179,44 +179,67 @@ static struct Curl_cftype *cf_types[] = {
NULL,
};
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
-CURLcode Curl_log_init(void)
+CURLcode Curl_trc_opt(const char *config)
{
- const char *setting = getenv("CURL_DEBUG");
- if(setting) {
- char *token, *tok_buf, *tmp;
- size_t i;
-
- tmp = strdup(setting);
- if(!tmp)
- return CURLE_OUT_OF_MEMORY;
-
- token = strtok_r(tmp, ", ", &tok_buf);
- while(token) {
- for(i = 0; cf_types[i]; ++i) {
- if(strcasecompare(token, cf_types[i]->name)) {
- cf_types[i]->log_level = CURL_LOG_DEBUG;
- break;
- }
+ char *token, *tok_buf, *tmp;
+ size_t i;
+ int lvl;
+
+ tmp = strdup(config);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+
+ token = strtok_r(tmp, ", ", &tok_buf);
+ while(token) {
+ switch(*token) {
+ case '-':
+ lvl = CURL_LOG_LVL_NONE;
+ ++token;
+ break;
+ case '+':
+ lvl = CURL_LOG_LVL_INFO;
+ ++token;
+ break;
+ default:
+ lvl = CURL_LOG_LVL_INFO;
+ break;
+ }
+ for(i = 0; cf_types[i]; ++i) {
+ if(strcasecompare(token, "all")) {
+ cf_types[i]->log_level = lvl;
+ }
+ else if(strcasecompare(token, cf_types[i]->name)) {
+ cf_types[i]->log_level = lvl;
+ break;
}
- token = strtok_r(NULL, ", ", &tok_buf);
}
- free(tmp);
+ token = strtok_r(NULL, ", ", &tok_buf);
+ }
+ free(tmp);
+ return CURLE_OK;
+}
+
+CURLcode Curl_trc_init(void)
+{
+#ifdef DEBUGBUILD
+ /* WIP: we use the auto-init from an env var only in DEBUG builds for
+ * convenience. */
+ const char *config = getenv("CURL_DEBUG");
+ if(config) {
+ return Curl_trc_opt(config);
}
+#endif
return CURLE_OK;
}
-#else /* DEBUGBUILD */
+#else /* !CURL_DISABLE_VERBOSE_STRINGS) */
-CURLcode Curl_log_init(void)
+CURLcode Curl_trc_init(void)
{
return CURLE_OK;
}
#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
-void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
+void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...)
{
(void)data;
diff --git a/libs/libcurl/src/curl_trc.h b/libs/libcurl/src/curl_trc.h
new file mode 100644
index 0000000000..f9288a6a64
--- /dev/null
+++ b/libs/libcurl/src/curl_trc.h
@@ -0,0 +1,150 @@
+#ifndef HEADER_CURL_TRC_H
+#define HEADER_CURL_TRC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+struct Curl_easy;
+struct Curl_cfilter;
+
+/**
+ * Init logging, return != 0 on failure.
+ */
+CURLcode Curl_trc_init(void);
+
+/**
+ * Configure tracing. May be called several times during global
+ * initialization. Later calls may not take effect.
+ *
+ * Configuration format supported:
+ * - comma-separated list of component names to enable logging on.
+ * E.g. 'http/2,ssl'. Unknown names are ignored. Names are compared
+ * case-insensitive.
+ * - component 'all' applies to all known log components
+ * - prefixing a component with '+' or '-' will en-/disable logging for
+ * that component
+ * Example: 'all,-ssl' would enable logging for all components but the
+ * SSL filters.
+ *
+ * @param config configuration string
+ */
+CURLcode Curl_trc_opt(const char *config);
+
+/* the function used to output verbose information */
+void Curl_debug(struct Curl_easy *data, curl_infotype type,
+ char *ptr, size_t size);
+
+/**
+ * Output an informational message when transfer's verbose logging is enabled.
+ */
+void Curl_infof(struct Curl_easy *data,
+#if defined(__GNUC__) && !defined(printf) && \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+ !defined(__MINGW32__)
+ const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+#else
+ const char *fmt, ...);
+#endif
+
+/**
+ * Output a failure message on registered callbacks for transfer.
+ */
+void Curl_failf(struct Curl_easy *data,
+#if defined(__GNUC__) && !defined(printf) && \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+ !defined(__MINGW32__)
+ const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+#else
+ const char *fmt, ...);
+#endif
+
+#define failf Curl_failf
+
+/**
+ * Output an informational message when both transfer's verbose logging
+ * and connection filters verbose logging are enabled.
+ */
+void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
+#if defined(__GNUC__) && !defined(printf) && \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+ !defined(__MINGW32__)
+ const char *fmt, ...)
+ __attribute__((format(printf, 3, 4)));
+#else
+ const char *fmt, ...);
+#endif
+
+#define CURL_LOG_LVL_NONE 0
+#define CURL_LOG_LVL_INFO 1
+
+
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
+/* informational messages enabled */
+
+#define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose)
+#define Curl_trc_cf_is_verbose(cf, data) \
+ ((data) && (data)->set.verbose && \
+ (cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
+
+/* explainer: we have some mix configuration and werror settings
+ * that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
+ * on gnuc and some other compiler. Need to treat carefully.
+ */
+#if defined(HAVE_VARIADIC_MACROS_C99) && \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+
+#define infof(data, ...) \
+ do { if(Curl_trc_is_verbose(data)) \
+ Curl_infof(data, __VA_ARGS__); } while(0)
+#define CURL_TRC_CF(data, cf, ...) \
+ do { if(Curl_trc_cf_is_verbose(cf, data)) \
+ Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0)
+
+#else /* no variadic macro args */
+#define infof Curl_infof
+#define CURL_TRC_CF Curl_trc_cf_infof
+#endif /* variadic macro args */
+
+#else /* !CURL_DISABLE_VERBOSE_STRINGS */
+/* All informational messages are not compiled in for size savings */
+
+#define Curl_trc_is_verbose(d) ((void)(d), FALSE)
+#define Curl_trc_cf_is_verbose(x,y) ((void)(x), (void)(y), FALSE)
+
+#if defined(HAVE_VARIADIC_MACROS_C99)
+#define infof(...) Curl_nop_stmt
+#define CURL_TRC_CF(...) Curl_nop_stmt
+#define Curl_trc_cf_infof(...) Curl_nop_stmt
+#elif defined(HAVE_VARIADIC_MACROS_GCC)
+#define infof(x...) Curl_nop_stmt
+#define CURL_TRC_CF(x...) Curl_nop_stmt
+#define Curl_trc_cf_infof(x...) Curl_nop_stmt
+#else
+#error "missing VARIADIC macro define, fix and rebuild!"
+#endif
+
+#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+
+#endif /* HEADER_CURL_TRC_H */
diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c
index a89ebdc59f..2cfd8e6139 100644
--- a/libs/libcurl/src/easy.c
+++ b/libs/libcurl/src/easy.c
@@ -158,8 +158,8 @@ static CURLcode global_init(long flags, bool memoryfuncs)
#endif
}
- if(Curl_log_init()) {
- DEBUGF(fprintf(stderr, "Error: Curl_log_init failed\n"));
+ if(Curl_trc_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_trc_init failed\n"));
goto fail;
}
@@ -168,19 +168,15 @@ static CURLcode global_init(long flags, bool memoryfuncs)
goto fail;
}
-#ifdef WIN32
if(Curl_win32_init(flags)) {
DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
goto fail;
}
-#endif
-#ifdef __AMIGA__
if(Curl_amiga_init()) {
DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
goto fail;
}
-#endif
if(Curl_macos_init()) {
DEBUGF(fprintf(stderr, "Error: Curl_macos_init failed\n"));
@@ -319,6 +315,26 @@ void curl_global_cleanup(void)
global_init_unlock();
}
+/**
+ * curl_global_trace() globally initializes curl logging.
+ */
+CURLcode curl_global_trace(const char *config)
+{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ CURLcode result;
+ global_init_lock();
+
+ result = Curl_trc_opt(config);
+
+ global_init_unlock();
+
+ return result;
+#else
+ (void)config;
+ return CURLE_OK;
+#endif
+}
+
/*
* curl_global_sslset() globally initializes the SSL backend to use.
*/
@@ -699,7 +715,7 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
*
* REALITY: it can't just create and destroy the multi handle that easily. It
* needs to keep it around since if this easy handle is used again by this
- * function, the same multi handle must be re-used so that the same pools and
+ * function, the same multi handle must be reused so that the same pools and
* caches can be used.
*
* DEBUG: if 'events' is set TRUE, this function will use a replacement engine
@@ -1048,7 +1064,7 @@ void curl_easy_reset(struct Curl_easy *data)
memset(&data->state.authhost, 0, sizeof(struct auth));
memset(&data->state.authproxy, 0, sizeof(struct auth));
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
Curl_http_auth_cleanup_digest(data);
#endif
}
diff --git a/libs/libcurl/src/formdata.c b/libs/libcurl/src/formdata.c
index 8ab2ece18c..b02213161b 100644
--- a/libs/libcurl/src/formdata.c
+++ b/libs/libcurl/src/formdata.c
@@ -27,7 +27,7 @@
#include <curl/curl.h>
#include "formdata.h"
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API)
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
#include <libgen.h>
@@ -941,7 +941,7 @@ int curl_formget(struct curl_httppost *form, void *arg,
void curl_formfree(struct curl_httppost *form)
{
(void)form;
- /* does nothing HTTP is disabled */
+ /* Nothing to do. */
}
#endif /* if disabled */
diff --git a/libs/libcurl/src/formdata.h b/libs/libcurl/src/formdata.h
index c10eb3603b..a8db4cba90 100644
--- a/libs/libcurl/src/formdata.h
+++ b/libs/libcurl/src/formdata.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
-#ifndef CURL_DISABLE_MIME
+#ifndef CURL_DISABLE_FORM_API
/* used by FormAdd for temporary storage */
struct FormInfo {
@@ -53,10 +53,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
curl_mimepart *,
struct curl_httppost *post,
curl_read_callback fread_func);
-#else
-/* disabled */
-#define Curl_getformdata(a,b,c,d) CURLE_NOT_BUILT_IN
-#endif
+#endif /* CURL_DISABLE_FORM_API */
#endif /* HEADER_CURL_FORMDATA_H */
diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c
index 851f75cedf..3e10be2de4 100644
--- a/libs/libcurl/src/ftp.c
+++ b/libs/libcurl/src/ftp.c
@@ -32,9 +32,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_UTSNAME_H
-#include <sys/utsname.h>
-#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
@@ -865,7 +862,7 @@ static CURLcode ftp_state_cwd(struct Curl_easy *data,
if(conn->bits.reuse && ftpc->entrypath &&
/* no need to go to entrypath when we have an absolute path */
!(ftpc->dirdepth && ftpc->dirs[0][0] == '/')) {
- /* This is a re-used connection. Since we change directory to where the
+ /* This is a reused connection. Since we change directory to where the
transfer is taking place, we must first get back to the original dir
where we ended up after login: */
ftpc->cwdcount = 0; /* we count this as the first path, then we add one
@@ -975,7 +972,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(ip_end) {
/* either ipv6 or (ipv4|domain|interface):port(-range) */
#ifdef ENABLE_IPV6
- if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
+ if(Curl_inet_pton(AF_INET6, string_ftpport, &sa6->sin6_addr) == 1) {
/* ipv6 */
port_min = port_max = 0;
strcpy(addr, string_ftpport);
@@ -1900,7 +1897,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
if(data->set.ftp_skip_ip) {
/* told to ignore the remotely given IP but instead use the host we used
for the control connection */
- infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead",
+ infof(data, "Skip %u.%u.%u.%u for data connection, reuse %s instead",
ip[0], ip[1], ip[2], ip[3],
conn->host.name);
ftpc->newhost = strdup(control_address(conn));
diff --git a/libs/libcurl/src/gopher.c b/libs/libcurl/src/gopher.c
index 1bad94d2cd..f2f016a332 100644
--- a/libs/libcurl/src/gopher.c
+++ b/libs/libcurl/src/gopher.c
@@ -185,7 +185,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
if(strlen(sel) < 1)
break;
- result = Curl_write(data, sockfd, sel, k, &amount);
+ result = Curl_nwrite(data, FIRSTSOCKET, sel, k, &amount);
if(!result) { /* Which may not have written it all! */
result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount);
if(result)
@@ -227,7 +227,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
free(sel_org);
if(!result)
- result = Curl_write(data, sockfd, "\r\n", 2, &amount);
+ result = Curl_nwrite(data, FIRSTSOCKET, "\r\n", 2, &amount);
if(result) {
failf(data, "Failed sending Gopher request");
return result;
diff --git a/libs/libcurl/src/headers.c b/libs/libcurl/src/headers.c
index 1272979677..bcd65be503 100644
--- a/libs/libcurl/src/headers.c
+++ b/libs/libcurl/src/headers.c
@@ -300,9 +300,16 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
if(data->state.prevhead)
/* line folding, append value to the previous header's value */
return unfold_value(data, header, hlen);
- else
- /* can't unfold without a previous header */
- return CURLE_BAD_FUNCTION_ARGUMENT;
+ else {
+ /* Can't unfold without a previous header. Instead of erroring, just
+ pass the leading blanks. */
+ while(hlen && ISBLANK(*header)) {
+ header++;
+ hlen--;
+ }
+ if(!hlen)
+ return CURLE_WEIRD_SERVER_REPLY;
+ }
}
hs = calloc(1, sizeof(*hs) + hlen);
diff --git a/libs/libcurl/src/hmac.c b/libs/libcurl/src/hmac.c
index eff2257974..9172ff71a2 100644
--- a/libs/libcurl/src/hmac.c
+++ b/libs/libcurl/src/hmac.c
@@ -26,7 +26,8 @@
#include "curl_setup.h"
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
+ || !defined(CURL_DISABLE_AWS)
#include <curl/curl.h>
@@ -169,4 +170,4 @@ CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
return CURLE_OK;
}
-#endif /* CURL_DISABLE_CRYPTO_AUTH */
+#endif /* Using NTLM (without SSPI) or AWS */
diff --git a/libs/libcurl/src/hostip.c b/libs/libcurl/src/hostip.c
index 3b1b3f8877..52632e7162 100644
--- a/libs/libcurl/src/hostip.c
+++ b/libs/libcurl/src/hostip.c
@@ -122,19 +122,6 @@
static void freednsentry(void *freethis);
/*
- * Return # of addresses in a Curl_addrinfo struct
- */
-static int num_addresses(const struct Curl_addrinfo *addr)
-{
- int i = 0;
- while(addr) {
- addr = addr->ai_next;
- i++;
- }
- return i;
-}
-
-/*
* Curl_printable_address() stores a printable version of the 1st address
* given in the 'ai' argument. The result will be stored in the buf that is
* bufsize bytes big.
@@ -388,6 +375,19 @@ Curl_fetch_addr(struct Curl_easy *data,
}
#ifndef CURL_DISABLE_SHUFFLE_DNS
+/*
+ * Return # of addresses in a Curl_addrinfo struct
+ */
+static int num_addresses(const struct Curl_addrinfo *addr)
+{
+ int i = 0;
+ while(addr) {
+ addr = addr->ai_next;
+ i++;
+ }
+ return i;
+}
+
UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
struct Curl_addrinfo **addr);
/*
@@ -601,7 +601,7 @@ bool Curl_ipv6works(struct Curl_easy *data)
if(data) {
/* the nature of most system is that IPv6 status doesn't come and go
during a program's lifetime so we only probe the first time and then we
- have the info kept for fast re-use */
+ have the info kept for fast reuse */
DEBUGASSERT(data);
DEBUGASSERT(data->multi);
if(data->multi->ipv6_up == IPV6_UNKNOWN) {
@@ -1240,7 +1240,7 @@ err:
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
if(dns) {
- infof(data, "RESOLVE %.*s:%d is - old addresses discarded",
+ infof(data, "RESOLVE %.*s:%d - old addresses discarded",
(int)hlen, host_begin, port);
/* delete old entry, there are two reasons for this
1. old entry may have different addresses.
diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c
index c0261b7cc5..68d4bb3655 100644
--- a/libs/libcurl/src/http.c
+++ b/libs/libcurl/src/http.c
@@ -233,7 +233,6 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
if(!http)
return CURLE_OUT_OF_MEMORY;
- Curl_mime_initpart(&http->form);
data->req.p.http = http;
connkeep(conn, "HTTP default");
@@ -342,6 +341,8 @@ char *Curl_copy_header_value(const char *header)
}
#ifndef CURL_DISABLE_HTTP_AUTH
+
+#ifndef CURL_DISABLE_BASIC_AUTH
/*
* http_output_basic() sets up an Authorization: header (or the proxy version)
* for HTTP Basic authentication.
@@ -403,6 +404,9 @@ fail:
return result;
}
+#endif
+
+#ifndef CURL_DISABLE_BEARER_AUTH
/*
* http_output_bearer() sets up an Authorization: header
* for HTTP Bearer authentication.
@@ -430,6 +434,8 @@ fail:
#endif
+#endif
+
/* pickoneauth() selects the most favourable authentication method from the
* ones available and the ones we want.
*
@@ -446,18 +452,26 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
of preference in case of the existence of multiple accepted types. */
if(avail & CURLAUTH_NEGOTIATE)
pick->picked = CURLAUTH_NEGOTIATE;
+#ifndef CURL_DISABLE_BEARER_AUTH
else if(avail & CURLAUTH_BEARER)
pick->picked = CURLAUTH_BEARER;
+#endif
+#ifndef CURL_DISABLE_DIGEST_AUTH
else if(avail & CURLAUTH_DIGEST)
pick->picked = CURLAUTH_DIGEST;
+#endif
else if(avail & CURLAUTH_NTLM)
pick->picked = CURLAUTH_NTLM;
else if(avail & CURLAUTH_NTLM_WB)
pick->picked = CURLAUTH_NTLM_WB;
+#ifndef CURL_DISABLE_BASIC_AUTH
else if(avail & CURLAUTH_BASIC)
pick->picked = CURLAUTH_BASIC;
+#endif
+#ifndef CURL_DISABLE_AWS
else if(avail & CURLAUTH_AWS_SIGV4)
pick->picked = CURLAUTH_AWS_SIGV4;
+#endif
else {
pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
picked = FALSE;
@@ -723,11 +737,11 @@ output_auth_headers(struct Curl_easy *data,
CURLcode result = CURLE_OK;
(void)conn;
-#ifdef CURL_DISABLE_CRYPTO_AUTH
+#ifdef CURL_DISABLE_DIGEST_AUTH
(void)request;
(void)path;
#endif
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifndef CURL_DISABLE_AWS
if(authstatus->picked == CURLAUTH_AWS_SIGV4) {
auth = "AWS_SIGV4";
result = Curl_output_aws_sigv4(data, proxy);
@@ -763,7 +777,7 @@ output_auth_headers(struct Curl_easy *data,
}
else
#endif
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifndef CURL_DISABLE_DIGEST_AUTH
if(authstatus->picked == CURLAUTH_DIGEST) {
auth = "Digest";
result = Curl_output_digest(data,
@@ -775,6 +789,7 @@ output_auth_headers(struct Curl_easy *data,
}
else
#endif
+#ifndef CURL_DISABLE_BASIC_AUTH
if(authstatus->picked == CURLAUTH_BASIC) {
/* Basic */
if(
@@ -794,6 +809,8 @@ output_auth_headers(struct Curl_easy *data,
functions work that way */
authstatus->done = TRUE;
}
+#endif
+#ifndef CURL_DISABLE_BEARER_AUTH
if(authstatus->picked == CURLAUTH_BEARER) {
/* Bearer */
if((!proxy && data->set.str[STRING_BEARER] &&
@@ -808,6 +825,7 @@ output_auth_headers(struct Curl_easy *data,
functions work that way */
authstatus->done = TRUE;
}
+#endif
if(auth) {
#ifndef CURL_DISABLE_PROXY
@@ -866,7 +884,12 @@ Curl_http_output_auth(struct Curl_easy *data,
#ifndef CURL_DISABLE_PROXY
(conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
#endif
- data->state.aptr.user || data->set.str[STRING_BEARER])
+ data->state.aptr.user ||
+#ifdef USE_SPNEGO
+ authhost->want & CURLAUTH_NEGOTIATE ||
+ authproxy->want & CURLAUTH_NEGOTIATE ||
+#endif
+ data->set.str[STRING_BEARER])
/* continue please */;
else {
authhost->done = TRUE;
@@ -1064,7 +1087,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
}
else
#endif
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifndef CURL_DISABLE_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.");
@@ -1087,6 +1110,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
}
else
#endif
+#ifndef CURL_DISABLE_BASIC_AUTH
if(checkprefix("Basic", auth) &&
is_valid_auth_separator(auth[5])) {
*availp |= CURLAUTH_BASIC;
@@ -1101,6 +1125,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
}
}
else
+#endif
+#ifndef CURL_DISABLE_BEARER_AUTH
if(checkprefix("Bearer", auth) &&
is_valid_auth_separator(auth[6])) {
*availp |= CURLAUTH_BEARER;
@@ -1113,6 +1139,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
data->state.authproblem = TRUE;
}
}
+#endif
/* there may be multiple methods on one line, so keep reading */
while(*auth && *auth != ',') /* read up to the next comma */
@@ -1277,7 +1304,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
curl_off_t *bytes_written,
/* how much of the buffer contains body data */
curl_off_t included_body_bytes,
- int socketindex)
+ int sockindex)
{
ssize_t amount;
CURLcode result;
@@ -1285,12 +1312,9 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
size_t size;
struct connectdata *conn = data->conn;
size_t sendsize;
- curl_socket_t sockfd;
size_t headersize;
- DEBUGASSERT(socketindex <= SECONDARYSOCKET);
-
- sockfd = Curl_conn_get_socket(data, socketindex);
+ DEBUGASSERT(sockindex <= SECONDARYSOCKET && sockindex >= 0);
/* The looping below is required since we use non-blocking sockets, but due
to the circumstances we will just loop and try again and again etc */
@@ -1372,9 +1396,25 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
else
sendsize = size;
}
+
+ /* We currently cannot send more that this for http here:
+ * - if sending blocks, it return 0 as amount
+ * - we then whisk aside the `in` into the `http` struct
+ * and install our own `data->state.fread_func` that
+ * on subsequent calls reads `in` empty.
+ * - when the whisked away `in` is empty, the `fread_func`
+ * is restored ot its original state.
+ * The problem is that `fread_func` can only return
+ * `upload_buffer_size` lengths. If the send we do here
+ * is larger and blocks, we do re-sending with smaller
+ * amounts of data and connection filters do not like
+ * that.
+ */
+ if(http && (sendsize > (size_t)data->set.upload_buffer_size))
+ sendsize = (size_t)data->set.upload_buffer_size;
}
- result = Curl_write(data, sockfd, ptr, sendsize, &amount);
+ result = Curl_nwrite(data, sockindex, ptr, sendsize, &amount);
if(!result) {
/*
@@ -1527,7 +1567,7 @@ CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
struct connectdata *conn = data->conn;
/* We default to persistent connections. We set this already in this connect
- function to make the re-use checks properly be able to check this bit. */
+ function to make the reuse checks properly be able to check this bit. */
connkeep(conn, "HTTP default");
return Curl_conn_connect(data, FIRSTSOCKET, FALSE, done);
@@ -1572,7 +1612,6 @@ CURLcode Curl_http_done(struct Curl_easy *data,
return CURLE_OK;
Curl_dyn_free(&http->send_buffer);
- Curl_mime_cleanpart(&http->form);
Curl_dyn_reset(&data->state.headerb);
Curl_hyper_done(data);
Curl_ws_done(data);
@@ -2370,45 +2409,53 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
switch(httpreq) {
case HTTPREQ_POST_MIME:
- http->sendit = &data->set.mimepost;
+ data->state.mimepost = &data->set.mimepost;
break;
+#ifndef CURL_DISABLE_FORM_API
case HTTPREQ_POST_FORM:
- /* Convert the form structure into a mime structure. */
- Curl_mime_cleanpart(&http->form);
- result = Curl_getformdata(data, &http->form, data->set.httppost,
- data->state.fread_func);
- if(result)
- return result;
- http->sendit = &http->form;
+ /* Convert the form structure into a mime structure, then keep
+ the conversion */
+ if(!data->state.formp) {
+ data->state.formp = calloc(sizeof(curl_mimepart), 1);
+ if(!data->state.formp)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_mime_cleanpart(data->state.formp);
+ result = Curl_getformdata(data, data->state.formp, data->set.httppost,
+ data->state.fread_func);
+ if(result)
+ return result;
+ data->state.mimepost = data->state.formp;
+ }
break;
+#endif
default:
- http->sendit = NULL;
+ data->state.mimepost = NULL;
}
#ifndef CURL_DISABLE_MIME
- if(http->sendit) {
+ if(data->state.mimepost) {
const char *cthdr = Curl_checkheaders(data, STRCONST("Content-Type"));
/* Read and seek body only. */
- http->sendit->flags |= MIME_BODY_ONLY;
+ data->state.mimepost->flags |= MIME_BODY_ONLY;
/* Prepare the mime structure headers & set content type. */
if(cthdr)
for(cthdr += 13; *cthdr == ' '; cthdr++)
;
- else if(http->sendit->kind == MIMEKIND_MULTIPART)
+ else if(data->state.mimepost->kind == MIMEKIND_MULTIPART)
cthdr = "multipart/form-data";
- curl_mime_headers(http->sendit, data->set.headers, 0);
- result = Curl_mime_prepare_headers(data, http->sendit, cthdr,
+ curl_mime_headers(data->state.mimepost, data->set.headers, 0);
+ result = Curl_mime_prepare_headers(data, data->state.mimepost, cthdr,
NULL, MIMESTRATEGY_FORM);
- curl_mime_headers(http->sendit, NULL, 0);
+ curl_mime_headers(data->state.mimepost, NULL, 0);
if(!result)
- result = Curl_mime_rewind(http->sendit);
+ result = Curl_mime_rewind(data->state.mimepost);
if(result)
return result;
- http->postsize = Curl_mime_size(http->sendit);
+ http->postsize = Curl_mime_size(data->state.mimepost);
}
#endif
@@ -2564,7 +2611,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
{
struct curl_slist *hdr;
- for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
+ for(hdr = data->state.mimepost->curlheaders; hdr; hdr = hdr->next) {
result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
if(result)
return result;
@@ -2599,7 +2646,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
/* Read from mime structure. */
data->state.fread_func = (curl_read_callback) Curl_mime_read;
- data->state.in = (void *) http->sendit;
+ data->state.in = (void *) data->state.mimepost;
http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */
@@ -2683,7 +2730,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
if(!data->req.upload_chunky) {
/* We're not sending it 'chunked', append it to the request
- already now to reduce the number if send() calls */
+ already now to reduce the number of send() calls */
result = Curl_dyn_addn(r, data->set.postfields,
(size_t)http->postsize);
included_body = http->postsize;
@@ -3024,7 +3071,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
*done = TRUE;
return CURLE_OK;
}
- /* We have a new url to load, but since we want to be able to re-use this
+ /* We have a new url to load, but since we want to be able to reuse this
connection properly, we read the full response in "ignore more" */
k->ignorebody = TRUE;
infof(data, "Ignoring the response-body");
@@ -3064,7 +3111,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
data->info.httpcode = 304;
infof(data, "Simulate an HTTP 304 response");
/* we abort the transfer before it is completed == we ruin the
- re-use ability. Close the connection */
+ reuse ability. Close the connection */
streamclose(conn, "Simulated 304 handling");
return CURLE_OK;
}
@@ -3308,8 +3355,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
altused ? altused : ""
);
- /* clear userpwd and proxyuserpwd to avoid re-using old credentials
- * from re-used connections */
+ /* clear userpwd and proxyuserpwd to avoid reusing old credentials
+ * from reused connections */
Curl_safefree(data->state.aptr.userpwd);
Curl_safefree(data->state.aptr.proxyuserpwd);
free(altused);
@@ -3918,6 +3965,29 @@ static CURLcode verify_header(struct Curl_easy *data)
return CURLE_OK;
}
+CURLcode Curl_bump_headersize(struct Curl_easy *data,
+ size_t delta,
+ bool connect_only)
+{
+ size_t bad = 0;
+ if(delta < MAX_HTTP_RESP_HEADER_SIZE) {
+ if(!connect_only)
+ data->req.headerbytecount += (unsigned int)delta;
+ data->info.header_size += (unsigned int)delta;
+ if(data->info.header_size > MAX_HTTP_RESP_HEADER_SIZE)
+ bad = data->info.header_size;
+ }
+ else
+ bad = data->info.header_size + delta;
+ if(bad) {
+ failf(data, "Too large response headers: %zu > %u",
+ bad, MAX_HTTP_RESP_HEADER_SIZE);
+ return CURLE_RECV_ERROR;
+ }
+ return CURLE_OK;
+}
+
+
/*
* Read any HTTP header lines from the server and pass them to the client app.
*/
@@ -4056,6 +4126,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* Switching Protocols */
if(k->upgr101 == UPGR101_H2) {
/* Switching to HTTP/2 */
+ DEBUGASSERT(conn->httpversion < 20);
infof(data, "Received 101, Switching to HTTP/2");
k->upgr101 = UPGR101_RECEIVED;
@@ -4098,6 +4169,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
}
else {
+ if(k->upgr101 == UPGR101_H2) {
+ /* A requested upgrade was denied, poke the multi handle to possibly
+ allow a pending pipewait to continue */
+ Curl_multi_connchanged(data->multi);
+ }
k->header = FALSE; /* no more header to parse! */
if((k->size == -1) && !k->chunk && !conn->bits.close &&
@@ -4165,8 +4241,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(result)
return result;
- data->info.header_size += (long)headerlen;
- data->req.headerbytecount += (long)headerlen;
+ result = Curl_bump_headersize(data, headerlen, FALSE);
+ if(result)
+ return result;
/*
* When all the headers have been parsed, see if we should give
@@ -4229,7 +4306,18 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if((k->httpcode == 417) && data->state.expect100header) {
/* 417 Expectation Failed - try again without the Expect
header */
- infof(data, "Got 417 while waiting for a 100");
+ if(!k->writebytecount &&
+ k->exp100 == EXP100_AWAITING_CONTINUE) {
+ infof(data, "Got HTTP failure 417 while waiting for a 100");
+ }
+ else {
+ infof(data, "Got HTTP failure 417 while sending data");
+ streamclose(conn,
+ "Stop sending data before everything sent");
+ result = http_perhapsrewind(data, conn);
+ if(result)
+ return result;
+ }
data->state.disableexpect = TRUE;
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->state.url);
@@ -4488,8 +4576,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(result)
return result;
- data->info.header_size += Curl_dyn_len(&data->state.headerb);
- data->req.headerbytecount += Curl_dyn_len(&data->state.headerb);
+ result = Curl_bump_headersize(data, Curl_dyn_len(&data->state.headerb),
+ FALSE);
+ if(result)
+ return result;
Curl_dyn_reset(&data->state.headerb);
}
diff --git a/libs/libcurl/src/http.h b/libs/libcurl/src/http.h
index dea4db7fb6..fc4f518530 100644
--- a/libs/libcurl/src/http.h
+++ b/libs/libcurl/src/http.h
@@ -64,6 +64,10 @@ extern const struct Curl_handler Curl_handler_wss;
struct dynhds;
+CURLcode Curl_bump_headersize(struct Curl_easy *data,
+ size_t delta,
+ bool connect_only);
+
/* Header specific functions */
bool Curl_compareheader(const char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */
@@ -183,21 +187,19 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data);
#define EXPECT_100_THRESHOLD (1024*1024)
#endif
+/* MAX_HTTP_RESP_HEADER_SIZE is the maximum size of all response headers
+ combined that libcurl allows for a single HTTP response, any HTTP
+ version. This count includes CONNECT response headers. */
+#define MAX_HTTP_RESP_HEADER_SIZE (300*1024)
+
#endif /* CURL_DISABLE_HTTP */
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
- curl_mimepart *sendit;
curl_off_t postsize; /* off_t to handle large file sizes */
const char *postdata;
-
- const char *p_pragma; /* Pragma: string */
-
- /* For FORM posting */
- curl_mimepart form;
-
struct back {
curl_read_callback fread_func; /* backup storage for fread pointer */
void *fread_in; /* backup storage for fread_in pointer */
@@ -292,7 +294,7 @@ void Curl_http_req_free(struct httpreq *req);
/**
* Create the list of HTTP/2 headers which represent the request,
- * using HTTP/2 pseudo headers preceeding the `req->headers`.
+ * using HTTP/2 pseudo headers preceding the `req->headers`.
*
* Applies the following transformations:
* - if `authority` is set, any "Host" header is removed.
diff --git a/libs/libcurl/src/http1.c b/libs/libcurl/src/http1.c
index 6845f8c2f4..1f54cf7212 100644
--- a/libs/libcurl/src/http1.c
+++ b/libs/libcurl/src/http1.c
@@ -163,7 +163,7 @@ static CURLcode start_req(struct h1_req_parser *parser,
break;
}
}
- /* no SPACE found or empty TARGET or empy HTTP_VERSION */
+ /* no SPACE found or empty TARGET or empty HTTP_VERSION */
if(!target_len || !hv_len)
goto out;
diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c
index c5528019b8..e7a7d69f27 100644
--- a/libs/libcurl/src/http2.c
+++ b/libs/libcurl/src/http2.c
@@ -41,6 +41,7 @@
#include "urlapi-int.h"
#include "cfilters.h"
#include "connect.h"
+#include "rand.h"
#include "strtoofft.h"
#include "strdup.h"
#include "transfer.h"
@@ -69,7 +70,7 @@
#define H2_CHUNK_SIZE (16 * 1024)
/* this is how much we want "in flight" for a stream */
#define H2_STREAM_WINDOW_SIZE (10 * 1024 * 1024)
-/* on receving from TLS, we prep for holding a full stream window */
+/* on receiving from TLS, we prep for holding a full stream window */
#define H2_NW_RECV_CHUNKS (H2_STREAM_WINDOW_SIZE / H2_CHUNK_SIZE)
/* on send into TLS, we just want to accumulate small frames */
#define H2_NW_SEND_CHUNKS 1
@@ -175,6 +176,7 @@ struct stream_ctx {
int32_t id; /* HTTP/2 protocol identifier for stream */
struct bufq recvbuf; /* response buffer */
struct bufq sendbuf; /* request buffer */
+ struct h1_req_parser h1; /* parsing the request */
struct dynhds resp_trailers; /* response trailer fields */
size_t resp_hds_len; /* amount of response header bytes in recvbuf */
size_t upload_blocked_len;
@@ -187,6 +189,7 @@ struct stream_ctx {
int status_code; /* HTTP response status code */
uint32_t error; /* stream error code */
uint32_t local_window_size; /* the local recv window size */
+ bool resp_hds_complete; /* we have a complete, final response */
bool closed; /* TRUE on stream close */
bool reset; /* TRUE on stream reset */
bool close_handled; /* TRUE if stream closure is handled by libcurl */
@@ -217,8 +220,8 @@ static void drain_stream(struct Curl_cfilter *cf,
(stream->upload_left || stream->upload_blocked_len))
bits |= CURL_CSELECT_OUT;
if(data->state.dselect_bits != bits) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] DRAIN dselect_bits=%x",
- stream->id, bits));
+ CURL_TRC_CF(data, cf, "[%d] DRAIN dselect_bits=%x",
+ stream->id, bits);
data->state.dselect_bits = bits;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
@@ -252,6 +255,7 @@ static CURLcode http2_data_setup(struct Curl_cfilter *cf,
H2_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
H2_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
+ Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
Curl_dynhds_init(&stream->resp_trailers, 0, DYN_HTTP_REQUEST);
stream->resp_hds_len = 0;
stream->bodystarted = FALSE;
@@ -281,8 +285,8 @@ static void http2_data_done(struct Curl_cfilter *cf,
if(ctx->h2) {
if(!stream->closed && stream->id > 0) {
/* RST_STREAM */
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] premature DATA_DONE, RST stream",
- stream->id));
+ CURL_TRC_CF(data, cf, "[%d] premature DATA_DONE, RST stream",
+ stream->id);
if(!nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
stream->id, NGHTTP2_STREAM_CLOSED))
(void)nghttp2_session_send(ctx->h2);
@@ -312,6 +316,7 @@ static void http2_data_done(struct Curl_cfilter *cf,
Curl_bufq_free(&stream->sendbuf);
Curl_bufq_free(&stream->recvbuf);
+ Curl_h1_req_parse_free(&stream->h1);
Curl_dynhds_free(&stream->resp_trailers);
if(stream->push_headers) {
/* if they weren't used and then freed before */
@@ -364,8 +369,12 @@ static ssize_t nw_out_writer(void *writer_ctx,
{
struct Curl_cfilter *cf = writer_ctx;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nwritten;
- return Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
+ nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
+ if(nwritten > 0)
+ CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten);
+ return nwritten;
}
static ssize_t send_callback(nghttp2_session *h2,
@@ -373,6 +382,10 @@ static ssize_t send_callback(nghttp2_session *h2,
void *userp);
static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
void *userp);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
+ void *userp);
+#endif
static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
const uint8_t *mem, size_t len, void *userp);
@@ -389,18 +402,6 @@ static int error_callback(nghttp2_session *session, const char *msg,
size_t len, void *userp);
/*
- * multi_connchanged() is called to tell that there is a connection in
- * this multi handle that has changed state (multiplexing become possible, the
- * number of allowed streams changed or similar), and a subsequent use of this
- * multi handle should move CONNECT_PEND handles back to CONNECT to have them
- * retry.
- */
-static void multi_connchanged(struct Curl_multi *multi)
-{
- multi->recheckstate = TRUE;
-}
-
-/*
* Initialize the cfilter context
*/
static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
@@ -427,6 +428,9 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
nghttp2_session_callbacks_set_send_callback(cbs, send_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(cbs, on_frame_recv);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ nghttp2_session_callbacks_set_on_frame_send_callback(cbs, on_frame_send);
+#endif
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
cbs, on_data_chunk_recv);
nghttp2_session_callbacks_set_on_stream_close_callback(cbs, on_stream_close);
@@ -475,6 +479,7 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
stream->id);
DEBUGASSERT(0);
}
+ CURL_TRC_CF(data, cf, "created session via Upgrade");
}
else {
nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN];
@@ -502,6 +507,8 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
/* all set, traffic will be send on connect */
result = CURLE_OK;
+ CURL_TRC_CF(data, cf, "[0] created h2 session%s",
+ via_h1_upgrade? " (via h1 upgrade)" : "");
out:
if(cbs)
@@ -547,8 +554,8 @@ static int h2_process_pending_input(struct Curl_cfilter *cf,
break;
}
else {
- DEBUGF(LOG_CF(data, cf, "process_pending_input: %zu bytes left "
- "in connection buffer", Curl_bufq_len(&ctx->inbufq)));
+ CURL_TRC_CF(data, cf, "process_pending_input: %zu bytes left "
+ "in connection buffer", Curl_bufq_len(&ctx->inbufq));
}
}
@@ -590,8 +597,8 @@ static bool http2_connisalive(struct Curl_cfilter *cf, struct Curl_easy *data,
*input_pending = FALSE;
nread = Curl_bufq_slurp(&ctx->inbufq, nw_in_reader, cf, &result);
if(nread != -1) {
- DEBUGF(LOG_CF(data, cf, "%zd bytes stray data read before trying "
- "h2 connection", nread));
+ CURL_TRC_CF(data, cf, "%zd bytes stray data read before trying "
+ "h2 connection", nread);
if(h2_process_pending_input(cf, data, &result) < 0)
/* immediate error, considered dead */
alive = FALSE;
@@ -653,13 +660,12 @@ static CURLcode nw_out_flush(struct Curl_cfilter *cf,
nwritten = Curl_bufq_pass(&ctx->outbufq, nw_out_writer, cf, &result);
if(nwritten < 0) {
if(result == CURLE_AGAIN) {
- DEBUGF(LOG_CF(data, cf, "flush nw send buffer(%zu) -> EAGAIN",
- Curl_bufq_len(&ctx->outbufq)));
+ CURL_TRC_CF(data, cf, "flush nw send buffer(%zu) -> EAGAIN",
+ Curl_bufq_len(&ctx->outbufq));
ctx->nw_out_blocked = 1;
}
return result;
}
- DEBUGF(LOG_CF(data, cf, "nw send buffer flushed"));
return Curl_bufq_is_empty(&ctx->outbufq)? CURLE_OK: CURLE_AGAIN;
}
@@ -851,8 +857,8 @@ static int push_promise(struct Curl_cfilter *cf,
struct cf_h2_ctx *ctx = cf->ctx;
int rv; /* one of the CURL_PUSH_* defines */
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] PUSH_PROMISE received",
- frame->promised_stream_id));
+ CURL_TRC_CF(data, cf, "[%d] PUSH_PROMISE received",
+ frame->promised_stream_id);
if(data->multi->push_cb) {
struct stream_ctx *stream;
struct stream_ctx *newstream;
@@ -871,7 +877,7 @@ static int push_promise(struct Curl_cfilter *cf,
heads.data = data;
heads.frame = frame;
/* ask the application */
- DEBUGF(LOG_CF(data, cf, "Got PUSH_PROMISE, ask application"));
+ CURL_TRC_CF(data, cf, "Got PUSH_PROMISE, ask application");
stream = H2_STREAM_CTX(data);
if(!stream) {
@@ -943,7 +949,7 @@ static int push_promise(struct Curl_cfilter *cf,
}
}
else {
- DEBUGF(LOG_CF(data, cf, "Got PUSH_PROMISE, ignore it"));
+ CURL_TRC_CF(data, cf, "Got PUSH_PROMISE, ignore it");
rv = CURL_PUSH_DENY;
}
fail:
@@ -980,20 +986,19 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
int rv;
if(!stream) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] No proto pointer", stream_id));
+ CURL_TRC_CF(data, cf, "[%d] No stream_ctx set", stream_id);
return CURLE_FAILED_INIT;
}
switch(frame->hd.type) {
case NGHTTP2_DATA:
rbuflen = Curl_bufq_len(&stream->recvbuf);
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[DATA len=%zu pad=%zu], "
- "buffered=%zu, window=%d/%d",
- stream_id, frame->hd.length, frame->data.padlen, rbuflen,
- nghttp2_session_get_stream_effective_recv_data_length(
- ctx->h2, stream->id),
- nghttp2_session_get_stream_effective_local_window_size(
- ctx->h2, stream->id)));
+ CURL_TRC_CF(data, cf, "[%d] DATA, buffered=%zu, window=%d/%d",
+ stream_id, rbuflen,
+ nghttp2_session_get_stream_effective_recv_data_length(
+ ctx->h2, stream->id),
+ nghttp2_session_get_stream_effective_local_window_size(
+ ctx->h2, stream->id));
/* If !body started on this stream, then receiving DATA is illegal. */
if(!stream->bodystarted) {
rv = nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
@@ -1011,7 +1016,7 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
ctx->h2, stream->id);
if(wsize > 0 && (uint32_t)wsize != stream->local_window_size) {
/* H2 flow control is not absolute, as the server might not have the
- * same view, yet. When we recieve more than we want, we enforce
+ * same view, yet. When we receive more than we want, we enforce
* the local window size again to make nghttp2 send WINDOW_UPATEs
* accordingly. */
nghttp2_session_set_local_window_size(ctx->h2,
@@ -1022,7 +1027,6 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
}
break;
case NGHTTP2_HEADERS:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[HEADERS]", stream_id));
if(stream->bodystarted) {
/* Only valid HEADERS after body started is trailer HEADERS. We
buffer them in on_header callback. */
@@ -1045,12 +1049,12 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
if(result)
return result;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] %zu header bytes",
- stream_id, Curl_bufq_len(&stream->recvbuf)));
+ if(stream->status_code / 100 != 1) {
+ stream->resp_hds_complete = TRUE;
+ }
drain_stream(cf, data, stream);
break;
case NGHTTP2_PUSH_PROMISE:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[PUSH_PROMISE]", stream_id));
rv = push_promise(cf, data, &frame->push_promise);
if(rv) { /* deny! */
DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
@@ -1060,38 +1064,127 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
if(nghttp2_is_fatal(rv))
return CURLE_SEND_ERROR;
else if(rv == CURL_PUSH_ERROROUT) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] fail in PUSH_PROMISE received",
- stream_id));
+ CURL_TRC_CF(data, cf, "[%d] fail in PUSH_PROMISE received",
+ stream_id);
return CURLE_RECV_ERROR;
}
}
break;
case NGHTTP2_RST_STREAM:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[RST]", stream_id));
stream->closed = TRUE;
- stream->reset = TRUE;
+ if(frame->rst_stream.error_code) {
+ stream->reset = TRUE;
+ }
stream->send_closed = TRUE;
data->req.keepon &= ~KEEP_SEND_HOLD;
drain_stream(cf, data, stream);
break;
case NGHTTP2_WINDOW_UPDATE:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[WINDOW_UPDATE]", stream_id));
if((data->req.keepon & KEEP_SEND_HOLD) &&
(data->req.keepon & KEEP_SEND)) {
data->req.keepon &= ~KEEP_SEND_HOLD;
drain_stream(cf, data, stream);
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] un-holding after win update",
- stream_id));
+ CURL_TRC_CF(data, cf, "[%d] un-holding after win update",
+ stream_id);
}
break;
default:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[%x]",
- stream_id, frame->hd.type));
break;
}
return CURLE_OK;
}
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen)
+{
+ switch(frame->hd.type) {
+ case NGHTTP2_DATA: {
+ return msnprintf(buffer, blen,
+ "FRAME[DATA, len=%d, eos=%d, padlen=%d]",
+ (int)frame->hd.length,
+ !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM),
+ (int)frame->data.padlen);
+ }
+ case NGHTTP2_HEADERS: {
+ return msnprintf(buffer, blen,
+ "FRAME[HEADERS, len=%d, hend=%d, eos=%d]",
+ (int)frame->hd.length,
+ !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS),
+ !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM));
+ }
+ case NGHTTP2_PRIORITY: {
+ return msnprintf(buffer, blen,
+ "FRAME[PRIORITY, len=%d, flags=%d]",
+ (int)frame->hd.length, frame->hd.flags);
+ }
+ case NGHTTP2_RST_STREAM: {
+ return msnprintf(buffer, blen,
+ "FRAME[RST_STREAM, len=%d, flags=%d, error=%u]",
+ (int)frame->hd.length, frame->hd.flags,
+ frame->rst_stream.error_code);
+ }
+ case NGHTTP2_SETTINGS: {
+ if(frame->hd.flags & NGHTTP2_FLAG_ACK) {
+ return msnprintf(buffer, blen, "FRAME[SETTINGS, ack=1]");
+ }
+ return msnprintf(buffer, blen,
+ "FRAME[SETTINGS, len=%d]", (int)frame->hd.length);
+ }
+ case NGHTTP2_PUSH_PROMISE: {
+ return msnprintf(buffer, blen,
+ "FRAME[PUSH_PROMISE, len=%d, hend=%d]",
+ (int)frame->hd.length,
+ !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS));
+ }
+ case NGHTTP2_PING: {
+ return msnprintf(buffer, blen,
+ "FRAME[PING, len=%d, ack=%d]",
+ (int)frame->hd.length,
+ frame->hd.flags&NGHTTP2_FLAG_ACK);
+ }
+ case NGHTTP2_GOAWAY: {
+ char scratch[128];
+ size_t s_len = sizeof(scratch)/sizeof(scratch[0]);
+ size_t len = (frame->goaway.opaque_data_len < s_len)?
+ frame->goaway.opaque_data_len : s_len-1;
+ if(len)
+ memcpy(scratch, frame->goaway.opaque_data, len);
+ scratch[len] = '\0';
+ return msnprintf(buffer, blen, "FRAME[GOAWAY, error=%d, reason='%s', "
+ "last_stream=%d]", frame->goaway.error_code,
+ scratch, frame->goaway.last_stream_id);
+ }
+ case NGHTTP2_WINDOW_UPDATE: {
+ return msnprintf(buffer, blen,
+ "FRAME[WINDOW_UPDATE, incr=%d]",
+ frame->window_update.window_size_increment);
+ }
+ default:
+ return msnprintf(buffer, blen, "FRAME[%d, len=%d, flags=%d]",
+ frame->hd.type, (int)frame->hd.length,
+ frame->hd.flags);
+ }
+}
+
+static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
+ void *userp)
+{
+ struct Curl_cfilter *cf = userp;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+
+ (void)session;
+ DEBUGASSERT(data);
+ if(data && Curl_trc_cf_is_verbose(cf, data)) {
+ char buffer[256];
+ int len;
+ len = fr_print(frame, buffer, sizeof(buffer)-1);
+ buffer[len] = 0;
+ CURL_TRC_CF(data, cf, "[%d] -> %s", frame->hd.stream_id, buffer);
+ }
+ return 0;
+}
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+
static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
void *userp)
{
@@ -1101,40 +1194,51 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
int32_t stream_id = frame->hd.stream_id;
DEBUGASSERT(data);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ if(Curl_trc_cf_is_verbose(cf, data)) {
+ char buffer[256];
+ int len;
+ len = fr_print(frame, buffer, sizeof(buffer)-1);
+ buffer[len] = 0;
+ CURL_TRC_CF(data, cf, "[%d] <- %s",frame->hd.stream_id, buffer);
+ }
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+
if(!stream_id) {
/* stream ID zero is for connection-oriented stuff */
DEBUGASSERT(data);
switch(frame->hd.type) {
case NGHTTP2_SETTINGS: {
- uint32_t max_conn = ctx->max_concurrent_streams;
- DEBUGF(LOG_CF(data, cf, "FRAME[SETTINGS]"));
- ctx->max_concurrent_streams = nghttp2_session_get_remote_settings(
- session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
- ctx->enable_push = nghttp2_session_get_remote_settings(
- session, NGHTTP2_SETTINGS_ENABLE_PUSH) != 0;
- DEBUGF(LOG_CF(data, cf, "MAX_CONCURRENT_STREAMS == %d",
- ctx->max_concurrent_streams));
- DEBUGF(LOG_CF(data, cf, "ENABLE_PUSH == %s",
- ctx->enable_push ? "TRUE" : "false"));
- if(data && max_conn != ctx->max_concurrent_streams) {
- /* only signal change if the value actually changed */
- DEBUGF(LOG_CF(data, cf, "MAX_CONCURRENT_STREAMS now %u",
- ctx->max_concurrent_streams));
- multi_connchanged(data->multi);
- }
- /* Since the initial stream window is 64K, a request might be on HOLD,
- * due to exhaustion. The (initial) SETTINGS may announce a much larger
- * window and *assume* that we treat this like a WINDOW_UPDATE. Some
- * servers send an explicit WINDOW_UPDATE, but not all seem to do that.
- * To be safe, we UNHOLD a stream in order not to stall. */
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
- struct stream_ctx *stream = H2_STREAM_CTX(data);
- data->req.keepon &= ~KEEP_SEND_HOLD;
- if(stream) {
- drain_stream(cf, data, stream);
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] un-holding after SETTINGS",
- stream_id));
+ if(!(frame->hd.flags & NGHTTP2_FLAG_ACK)) {
+ uint32_t max_conn = ctx->max_concurrent_streams;
+ ctx->max_concurrent_streams = nghttp2_session_get_remote_settings(
+ session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
+ ctx->enable_push = nghttp2_session_get_remote_settings(
+ session, NGHTTP2_SETTINGS_ENABLE_PUSH) != 0;
+ CURL_TRC_CF(data, cf, "[0] MAX_CONCURRENT_STREAMS: %d",
+ ctx->max_concurrent_streams);
+ CURL_TRC_CF(data, cf, "[0] ENABLE_PUSH: %s",
+ ctx->enable_push ? "TRUE" : "false");
+ if(data && max_conn != ctx->max_concurrent_streams) {
+ /* only signal change if the value actually changed */
+ CURL_TRC_CF(data, cf, "[0] notify MAX_CONCURRENT_STREAMS: %u",
+ ctx->max_concurrent_streams);
+ Curl_multi_connchanged(data->multi);
+ }
+ /* Since the initial stream window is 64K, a request might be on HOLD,
+ * due to exhaustion. The (initial) SETTINGS may announce a much larger
+ * window and *assume* that we treat this like a WINDOW_UPDATE. Some
+ * servers send an explicit WINDOW_UPDATE, but not all seem to do that.
+ * To be safe, we UNHOLD a stream in order not to stall. */
+ if((data->req.keepon & KEEP_SEND_HOLD) &&
+ (data->req.keepon & KEEP_SEND)) {
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ data->req.keepon &= ~KEEP_SEND_HOLD;
+ if(stream) {
+ drain_stream(cf, data, stream);
+ CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
+ stream_id);
+ }
}
}
break;
@@ -1144,26 +1248,20 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
ctx->goaway_error = frame->goaway.error_code;
ctx->last_stream_id = frame->goaway.last_stream_id;
if(data) {
- DEBUGF(LOG_CF(data, cf, "FRAME[GOAWAY, error=%d, last_stream=%u]",
- ctx->goaway_error, ctx->last_stream_id));
infof(data, "received GOAWAY, error=%d, last_stream=%u",
ctx->goaway_error, ctx->last_stream_id);
- multi_connchanged(data->multi);
+ Curl_multi_connchanged(data->multi);
}
break;
- case NGHTTP2_WINDOW_UPDATE:
- DEBUGF(LOG_CF(data, cf, "FRAME[WINDOW_UPDATE]"));
- break;
default:
- DEBUGF(LOG_CF(data, cf, "recv frame %x on 0", frame->hd.type));
+ break;
}
return 0;
}
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
if(!data_s) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] No Curl_easy associated",
- stream_id));
+ CURL_TRC_CF(data, cf, "[%d] No Curl_easy associated", stream_id);
return 0;
}
@@ -1190,8 +1288,8 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
/* Receiving a Stream ID not in the hash should not happen - unless
we have aborted a transfer artificially and there were more data
in the pipeline. Silently ignore. */
- DEBUGF(LOG_CF(CF_DATA_CURRENT(cf), cf, "[h2sid=%d] Data for unknown",
- stream_id));
+ CURL_TRC_CF(CF_DATA_CURRENT(cf), cf, "[%d] Data for unknown",
+ stream_id);
/* consumed explicitly as no one will read it */
nghttp2_session_consume(session, stream_id, len);
return 0;
@@ -1233,8 +1331,6 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
return 0;
}
stream = H2_STREAM_CTX(data_s);
- DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] on_stream_close(), %s (err %d)",
- stream_id, nghttp2_http2_strerror(error_code), error_code));
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1244,6 +1340,11 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
stream->reset = TRUE;
data_s->req.keepon &= ~KEEP_SEND_HOLD;
+ if(stream->error)
+ CURL_TRC_CF(data_s, cf, "[%d] RESET: %s (err %d)",
+ stream_id, nghttp2_http2_strerror(error_code), error_code);
+ else
+ CURL_TRC_CF(data_s, cf, "[%d] CLOSED", stream_id);
drain_stream(cf, data_s, stream);
/* remove `data_s` from the nghttp2 stream */
@@ -1253,7 +1354,6 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
stream_id);
DEBUGASSERT(0);
}
- DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] closed now", stream_id));
return 0;
}
@@ -1270,8 +1370,6 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- DEBUGF(LOG_CF(data_s, cf, "on_begin_headers() was called"));
-
if(frame->hd.type != NGHTTP2_HEADERS) {
return 0;
}
@@ -1377,10 +1475,8 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(stream->bodystarted) {
/* This is a trailer */
- DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] trailer: %.*s: %.*s",
- stream->id,
- (int)namelen, name,
- (int)valuelen, value));
+ CURL_TRC_CF(data_s, cf, "[%d] trailer: %.*s: %.*s",
+ stream->id, (int)namelen, name, (int)valuelen, value);
result = Curl_dynhds_add(&stream->resp_trailers,
(const char *)name, namelen,
(const char *)value, valuelen);
@@ -1417,8 +1513,8 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(CF_DATA_CURRENT(cf) != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] status: HTTP/2 %03d",
- stream->id, stream->status_code));
+ CURL_TRC_CF(data_s, cf, "[%d] status: HTTP/2 %03d",
+ stream->id, stream->status_code);
return 0;
}
@@ -1441,10 +1537,8 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(CF_DATA_CURRENT(cf) != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] header: %.*s: %.*s",
- stream->id,
- (int)namelen, name,
- (int)valuelen, value));
+ CURL_TRC_CF(data_s, cf, "[%d] header: %.*s: %.*s",
+ stream->id, (int)namelen, name, (int)valuelen, value);
return 0; /* 0 is successful */
}
@@ -1490,9 +1584,9 @@ static ssize_t req_body_read_callback(nghttp2_session *session,
if(nread > 0 && stream->upload_left != -1)
stream->upload_left -= nread;
- DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] req_body_read(len=%zu) left=%"
- CURL_FORMAT_CURL_OFF_T " -> %zd, %d",
- stream_id, length, stream->upload_left, nread, result));
+ CURL_TRC_CF(data_s, cf, "[%d] req_body_read(len=%zu) left=%"
+ CURL_FORMAT_CURL_OFF_T " -> %zd, %d",
+ stream_id, length, stream->upload_left, nread, result);
if(stream->upload_left == 0)
*data_flags = NGHTTP2_DATA_FLAG_EOF;
@@ -1565,7 +1659,7 @@ static CURLcode http2_data_done_send(struct Curl_cfilter *cf,
if(!ctx || !ctx->h2 || !stream)
goto out;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] data done send", stream->id));
+ CURL_TRC_CF(data, cf, "[%d] data done send", stream->id);
if(!stream->send_closed) {
stream->send_closed = TRUE;
if(stream->upload_left) {
@@ -1590,8 +1684,8 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
ssize_t rv = 0;
if(stream->error == NGHTTP2_REFUSED_STREAM) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] REFUSED_STREAM, try again on a new "
- "connection", stream->id));
+ CURL_TRC_CF(data, cf, "[%d] REFUSED_STREAM, try again on a new "
+ "connection", stream->id);
connclose(cf->conn, "REFUSED_STREAM"); /* don't use this anymore */
data->state.refused_stream = TRUE;
*err = CURLE_SEND_ERROR; /* trigger Curl_retry_request() later */
@@ -1652,7 +1746,7 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
rv = 0;
out:
- DEBUGF(LOG_CF(data, cf, "handle_stream_close -> %zd, %d", rv, *err));
+ CURL_TRC_CF(data, cf, "handle_stream_close -> %zd, %d", rv, *err);
return rv;
}
@@ -1709,8 +1803,7 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
nghttp2_priority_spec pri_spec;
h2_pri_spec(data, &pri_spec);
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] Queuing PRIORITY",
- stream->id));
+ CURL_TRC_CF(data, cf, "[%d] Queuing PRIORITY", stream->id);
DEBUGASSERT(stream->id != -1);
rv = nghttp2_submit_priority(ctx->h2, NGHTTP2_FLAG_NONE,
stream->id, &pri_spec);
@@ -1724,26 +1817,24 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
out:
if(nghttp2_is_fatal(rv)) {
- DEBUGF(LOG_CF(data, cf, "nghttp2_session_send error (%s)%d",
- nghttp2_strerror(rv), rv));
+ CURL_TRC_CF(data, cf, "nghttp2_session_send error (%s)%d",
+ nghttp2_strerror(rv), rv);
return CURLE_SEND_ERROR;
}
return nw_out_flush(cf, data);
}
static ssize_t stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct stream_ctx *stream,
char *buf, size_t len, CURLcode *err)
{
struct cf_h2_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H2_STREAM_CTX(data);
ssize_t nread = -1;
*err = CURLE_AGAIN;
if(!Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
(unsigned char *)buf, len, err);
- DEBUGF(LOG_CF(data, cf, "recvbuf read(len=%zu) -> %zd, %d",
- len, nread, *err));
if(nread < 0)
goto out;
DEBUGASSERT(nread > 0);
@@ -1751,13 +1842,13 @@ static ssize_t stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
if(nread < 0) {
if(stream->closed) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] returning CLOSE", stream->id));
+ CURL_TRC_CF(data, cf, "[%d] returning CLOSE", stream->id);
nread = http2_handle_stream_close(cf, data, stream, err);
}
else if(stream->reset ||
(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) ||
(ctx->goaway && ctx->last_stream_id < stream->id)) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] returning ERR", stream->id));
+ CURL_TRC_CF(data, cf, "[%d] returning ERR", stream->id);
*err = stream->bodystarted? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
nread = -1;
}
@@ -1768,8 +1859,9 @@ static ssize_t stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
}
out:
- DEBUGF(LOG_CF(data, cf, "stream_recv(len=%zu) -> %zd, %d",
- len, nread, *err));
+ if(nread < 0 && *err != CURLE_AGAIN)
+ CURL_TRC_CF(data, cf, "[%d] stream_recv(len=%zu) -> %zd, %d",
+ stream->id, len, nread, *err);
return nread;
}
@@ -1783,8 +1875,8 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
/* Process network input buffer fist */
if(!Curl_bufq_is_empty(&ctx->inbufq)) {
- DEBUGF(LOG_CF(data, cf, "Process %zu bytes in connection buffer",
- Curl_bufq_len(&ctx->inbufq)));
+ CURL_TRC_CF(data, cf, "Process %zu bytes in connection buffer",
+ Curl_bufq_len(&ctx->inbufq));
if(h2_process_pending_input(cf, data, &result) < 0)
return result;
}
@@ -1804,8 +1896,6 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
}
nread = Curl_bufq_slurp(&ctx->inbufq, nw_in_reader, cf, &result);
- /* DEBUGF(LOG_CF(data, cf, "read %zu bytes nw data -> %zd, %d",
- Curl_bufq_len(&ctx->inbufq), nread, result)); */
if(nread < 0) {
if(result != CURLE_AGAIN) {
failf(data, "Failed receiving HTTP2 data: %d(%s)", result,
@@ -1815,9 +1905,14 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
break;
}
else if(nread == 0) {
+ CURL_TRC_CF(data, cf, "[0] ingress: connection closed");
ctx->conn_closed = TRUE;
break;
}
+ else {
+ CURL_TRC_CF(data, cf, "[0] ingress: read %zd bytes",
+ nread);
+ }
if(h2_process_pending_input(cf, data, &result))
return result;
@@ -1839,9 +1934,21 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
CURLcode result;
struct cf_call_data save;
+ if(!stream) {
+ /* Abnormal call sequence: either this transfer has never opened a stream
+ * (unlikely) or the transfer has been done, cleaned up its resources, but
+ * a read() is called anyway. It is not clear what the calling sequence
+ * is for such a case. */
+ failf(data, "[%zd-%zd], http/2 recv on a transfer never opened "
+ "or already cleared", (ssize_t)data->id,
+ (ssize_t)cf->conn->connection_id);
+ *err = CURLE_HTTP2;
+ return -1;
+ }
+
CF_DATA_SAVE(save, cf, data);
- nread = stream_recv(cf, data, buf, len, err);
+ nread = stream_recv(cf, data, stream, buf, len, err);
if(nread < 0 && *err != CURLE_AGAIN)
goto out;
@@ -1850,7 +1957,7 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
if(*err)
goto out;
- nread = stream_recv(cf, data, buf, len, err);
+ nread = stream_recv(cf, data, stream, buf, len, err);
}
if(nread > 0) {
@@ -1872,28 +1979,34 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
}
if(stream->closed) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] closed stream, set drain",
- stream->id));
+ CURL_TRC_CF(data, cf, "[%d] DRAIN closed stream", stream->id);
drain_stream(cf, data, stream);
}
}
out:
result = h2_progress_egress(cf, data);
- if(result && result != CURLE_AGAIN) {
+ if(result == CURLE_AGAIN) {
+ /* pending data to send, need to be called again. Ideally, we'd
+ * monitor the socket for POLLOUT, but we might not be in SENDING
+ * transfer state any longer and are unable to make this happen.
+ */
+ drain_stream(cf, data, stream);
+ }
+ else if(result) {
*err = result;
nread = -1;
}
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_recv(len=%zu) -> %zd %d, "
- "buffered=%zu, window=%d/%d, connection %d/%d",
- stream->id, len, nread, *err,
- Curl_bufq_len(&stream->recvbuf),
- nghttp2_session_get_stream_effective_recv_data_length(
- ctx->h2, stream->id),
- nghttp2_session_get_stream_effective_local_window_size(
- ctx->h2, stream->id),
- nghttp2_session_get_local_window_size(ctx->h2),
- HTTP2_HUGE_WINDOW_SIZE));
+ CURL_TRC_CF(data, cf, "[%d] cf_recv(len=%zu) -> %zd %d, "
+ "buffered=%zu, window=%d/%d, connection %d/%d",
+ stream->id, len, nread, *err,
+ Curl_bufq_len(&stream->recvbuf),
+ nghttp2_session_get_stream_effective_recv_data_length(
+ ctx->h2, stream->id),
+ nghttp2_session_get_stream_effective_local_window_size(
+ ctx->h2, stream->id),
+ nghttp2_session_get_local_window_size(ctx->h2),
+ HTTP2_HUGE_WINDOW_SIZE);
CF_DATA_RESTORE(cf, save);
return nread;
@@ -1905,7 +2018,6 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
{
struct cf_h2_ctx *ctx = cf->ctx;
struct stream_ctx *stream = NULL;
- struct h1_req_parser h1;
struct dynhds h2_headers;
nghttp2_nv *nva = NULL;
const void *body = NULL;
@@ -1915,7 +2027,6 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
nghttp2_priority_spec pri_spec;
ssize_t nwritten;
- Curl_h1_req_parse_init(&h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
*err = http2_data_setup(cf, data, &stream);
@@ -1924,17 +2035,22 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
goto out;
}
- nwritten = Curl_h1_req_parse_read(&h1, buf, len, NULL, 0, err);
+ nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
if(nwritten < 0)
goto out;
- DEBUGASSERT(h1.done);
- DEBUGASSERT(h1.req);
+ if(!stream->h1.done) {
+ /* need more data */
+ goto out;
+ }
+ DEBUGASSERT(stream->h1.req);
- *err = Curl_http_req_to_h2(&h2_headers, h1.req, data);
+ *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
if(*err) {
nwritten = -1;
goto out;
}
+ /* no longer needed */
+ Curl_h1_req_parse_free(&stream->h1);
nheader = Curl_dynhds_count(&h2_headers);
nva = malloc(sizeof(nghttp2_nv) * nheader);
@@ -1953,29 +2069,9 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
}
-#define MAX_ACC 60000 /* <64KB to account for some overhead */
- {
- size_t acc = 0;
-
- for(i = 0; i < nheader; ++i) {
- acc += nva[i].namelen + nva[i].valuelen;
-
- infof(data, "h2 [%.*s: %.*s]",
- (int)nva[i].namelen, nva[i].name,
- (int)nva[i].valuelen, nva[i].value);
- }
-
- if(acc > MAX_ACC) {
- infof(data, "http_request: Warning: The cumulative length of all "
- "headers exceeds %d bytes and that could cause the "
- "stream to be rejected.", MAX_ACC);
- }
- }
-
h2_pri_spec(data, &pri_spec);
-
- DEBUGF(LOG_CF(data, cf, "send request allowed %d",
- nghttp2_session_check_request_allowed(ctx->h2)));
+ if(!nghttp2_session_check_request_allowed(ctx->h2))
+ CURL_TRC_CF(data, cf, "send request NOT allowed (via nghttp2)");
switch(data->state.httpreq) {
case HTTPREQ_POST:
@@ -1999,19 +2095,35 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
NULL, data);
}
- Curl_safefree(nva);
-
if(stream_id < 0) {
- DEBUGF(LOG_CF(data, cf, "send: nghttp2_submit_request error (%s)%u",
- nghttp2_strerror(stream_id), stream_id));
+ CURL_TRC_CF(data, cf, "send: nghttp2_submit_request error (%s)%u",
+ nghttp2_strerror(stream_id), stream_id);
*err = CURLE_SEND_ERROR;
nwritten = -1;
goto out;
}
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) submit %s",
- stream_id, len, data->state.url));
- infof(data, "Using Stream ID: %u", stream_id);
+#define MAX_ACC 60000 /* <64KB to account for some overhead */
+ if(Curl_trc_is_verbose(data)) {
+ size_t acc = 0;
+
+ infof(data, "[HTTP/2] [%d] OPENED stream for %s",
+ stream_id, data->state.url);
+ for(i = 0; i < nheader; ++i) {
+ acc += nva[i].namelen + nva[i].valuelen;
+
+ infof(data, "[HTTP/2] [%d] [%.*s: %.*s]", stream_id,
+ (int)nva[i].namelen, nva[i].name,
+ (int)nva[i].valuelen, nva[i].value);
+ }
+
+ if(acc > MAX_ACC) {
+ infof(data, "[HTTP/2] Warning: The cumulative length of all "
+ "headers exceeds %d bytes and that could cause the "
+ "stream to be rejected.", MAX_ACC);
+ }
+ }
+
stream->id = stream_id;
stream->local_window_size = H2_STREAM_WINDOW_SIZE;
if(data->set.max_recv_speed) {
@@ -2042,10 +2154,10 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
}
out:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] submit -> %zd, %d",
- stream? stream->id : -1, nwritten, *err));
+ CURL_TRC_CF(data, cf, "[%d] submit -> %zd, %d",
+ stream? stream->id : -1, nwritten, *err);
+ Curl_safefree(nva);
*pstream = stream;
- Curl_h1_req_parse_free(&h1);
Curl_dynhds_free(&h2_headers);
return nwritten;
}
@@ -2059,46 +2171,55 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
int rv;
ssize_t nwritten;
CURLcode result;
- int blocked = 0;
+ int blocked = 0, was_blocked = 0;
CF_DATA_SAVE(save, cf, data);
if(stream && stream->id != -1) {
- if(stream->close_handled) {
- infof(data, "stream %u closed", stream->id);
- *err = CURLE_HTTP2_STREAM;
- nwritten = -1;
- goto out;
- }
- else if(stream->closed) {
- nwritten = http2_handle_stream_close(cf, data, stream, err);
- goto out;
- }
- else if(stream->upload_blocked_len) {
- /* the data in `buf` has alread been submitted or added to the
+ if(stream->upload_blocked_len) {
+ /* the data in `buf` has already been submitted or added to the
* buffers, but have been EAGAINed on the last invocation. */
+ /* TODO: this assertion triggers in OSSFuzz runs and it is not
+ * clear why. Disable for now to let OSSFuzz continue its tests. */
DEBUGASSERT(len >= stream->upload_blocked_len);
if(len < stream->upload_blocked_len) {
/* Did we get called again with a smaller `len`? This should not
- * happend. We are not prepared to handle that. */
- failf(data, "HTTP/2 send again with decreased length");
+ * happen. We are not prepared to handle that. */
+ failf(data, "HTTP/2 send again with decreased length (%zd vs %zd)",
+ len, stream->upload_blocked_len);
*err = CURLE_HTTP2;
nwritten = -1;
goto out;
}
nwritten = (ssize_t)stream->upload_blocked_len;
stream->upload_blocked_len = 0;
+ was_blocked = 1;
+ }
+ else if(stream->closed) {
+ if(stream->resp_hds_complete) {
+ /* Server decided to close the stream after having sent us a findl
+ * response. This is valid if it is not interested in the request
+ * body. This happens on 30x or 40x responses.
+ * We silently discard the data sent, since this is not a transport
+ * error situation. */
+ CURL_TRC_CF(data, cf, "[%d] discarding data"
+ "on closed stream with response", stream->id);
+ *err = CURLE_OK;
+ nwritten = (ssize_t)len;
+ goto out;
+ }
+ infof(data, "stream %u closed", stream->id);
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
}
else {
/* If stream_id != -1, we have dispatched request HEADERS and
* optionally request body, and now are going to send or sending
* more request body in DATA frame */
nwritten = Curl_bufq_write(&stream->sendbuf, buf, len, err);
- if(nwritten < 0) {
- if(*err != CURLE_AGAIN)
- goto out;
- nwritten = 0;
- }
+ if(nwritten < 0 && *err != CURLE_AGAIN)
+ goto out;
}
if(!Curl_bufq_is_empty(&stream->sendbuf)) {
@@ -2124,8 +2245,10 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
result = h2_progress_egress(cf, data);
/* if the stream has been closed in egress handling (nghttp2 does that
* when it does not like the headers, for example */
- if(stream && stream->closed) {
- nwritten = http2_handle_stream_close(cf, data, stream, err);
+ if(stream && stream->closed && !was_blocked) {
+ infof(data, "stream %u closed", stream->id);
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
goto out;
}
else if(result == CURLE_AGAIN) {
@@ -2143,7 +2266,7 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
blocked = 1;
}
- if(stream && blocked) {
+ if(stream && blocked && nwritten > 0) {
/* Unable to send all data, due to connection blocked or H2 window
* exhaustion. Data is left in our stream buffer, or nghttp2's internal
* frame buffer or our network out buffer. */
@@ -2153,19 +2276,19 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
/* H2 flow window exhaustion. We need to HOLD upload until we get
* a WINDOW_UPDATE from the server. */
data->req.keepon |= KEEP_SEND_HOLD;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] holding send as remote flow "
- "window is exhausted", stream->id));
+ CURL_TRC_CF(data, cf, "[%d] holding send as remote flow "
+ "window is exhausted", stream->id);
}
/* Whatever the cause, we need to return CURL_EAGAIN for this call.
* We have unwritten state that needs us being invoked again and EAGAIN
* is the only way to ensure that. */
stream->upload_blocked_len = nwritten;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) BLOCK: win %u/%zu "
- "blocked_len=%zu",
- stream->id, len,
- nghttp2_session_get_remote_window_size(ctx->h2), rwin,
- nwritten));
+ CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) BLOCK: win %u/%zu "
+ "blocked_len=%zu",
+ stream->id, len,
+ nghttp2_session_get_remote_window_size(ctx->h2), rwin,
+ nwritten);
*err = CURLE_AGAIN;
nwritten = -1;
goto out;
@@ -2177,7 +2300,7 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
nwritten = http2_handle_stream_close(cf, data, stream, err);
}
else {
- DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
+ CURL_TRC_CF(data, cf, "send: nothing to do in this session");
*err = CURLE_HTTP2;
nwritten = -1;
}
@@ -2185,24 +2308,24 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
out:
if(stream) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) -> %zd, %d, "
- "upload_left=%" CURL_FORMAT_CURL_OFF_T ", "
- "h2 windows %d-%d (stream-conn), "
- "buffers %zu-%zu (stream-conn)",
- stream->id, len, nwritten, *err,
- (ssize_t)stream->upload_left,
- nghttp2_session_get_stream_remote_window_size(
- ctx->h2, stream->id),
- nghttp2_session_get_remote_window_size(ctx->h2),
- Curl_bufq_len(&stream->sendbuf),
- Curl_bufq_len(&ctx->outbufq)));
+ CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) -> %zd, %d, "
+ "upload_left=%" CURL_FORMAT_CURL_OFF_T ", "
+ "h2 windows %d-%d (stream-conn), "
+ "buffers %zu-%zu (stream-conn)",
+ stream->id, len, nwritten, *err,
+ (ssize_t)stream->upload_left,
+ nghttp2_session_get_stream_remote_window_size(
+ ctx->h2, stream->id),
+ nghttp2_session_get_remote_window_size(ctx->h2),
+ Curl_bufq_len(&stream->sendbuf),
+ Curl_bufq_len(&ctx->outbufq));
}
else {
- DEBUGF(LOG_CF(data, cf, "cf_send(len=%zu) -> %zd, %d, "
- "connection-window=%d, nw_send_buffer(%zu)",
- len, nwritten, *err,
- nghttp2_session_get_remote_window_size(ctx->h2),
- Curl_bufq_len(&ctx->outbufq)));
+ CURL_TRC_CF(data, cf, "cf_send(len=%zu) -> %zd, %d, "
+ "connection-window=%d, nw_send_buffer(%zu)",
+ len, nwritten, *err,
+ nghttp2_session_get_remote_window_size(ctx->h2),
+ Curl_bufq_len(&ctx->outbufq));
}
CF_DATA_RESTORE(cf, save);
return nwritten;
@@ -2273,8 +2396,12 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
if(result)
goto out;
+ /* Send out our SETTINGS and ACKs and such. If that blocks, we
+ * have it buffered and can count this filter as being connected */
result = h2_progress_egress(cf, data);
- if(result)
+ if(result == CURLE_AGAIN)
+ result = CURLE_OK;
+ else if(result)
goto out;
*done = TRUE;
@@ -2282,6 +2409,7 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
result = CURLE_OK;
out:
+ CURL_TRC_CF(data, cf, "cf_connect() -> %d, %d, ", result, *done);
CF_DATA_RESTORE(cf, save);
return result;
}
@@ -2419,8 +2547,8 @@ static bool cf_h2_is_alive(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data);
result = (ctx && ctx->h2 && http2_connisalive(cf, data, input_pending));
- DEBUGF(LOG_CF(data, cf, "conn alive -> %d, input_pending=%d",
- result, *input_pending));
+ CURL_TRC_CF(data, cf, "conn alive -> %d, input_pending=%d",
+ result, *input_pending);
CF_DATA_RESTORE(cf, save);
return result;
}
@@ -2471,7 +2599,7 @@ static CURLcode cf_h2_query(struct Curl_cfilter *cf,
struct Curl_cftype Curl_cft_nghttp2 = {
"HTTP/2",
CF_TYPE_MULTIPLEX,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
cf_h2_destroy,
cf_h2_connect,
cf_h2_close,
@@ -2599,7 +2727,7 @@ CURLcode Curl_http2_switch(struct Curl_easy *data,
conn->httpversion = 20; /* we know we're on HTTP/2 now */
conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- multi_connchanged(data->multi);
+ Curl_multi_connchanged(data->multi);
if(cf->next) {
bool done;
@@ -2627,7 +2755,7 @@ CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data)
cf->conn->httpversion = 20; /* we know we're on HTTP/2 now */
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- multi_connchanged(data->multi);
+ Curl_multi_connchanged(data->multi);
if(cf_h2->next) {
bool done;
@@ -2684,7 +2812,7 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data,
conn->httpversion = 20; /* we know we're on HTTP/2 now */
conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- multi_connchanged(data->multi);
+ Curl_multi_connchanged(data->multi);
if(cf->next) {
bool done;
diff --git a/libs/libcurl/src/http_aws_sigv4.c b/libs/libcurl/src/http_aws_sigv4.c
index e7baaf82cd..395c8093cc 100644
--- a/libs/libcurl/src/http_aws_sigv4.c
+++ b/libs/libcurl/src/http_aws_sigv4.c
@@ -24,7 +24,7 @@
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_AWS)
#include "urldata.h"
#include "strcase.h"
@@ -44,16 +44,16 @@
#include "slist.h"
-#define HMAC_SHA256(k, kl, d, dl, o) \
- do { \
- ret = Curl_hmacit(Curl_HMAC_SHA256, \
- (unsigned char *)k, \
- kl, \
- (unsigned char *)d, \
- dl, o); \
- if(ret) { \
- goto fail; \
- } \
+#define HMAC_SHA256(k, kl, d, dl, o) \
+ do { \
+ result = Curl_hmacit(Curl_HMAC_SHA256, \
+ (unsigned char *)k, \
+ kl, \
+ (unsigned char *)d, \
+ dl, o); \
+ if(result) { \
+ goto fail; \
+ } \
} while(0)
#define TIMESTAMP_SIZE 17
@@ -199,10 +199,41 @@ static CURLcode make_headers(struct Curl_easy *data,
head = tmp_head;
}
+ /* copy user headers to our header list. the logic is based on how http.c
+ handles user headers.
+
+ user headers in format 'name:' with no value are used to signal that an
+ internal header of that name should be removed. those user headers are not
+ added to this list.
+
+ user headers in format 'name;' with no value are used to signal that a
+ header of that name with no value should be sent. those user headers are
+ added to this list but in the format that they will be sent, ie the
+ semi-colon is changed to a colon for format 'name:'.
+
+ user headers with a value of whitespace only, or without a colon or
+ semi-colon, are not added to this list.
+ */
for(l = data->set.headers; l; l = l->next) {
- tmp_head = curl_slist_append(head, l->data);
- if(!tmp_head)
+ char *dupdata, *ptr;
+ char *sep = strchr(l->data, ':');
+ if(!sep)
+ sep = strchr(l->data, ';');
+ if(!sep || (*sep == ':' && !*(sep + 1)))
+ continue;
+ for(ptr = sep + 1; ISSPACE(*ptr); ++ptr)
+ ;
+ if(!*ptr && ptr != sep + 1) /* a value of whitespace only */
+ continue;
+ dupdata = strdup(l->data);
+ if(!dupdata)
goto fail;
+ dupdata[sep - l->data] = ':';
+ tmp_head = Curl_slist_append_nodup(head, dupdata);
+ if(!tmp_head) {
+ free(dupdata);
+ goto fail;
+ }
head = tmp_head;
}
@@ -214,23 +245,22 @@ static CURLcode make_headers(struct Curl_easy *data,
if(!tmp_head)
goto fail;
head = tmp_head;
- *date_header = curl_maprintf("%s: %s", date_hdr_key, timestamp);
+ *date_header = curl_maprintf("%s: %s\r\n", date_hdr_key, timestamp);
}
else {
char *value;
- *date_header = strdup(*date_header);
- if(!*date_header)
- goto fail;
-
value = strchr(*date_header, ':');
- if(!value)
+ if(!value) {
+ *date_header = NULL;
goto fail;
+ }
++value;
while(ISBLANK(*value))
++value;
strncpy(timestamp, value, TIMESTAMP_SIZE - 1);
timestamp[TIMESTAMP_SIZE - 1] = 0;
+ *date_header = NULL;
}
/* alpha-sort in a case sensitive manner */
@@ -370,9 +400,112 @@ fail:
return ret;
}
+struct pair {
+ const char *p;
+ size_t len;
+};
+
+static int compare_func(const void *a, const void *b)
+{
+ const struct pair *aa = a;
+ const struct pair *bb = b;
+ return strncmp(aa->p, bb->p, aa->len < bb->len ? aa->len : bb->len);
+}
+
+#define MAX_QUERYPAIRS 64
+
+static CURLcode canon_query(struct Curl_easy *data,
+ const char *query, struct dynbuf *dq)
+{
+ CURLcode result = CURLE_OK;
+ int entry = 0;
+ int i;
+ const char *p = query;
+ struct pair array[MAX_QUERYPAIRS];
+ struct pair *ap = &array[0];
+ if(!query)
+ return result;
+
+ /* sort the name=value pairs first */
+ do {
+ char *amp;
+ entry++;
+ ap->p = p;
+ amp = strchr(p, '&');
+ if(amp)
+ ap->len = amp - p; /* excluding the ampersand */
+ else {
+ ap->len = strlen(p);
+ break;
+ }
+ ap++;
+ p = amp + 1;
+ } while(entry < MAX_QUERYPAIRS);
+ if(entry == MAX_QUERYPAIRS) {
+ /* too many query pairs for us */
+ failf(data, "aws-sigv4: too many query pairs in URL");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ qsort(&array[0], entry, sizeof(struct pair), compare_func);
+
+ ap = &array[0];
+ for(i = 0; !result && (i < entry); i++, ap++) {
+ size_t len;
+ const char *q = ap->p;
+ if(!ap->len)
+ continue;
+ for(len = ap->len; len && !result; q++, len--) {
+ if(ISALNUM(*q))
+ result = Curl_dyn_addn(dq, q, 1);
+ else {
+ switch(*q) {
+ case '-':
+ case '.':
+ case '_':
+ case '~':
+ case '=':
+ /* allowed as-is */
+ result = Curl_dyn_addn(dq, q, 1);
+ break;
+ case '%':
+ /* uppercase the following if hexadecimal */
+ if(ISXDIGIT(q[1]) && ISXDIGIT(q[2])) {
+ char tmp[3]="%";
+ tmp[1] = Curl_raw_toupper(q[1]);
+ tmp[2] = Curl_raw_toupper(q[2]);
+ result = Curl_dyn_addn(dq, tmp, 3);
+ q += 2;
+ len -= 2;
+ }
+ else
+ /* '%' without a following two-digit hex, encode it */
+ result = Curl_dyn_addn(dq, "%25", 3);
+ break;
+ default: {
+ /* URL encode */
+ const char hex[] = "0123456789ABCDEF";
+ char out[3]={'%'};
+ out[1] = hex[((unsigned char)*q)>>4];
+ out[2] = hex[*q & 0xf];
+ result = Curl_dyn_addn(dq, out, 3);
+ break;
+ }
+ }
+ }
+ }
+ if(i < entry - 1) {
+ /* insert ampersands between query pairs */
+ result = Curl_dyn_addn(dq, "&", 1);
+ }
+ }
+ return result;
+}
+
+
CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
{
- CURLcode ret = CURLE_OUT_OF_MEMORY;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
struct connectdata *conn = data->conn;
size_t len;
const char *arg;
@@ -388,6 +521,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
char date[9];
struct dynbuf canonical_headers;
struct dynbuf signed_headers;
+ struct dynbuf canonical_query;
char *date_header = NULL;
Curl_HttpReq httpreq;
const char *method = NULL;
@@ -416,6 +550,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
/* we init those buffers here, so goto fail will free initialized dynbuf */
Curl_dyn_init(&canonical_headers, CURL_MAX_HTTP_HEADER);
+ Curl_dyn_init(&canonical_query, CURL_MAX_HTTP_HEADER);
Curl_dyn_init(&signed_headers, CURL_MAX_HTTP_HEADER);
/*
@@ -431,15 +566,15 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
/* provider1[:provider2[:region[:service]]]
No string can be longer than N bytes of non-whitespace
- */
+ */
(void)sscanf(arg, "%" MAX_SIGV4_LEN_TXT "[^:]"
":%" MAX_SIGV4_LEN_TXT "[^:]"
":%" MAX_SIGV4_LEN_TXT "[^:]"
":%" MAX_SIGV4_LEN_TXT "s",
provider0, provider1, region, service);
if(!provider0[0]) {
- failf(data, "first provider can't be empty");
- ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ failf(data, "first aws-sigv4 provider can't be empty");
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
goto fail;
}
else if(!provider1[0])
@@ -448,35 +583,38 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
if(!service[0]) {
char *hostdot = strchr(hostname, '.');
if(!hostdot) {
- failf(data, "service missing in parameters and hostname");
- ret = CURLE_URL_MALFORMAT;
+ failf(data, "aws-sigv4: service missing in parameters and hostname");
+ result = CURLE_URL_MALFORMAT;
goto fail;
}
len = hostdot - hostname;
if(len > MAX_SIGV4_LEN) {
- failf(data, "service too long in hostname");
- ret = CURLE_URL_MALFORMAT;
+ failf(data, "aws-sigv4: service too long in hostname");
+ result = CURLE_URL_MALFORMAT;
goto fail;
}
strncpy(service, hostname, len);
service[len] = '\0';
+ infof(data, "aws_sigv4: picked service %s from host", service);
+
if(!region[0]) {
const char *reg = hostdot + 1;
const char *hostreg = strchr(reg, '.');
if(!hostreg) {
- failf(data, "region missing in parameters and hostname");
- ret = CURLE_URL_MALFORMAT;
+ failf(data, "aws-sigv4: region missing in parameters and hostname");
+ result = CURLE_URL_MALFORMAT;
goto fail;
}
len = hostreg - reg;
if(len > MAX_SIGV4_LEN) {
- failf(data, "region too long in hostname");
- ret = CURLE_URL_MALFORMAT;
+ failf(data, "aws-sigv4: region too long in hostname");
+ result = CURLE_URL_MALFORMAT;
goto fail;
}
strncpy(region, reg, len);
region[len] = '\0';
+ infof(data, "aws_sigv4: picked region %s from host", region);
}
}
@@ -491,11 +629,11 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
if(!payload_hash) {
if(sign_as_s3)
- ret = calc_s3_payload_hash(data, httpreq, provider1, sha_hash,
- sha_hex, content_sha256_hdr);
+ result = calc_s3_payload_hash(data, httpreq, provider1, sha_hash,
+ sha_hex, content_sha256_hdr);
else
- ret = calc_payload_hash(data, sha_hash, sha_hex);
- if(ret)
+ result = calc_payload_hash(data, sha_hash, sha_hex);
+ if(result)
goto fail;
payload_hash = sha_hex;
@@ -514,21 +652,20 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
#else
time(&clock);
#endif
- ret = Curl_gmtime(clock, &tm);
- if(ret) {
+ result = Curl_gmtime(clock, &tm);
+ if(result) {
goto fail;
}
if(!strftime(timestamp, sizeof(timestamp), "%Y%m%dT%H%M%SZ", &tm)) {
- ret = CURLE_OUT_OF_MEMORY;
+ result = CURLE_OUT_OF_MEMORY;
goto fail;
}
- ret = make_headers(data, hostname, timestamp, provider1,
- &date_header, content_sha256_hdr,
- &canonical_headers, &signed_headers);
- if(ret)
+ result = make_headers(data, hostname, timestamp, provider1,
+ &date_header, content_sha256_hdr,
+ &canonical_headers, &signed_headers);
+ if(result)
goto fail;
- ret = CURLE_OUT_OF_MEMORY;
if(*content_sha256_hdr) {
/* make_headers() needed this without the \r\n for canonicalization */
@@ -540,6 +677,11 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
memcpy(date, timestamp, sizeof(date));
date[sizeof(date) - 1] = 0;
+ result = canon_query(data, data->state.up.query, &canonical_query);
+ if(result)
+ goto fail;
+ result = CURLE_OUT_OF_MEMORY;
+
canonical_request =
curl_maprintf("%s\n" /* HTTPRequestMethod */
"%s\n" /* CanonicalURI */
@@ -549,13 +691,16 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
"%.*s", /* HashedRequestPayload in hex */
method,
data->state.up.path,
- data->state.up.query ? data->state.up.query : "",
+ Curl_dyn_ptr(&canonical_query) ?
+ Curl_dyn_ptr(&canonical_query) : "",
Curl_dyn_ptr(&canonical_headers),
Curl_dyn_ptr(&signed_headers),
(int)payload_hash_len, payload_hash);
if(!canonical_request)
goto fail;
+ DEBUGF(infof(data, "Canonical request: %s", canonical_request));
+
/* provider 0 lowercase */
Curl_strntolower(provider0, provider0, strlen(provider0));
request_type = curl_maprintf("%s4_request", provider0);
@@ -612,14 +757,19 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
"Credential=%s/%s, "
"SignedHeaders=%s, "
"Signature=%s\r\n"
- "%s\r\n"
+ /*
+ * date_header is added here, only if it wasn't
+ * user-specified (using CURLOPT_HTTPHEADER).
+ * date_header includes \r\n
+ */
+ "%s"
"%s", /* optional sha256 header includes \r\n */
provider0,
user,
credential_scope,
Curl_dyn_ptr(&signed_headers),
sha_hex,
- date_header,
+ date_header ? date_header : "",
content_sha256_hdr);
if(!auth_headers) {
goto fail;
@@ -628,9 +778,10 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
Curl_safefree(data->state.aptr.userpwd);
data->state.aptr.userpwd = auth_headers;
data->state.authhost.done = TRUE;
- ret = CURLE_OK;
+ result = CURLE_OK;
fail:
+ Curl_dyn_free(&canonical_query);
Curl_dyn_free(&canonical_headers);
Curl_dyn_free(&signed_headers);
free(canonical_request);
@@ -639,7 +790,7 @@ fail:
free(str_to_sign);
free(secret);
free(date_header);
- return ret;
+ return result;
}
-#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) */
+#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_AWS) */
diff --git a/libs/libcurl/src/http_digest.c b/libs/libcurl/src/http_digest.c
index 073bbc8fde..344929e825 100644
--- a/libs/libcurl/src/http_digest.c
+++ b/libs/libcurl/src/http_digest.c
@@ -24,7 +24,7 @@
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
#include "urldata.h"
#include "strcase.h"
diff --git a/libs/libcurl/src/http_digest.h b/libs/libcurl/src/http_digest.h
index 7ac8a7fc5f..c3bf52da2c 100644
--- a/libs/libcurl/src/http_digest.h
+++ b/libs/libcurl/src/http_digest.h
@@ -25,7 +25,7 @@
***************************************************************************/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
/* this is for digest header input */
CURLcode Curl_input_digest(struct Curl_easy *data,
@@ -39,6 +39,6 @@ CURLcode Curl_output_digest(struct Curl_easy *data,
void Curl_http_auth_cleanup_digest(struct Curl_easy *data);
-#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_CRYPTO_AUTH */
+#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_DIGEST_AUTH */
#endif /* HEADER_CURL_HTTP_DIGEST_H */
diff --git a/libs/libcurl/src/http_proxy.c b/libs/libcurl/src/http_proxy.c
index c741b01261..fb4e4fa91c 100644
--- a/libs/libcurl/src/http_proxy.c
+++ b/libs/libcurl/src/http_proxy.c
@@ -69,7 +69,7 @@ static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
return CURLE_OK;
}
- DEBUGF(LOG_CF(data, cf, "connect"));
+ CURL_TRC_CF(data, cf, "connect");
connect_sub:
result = cf->next->cft->do_connect(cf->next, data, blocking, done);
if(result || !*done)
@@ -86,7 +86,7 @@ connect_sub:
case CURL_HTTP_VERSION_NONE:
case CURL_HTTP_VERSION_1_0:
case CURL_HTTP_VERSION_1_1:
- DEBUGF(LOG_CF(data, cf, "installing subfilter for HTTP/1.1"));
+ CURL_TRC_CF(data, cf, "installing subfilter for HTTP/1.1");
infof(data, "CONNECT tunnel: HTTP/1.%d negotiated",
(alpn == CURL_HTTP_VERSION_1_0)? 0 : 1);
result = Curl_cf_h1_proxy_insert_after(cf, data);
@@ -96,7 +96,7 @@ connect_sub:
break;
#ifdef USE_NGHTTP2
case CURL_HTTP_VERSION_2:
- DEBUGF(LOG_CF(data, cf, "installing subfilter for HTTP/2"));
+ CURL_TRC_CF(data, cf, "installing subfilter for HTTP/2");
infof(data, "CONNECT tunnel: HTTP/2 negotiated");
result = Curl_cf_h2_proxy_insert_after(cf, data);
if(result)
@@ -105,7 +105,7 @@ connect_sub:
break;
#endif
default:
- DEBUGF(LOG_CF(data, cf, "installing subfilter for default HTTP/1.1"));
+ CURL_TRC_CF(data, cf, "installing subfilter for default HTTP/1.1");
infof(data, "CONNECT tunnel: unsupported ALPN(%d) negotiated", alpn);
result = CURLE_COULDNT_CONNECT;
goto out;
@@ -156,7 +156,7 @@ static void http_proxy_cf_destroy(struct Curl_cfilter *cf,
struct cf_proxy_ctx *ctx = cf->ctx;
(void)data;
- DEBUGF(LOG_CF(data, cf, "destroy"));
+ CURL_TRC_CF(data, cf, "destroy");
free(ctx);
}
@@ -165,7 +165,7 @@ static void http_proxy_cf_close(struct Curl_cfilter *cf,
{
struct cf_proxy_ctx *ctx = cf->ctx;
- DEBUGF(LOG_CF(data, cf, "close"));
+ CURL_TRC_CF(data, cf, "close");
cf->connected = FALSE;
if(ctx->cf_protocol) {
struct Curl_cfilter *f;
diff --git a/libs/libcurl/src/idn.c b/libs/libcurl/src/idn.c
index 47b4d4655d..80836bef5e 100644
--- a/libs/libcurl/src/idn.c
+++ b/libs/libcurl/src/idn.c
@@ -68,27 +68,59 @@ WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
#define IDN_MAX_LENGTH 255
-bool Curl_win32_idn_to_ascii(const char *in, char **out)
+static CURLcode win32_idn_to_ascii(const char *in, char **out)
{
- bool success = FALSE;
-
wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
+ *out = NULL;
if(in_w) {
wchar_t punycode[IDN_MAX_LENGTH];
- int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
+ int chars = IdnToAscii(0, in_w, (int)(wcslen(in_w) + 1), punycode,
+ IDN_MAX_LENGTH);
curlx_unicodefree(in_w);
if(chars) {
char *mstr = curlx_convert_wchar_to_UTF8(punycode);
if(mstr) {
*out = strdup(mstr);
curlx_unicodefree(mstr);
- if(*out)
- success = TRUE;
+ if(!*out)
+ return CURLE_OUT_OF_MEMORY;
}
+ else
+ return CURLE_OUT_OF_MEMORY;
}
+ else
+ return CURLE_URL_MALFORMAT;
}
- return success;
+ return CURLE_OK;
+}
+
+static CURLcode win32_ascii_to_idn(const char *in, char **output)
+{
+ char *out = NULL;
+
+ wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
+ if(in_w) {
+ WCHAR idn[IDN_MAX_LENGTH]; /* stores a UTF-16 string */
+ int chars = IdnToUnicode(0, in_w, (int)(wcslen(in_w) + 1), idn,
+ IDN_MAX_LENGTH);
+ if(chars) {
+ /* 'chars' is "the number of characters retrieved" */
+ char *mstr = curlx_convert_wchar_to_UTF8(idn);
+ if(mstr) {
+ out = strdup(mstr);
+ curlx_unicodefree(mstr);
+ if(!out)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else
+ return CURLE_URL_MALFORMAT;
+ }
+ else
+ return CURLE_URL_MALFORMAT;
+ *output = out;
+ return CURLE_OK;
}
#endif /* USE_WIN32_IDN */
@@ -115,10 +147,15 @@ bool Curl_is_ASCII_name(const char *hostname)
/*
* Curl_idn_decode() returns an allocated IDN decoded string if it was
* possible. NULL on error.
+ *
+ * CURLE_URL_MALFORMAT - the host name could not be converted
+ * CURLE_OUT_OF_MEMORY - memory problem
+ *
*/
-static char *idn_decode(const char *input)
+static CURLcode idn_decode(const char *input, char **output)
{
char *decoded = NULL;
+ CURLcode result = CURLE_OK;
#ifdef USE_LIBIDN2
if(idn2_check_version(IDN2_VERSION)) {
int flags = IDN2_NFC_INPUT
@@ -135,26 +172,68 @@ static char *idn_decode(const char *input)
compatibility */
rc = IDN2_LOOKUP(input, &decoded, IDN2_TRANSITIONAL);
if(rc != IDN2_OK)
- decoded = NULL;
+ result = CURLE_URL_MALFORMAT;
}
#elif defined(USE_WIN32_IDN)
- if(!Curl_win32_idn_to_ascii(input, &decoded))
- decoded = NULL;
+ result = win32_idn_to_ascii(input, &decoded);
+#endif
+ if(!result)
+ *output = decoded;
+ return result;
+}
+
+static CURLcode idn_encode(const char *puny, char **output)
+{
+ char *enc = NULL;
+#ifdef USE_LIBIDN2
+ int rc = idn2_to_unicode_8z8z(puny, &enc, 0);
+ if(rc != IDNA_SUCCESS)
+ return rc == IDNA_MALLOC_ERROR ? CURLE_OUT_OF_MEMORY : CURLE_URL_MALFORMAT;
+#elif defined(USE_WIN32_IDN)
+ CURLcode result = win32_ascii_to_idn(puny, &enc);
+ if(result)
+ return result;
#endif
- return decoded;
+ *output = enc;
+ return CURLE_OK;
}
-char *Curl_idn_decode(const char *input)
+CURLcode Curl_idn_decode(const char *input, char **output)
{
- char *d = idn_decode(input);
+ char *d = NULL;
+ CURLcode result = idn_decode(input, &d);
#ifdef USE_LIBIDN2
- if(d) {
+ if(!result) {
char *c = strdup(d);
idn2_free(d);
- d = c;
+ if(c)
+ d = c;
+ else
+ result = CURLE_OUT_OF_MEMORY;
}
#endif
- return d;
+ if(!result)
+ *output = d;
+ return result;
+}
+
+CURLcode Curl_idn_encode(const char *puny, char **output)
+{
+ char *d = NULL;
+ CURLcode result = idn_encode(puny, &d);
+#ifdef USE_LIBIDN2
+ if(!result) {
+ char *c = strdup(d);
+ idn2_free(d);
+ if(c)
+ d = c;
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ }
+#endif
+ if(!result)
+ *output = d;
+ return result;
}
/*
@@ -182,8 +261,9 @@ CURLcode Curl_idnconvert_hostname(struct hostname *host)
#ifdef USE_IDN
/* Check name for non-ASCII and convert hostname if we can */
if(!Curl_is_ASCII_name(host->name)) {
- char *decoded = idn_decode(host->name);
- if(decoded) {
+ char *decoded;
+ CURLcode result = idn_decode(host->name, &decoded);
+ if(!result) {
if(!*decoded) {
/* zero length is a bad host name */
Curl_idn_free(decoded);
@@ -195,7 +275,7 @@ CURLcode Curl_idnconvert_hostname(struct hostname *host)
host->name = host->encalloc;
}
else
- return CURLE_URL_MALFORMAT;
+ return result;
}
#endif
return CURLE_OK;
diff --git a/libs/libcurl/src/idn.h b/libs/libcurl/src/idn.h
index 82b06e921c..5f5e527479 100644
--- a/libs/libcurl/src/idn.h
+++ b/libs/libcurl/src/idn.h
@@ -24,15 +24,13 @@
*
***************************************************************************/
-#ifdef USE_WIN32_IDN
-bool Curl_win32_idn_to_ascii(const char *in, char **out);
-#endif /* USE_WIN32_IDN */
bool Curl_is_ASCII_name(const char *hostname);
CURLcode Curl_idnconvert_hostname(struct hostname *host);
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
#define USE_IDN
void Curl_free_idnconverted_hostname(struct hostname *host);
-char *Curl_idn_decode(const char *input);
+CURLcode Curl_idn_decode(const char *input, char **output);
+CURLcode Curl_idn_encode(const char *input, char **output);
#ifdef USE_LIBIDN2
#define Curl_idn_free(x) idn2_free(x)
#else
diff --git a/libs/libcurl/src/if2ip.c b/libs/libcurl/src/if2ip.c
index 4d66f33c27..3e9b87cb55 100644
--- a/libs/libcurl/src/if2ip.c
+++ b/libs/libcurl/src/if2ip.c
@@ -92,6 +92,8 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
}
#endif
+#ifndef CURL_DISABLE_BINDLOCAL
+
#if defined(HAVE_GETIFADDRS)
if2ip_result_t Curl_if2ip(int af,
@@ -254,3 +256,5 @@ if2ip_result_t Curl_if2ip(int af,
}
#endif
+
+#endif /* CURL_DISABLE_BINDLOCAL */
diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c
index 1e0c506f1c..e444457442 100644
--- a/libs/libcurl/src/imap.c
+++ b/libs/libcurl/src/imap.c
@@ -45,9 +45,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_UTSNAME_H
-#include <sys/utsname.h>
-#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
@@ -1094,10 +1091,19 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
if(imapcode == '*') {
/* See if this is an UIDVALIDITY response */
- char tmp[20];
- if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) {
- Curl_safefree(imapc->mailbox_uidvalidity);
- imapc->mailbox_uidvalidity = strdup(tmp);
+ if(checkprefix("OK [UIDVALIDITY ", line + 2)) {
+ size_t len = 0;
+ const char *p = &line[2] + strlen("OK [UIDVALIDITY ");
+ while((len < 20) && p[len] && ISDIGIT(p[len]))
+ len++;
+ if(len && (p[len] == ']')) {
+ struct dynbuf uid;
+ Curl_dyn_init(&uid, 20);
+ if(Curl_dyn_addn(&uid, p, len))
+ return CURLE_OUT_OF_MEMORY;
+ Curl_safefree(imapc->mailbox_uidvalidity);
+ imapc->mailbox_uidvalidity = Curl_dyn_ptr(&uid);
+ }
}
}
else if(imapcode == IMAP_RESP_OK) {
@@ -1109,7 +1115,10 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
}
else {
/* Note the currently opened mailbox on this connection */
+ DEBUGASSERT(!imapc->mailbox);
imapc->mailbox = strdup(imap->mailbox);
+ if(!imapc->mailbox)
+ return CURLE_OUT_OF_MEMORY;
if(imap->custom)
result = imap_perform_list(data);
@@ -1806,79 +1815,37 @@ static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
*/
static char *imap_atom(const char *str, bool escape_only)
{
- /* !checksrc! disable PARENBRACE 1 */
- const char atom_specials[] = "(){ %*]";
- const char *p1;
- char *p2;
- size_t backsp_count = 0;
- size_t quote_count = 0;
- bool others_exists = FALSE;
- size_t newlen = 0;
- char *newstr = NULL;
+ struct dynbuf line;
+ size_t nclean;
+ size_t len;
if(!str)
return NULL;
- /* Look for "atom-specials", counting the backslash and quote characters as
- these will need escaping */
- p1 = str;
- while(*p1) {
- if(*p1 == '\\')
- backsp_count++;
- else if(*p1 == '"')
- quote_count++;
- else if(!escape_only) {
- const char *p3 = atom_specials;
-
- while(*p3 && !others_exists) {
- if(*p1 == *p3)
- others_exists = TRUE;
-
- p3++;
- }
- }
-
- p1++;
- }
-
- /* Does the input contain any "atom-special" characters? */
- if(!backsp_count && !quote_count && !others_exists)
+ len = strlen(str);
+ nclean = strcspn(str, "() {%*]\\\"");
+ if(len == nclean)
+ /* nothing to escape, return a strdup */
return strdup(str);
- /* Calculate the new string length */
- newlen = strlen(str) + backsp_count + quote_count + (escape_only ? 0 : 2);
+ Curl_dyn_init(&line, 2000);
- /* Allocate the new string */
- newstr = (char *) malloc((newlen + 1) * sizeof(char));
- if(!newstr)
+ if(!escape_only && Curl_dyn_addn(&line, "\"", 1))
return NULL;
- /* Surround the string in quotes if necessary */
- p2 = newstr;
- if(!escape_only) {
- newstr[0] = '"';
- newstr[newlen - 1] = '"';
- p2++;
+ while(*str) {
+ if((*str == '\\' || *str == '"') &&
+ Curl_dyn_addn(&line, "\\", 1))
+ return NULL;
+ if(Curl_dyn_addn(&line, str, 1))
+ return NULL;
+ str++;
}
- /* Copy the string, escaping backslash and quote characters along the way */
- p1 = str;
- while(*p1) {
- if(*p1 == '\\' || *p1 == '"') {
- *p2 = '\\';
- p2++;
- }
-
- *p2 = *p1;
-
- p1++;
- p2++;
- }
-
- /* Terminate the string */
- newstr[newlen] = '\0';
+ if(!escape_only && Curl_dyn_addn(&line, "\"", 1))
+ return NULL;
- return newstr;
+ return Curl_dyn_ptr(&line);
}
/***********************************************************************
diff --git a/libs/libcurl/src/inet_ntop.c b/libs/libcurl/src/inet_ntop.c
index 786634114d..90a9453a30 100644
--- a/libs/libcurl/src/inet_ntop.c
+++ b/libs/libcurl/src/inet_ntop.c
@@ -117,8 +117,9 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
if(words[i] == 0) {
- if(cur.base == -1)
- cur.base = i, cur.len = 1;
+ if(cur.base == -1) {
+ cur.base = i; cur.len = 1;
+ }
else
cur.len++;
}
diff --git a/libs/libcurl/src/krb5.c b/libs/libcurl/src/krb5.c
index 7c9e8da7ba..d69be2c17a 100644
--- a/libs/libcurl/src/krb5.c
+++ b/libs/libcurl/src/krb5.c
@@ -72,7 +72,7 @@ static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
char *sptr = s;
CURLcode result = CURLE_OK;
#ifdef HAVE_GSSAPI
- enum protection_level data_sec = conn->data_prot;
+ unsigned char data_sec = conn->data_prot;
#endif
if(!cmd)
@@ -91,7 +91,7 @@ static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
#ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD;
#endif
- result = Curl_write(data, conn->sock[FIRSTSOCKET], sptr, write_len,
+ result = Curl_nwrite(data, FIRSTSOCKET, sptr, write_len,
&bytes_written);
#ifdef HAVE_GSSAPI
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
@@ -385,7 +385,7 @@ static const struct Curl_sec_client_mech Curl_krb5_client_mech = {
};
static const struct {
- enum protection_level level;
+ unsigned char level;
const char *name;
} level_names[] = {
{ PROT_CLEAR, "clear" },
@@ -394,8 +394,7 @@ static const struct {
{ PROT_PRIVATE, "private" }
};
-static enum protection_level
-name_to_level(const char *name)
+static unsigned char name_to_level(const char *name)
{
int i;
for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++)
@@ -734,7 +733,7 @@ static int sec_set_protection_level(struct Curl_easy *data)
{
int code;
struct connectdata *conn = data->conn;
- enum protection_level level = conn->request_data_prot;
+ unsigned char level = conn->request_data_prot;
DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
@@ -793,7 +792,7 @@ static int sec_set_protection_level(struct Curl_easy *data)
int
Curl_sec_request_prot(struct connectdata *conn, const char *level)
{
- enum protection_level l = name_to_level(level);
+ unsigned char l = name_to_level(level);
if(l == PROT_NONE)
return -1;
DEBUGASSERT(l > PROT_NONE && l < PROT_LAST);
diff --git a/libs/libcurl/src/ldap.c b/libs/libcurl/src/ldap.c
index 721c3a6f39..c144c24d51 100644
--- a/libs/libcurl/src/ldap.c
+++ b/libs/libcurl/src/ldap.c
@@ -239,7 +239,7 @@ static int ldap_win_bind_auth(LDAP *server, const char *user,
}
else
#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if !defined(CURL_DISABLE_DIGEST_AUTH)
if(authflags & CURLAUTH_DIGEST) {
method = LDAP_AUTH_DIGEST;
}
@@ -762,7 +762,7 @@ quit:
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- connclose(conn, "LDAP connection always disable re-use");
+ connclose(conn, "LDAP connection always disable reuse");
return result;
}
diff --git a/libs/libcurl/src/libcurl.plist b/libs/libcurl/src/libcurl.plist
index f1e86cc3a8..62325c2f70 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>8.2.1</string>
+ <string>8.3.0</string>
<key>CFBundleName</key>
<string>libcurl</string>
@@ -27,9 +27,9 @@
<string>????</string>
<key>CFBundleShortVersionString</key>
- <string>libcurl 8.2.1</string>
+ <string>libcurl 8.3.0</string>
<key>CFBundleGetInfoString</key>
- <string>libcurl.plist 8.2.1</string>
+ <string>libcurl.plist 8.3.0</string>
</dict>
</plist>
diff --git a/libs/libcurl/src/macos.c b/libs/libcurl/src/macos.c
index d316effc5a..c6d2c11cce 100644
--- a/libs/libcurl/src/macos.c
+++ b/libs/libcurl/src/macos.c
@@ -24,21 +24,16 @@
#include "curl_setup.h"
-#if defined(__APPLE__)
-
-#if !defined(TARGET_OS_OSX) || TARGET_OS_OSX
+#ifdef CURL_MACOS_CALL_COPYPROXIES
#include <curl/curl.h>
#include "macos.h"
-#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
-#endif
CURLcode Curl_macos_init(void)
{
-#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
{
/*
* The automagic conversion from IPv4 literals to IPv6 literals only
@@ -46,17 +41,15 @@ CURLcode Curl_macos_init(void)
* 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.
+ * This function is only available on macOS and is not needed for
+ * IPv4-only builds, hence the conditions for defining
+ * CURL_MACOS_CALL_COPYPROXIES in curl_setup.h.
*/
CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
if(dict)
CFRelease(dict);
}
-#endif
return CURLE_OK;
}
-#endif /* TARGET_OS_OSX */
-
-#endif /* __APPLE__ */
+#endif
diff --git a/libs/libcurl/src/macos.h b/libs/libcurl/src/macos.h
index f57b49538e..c4ca63eece 100644
--- a/libs/libcurl/src/macos.h
+++ b/libs/libcurl/src/macos.h
@@ -23,9 +23,10 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+
#include "curl_setup.h"
-#if defined(__APPLE__) && (!defined(TARGET_OS_OSX) || TARGET_OS_OSX)
+#ifdef CURL_MACOS_CALL_COPYPROXIES
CURLcode Curl_macos_init(void);
diff --git a/libs/libcurl/src/md4.c b/libs/libcurl/src/md4.c
index fc4ac18e3e..c7ce9e6d80 100644
--- a/libs/libcurl/src/md4.c
+++ b/libs/libcurl/src/md4.c
@@ -42,6 +42,7 @@
#ifdef USE_WOLFSSL
#include <wolfssl/options.h>
+#define VOID_MD4_INIT
#ifdef NO_MD4
#define WOLFSSL_NO_MD4
#endif
@@ -92,9 +93,10 @@
typedef struct md4_ctx MD4_CTX;
-static void MD4_Init(MD4_CTX *ctx)
+static int MD4_Init(MD4_CTX *ctx)
{
md4_init(ctx);
+ return 1;
}
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
@@ -114,9 +116,9 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
#elif defined(AN_APPLE_OS)
typedef CC_MD4_CTX MD4_CTX;
-static void MD4_Init(MD4_CTX *ctx)
+static int MD4_Init(MD4_CTX *ctx)
{
- (void)CC_MD4_Init(ctx);
+ return CC_MD4_Init(ctx);
}
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
@@ -137,15 +139,22 @@ struct md4_ctx {
};
typedef struct md4_ctx MD4_CTX;
-static void MD4_Init(MD4_CTX *ctx)
+static int MD4_Init(MD4_CTX *ctx)
{
ctx->hCryptProv = 0;
ctx->hHash = 0;
- if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
- CryptCreateHash(ctx->hCryptProv, CALG_MD4, 0, 0, &ctx->hHash);
+ if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ return 0;
+
+ if(!CryptCreateHash(ctx->hCryptProv, CALG_MD4, 0, 0, &ctx->hHash)) {
+ CryptReleaseContext(ctx->hCryptProv, 0);
+ ctx->hCryptProv = 0;
+ return 0;
}
+
+ return 1;
}
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
@@ -176,10 +185,11 @@ struct md4_ctx {
};
typedef struct md4_ctx MD4_CTX;
-static void MD4_Init(MD4_CTX *ctx)
+static int MD4_Init(MD4_CTX *ctx)
{
ctx->data = NULL;
ctx->size = 0;
+ return 1;
}
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
@@ -258,7 +268,7 @@ struct md4_ctx {
};
typedef struct md4_ctx MD4_CTX;
-static void MD4_Init(MD4_CTX *ctx);
+static int MD4_Init(MD4_CTX *ctx);
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
@@ -397,7 +407,7 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
return ptr;
}
-static void MD4_Init(MD4_CTX *ctx)
+static int MD4_Init(MD4_CTX *ctx)
{
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
@@ -406,6 +416,7 @@ static void MD4_Init(MD4_CTX *ctx)
ctx->lo = 0;
ctx->hi = 0;
+ return 1;
}
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
@@ -496,14 +507,21 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
#endif /* CRYPTO LIBS */
-void Curl_md4it(unsigned char *output, const unsigned char *input,
- const size_t len)
+CURLcode Curl_md4it(unsigned char *output, const unsigned char *input,
+ const size_t len)
{
MD4_CTX ctx;
+#ifdef VOID_MD4_INIT
MD4_Init(&ctx);
+#else
+ if(!MD4_Init(&ctx))
+ return CURLE_FAILED_INIT;
+#endif
+
MD4_Update(&ctx, input, curlx_uztoui(len));
MD4_Final(output, &ctx);
+ return CURLE_OK;
}
#endif /* USE_CURL_NTLM_CORE */
diff --git a/libs/libcurl/src/md5.c b/libs/libcurl/src/md5.c
index 965cf35711..9e68d2d98c 100644
--- a/libs/libcurl/src/md5.c
+++ b/libs/libcurl/src/md5.c
@@ -24,7 +24,8 @@
#include "curl_setup.h"
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
+ || !defined(CURL_DISABLE_DIGEST_AUTH)
#include <string.h>
#include <curl/curl.h>
@@ -213,7 +214,8 @@ static CURLcode my_md5_init(my_md5_ctx *ctx)
if(!CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash)) {
CryptReleaseContext(ctx->hCryptProv, 0);
- return CURLE_OUT_OF_MEMORY;
+ ctx->hCryptProv = 0;
+ return CURLE_FAILED_INIT;
}
return CURLE_OK;
@@ -651,4 +653,4 @@ CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
return CURLE_OK;
}
-#endif /* CURL_DISABLE_CRYPTO_AUTH */
+#endif /* Using NTLM (without SSPI) || Digest */
diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c
index 3e47aee65a..90849e7508 100644
--- a/libs/libcurl/src/mime.c
+++ b/libs/libcurl/src/mime.c
@@ -1167,14 +1167,16 @@ static void mime_subparts_unbind(void *ptr)
void Curl_mime_cleanpart(curl_mimepart *part)
{
- cleanup_part_content(part);
- curl_slist_free_all(part->curlheaders);
- if(part->flags & MIME_USERHEADERS_OWNER)
- curl_slist_free_all(part->userheaders);
- Curl_safefree(part->mimetype);
- Curl_safefree(part->name);
- Curl_safefree(part->filename);
- Curl_mime_initpart(part);
+ if(part) {
+ cleanup_part_content(part);
+ curl_slist_free_all(part->curlheaders);
+ if(part->flags & MIME_USERHEADERS_OWNER)
+ curl_slist_free_all(part->userheaders);
+ Curl_safefree(part->mimetype);
+ Curl_safefree(part->name);
+ Curl_safefree(part->filename);
+ Curl_mime_initpart(part);
+ }
}
/* Recursively delete a mime handle and its parts. */
diff --git a/libs/libcurl/src/mqtt.c b/libs/libcurl/src/mqtt.c
index cd72c5015e..eb4ee55533 100644
--- a/libs/libcurl/src/mqtt.c
+++ b/libs/libcurl/src/mqtt.c
@@ -117,11 +117,9 @@ static CURLcode mqtt_send(struct Curl_easy *data,
char *buf, size_t len)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
struct MQTT *mq = data->req.p.mqtt;
ssize_t n;
- result = Curl_write(data, sockfd, buf, len, &n);
+ result = Curl_nwrite(data, FIRSTSOCKET, buf, len, &n);
if(result)
return result;
Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c
index 6d9a39e937..78c4a23ba4 100644
--- a/libs/libcurl/src/multi.c
+++ b/libs/libcurl/src/multi.c
@@ -459,7 +459,7 @@ struct Curl_multi *curl_multi_init(void)
CURL_DNS_HASH_SIZE);
}
-#ifdef DEBUGBUILD
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data)
{
if(!multi->warned) {
@@ -638,7 +638,6 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
CONNCACHE_UNLOCK(data);
multi_warn_debug(multi, data);
- infof(data, "processing: %s", data->state.url);
return CURLM_OK;
}
@@ -668,8 +667,14 @@ static CURLcode multi_done(struct Curl_easy *data,
struct connectdata *conn = data->conn;
unsigned int i;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ DEBUGF(infof(data, "multi_done[%s]: status: %d prem: %d done: %d",
+ multi_statename[data->mstate],
+ (int)status, (int)premature, data->state.done));
+#else
DEBUGF(infof(data, "multi_done: status: %d prem: %d done: %d",
(int)status, (int)premature, data->state.done));
+#endif
if(data->state.done)
/* Stop if multi_done() has already been called */
@@ -752,7 +757,7 @@ static CURLcode multi_done(struct Curl_easy *data,
if premature is TRUE, it means this connection was said to be DONE before
the entire request operation is complete and thus we can't know in what
- state it is for re-using, so we're forced to close it. In a perfect world
+ state it is for reusing, so we're forced to close it. In a perfect world
we can add code that keep track of if we really must close it here or not,
but currently we have no such detail knowledge.
*/
@@ -769,7 +774,7 @@ static CURLcode multi_done(struct Curl_easy *data,
#endif
) || conn->bits.close
|| (premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
- DEBUGF(infof(data, "multi_done, not re-using connection=%"
+ DEBUGF(infof(data, "multi_done, not reusing connection=%"
CURL_FORMAT_CURL_OFF_T ", forbid=%d"
", close=%d, premature=%d, conn_multiplex=%d",
conn->connection_id,
@@ -1105,8 +1110,7 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
- data = multi->easyp;
- while(data) {
+ for(data = multi->easyp; data; data = data->next) {
int bitmap;
#ifdef __clang_analyzer_
/* to prevent "The left operand of '>=' is a garbage value" warnings */
@@ -1115,30 +1119,21 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
bitmap = multi_getsock(data, sockbunch);
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
- curl_socket_t s = CURL_SOCKET_BAD;
-
- if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK(sockbunch[i])) {
- if(!FDSET_SOCK(sockbunch[i]))
- /* pretend it doesn't exist */
- continue;
- FD_SET(sockbunch[i], read_fd_set);
- s = sockbunch[i];
- }
- if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK(sockbunch[i])) {
+ if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
if(!FDSET_SOCK(sockbunch[i]))
/* pretend it doesn't exist */
continue;
- FD_SET(sockbunch[i], write_fd_set);
- s = sockbunch[i];
+ if(bitmap & GETSOCK_READSOCK(i))
+ FD_SET(sockbunch[i], read_fd_set);
+ if(bitmap & GETSOCK_WRITESOCK(i))
+ FD_SET(sockbunch[i], write_fd_set);
+ if((int)sockbunch[i] > this_max_fd)
+ this_max_fd = (int)sockbunch[i];
}
- if(s == CURL_SOCKET_BAD)
- /* this socket is unused, break out of loop */
+ else {
break;
- if((int)s > this_max_fd)
- this_max_fd = (int)s;
+ }
}
-
- data = data->next; /* check next handle */
}
*max_fd = this_max_fd;
@@ -1201,27 +1196,17 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
return CURLM_BAD_FUNCTION_ARGUMENT;
/* Count up how many fds we have from the multi handle */
- data = multi->easyp;
- while(data) {
+ for(data = multi->easyp; data; data = data->next) {
bitmap = multi_getsock(data, sockbunch);
- for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
- curl_socket_t s = CURL_SOCKET_BAD;
-
- if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
- ++nfds;
- s = sockbunch[i];
- }
- if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
+ for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
+ if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
++nfds;
- s = sockbunch[i];
}
- if(s == CURL_SOCKET_BAD) {
+ else {
break;
}
}
-
- data = data->next; /* check next handle */
}
/* If the internally desired timeout is actually shorter than requested from
@@ -1261,49 +1246,42 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
if(curlfds) {
/* Add the curl handles to our pollfds first */
- data = multi->easyp;
- while(data) {
+ for(data = multi->easyp; data; data = data->next) {
bitmap = multi_getsock(data, sockbunch);
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
- curl_socket_t s = CURL_SOCKET_BAD;
+ if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
+ struct pollfd *ufd = &ufds[nfds++];
#ifdef USE_WINSOCK
- long mask = 0;
+ long mask = 0;
#endif
- if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
- s = sockbunch[i];
+ ufd->fd = sockbunch[i];
+ ufd->events = 0;
+ if(bitmap & GETSOCK_READSOCK(i)) {
#ifdef USE_WINSOCK
- mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
+ mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
#endif
- ufds[nfds].fd = s;
- ufds[nfds].events = POLLIN;
- ++nfds;
- }
- if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
- s = sockbunch[i];
+ ufd->events |= POLLIN;
+ }
+ if(bitmap & GETSOCK_WRITESOCK(i)) {
+#ifdef USE_WINSOCK
+ mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
+ reset_socket_fdwrite(sockbunch[i]);
+#endif
+ ufd->events |= POLLOUT;
+ }
#ifdef USE_WINSOCK
- mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
- reset_socket_fdwrite(s);
+ if(WSAEventSelect(sockbunch[i], multi->wsa_event, mask) != 0) {
+ if(ufds_malloc)
+ free(ufds);
+ return CURLM_INTERNAL_ERROR;
+ }
#endif
- ufds[nfds].fd = s;
- ufds[nfds].events = POLLOUT;
- ++nfds;
}
- /* 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 */
+ else {
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 */
}
}
@@ -1412,8 +1390,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
/* Count up all our own sockets that had activity,
and remove them from the event. */
if(curlfds) {
- data = multi->easyp;
- while(data) {
+
+ for(data = multi->easyp; data; data = data->next) {
bitmap = multi_getsock(data, sockbunch);
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
@@ -1430,8 +1408,6 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
break;
}
}
-
- data = data->next;
}
}
@@ -1577,6 +1553,18 @@ static bool multi_ischanged(struct Curl_multi *multi, bool clear)
return retval;
}
+/*
+ * Curl_multi_connchanged() is called to tell that there is a connection in
+ * this multi handle that has changed state (multiplexing become possible, the
+ * number of allowed streams changed or similar), and a subsequent use of this
+ * multi handle should move CONNECT_PEND handles back to CONNECT to have them
+ * retry.
+ */
+void Curl_multi_connchanged(struct Curl_multi *multi)
+{
+ multi->recheckstate = TRUE;
+}
+
CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
struct Curl_easy *data,
struct connectdata *conn)
@@ -1611,7 +1599,6 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done)
DEBUGASSERT(conn->handler);
if(conn->handler->do_it)
- /* generic protocol-specific function pointer set in curl_connect() */
result = conn->handler->do_it(data, done);
return result;
@@ -1787,9 +1774,8 @@ static CURLcode protocol_connect(struct Curl_easy *data,
*/
static CURLcode readrewind(struct Curl_easy *data)
{
- struct connectdata *conn = data->conn;
curl_mimepart *mimepart = &data->set.mimepost;
- DEBUGASSERT(conn);
+ DEBUGASSERT(data->conn);
data->state.rewindbeforesend = FALSE; /* we rewind now */
@@ -1802,12 +1788,12 @@ static CURLcode readrewind(struct Curl_easy *data)
/* We have sent away data. If not using CURLOPT_POSTFIELDS or
CURLOPT_HTTPPOST, call app to rewind
*/
- if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
- struct HTTP *http = data->req.p.http;
-
- if(http->sendit)
- mimepart = http->sendit;
+#ifndef CURL_DISABLE_HTTP
+ if(data->conn->handler->protocol & PROTO_FAMILY_HTTP) {
+ if(data->state.mimepost)
+ mimepart = data->state.mimepost;
}
+#endif
if(data->set.postfields ||
(data->state.httpreq == HTTPREQ_GET) ||
(data->state.httpreq == HTTPREQ_HEAD))
@@ -2460,7 +2446,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(done || (result == CURLE_RECV_ERROR)) {
/* If CURLE_RECV_ERROR happens early enough, we assume it was a race
- * condition and the server closed the re-used connection exactly when
+ * condition and the server closed the reused connection exactly when
* we wanted to use it, so figure out if that is indeed the case.
*/
CURLcode ret = Curl_retry_request(data, &newurl);
@@ -2502,7 +2488,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(result) {
/*
* The transfer phase returned error, we mark the connection to get
- * closed to prevent being re-used. This is because we can't possibly
+ * closed to prevent being reused. This is because we can't possibly
* know if the connection is in a good shape or not now. Unless it is
* a protocol which uses two "channels" like FTP, as then the error
* happened in the data connection.
@@ -2933,7 +2919,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
/* walk over the sockets we got right now */
for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
- (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
+ (curraction & GETSOCK_MASK_RW(i));
i++) {
unsigned char action = CURL_POLL_NONE;
unsigned char prevaction = 0;
diff --git a/libs/libcurl/src/multiif.h b/libs/libcurl/src/multiif.h
index 921a377fad..1bdd6c660b 100644
--- a/libs/libcurl/src/multiif.h
+++ b/libs/libcurl/src/multiif.h
@@ -41,6 +41,8 @@ void Curl_set_in_callback(struct Curl_easy *data, bool value);
bool Curl_is_in_callback(struct Curl_easy *easy);
CURLcode Curl_preconnect(struct Curl_easy *data);
+void Curl_multi_connchanged(struct Curl_multi *multi);
+
/* Internal version of curl_multi_init() accepts size parameters for the
socket, connection and dns hashes */
struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
@@ -57,6 +59,9 @@ struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
/* set the bit for the given sock number to make the bitmap for readable */
#define GETSOCK_READSOCK(x) (1 << (x))
+/* mask for checking if read and/or write is set for index x */
+#define GETSOCK_MASK_RW(x) (GETSOCK_READSOCK(x)|GETSOCK_WRITESOCK(x))
+
#ifdef DEBUGBUILD
/*
* Curl_multi_dump is not a stable public function, this is only meant to
diff --git a/libs/libcurl/src/pingpong.c b/libs/libcurl/src/pingpong.c
index 4134e2749f..bd30f8e5e6 100644
--- a/libs/libcurl/src/pingpong.c
+++ b/libs/libcurl/src/pingpong.c
@@ -204,8 +204,7 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
#ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD;
#endif
- result = Curl_write(data, conn->sock[FIRSTSOCKET], s, write_len,
- &bytes_written);
+ result = Curl_nwrite(data, FIRSTSOCKET, s, write_len, &bytes_written);
if(result)
return result;
#ifdef HAVE_GSSAPI
@@ -341,7 +340,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
ssize_t clipamount = 0;
bool restart = FALSE;
- data->req.headerbytecount += (long)gotbytes;
+ data->req.headerbytecount += (unsigned int)gotbytes;
pp->nread_resp += gotbytes;
for(i = 0; i < gotbytes; ptr++, i++) {
@@ -467,11 +466,10 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
struct pingpong *pp)
{
/* we have a piece of a command still left to send */
- struct connectdata *conn = data->conn;
ssize_t written;
- curl_socket_t sock = conn->sock[FIRSTSOCKET];
- CURLcode result = Curl_write(data, sock, pp->sendthis + pp->sendsize -
- pp->sendleft, pp->sendleft, &written);
+ CURLcode result = Curl_nwrite(data, FIRSTSOCKET,
+ pp->sendthis + pp->sendsize - pp->sendleft,
+ pp->sendleft, &written);
if(result)
return result;
diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c
index d19308dd32..32e410f79f 100644
--- a/libs/libcurl/src/pop3.c
+++ b/libs/libcurl/src/pop3.c
@@ -47,9 +47,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_UTSNAME_H
-#include <sys/utsname.h>
-#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
@@ -422,7 +419,7 @@ static CURLcode pop3_perform_user(struct Curl_easy *data,
return result;
}
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifndef CURL_DISABLE_DIGEST_AUTH
/***********************************************************************
*
* pop3_perform_apop()
@@ -566,7 +563,7 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data,
}
if(!result && progress == SASL_IDLE) {
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifndef CURL_DISABLE_DIGEST_AUTH
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
/* Perform APOP authentication */
result = pop3_perform_apop(data, conn);
@@ -834,7 +831,7 @@ static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
pop3_state(data, POP3_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifndef CURL_DISABLE_DIGEST_AUTH
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
/* Perform APOP authentication */
result = pop3_perform_apop(data, conn);
@@ -855,7 +852,7 @@ static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
return result;
}
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifndef CURL_DISABLE_DIGEST_AUTH
/* For APOP responses */
static CURLcode pop3_state_apop_resp(struct Curl_easy *data, int pop3code,
pop3state instate)
@@ -1018,7 +1015,7 @@ static CURLcode pop3_statemachine(struct Curl_easy *data,
result = pop3_state_auth_resp(data, pop3code, pop3c->state);
break;
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifndef CURL_DISABLE_DIGEST_AUTH
case POP3_APOP:
result = pop3_state_apop_resp(data, pop3code, pop3c->state);
break;
diff --git a/libs/libcurl/src/rand.c b/libs/libcurl/src/rand.c
index 7a40f4ac63..faeecad273 100644
--- a/libs/libcurl/src/rand.c
+++ b/libs/libcurl/src/rand.c
@@ -36,6 +36,7 @@ uint32_t arc4random(void);
#endif
#include <curl/curl.h>
+#include "urldata.h"
#include "vtls/vtls.h"
#include "sendf.h"
#include "timeval.h"
@@ -187,7 +188,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
* 'rnd' points to.
*
* If libcurl is built without TLS support or with a TLS backend that lacks a
- * proper random API (rustls, Gskit or mbedTLS), this function will use "weak"
+ * proper random API (rustls or mbedTLS), this function will use "weak"
* random.
*
* When built *with* TLS support and a backend that offers strong random, it
diff --git a/libs/libcurl/src/rand.h b/libs/libcurl/src/rand.h
index c215319054..9acc235aa1 100644
--- a/libs/libcurl/src/rand.h
+++ b/libs/libcurl/src/rand.h
@@ -24,20 +24,6 @@
*
***************************************************************************/
-/*
- * Curl_rand() stores 'num' number of random unsigned characters in the buffer
- * 'rnd' points to.
- *
- * If libcurl is built without TLS support or with a TLS backend that lacks a
- * proper random API (Gskit or mbedTLS), this function will use "weak" random.
- *
- * When built *with* TLS support and a backend that offers strong random, it
- * will return error if it cannot provide strong random values.
- *
- * NOTE: 'data' may be passed in as NULL when coming from external API without
- * easy handle!
- *
- */
CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
/*
diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c
index 568493d56b..da82a92a19 100644
--- a/libs/libcurl/src/sendf.c
+++ b/libs/libcurl/src/sendf.c
@@ -139,27 +139,27 @@ static size_t convert_lineends(struct Curl_easy *data,
#endif /* CURL_DO_LINEEND_CONV && !CURL_DISABLE_FTP */
/*
- * Curl_write() is an internal write function that sends data to the
- * server. Works with plain sockets, SCP, SSL or kerberos.
+ * Curl_nwrite() is an internal write function that sends data to the
+ * server. Works with a socket index for the connection.
*
- * If the write would block (CURLE_AGAIN), we return CURLE_OK and
- * (*written == 0). Otherwise we return regular CURLcode value.
+ * If the write would block (CURLE_AGAIN), it returns CURLE_OK and
+ * (*nwritten == 0). Otherwise we return regular CURLcode value.
*/
-CURLcode Curl_write(struct Curl_easy *data,
- curl_socket_t sockfd,
- const void *mem,
- size_t len,
- ssize_t *written)
+CURLcode Curl_nwrite(struct Curl_easy *data,
+ int sockindex,
+ const void *buf,
+ size_t blen,
+ ssize_t *pnwritten)
{
- ssize_t bytes_written;
+ ssize_t nwritten;
CURLcode result = CURLE_OK;
struct connectdata *conn;
- int num;
+
+ DEBUGASSERT(sockindex >= 0 && sockindex < 2);
+ DEBUGASSERT(pnwritten);
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
conn = data->conn;
- num = (sockfd != CURL_SOCKET_BAD && sockfd == conn->sock[SECONDARYSOCKET]);
-
#ifdef CURLDEBUG
{
/* Allow debug builds to override this logic to force short sends
@@ -168,31 +168,47 @@ CURLcode Curl_write(struct Curl_easy *data,
if(p) {
size_t altsize = (size_t)strtoul(p, NULL, 10);
if(altsize)
- len = CURLMIN(len, altsize);
+ blen = CURLMIN(blen, altsize);
}
}
#endif
- bytes_written = conn->send[num](data, num, mem, len, &result);
-
- *written = bytes_written;
- if(bytes_written >= 0)
- /* we completely ignore the curlcode value when subzero is not returned */
- return CURLE_OK;
+ nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result);
+ if(result == CURLE_AGAIN) {
+ nwritten = 0;
+ result = CURLE_OK;
+ }
+ else if(result) {
+ nwritten = -1; /* make sure */
+ }
+ else {
+ DEBUGASSERT(nwritten >= 0);
+ }
- /* handle CURLE_AGAIN or a send failure */
- switch(result) {
- case CURLE_AGAIN:
- *written = 0;
- return CURLE_OK;
+ *pnwritten = nwritten;
+ return result;
+}
- case CURLE_OK:
- /* general send failure */
- return CURLE_SEND_ERROR;
+/*
+ * Curl_write() is an internal write function that sends data to the
+ * server. Works with plain sockets, SCP, SSL or kerberos.
+ *
+ * If the write would block (CURLE_AGAIN), we return CURLE_OK and
+ * (*written == 0). Otherwise we return regular CURLcode value.
+ */
+CURLcode Curl_write(struct Curl_easy *data,
+ curl_socket_t sockfd,
+ const void *mem,
+ size_t len,
+ ssize_t *written)
+{
+ struct connectdata *conn;
+ int num;
- default:
- /* we got a specific curlcode, forward it */
- return result;
- }
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+ conn = data->conn;
+ num = (sockfd != CURL_SOCKET_BAD && sockfd == conn->sock[SECONDARYSOCKET]);
+ return Curl_nwrite(data, num, mem, len, written);
}
static CURLcode pausewrite(struct Curl_easy *data,
@@ -421,4 +437,3 @@ CURLcode Curl_read(struct Curl_easy *data, /* transfer */
out:
return result;
}
-
diff --git a/libs/libcurl/src/sendf.h b/libs/libcurl/src/sendf.h
index bf4fa2293e..341c72f1c2 100644
--- a/libs/libcurl/src/sendf.h
+++ b/libs/libcurl/src/sendf.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
-#include "curl_log.h"
+#include "curl_trc.h"
#define CLIENTWRITE_BODY (1<<0)
@@ -51,4 +51,11 @@ CURLcode Curl_write(struct Curl_easy *data,
const void *mem, size_t len,
ssize_t *written);
+/* internal write-function, using sockindex for connection destination */
+CURLcode Curl_nwrite(struct Curl_easy *data,
+ int sockindex,
+ const void *buf,
+ size_t blen,
+ ssize_t *pnwritten);
+
#endif /* HEADER_CURL_SENDF_H */
diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c
index 029fb341ac..a91c8d3589 100644
--- a/libs/libcurl/src/setopt.c
+++ b/libs/libcurl/src/setopt.c
@@ -666,17 +666,20 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.method = HTTPREQ_GET;
break;
-#ifndef CURL_DISABLE_MIME
+#ifndef CURL_DISABLE_FORM_API
case CURLOPT_HTTPPOST:
/*
- * Set to make us do HTTP POST
+ * Set to make us do HTTP POST. Legacy API-style.
*/
data->set.httppost = va_arg(param, struct curl_httppost *);
data->set.method = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
+ Curl_mime_cleanpart(data->state.formp);
+ Curl_safefree(data->state.formp);
break;
#endif
+#if !defined(CURL_DISABLE_AWS)
case CURLOPT_AWS_SIGV4:
/*
* String that is merged to some authentication
@@ -690,6 +693,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
if(data->set.str[STRING_AWS_SIGV4])
data->set.httpauth = CURLAUTH_AWS_SIGV4;
break;
+#endif
case CURLOPT_REFERER:
/*
@@ -985,6 +989,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
if(!result) {
data->set.method = HTTPREQ_POST_MIME;
data->set.opt_no_body = FALSE; /* this is implied */
+#ifndef CURL_DISABLE_FORM_API
+ Curl_mime_cleanpart(data->state.formp);
+ Curl_safefree(data->state.formp);
+#endif
}
break;
@@ -1237,6 +1245,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.out = va_arg(param, void *);
break;
+#ifdef CURL_LIST_ONLY_PROTOCOL
case CURLOPT_DIRLISTONLY:
/*
* An option that changes the command to one that asks for a list only, no
@@ -1244,7 +1253,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
-
+#endif
case CURLOPT_APPEND:
/*
* We want to upload and append to an existing file. Used for FTP and
@@ -1885,6 +1894,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
result = Curl_setstropt(&data->set.str[STRING_DEVICE],
va_arg(param, char *));
break;
+#ifndef CURL_DISABLE_BINDLOCAL
case CURLOPT_LOCALPORT:
/*
* Set what local port to bind the socket to when performing an operation.
@@ -1903,6 +1913,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.localportrange = curlx_sltous(arg);
break;
+#endif
case CURLOPT_GSSAPI_DELEGATION:
/*
* GSS-API credential delegation bitmask
diff --git a/libs/libcurl/src/setup-os400.h b/libs/libcurl/src/setup-os400.h
index fbae57a44d..d3f98daaf5 100644
--- a/libs/libcurl/src/setup-os400.h
+++ b/libs/libcurl/src/setup-os400.h
@@ -34,6 +34,9 @@
/* No OS/400 header file defines u_int32_t. */
typedef unsigned long u_int32_t;
+/* OS/400 has no idea of a tty! */
+#define isatty(fd) 0
+
/* System API wrapper prototypes & definitions to support ASCII parameters. */
@@ -57,94 +60,6 @@ extern int Curl_getnameinfo_a(const struct sockaddr *sa,
int flags);
#define getnameinfo Curl_getnameinfo_a
-
-/* GSKit wrappers. */
-
-extern int Curl_gsk_environment_open(gsk_handle * my_env_handle);
-#define gsk_environment_open Curl_gsk_environment_open
-
-extern int Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
- gsk_handle * my_session_handle);
-#define gsk_secure_soc_open Curl_gsk_secure_soc_open
-
-extern int Curl_gsk_environment_close(gsk_handle * my_env_handle);
-#define gsk_environment_close Curl_gsk_environment_close
-
-extern int Curl_gsk_secure_soc_close(gsk_handle * my_session_handle);
-#define gsk_secure_soc_close Curl_gsk_secure_soc_close
-
-extern int Curl_gsk_environment_init(gsk_handle my_env_handle);
-#define gsk_environment_init Curl_gsk_environment_init
-
-extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle);
-#define gsk_secure_soc_init Curl_gsk_secure_soc_init
-
-extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle,
- GSK_BUF_ID bufID,
- const char *buffer,
- int bufSize);
-#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a
-
-extern int Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle,
- GSK_ENUM_ID enumID,
- GSK_ENUM_VALUE enumValue);
-#define gsk_attribute_set_enum Curl_gsk_attribute_set_enum
-
-extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
- GSK_NUM_ID numID,
- int numValue);
-#define gsk_attribute_set_numeric_value Curl_gsk_attribute_set_numeric_value
-
-extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
- GSK_CALLBACK_ID callBackID,
- void *callBackAreaPtr);
-#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback
-
-extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle,
- GSK_BUF_ID bufID,
- const char **buffer,
- int *bufSize);
-#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a
-
-extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle,
- GSK_ENUM_ID enumID,
- GSK_ENUM_VALUE *enumValue);
-#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum
-
-extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
- GSK_NUM_ID numID,
- int *numValue);
-#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value
-
-extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
- GSK_CERT_ID certID,
- const gsk_cert_data_elem **certDataElem,
- int *certDataElementCount);
-#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info
-
-extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
- GSK_MISC_ID miscID);
-#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc
-
-extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle,
- char *readBuffer,
- int readBufSize, int *amtRead);
-#define gsk_secure_soc_read Curl_gsk_secure_soc_read
-
-extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle,
- char *writeBuffer,
- int writeBufSize, int *amtWritten);
-#define gsk_secure_soc_write Curl_gsk_secure_soc_write
-
-extern const char * Curl_gsk_strerror_a(int gsk_return_value);
-#define gsk_strerror Curl_gsk_strerror_a
-
-extern int Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
- int IOCompletionPort,
- Qso_OverlappedIO_t * communicationsArea);
-#define gsk_secure_soc_startInit Curl_gsk_secure_soc_startInit
-
-
/* GSSAPI wrappers. */
extern OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status,
diff --git a/libs/libcurl/src/setup-vms.h b/libs/libcurl/src/setup-vms.h
index 139b638890..ea1cd42294 100644
--- a/libs/libcurl/src/setup-vms.h
+++ b/libs/libcurl/src/setup-vms.h
@@ -262,7 +262,6 @@ static struct passwd *vms_getpwuid(uid_t uid)
#define PKCS12_parse PKCS12_PARSE
#define RAND_add RAND_ADD
#define RAND_bytes RAND_BYTES
-#define RAND_egd RAND_EGD
#define RAND_file_name RAND_FILE_NAME
#define RAND_load_file RAND_LOAD_FILE
#define RAND_status RAND_STATUS
diff --git a/libs/libcurl/src/sha256.c b/libs/libcurl/src/sha256.c
index dc65e2f0fd..24b1a7a76b 100644
--- a/libs/libcurl/src/sha256.c
+++ b/libs/libcurl/src/sha256.c
@@ -25,7 +25,8 @@
#include "curl_setup.h"
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
+ || defined(USE_LIBSSH2)
#include "warnless.h"
#include "curl_sha256.h"
@@ -110,7 +111,10 @@ static CURLcode my_sha256_init(my_sha256_ctx *ctx)
if(!ctx->openssl_ctx)
return CURLE_OUT_OF_MEMORY;
- EVP_DigestInit_ex(ctx->openssl_ctx, EVP_sha256(), NULL);
+ if(!EVP_DigestInit_ex(ctx->openssl_ctx, EVP_sha256(), NULL)) {
+ EVP_MD_CTX_destroy(ctx->openssl_ctx);
+ return CURLE_FAILED_INIT;
+ }
return CURLE_OK;
}
@@ -218,9 +222,14 @@ typedef struct sha256_ctx my_sha256_ctx;
static CURLcode my_sha256_init(my_sha256_ctx *ctx)
{
- if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_AES,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
- CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash);
+ if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_AES,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ return CURLE_OUT_OF_MEMORY;
+
+ if(!CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash)) {
+ CryptReleaseContext(ctx->hCryptProv, 0);
+ ctx->hCryptProv = 0;
+ return CURLE_FAILED_INIT;
}
return CURLE_OK;
@@ -533,4 +542,4 @@ const struct HMAC_params Curl_HMAC_SHA256[] = {
};
-#endif /* CURL_DISABLE_CRYPTO_AUTH */
+#endif /* AWS, DIGEST, or libSSH2 */
diff --git a/libs/libcurl/src/smb.c b/libs/libcurl/src/smb.c
index c1e3f9d593..75fa4614d4 100644
--- a/libs/libcurl/src/smb.c
+++ b/libs/libcurl/src/smb.c
@@ -564,12 +564,11 @@ static CURLcode smb_send(struct Curl_easy *data, ssize_t len,
size_t upload_size)
{
struct connectdata *conn = data->conn;
- curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
struct smb_conn *smbc = &conn->proto.smbc;
ssize_t bytes_written;
CURLcode result;
- result = Curl_write(data, sockfd, data->state.ulbuf,
+ result = Curl_nwrite(data, FIRSTSOCKET, data->state.ulbuf,
len, &bytes_written);
if(result)
return result;
@@ -587,7 +586,6 @@ static CURLcode smb_send(struct Curl_easy *data, ssize_t len,
static CURLcode smb_flush(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
- curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
struct smb_conn *smbc = &conn->proto.smbc;
ssize_t bytes_written;
ssize_t len = smbc->send_size - smbc->sent;
@@ -596,9 +594,9 @@ static CURLcode smb_flush(struct Curl_easy *data)
if(!smbc->send_size)
return CURLE_OK;
- result = Curl_write(data, sockfd,
- data->state.ulbuf + smbc->sent,
- len, &bytes_written);
+ result = Curl_nwrite(data, FIRSTSOCKET,
+ data->state.ulbuf + smbc->sent,
+ len, &bytes_written);
if(result)
return result;
diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c
index 5109c90b93..10a4b9c038 100644
--- a/libs/libcurl/src/smtp.c
+++ b/libs/libcurl/src/smtp.c
@@ -49,9 +49,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_UTSNAME_H
-#include <sys/utsname.h>
-#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c
index f85761bb76..2d64a277eb 100644
--- a/libs/libcurl/src/strerror.c
+++ b/libs/libcurl/src/strerror.c
@@ -938,7 +938,7 @@ const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(!get_winapi_error(err, buf, buflen)) {
- msnprintf(buf, buflen, "Unknown error %u (0x%08X)", err, err);
+ msnprintf(buf, buflen, "Unknown error %lu (0x%08lX)", err, err);
}
#else
{
diff --git a/libs/libcurl/src/system_win32.h b/libs/libcurl/src/system_win32.h
index 21b76efd0f..33169a129d 100644
--- a/libs/libcurl/src/system_win32.h
+++ b/libs/libcurl/src/system_win32.h
@@ -42,7 +42,8 @@ extern IF_NAMETOINDEX_FN Curl_if_nametoindex;
/* This is used to dynamically load DLLs */
HMODULE Curl_load_library(LPCTSTR filename);
-
-#endif /* WIN32 */
+#else /* WIN32 */
+#define Curl_win32_init(x) CURLE_OK
+#endif /* !WIN32 */
#endif /* HEADER_CURL_SYSTEM_WIN32_H */
diff --git a/libs/libcurl/src/telnet.c b/libs/libcurl/src/telnet.c
index e0d54b6c7a..1166f79459 100644
--- a/libs/libcurl/src/telnet.c
+++ b/libs/libcurl/src/telnet.c
@@ -1266,10 +1266,10 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
break;
default: /* write! */
bytes_written = 0;
- result = Curl_write(data, conn->sock[FIRSTSOCKET],
- outbuf + total_written,
- outlen - total_written,
- &bytes_written);
+ result = Curl_nwrite(data, FIRSTSOCKET,
+ outbuf + total_written,
+ outlen - total_written,
+ &bytes_written);
total_written += bytes_written;
break;
}
diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c
index 4d466c145e..8fe343e0bd 100644
--- a/libs/libcurl/src/transfer.c
+++ b/libs/libcurl/src/transfer.c
@@ -431,6 +431,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
curl_off_t max_recv = data->set.max_recv_speed?
data->set.max_recv_speed : CURL_OFF_T_MAX;
char *buf = data->state.buffer;
+ bool data_eof_handled = FALSE;
DEBUGASSERT(buf);
*done = FALSE;
@@ -448,8 +449,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
to ensure that http2_handle_stream_close is called when we read all
incoming bytes for a particular stream. */
bool is_http3 = Curl_conn_is_http3(data, conn, FIRSTSOCKET);
- bool data_eof_handled = is_http3
- || Curl_conn_is_http2(data, conn, FIRSTSOCKET);
+ data_eof_handled = is_http3 || Curl_conn_is_http2(data, conn, FIRSTSOCKET);
if(!data_eof_handled && k->size != -1 && !k->header) {
/* make sure we don't read too much */
@@ -492,15 +492,16 @@ static CURLcode readwrite_data(struct Curl_easy *data,
if(0 < nread || is_empty_data) {
buf[nread] = 0;
}
- else {
+ if(!nread) {
/* if we receive 0 or less here, either the data transfer is done or the
server closed the connection and we bail out from this! */
if(data_eof_handled)
DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
else
DEBUGF(infof(data, "nread <= 0, server closed connection, bailing"));
- k->keepon &= ~KEEP_RECV;
- break;
+ k->keepon = 0; /* stop sending as well */
+ if(!is_empty_data)
+ break;
}
/* Default buffer to use when we write the buffer, it may be changed
@@ -761,7 +762,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
}
if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
- conn->bits.close) {
+ (conn->bits.close || data_eof_handled)) {
/* When we've read the entire thing and the close bit is set, the server
may now close the connection. If there's now any kind of sending going
on from our side, we need to stop that immediately. */
@@ -824,9 +825,6 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
bool sending_http_headers = FALSE;
struct SingleRequest *k = &data->req;
- if((k->bytecount == 0) && (k->writebytecount == 0))
- Curl_pgrsTime(data, TIMER_STARTTRANSFER);
-
*didwhat |= KEEP_SEND;
do {
@@ -1335,7 +1333,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
}
data->state.prefer_ascii = data->set.prefer_ascii;
+#ifdef CURL_LIST_ONLY_PROTOCOL
data->state.list_only = data->set.list_only;
+#endif
data->state.httpreq = data->set.method;
data->state.url = data->set.str[STRING_SET_URL];
@@ -1397,7 +1397,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
Curl_pgrsResetTransferSizes(data);
Curl_pgrsStartNow(data);
- /* In case the handle is re-used and an authentication method was picked
+ /* In case the handle is reused and an authentication method was picked
in the session we need to make sure we only use the one(s) we now
consider to be fine */
data->state.authhost.picked &= data->state.authhost.want;
@@ -1787,7 +1787,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
&& (data->set.rtspreq != RTSPREQ_RECEIVE)
#endif
)
- /* We got no data, we attempted to re-use a connection. For HTTP this
+ /* We got no data, we attempted to reuse a connection. For HTTP this
can be a retry so we try again regardless if we expected a body.
For other protocols we only try again only if we expected a body.
diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c
index 79a2ad1d8e..5951e6a066 100644
--- a/libs/libcurl/src/url.c
+++ b/libs/libcurl/src/url.c
@@ -414,7 +414,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_hsts_cleanup(&data->hsts);
curl_slist_free_all(data->set.hstslist); /* clean up list */
#endif
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
Curl_http_auth_cleanup_digest(data);
#endif
Curl_safefree(data->info.contenttype);
@@ -457,6 +457,11 @@ CURLcode Curl_close(struct Curl_easy **datap)
}
#endif
+ Curl_mime_cleanpart(data->state.formp);
+#ifndef CURL_DISABLE_HTTP
+ Curl_safefree(data->state.formp);
+#endif
+
/* destruct wildcard structures if it is needed */
Curl_wildcard_dtor(&data->wildcard);
Curl_freeset(data);
@@ -490,7 +495,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->filesize = -1; /* we don't know the size */
set->postfieldsize = -1; /* unknown size */
- set->maxredirs = -1; /* allow any amount by default */
+ set->maxredirs = 30; /* sensible default */
set->method = HTTPREQ_GET; /* Default HTTP request */
#ifndef CURL_DISABLE_RTSP
@@ -948,7 +953,7 @@ static bool extract_if_dead(struct connectdata *conn,
* that we expect - in general - no waiting input data. Input
* waiting might be a TLS Notify Close, for example. We reject
* that.
- * For protocols where data from other other end may arrive at
+ * For protocols where data from other end may arrive at
* any time (HTTP/2 PING for example), the protocol handler needs
* to install its own `connection_check` callback.
*/
@@ -1073,6 +1078,9 @@ ConnectionExists(struct Curl_easy *data,
bool wantProxyNTLMhttp = FALSE;
#endif
#endif
+ /* plain HTTP with upgrade */
+ bool h2upgrade = (data->state.httpwant == CURL_HTTP_VERSION_2_0) &&
+ (needle->handler->protocol & CURLPROTO_HTTP);
*force_reuse = FALSE;
*waitpipe = FALSE;
@@ -1095,7 +1103,7 @@ ConnectionExists(struct Curl_easy *data,
infof(data, "Server doesn't support multiplex yet, wait");
*waitpipe = TRUE;
CONNCACHE_UNLOCK(data);
- return FALSE; /* no re-use */
+ return FALSE; /* no reuse */
}
infof(data, "Server doesn't support multiplex (yet)");
@@ -1135,7 +1143,7 @@ ConnectionExists(struct Curl_easy *data,
}
if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
- && data->set.ipver != check->ip_version) {
+ && data->set.ipver != check->ip_version) {
/* skip because the connection is not via the requested IP version */
continue;
}
@@ -1150,16 +1158,11 @@ ConnectionExists(struct Curl_easy *data,
continue;
}
- if(Curl_resolver_asynch()) {
- /* primary_ip[0] is NUL only if the resolving of the name hasn't
- completed yet and until then we don't re-use this connection */
- if(!check->primary_ip[0]) {
- infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T " is still "
- "name resolving, can't reuse",
- check->connection_id);
- continue;
- }
- }
+ if(Curl_resolver_asynch() &&
+ /* primary_ip[0] is NUL only if the resolving of the name hasn't
+ completed yet and until then we don't reuse this connection */
+ !check->primary_ip[0])
+ continue;
}
if(!Curl_conn_is_connected(check, FIRSTSOCKET)) {
@@ -1238,6 +1241,17 @@ ConnectionExists(struct Curl_easy *data,
}
#endif
+ if(h2upgrade && !check->httpversion && canmultiplex) {
+ if(data->set.pipewait) {
+ infof(data, "Server upgrade doesn't support multiplex yet, wait");
+ *waitpipe = TRUE;
+ CONNCACHE_UNLOCK(data);
+ return FALSE; /* no reuse */
+ }
+ infof(data, "Server upgrade cannot be used");
+ continue; /* can't be used atm */
+ }
+
if(!canmultiplex && CONN_INUSE(check))
/* this request can't be multiplexed but the checked connection is
already in use so we skip it */
@@ -1254,14 +1268,14 @@ ConnectionExists(struct Curl_easy *data,
if(needle->localdev || needle->localport) {
/* If we are bound to a specific local end (IP+port), we must not
- re-use a random other one, although if we didn't ask for a
+ reuse a random other one, although if we didn't ask for a
particular one we can reuse one that was bound.
This comparison is a bit rough and too strict. Since the input
parameters can be specified in numerous ways and still end up the
same it would take a lot of processing to make it really accurate.
- Instead, this matching will assume that re-uses of bound connections
- will most likely also re-use the exact same binding parameters and
+ Instead, this matching will assume that reuses of bound connections
+ will most likely also reuse the exact same binding parameters and
missing out a few edge cases shouldn't hurt anyone very much.
*/
if((check->localport != needle->localport) ||
@@ -1294,7 +1308,7 @@ ConnectionExists(struct Curl_easy *data,
(((check->httpversion >= 20) &&
(data->state.httpwant < CURL_HTTP_VERSION_2_0))
|| ((check->httpversion >= 30) &&
- (data->state.httpwant < CURL_HTTP_VERSION_3))))
+ (data->state.httpwant < CURL_HTTP_VERSION_3))))
continue;
#ifdef USE_SSH
else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
@@ -1485,13 +1499,7 @@ void Curl_verboseconnect(struct Curl_easy *data,
{
if(data->set.verbose)
infof(data, "Connected to %s (%s) port %u",
-#ifndef CURL_DISABLE_PROXY
- conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
- conn->bits.httpproxy ? conn->http_proxy.host.dispname :
-#endif
- conn->bits.conn_to_host ? conn->conn_to_host.dispname :
- conn->host.dispname,
- conn->primary_ip, conn->port);
+ CURL_CONN_HOST_DISPNAME(conn), conn->primary_ip, conn->port);
}
#endif
@@ -1587,8 +1595,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
if(!conn->localdev)
goto error;
}
+#ifndef CURL_DISABLE_BINDLOCAL
conn->localportrange = data->set.localportrange;
conn->localport = data->set.localport;
+#endif
/* the close socket stuff needs to be copied to the connection struct as
it may live on without (this specific) Curl_easy */
@@ -2120,7 +2130,7 @@ static char *detect_proxy(struct Curl_easy *data,
/*
* If this is supposed to use a proxy, we need to figure out the proxy
- * host name, so that we can re-use an existing connection
+ * host name, so that we can reuse an existing connection
* that may exist registered to the same proxy host.
*/
static CURLcode parse_proxy(struct Curl_easy *data,
@@ -2441,7 +2451,7 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
/***********************************************************************
* If this is supposed to use a proxy, we need to figure out the proxy host
- * name, proxy type and port number, so that we can re-use an existing
+ * name, proxy type and port number, so that we can reuse an existing
* connection that may exist registered to the same proxy host.
***********************************************************************/
if(proxy || socksproxy) {
@@ -3259,7 +3269,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
/* Resolve the name of the server or proxy */
if(conn->bits.reuse) {
/* We're reusing the connection - no need to resolve anything, and
- idnconvert_hostname() was called already in create_conn() for the re-use
+ idnconvert_hostname() was called already in create_conn() for the reuse
case. */
*async = FALSE;
return CURLE_OK;
@@ -3278,7 +3288,7 @@ static void reuse_conn(struct Curl_easy *data,
struct connectdata *existing)
{
/* get the user+password information from the temp struct since it may
- * be new for this request even when we re-use an existing connection */
+ * be new for this request even when we reuse an existing connection */
if(temp->user) {
/* use the new user name and password though */
Curl_safefree(existing->user);
@@ -3338,14 +3348,14 @@ static void reuse_conn(struct Curl_easy *data,
existing->hostname_resolve = temp->hostname_resolve;
temp->hostname_resolve = NULL;
- /* re-use init */
- existing->bits.reuse = TRUE; /* yes, we're re-using here */
+ /* reuse init */
+ existing->bits.reuse = TRUE; /* yes, we're reusing here */
conn_free(data, temp);
}
/**
- * create_conn() sets up a new connectdata struct, or re-uses an already
+ * create_conn() sets up a new connectdata struct, or reuses an already
* existing one, and resolves host name.
*
* if this function returns CURLE_OK and *async is set to TRUE, the resolve
@@ -3657,7 +3667,7 @@ static CURLcode create_conn(struct Curl_easy *data,
/*************************************************************
* Check the current list of connections to see if we can
- * re-use an already existing one or if we have to create a
+ * reuse an already existing one or if we have to create a
* new one.
*************************************************************/
@@ -3665,7 +3675,7 @@ static CURLcode create_conn(struct Curl_easy *data,
DEBUGASSERT(conn->passwd);
/* reuse_fresh is TRUE if we are told to use a new connection by force, but
- we only acknowledge this option if this is not a re-used connection
+ we only acknowledge this option if this is not a reused connection
already (which happens due to follow-location or during an HTTP
authentication phase). CONNECT_ONLY transfers also refuse reuse. */
if((data->set.reuse_fresh && !data->state.followlocation) ||
diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c
index 1125f4a90c..2e4138306f 100644
--- a/libs/libcurl/src/urlapi.c
+++ b/libs/libcurl/src/urlapi.c
@@ -1109,6 +1109,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) {
/* This cannot be done with strcpy, as the memory chunks overlap! */
path++;
+ pathlen--;
}
#endif
@@ -1384,6 +1385,7 @@ CURLU *curl_url_dup(const CURLU *in)
DUP(u, in, path);
DUP(u, in, query);
DUP(u, in, fragment);
+ DUP(u, in, zoneid);
u->portnum = in->portnum;
}
return u;
@@ -1401,6 +1403,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
bool urldecode = (flags & CURLU_URLDECODE)?1:0;
bool urlencode = (flags & CURLU_URLENCODE)?1:0;
bool punycode = FALSE;
+ bool depunyfy = FALSE;
bool plusdecode = FALSE;
(void)flags;
if(!u)
@@ -1431,6 +1434,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
ptr = u->host;
ifmissing = CURLUE_NO_HOST;
punycode = (flags & CURLU_PUNYCODE)?1:0;
+ depunyfy = (flags & CURLU_PUNY2IDN)?1:0;
break;
case CURLUPART_ZONEID:
ptr = u->zoneid;
@@ -1481,6 +1485,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
char *port = u->port;
char *allochost = NULL;
punycode = (flags & CURLU_PUNYCODE)?1:0;
+ depunyfy = (flags & CURLU_PUNY2IDN)?1:0;
if(u->scheme && strcasecompare("file", u->scheme)) {
url = aprintf("file://%s%s%s",
u->path,
@@ -1540,9 +1545,23 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
#ifndef USE_IDN
return CURLUE_LACKS_IDN;
#else
- allochost = Curl_idn_decode(u->host);
- if(!allochost)
- return CURLUE_OUT_OF_MEMORY;
+ CURLcode result = Curl_idn_decode(u->host, &allochost);
+ if(result)
+ return (result == CURLE_OUT_OF_MEMORY) ?
+ CURLUE_OUT_OF_MEMORY : CURLUE_BAD_HOSTNAME;
+#endif
+ }
+ }
+ else if(depunyfy) {
+ if(Curl_is_ASCII_name(u->host) && !strncmp("xn--", u->host, 4)) {
+#ifndef USE_IDN
+ return CURLUE_LACKS_IDN;
+#else
+ CURLcode result = Curl_idn_encode(u->host, &allochost);
+ if(result)
+ /* this is the most likely error */
+ return (result == CURLE_OUT_OF_MEMORY) ?
+ CURLUE_OUT_OF_MEMORY : CURLUE_BAD_HOSTNAME;
#endif
}
}
@@ -1616,9 +1635,26 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
#ifndef USE_IDN
return CURLUE_LACKS_IDN;
#else
- char *allochost = Curl_idn_decode(*part);
- if(!allochost)
- return CURLUE_OUT_OF_MEMORY;
+ char *allochost;
+ CURLcode result = Curl_idn_decode(*part, &allochost);
+ if(result)
+ return (result == CURLE_OUT_OF_MEMORY) ?
+ CURLUE_OUT_OF_MEMORY : CURLUE_BAD_HOSTNAME;
+ free(*part);
+ *part = allochost;
+#endif
+ }
+ }
+ else if(depunyfy) {
+ if(Curl_is_ASCII_name(u->host) && !strncmp("xn--", u->host, 4)) {
+#ifndef USE_IDN
+ return CURLUE_LACKS_IDN;
+#else
+ char *allochost;
+ CURLcode result = Curl_idn_encode(*part, &allochost);
+ if(result)
+ return (result == CURLE_OUT_OF_MEMORY) ?
+ CURLUE_OUT_OF_MEMORY : CURLUE_BAD_HOSTNAME;
free(*part);
*part = allochost;
#endif
@@ -1780,6 +1816,10 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
char *oldurl;
char *redired_url;
+ if(!nalloc)
+ /* a blank URL is not a valid URL */
+ return CURLUE_MALFORMED_INPUT;
+
/* if the new thing is absolute or the old one is not
* (we could not get an absolute url in 'oldurl'),
* then replace the existing with the new. */
diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h
index 81b67bb889..76f621f3e6 100644
--- a/libs/libcurl/src/urldata.h
+++ b/libs/libcurl/src/urldata.h
@@ -101,6 +101,12 @@ typedef unsigned int curl_prot_t;
#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS)
#define PROTO_FAMILY_SSH (CURLPROTO_SCP|CURLPROTO_SFTP)
+#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) || \
+ !defined(CURL_DISABLE_POP3)
+/* these protocols support CURLOPT_DIRLISTONLY */
+#define CURL_LIST_ONLY_PROTOCOL 1
+#endif
+
#define DEFAULT_CONNCACHE_SIZE 5
/* length of longest IPv6 address string including the trailing null */
@@ -330,6 +336,7 @@ struct Curl_ssl_session {
#include "curl_sspi.h"
#endif
+#ifndef CURL_DISABLE_DIGEST_AUTH
/* Struct used for Digest challenge-response authentication */
struct digestdata {
#if defined(USE_WINDOWS_SSPI)
@@ -353,6 +360,7 @@ struct digestdata {
BIT(userhash);
#endif
};
+#endif
typedef enum {
NTLMSTATE_NONE,
@@ -489,7 +497,7 @@ struct ConnectBits {
#endif
/* always modify bits.close with the connclose() and connkeep() macros! */
BIT(close); /* if set, we close the connection after this request */
- BIT(reuse); /* if set, this is a re-used connection */
+ BIT(reuse); /* if set, this is a reused connection */
BIT(altused); /* this is an alt-svc "redirect" */
BIT(conn_to_host); /* if set, this connection has a "connect to host"
that overrides the host in the URL */
@@ -629,17 +637,16 @@ struct SingleRequest {
curl_off_t bytecount; /* total number of bytes read */
curl_off_t writebytecount; /* number of bytes written */
- curl_off_t headerbytecount; /* only count received headers */
- curl_off_t deductheadercount; /* this amount of bytes doesn't count when we
- check if anything has been transferred at
- the end of a connection. We use this
- counter to make only a 100 reply (without a
- following second response code) result in a
- CURLE_GOT_NOTHING error code */
-
curl_off_t pendingheader; /* this many bytes left to send is actually
header and not body */
struct curltime start; /* transfer started at this time */
+ unsigned int headerbytecount; /* only count received headers */
+ unsigned int deductheadercount; /* this amount of bytes doesn't count when
+ we check if anything has been transferred
+ at the end of a connection. We use this
+ counter to make only a 100 reply (without
+ a following second response code) result
+ in a CURLE_GOT_NOTHING error code */
enum {
HEADER_NORMAL, /* no bad header at all */
HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest
@@ -701,7 +708,9 @@ struct SingleRequest {
struct curltime last_sndbuf_update; /* last time readwrite_upload called
win_update_buffer_size */
#endif
+#ifndef CURL_DISABLE_COOKIES
unsigned char setcookies;
+#endif
unsigned char writer_stack_depth; /* Unencoding stack depth. */
BIT(header); /* incoming data has HTTP header */
BIT(content_range); /* set TRUE if Content-Range: was found */
@@ -747,7 +756,7 @@ struct Curl_handler {
* after the connect() and everything is done, as a step in the connection.
* The 'done' pointer points to a bool that should be set to TRUE if the
* function completes before return. If it doesn't complete, the caller
- * should call the curl_connecting() function until it is.
+ * should call the ->connecting() function until it is.
*/
CURLcode (*connect_it)(struct Curl_easy *data, bool *done);
@@ -887,7 +896,7 @@ struct connectdata {
/* 'dns_entry' is the particular host we use. This points to an entry in the
DNS cache and it will not get pruned while locked. It gets unlocked in
- multi_done(). This entry will be NULL if the connection is re-used as then
+ multi_done(). This entry will be NULL if the connection is reused as then
there is no name resolve done. */
struct Curl_dns_entry *dns_entry;
@@ -1024,14 +1033,19 @@ struct connectdata {
#ifndef CURL_DISABLE_SMB
struct smb_conn smbc;
#endif
+#ifdef USE_LIBRTMP
void *rtmp;
+#endif
+#ifdef USE_OPENLDAP
struct ldapconninfo *ldapc;
+#endif
#ifndef CURL_DISABLE_MQTT
struct mqtt_conn mqtt;
#endif
#ifdef USE_WEBSOCKETS
struct websocket *ws;
#endif
+ unsigned int unused:1; /* avoids empty union */
} proto;
struct connectbundle *bundle; /* The bundle we are member of */
@@ -1045,7 +1059,7 @@ struct connectdata {
/* When this connection is created, store the conditions for the local end
bind. This is stored before the actual bind and before any connection is
made and will serve the purpose of being used for comparison reasons so
- that subsequent bound-requested connections aren't accidentally re-using
+ that subsequent bound-requested connections aren't accidentally reusing
wrong connections. */
char *localdev;
unsigned short localportrange;
@@ -1077,6 +1091,18 @@ struct connectdata {
unsigned char gssapi_delegation; /* inherited from set.gssapi_delegation */
};
+#ifndef CURL_DISABLE_PROXY
+#define CURL_CONN_HOST_DISPNAME(c) \
+ ((c)->bits.socksproxy ? (c)->socks_proxy.host.dispname : \
+ (c)->bits.httpproxy ? (c)->http_proxy.host.dispname : \
+ (c)->bits.conn_to_host ? (c)->conn_to_host.dispname : \
+ (c)->host.dispname)
+#else
+#define CURL_CONN_HOST_DISPNAME(c) \
+ (c)->bits.conn_to_host ? (c)->conn_to_host.dispname : \
+ (c)->host.dispname
+#endif
+
/* The end of connectdata. */
/*
@@ -1089,7 +1115,6 @@ struct PureInfo {
int httpversion; /* the http version number X.Y = X*10+Y */
time_t filetime; /* If requested, this is might get set. Set to -1 if the
time was unretrievable. */
- curl_off_t header_size; /* size of read header(s) in bytes */
curl_off_t request_size; /* the amount of bytes sent in the request(s) */
unsigned long proxyauthavail; /* what proxy auth types were announced */
unsigned long httpauthavail; /* what host auth types were announced */
@@ -1097,6 +1122,7 @@ struct PureInfo {
char *contenttype; /* the content type of the object */
char *wouldredirect; /* URL this would've been redirected to if asked to */
curl_off_t retry_after; /* info from Retry-After: header */
+ unsigned int header_size; /* size of read header(s) in bytes */
/* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip'
and, 'conn_local_port' are copied over from the connectdata struct in
@@ -1116,10 +1142,8 @@ struct PureInfo {
int conn_local_port;
const char *conn_scheme;
unsigned int conn_protocol;
- struct curl_certinfo certs; /* info about the certs, only populated in
- OpenSSL, GnuTLS, Schannel, NSS and GSKit
- builds. Asked for with CURLOPT_CERTINFO
- / CURLINFO_CERTINFO */
+ struct curl_certinfo certs; /* info about the certs. Asked for with
+ CURLOPT_CERTINFO / CURLINFO_CERTINFO */
CURLproxycode pxcode;
BIT(timecond); /* set to TRUE if the time condition didn't match, which
thus made the document NOT get fetched */
@@ -1325,7 +1349,7 @@ struct UrlState {
/* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
void (*prev_signal)(int sig);
#endif
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifndef CURL_DISABLE_DIGEST_AUTH
struct digestdata digest; /* state data for host Digest auth */
struct digestdata proxydigest; /* state data for proxy Digest auth */
#endif
@@ -1383,6 +1407,9 @@ struct UrlState {
struct curl_slist *resolve; /* set to point to the set.resolve list when
this should be dealt with in pretransfer */
#ifndef CURL_DISABLE_HTTP
+ curl_mimepart *mimepost;
+ curl_mimepart *formp; /* storage for old API form-posting, alloced on
+ demand */
size_t trailers_bytes_sent;
struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
headers */
@@ -1454,9 +1481,13 @@ struct UrlState {
when multi_done() is called, to prevent multi_done() to get
invoked twice when the multi interface is used. */
BIT(previouslypending); /* this transfer WAS in the multi->pending queue */
+#ifndef CURL_DISABLE_COOKIES
BIT(cookie_engine);
+#endif
BIT(prefer_ascii); /* ASCII rather than binary */
+#ifdef CURL_LIST_ONLY_PROTOCOL
BIT(list_only); /* list directory contents */
+#endif
BIT(url_alloc); /* URL string is malloc()'ed */
BIT(referer_alloc); /* referer string is malloc()ed */
BIT(wildcard_resolve); /* Set to true if any resolve change is a wildcard */
@@ -1613,10 +1644,12 @@ struct UserDefined {
curl_off_t postfieldsize; /* if POST, this might have a size to use instead
of strlen(), and then the data *may* be binary
(contain zero bytes) */
+#ifndef CURL_DISABLE_BINDLOCAL
unsigned short localport; /* local port number to bind to */
unsigned short localportrange; /* number of additional port numbers to test
in case the 'localport' one can't be
bind()ed */
+#endif
curl_write_callback fwrite_func; /* function that stores the output */
curl_write_callback fwrite_header; /* function that stores headers */
curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */
@@ -1804,7 +1837,9 @@ struct UserDefined {
BIT(tftp_no_options); /* do not send TFTP options requests */
#endif
BIT(sep_headers); /* handle host and proxy headers separately */
+#ifndef CURL_DISABLE_COOKIES
BIT(cookiesession); /* new cookie session? */
+#endif
BIT(crlf); /* convert crlf on ftp upload(?) */
BIT(ssh_compression); /* enable SSH compression */
@@ -1819,7 +1854,9 @@ struct UserDefined {
BIT(tunnel_thru_httpproxy); /* use CONNECT through an HTTP proxy */
BIT(prefer_ascii); /* ASCII rather than binary */
BIT(remote_append); /* append, not overwrite, on upload */
+#ifdef CURL_LIST_ONLY_PROTOCOL
BIT(list_only); /* list directory */
+#endif
#ifndef CURL_DISABLE_FTP
BIT(ftp_use_port); /* use the FTP PORT command */
BIT(ftp_use_epsv); /* if EPSV is to be attempted or not */
@@ -1843,7 +1880,7 @@ struct UserDefined {
BIT(verbose); /* output verbosity */
BIT(krb); /* Kerberos connection requested */
BIT(reuse_forbid); /* forbidden to be reused, close after use */
- BIT(reuse_fresh); /* do not re-use an existing connection */
+ BIT(reuse_fresh); /* do not reuse an existing connection */
BIT(no_signal); /* do not use any signal/alarm handler */
BIT(tcp_nodelay); /* whether to enable TCP_NODELAY or not */
BIT(ignorecl); /* ignore content length */
diff --git a/libs/libcurl/src/vauth/cram.c b/libs/libcurl/src/vauth/cram.c
index 0ae4b882e1..c753cc3b51 100644
--- a/libs/libcurl/src/vauth/cram.c
+++ b/libs/libcurl/src/vauth/cram.c
@@ -26,7 +26,7 @@
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+#ifndef CURL_DISABLE_DIGEST_AUTH
#include <curl/curl.h>
#include "urldata.h"
@@ -94,4 +94,4 @@ CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg,
return CURLE_OK;
}
-#endif /* !CURL_DISABLE_CRYPTO_AUTH */
+#endif /* !CURL_DISABLE_DIGEST_AUTH */
diff --git a/libs/libcurl/src/vauth/digest.c b/libs/libcurl/src/vauth/digest.c
index 770bac7682..e73302ff6a 100644
--- a/libs/libcurl/src/vauth/digest.c
+++ b/libs/libcurl/src/vauth/digest.c
@@ -27,7 +27,7 @@
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+#ifndef CURL_DISABLE_DIGEST_AUTH
#include <curl/curl.h>
@@ -420,7 +420,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
msnprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
/* Generate our SPN */
- spn = Curl_auth_build_spn(service, realm, NULL);
+ spn = Curl_auth_build_spn(service, data->conn->host.name, NULL);
if(!spn)
return CURLE_OUT_OF_MEMORY;
@@ -992,4 +992,4 @@ void Curl_auth_digest_cleanup(struct digestdata *digest)
}
#endif /* !USE_WINDOWS_SSPI */
-#endif /* CURL_DISABLE_CRYPTO_AUTH */
+#endif /* !CURL_DISABLE_DIGEST_AUTH */
diff --git a/libs/libcurl/src/vauth/digest.h b/libs/libcurl/src/vauth/digest.h
index 17fea3fb4d..edbd0f99e2 100644
--- a/libs/libcurl/src/vauth/digest.h
+++ b/libs/libcurl/src/vauth/digest.h
@@ -26,7 +26,7 @@
#include <curl/curl.h>
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+#ifndef CURL_DISABLE_DIGEST_AUTH
#define DIGEST_MAX_VALUE_LENGTH 256
#define DIGEST_MAX_CONTENT_LENGTH 1024
diff --git a/libs/libcurl/src/vauth/digest_sspi.c b/libs/libcurl/src/vauth/digest_sspi.c
index 17832b0a59..996b83d50e 100644
--- a/libs/libcurl/src/vauth/digest_sspi.c
+++ b/libs/libcurl/src/vauth/digest_sspi.c
@@ -27,7 +27,7 @@
#include "curl_setup.h"
-#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_DIGEST_AUTH)
#include <curl/curl.h>
@@ -665,4 +665,4 @@ void Curl_auth_digest_cleanup(struct digestdata *digest)
Curl_safefree(digest->passwd);
}
-#endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_CRYPTO_AUTH */
+#endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_DIGEST_AUTH */
diff --git a/libs/libcurl/src/vauth/ntlm.c b/libs/libcurl/src/vauth/ntlm.c
index d59d2df0ff..0cdf1a159f 100644
--- a/libs/libcurl/src/vauth/ntlm.c
+++ b/libs/libcurl/src/vauth/ntlm.c
@@ -45,12 +45,6 @@
#include "rand.h"
#include "vtls/vtls.h"
-/* SSL backend-specific #if branches in this file must be kept in the order
- documented in curl_ntlm_core. */
-#if defined(NTLM_NEEDS_NSS_INIT)
-#include "vtls/nssg.h" /* for Curl_nss_force_init() */
-#endif
-
#define BUILDING_CURL_NTLM_MSGS_C
#include "vauth/vauth.h"
#include "vauth/ntlm.h"
@@ -274,12 +268,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
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 */
- result = Curl_nss_force_init(data);
- if(result)
- return result;
-#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
(void)data;
#endif
diff --git a/libs/libcurl/src/vauth/vauth.h b/libs/libcurl/src/vauth/vauth.h
index 56a62574e5..5d5c2f4c9c 100644
--- a/libs/libcurl/src/vauth/vauth.h
+++ b/libs/libcurl/src/vauth/vauth.h
@@ -30,7 +30,7 @@
struct Curl_easy;
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if !defined(CURL_DISABLE_DIGEST_AUTH)
struct digestdata;
#endif
@@ -86,7 +86,7 @@ CURLcode Curl_auth_create_login_message(const char *value,
CURLcode Curl_auth_create_external_message(const char *user,
struct bufref *out);
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+#ifndef CURL_DISABLE_DIGEST_AUTH
/* This is used to generate a CRAM-MD5 response message */
CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg,
const char *userp,
@@ -119,7 +119,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
/* This is used to clean up the digest specific data */
void Curl_auth_digest_cleanup(struct digestdata *digest);
-#endif /* !CURL_DISABLE_CRYPTO_AUTH */
+#endif /* !CURL_DISABLE_DIGEST_AUTH */
#ifdef USE_GSASL
/* This is used to evaluate if MECH is supported by gsasl */
diff --git a/libs/libcurl/src/vquic/curl_msh3.c b/libs/libcurl/src/vquic/curl_msh3.c
index 9e145bfe16..5d31e234d8 100644
--- a/libs/libcurl/src/vquic/curl_msh3.c
+++ b/libs/libcurl/src/vquic/curl_msh3.c
@@ -30,7 +30,7 @@
#include "timeval.h"
#include "multiif.h"
#include "sendf.h"
-#include "curl_log.h"
+#include "curl_trc.h"
#include "cfilters.h"
#include "cf-socket.h"
#include "connect.h"
@@ -173,7 +173,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
msh3_lock_initialize(&stream->recv_lock);
Curl_bufq_init2(&stream->recvbuf, H3_STREAM_CHUNK_SIZE,
H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
- DEBUGF(LOG_CF(data, cf, "data setup"));
+ CURL_TRC_CF(data, cf, "data setup");
return CURLE_OK;
}
@@ -183,7 +183,7 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
(void)cf;
if(stream) {
- DEBUGF(LOG_CF(data, cf, "easy handle is done"));
+ CURL_TRC_CF(data, cf, "easy handle is done");
Curl_bufq_free(&stream->recvbuf);
free(stream);
H3_STREAM_LCTX(data) = NULL;
@@ -235,7 +235,7 @@ static void MSH3_CALL msh3_conn_connected(MSH3_CONNECTION *Connection,
struct Curl_easy *data = CF_DATA_CURRENT(cf);
(void)Connection;
- DEBUGF(LOG_CF(data, cf, "[MSH3] connected"));
+ CURL_TRC_CF(data, cf, "[MSH3] connected");
ctx->handshake_succeeded = true;
ctx->connected = true;
ctx->handshake_complete = true;
@@ -249,7 +249,7 @@ static void MSH3_CALL msh3_conn_shutdown_complete(MSH3_CONNECTION *Connection,
struct Curl_easy *data = CF_DATA_CURRENT(cf);
(void)Connection;
- DEBUGF(LOG_CF(data, cf, "[MSH3] shutdown complete"));
+ CURL_TRC_CF(data, cf, "[MSH3] shutdown complete");
ctx->connected = false;
ctx->handshake_complete = true;
}
@@ -474,18 +474,18 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
if(stream->reset) {
failf(data, "HTTP/3 stream reset by server");
*err = CURLE_PARTIAL_FILE;
- DEBUGF(LOG_CF(data, cf, "cf_recv, was reset -> %d", *err));
+ CURL_TRC_CF(data, cf, "cf_recv, was reset -> %d", *err);
goto out;
}
else if(stream->error3) {
failf(data, "HTTP/3 stream was not closed cleanly: (error %zd)",
(ssize_t)stream->error3);
*err = CURLE_HTTP3;
- DEBUGF(LOG_CF(data, cf, "cf_recv, closed uncleanly -> %d", *err));
+ CURL_TRC_CF(data, cf, "cf_recv, closed uncleanly -> %d", *err);
goto out;
}
else {
- DEBUGF(LOG_CF(data, cf, "cf_recv, closed ok -> %d", *err));
+ CURL_TRC_CF(data, cf, "cf_recv, closed ok -> %d", *err);
}
*err = CURLE_OK;
nread = 0;
@@ -523,7 +523,7 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
return -1;
}
CF_DATA_SAVE(save, cf, data);
- DEBUGF(LOG_CF(data, cf, "req: recv with %zu byte buffer", len));
+ CURL_TRC_CF(data, cf, "req: recv with %zu byte buffer", len);
msh3_lock_acquire(&stream->recv_lock);
@@ -538,8 +538,8 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
if(!Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
(unsigned char *)buf, len, err);
- DEBUGF(LOG_CF(data, cf, "read recvbuf(len=%zu) -> %zd, %d",
- len, nread, *err));
+ CURL_TRC_CF(data, cf, "read recvbuf(len=%zu) -> %zd, %d",
+ len, nread, *err);
if(nread < 0)
goto out;
if(stream->closed)
@@ -550,7 +550,7 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
goto out;
}
else {
- DEBUGF(LOG_CF(data, cf, "req: nothing here, call again"));
+ CURL_TRC_CF(data, cf, "req: nothing here, call again");
*err = CURLE_AGAIN;
}
@@ -581,7 +581,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
/* Sizes must match for cast below to work" */
DEBUGASSERT(stream);
- DEBUGF(LOG_CF(data, cf, "req: send %zu bytes", len));
+ CURL_TRC_CF(data, cf, "req: send %zu bytes", len);
if(!stream->req) {
/* The first send on the request contains the headers and possibly some
@@ -630,7 +630,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
break;
}
- DEBUGF(LOG_CF(data, cf, "req: send %zu headers", nheader));
+ CURL_TRC_CF(data, cf, "req: send %zu headers", nheader);
stream->req = MsH3RequestOpen(ctx->qconn, &msh3_request_if, data,
nva, nheader,
eos ? MSH3_REQUEST_FLAG_FIN :
@@ -646,7 +646,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
}
else {
/* request is open */
- DEBUGF(LOG_CF(data, cf, "req: send %zu body bytes", len));
+ CURL_TRC_CF(data, cf, "req: send %zu body bytes", len);
if(len > 0xFFFFFFFF) {
len = 0xFFFFFFFF;
}
@@ -694,7 +694,7 @@ static int cf_msh3_get_select_socks(struct Curl_cfilter *cf,
drain_stream(cf, data);
}
}
- DEBUGF(LOG_CF(data, cf, "select_sock -> %d", bitmap));
+ CURL_TRC_CF(data, cf, "select_sock -> %d", bitmap);
CF_DATA_RESTORE(cf, save);
return bitmap;
}
@@ -711,8 +711,8 @@ static bool cf_msh3_data_pending(struct Curl_cfilter *cf,
(void)cf;
if(stream && stream->req) {
msh3_lock_acquire(&stream->recv_lock);
- DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data pending = %zu",
- Curl_bufq_len(&stream->recvbuf)));
+ CURL_TRC_CF((struct Curl_easy *)data, cf, "data pending = %zu",
+ Curl_bufq_len(&stream->recvbuf));
pending = !Curl_bufq_is_empty(&stream->recvbuf);
msh3_lock_release(&stream->recv_lock);
if(pending)
@@ -774,7 +774,7 @@ static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf,
h3_data_done(cf, data);
break;
case CF_CTRL_DATA_DONE_SEND:
- DEBUGF(LOG_CF(data, cf, "req: send done"));
+ CURL_TRC_CF(data, cf, "req: send done");
if(stream) {
stream->upload_done = TRUE;
if(stream->req) {
@@ -787,7 +787,7 @@ static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf,
}
break;
case CF_CTRL_CONN_INFO_UPDATE:
- DEBUGF(LOG_CF(data, cf, "req: update info"));
+ CURL_TRC_CF(data, cf, "req: update info");
cf_msh3_active(cf, data);
break;
default:
@@ -813,17 +813,17 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
/* TODO: need a way to provide trust anchors to MSH3 */
#ifdef DEBUGBUILD
/* we need this for our test cases to run */
- DEBUGF(LOG_CF(data, cf, "non-standard CA not supported, "
- "switching off verifypeer in DEBUG mode"));
+ CURL_TRC_CF(data, cf, "non-standard CA not supported, "
+ "switching off verifypeer in DEBUG mode");
verify = 0;
#else
- DEBUGF(LOG_CF(data, cf, "non-standard CA not supported, "
- "attempting with built-in verification"));
+ CURL_TRC_CF(data, cf, "non-standard CA not supported, "
+ "attempting with built-in verification");
#endif
}
- DEBUGF(LOG_CF(data, cf, "connecting to %s:%d (verify=%d)",
- cf->conn->host.name, (int)cf->conn->remote_port, verify));
+ CURL_TRC_CF(data, cf, "connecting to %s:%d (verify=%d)",
+ cf->conn->host.name, (int)cf->conn->remote_port, verify);
ctx->api = MsH3ApiOpen();
if(!ctx->api) {
@@ -888,7 +888,7 @@ static CURLcode cf_msh3_connect(struct Curl_cfilter *cf,
if(ctx->handshake_complete) {
ctx->handshake_at = Curl_now();
if(ctx->handshake_succeeded) {
- DEBUGF(LOG_CF(data, cf, "handshake succeeded"));
+ CURL_TRC_CF(data, cf, "handshake succeeded");
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
cf->conn->httpversion = 30;
cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
@@ -918,7 +918,7 @@ static void cf_msh3_close(struct Curl_cfilter *cf, struct Curl_easy *data)
CF_DATA_SAVE(save, cf, data);
if(ctx) {
- DEBUGF(LOG_CF(data, cf, "destroying"));
+ CURL_TRC_CF(data, cf, "destroying");
if(ctx->qconn) {
MsH3ConnectionClose(ctx->qconn);
ctx->qconn = NULL;
@@ -935,13 +935,13 @@ static void cf_msh3_close(struct Curl_cfilter *cf, struct Curl_easy *data)
*/
ctx->active = FALSE;
if(ctx->sock[SP_LOCAL] == cf->conn->sock[cf->sockindex]) {
- DEBUGF(LOG_CF(data, cf, "cf_msh3_close(%d) active",
- (int)ctx->sock[SP_LOCAL]));
+ CURL_TRC_CF(data, cf, "cf_msh3_close(%d) active",
+ (int)ctx->sock[SP_LOCAL]);
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
}
else {
- DEBUGF(LOG_CF(data, cf, "cf_socket_close(%d) no longer at "
- "conn->sock[], discarding", (int)ctx->sock[SP_LOCAL]));
+ CURL_TRC_CF(data, cf, "cf_socket_close(%d) no longer at "
+ "conn->sock[], discarding", (int)ctx->sock[SP_LOCAL]);
ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
}
if(cf->sockindex == FIRSTSOCKET)
diff --git a/libs/libcurl/src/vquic/curl_ngtcp2.c b/libs/libcurl/src/vquic/curl_ngtcp2.c
index 50ca212a96..7fd7085304 100644
--- a/libs/libcurl/src/vquic/curl_ngtcp2.c
+++ b/libs/libcurl/src/vquic/curl_ngtcp2.c
@@ -58,6 +58,7 @@
#include "dynbuf.h"
#include "http1.h"
#include "select.h"
+#include "inet_pton.h"
#include "vquic.h"
#include "vquic_int.h"
#include "vtls/keylog.h"
@@ -162,6 +163,9 @@ struct cf_ngtcp2_ctx {
size_t max_stream_window; /* max flow window for one stream */
int qlogfd;
BIT(got_first_byte); /* if first byte was received */
+#ifdef USE_OPENSSL
+ BIT(x509_store_setup); /* if x509 store has been set up */
+#endif
};
/* How to access `call_data` from a cf_ngtcp2 filter */
@@ -176,6 +180,7 @@ struct h3_stream_ctx {
int64_t id; /* HTTP/3 protocol identifier */
struct bufq sendbuf; /* h3 request body */
struct bufq recvbuf; /* h3 response body */
+ struct h1_req_parser h1; /* h1 request parsing */
size_t sendbuf_len_in_flight; /* sendbuf amount "in flight" */
size_t upload_blocked_len; /* the amount written last and EGAINed */
size_t recv_buf_nonflow; /* buffered bytes, not counting for flow control */
@@ -223,9 +228,9 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
stream->recv_buf_nonflow = 0;
+ Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
H3_STREAM_LCTX(data) = stream;
- DEBUGF(LOG_CF(data, cf, "data setup"));
return CURLE_OK;
}
@@ -235,10 +240,10 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
(void)cf;
if(stream) {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] easy handle is done",
- stream->id));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id);
Curl_bufq_free(&stream->sendbuf);
Curl_bufq_free(&stream->recvbuf);
+ Curl_h1_req_parse_free(&stream->h1);
free(stream);
H3_STREAM_LCTX(data) = NULL;
}
@@ -392,6 +397,7 @@ static int init_ngh3_conn(struct Curl_cfilter *cf);
static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
struct Curl_cfilter *cf, struct Curl_easy *data)
{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct connectdata *conn = cf->conn;
CURLcode result = CURLE_FAILED_INIT;
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
@@ -440,10 +446,6 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
}
- result = Curl_ssl_setup_x509_store(cf, data, ssl_ctx);
- if(result)
- goto out;
-
/* OpenSSL always tries to verify the peer, this only says whether it should
* fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with
@@ -453,6 +455,15 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
/* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) {
+ /* When a user callback is installed to modify the SSL_CTX,
+ * we need to do the full initialization before calling it.
+ * See: #11800 */
+ if(!ctx->x509_store_setup) {
+ result = Curl_ssl_setup_x509_store(cf, data, ssl_ctx);
+ if(result)
+ goto out;
+ ctx->x509_store_setup = TRUE;
+ }
Curl_set_in_callback(data, true);
result = (*data->set.ssl.fsslctx)(data, ssl_ctx,
data->set.ssl.fsslctxp);
@@ -501,8 +512,8 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
struct cf_ngtcp2_ctx *ctx = cf->ctx;
const uint8_t *alpn = NULL;
size_t alpnlen = 0;
+ unsigned char checkip[16];
- (void)data;
DEBUGASSERT(!ctx->ssl);
ctx->ssl = SSL_new(ctx->sslctx);
@@ -516,7 +527,19 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
SSL_set_alpn_protos(ctx->ssl, alpn, (int)alpnlen);
/* set SNI */
- SSL_set_tlsext_host_name(ctx->ssl, cf->conn->host.name);
+ if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip))
+#ifdef ENABLE_IPV6
+ && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip))
+#endif
+ ) {
+ char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL);
+ if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) {
+ failf(data, "Failed set SNI");
+ SSL_free(ctx->ssl);
+ ctx->ssl = NULL;
+ return CURLE_QUIC_CONNECT_ERROR;
+ }
+ }
return CURLE_OK;
}
#elif defined(USE_GNUTLS)
@@ -544,15 +567,15 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
gnutls_session_set_ptr(ctx->gtls->session, &ctx->conn_ref);
if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls->session) != 0) {
- DEBUGF(LOG_CF(data, cf,
- "ngtcp2_crypto_gnutls_configure_client_session failed\n"));
+ CURL_TRC_CF(data, cf,
+ "ngtcp2_crypto_gnutls_configure_client_session failed\n");
return CURLE_QUIC_CONNECT_ERROR;
}
rc = gnutls_priority_set_direct(ctx->gtls->session, QUIC_PRIORITY, NULL);
if(rc < 0) {
- DEBUGF(LOG_CF(data, cf, "gnutls_priority_set_direct failed: %s\n",
- gnutls_strerror(rc)));
+ CURL_TRC_CF(data, cf, "gnutls_priority_set_direct failed: %s\n",
+ gnutls_strerror(rc));
return CURLE_QUIC_CONNECT_ERROR;
}
@@ -596,7 +619,7 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
if(wolfSSL_CTX_set_cipher_list(ssl_ctx, QUIC_CIPHERS) != 1) {
char error_buffer[256];
ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
- failf(data, "SSL_CTX_set_ciphersuites: %s", error_buffer);
+ failf(data, "wolfSSL_CTX_set_cipher_list: %s", error_buffer);
goto out;
}
@@ -728,8 +751,8 @@ static void report_consumed_data(struct Curl_cfilter *cf,
}
}
if(consumed > 0) {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] consumed %zu DATA bytes",
- stream->id, consumed));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] ACK %zu bytes of DATA",
+ stream->id, consumed);
ngtcp2_conn_extend_max_stream_offset(ctx->qconn, stream->id,
consumed);
ngtcp2_conn_extend_max_offset(ctx->qconn, consumed);
@@ -751,8 +774,8 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
nconsumed =
nghttp3_conn_read_stream(ctx->h3conn, stream_id, buf, buflen, fin);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read_stream(len=%zu) -> %zd",
- stream_id, buflen, nconsumed));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read_stream(len=%zu) -> %zd",
+ stream_id, buflen, nconsumed);
if(nconsumed < 0) {
ngtcp2_ccerr_set_application_error(
&ctx->last_error,
@@ -810,8 +833,8 @@ static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
rv = nghttp3_conn_close_stream(ctx->h3conn, stream3_id,
app_error_code);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] quic close(err=%"
- PRIu64 ") -> %d", stream3_id, app_error_code, rv));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] quic close(err=%"
+ PRIu64 ") -> %d", stream3_id, app_error_code, rv);
if(rv) {
ngtcp2_ccerr_set_application_error(
&ctx->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0);
@@ -835,7 +858,7 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
(void)data;
rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] reset -> %d", stream_id, rv));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv);
if(rv) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -1064,8 +1087,6 @@ static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf,
stream && nghttp3_conn_is_stream_writable(ctx->h3conn, stream->id))
rv |= GETSOCK_WRITESOCK(0);
- /* DEBUGF(LOG_CF(data, cf, "get_select_socks -> %x (sock=%d)",
- rv, (int)socks[0])); */
CF_DATA_RESTORE(cf, save);
return rv;
}
@@ -1095,21 +1116,23 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
(void)conn;
(void)stream_id;
- (void)app_error_code;
- (void)cf;
/* we might be called by nghttp3 after we already cleaned up */
if(!stream)
return 0;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] h3 close(err=%" PRId64 ")",
- stream_id, app_error_code));
stream->closed = TRUE;
stream->error3 = app_error_code;
- if(app_error_code == NGHTTP3_H3_INTERNAL_ERROR) {
+ if(stream->error3 != NGHTTP3_H3_NO_ERROR) {
stream->reset = TRUE;
stream->send_closed = TRUE;
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] RESET: error %" PRId64,
+ stream->id, stream->error3);
+ }
+ else {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] CLOSED", stream->id);
}
+ data->req.keepon &= ~KEEP_SEND_HOLD;
h3_drain_stream(cf, data);
return 0;
}
@@ -1133,9 +1156,6 @@ static CURLcode write_resp_raw(struct Curl_cfilter *cf,
return CURLE_RECV_ERROR;
}
nwritten = Curl_bufq_write(&stream->recvbuf, mem, memlen, &result);
- /* DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] add recvbuf(len=%zu) "
- "-> %zd, %d", stream->id, memlen, nwritten, result));
- */
if(nwritten < 0) {
return result;
}
@@ -1158,14 +1178,24 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
{
struct Curl_cfilter *cf = user_data;
struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
CURLcode result;
(void)conn;
(void)stream3_id;
+ if(!stream)
+ return NGHTTP3_ERR_CALLBACK_FAILURE;
+
result = write_resp_raw(cf, data, buf, buflen, TRUE);
+ if(result) {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu, ERROR receiving %d",
+ stream->id, buflen, result);
+ return NGHTTP3_ERR_CALLBACK_FAILURE;
+ }
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu", stream->id, buflen);
h3_drain_stream(cf, data);
- return result? -1 : 0;
+ return 0;
}
static int cb_h3_deferred_consume(nghttp3_conn *conn, int64_t stream3_id,
@@ -1204,8 +1234,8 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
return -1;
}
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] end_headers(status_code=%d",
- stream_id, stream->status_code));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] end_headers, status=%d",
+ stream_id, stream->status_code);
if(stream->status_code / 100 != 1) {
stream->resp_hds_complete = TRUE;
}
@@ -1244,8 +1274,7 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
return -1;
ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n",
stream->status_code);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] status: %s",
- stream_id, line));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] status: %s", stream_id, line);
result = write_resp_raw(cf, data, line, ncopy, FALSE);
if(result) {
return -1;
@@ -1253,9 +1282,9 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
}
else {
/* store as an HTTP1-style header */
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] header: %.*s: %.*s",
- stream_id, (int)h3name.len, h3name.base,
- (int)h3val.len, h3val.base));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] header: %.*s: %.*s",
+ stream_id, (int)h3name.len, h3name.base,
+ (int)h3val.len, h3val.base);
result = write_resp_raw(cf, data, h3name.base, h3name.len, FALSE);
if(result) {
return -1;
@@ -1307,7 +1336,7 @@ static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t stream_id,
rv = ngtcp2_conn_shutdown_stream_write(ctx->qconn, 0, stream_id,
app_error_code);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] reset -> %d", stream_id, rv));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv);
if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -1404,35 +1433,17 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
if(stream->reset) {
failf(data,
"HTTP/3 stream %" PRId64 " reset by server", stream->id);
- *err = CURLE_PARTIAL_FILE;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, was reset -> %d",
- stream->id, *err));
+ *err = stream->resp_hds_complete? CURLE_PARTIAL_FILE : CURLE_HTTP3;
goto out;
}
- else if(stream->error3 != NGHTTP3_H3_NO_ERROR) {
- failf(data,
- "HTTP/3 stream %" PRId64 " was not closed cleanly: "
- "(err %"PRId64")", stream->id, stream->error3);
- *err = CURLE_HTTP3;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed uncleanly"
- " -> %d", stream->id, *err));
- goto out;
- }
-
- if(!stream->resp_hds_complete) {
+ else if(!stream->resp_hds_complete) {
failf(data,
"HTTP/3 stream %" PRId64 " was closed cleanly, but before getting"
" all response header fields, treated as error",
stream->id);
*err = CURLE_HTTP3;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed incomplete"
- " -> %d", stream->id, *err));
goto out;
}
- else {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed ok"
- " -> %d", stream->id, *err));
- }
*err = CURLE_OK;
nread = 0;
@@ -1469,10 +1480,11 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
if(!Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
(unsigned char *)buf, len, err);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read recvbuf(len=%zu) "
- "-> %zd, %d", stream->id, len, nread, *err));
- if(nread < 0)
+ if(nread < 0) {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
+ "-> %zd, %d", stream->id, len, nread, *err);
goto out;
+ }
report_consumed_data(cf, data, nread);
}
@@ -1486,10 +1498,11 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
(unsigned char *)buf, len, err);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read recvbuf(len=%zu) "
- "-> %zd, %d", stream->id, len, nread, *err));
- if(nread < 0)
+ if(nread < 0) {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
+ "-> %zd, %d", stream->id, len, nread, *err);
goto out;
+ }
report_consumed_data(cf, data, nread);
}
@@ -1517,8 +1530,8 @@ out:
nread = -1;
}
}
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv(len=%zu) -> %zd, %d",
- stream? stream->id : -1, len, nread, *err));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv(len=%zu) -> %zd, %d",
+ stream? stream->id : -1, len, nread, *err);
CF_DATA_RESTORE(cf, save);
return nread;
}
@@ -1555,8 +1568,7 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
(data->req.keepon & KEEP_SEND)) {
data->req.keepon &= ~KEEP_SEND_HOLD;
h3_drain_stream(cf, data);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] unpausing acks",
- stream_id));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] unpausing acks", stream_id);
}
}
return 0;
@@ -1613,18 +1625,18 @@ cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
}
else if(!nwritten) {
/* Not EOF, and nothing to give, we signal WOULDBLOCK. */
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read req body -> AGAIN",
- stream->id));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> AGAIN",
+ stream->id);
return NGHTTP3_ERR_WOULDBLOCK;
}
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read req body -> "
- "%d vecs%s with %zu (buffered=%zu, left=%"
- CURL_FORMAT_CURL_OFF_T ")",
- stream->id, (int)nvecs,
- *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
- nwritten, Curl_bufq_len(&stream->sendbuf),
- stream->upload_left));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> "
+ "%d vecs%s with %zu (buffered=%zu, left=%"
+ CURL_FORMAT_CURL_OFF_T ")",
+ stream->id, (int)nvecs,
+ *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
+ nwritten, Curl_bufq_len(&stream->sendbuf),
+ stream->upload_left);
return (nghttp3_ssize)nvecs;
}
@@ -1639,7 +1651,6 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = NULL;
- struct h1_req_parser h1;
struct dynhds h2_headers;
size_t nheader;
nghttp3_nv *nva = NULL;
@@ -1649,7 +1660,6 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
nghttp3_data_reader reader;
nghttp3_data_reader *preader = NULL;
- Curl_h1_req_parse_init(&h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
*err = h3_data_setup(cf, data);
@@ -1658,24 +1668,22 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
stream = H3_STREAM_CTX(data);
DEBUGASSERT(stream);
- rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, NULL);
- if(rc) {
- failf(data, "can get bidi streams");
- *err = CURLE_SEND_ERROR;
- goto out;
- }
-
- nwritten = Curl_h1_req_parse_read(&h1, buf, len, NULL, 0, err);
+ nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
if(nwritten < 0)
goto out;
- DEBUGASSERT(h1.done);
- DEBUGASSERT(h1.req);
+ if(!stream->h1.done) {
+ /* need more data */
+ goto out;
+ }
+ DEBUGASSERT(stream->h1.req);
- *err = Curl_http_req_to_h2(&h2_headers, h1.req, data);
+ *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
if(*err) {
nwritten = -1;
goto out;
}
+ /* no longer needed */
+ Curl_h1_req_parse_free(&stream->h1);
nheader = Curl_dynhds_count(&h2_headers);
nva = malloc(sizeof(nghttp3_nv) * nheader);
@@ -1694,6 +1702,13 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
nva[i].flags = NGHTTP3_NV_FLAG_NONE;
}
+ rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, NULL);
+ if(rc) {
+ failf(data, "can get bidi streams");
+ *err = CURLE_SEND_ERROR;
+ goto out;
+ }
+
switch(data->state.httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
@@ -1723,12 +1738,12 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
if(rc) {
switch(rc) {
case NGHTTP3_ERR_CONN_CLOSING:
- DEBUGF(LOG_CF(data, cf, "h3sid[%"PRId64"] failed to send, "
- "connection is closing", stream->id));
+ CURL_TRC_CF(data, cf, "h3sid[%"PRId64"] failed to send, "
+ "connection is closing", stream->id);
break;
default:
- DEBUGF(LOG_CF(data, cf, "h3sid[%"PRId64"] failed to send -> %d (%s)",
- stream->id, rc, ngtcp2_strerror(rc)));
+ CURL_TRC_CF(data, cf, "h3sid[%"PRId64"] failed to send -> %d (%s)",
+ stream->id, rc, ngtcp2_strerror(rc));
break;
}
*err = CURLE_SEND_ERROR;
@@ -1736,13 +1751,18 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
goto out;
}
- infof(data, "Using HTTP/3 Stream ID: %" PRId64, stream->id);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] opened for %s",
- stream->id, data->state.url));
+ if(Curl_trc_is_verbose(data)) {
+ infof(data, "[HTTP/3] [%" PRId64 "] OPENED stream for %s",
+ stream->id, data->state.url);
+ for(i = 0; i < nheader; ++i) {
+ infof(data, "[HTTP/3] [%" PRId64 "] [%.*s: %.*s]", stream->id,
+ (int)nva[i].namelen, nva[i].name,
+ (int)nva[i].valuelen, nva[i].value);
+ }
+ }
out:
free(nva);
- Curl_h1_req_parse_free(&h1);
Curl_dynhds_free(&h2_headers);
return nwritten;
}
@@ -1773,12 +1793,13 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
if(!stream || stream->id < 0) {
sent = h3_stream_open(cf, data, buf, len, err);
if(sent < 0) {
- DEBUGF(LOG_CF(data, cf, "failed to open stream -> %d", *err));
+ CURL_TRC_CF(data, cf, "failed to open stream -> %d", *err);
goto out;
}
+ stream = H3_STREAM_CTX(data);
}
else if(stream->upload_blocked_len) {
- /* the data in `buf` has alread been submitted or added to the
+ /* the data in `buf` has already been submitted or added to the
* buffers, but have been EAGAINed on the last invocation. */
DEBUGASSERT(len >= stream->upload_blocked_len);
if(len < stream->upload_blocked_len) {
@@ -1793,15 +1814,27 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
stream->upload_blocked_len = 0;
}
else if(stream->closed) {
+ if(stream->resp_hds_complete) {
+ /* Server decided to close the stream after having sent us a final
+ * response. This is valid if it is not interested in the request
+ * body. This happens on 30x or 40x responses.
+ * We silently discard the data sent, since this is not a transport
+ * error situation. */
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] discarding data"
+ "on closed stream with response", stream->id);
+ *err = CURLE_OK;
+ sent = (ssize_t)len;
+ goto out;
+ }
*err = CURLE_HTTP3;
sent = -1;
goto out;
}
else {
sent = Curl_bufq_write(&stream->sendbuf, buf, len, err);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send, add to "
- "sendbuf(len=%zu) -> %zd, %d",
- stream->id, len, sent, *err));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send, add to "
+ "sendbuf(len=%zu) -> %zd, %d",
+ stream->id, len, sent, *err);
if(sent < 0) {
goto out;
}
@@ -1821,9 +1854,9 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
* "written" into our various internal connection buffers.
* We put the stream upload on HOLD, until this gets ACKed. */
stream->upload_blocked_len = sent;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send(len=%zu), "
- "%zu bytes in flight -> EGAIN", stream->id, len,
- stream->sendbuf_len_in_flight));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu), "
+ "%zu bytes in flight -> EGAIN", stream->id, len,
+ stream->sendbuf_len_in_flight);
*err = CURLE_AGAIN;
sent = -1;
data->req.keepon |= KEEP_SEND_HOLD;
@@ -1835,8 +1868,8 @@ out:
*err = result;
sent = -1;
}
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
- stream? stream->id : -1, len, sent, *err));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
+ stream? stream->id : -1, len, sent, *err);
CF_DATA_RESTORE(cf, save);
return sent;
}
@@ -1909,12 +1942,12 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
ctx->q.local_addrlen);
ngtcp2_addr_init(&path.remote, (struct sockaddr *)remote_addr,
remote_addrlen);
- pi.ecn = (uint32_t)ecn;
+ pi.ecn = (uint8_t)ecn;
rv = ngtcp2_conn_read_pkt(ctx->qconn, &path, &pi, pkt, pktlen, pktx->ts);
if(rv) {
- DEBUGF(LOG_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s",
- ngtcp2_strerror(rv)));
+ CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s",
+ ngtcp2_strerror(rv));
if(!ctx->last_error.error_code) {
if(rv == NGTCP2_ERR_CRYPTO) {
ngtcp2_ccerr_set_tls_alert(&ctx->last_error,
@@ -1954,6 +1987,15 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
pktx->ts = timestamp();
}
+#ifdef USE_OPENSSL
+ if(!ctx->x509_store_setup) {
+ result = Curl_ssl_setup_x509_store(cf, data, ctx->sslctx);
+ if(result)
+ return result;
+ ctx->x509_store_setup = TRUE;
+ }
+#endif
+
for(i = 0; i < pkts_max; i += pkts_chunk) {
pktx->pkt_count = 0;
result = vquic_recv_packets(cf, data, &ctx->q, pkts_chunk,
@@ -2129,8 +2171,6 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
/* add the next packet to send, if any, to our buffer */
nread = Curl_bufq_sipn(&ctx->q.sendbuf, max_payload_size,
read_pkt_to_send, pktx, &curlcode);
- /* DEBUGF(LOG_CF(data, cf, "sip packet(maxlen=%zu) -> %zd, %d",
- max_payload_size, nread, curlcode)); */
if(nread < 0) {
if(curlcode != CURLE_AGAIN)
return curlcode;
@@ -2246,9 +2286,16 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
}
break;
}
- case CF_CTRL_DATA_IDLE:
- result = check_and_set_expiry(cf, data, NULL);
+ case CF_CTRL_DATA_IDLE: {
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ CURL_TRC_CF(data, cf, "data idle");
+ if(stream && !stream->closed) {
+ result = check_and_set_expiry(cf, data, NULL);
+ if(result)
+ CURL_TRC_CF(data, cf, "data idle, check_and_set_expiry -> %d", result);
+ }
break;
+ }
default:
break;
}
@@ -2305,7 +2352,7 @@ static void cf_ngtcp2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
ngtcp2_tstamp ts;
ngtcp2_ssize rc;
- DEBUGF(LOG_CF(data, cf, "close"));
+ CURL_TRC_CF(data, cf, "close");
ts = timestamp();
rc = ngtcp2_conn_write_connection_close(ctx->qconn, NULL, /* path */
NULL, /* pkt_info */
@@ -2329,7 +2376,7 @@ static void cf_ngtcp2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
- DEBUGF(LOG_CF(data, cf, "destroy"));
+ CURL_TRC_CF(data, cf, "destroy");
if(ctx) {
cf_ngtcp2_ctx_clear(ctx);
free(ctx);
@@ -2350,7 +2397,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
int rc;
int rv;
CURLcode result;
- const struct Curl_sockaddr_ex *sockaddr;
+ const struct Curl_sockaddr_ex *sockaddr = NULL;
int qfd;
ctx->version = NGTCP2_PROTO_VER_MAX;
@@ -2396,6 +2443,8 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd,
&sockaddr, NULL, NULL, NULL, NULL);
+ if(!sockaddr)
+ return CURLE_QUIC_CONNECT_ERROR;
ctx->q.local_addrlen = sizeof(ctx->q.local_addr);
rv = getsockname(ctx->q.sockfd, (struct sockaddr *)&ctx->q.local_addr,
&ctx->q.local_addrlen);
@@ -2460,7 +2509,7 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
/* Not time yet to attempt the next connect */
- DEBUGF(LOG_CF(data, cf, "waiting for reconnect time"));
+ CURL_TRC_CF(data, cf, "waiting for reconnect time");
goto out;
}
@@ -2484,11 +2533,11 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
if(ngtcp2_conn_get_handshake_completed(ctx->qconn)) {
ctx->handshake_at = now;
- DEBUGF(LOG_CF(data, cf, "handshake complete after %dms",
- (int)Curl_timediff(now, ctx->started_at)));
+ CURL_TRC_CF(data, cf, "handshake complete after %dms",
+ (int)Curl_timediff(now, ctx->started_at));
result = qng_verify_peer(cf, data);
if(!result) {
- DEBUGF(LOG_CF(data, cf, "peer verified"));
+ CURL_TRC_CF(data, cf, "peer verified");
cf->connected = TRUE;
cf->conn->alpn = CURL_HTTP_VERSION_3;
*done = TRUE;
@@ -2510,8 +2559,8 @@ out:
*/
int reconn_delay_ms = 200;
- DEBUGF(LOG_CF(data, cf, "connect, remote closed, reconnect after %dms",
- reconn_delay_ms));
+ CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms",
+ reconn_delay_ms);
Curl_conn_cf_close(cf->next, data);
cf_ngtcp2_ctx_clear(ctx);
result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
@@ -2526,8 +2575,8 @@ out:
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(result) {
- const char *r_ip;
- int r_port;
+ const char *r_ip = NULL;
+ int r_port = 0;
Curl_cf_socket_peek(cf->next, data, NULL, NULL,
&r_ip, &r_port, NULL, NULL);
@@ -2538,7 +2587,8 @@ out:
if(!result && ctx->qconn) {
result = check_and_set_expiry(cf, data, &pktx);
}
- DEBUGF(LOG_CF(data, cf, "connect -> %d, done=%d", result, *done));
+ if(result || *done)
+ CURL_TRC_CF(data, cf, "connect -> %d, done=%d", result, *done);
CF_DATA_RESTORE(cf, save);
return result;
}
@@ -2562,7 +2612,7 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
INT_MAX : (int)rp->initial_max_streams_bidi;
else /* not arrived yet? */
*pres1 = Curl_multi_max_concurrent_streams(data->multi);
- DEBUGF(LOG_CF(data, cf, "query max_conncurrent -> %d", *pres1));
+ CURL_TRC_CF(data, cf, "query max_conncurrent -> %d", *pres1);
CF_DATA_RESTORE(cf, save);
return CURLE_OK;
}
diff --git a/libs/libcurl/src/vquic/curl_quiche.c b/libs/libcurl/src/vquic/curl_quiche.c
index f6e995c6c5..cec899f161 100644
--- a/libs/libcurl/src/vquic/curl_quiche.c
+++ b/libs/libcurl/src/vquic/curl_quiche.c
@@ -45,8 +45,10 @@
#include "vquic_int.h"
#include "curl_quiche.h"
#include "transfer.h"
+#include "inet_pton.h"
#include "vtls/openssl.h"
#include "vtls/keylog.h"
+#include "vtls/vtls.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -56,7 +58,7 @@
/* #define DEBUG_QUICHE */
#define QUIC_MAX_STREAMS (100)
-#define QUIC_IDLE_TIMEOUT (5 * 1000) /* milliseconds */
+#define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */
#define H3_STREAM_WINDOW_SIZE (128 * 1024)
#define H3_STREAM_CHUNK_SIZE (16 * 1024)
@@ -88,54 +90,6 @@ static void keylog_callback(const SSL *ssl, const char *line)
Curl_tls_keylog_write_line(line);
}
-static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
-{
- SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
-
- SSL_CTX_set_alpn_protos(ssl_ctx,
- (const uint8_t *)QUICHE_H3_APPLICATION_PROTOCOL,
- sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1);
-
- SSL_CTX_set_default_verify_paths(ssl_ctx);
-
- /* Open the file if a TLS or QUIC backend has not done this before. */
- Curl_tls_keylog_open();
- if(Curl_tls_keylog_enabled()) {
- SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
- }
-
- {
- struct connectdata *conn = data->conn;
- if(conn->ssl_config.verifypeer) {
- const char * const ssl_cafile = conn->ssl_config.CAfile;
- const char * const ssl_capath = conn->ssl_config.CApath;
- if(ssl_cafile || ssl_capath) {
- SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
- /* tell OpenSSL where to find CA certificates that are used to verify
- the server's certificate. */
- if(!SSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:"
- " CAfile: %s CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- return NULL;
- }
- infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
- infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
- }
-#ifdef CURL_CA_FALLBACK
- else {
- /* 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(ssl_ctx);
- }
-#endif
- }
- }
- return ssl_ctx;
-}
-
struct cf_quiche_ctx {
struct cf_quic_ctx q;
quiche_conn *qconn;
@@ -154,6 +108,7 @@ struct cf_quiche_ctx {
size_t sends_on_hold; /* # of streams with SEND_HOLD set */
BIT(goaway); /* got GOAWAY from server */
BIT(got_first_byte); /* if first byte was received */
+ BIT(x509_store_setup); /* if x509 store has been set up */
};
#ifdef DEBUG_QUICHE
@@ -181,12 +136,96 @@ static void cf_quiche_ctx_clear(struct cf_quiche_ctx *ctx)
}
}
+static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+
+ if(!ctx->x509_store_setup) {
+ if(cf->conn->ssl_config.verifypeer) {
+ const char * const ssl_cafile = cf->conn->ssl_config.CAfile;
+ const char * const ssl_capath = cf->conn->ssl_config.CApath;
+ if(ssl_cafile || ssl_capath) {
+ SSL_CTX_set_verify(ctx->sslctx, SSL_VERIFY_PEER, NULL);
+ /* tell OpenSSL where to find CA certificates that are used to verify
+ the server's certificate. */
+ if(!SSL_CTX_load_verify_locations(
+ ctx->sslctx, ssl_cafile, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+ }
+#ifdef CURL_CA_FALLBACK
+ else {
+ /* 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(ssl_ctx);
+ }
+#endif
+ }
+ ctx->x509_store_setup = TRUE;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ unsigned char checkip[16];
+
+ DEBUGASSERT(!ctx->sslctx);
+ ctx->sslctx = SSL_CTX_new(TLS_method());
+ if(!ctx->sslctx)
+ return CURLE_OUT_OF_MEMORY;
+
+ SSL_CTX_set_alpn_protos(ctx->sslctx,
+ (const uint8_t *)QUICHE_H3_APPLICATION_PROTOCOL,
+ sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1);
+
+ SSL_CTX_set_default_verify_paths(ctx->sslctx);
+
+ /* Open the file if a TLS or QUIC backend has not done this before. */
+ Curl_tls_keylog_open();
+ if(Curl_tls_keylog_enabled()) {
+ SSL_CTX_set_keylog_callback(ctx->sslctx, keylog_callback);
+ }
+
+ ctx->ssl = SSL_new(ctx->sslctx);
+ if(!ctx->ssl)
+ return CURLE_QUIC_CONNECT_ERROR;
+
+ SSL_set_app_data(ctx->ssl, cf);
+
+ if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip))
+#ifdef ENABLE_IPV6
+ && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip))
+#endif
+ ) {
+ char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL);
+ if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) {
+ failf(data, "Failed set SNI");
+ SSL_free(ctx->ssl);
+ ctx->ssl = NULL;
+ return CURLE_QUIC_CONNECT_ERROR;
+ }
+ }
+
+ return CURLE_OK;
+}
+
/**
* All about the H3 internals of a stream
*/
struct stream_ctx {
int64_t id; /* HTTP/3 protocol stream identifier */
struct bufq recvbuf; /* h3 response */
+ struct h1_req_parser h1; /* h1 request parsing */
uint64_t error3; /* HTTP/3 stream error code */
curl_off_t upload_left; /* number of request bytes left to upload */
bool closed; /* TRUE on stream close */
@@ -217,11 +256,10 @@ static void stream_send_suspend(struct Curl_cfilter *cf,
data->req.keepon |= KEEP_SEND_HOLD;
++ctx->sends_on_hold;
if(H3_STREAM_ID(data) >= 0)
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] suspend sending",
- H3_STREAM_ID(data)));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] suspend sending",
+ H3_STREAM_ID(data));
else
- DEBUGF(LOG_CF(data, cf, "[%s] suspend sending",
- data->state.url));
+ CURL_TRC_CF(data, cf, "[%s] suspend sending", data->state.url);
}
}
@@ -234,11 +272,10 @@ static void stream_send_resume(struct Curl_cfilter *cf,
data->req.keepon &= ~KEEP_SEND_HOLD;
--ctx->sends_on_hold;
if(H3_STREAM_ID(data) >= 0)
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] resume sending",
- H3_STREAM_ID(data)));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] resume sending",
+ H3_STREAM_ID(data));
else
- DEBUGF(LOG_CF(data, cf, "[%s] resume sending",
- data->state.url));
+ CURL_TRC_CF(data, cf, "[%s] resume sending", data->state.url);
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
}
@@ -277,7 +314,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
stream->id = -1;
Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
- DEBUGF(LOG_CF(data, cf, "data setup"));
+ Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
return CURLE_OK;
}
@@ -288,13 +325,13 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
(void)cf;
if(stream) {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] easy handle is done",
- stream->id));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id);
if(stream_send_is_suspended(data)) {
data->req.keepon &= ~KEEP_SEND_HOLD;
--ctx->sends_on_hold;
}
Curl_bufq_free(&stream->recvbuf);
+ Curl_h1_req_parse_free(&stream->h1);
free(stream);
H3_STREAM_LCTX(data) = NULL;
}
@@ -379,8 +416,12 @@ static int cb_each_header(uint8_t *name, size_t name_len,
struct stream_ctx *stream = H3_STREAM_CTX(x->data);
CURLcode result;
- (void)stream;
+ if(!stream)
+ return CURLE_OK;
+
if((name_len == 7) && !strncmp(HTTP_PSEUDO_STATUS, (char *)name, 7)) {
+ CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] status: %.*s",
+ stream->id, (int)value_len, value);
result = write_resp_raw(x->cf, x->data, "HTTP/3 ", sizeof("HTTP/3 ") - 1);
if(!result)
result = write_resp_raw(x->cf, x->data, value, value_len);
@@ -388,6 +429,9 @@ static int cb_each_header(uint8_t *name, size_t name_len,
result = write_resp_raw(x->cf, x->data, " \r\n", 3);
}
else {
+ CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] header: %.*s: %.*s",
+ stream->id, (int)name_len, name,
+ (int)value_len, value);
result = write_resp_raw(x->cf, x->data, name, name_len);
if(!result)
result = write_resp_raw(x->cf, x->data, ": ", 2);
@@ -397,10 +441,8 @@ static int cb_each_header(uint8_t *name, size_t name_len,
result = write_resp_raw(x->cf, x->data, "\r\n", 2);
}
if(result) {
- DEBUGF(LOG_CF(x->data, x->cf,
- "[h3sid=%"PRId64"][HEADERS][%.*s: %.*s] error %d",
- stream? stream->id : -1, (int)name_len, name,
- (int)value_len, value, result));
+ CURL_TRC_CF(x->data, x->cf, "[%"PRId64"] on header error %d",
+ stream->id, result);
}
return result;
}
@@ -455,8 +497,8 @@ static CURLcode cf_recv_body(struct Curl_cfilter *cf,
stream_resp_read, &cb_ctx, &result);
if(nwritten < 0 && result != CURLE_AGAIN) {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] recv_body error %zd",
- stream->id, nwritten));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] recv_body error %zd",
+ stream->id, nwritten);
failf(data, "Error %d in HTTP/3 response body for stream[%"PRId64"]",
result, stream->id);
stream->closed = TRUE;
@@ -514,7 +556,7 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
rc, stream3_id);
return CURLE_RECV_ERROR;
}
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][HEADERS]", stream3_id));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] <- [HEADERS]", stream3_id);
break;
case QUICHE_H3_EVENT_DATA:
@@ -524,7 +566,7 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
break;
case QUICHE_H3_EVENT_RESET:
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][RESET]", stream3_id));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] RESET", stream3_id);
stream->closed = TRUE;
stream->reset = TRUE;
stream->send_closed = TRUE;
@@ -532,7 +574,7 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
break;
case QUICHE_H3_EVENT_FINISHED:
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][FINISHED]", stream3_id));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] CLOSED", stream3_id);
if(!stream->resp_hds_complete) {
result = write_resp_raw(cf, data, "\r\n", 2);
if(result)
@@ -541,15 +583,16 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
}
stream->closed = TRUE;
streamclose(cf->conn, "End of stream");
+ data->req.keepon &= ~KEEP_SEND_HOLD;
break;
case QUICHE_H3_EVENT_GOAWAY:
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][GOAWAY]", stream3_id));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] <- [GOAWAY]", stream3_id);
break;
default:
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] recv, unhandled event %d",
- stream3_id, quiche_h3_event_type(ev)));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] recv, unhandled event %d",
+ stream3_id, quiche_h3_event_type(ev));
break;
}
return result;
@@ -571,26 +614,25 @@ static CURLcode cf_poll_events(struct Curl_cfilter *cf,
break;
}
else if(stream3_id < 0) {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] error poll: %"PRId64,
- stream? stream->id : -1, stream3_id));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] error poll: %"PRId64,
+ stream? stream->id : -1, stream3_id);
return CURLE_HTTP3;
}
sdata = get_stream_easy(cf, data, stream3_id);
if(!sdata) {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] discard event %s for "
- "unknown [h3sid=%"PRId64"]",
- stream? stream->id : -1, cf_ev_name(ev),
- stream3_id));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] discard event %s for "
+ "unknown [%"PRId64"]",
+ stream? stream->id : -1, cf_ev_name(ev), stream3_id);
}
else {
result = h3_process_event(cf, sdata, stream3_id, ev);
drain_stream(cf, sdata);
if(result) {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] error processing event %s "
- "for [h3sid=%"PRId64"] -> %d",
- stream? stream->id : -1, cf_ev_name(ev),
- stream3_id, result));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] error processing event %s "
+ "for [%"PRId64"] -> %d",
+ stream? stream->id : -1, cf_ev_name(ev),
+ stream3_id, result);
if(data == sdata) {
/* Only report this error to the caller if it is about the
* transfer we were called with. Otherwise we fail a transfer
@@ -633,7 +675,7 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
&recv_info);
if(nread < 0) {
if(QUICHE_ERR_DONE == nread) {
- DEBUGF(LOG_CF(r->data, r->cf, "ingress, quiche is DONE"));
+ CURL_TRC_CF(r->data, r->cf, "ingress, quiche is DONE");
return CURLE_OK;
}
else if(QUICHE_ERR_TLS_FAIL == nread) {
@@ -650,8 +692,8 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
}
}
else if((size_t)nread < pktlen) {
- DEBUGF(LOG_CF(r->data, r->cf, "ingress, quiche only read %zd/%zu bytes",
- nread, pktlen));
+ CURL_TRC_CF(r->data, r->cf, "ingress, quiche only read %zd/%zu bytes",
+ nread, pktlen);
}
return CURLE_OK;
@@ -665,6 +707,10 @@ static CURLcode cf_process_ingress(struct Curl_cfilter *cf,
CURLcode result;
DEBUGASSERT(ctx->qconn);
+ result = quic_x509_store_setup(cf, data);
+ if(result)
+ return result;
+
rctx.cf = cf;
rctx.data = data;
rctx.pkts = 0;
@@ -720,10 +766,20 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
struct cf_quiche_ctx *ctx = cf->ctx;
ssize_t nread;
CURLcode result;
+ int64_t expiry_ns;
int64_t timeout_ns;
struct read_ctx readx;
size_t pkt_count, gsolen;
+ expiry_ns = quiche_conn_timeout_as_nanos(ctx->qconn);
+ if(!expiry_ns) {
+ quiche_conn_on_timeout(ctx->qconn);
+ if(quiche_conn_is_closed(ctx->qconn)) {
+ failf(data, "quiche_conn_on_timeout closed the connection");
+ return CURLE_SEND_ERROR;
+ }
+ }
+
result = vquic_flush(cf, data, &ctx->q);
if(result) {
if(result == CURLE_AGAIN) {
@@ -742,9 +798,6 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
/* add the next packet to send, if any, to our buffer */
nread = Curl_bufq_sipn(&ctx->q.sendbuf, 0,
read_pkt_to_send, &readx, &result);
- /* DEBUGF(LOG_CF(data, cf, "sip packet(maxlen=%zu) -> %zd, %d",
- (size_t)0, nread, result)); */
-
if(nread < 0) {
if(result != CURLE_AGAIN)
return result;
@@ -795,8 +848,8 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
failf(data,
"HTTP/3 stream %" PRId64 " reset by server", stream->id);
*err = stream->resp_got_header? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, was reset -> %d",
- stream->id, *err));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv, was reset -> %d",
+ stream->id, *err);
}
else if(!stream->resp_got_header) {
failf(data,
@@ -805,14 +858,12 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
stream->id);
/* *err = CURLE_PARTIAL_FILE; */
*err = CURLE_RECV_ERROR;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed incomplete"
- " -> %d", stream->id, *err));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv, closed incomplete"
+ " -> %d", stream->id, *err);
}
else {
*err = CURLE_OK;
nread = 0;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed ok"
- " -> %d", stream->id, *err));
}
return nread;
}
@@ -833,14 +884,14 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
if(!Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
(unsigned char *)buf, len, err);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read recvbuf(len=%zu) "
- "-> %zd, %d", stream->id, len, nread, *err));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
+ "-> %zd, %d", stream->id, len, nread, *err);
if(nread < 0)
goto out;
}
if(cf_process_ingress(cf, data)) {
- DEBUGF(LOG_CF(data, cf, "cf_recv, error on ingress"));
+ CURL_TRC_CF(data, cf, "cf_recv, error on ingress");
*err = CURLE_RECV_ERROR;
nread = -1;
goto out;
@@ -850,8 +901,8 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
(unsigned char *)buf, len, err);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read recvbuf(len=%zu) "
- "-> %zd, %d", stream->id, len, nread, *err));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
+ "-> %zd, %d", stream->id, len, nread, *err);
if(nread < 0)
goto out;
}
@@ -878,16 +929,15 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
out:
result = cf_flush_egress(cf, data);
if(result) {
- DEBUGF(LOG_CF(data, cf, "cf_recv, flush egress failed"));
+ CURL_TRC_CF(data, cf, "cf_recv, flush egress failed");
*err = result;
nread = -1;
}
if(nread > 0)
ctx->data_recvd += nread;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] cf_recv(total=%"
- CURL_FORMAT_CURL_OFF_T ") -> %zd, %d",
- stream ? stream->id : (int64_t)0,
- ctx->data_recvd, nread, *err));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] cf_recv(total=%"
+ CURL_FORMAT_CURL_OFF_T ") -> %zd, %d",
+ stream->id, ctx->data_recvd, nread, *err);
return nread;
}
@@ -904,7 +954,6 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
struct stream_ctx *stream = H3_STREAM_CTX(data);
size_t nheader, i;
int64_t stream3_id;
- struct h1_req_parser h1;
struct dynhds h2_headers;
quiche_h3_header *nva = NULL;
ssize_t nwritten;
@@ -918,21 +967,25 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
DEBUGASSERT(stream);
}
- Curl_h1_req_parse_init(&h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
DEBUGASSERT(stream);
- nwritten = Curl_h1_req_parse_read(&h1, buf, len, NULL, 0, err);
+ nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
if(nwritten < 0)
goto out;
- DEBUGASSERT(h1.done);
- DEBUGASSERT(h1.req);
+ if(!stream->h1.done) {
+ /* need more data */
+ goto out;
+ }
+ DEBUGASSERT(stream->h1.req);
- *err = Curl_http_req_to_h2(&h2_headers, h1.req, data);
+ *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
if(*err) {
nwritten = -1;
goto out;
}
+ /* no longer needed */
+ Curl_h1_req_parse_free(&stream->h1);
nheader = Curl_dynhds_count(&h2_headers);
nva = malloc(sizeof(quiche_h3_header) * nheader);
@@ -975,16 +1028,16 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
if(QUICHE_H3_ERR_STREAM_BLOCKED == stream3_id) {
/* quiche seems to report this error if the connection window is
* exhausted. Which happens frequently and intermittent. */
- DEBUGF(LOG_CF(data, cf, "send_request(%s) rejected with BLOCKED",
- data->state.url));
+ CURL_TRC_CF(data, cf, "send_request(%s) rejected with BLOCKED",
+ data->state.url);
stream_send_suspend(cf, data);
*err = CURLE_AGAIN;
nwritten = -1;
goto out;
}
else {
- DEBUGF(LOG_CF(data, cf, "send_request(%s) -> %" PRId64,
- data->state.url, stream3_id));
+ CURL_TRC_CF(data, cf, "send_request(%s) -> %" PRId64,
+ data->state.url, stream3_id);
}
*err = CURLE_SEND_ERROR;
nwritten = -1;
@@ -997,13 +1050,18 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
stream->closed = FALSE;
stream->reset = FALSE;
- infof(data, "Using HTTP/3 Stream ID: %" PRId64, stream3_id);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] opened for %s",
- stream3_id, data->state.url));
+ if(Curl_trc_is_verbose(data)) {
+ infof(data, "[HTTP/3] [%" PRId64 "] OPENED stream for %s",
+ stream->id, data->state.url);
+ for(i = 0; i < nheader; ++i) {
+ infof(data, "[HTTP/3] [%" PRId64 "] [%.*s: %.*s]", stream->id,
+ (int)nva[i].name_len, nva[i].name,
+ (int)nva[i].value_len, nva[i].value);
+ }
+ }
out:
free(nva);
- Curl_h1_req_parse_free(&h1);
Curl_dynhds_free(&h2_headers);
return nwritten;
}
@@ -1037,24 +1095,40 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
/* TODO: we seem to be blocked on flow control and should HOLD
* sending. But when do we open again? */
if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] send_body(len=%zu) "
- "-> window exhausted", stream->id, len));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
+ "-> window exhausted", stream->id, len);
stream_send_suspend(cf, data);
}
*err = CURLE_AGAIN;
nwritten = -1;
goto out;
}
+ else if(nwritten == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE &&
+ stream->closed && stream->resp_hds_complete) {
+ /* sending request body on a stream that has been closed by the
+ * server. If the server has send us a final response, we should
+ * silently discard the send data.
+ * This happens for example on redirects where the server, instead
+ * of reading the full request body just closed the stream after
+ * sending the 30x response.
+ * This is sort of a race: had the transfer loop called recv first,
+ * it would see the response and stop/discard sending on its own- */
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] discarding data"
+ "on closed stream with response", stream->id);
+ *err = CURLE_OK;
+ nwritten = (ssize_t)len;
+ goto out;
+ }
else if(nwritten == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] send_body(len=%zu) "
- "-> exceeds size", stream->id, len));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
+ "-> exceeds size", stream->id, len);
*err = CURLE_SEND_ERROR;
nwritten = -1;
goto out;
}
else if(nwritten < 0) {
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] send_body(len=%zu) "
- "-> quiche err %zd", stream->id, len, nwritten));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
+ "-> quiche err %zd", stream->id, len, nwritten);
*err = CURLE_SEND_ERROR;
nwritten = -1;
goto out;
@@ -1068,9 +1142,9 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
if(stream->upload_left == 0)
stream->send_closed = TRUE;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] send body(len=%zu, "
- "left=%" CURL_FORMAT_CURL_OFF_T ") -> %zd",
- stream->id, len, stream->upload_left, nwritten));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] send body(len=%zu, "
+ "left=%" CURL_FORMAT_CURL_OFF_T ") -> %zd",
+ stream->id, len, stream->upload_left, nwritten);
*err = CURLE_OK;
}
}
@@ -1081,8 +1155,8 @@ out:
*err = result;
nwritten = -1;
}
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
- stream? stream->id : -1, len, nwritten, *err));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
+ stream? stream->id : -1, len, nwritten, *err);
return nwritten;
}
@@ -1171,16 +1245,20 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
stream->upload_left = 0;
body[0] = 'X';
sent = cf_quiche_send(cf, data, body, 0, &result);
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] DONE_SEND -> %zd, %d",
- stream->id, sent, result));
+ CURL_TRC_CF(data, cf, "[%"PRId64"] DONE_SEND -> %zd, %d",
+ stream->id, sent, result);
}
break;
}
- case CF_CTRL_DATA_IDLE:
- result = cf_flush_egress(cf, data);
- if(result)
- DEBUGF(LOG_CF(data, cf, "data idle, flush egress -> %d", result));
+ case CF_CTRL_DATA_IDLE: {
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ if(stream && !stream->closed) {
+ result = cf_flush_egress(cf, data);
+ if(result)
+ CURL_TRC_CF(data, cf, "data idle, flush egress -> %d", result);
+ }
break;
+ }
default:
break;
}
@@ -1210,7 +1288,7 @@ static CURLcode cf_verify_peer(struct Curl_cfilter *cf,
goto out;
}
else
- DEBUGF(LOG_CF(data, cf, "Skipped certificate verification"));
+ CURL_TRC_CF(data, cf, "Skipped certificate verification");
ctx->h3config = quiche_h3_config_new();
if(!ctx->h3config) {
@@ -1298,15 +1376,9 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
DEBUGASSERT(!ctx->ssl);
DEBUGASSERT(!ctx->sslctx);
- ctx->sslctx = quic_ssl_ctx(data);
- if(!ctx->sslctx)
- return CURLE_QUIC_CONNECT_ERROR;
- ctx->ssl = SSL_new(ctx->sslctx);
- if(!ctx->ssl)
- return CURLE_QUIC_CONNECT_ERROR;
-
- SSL_set_app_data(ctx->ssl, cf);
- SSL_set_tlsext_host_name(ctx->ssl, cf->conn->host.name);
+ result = quic_ssl_setup(cf, data);
+ if(result)
+ return result;
result = Curl_rand(data, ctx->scid, sizeof(ctx->scid));
if(result)
@@ -1357,8 +1429,8 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
offset += 1 + alpn_len;
}
- DEBUGF(LOG_CF(data, cf, "Sent QUIC client Initial, ALPN: %s",
- alpn_protocols + 1));
+ CURL_TRC_CF(data, cf, "Sent QUIC client Initial, ALPN: %s",
+ alpn_protocols + 1);
}
return CURLE_OK;
@@ -1389,7 +1461,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
/* Not time yet to attempt the next connect */
- DEBUGF(LOG_CF(data, cf, "waiting for reconnect time"));
+ CURL_TRC_CF(data, cf, "waiting for reconnect time");
goto out;
}
@@ -1412,12 +1484,12 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
goto out;
if(quiche_conn_is_established(ctx->qconn)) {
- DEBUGF(LOG_CF(data, cf, "handshake complete after %dms",
- (int)Curl_timediff(now, ctx->started_at)));
+ CURL_TRC_CF(data, cf, "handshake complete after %dms",
+ (int)Curl_timediff(now, ctx->started_at));
ctx->handshake_at = now;
result = cf_verify_peer(cf, data);
if(!result) {
- DEBUGF(LOG_CF(data, cf, "peer verified"));
+ CURL_TRC_CF(data, cf, "peer verified");
cf->connected = TRUE;
cf->conn->alpn = CURL_HTTP_VERSION_3;
*done = TRUE;
@@ -1436,8 +1508,8 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
*/
int reconn_delay_ms = 200;
- DEBUGF(LOG_CF(data, cf, "connect, remote closed, reconnect after %dms",
- reconn_delay_ms));
+ CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms",
+ reconn_delay_ms);
Curl_conn_cf_close(cf->next, data);
cf_quiche_ctx_clear(ctx);
result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
@@ -1503,7 +1575,7 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
max_streams += quiche_conn_peer_streams_left_bidi(ctx->qconn);
}
*pres1 = (max_streams > INT_MAX)? INT_MAX : (int)max_streams;
- DEBUGF(LOG_CF(data, cf, "query: MAX_CONCURRENT -> %d", *pres1));
+ CURL_TRC_CF(data, cf, "query: MAX_CONCURRENT -> %d", *pres1);
return CURLE_OK;
}
case CF_QUERY_CONNECT_REPLY_MS:
diff --git a/libs/libcurl/src/vquic/vquic.c b/libs/libcurl/src/vquic/vquic.c
index 2cf802bd76..e49b6567ad 100644
--- a/libs/libcurl/src/vquic/vquic.c
+++ b/libs/libcurl/src/vquic/vquic.c
@@ -43,12 +43,14 @@
#include "bufq.h"
#include "dynbuf.h"
#include "cfilters.h"
-#include "curl_log.h"
+#include "curl_trc.h"
#include "curl_msh3.h"
#include "curl_ngtcp2.h"
#include "curl_quiche.h"
+#include "rand.h"
#include "vquic.h"
#include "vquic_int.h"
+#include "strerror.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -88,6 +90,16 @@ CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx)
#else
qctx->no_gso = TRUE;
#endif
+#ifdef DEBUGBUILD
+ {
+ char *p = getenv("CURL_DBG_QUIC_WBLOCK");
+ if(p) {
+ long l = strtol(p, NULL, 10);
+ if(l >= 0 && l <= 100)
+ qctx->wblock_percent = (int)l;
+ }
+ }
+#endif
return CURLE_OK;
}
@@ -230,6 +242,17 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
const uint8_t *pkt, size_t pktlen,
size_t gsolen, size_t *psent)
{
+#ifdef DEBUGBUILD
+ /* simulate network blocking/partial writes */
+ if(qctx->wblock_percent > 0) {
+ unsigned char c;
+ Curl_rand(data, &c, 1);
+ if(c >= ((100-qctx->wblock_percent)*256/100)) {
+ CURL_TRC_CF(data, cf, "vquic_flush() simulate EWOULDBLOCK");
+ return CURLE_AGAIN;
+ }
+ }
+#endif
if(qctx->no_gso && pktlen > gsolen) {
return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
}
@@ -253,11 +276,9 @@ CURLcode vquic_flush(struct Curl_cfilter *cf, struct Curl_easy *data,
blen = qctx->split_len;
}
- DEBUGF(LOG_CF(data, cf, "vquic_send(len=%zu, gso=%zu)",
- blen, gsolen));
result = vquic_send_packets(cf, data, qctx, buf, blen, gsolen, &sent);
- DEBUGF(LOG_CF(data, cf, "vquic_send(len=%zu, gso=%zu) -> %d, sent=%zu",
- blen, gsolen, result, sent));
+ CURL_TRC_CF(data, cf, "vquic_send(len=%zu, gso=%zu) -> %d, sent=%zu",
+ blen, gsolen, result, sent);
if(result) {
if(result == CURLE_AGAIN) {
Curl_bufq_skip(&qctx->sendbuf, sent);
@@ -288,9 +309,9 @@ CURLcode vquic_send_tail_split(struct Curl_cfilter *cf, struct Curl_easy *data,
qctx->split_len = Curl_bufq_len(&qctx->sendbuf) - tail_len;
qctx->split_gsolen = gsolen;
qctx->gsolen = tail_gsolen;
- DEBUGF(LOG_CF(data, cf, "vquic_send_tail_split: [%zu gso=%zu][%zu gso=%zu]",
- qctx->split_len, qctx->split_gsolen,
- tail_len, qctx->gsolen));
+ CURL_TRC_CF(data, cf, "vquic_send_tail_split: [%zu gso=%zu][%zu gso=%zu]",
+ qctx->split_len, qctx->split_gsolen,
+ tail_len, qctx->gsolen);
return vquic_flush(cf, data, qctx);
}
@@ -308,6 +329,7 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
struct sockaddr_storage remote_addr[MMSG_NUM];
size_t total_nread, pkts;
int mcount, i, n;
+ char errstr[STRERROR_LEN];
CURLcode result = CURLE_OK;
DEBUGASSERT(max_pkts > 0);
@@ -330,12 +352,12 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
;
if(mcount == -1) {
if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
- DEBUGF(LOG_CF(data, cf, "ingress, recvmmsg -> EAGAIN"));
+ CURL_TRC_CF(data, cf, "ingress, recvmmsg -> EAGAIN");
goto out;
}
if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
- const char *r_ip;
- int r_port;
+ const char *r_ip = NULL;
+ int r_port = 0;
Curl_cf_socket_peek(cf->next, data, NULL, NULL,
&r_ip, &r_port, NULL, NULL);
failf(data, "QUIC: connection to %s port %u refused",
@@ -343,13 +365,14 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
result = CURLE_COULDNT_CONNECT;
goto out;
}
- failf(data, "QUIC: recvmsg() unexpectedly returned %d (errno=%d)",
- mcount, SOCKERRNO);
+ Curl_strerror(SOCKERRNO, errstr, sizeof(errstr));
+ failf(data, "QUIC: recvmsg() unexpectedly returned %d (errno=%d; %s)",
+ mcount, SOCKERRNO, errstr);
result = CURLE_RECV_ERROR;
goto out;
}
- DEBUGF(LOG_CF(data, cf, "recvmmsg() -> %d packets", mcount));
+ CURL_TRC_CF(data, cf, "recvmmsg() -> %d packets", mcount);
pkts += mcount;
for(i = 0; i < mcount; ++i) {
total_nread += mmsg[i].msg_len;
@@ -362,8 +385,9 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
}
out:
- DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
- pkts, total_nread, result));
+ if(total_nread || result)
+ CURL_TRC_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
+ pkts, total_nread, result);
return result;
}
@@ -380,6 +404,7 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
struct sockaddr_storage remote_addr;
size_t total_nread, pkts;
ssize_t nread;
+ char errstr[STRERROR_LEN];
CURLcode result = CURLE_OK;
msg_iov.iov_base = buf;
@@ -401,8 +426,8 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
goto out;
}
if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
- const char *r_ip;
- int r_port;
+ const char *r_ip = NULL;
+ int r_port = 0;
Curl_cf_socket_peek(cf->next, data, NULL, NULL,
&r_ip, &r_port, NULL, NULL);
failf(data, "QUIC: connection to %s port %u refused",
@@ -410,8 +435,9 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
result = CURLE_COULDNT_CONNECT;
goto out;
}
- failf(data, "QUIC: recvmsg() unexpectedly returned %zd (errno=%d)",
- nread, SOCKERRNO);
+ Curl_strerror(SOCKERRNO, errstr, sizeof(errstr));
+ failf(data, "QUIC: recvmsg() unexpectedly returned %zd (errno=%d; %s)",
+ nread, SOCKERRNO, errstr);
result = CURLE_RECV_ERROR;
goto out;
}
@@ -425,8 +451,9 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
}
out:
- DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
- pkts, total_nread, result));
+ if(total_nread || result)
+ CURL_TRC_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
+ pkts, total_nread, result);
return result;
}
@@ -443,6 +470,7 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf,
socklen_t remote_addrlen = sizeof(remote_addr);
size_t total_nread, pkts;
ssize_t nread;
+ char errstr[STRERROR_LEN];
CURLcode result = CURLE_OK;
DEBUGASSERT(max_pkts > 0);
@@ -454,12 +482,12 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf,
;
if(nread == -1) {
if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
- DEBUGF(LOG_CF(data, cf, "ingress, recvfrom -> EAGAIN"));
+ CURL_TRC_CF(data, cf, "ingress, recvfrom -> EAGAIN");
goto out;
}
if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
- const char *r_ip;
- int r_port;
+ const char *r_ip = NULL;
+ int r_port = 0;
Curl_cf_socket_peek(cf->next, data, NULL, NULL,
&r_ip, &r_port, NULL, NULL);
failf(data, "QUIC: connection to %s port %u refused",
@@ -467,8 +495,9 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf,
result = CURLE_COULDNT_CONNECT;
goto out;
}
- failf(data, "QUIC: recvfrom() unexpectedly returned %zd (errno=%d)",
- nread, SOCKERRNO);
+ Curl_strerror(SOCKERRNO, errstr, sizeof(errstr));
+ failf(data, "QUIC: recvfrom() unexpectedly returned %zd (errno=%d; %s)",
+ nread, SOCKERRNO, errstr);
result = CURLE_RECV_ERROR;
goto out;
}
@@ -482,8 +511,9 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf,
}
out:
- DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
- pkts, total_nread, result));
+ if(total_nread || result)
+ CURL_TRC_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
+ pkts, total_nread, result);
return result;
}
#endif /* !HAVE_SENDMMSG && !HAVE_SENDMSG */
diff --git a/libs/libcurl/src/vquic/vquic_int.h b/libs/libcurl/src/vquic/vquic_int.h
index 6c137fc494..3fe06fb9c9 100644
--- a/libs/libcurl/src/vquic/vquic_int.h
+++ b/libs/libcurl/src/vquic/vquic_int.h
@@ -41,6 +41,9 @@ struct cf_quic_ctx {
size_t gsolen; /* length of individual packets in send buf */
size_t split_len; /* if != 0, buffer length after which GSO differs */
size_t split_gsolen; /* length of individual packets after split_len */
+#ifdef DEBUGBUILD
+ int wblock_percent; /* percent of writes doing EAGAIN */
+#endif
bool no_gso; /* do not use gso on sending */
};
diff --git a/libs/libcurl/src/vssh/libssh.c b/libs/libcurl/src/vssh/libssh.c
index aae6f5aa54..94a5659055 100644
--- a/libs/libcurl/src/vssh/libssh.c
+++ b/libs/libcurl/src/vssh/libssh.c
@@ -40,9 +40,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_UTSNAME_H
-#include <sys/utsname.h>
-#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
@@ -2186,7 +2183,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
myssh_setup_connection(data, conn);
/* We default to persistent connections. We set this already in this connect
- function to make the re-use checks properly be able to check this bit. */
+ function to make the reuse checks properly be able to check this bit. */
connkeep(conn, "SSH default");
if(conn->handler->protocol & CURLPROTO_SCP) {
diff --git a/libs/libcurl/src/vssh/libssh2.c b/libs/libcurl/src/vssh/libssh2.c
index 0cb7a8b0a7..6894b78307 100644
--- a/libs/libcurl/src/vssh/libssh2.c
+++ b/libs/libcurl/src/vssh/libssh2.c
@@ -43,9 +43,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_UTSNAME_H
-#include <sys/utsname.h>
-#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
@@ -2537,7 +2534,8 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(from > size) {
failf(data, "Offset (%"
CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
- CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize);
+ CURL_FORMAT_CURL_OFF_T ")", from,
+ (curl_off_t)attrs.filesize);
return CURLE_BAD_DOWNLOAD_RESUME;
}
if(from > to) {
@@ -2563,7 +2561,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
failf(data, "Offset (%"
CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
CURL_FORMAT_CURL_OFF_T ")",
- data->state.resume_from, attrs.filesize);
+ data->state.resume_from, (curl_off_t)attrs.filesize);
return CURLE_BAD_DOWNLOAD_RESUME;
}
/* download from where? */
@@ -2573,7 +2571,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if((curl_off_t)attrs.filesize < data->state.resume_from) {
failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
- data->state.resume_from, attrs.filesize);
+ data->state.resume_from, (curl_off_t)attrs.filesize);
return CURLE_BAD_DOWNLOAD_RESUME;
}
}
@@ -3254,7 +3252,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
}
/* We default to persistent connections. We set this already in this connect
- function to make the re-use checks properly be able to check this bit. */
+ function to make the reuse checks properly be able to check this bit. */
connkeep(conn, "SSH default");
sshc = &conn->proto.sshc;
diff --git a/libs/libcurl/src/vssh/wolfssh.c b/libs/libcurl/src/vssh/wolfssh.c
index f0ea484e71..78582e7849 100644
--- a/libs/libcurl/src/vssh/wolfssh.c
+++ b/libs/libcurl/src/vssh/wolfssh.c
@@ -374,7 +374,7 @@ static CURLcode wssh_connect(struct Curl_easy *data, bool *done)
wssh_setup_connection(data, conn);
/* We default to persistent connections. We set this already in this connect
- function to make the re-use checks properly be able to check this bit. */
+ function to make the reuse checks properly be able to check this bit. */
connkeep(conn, "SSH default");
if(conn->handler->protocol & CURLPROTO_SCP) {
diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c
index 648588069d..33f566931c 100644
--- a/libs/libcurl/src/vtls/bearssl.c
+++ b/libs/libcurl/src/vtls/bearssl.c
@@ -587,6 +587,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
const bool verifyhost = conn_config->verifyhost;
CURLcode ret;
unsigned version_min, version_max;
+ int session_set = 0;
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -594,6 +595,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
#endif
DEBUGASSERT(backend);
+ CURL_TRC_CF(data, cf, "connect_step1");
switch(conn_config->version) {
case CURL_SSLVERSION_SSLv2:
@@ -624,38 +626,34 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR;
}
- if(ca_info_blob) {
- struct cafile_source source;
- source.type = CAFILE_SOURCE_BLOB;
- source.data = ca_info_blob->data;
- source.len = ca_info_blob->len;
+ if(verifypeer) {
+ if(ca_info_blob) {
+ struct cafile_source source;
+ source.type = CAFILE_SOURCE_BLOB;
+ source.data = ca_info_blob->data;
+ source.len = ca_info_blob->len;
- ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
- if(ret != CURLE_OK) {
- if(verifypeer) {
+ CURL_TRC_CF(data, cf, "connect_step1, load ca_info_blob");
+ ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
+ if(ret != CURLE_OK) {
failf(data, "error importing CA certificate blob");
return ret;
}
- /* Only warn if no certificate verification is required. */
- infof(data, "error importing CA certificate blob, continuing anyway");
}
- }
- if(ssl_cafile) {
- struct cafile_source source;
- source.type = CAFILE_SOURCE_PATH;
- source.data = ssl_cafile;
- source.len = 0;
+ if(ssl_cafile) {
+ struct cafile_source source;
+ source.type = CAFILE_SOURCE_PATH;
+ source.data = ssl_cafile;
+ source.len = 0;
- ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
- if(ret != CURLE_OK) {
- if(verifypeer) {
+ CURL_TRC_CF(data, cf, "connect_step1, load cafile");
+ ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
+ if(ret != CURLE_OK) {
failf(data, "error setting certificate verify locations."
" CAfile: %s", ssl_cafile);
return ret;
}
- infof(data, "error setting certificate verify locations,"
- " continuing anyway:");
}
}
@@ -669,6 +667,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
if(conn_config->cipher_list) {
/* Override the ciphers as specified. For the default cipher list see the
BearSSL source code of br_ssl_client_init_full() */
+ CURL_TRC_CF(data, cf, "connect_step1, set ciphers");
ret = bearssl_set_selected_ciphers(data, &backend->ctx.eng,
conn_config->cipher_list);
if(ret)
@@ -684,10 +683,12 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
if(ssl_config->primary.sessionid) {
void *session;
+ CURL_TRC_CF(data, cf, "connect_step1, check session cache");
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(cf, data, &session, NULL)) {
br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
- infof(data, "BearSSL: re-using session ID");
+ session_set = 1;
+ infof(data, "BearSSL: reusing session ID");
}
Curl_ssl_sessionid_unlock(data);
}
@@ -724,6 +725,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR;
}
hostname = snihost;
+ CURL_TRC_CF(data, cf, "connect_step1, SNI set");
}
/* give application a chance to interfere with SSL set up. */
@@ -738,7 +740,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
}
}
- if(!br_ssl_client_reset(&backend->ctx, hostname, 1))
+ if(!br_ssl_client_reset(&backend->ctx, hostname, session_set))
return CURLE_FAILED_INIT;
backend->active = TRUE;
@@ -747,6 +749,28 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
return CURLE_OK;
}
+static int bearssl_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+
+ if(sock == CURL_SOCKET_BAD)
+ return GETSOCK_BLANK;
+ else {
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
+ unsigned state = br_ssl_engine_current_state(&backend->ctx.eng);
+ if(state & BR_SSL_SENDREC) {
+ socks[0] = sock;
+ return GETSOCK_WRITESOCK(0);
+ }
+ }
+ socks[0] = sock;
+ return GETSOCK_READSOCK(0);
+}
+
static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
struct Curl_easy *data,
unsigned target)
@@ -798,6 +822,7 @@ static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
if(state & BR_SSL_SENDREC) {
buf = br_ssl_engine_sendrec_buf(&backend->ctx.eng, &len);
ret = Curl_conn_cf_send(cf->next, data, (char *)buf, len, &result);
+ CURL_TRC_CF(data, cf, "ssl_send(len=%zu) -> %zd, %d", len, ret, result);
if(ret <= 0) {
return result;
}
@@ -806,6 +831,7 @@ static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
else if(state & BR_SSL_RECVREC) {
buf = br_ssl_engine_recvrec_buf(&backend->ctx.eng, &len);
ret = Curl_conn_cf_recv(cf->next, data, (char *)buf, len, &result);
+ CURL_TRC_CF(data, cf, "ssl_recv(len=%zu) -> %zd, %d", len, ret, result);
if(ret == 0) {
failf(data, "SSL: EOF without close notify");
return CURLE_READ_ERROR;
@@ -827,16 +853,26 @@ static CURLcode bearssl_connect_step2(struct Curl_cfilter *cf,
CURLcode ret;
DEBUGASSERT(backend);
+ CURL_TRC_CF(data, cf, "connect_step2");
ret = bearssl_run_until(cf, data, BR_SSL_SENDAPP | BR_SSL_RECVAPP);
if(ret == CURLE_AGAIN)
return CURLE_OK;
if(ret == CURLE_OK) {
+ unsigned int tver;
if(br_ssl_engine_current_state(&backend->ctx.eng) == BR_SSL_CLOSED) {
failf(data, "SSL: connection closed during handshake");
return CURLE_SSL_CONNECT_ERROR;
}
connssl->connecting_state = ssl_connect_3;
+ /* Informational message */
+ tver = br_ssl_engine_get_version(&backend->ctx.eng);
+ if(tver == 0x0303)
+ infof(data, "SSL connection using TLSv1.2");
+ else if(tver == 0x0304)
+ infof(data, "SSL connection using TLSv1.3");
+ else
+ infof(data, "SSL connection using TLS 0x%x", tver);
}
return ret;
}
@@ -852,6 +888,7 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
DEBUGASSERT(backend);
+ CURL_TRC_CF(data, cf, "connect_step3");
if(connssl->alpn) {
const char *proto;
@@ -960,8 +997,10 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
timediff_t timeout_ms;
int what;
+ CURL_TRC_CF(data, cf, "connect_common(blocking=%d)", !nonblocking);
/* check if the connection has already been established */
if(ssl_connection_complete == connssl->state) {
+ CURL_TRC_CF(data, cf, "connect_common, connected");
*done = TRUE;
return CURLE_OK;
}
@@ -993,8 +1032,10 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
curl_socket_t readfd = ssl_connect_2_reading ==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ CURL_TRC_CF(data, cf, "connect_common, check socket");
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking?0:timeout_ms);
+ CURL_TRC_CF(data, cf, "connect_common, check socket -> %d", what);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -1169,7 +1210,7 @@ const struct Curl_ssl Curl_ssl_bearssl = {
Curl_none_cert_status_request, /* cert_status_request */
bearssl_connect, /* connect */
bearssl_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ bearssl_get_select_socks, /* getsock */
bearssl_get_internals, /* get_internals */
bearssl_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/gskit.c b/libs/libcurl/src/vtls/gskit.c
deleted file mode 100644
index 4af921092a..0000000000
--- a/libs/libcurl/src/vtls/gskit.c
+++ /dev/null
@@ -1,1329 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 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.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-#include "curl_setup.h"
-
-#ifdef USE_GSKIT
-
-#include <gskssl.h>
-#include <qsoasync.h>
-#undef HAVE_SOCKETPAIR /* because the native one isn't good enough */
-#include "socketpair.h"
-#include "strerror.h"
-
-/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
-#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
-#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
-#endif
-
-#ifndef GSK_TLSV10_CIPHER_SPECS
-#define GSK_TLSV10_CIPHER_SPECS 236
-#endif
-
-#ifndef GSK_TLSV11_CIPHER_SPECS
-#define GSK_TLSV11_CIPHER_SPECS 237
-#endif
-
-#ifndef GSK_TLSV12_CIPHER_SPECS
-#define GSK_TLSV12_CIPHER_SPECS 238
-#endif
-
-#ifndef GSK_PROTOCOL_TLSV11
-#define GSK_PROTOCOL_TLSV11 437
-#endif
-
-#ifndef GSK_PROTOCOL_TLSV12
-#define GSK_PROTOCOL_TLSV12 438
-#endif
-
-#ifndef GSK_FALSE
-#define GSK_FALSE 0
-#endif
-
-#ifndef GSK_TRUE
-#define GSK_TRUE 1
-#endif
-
-
-#include <limits.h>
-
-#include <curl/curl.h>
-#include "urldata.h"
-#include "sendf.h"
-#include "gskit.h"
-#include "vtls.h"
-#include "vtls_int.h"
-#include "connect.h" /* for the connect timeout */
-#include "select.h"
-#include "strcase.h"
-#include "timediff.h"
-#include "x509asn1.h"
-#include "curl_printf.h"
-
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
-
-
-/* Directions. */
-#define SOS_READ 0x01
-#define SOS_WRITE 0x02
-
-/* SSL version flags. */
-#define CURL_GSKPROTO_SSLV2 0
-#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
-#define CURL_GSKPROTO_SSLV3 1
-#define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3)
-#define CURL_GSKPROTO_TLSV10 2
-#define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10)
-#define CURL_GSKPROTO_TLSV11 3
-#define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11)
-#define CURL_GSKPROTO_TLSV12 4
-#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
-#define CURL_GSKPROTO_LAST 5
-
-struct gskit_ssl_backend_data {
- gsk_handle handle;
- int iocport;
- int localfd;
- int remotefd;
-};
-
-#define BACKEND ((struct gskit_ssl_backend_data *)connssl->backend)
-
-/* Supported ciphers. */
-struct gskit_cipher {
- const char *name; /* Cipher name. */
- const char *gsktoken; /* Corresponding token for GSKit String. */
- unsigned int versions; /* SSL version flags. */
-};
-
-static const struct gskit_cipher ciphertable[] = {
- { "null-md5", "01",
- CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
- CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
- { "null-sha", "02",
- CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
- CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
- { "exp-rc4-md5", "03",
- CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
- { "rc4-md5", "04",
- CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
- CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
- { "rc4-sha", "05",
- CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
- CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
- { "exp-rc2-cbc-md5", "06",
- CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
- { "exp-des-cbc-sha", "09",
- CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
- CURL_GSKPROTO_TLSV11_MASK },
- { "des-cbc3-sha", "0A",
- CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
- CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
- { "aes128-sha", "2F",
- CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
- CURL_GSKPROTO_TLSV12_MASK },
- { "aes256-sha", "35",
- CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
- CURL_GSKPROTO_TLSV12_MASK },
- { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK },
- { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK },
- { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
- { "aes128-gcm-sha256",
- "9C", CURL_GSKPROTO_TLSV12_MASK },
- { "aes256-gcm-sha384",
- "9D", CURL_GSKPROTO_TLSV12_MASK },
- { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK },
- { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK },
- { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK },
- { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK },
- { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK },
- { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK },
- { (const char *) NULL, (const char *) NULL, 0 }
-};
-
-
-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 gskit_status(struct Curl_easy *data, int rc,
- const char *procname, CURLcode defcode)
-{
- char buffer[STRERROR_LEN];
- /* Process GSKit status and map it to a CURLcode. */
- switch(rc) {
- case GSK_OK:
- case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
- return CURLE_OK;
- case GSK_KEYRING_OPEN_ERROR:
- case GSK_OS400_ERROR_NO_ACCESS:
- return CURLE_SSL_CACERT_BADFILE;
- case GSK_INSUFFICIENT_STORAGE:
- return CURLE_OUT_OF_MEMORY;
- case GSK_ERROR_BAD_V2_CIPHER:
- case GSK_ERROR_BAD_V3_CIPHER:
- case GSK_ERROR_NO_CIPHERS:
- return CURLE_SSL_CIPHER;
- case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
- case GSK_ERROR_CERT_VALIDATION:
- return CURLE_PEER_FAILED_VERIFICATION;
- case GSK_OS400_ERROR_TIMED_OUT:
- return CURLE_OPERATION_TIMEDOUT;
- case GSK_WOULD_BLOCK:
- return CURLE_AGAIN;
- case GSK_OS400_ERROR_NOT_REGISTERED:
- break;
- case GSK_ERROR_IO:
- switch(errno) {
- case ENOMEM:
- return CURLE_OUT_OF_MEMORY;
- default:
- failf(data, "%s I/O error: %s", procname,
- Curl_strerror(errno, buffer, sizeof(buffer)));
- break;
- }
- break;
- default:
- failf(data, "%s: %s", procname, gsk_strerror(rc));
- break;
- }
- return defcode;
-}
-
-
-static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
- GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
-{
- char buffer[STRERROR_LEN];
- int rc = gsk_attribute_set_enum(h, id, value);
-
- switch(rc) {
- case GSK_OK:
- return CURLE_OK;
- case GSK_ERROR_IO:
- failf(data, "gsk_attribute_set_enum() I/O error: %s",
- Curl_strerror(errno, buffer, sizeof(buffer)));
- break;
- case GSK_ATTRIBUTE_INVALID_ID:
- if(unsupported_ok)
- return CURLE_UNSUPPORTED_PROTOCOL;
- default:
- failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
- break;
- }
- return CURLE_SSL_CONNECT_ERROR;
-}
-
-
-static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
- GSK_BUF_ID id, const char *buf, bool unsupported_ok)
-{
- char buffer[STRERROR_LEN];
- int rc = gsk_attribute_set_buffer(h, id, buf, 0);
-
- switch(rc) {
- case GSK_OK:
- return CURLE_OK;
- case GSK_ERROR_IO:
- failf(data, "gsk_attribute_set_buffer() I/O error: %s",
- Curl_strerror(errno, buffer, sizeof(buffer)));
- break;
- case GSK_ATTRIBUTE_INVALID_ID:
- if(unsupported_ok)
- return CURLE_UNSUPPORTED_PROTOCOL;
- default:
- failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
- break;
- }
- return CURLE_SSL_CONNECT_ERROR;
-}
-
-
-static CURLcode set_numeric(struct Curl_easy *data,
- gsk_handle h, GSK_NUM_ID id, int value)
-{
- char buffer[STRERROR_LEN];
- int rc = gsk_attribute_set_numeric_value(h, id, value);
-
- switch(rc) {
- case GSK_OK:
- return CURLE_OK;
- case GSK_ERROR_IO:
- failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
- Curl_strerror(errno, buffer, sizeof(buffer)));
- break;
- default:
- failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
- break;
- }
- return CURLE_SSL_CONNECT_ERROR;
-}
-
-
-static CURLcode set_ciphers(struct Curl_cfilter *cf, struct Curl_easy *data,
- gsk_handle h, unsigned int *protoflags)
-{
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct connectdata *conn = data->conn;
- const char *cipherlist = conn_config->cipher_list;
- const char *clp;
- const struct gskit_cipher *ctp;
- int i;
- int l;
- bool unsupported;
- CURLcode result;
- struct {
- char *buf;
- char *ptr;
- } ciphers[CURL_GSKPROTO_LAST];
-
- /* Compile cipher list into GSKit-compatible cipher lists. */
-
- if(!cipherlist)
- return CURLE_OK;
- while(is_separator(*cipherlist)) /* Skip initial separators. */
- cipherlist++;
- if(!*cipherlist)
- return CURLE_OK;
-
- /* We allocate GSKit buffers of the same size as the input string: since
- GSKit tokens are always shorter than their cipher names, allocated buffers
- will always be large enough to accommodate the result. */
- l = strlen(cipherlist) + 1;
- memset(ciphers, 0, sizeof(ciphers));
- for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
- ciphers[i].buf = malloc(l);
- if(!ciphers[i].buf) {
- while(i--)
- free(ciphers[i].buf);
- return CURLE_OUT_OF_MEMORY;
- }
- ciphers[i].ptr = ciphers[i].buf;
- *ciphers[i].ptr = '\0';
- }
-
- /* Process each cipher in input string. */
- unsupported = FALSE;
- result = CURLE_OK;
- for(;;) {
- for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
- cipherlist++;
- l = cipherlist - clp;
- if(!l)
- break;
- /* Search the cipher in our table. */
- for(ctp = ciphertable; ctp->name; ctp++)
- if(strncasecompare(ctp->name, clp, l) && !ctp->name[l])
- break;
- if(!ctp->name) {
- failf(data, "Unknown cipher %.*s", l, clp);
- result = CURLE_SSL_CIPHER;
- }
- else {
- unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
- CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK));
- for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
- if(ctp->versions & (1 << i)) {
- strcpy(ciphers[i].ptr, ctp->gsktoken);
- ciphers[i].ptr += strlen(ctp->gsktoken);
- }
- }
- }
-
- /* Advance to next cipher name or end of string. */
- while(is_separator(*cipherlist))
- cipherlist++;
- }
-
- /* Disable protocols with empty cipher lists. */
- for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
- if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) {
- *protoflags &= ~(1 << i);
- ciphers[i].buf[0] = '\0';
- }
- }
-
- /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */
- if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) {
- result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
- ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE);
- if(result == CURLE_UNSUPPORTED_PROTOCOL) {
- result = CURLE_OK;
- if(unsupported) {
- failf(data, "TLSv1.1-only ciphers are not yet supported");
- result = CURLE_SSL_CIPHER;
- }
- }
- }
- if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
- result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
- ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE);
- if(result == CURLE_UNSUPPORTED_PROTOCOL) {
- result = CURLE_OK;
- if(unsupported) {
- failf(data, "TLSv1.2-only ciphers are not yet supported");
- result = CURLE_SSL_CIPHER;
- }
- }
- }
-
- /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to
- the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */
- if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
- result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
- ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE);
- if(result == CURLE_UNSUPPORTED_PROTOCOL) {
- result = CURLE_OK;
- strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
- ciphers[CURL_GSKPROTO_TLSV10].ptr);
- }
- }
-
- /* Set-up other ciphers. */
- if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
- result = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
- ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE);
- if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
- result = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
- ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE);
-
- /* Clean-up. */
- for(i = 0; i < CURL_GSKPROTO_LAST; i++)
- free(ciphers[i].buf);
-
- return result;
-}
-
-
-static int gskit_init(void)
-{
- /* No initialization needed. */
- return 1;
-}
-
-
-static void gskit_cleanup(void)
-{
- /* Nothing to do. */
-}
-
-
-static CURLcode init_environment(struct Curl_easy *data,
- gsk_handle *envir, const char *appid,
- const char *file, const char *label,
- const char *password)
-{
- int rc;
- CURLcode result;
- gsk_handle h;
-
- /* Creates the GSKit environment. */
-
- rc = gsk_environment_open(&h);
- switch(rc) {
- case GSK_OK:
- break;
- case GSK_INSUFFICIENT_STORAGE:
- return CURLE_OUT_OF_MEMORY;
- default:
- failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
- if(!result && appid)
- result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
- if(!result && file)
- result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
- if(!result && label)
- result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
- if(!result && password)
- result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
-
- if(!result) {
- /* Locate CAs, Client certificate and key according to our settings.
- Note: this call may be blocking for some tenths of seconds. */
- result = gskit_status(data, gsk_environment_init(h),
- "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
- if(!result) {
- *envir = h;
- return result;
- }
- }
- /* Error: rollback. */
- gsk_environment_close(&h);
- return result;
-}
-
-
-static void cancel_async_handshake(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- Qso_OverlappedIO_t cstat;
-
- (void)data;
- DEBUGASSERT(BACKEND);
-
- if(QsoCancelOperation(Curl_conn_cf_get_socket(cf, data), 0) > 0)
- QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
-}
-
-
-static void close_async_handshake(struct ssl_connect_data *connssl)
-{
- DEBUGASSERT(BACKEND);
- QsoDestroyIOCompletionPort(BACKEND->iocport);
- BACKEND->iocport = -1;
-}
-
-static int pipe_ssloverssl(struct Curl_cfilter *cf, struct Curl_easy *data,
- int directions)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
- struct ssl_connect_data *connssl_next = cf_ssl_next?
- cf_ssl_next->ctx : NULL;
- struct gskit_ssl_backend_data *backend_next;
- struct pollfd fds[2];
- int n;
- int m;
- int i;
- int ret = 0;
- char buf[CURL_MAX_WRITE_SIZE];
-
- DEBUGASSERT(BACKEND);
-
- if(!connssl_next)
- return 0; /* No SSL over SSL: OK. */
-
- DEBUGASSERT(connssl_next->backend);
- backend_next = (struct gskit_ssl_backend_data *)connssl_next->backend;
-
- n = 1;
- fds[0].fd = BACKEND->remotefd;
- fds[1].fd = Curl_conn_cf_get_socket(cf, data);
-
- if(directions & SOS_READ) {
- fds[0].events |= POLLOUT;
- }
- if(directions & SOS_WRITE) {
- n = 2;
- fds[0].events |= POLLIN;
- fds[1].events |= POLLOUT;
- }
- i = Curl_poll(fds, n, 0);
- if(i < 0)
- return -1; /* Select error. */
-
- if(fds[0].revents & POLLOUT) {
- /* Try getting data from HTTPS proxy and pipe it upstream. */
- n = 0;
- i = gsk_secure_soc_read(backend_next->handle, buf, sizeof(buf), &n);
- switch(i) {
- case GSK_OK:
- if(n) {
- i = write(BACKEND->remotefd, buf, n);
- if(i < 0)
- return -1;
- ret = 1;
- }
- break;
- case GSK_OS400_ERROR_TIMED_OUT:
- case GSK_WOULD_BLOCK:
- break;
- default:
- return -1;
- }
- }
-
- if((fds[0].revents & POLLIN) && (fds[1].revents & POLLOUT)) {
- /* Pipe data to HTTPS proxy. */
- n = read(BACKEND->remotefd, buf, sizeof(buf));
- if(n < 0)
- return -1;
- if(n) {
- i = gsk_secure_soc_write(backend_next->handle, buf, n, &m);
- if(i != GSK_OK || n != m)
- return -1;
- ret = 1;
- }
- }
-
- return ret; /* OK */
-}
-
-
-static void close_one(struct Curl_cfilter *cf, struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
-
- DEBUGASSERT(BACKEND);
- if(BACKEND->handle) {
- gskit_status(data, gsk_secure_soc_close(&BACKEND->handle),
- "gsk_secure_soc_close()", 0);
- /* Last chance to drain output. */
- while(pipe_ssloverssl(cf, data, SOS_WRITE) > 0)
- ;
- BACKEND->handle = (gsk_handle) NULL;
- if(BACKEND->localfd >= 0) {
- close(BACKEND->localfd);
- BACKEND->localfd = -1;
- }
- if(BACKEND->remotefd >= 0) {
- close(BACKEND->remotefd);
- BACKEND->remotefd = -1;
- }
- }
- if(BACKEND->iocport >= 0)
- close_async_handshake(connssl);
-}
-
-
-static ssize_t gskit_send(struct Curl_cfilter *cf, struct Curl_easy *data,
- const void *mem, size_t len, CURLcode *curlcode)
-{
- struct connectdata *conn = cf->conn;
- struct ssl_connect_data *connssl = cf->ctx;
- CURLcode cc = CURLE_SEND_ERROR;
- int written;
-
- DEBUGASSERT(BACKEND);
-
- if(pipe_ssloverssl(cf, data, SOS_WRITE) >= 0) {
- cc = gskit_status(data,
- gsk_secure_soc_write(BACKEND->handle,
- (char *) mem, (int) len, &written),
- "gsk_secure_soc_write()", CURLE_SEND_ERROR);
- if(cc == CURLE_OK)
- if(pipe_ssloverssl(cf, data, SOS_WRITE) < 0)
- cc = CURLE_SEND_ERROR;
- }
- if(cc != CURLE_OK) {
- *curlcode = cc;
- written = -1;
- }
- return (ssize_t) written; /* number of bytes */
-}
-
-
-static ssize_t gskit_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
- char *buf, size_t buffersize, CURLcode *curlcode)
-{
- struct connectdata *conn = cf->conn;
- struct ssl_connect_data *connssl = cf->ctx;
- int nread;
- CURLcode cc = CURLE_RECV_ERROR;
-
- (void)data;
- DEBUGASSERT(BACKEND);
-
- if(pipe_ssloverssl(cf, data, SOS_READ) >= 0) {
- int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
- cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
- buf, buffsize, &nread),
- "gsk_secure_soc_read()", CURLE_RECV_ERROR);
- }
- switch(cc) {
- case CURLE_OK:
- break;
- case CURLE_OPERATION_TIMEDOUT:
- cc = CURLE_AGAIN;
- default:
- *curlcode = cc;
- nread = -1;
- break;
- }
- return (ssize_t) nread;
-}
-
-static CURLcode
-set_ssl_version_min_max(unsigned int *protoflags,
- struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct connectdata *conn = data->conn;
- long ssl_version = conn_config->version;
- long ssl_version_max = conn_config->version_max;
- long i = ssl_version;
- switch(ssl_version_max) {
- case CURL_SSLVERSION_MAX_NONE:
- case CURL_SSLVERSION_MAX_DEFAULT:
- ssl_version_max = CURL_SSLVERSION_TLSv1_2;
- break;
- }
- for(; i <= (ssl_version_max >> 16); ++i) {
- switch(i) {
- case CURL_SSLVERSION_TLSv1_0:
- *protoflags |= CURL_GSKPROTO_TLSV10_MASK;
- break;
- case CURL_SSLVERSION_TLSv1_1:
- *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
- break;
- case CURL_SSLVERSION_TLSv1_2:
- *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
- break;
- case CURL_SSLVERSION_TLSv1_3:
- failf(data, "GSKit: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
-
- return CURLE_OK;
-}
-
-static CURLcode gskit_connect_step1(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
- struct ssl_connect_data *connssl_next = cf_ssl_next?
- cf_ssl_next->ctx : NULL;
- gsk_handle envir;
- CURLcode result;
- const char * const keyringfile = conn_config->CAfile;
- const char * const keyringpwd = ssl_config->key_passwd;
- const char * const keyringlabel = ssl_config->primary.clientcert;
- const long int ssl_version = conn_config->version;
- const bool verifypeer = conn_config->verifypeer;
- const char *hostname = connssl->hostname;
- const char *sni;
- unsigned int protoflags = 0;
- Qso_OverlappedIO_t commarea;
- int sockpair[2];
- static const int sobufsize = CURL_MAX_WRITE_SIZE;
-
- /* Create SSL environment, start (preferably asynchronous) handshake. */
- DEBUGASSERT(BACKEND);
-
- BACKEND->handle = (gsk_handle) NULL;
- BACKEND->iocport = -1;
- BACKEND->localfd = -1;
- BACKEND->remotefd = -1;
-
- /* GSKit supports two ways of specifying an SSL context: either by
- * application identifier (that should have been defined at the system
- * level) or by keyring file, password and certificate label.
- * Local certificate name (CURLOPT_SSLCERT) is used to hold either the
- * application identifier of the certificate label.
- * Key password (CURLOPT_KEYPASSWD) holds the keyring password.
- * It is not possible to have different keyrings for the CAs and the
- * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
- * the keyring file.
- * If no key password is given and the keyring is the system keyring,
- * application identifier mode is tried first, as recommended in IBM doc.
- */
-
- envir = (gsk_handle) NULL;
-
- if(keyringlabel && *keyringlabel && !keyringpwd &&
- !strcmp(keyringfile, CURL_CA_BUNDLE)) {
- /* Try application identifier mode. */
- init_environment(data, &envir, keyringlabel, (const char *) NULL,
- (const char *) NULL, (const char *) NULL);
- }
-
- if(!envir) {
- /* Use keyring mode. */
- result = init_environment(data, &envir, (const char *) NULL,
- keyringfile, keyringlabel, keyringpwd);
- if(result)
- return result;
- }
-
- /* Create secure session. */
- result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle),
- "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
- gsk_environment_close(&envir);
- if(result)
- return result;
-
- /* Establish a pipelining socket pair for SSL over SSL. */
- if(connssl_next) {
- if(Curl_socketpair(0, 0, 0, sockpair))
- return CURLE_SSL_CONNECT_ERROR;
- BACKEND->localfd = sockpair[0];
- BACKEND->remotefd = sockpair[1];
- setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
- (void *) &sobufsize, sizeof(sobufsize));
- setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
- (void *) &sobufsize, sizeof(sobufsize));
- setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
- (void *) &sobufsize, sizeof(sobufsize));
- setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
- (void *) &sobufsize, sizeof(sobufsize));
- curlx_nonblock(BACKEND->localfd, TRUE);
- curlx_nonblock(BACKEND->remotefd, TRUE);
- }
-
- /* Determine which SSL/TLS version should be enabled. */
- sni = hostname;
- switch(ssl_version) {
- case CURL_SSLVERSION_SSLv2:
- protoflags = CURL_GSKPROTO_SSLV2_MASK;
- sni = NULL;
- break;
- case CURL_SSLVERSION_SSLv3:
- protoflags = CURL_GSKPROTO_SSLV3_MASK;
- sni = NULL;
- break;
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- protoflags = CURL_GSKPROTO_TLSV10_MASK |
- CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
- break;
- case CURL_SSLVERSION_TLSv1_0:
- case CURL_SSLVERSION_TLSv1_1:
- case CURL_SSLVERSION_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_3:
- result = set_ssl_version_min_max(&protoflags, cf, data);
- if(result != CURLE_OK)
- return result;
- break;
- default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
- if(sni) {
- char *snihost = Curl_ssl_snihost(data, sni, NULL);
- if(!snihost) {
- failf(data, "Failed to set SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
- result = set_buffer(data, BACKEND->handle,
- GSK_SSL_EXTN_SERVERNAME_REQUEST, snihost, TRUE);
- if(result == CURLE_UNSUPPORTED_PROTOCOL)
- result = CURLE_OK;
- }
-
- /* Set session parameters. */
- if(!result) {
- /* Compute the handshake timeout. Since GSKit granularity is 1 second,
- we round up the required value. */
- timediff_t timeout = Curl_timeleft(data, NULL, TRUE);
- if(timeout < 0)
- result = CURLE_OPERATION_TIMEDOUT;
- else
- result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT,
- (timeout + 999) / 1000);
- }
- if(!result)
- result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
- if(!result)
- result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
- BACKEND->localfd: Curl_conn_cf_get_socket(cf, data));
- if(!result)
- result = set_ciphers(cf, data, BACKEND->handle, &protoflags);
- if(!protoflags) {
- failf(data, "No SSL protocol/cipher combination enabled");
- result = CURLE_SSL_CIPHER;
- }
- if(!result)
- result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
- (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
- GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
- if(!result)
- result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3,
- (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
- GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
- if(!result)
- result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1,
- (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
- GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
- if(!result) {
- result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11,
- (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
- GSK_TRUE: GSK_FALSE, TRUE);
- if(result == CURLE_UNSUPPORTED_PROTOCOL) {
- result = CURLE_OK;
- if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
- failf(data, "TLS 1.1 not yet supported");
- result = CURLE_SSL_CIPHER;
- }
- }
- }
- if(!result) {
- result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12,
- (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
- GSK_TRUE: GSK_FALSE, TRUE);
- if(result == CURLE_UNSUPPORTED_PROTOCOL) {
- result = CURLE_OK;
- if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
- failf(data, "TLS 1.2 not yet supported");
- result = CURLE_SSL_CIPHER;
- }
- }
- }
- if(!result)
- result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE,
- verifypeer? GSK_SERVER_AUTH_FULL:
- GSK_SERVER_AUTH_PASSTHRU, FALSE);
-
- if(!result) {
- /* Start handshake. Try asynchronous first. */
- memset(&commarea, 0, sizeof(commarea));
- BACKEND->iocport = QsoCreateIOCompletionPort();
- if(BACKEND->iocport != -1) {
- result = gskit_status(data,
- gsk_secure_soc_startInit(BACKEND->handle,
- BACKEND->iocport,
- &commarea),
- "gsk_secure_soc_startInit()",
- CURLE_SSL_CONNECT_ERROR);
- if(!result) {
- connssl->connecting_state = ssl_connect_2;
- return CURLE_OK;
- }
- else
- close_async_handshake(connssl);
- }
- else if(errno != ENOBUFS)
- result = gskit_status(data, GSK_ERROR_IO,
- "QsoCreateIOCompletionPort()", 0);
- else if(connssl_next) {
- /* Cannot pipeline while handshaking synchronously. */
- result = CURLE_SSL_CONNECT_ERROR;
- }
- else {
- /* No more completion port available. Use synchronous IO. */
- result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
- "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
- if(!result) {
- connssl->connecting_state = ssl_connect_3;
- return CURLE_OK;
- }
- }
- }
-
- /* Error: rollback. */
- close_one(cf, data);
- return result;
-}
-
-
-static CURLcode gskit_connect_step2(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- bool nonblocking)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- Qso_OverlappedIO_t cstat;
- struct timeval stmv;
- CURLcode result;
-
- /* Poll or wait for end of SSL asynchronous handshake. */
- DEBUGASSERT(BACKEND);
-
- for(;;) {
- timediff_t timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
- stmv.tv_sec = 0;
- stmv.tv_usec = 0;
- if(timeout_ms < 0)
- timeout_ms = 0;
- switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat,
- curlx_mstotv(&stmv, timeout_ms))) {
- case 1: /* Operation complete. */
- break;
- case -1: /* An error occurred: handshake still in progress. */
- if(errno == EINTR) {
- if(nonblocking)
- return CURLE_OK;
- continue; /* Retry. */
- }
- if(errno != ETIME) {
- char buffer[STRERROR_LEN];
- failf(data, "QsoWaitForIOCompletion() I/O error: %s",
- Curl_strerror(errno, buffer, sizeof(buffer)));
- cancel_async_handshake(cf, data);
- close_async_handshake(connssl);
- return CURLE_SSL_CONNECT_ERROR;
- }
- /* FALL INTO... */
- case 0: /* Handshake in progress, timeout occurred. */
- if(nonblocking)
- return CURLE_OK;
- cancel_async_handshake(cf, data);
- close_async_handshake(connssl);
- return CURLE_OPERATION_TIMEDOUT;
- }
- break;
- }
- result = gskit_status(data, cstat.returnValue, "SSL handshake",
- CURLE_SSL_CONNECT_ERROR);
- if(!result)
- connssl->connecting_state = ssl_connect_3;
- close_async_handshake(connssl);
- return result;
-}
-
-
-static CURLcode gskit_connect_step3(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- const gsk_cert_data_elem *cdev;
- int cdec;
- const gsk_cert_data_elem *p;
- const char *cert = (const char *) NULL;
- const char *certend = (const char *) NULL;
- const char *ptr;
- CURLcode result;
-
- /* SSL handshake done: gather certificate info and verify host. */
- DEBUGASSERT(BACKEND);
-
- if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle,
- GSK_PARTNER_CERT_INFO,
- &cdev, &cdec),
- "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
- CURLE_OK) {
- int i;
-
- infof(data, "Server certificate:");
- p = cdev;
- for(i = 0; i++ < cdec; p++)
- switch(p->cert_data_id) {
- case CERT_BODY_DER:
- cert = p->cert_data_p;
- certend = cert + cdev->cert_data_l;
- break;
- case CERT_DN_PRINTABLE:
- infof(data, "\t subject: %.*s", p->cert_data_l, p->cert_data_p);
- break;
- case CERT_ISSUER_DN_PRINTABLE:
- infof(data, "\t issuer: %.*s", p->cert_data_l, p->cert_data_p);
- break;
- case CERT_VALID_FROM:
- infof(data, "\t start date: %.*s", p->cert_data_l, p->cert_data_p);
- break;
- case CERT_VALID_TO:
- infof(data, "\t expire date: %.*s", p->cert_data_l, p->cert_data_p);
- break;
- }
- }
-
- /* Verify host. */
- result = Curl_verifyhost(cf, data, cert, certend);
- if(result)
- return result;
-
- /* The only place GSKit can get the whole CA chain is a validation
- callback where no user data pointer is available. Therefore it's not
- possible to copy this chain into our structures for CAINFO.
- However the server certificate may be available, thus we can return
- info about it. */
- if(data->set.ssl.certinfo) {
- result = Curl_ssl_init_certinfo(data, 1);
- if(result)
- return result;
-
- if(cert) {
- result = Curl_extract_certinfo(data, 0, cert, certend);
- if(result)
- return result;
- }
- }
-
- /* Check pinned public key. */
- ptr = Curl_ssl_cf_is_proxy(cf)?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
- data->set.str[STRING_SSL_PINNEDPUBLICKEY];
- if(!result && ptr) {
- struct Curl_X509certificate x509;
- struct Curl_asn1Element *p;
-
- memset(&x509, 0, sizeof(x509));
- if(Curl_parseX509(&x509, cert, certend))
- return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- p = &x509.subjectPublicKeyInfo;
- result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
- if(result) {
- failf(data, "SSL: public key does not match pinned public key");
- return result;
- }
- }
-
- connssl->connecting_state = ssl_connect_done;
- return CURLE_OK;
-}
-
-
-static CURLcode gskit_connect_common(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- bool nonblocking, bool *done)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- timediff_t timeout_ms;
- CURLcode result = CURLE_OK;
-
- *done = connssl->state == ssl_connection_complete;
- if(*done)
- return CURLE_OK;
-
- /* Step 1: create session, start handshake. */
- if(connssl->connecting_state == ssl_connect_1) {
- /* check allowed time left */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
-
- if(timeout_ms < 0) {
- /* no need to continue if time already is up */
- failf(data, "SSL connection timeout");
- result = CURLE_OPERATION_TIMEDOUT;
- }
- else
- result = gskit_connect_step1(cf, data);
- }
-
- /* Handle handshake pipelining. */
- if(!result)
- if(pipe_ssloverssl(cf, data, SOS_READ | SOS_WRITE) < 0)
- result = CURLE_SSL_CONNECT_ERROR;
-
- /* Step 2: check if handshake is over. */
- if(!result && connssl->connecting_state == ssl_connect_2) {
- /* check allowed time left */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
-
- if(timeout_ms < 0) {
- /* no need to continue if time already is up */
- failf(data, "SSL connection timeout");
- result = CURLE_OPERATION_TIMEDOUT;
- }
- else
- result = gskit_connect_step2(cf, data, nonblocking);
- }
-
- /* Handle handshake pipelining. */
- if(!result)
- if(pipe_ssloverssl(cf, data, SOS_READ | SOS_WRITE) < 0)
- result = CURLE_SSL_CONNECT_ERROR;
-
- /* Step 3: gather certificate info, verify host. */
- if(!result && connssl->connecting_state == ssl_connect_3)
- result = gskit_connect_step3(cf, data);
-
- if(result)
- close_one(cf, data);
- else if(connssl->connecting_state == ssl_connect_done) {
- connssl->state = ssl_connection_complete;
- connssl->connecting_state = ssl_connect_1;
- *done = TRUE;
- }
-
- return result;
-}
-
-
-static CURLcode gskit_connect_nonblocking(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- bool *done)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- CURLcode result;
-
- result = gskit_connect_common(cf, data, TRUE, done);
- if(*done || result)
- connssl->connecting_state = ssl_connect_1;
- return result;
-}
-
-
-static CURLcode gskit_connect(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- CURLcode result;
- bool done;
-
- connssl->connecting_state = ssl_connect_1;
- result = gskit_connect_common(cf, data, FALSE, &done);
- if(result)
- return result;
-
- DEBUGASSERT(done);
-
- return CURLE_OK;
-}
-
-
-static void gskit_close(struct Curl_cfilter *cf, struct Curl_easy *data)
-{
- close_one(cf, data);
-}
-
-
-static int gskit_shutdown(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- int what;
- int rc;
- char buf[120];
- int loop = 10; /* don't get stuck */
-
- DEBUGASSERT(BACKEND);
-
- if(!BACKEND->handle)
- return 0;
-
-#ifndef CURL_DISABLE_FTP
- if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
- return 0;
-#endif
-
- close_one(cf, data);
- rc = 0;
- what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
- SSL_SHUTDOWN_TIMEOUT);
-
- while(loop--) {
- ssize_t nread;
-
- if(what < 0) {
- /* anything that gets here is fatally bad */
- failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
- rc = -1;
- break;
- }
-
- if(!what) { /* timeout */
- failf(data, "SSL shutdown timeout");
- break;
- }
-
- /* Something to read, let's do it and hope that it is the close
- notify alert from the server. No way to gsk_secure_soc_read() now, so
- use read(). */
-
- nread = read(Curl_conn_cf_get_socket(cf, data), buf, sizeof(buf));
-
- if(nread < 0) {
- char buffer[STRERROR_LEN];
- failf(data, "read: %s", Curl_strerror(errno, buffer, sizeof(buffer)));
- rc = -1;
- }
-
- if(nread <= 0)
- break;
-
- what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data), 0);
- }
-
- return rc;
-}
-
-
-static size_t gskit_version(char *buffer, size_t size)
-{
- return msnprintf(buffer, size, "GSKit");
-}
-
-
-static int gskit_check_cxn(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- int err;
- int errlen;
-
- (void)data;
- /* The only thing that can be tested here is at the socket level. */
- DEBUGASSERT(BACKEND);
-
- if(!BACKEND->handle)
- return 0; /* connection has been closed */
-
- err = 0;
- errlen = sizeof(err);
-
- if(getsockopt(Curl_conn_cf_get_socket(cf, data), SOL_SOCKET, SO_ERROR,
- (unsigned char *) &err, &errlen) ||
- errlen != sizeof(err) || err)
- return 0; /* connection has been closed */
-
- return -1; /* connection status unknown */
-}
-
-static void *gskit_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
-{
- (void)info;
- DEBUGASSERT(BACKEND);
- return BACKEND->handle;
-}
-
-const struct Curl_ssl Curl_ssl_gskit = {
- { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
-
- SSLSUPP_CERTINFO |
- SSLSUPP_PINNEDPUBKEY,
-
- sizeof(struct gskit_ssl_backend_data),
-
- gskit_init, /* init */
- gskit_cleanup, /* cleanup */
- gskit_version, /* version */
- gskit_check_cxn, /* check_cxn */
- gskit_shutdown, /* shutdown */
- Curl_none_data_pending, /* data_pending */
- Curl_none_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
- gskit_connect, /* connect */
- gskit_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
- gskit_get_internals, /* get_internals */
- gskit_close, /* close_one */
- Curl_none_close_all, /* close_all */
- /* No session handling for GSKit */
- Curl_none_session_free, /* session_free */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
- NULL, /* sha256sum */
- NULL, /* associate_connection */
- NULL, /* disassociate_connection */
- NULL, /* free_multi_ssl_backend_data */
- gskit_recv, /* recv decrypted data */
- gskit_send, /* send data to encrypt */
-};
-
-#endif /* USE_GSKIT */
diff --git a/libs/libcurl/src/vtls/gskit.h b/libs/libcurl/src/vtls/gskit.h
deleted file mode 100644
index 462df7ef62..0000000000
--- a/libs/libcurl/src/vtls/gskit.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef HEADER_CURL_GSKIT_H
-#define HEADER_CURL_GSKIT_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 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.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-#include "curl_setup.h"
-
-/*
- * This header should only be needed to get included by vtls.c and gskit.c
- */
-
-#include "urldata.h"
-
-#ifdef USE_GSKIT
-
-extern const struct Curl_ssl Curl_ssl_gskit;
-
-#endif /* USE_GSKIT */
-
-#endif /* HEADER_CURL_GSKIT_H */
diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c
index 328e84a520..c806a08cc4 100644
--- a/libs/libcurl/src/vtls/gtls.c
+++ b/libs/libcurl/src/vtls/gtls.c
@@ -735,7 +735,7 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
ssl_sessionid, ssl_idsize);
/* Informational message */
- infof(data, "SSL re-using session ID");
+ infof(data, "SSL reusing session ID");
}
Curl_ssl_sessionid_unlock(data);
}
diff --git a/libs/libcurl/src/vtls/hostcheck.c b/libs/libcurl/src/vtls/hostcheck.c
index c2d1fb0ba1..3078ab8061 100644
--- a/libs/libcurl/src/vtls/hostcheck.c
+++ b/libs/libcurl/src/vtls/hostcheck.c
@@ -24,8 +24,7 @@
#include "curl_setup.h"
-#if defined(USE_OPENSSL) \
- || defined(USE_GSKIT) \
+#if defined(USE_OPENSSL) \
|| defined(USE_SCHANNEL)
/* these backends use functions from this file */
@@ -133,4 +132,4 @@ bool Curl_cert_hostcheck(const char *match, size_t matchlen,
return FALSE;
}
-#endif /* OPENSSL, GSKIT or schannel+wince */
+#endif /* OPENSSL or SCHANNEL */
diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c
index 4e4fe3f239..5f9414b881 100644
--- a/libs/libcurl/src/vtls/mbedtls.c
+++ b/libs/libcurl/src/vtls/mbedtls.c
@@ -165,8 +165,8 @@ static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
DEBUGASSERT(data);
nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result);
- DEBUGF(LOG_CF(data, cf, "bio_cf_out_write(len=%zu) -> %zd, err=%d",
- blen, nwritten, result));
+ CURL_TRC_CF(data, cf, "bio_cf_out_write(len=%zu) -> %zd, err=%d",
+ blen, nwritten, result);
if(nwritten < 0 && CURLE_AGAIN == result) {
nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
}
@@ -186,8 +186,8 @@ static int bio_cf_read(void *bio, unsigned char *buf, size_t blen)
return 0;
nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result);
- DEBUGF(LOG_CF(data, cf, "bio_cf_in_read(len=%zu) -> %zd, err=%d",
- blen, nread, result));
+ CURL_TRC_CF(data, cf, "bio_cf_in_read(len=%zu) -> %zd, err=%d",
+ blen, nread, result);
if(nread < 0 && CURLE_AGAIN == result) {
nread = MBEDTLS_ERR_SSL_WANT_READ;
}
@@ -619,7 +619,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
return CURLE_SSL_CONNECT_ERROR;
}
- infof(data, "mbedTLS re-using session");
+ infof(data, "mbedTLS reusing session");
}
Curl_ssl_sessionid_unlock(data);
}
diff --git a/libs/libcurl/src/vtls/nss.c b/libs/libcurl/src/vtls/nss.c
deleted file mode 100644
index 6c1df15ddb..0000000000
--- a/libs/libcurl/src/vtls/nss.c
+++ /dev/null
@@ -1,2551 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 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.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-/*
- * Source file for all NSS-specific code for the TLS/SSL layer. No code
- * but vtls.c should ever call or use these functions.
- */
-
-#include "curl_setup.h"
-
-#ifdef USE_NSS
-
-#include "urldata.h"
-#include "sendf.h"
-#include "formdata.h" /* for the boundary function */
-#include "url.h" /* for the ssl config check function */
-#include "connect.h"
-#include "strcase.h"
-#include "select.h"
-#include "vtls.h"
-#include "vtls_int.h"
-#include "llist.h"
-#include "multiif.h"
-#include "curl_printf.h"
-#include "nssg.h"
-#include <nspr.h>
-#include <nss.h>
-#include <ssl.h>
-#include <sslerr.h>
-#include <secerr.h>
-#include <secmod.h>
-#include <sslproto.h>
-#include <prtypes.h>
-#include <pk11pub.h>
-#include <prio.h>
-#include <secitem.h>
-#include <secport.h>
-#include <certdb.h>
-#include <base64.h>
-#include <cert.h>
-#include <prerror.h>
-#include <keyhi.h> /* for SECKEY_DestroyPublicKey() */
-#include <private/pprio.h> /* for PR_ImportTCPSocket */
-
-#define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH)
-
-#if NSSVERNUM >= 0x030f00 /* 3.15.0 */
-#include <ocsp.h>
-#endif
-
-#include "warnless.h"
-#include "x509asn1.h"
-
-/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
-
-#define SSL_DIR "/etc/pki/nssdb"
-
-/* enough to fit the string "PEM Token #[0|1]" */
-#define SLOTSIZE 13
-
-struct nss_ssl_backend_data {
- PRFileDesc *handle;
- char *client_nickname;
- struct Curl_easy *data;
- struct Curl_llist obj_list;
- PK11GenericObject *obj_clicert;
-};
-
-static PRLock *nss_initlock = NULL;
-static PRLock *nss_crllock = NULL;
-static PRLock *nss_findslot_lock = NULL;
-static PRLock *nss_trustload_lock = NULL;
-static struct Curl_llist nss_crl_list;
-static NSSInitContext *nss_context = NULL;
-static volatile int initialized = 0;
-
-/* type used to wrap pointers as list nodes */
-struct ptr_list_wrap {
- void *ptr;
- struct Curl_llist_element node;
-};
-
-struct cipher_s {
- const char *name;
- int num;
-};
-
-#define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \
- CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \
- ptr->type = (_type); \
- ptr->pValue = (_val); \
- ptr->ulValueLen = (_len); \
-} while(0)
-
-#define CERT_NewTempCertificate __CERT_NewTempCertificate
-
-#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0])
-static const struct cipher_s cipherlist[] = {
- /* SSL2 cipher suites */
- {"rc4", SSL_EN_RC4_128_WITH_MD5},
- {"rc4-md5", SSL_EN_RC4_128_WITH_MD5},
- {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5},
- {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5},
- {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5},
- {"des", SSL_EN_DES_64_CBC_WITH_MD5},
- {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5},
- /* SSL3/TLS cipher suites */
- {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5},
- {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA},
- {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA},
- {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA},
- {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
- {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
- {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
- {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA},
- {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA},
- {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA},
- {"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},
- {"dhe_rsa_aes_128_cbc_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
- {"dhe_rsa_aes_256_cbc_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
- {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA},
- {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA},
- /* ECC ciphers. */
- {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA},
- {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA},
- {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA},
- {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA},
- {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA},
- {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA},
- {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
- {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA},
- {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
- {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
- {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA},
- {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA},
- {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA},
- {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA},
- {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA},
- {"ecdhe_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA},
- {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
- {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
- {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
- {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
- {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA},
- {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA},
- {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA},
- {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA},
- {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA},
-#ifdef TLS_RSA_WITH_NULL_SHA256
- /* new HMAC-SHA256 cipher suites specified in RFC */
- {"rsa_null_sha_256", TLS_RSA_WITH_NULL_SHA256},
- {"rsa_aes_128_cbc_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256},
- {"rsa_aes_256_cbc_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256},
- {"dhe_rsa_aes_128_cbc_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
- {"dhe_rsa_aes_256_cbc_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
- {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
- {"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
-#endif
-#ifdef TLS_RSA_WITH_AES_128_GCM_SHA256
- /* AES GCM cipher suites in RFC 5288 and RFC 5289 */
- {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256},
- {"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
- {"dhe_dss_aes_128_gcm_sha_256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256},
- {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
- {"ecdh_ecdsa_aes_128_gcm_sha_256", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256},
- {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- {"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256},
-#endif
-#ifdef TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- /* cipher suites using SHA384 */
- {"rsa_aes_256_gcm_sha_384", TLS_RSA_WITH_AES_256_GCM_SHA384},
- {"dhe_rsa_aes_256_gcm_sha_384", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
- {"dhe_dss_aes_256_gcm_sha_384", TLS_DHE_DSS_WITH_AES_256_GCM_SHA384},
- {"ecdhe_ecdsa_aes_256_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
- {"ecdhe_rsa_aes_256_sha_384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
- {"ecdhe_ecdsa_aes_256_gcm_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
- {"ecdhe_rsa_aes_256_gcm_sha_384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
-#endif
-#ifdef TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- /* chacha20-poly1305 cipher suites */
- {"ecdhe_rsa_chacha20_poly1305_sha_256",
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
- {"ecdhe_ecdsa_chacha20_poly1305_sha_256",
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
- {"dhe_rsa_chacha20_poly1305_sha_256",
- TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
-#endif
-#ifdef TLS_AES_256_GCM_SHA384
- {"aes_128_gcm_sha_256", TLS_AES_128_GCM_SHA256},
- {"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)
-static const char *pem_library = "nsspem.dll";
-static const char *trust_library = "nssckbi.dll";
-#elif defined(__APPLE__)
-static const char *pem_library = "libnsspem.dylib";
-static const char *trust_library = "libnssckbi.dylib";
-#else
-static const char *pem_library = "libnsspem.so";
-static const char *trust_library = "libnssckbi.so";
-#endif
-
-static SECMODModule *pem_module = NULL;
-static SECMODModule *trust_module = NULL;
-
-/* NSPR I/O layer we use to detect blocking direction during SSL handshake */
-static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
-static PRIOMethods nspr_io_methods;
-
-static const char *nss_error_to_name(PRErrorCode code)
-{
- const char *name = PR_ErrorToName(code);
- if(name)
- return name;
-
- return "unknown error";
-}
-
-static void nss_print_error_message(struct Curl_easy *data, PRUint32 err)
-{
- failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
-}
-
-static char *nss_sslver_to_name(PRUint16 nssver)
-{
- switch(nssver) {
- case SSL_LIBRARY_VERSION_2:
- return strdup("SSLv2");
- case SSL_LIBRARY_VERSION_3_0:
- return strdup("SSLv3");
- case SSL_LIBRARY_VERSION_TLS_1_0:
- return strdup("TLSv1.0");
-#ifdef SSL_LIBRARY_VERSION_TLS_1_1
- case SSL_LIBRARY_VERSION_TLS_1_1:
- return strdup("TLSv1.1");
-#endif
-#ifdef SSL_LIBRARY_VERSION_TLS_1_2
- case SSL_LIBRARY_VERSION_TLS_1_2:
- return strdup("TLSv1.2");
-#endif
-#ifdef SSL_LIBRARY_VERSION_TLS_1_3
- case SSL_LIBRARY_VERSION_TLS_1_3:
- return strdup("TLSv1.3");
-#endif
- default:
- return curl_maprintf("0x%04x", nssver);
- }
-}
-
-/* the longest cipher name this supports */
-#define MAX_CIPHER_LENGTH 128
-
-static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc *model,
- const char *cipher_list)
-{
- unsigned int i;
- const char *cipher;
-
- /* use accessors to avoid dynamic linking issues after an update of NSS */
- const PRUint16 num_implemented_ciphers = SSL_GetNumImplementedCiphers();
- const PRUint16 *implemented_ciphers = SSL_GetImplementedCiphers();
- if(!implemented_ciphers)
- return SECFailure;
-
- /* First disable all ciphers. This uses a different max value in case
- * NSS adds more ciphers later we don't want them available by
- * accident
- */
- for(i = 0; i < num_implemented_ciphers; i++) {
- SSL_CipherPrefSet(model, implemented_ciphers[i], PR_FALSE);
- }
-
- cipher = cipher_list;
-
- while(cipher && cipher[0]) {
- const char *end;
- char name[MAX_CIPHER_LENGTH + 1];
- size_t len;
- bool found = FALSE;
- while((*cipher) && (ISBLANK(*cipher)))
- ++cipher;
-
- end = strpbrk(cipher, ":, ");
- if(end)
- len = end - cipher;
- else
- len = strlen(cipher);
-
- if(len > MAX_CIPHER_LENGTH) {
- failf(data, "Bad cipher list");
- return SECFailure;
- }
- else if(len) {
- memcpy(name, cipher, len);
- name[len] = 0;
-
- for(i = 0; i<NUM_OF_CIPHERS; i++) {
- if(strcasecompare(name, cipherlist[i].name)) {
- /* Enable the selected cipher */
- if(SSL_CipherPrefSet(model, cipherlist[i].num, PR_TRUE) !=
- SECSuccess) {
- failf(data, "cipher-suite not supported by NSS: %s", name);
- return SECFailure;
- }
- found = TRUE;
- break;
- }
- }
- }
-
- if(!found && len) {
- failf(data, "Unknown cipher: %s", name);
- return SECFailure;
- }
- if(end)
- cipher = ++end;
- else
- break;
- }
-
- return SECSuccess;
-}
-
-/*
- * Return true if at least one cipher-suite is enabled. Used to determine
- * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers.
- */
-static bool any_cipher_enabled(void)
-{
- unsigned int i;
-
- for(i = 0; i<NUM_OF_CIPHERS; i++) {
- PRInt32 policy = 0;
- SSL_CipherPolicyGet(cipherlist[i].num, &policy);
- if(policy)
- return TRUE;
- }
-
- return FALSE;
-}
-
-/*
- * Determine whether the nickname passed in is a filename that needs to
- * be loaded as a PEM or a regular NSS nickname.
- *
- * returns 1 for a file
- * returns 0 for not a file (NSS nickname)
- */
-static int is_file(const char *filename)
-{
- struct_stat st;
-
- if(!filename)
- return 0;
-
- if(stat(filename, &st) == 0)
- if(S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISCHR(st.st_mode))
- return 1;
-
- return 0;
-}
-
-/* Check if the given string is filename or nickname of a certificate. If the
- * given string is recognized as filename, return NULL. If the given string is
- * recognized as nickname, return a duplicated string. The returned string
- * should be later deallocated using free(). If the OOM failure occurs, we
- * return NULL, too.
- */
-static char *dup_nickname(struct Curl_easy *data, const char *str)
-{
- const char *n;
-
- if(!is_file(str))
- /* no such file exists, use the string as nickname */
- return strdup(str);
-
- /* search the first slash; we require at least one slash in a file name */
- n = strchr(str, '/');
- if(!n) {
- infof(data, "WARNING: certificate file name \"%s\" handled as nickname; "
- "please use \"./%s\" to force file name", str, str);
- return strdup(str);
- }
-
- /* we'll use the PEM reader to read the certificate from file */
- return NULL;
-}
-
-/* Lock/unlock wrapper for PK11_FindSlotByName() to work around race condition
- * in nssSlot_IsTokenPresent() causing spurious SEC_ERROR_NO_TOKEN. For more
- * details, go to <https://bugzilla.mozilla.org/1297397>.
- */
-static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
-{
- PK11SlotInfo *slot;
- PR_Lock(nss_findslot_lock);
- slot = PK11_FindSlotByName(slot_name);
- PR_Unlock(nss_findslot_lock);
- return slot;
-}
-
-/* wrap 'ptr' as list node and tail-insert into 'list' */
-static CURLcode insert_wrapped_ptr(struct Curl_llist *list, void *ptr)
-{
- struct ptr_list_wrap *wrap = malloc(sizeof(*wrap));
- if(!wrap)
- return CURLE_OUT_OF_MEMORY;
-
- wrap->ptr = ptr;
- Curl_llist_insert_next(list, list->tail, wrap, &wrap->node);
- return CURLE_OK;
-}
-
-/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
- * the call succeeds, append the object handle to the list of objects so that
- * the object can be destroyed in nss_close(). */
-static CURLcode nss_create_object(struct ssl_connect_data *connssl,
- CK_OBJECT_CLASS obj_class,
- const char *filename, bool cacert)
-{
- PK11SlotInfo *slot;
- PK11GenericObject *obj;
- CK_BBOOL cktrue = CK_TRUE;
- CK_BBOOL ckfalse = CK_FALSE;
- CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
- int attr_cnt = 0;
- CURLcode result = (cacert)
- ? CURLE_SSL_CACERT_BADFILE
- : CURLE_SSL_CERTPROBLEM;
-
- const int slot_id = (cacert) ? 0 : 1;
- char *slot_name = aprintf("PEM Token #%d", slot_id);
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
-
- DEBUGASSERT(backend);
-
- if(!slot_name)
- return CURLE_OUT_OF_MEMORY;
-
- slot = nss_find_slot_by_name(slot_name);
- free(slot_name);
- if(!slot)
- return result;
-
- PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
- PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
- PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
- (CK_ULONG)strlen(filename) + 1);
-
- if(CKO_CERTIFICATE == obj_class) {
- CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
- PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
- }
-
- /* PK11_CreateManagedGenericObject() was introduced in NSS 3.34 because
- * PK11_DestroyGenericObject() does not release resources allocated by
- * PK11_CreateGenericObject() early enough. */
- obj =
-#ifdef HAVE_PK11_CREATEMANAGEDGENERICOBJECT
- PK11_CreateManagedGenericObject
-#else
- PK11_CreateGenericObject
-#endif
- (slot, attrs, attr_cnt, PR_FALSE);
-
- PK11_FreeSlot(slot);
- if(!obj)
- return result;
-
- if(insert_wrapped_ptr(&backend->obj_list, obj) != CURLE_OK) {
- PK11_DestroyGenericObject(obj);
- return CURLE_OUT_OF_MEMORY;
- }
-
- if(!cacert && CKO_CERTIFICATE == obj_class)
- /* store reference to a client certificate */
- backend->obj_clicert = obj;
-
- return CURLE_OK;
-}
-
-/* Destroy the NSS object whose handle is given by ptr. This function is
- * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy
- * NSS objects in nss_close() */
-static void nss_destroy_object(void *user, void *ptr)
-{
- struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
- PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr;
- (void) user;
- PK11_DestroyGenericObject(obj);
- free(wrap);
-}
-
-/* same as nss_destroy_object() but for CRL items */
-static void nss_destroy_crl_item(void *user, void *ptr)
-{
- struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
- SECItem *crl_der = (SECItem *) wrap->ptr;
- (void) user;
- SECITEM_FreeItem(crl_der, PR_TRUE);
- free(wrap);
-}
-
-static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
- const char *filename, PRBool cacert)
-{
- CURLcode result = (cacert)
- ? CURLE_SSL_CACERT_BADFILE
- : CURLE_SSL_CERTPROBLEM;
-
- /* libnsspem.so leaks memory if the requested file does not exist. For more
- * details, go to <https://bugzilla.redhat.com/734760>. */
- if(is_file(filename))
- result = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert);
-
- if(!result && !cacert) {
- /* we have successfully loaded a client certificate */
- char *nickname = NULL;
- char *n = strrchr(filename, '/');
- if(n)
- n++;
-
- /* The following undocumented magic helps to avoid a SIGSEGV on call
- * of PK11_ReadRawAttribute() from SelectClientCert() when using an
- * immature version of libnsspem.so. For more details, go to
- * <https://bugzilla.redhat.com/733685>. */
- nickname = aprintf("PEM Token #1:%s", n);
- if(nickname) {
- CERTCertificate *cert = PK11_FindCertFromNickname(nickname, NULL);
- if(cert)
- CERT_DestroyCertificate(cert);
-
- free(nickname);
- }
- }
-
- return result;
-}
-
-/* add given CRL to cache if it is not already there */
-static CURLcode nss_cache_crl(SECItem *crl_der)
-{
- CERTCertDBHandle *db = CERT_GetDefaultCertDB();
- CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crl_der, 0);
- if(crl) {
- /* CRL already cached */
- SEC_DestroyCrl(crl);
- SECITEM_FreeItem(crl_der, PR_TRUE);
- return CURLE_OK;
- }
-
- /* acquire lock before call of CERT_CacheCRL() and accessing nss_crl_list */
- PR_Lock(nss_crllock);
-
- if(SECSuccess != CERT_CacheCRL(db, crl_der)) {
- /* unable to cache CRL */
- SECITEM_FreeItem(crl_der, PR_TRUE);
- PR_Unlock(nss_crllock);
- return CURLE_SSL_CRL_BADFILE;
- }
-
- /* store the CRL item so that we can free it in nss_cleanup() */
- if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
- if(SECSuccess == CERT_UncacheCRL(db, crl_der))
- SECITEM_FreeItem(crl_der, PR_TRUE);
- PR_Unlock(nss_crllock);
- return CURLE_OUT_OF_MEMORY;
- }
-
- /* we need to clear session cache, so that the CRL could take effect */
- SSL_ClearSessionCache();
- PR_Unlock(nss_crllock);
- return CURLE_OK;
-}
-
-static CURLcode nss_load_crl(const char *crlfilename)
-{
- PRFileDesc *infile;
- PRFileInfo info;
- SECItem filedata = { 0, NULL, 0 };
- SECItem *crl_der = NULL;
- char *body;
-
- infile = PR_Open(crlfilename, PR_RDONLY, 0);
- if(!infile)
- return CURLE_SSL_CRL_BADFILE;
-
- if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info))
- goto fail;
-
- if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1))
- goto fail;
-
- if(info.size != PR_Read(infile, filedata.data, info.size))
- goto fail;
-
- crl_der = SECITEM_AllocItem(NULL, NULL, 0U);
- if(!crl_der)
- goto fail;
-
- /* place a trailing zero right after the visible data */
- body = (char *)filedata.data;
- body[--filedata.len] = '\0';
-
- body = strstr(body, "-----BEGIN");
- if(body) {
- /* assume ASCII */
- char *trailer;
- char *begin = PORT_Strchr(body, '\n');
- if(!begin)
- begin = PORT_Strchr(body, '\r');
- if(!begin)
- goto fail;
-
- trailer = strstr(++begin, "-----END");
- if(!trailer)
- goto fail;
-
- /* retrieve DER from ASCII */
- *trailer = '\0';
- if(ATOB_ConvertAsciiToItem(crl_der, begin))
- goto fail;
-
- SECITEM_FreeItem(&filedata, PR_FALSE);
- }
- else
- /* assume DER */
- *crl_der = filedata;
-
- PR_Close(infile);
- return nss_cache_crl(crl_der);
-
-fail:
- PR_Close(infile);
- SECITEM_FreeItem(crl_der, PR_TRUE);
- SECITEM_FreeItem(&filedata, PR_FALSE);
- return CURLE_SSL_CRL_BADFILE;
-}
-
-static CURLcode nss_load_key(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- char *key_file)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- PK11SlotInfo *slot, *tmp;
- SECStatus status;
- CURLcode result;
-
- (void)data;
- result = nss_create_object(connssl, CKO_PRIVATE_KEY, key_file, FALSE);
- if(result) {
- PR_SetError(SEC_ERROR_BAD_KEY, 0);
- return result;
- }
-
- slot = nss_find_slot_by_name("PEM Token #1");
- if(!slot)
- return CURLE_SSL_CERTPROBLEM;
-
- /* This will force the token to be seen as re-inserted */
- tmp = SECMOD_WaitForAnyTokenEvent(pem_module, 0, 0);
- if(tmp)
- PK11_FreeSlot(tmp);
- if(!PK11_IsPresent(slot)) {
- PK11_FreeSlot(slot);
- return CURLE_SSL_CERTPROBLEM;
- }
-
- status = PK11_Authenticate(slot, PR_TRUE, ssl_config->key_passwd);
- PK11_FreeSlot(slot);
-
- return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
-}
-
-static int display_error(struct Curl_easy *data, PRInt32 err,
- const char *filename)
-{
- switch(err) {
- case SEC_ERROR_BAD_PASSWORD:
- failf(data, "Unable to load client key: Incorrect password");
- return 1;
- case SEC_ERROR_UNKNOWN_CERT:
- failf(data, "Unable to load certificate %s", filename);
- return 1;
- default:
- break;
- }
- return 0; /* The caller will print a generic error */
-}
-
-static CURLcode cert_stuff(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- char *cert_file, char *key_file)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- CURLcode result;
-
- if(cert_file) {
- result = nss_load_cert(connssl, cert_file, PR_FALSE);
- if(result) {
- const PRErrorCode err = PR_GetError();
- if(!display_error(data, err, cert_file)) {
- const char *err_name = nss_error_to_name(err);
- failf(data, "unable to load client cert: %d (%s)", err, err_name);
- }
-
- return result;
- }
- }
-
- if(key_file || (is_file(cert_file))) {
- if(key_file)
- result = nss_load_key(cf, data, key_file);
- else
- /* In case the cert file also has the key */
- result = nss_load_key(cf, data, cert_file);
- if(result) {
- const PRErrorCode err = PR_GetError();
- if(!display_error(data, err, key_file)) {
- const char *err_name = nss_error_to_name(err);
- failf(data, "unable to load client key: %d (%s)", err, err_name);
- }
-
- return result;
- }
- }
-
- return CURLE_OK;
-}
-
-static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg)
-{
- (void)slot; /* unused */
-
- if(retry || !arg)
- return NULL;
- else
- return (char *)PORT_Strdup((char *)arg);
-}
-
-/* bypass the default SSL_AuthCertificate() hook in case we do not want to
- * verify peer */
-static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
- PRBool isServer)
-{
- struct Curl_cfilter *cf = (struct Curl_cfilter *)arg;
- struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- struct Curl_easy *data = backend->data;
-
- DEBUGASSERT(data);
-#ifdef SSL_ENABLE_OCSP_STAPLING
- if(conn_config->verifystatus) {
- SECStatus cacheResult;
-
- const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
- if(!csa) {
- failf(data, "Invalid OCSP response");
- return SECFailure;
- }
-
- if(csa->len == 0) {
- failf(data, "No OCSP response received");
- return SECFailure;
- }
-
- cacheResult = CERT_CacheOCSPResponseFromSideChannel(
- CERT_GetDefaultCertDB(), SSL_PeerCertificate(fd),
- PR_Now(), &csa->items[0], arg
- );
-
- if(cacheResult != SECSuccess) {
- failf(data, "Invalid OCSP response");
- return cacheResult;
- }
- }
-#endif
-
- if(!conn_config->verifypeer) {
- infof(data, "skipping SSL peer certificate verification");
- return SECSuccess;
- }
-
- return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
-}
-
-/**
- * Inform the application that the handshake is complete.
- */
-static void HandshakeCallback(PRFileDesc *sock, void *arg)
-{
- struct Curl_cfilter *cf = (struct Curl_cfilter *)arg;
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- struct Curl_easy *data = backend->data;
- unsigned int buflenmax = 50;
- unsigned char buf[50];
- unsigned int buflen;
- SSLNextProtoState state;
-
- DEBUGASSERT(data);
- if(!connssl->alpn) {
- return;
- }
-
- if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {
-
- switch(state) {
-#if NSSVERNUM >= 0x031a00 /* 3.26.0 */
- /* used by NSS internally to implement 0-RTT */
- case SSL_NEXT_PROTO_EARLY_VALUE:
- /* fall through! */
-#endif
- case SSL_NEXT_PROTO_NO_SUPPORT:
- case SSL_NEXT_PROTO_NO_OVERLAP:
- Curl_alpn_set_negotiated(cf, data, NULL, 0);
- return;
-#ifdef SSL_ENABLE_ALPN
- case SSL_NEXT_PROTO_SELECTED:
- Curl_alpn_set_negotiated(cf, data, buf, buflen);
- break;
-#endif
- default:
- /* ignore SSL_NEXT_PROTO_NEGOTIATED */
- break;
- }
-
- }
-}
-
-#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
-static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
- PRBool *canFalseStart)
-{
- struct Curl_easy *data = (struct Curl_easy *)client_data;
-
- SSLChannelInfo channelInfo;
- SSLCipherSuiteInfo cipherInfo;
-
- SECStatus rv;
- PRBool negotiatedExtension;
-
- *canFalseStart = PR_FALSE;
-
- if(SSL_GetChannelInfo(sock, &channelInfo, sizeof(channelInfo)) != SECSuccess)
- return SECFailure;
-
- if(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
- sizeof(cipherInfo)) != SECSuccess)
- return SECFailure;
-
- /* Prevent version downgrade attacks from TLS 1.2, and avoid False Start for
- * TLS 1.3 and later. See https://bugzilla.mozilla.org/show_bug.cgi?id=861310
- */
- if(channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2)
- goto end;
-
- /* Only allow ECDHE key exchange algorithm.
- * See https://bugzilla.mozilla.org/show_bug.cgi?id=952863 */
- if(cipherInfo.keaType != ssl_kea_ecdh)
- goto end;
-
- /* Prevent downgrade attacks on the symmetric cipher. We do not allow CBC
- * mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt
- * design. See https://bugzilla.mozilla.org/show_bug.cgi?id=1109766 */
- if(cipherInfo.symCipher != ssl_calg_aes_gcm)
- goto end;
-
- /* Enforce ALPN to do False Start, as an indicator of server
- compatibility. */
- rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn,
- &negotiatedExtension);
- if(rv != SECSuccess || !negotiatedExtension) {
- rv = SSL_HandshakeNegotiatedExtension(sock, ssl_next_proto_nego_xtn,
- &negotiatedExtension);
- }
-
- if(rv != SECSuccess || !negotiatedExtension)
- goto end;
-
- *canFalseStart = PR_TRUE;
-
- infof(data, "Trying TLS False Start");
-
-end:
- return SECSuccess;
-}
-#endif
-
-static void display_cert_info(struct Curl_easy *data,
- CERTCertificate *cert)
-{
- char *subject, *issuer, *common_name;
- PRExplodedTime printableTime;
- char timeString[256];
- PRTime notBefore, notAfter;
-
- subject = CERT_NameToAscii(&cert->subject);
- issuer = CERT_NameToAscii(&cert->issuer);
- common_name = CERT_GetCommonName(&cert->subject);
- infof(data, "subject: %s", subject);
-
- CERT_GetCertTimes(cert, &notBefore, &notAfter);
- PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
- PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
- infof(data, " start date: %s", timeString);
- PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
- PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
- infof(data, " expire date: %s", timeString);
- infof(data, " common name: %s", common_name);
- infof(data, " issuer: %s", issuer);
-
- PR_Free(subject);
- PR_Free(issuer);
- PR_Free(common_name);
-}
-
-/* A number of certs that will never occur in a real server handshake */
-#define TOO_MANY_CERTS 300
-
-static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock)
-{
- CURLcode result = CURLE_OK;
- SSLChannelInfo channel;
- SSLCipherSuiteInfo suite;
- CERTCertificate *cert;
- CERTCertificate *cert2;
- CERTCertificate *cert3;
- PRTime now;
-
- if(SSL_GetChannelInfo(sock, &channel, sizeof(channel)) ==
- SECSuccess && channel.length == sizeof(channel) &&
- channel.cipherSuite) {
- if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
- &suite, sizeof(suite)) == SECSuccess) {
- infof(data, "SSL connection using %s", suite.cipherSuiteName);
- }
- }
-
- cert = SSL_PeerCertificate(sock);
- if(cert) {
- infof(data, "Server certificate:");
-
- if(!data->set.ssl.certinfo) {
- display_cert_info(data, cert);
- CERT_DestroyCertificate(cert);
- }
- else {
- /* Count certificates in chain. */
- int i = 1;
- now = PR_Now();
- if(!cert->isRoot) {
- cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
- while(cert2) {
- i++;
- if(i >= TOO_MANY_CERTS) {
- CERT_DestroyCertificate(cert2);
- failf(data, "certificate loop");
- return CURLE_SSL_CERTPROBLEM;
- }
- if(cert2->isRoot) {
- CERT_DestroyCertificate(cert2);
- break;
- }
- cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA);
- CERT_DestroyCertificate(cert2);
- cert2 = cert3;
- }
- }
-
- result = Curl_ssl_init_certinfo(data, i);
- if(!result) {
- for(i = 0; cert; cert = cert2) {
- result = Curl_extract_certinfo(data, i++, (char *)cert->derCert.data,
- (char *)cert->derCert.data +
- cert->derCert.len);
- if(result)
- break;
-
- if(cert->isRoot) {
- CERT_DestroyCertificate(cert);
- break;
- }
-
- cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
- CERT_DestroyCertificate(cert);
- }
- }
- }
- }
-
- return result;
-}
-
-static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
-{
- struct Curl_cfilter *cf = (struct Curl_cfilter *)arg;
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- struct Curl_easy *data = backend->data;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct ssl_config_data *ssl_config;
- PRErrorCode err = PR_GetError();
- CERTCertificate *cert;
-
- DEBUGASSERT(data);
- ssl_config = Curl_ssl_cf_get_config(cf, data);
- /* remember the cert verification result */
- ssl_config->certverifyresult = err;
-
- if(err == SSL_ERROR_BAD_CERT_DOMAIN && !conn_config->verifyhost)
- /* we are asked not to verify the host name */
- return SECSuccess;
-
- /* print only info about the cert, the error is printed off the callback */
- cert = SSL_PeerCertificate(sock);
- if(cert) {
- infof(data, "Server certificate:");
- display_cert_info(data, cert);
- CERT_DestroyCertificate(cert);
- }
-
- return SECFailure;
-}
-
-/**
- *
- * Check that the Peer certificate's issuer certificate matches the one found
- * by issuer_nickname. This is not exactly the way OpenSSL and GNU TLS do the
- * issuer check, so we provide comments that mimic the OpenSSL
- * X509_check_issued function (in x509v3/v3_purp.c)
- */
-static SECStatus check_issuer_cert(PRFileDesc *sock,
- char *issuer_nickname)
-{
- CERTCertificate *cert, *cert_issuer, *issuer;
- SECStatus res = SECSuccess;
- void *proto_win = NULL;
-
- cert = SSL_PeerCertificate(sock);
- cert_issuer = CERT_FindCertIssuer(cert, PR_Now(), certUsageObjectSigner);
-
- proto_win = SSL_RevealPinArg(sock);
- issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
-
- if((!cert_issuer) || (!issuer))
- res = SECFailure;
- else if(SECITEM_CompareItem(&cert_issuer->derCert,
- &issuer->derCert) != SECEqual)
- res = SECFailure;
-
- CERT_DestroyCertificate(cert);
- CERT_DestroyCertificate(issuer);
- CERT_DestroyCertificate(cert_issuer);
- return res;
-}
-
-static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
- const char *pinnedpubkey)
-{
- CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- struct Curl_easy *data = NULL;
- CERTCertificate *cert;
-
- DEBUGASSERT(backend);
- data = backend->data;
-
- if(!pinnedpubkey)
- /* no pinned public key specified */
- return CURLE_OK;
-
- /* get peer certificate */
- cert = SSL_PeerCertificate(backend->handle);
- if(cert) {
- /* extract public key from peer certificate */
- SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert);
- if(pubkey) {
- /* encode the public key as DER */
- SECItem *cert_der = PK11_DEREncodePublicKey(pubkey);
- if(cert_der) {
- /* compare the public key with the pinned public key */
- result = Curl_pin_peer_pubkey(data, pinnedpubkey, cert_der->data,
- cert_der->len);
- SECITEM_FreeItem(cert_der, PR_TRUE);
- }
- SECKEY_DestroyPublicKey(pubkey);
- }
- CERT_DestroyCertificate(cert);
- }
-
- /* report the resulting status */
- switch(result) {
- case CURLE_OK:
- infof(data, "pinned public key verified successfully");
- break;
- case CURLE_SSL_PINNEDPUBKEYNOTMATCH:
- failf(data, "failed to verify pinned public key");
- break;
- default:
- /* OOM, etc. */
- break;
- }
-
- return result;
-}
-
-/**
- *
- * Callback to pick the SSL client certificate.
- */
-static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
- struct CERTDistNamesStr *caNames,
- struct CERTCertificateStr **pRetCert,
- struct SECKEYPrivateKeyStr **pRetKey)
-{
- struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- struct Curl_easy *data = NULL;
- const char *nickname = NULL;
- static const char pem_slotname[] = "PEM Token #1";
-
- DEBUGASSERT(backend);
-
- data = backend->data;
- nickname = backend->client_nickname;
-
- if(backend->obj_clicert) {
- /* use the cert/key provided by PEM reader */
- SECItem cert_der = { 0, NULL, 0 };
- void *proto_win = SSL_RevealPinArg(sock);
- struct CERTCertificateStr *cert;
- struct SECKEYPrivateKeyStr *key;
-
- PK11SlotInfo *slot = nss_find_slot_by_name(pem_slotname);
- if(!slot) {
- failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
- return SECFailure;
- }
-
- if(PK11_ReadRawAttribute(PK11_TypeGeneric, backend->obj_clicert, CKA_VALUE,
- &cert_der) != SECSuccess) {
- failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
- PK11_FreeSlot(slot);
- return SECFailure;
- }
-
- cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win);
- SECITEM_FreeItem(&cert_der, PR_FALSE);
- if(!cert) {
- failf(data, "NSS: client certificate from file not found");
- PK11_FreeSlot(slot);
- return SECFailure;
- }
-
- key = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
- PK11_FreeSlot(slot);
- if(!key) {
- failf(data, "NSS: private key from file not found");
- CERT_DestroyCertificate(cert);
- return SECFailure;
- }
-
- infof(data, "NSS: client certificate from file");
- display_cert_info(data, cert);
-
- *pRetCert = cert;
- *pRetKey = key;
- return SECSuccess;
- }
-
- /* use the default NSS hook */
- if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
- pRetCert, pRetKey)
- || !*pRetCert) {
-
- if(!nickname)
- failf(data, "NSS: client certificate not found (nickname not "
- "specified)");
- else
- failf(data, "NSS: client certificate not found: %s", nickname);
-
- return SECFailure;
- }
-
- /* get certificate nickname if any */
- nickname = (*pRetCert)->nickname;
- if(!nickname)
- nickname = "[unknown]";
-
- if(!strncmp(nickname, pem_slotname, sizeof(pem_slotname) - 1U)) {
- failf(data, "NSS: refusing previously loaded certificate from file: %s",
- nickname);
- return SECFailure;
- }
-
- if(!*pRetKey) {
- failf(data, "NSS: private key not found for certificate: %s", nickname);
- return SECFailure;
- }
-
- infof(data, "NSS: using client certificate: %s", nickname);
- display_cert_info(data, *pRetCert);
- return SECSuccess;
-}
-
-/* update blocking direction in case of PR_WOULD_BLOCK_ERROR */
-static void nss_update_connecting_state(ssl_connect_state state, void *secret)
-{
- struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret;
- if(PR_GetError() != PR_WOULD_BLOCK_ERROR)
- /* an unrelated error is passing by */
- return;
-
- switch(connssl->connecting_state) {
- case ssl_connect_2:
- case ssl_connect_2_reading:
- case ssl_connect_2_writing:
- break;
- default:
- /* we are not called from an SSL handshake */
- return;
- }
-
- /* update the state accordingly */
- connssl->connecting_state = state;
-}
-
-/* recv() wrapper we use to detect blocking direction during SSL handshake */
-static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
- PRIntn flags, PRIntervalTime timeout)
-{
- const PRRecvFN recv_fn = fd->lower->methods->recv;
- const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout);
- if(rv < 0)
- /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
- nss_update_connecting_state(ssl_connect_2_reading, fd->secret);
- return rv;
-}
-
-/* send() wrapper we use to detect blocking direction during SSL handshake */
-static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
- PRIntn flags, PRIntervalTime timeout)
-{
- const PRSendFN send_fn = fd->lower->methods->send;
- const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout);
- if(rv < 0)
- /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
- nss_update_connecting_state(ssl_connect_2_writing, fd->secret);
- return rv;
-}
-
-/* close() wrapper to avoid assertion failure due to fd->secret != NULL */
-static PRStatus nspr_io_close(PRFileDesc *fd)
-{
- const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close;
- fd->secret = NULL;
- return close_fn(fd);
-}
-
-/* load a PKCS #11 module */
-static CURLcode nss_load_module(SECMODModule **pmod, const char *library,
- const char *name)
-{
- char *config_string;
- SECMODModule *module = *pmod;
- if(module)
- /* already loaded */
- return CURLE_OK;
-
- config_string = aprintf("library=%s name=%s", library, name);
- if(!config_string)
- return CURLE_OUT_OF_MEMORY;
-
- module = SECMOD_LoadUserModule(config_string, NULL, PR_FALSE);
- free(config_string);
-
- if(module && module->loaded) {
- /* loaded successfully */
- *pmod = module;
- return CURLE_OK;
- }
-
- if(module)
- SECMOD_DestroyModule(module);
- return CURLE_FAILED_INIT;
-}
-
-/* unload a PKCS #11 module */
-static void nss_unload_module(SECMODModule **pmod)
-{
- SECMODModule *module = *pmod;
- if(!module)
- /* not loaded */
- return;
-
- if(SECMOD_UnloadUserModule(module) != SECSuccess)
- /* unload failed */
- return;
-
- SECMOD_DestroyModule(module);
- *pmod = NULL;
-}
-
-/* data might be NULL */
-static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
-{
- NSSInitParameters initparams;
- PRErrorCode err;
- const char *err_name;
-
- if(nss_context)
- return CURLE_OK;
-
- memset((void *) &initparams, '\0', sizeof(initparams));
- initparams.length = sizeof(initparams);
-
- if(cert_dir) {
- char *certpath = aprintf("sql:%s", cert_dir);
- if(!certpath)
- return CURLE_OUT_OF_MEMORY;
-
- infof(data, "Initializing NSS with certpath: %s", certpath);
- nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
- NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
- free(certpath);
-
- if(nss_context)
- return CURLE_OK;
-
- err = PR_GetError();
- err_name = nss_error_to_name(err);
- infof(data, "Unable to initialize NSS database: %d (%s)", err, err_name);
- }
-
- infof(data, "Initializing NSS with certpath: none");
- nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
- | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
- | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
- if(nss_context)
- return CURLE_OK;
-
- err = PR_GetError();
- err_name = nss_error_to_name(err);
- failf(data, "Unable to initialize NSS: %d (%s)", err, err_name);
- return CURLE_SSL_CACERT_BADFILE;
-}
-
-/* data might be NULL */
-static CURLcode nss_setup(struct Curl_easy *data)
-{
- char *cert_dir;
- struct_stat st;
- CURLcode result;
-
- if(initialized)
- return CURLE_OK;
-
- /* list of all CRL items we need to destroy in nss_cleanup() */
- Curl_llist_init(&nss_crl_list, nss_destroy_crl_item);
-
- /* First we check if $SSL_DIR points to a valid dir */
- cert_dir = getenv("SSL_DIR");
- if(cert_dir) {
- if((stat(cert_dir, &st) != 0) ||
- (!S_ISDIR(st.st_mode))) {
- cert_dir = NULL;
- }
- }
-
- /* Now we check if the default location is a valid dir */
- if(!cert_dir) {
- if((stat(SSL_DIR, &st) == 0) &&
- (S_ISDIR(st.st_mode))) {
- cert_dir = (char *)SSL_DIR;
- }
- }
-
- if(nspr_io_identity == PR_INVALID_IO_LAYER) {
- /* allocate an identity for our own NSPR I/O layer */
- nspr_io_identity = PR_GetUniqueIdentity("libcurl");
- if(nspr_io_identity == PR_INVALID_IO_LAYER)
- return CURLE_OUT_OF_MEMORY;
-
- /* the default methods just call down to the lower I/O layer */
- memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(),
- sizeof(nspr_io_methods));
-
- /* override certain methods in the table by our wrappers */
- nspr_io_methods.recv = nspr_io_recv;
- nspr_io_methods.send = nspr_io_send;
- nspr_io_methods.close = nspr_io_close;
- }
-
- result = nss_init_core(data, cert_dir);
- if(result)
- return result;
-
- if(!any_cipher_enabled())
- NSS_SetDomesticPolicy();
-
- initialized = 1;
-
- return CURLE_OK;
-}
-
-/**
- * Global SSL init
- *
- * @retval 0 error initializing SSL
- * @retval 1 SSL initialized successfully
- */
-static int nss_init(void)
-{
- /* curl_global_init() is not thread-safe so this test is ok */
- if(!nss_initlock) {
- PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
- nss_initlock = PR_NewLock();
- nss_crllock = PR_NewLock();
- nss_findslot_lock = PR_NewLock();
- nss_trustload_lock = PR_NewLock();
- }
-
- /* We will actually initialize NSS later */
-
- return 1;
-}
-
-/* data might be NULL */
-CURLcode Curl_nss_force_init(struct Curl_easy *data)
-{
- CURLcode result;
- if(!nss_initlock) {
- if(data)
- failf(data, "unable to initialize NSS, curl_global_init() should have "
- "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL");
- return CURLE_FAILED_INIT;
- }
-
- PR_Lock(nss_initlock);
- result = nss_setup(data);
- PR_Unlock(nss_initlock);
-
- return result;
-}
-
-/* Global cleanup */
-static void nss_cleanup(void)
-{
- /* This function isn't required to be threadsafe and this is only done
- * as a safety feature.
- */
- PR_Lock(nss_initlock);
- if(initialized) {
- /* Free references to client certificates held in the SSL session cache.
- * Omitting this hampers destruction of the security module owning
- * the certificates. */
- SSL_ClearSessionCache();
-
- nss_unload_module(&pem_module);
- nss_unload_module(&trust_module);
- NSS_ShutdownContext(nss_context);
- nss_context = NULL;
- }
-
- /* destroy all CRL items */
- Curl_llist_destroy(&nss_crl_list, NULL);
-
- PR_Unlock(nss_initlock);
-
- PR_DestroyLock(nss_initlock);
- PR_DestroyLock(nss_crllock);
- PR_DestroyLock(nss_findslot_lock);
- PR_DestroyLock(nss_trustload_lock);
- nss_initlock = NULL;
-
- initialized = 0;
-}
-
-static void close_one(struct ssl_connect_data *connssl)
-{
- /* before the cleanup, check whether we are using a client certificate */
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- bool client_cert = true;
-
- DEBUGASSERT(backend);
-
- client_cert = (backend->client_nickname != NULL)
- || (backend->obj_clicert != NULL);
-
- if(backend->handle) {
- char buf[32];
- /* Maybe the server has already sent a close notify alert.
- Read it to avoid an RST on the TCP connection. */
- (void)PR_Recv(backend->handle, buf, (int)sizeof(buf), 0,
- PR_INTERVAL_NO_WAIT);
- }
-
- free(backend->client_nickname);
- backend->client_nickname = NULL;
-
- /* destroy all NSS objects in order to avoid failure of NSS shutdown */
- Curl_llist_destroy(&backend->obj_list, NULL);
- backend->obj_clicert = NULL;
-
- if(backend->handle) {
- if(client_cert)
- /* A server might require different authentication based on the
- * particular path being requested by the client. To support this
- * scenario, we must ensure that a connection will never reuse the
- * authentication data from a previous connection. */
- SSL_InvalidateSession(backend->handle);
-
- PR_Close(backend->handle);
- backend->handle = NULL;
- }
-}
-
-/*
- * This function is called when an SSL connection is closed.
- */
-static void nss_close(struct Curl_cfilter *cf, struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- (void)data;
- DEBUGASSERT(backend);
-
- if(backend->handle) {
- /* NSS closes the socket we previously handed to it, so we must mark it
- as closed to avoid double close */
- fake_sclose(cf->conn->sock[cf->sockindex]);
- cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
- }
-
- close_one(connssl);
-}
-
-/* return true if NSS can provide error code (and possibly msg) for the
- error */
-static bool is_nss_error(CURLcode err)
-{
- switch(err) {
- case CURLE_PEER_FAILED_VERIFICATION:
- case CURLE_SSL_CERTPROBLEM:
- case CURLE_SSL_CONNECT_ERROR:
- case CURLE_SSL_ISSUER_ERROR:
- return true;
-
- default:
- return false;
- }
-}
-
-/* return true if the given error code is related to a client certificate */
-static bool is_cc_error(PRInt32 err)
-{
- switch(err) {
- case SSL_ERROR_BAD_CERT_ALERT:
- case SSL_ERROR_EXPIRED_CERT_ALERT:
- case SSL_ERROR_REVOKED_CERT_ALERT:
- return true;
-
- default:
- return false;
- }
-}
-
-static CURLcode nss_load_ca_certificates(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- const char *cafile = conn_config->CAfile;
- const char *capath = conn_config->CApath;
- bool use_trust_module;
- CURLcode result = CURLE_OK;
-
- /* treat empty string as unset */
- if(cafile && !cafile[0])
- cafile = NULL;
- if(capath && !capath[0])
- capath = NULL;
-
- infof(data, " CAfile: %s", cafile ? cafile : "none");
- infof(data, " CApath: %s", capath ? capath : "none");
-
- /* load libnssckbi.so if no other trust roots were specified */
- use_trust_module = !cafile && !capath;
-
- PR_Lock(nss_trustload_lock);
- if(use_trust_module && !trust_module) {
- /* libnssckbi.so needed but not yet loaded --> load it! */
- result = nss_load_module(&trust_module, trust_library, "trust");
- infof(data, "%s %s", (result) ? "failed to load" : "loaded",
- trust_library);
- if(result == CURLE_FAILED_INIT)
- /* If libnssckbi.so is not available (or fails to load), one can still
- use CA certificates stored in NSS database. Ignore the failure. */
- result = CURLE_OK;
- }
- else if(!use_trust_module && trust_module) {
- /* libnssckbi.so not needed but already loaded --> unload it! */
- infof(data, "unloading %s", trust_library);
- nss_unload_module(&trust_module);
- }
- PR_Unlock(nss_trustload_lock);
-
- if(cafile)
- result = nss_load_cert(connssl, cafile, PR_TRUE);
-
- if(result)
- return result;
-
- if(capath) {
- struct_stat st;
- if(stat(capath, &st) == -1)
- return CURLE_SSL_CACERT_BADFILE;
-
- if(S_ISDIR(st.st_mode)) {
- PRDirEntry *entry;
- PRDir *dir = PR_OpenDir(capath);
- if(!dir)
- return CURLE_SSL_CACERT_BADFILE;
-
- while((entry =
- PR_ReadDir(dir, (PRDirFlags)(PR_SKIP_BOTH | PR_SKIP_HIDDEN)))) {
- char *fullpath = aprintf("%s/%s", capath, entry->name);
- if(!fullpath) {
- PR_CloseDir(dir);
- return CURLE_OUT_OF_MEMORY;
- }
-
- if(CURLE_OK != nss_load_cert(connssl, fullpath, PR_TRUE))
- /* This is purposefully tolerant of errors so non-PEM files can
- * be in the same directory */
- infof(data, "failed to load '%s' from CURLOPT_CAPATH", fullpath);
-
- free(fullpath);
- }
-
- PR_CloseDir(dir);
- }
- else
- infof(data, "WARNING: CURLOPT_CAPATH not a directory (%s)", capath);
- }
-
- return CURLE_OK;
-}
-
-static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version)
-{
- switch(version) {
- case CURL_SSLVERSION_SSLv2:
- *nssver = SSL_LIBRARY_VERSION_2;
- return CURLE_OK;
-
- case CURL_SSLVERSION_SSLv3:
- return CURLE_NOT_BUILT_IN;
-
- case CURL_SSLVERSION_TLSv1_0:
- *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
- return CURLE_OK;
-
- case CURL_SSLVERSION_TLSv1_1:
-#ifdef SSL_LIBRARY_VERSION_TLS_1_1
- *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
- return CURLE_OK;
-#else
- return CURLE_SSL_CONNECT_ERROR;
-#endif
-
- case CURL_SSLVERSION_TLSv1_2:
-#ifdef SSL_LIBRARY_VERSION_TLS_1_2
- *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
- return CURLE_OK;
-#else
- return CURLE_SSL_CONNECT_ERROR;
-#endif
-
- case CURL_SSLVERSION_TLSv1_3:
-#ifdef SSL_LIBRARY_VERSION_TLS_1_3
- *nssver = SSL_LIBRARY_VERSION_TLS_1_3;
- return CURLE_OK;
-#else
- return CURLE_SSL_CONNECT_ERROR;
-#endif
-
- default:
- return CURLE_SSL_CONNECT_ERROR;
- }
-}
-
-static CURLcode nss_init_sslver(SSLVersionRange *sslver,
- struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- CURLcode result;
- const long min = conn_config->version;
- const long max = conn_config->version_max;
- SSLVersionRange vrange;
-
- switch(min) {
- case CURL_SSLVERSION_TLSv1:
- case CURL_SSLVERSION_DEFAULT:
- /* Bump our minimum TLS version if NSS has stricter requirements. */
- if(SSL_VersionRangeGetDefault(ssl_variant_stream, &vrange) != SECSuccess)
- return CURLE_SSL_CONNECT_ERROR;
- if(sslver->min < vrange.min)
- sslver->min = vrange.min;
- break;
- default:
- result = nss_sslver_from_curl(&sslver->min, min);
- if(result) {
- failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
- return result;
- }
- }
-
- switch(max) {
- case CURL_SSLVERSION_MAX_NONE:
- case CURL_SSLVERSION_MAX_DEFAULT:
- break;
- default:
- result = nss_sslver_from_curl(&sslver->max, max >> 16);
- if(result) {
- failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
- return result;
- }
- }
-
- return CURLE_OK;
-}
-
-static CURLcode nss_fail_connect(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- CURLcode curlerr)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
-
- DEBUGASSERT(backend);
-
- if(is_nss_error(curlerr)) {
- /* read NSPR error code */
- PRErrorCode err = PR_GetError();
- if(is_cc_error(err))
- curlerr = CURLE_SSL_CERTPROBLEM;
-
- /* print the error number and error string */
- infof(data, "NSS error %d (%s)", err, nss_error_to_name(err));
-
- /* print a human-readable message describing the error if available */
- nss_print_error_message(data, err);
- }
-
- /* cleanup on connection failure */
- Curl_llist_destroy(&backend->obj_list, NULL);
-
- return curlerr;
-}
-
-/* Switch the SSL socket into blocking or non-blocking mode. */
-static CURLcode nss_set_blocking(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- bool blocking)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- PRSocketOptionData sock_opt;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
-
- DEBUGASSERT(backend);
-
- sock_opt.option = PR_SockOpt_Nonblocking;
- sock_opt.value.non_blocking = !blocking;
-
- if(PR_SetSocketOption(backend->handle, &sock_opt) != PR_SUCCESS)
- return nss_fail_connect(cf, data, CURLE_SSL_CONNECT_ERROR);
-
- return CURLE_OK;
-}
-
-static CURLcode nss_setup_connect(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- PRFileDesc *model = NULL;
- PRFileDesc *nspr_io = NULL;
- PRFileDesc *nspr_io_stub = NULL;
- PRBool ssl_no_cache;
- PRBool ssl_cbc_random_iv;
- curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
- struct ssl_connect_data *connssl_next = cf_ssl_next?
- cf_ssl_next->ctx : NULL;
- CURLcode result;
- bool second_layer = FALSE;
- SSLVersionRange sslver_supported;
- SSLVersionRange sslver = {
- SSL_LIBRARY_VERSION_TLS_1_0, /* min */
-#ifdef SSL_LIBRARY_VERSION_TLS_1_3
- SSL_LIBRARY_VERSION_TLS_1_3 /* max */
-#elif defined SSL_LIBRARY_VERSION_TLS_1_2
- SSL_LIBRARY_VERSION_TLS_1_2
-#elif defined SSL_LIBRARY_VERSION_TLS_1_1
- SSL_LIBRARY_VERSION_TLS_1_1
-#else
- SSL_LIBRARY_VERSION_TLS_1_0
-#endif
- };
- const char *hostname = connssl->hostname;
- char *snihost;
-
- snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost) {
- failf(data, "Failed to set SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- DEBUGASSERT(backend);
-
- backend->data = data;
-
- /* list of all NSS objects we need to destroy in nss_do_close() */
- Curl_llist_init(&backend->obj_list, nss_destroy_object);
-
- PR_Lock(nss_initlock);
- result = nss_setup(data);
- if(result) {
- PR_Unlock(nss_initlock);
- goto error;
- }
-
- PK11_SetPasswordFunc(nss_get_password);
-
- result = nss_load_module(&pem_module, pem_library, "PEM");
- PR_Unlock(nss_initlock);
- if(result == CURLE_FAILED_INIT)
- infof(data, "WARNING: failed to load NSS PEM library %s. Using "
- "OpenSSL PEM certificates will not work.", pem_library);
- else if(result)
- goto error;
-
- result = CURLE_SSL_CONNECT_ERROR;
-
- model = PR_NewTCPSocket();
- if(!model)
- goto error;
- model = SSL_ImportFD(NULL, model);
-
- if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
- goto error;
- if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
- goto error;
- if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
- goto error;
-
- /* do not use SSL cache if disabled or we are not going to verify peer */
- ssl_no_cache = (ssl_config->primary.sessionid
- && conn_config->verifypeer) ? PR_FALSE : PR_TRUE;
- if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
- goto error;
-
- /* enable/disable the requested SSL version(s) */
- if(nss_init_sslver(&sslver, cf, data) != CURLE_OK)
- goto error;
- if(SSL_VersionRangeGetSupported(ssl_variant_stream,
- &sslver_supported) != SECSuccess)
- goto error;
- if(sslver_supported.max < sslver.max && sslver_supported.max >= sslver.min) {
- char *sslver_req_str, *sslver_supp_str;
- sslver_req_str = nss_sslver_to_name(sslver.max);
- sslver_supp_str = nss_sslver_to_name(sslver_supported.max);
- if(sslver_req_str && sslver_supp_str)
- infof(data, "Falling back from %s to max supported SSL version (%s)",
- sslver_req_str, sslver_supp_str);
- free(sslver_req_str);
- free(sslver_supp_str);
- sslver.max = sslver_supported.max;
- }
- if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
- goto error;
-
- ssl_cbc_random_iv = !ssl_config->enable_beast;
-#ifdef SSL_CBC_RANDOM_IV
- /* unless the user explicitly asks to allow the protocol vulnerability, we
- use the work-around */
- if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess)
- infof(data, "WARNING: failed to set SSL_CBC_RANDOM_IV = %d",
- ssl_cbc_random_iv);
-#else
- if(ssl_cbc_random_iv)
- infof(data, "WARNING: support for SSL_CBC_RANDOM_IV not compiled in");
-#endif
-
- if(conn_config->cipher_list) {
- if(set_ciphers(data, model, conn_config->cipher_list) != SECSuccess) {
- result = CURLE_SSL_CIPHER;
- goto error;
- }
- }
-
- if(!conn_config->verifypeer && conn_config->verifyhost)
- infof(data, "WARNING: ignoring value of ssl.verifyhost");
-
- /* bypass the default SSL_AuthCertificate() hook in case we do not want to
- * verify peer */
- if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, cf) != SECSuccess)
- goto error;
-
- /* not checked yet */
- ssl_config->certverifyresult = 0;
-
- if(SSL_BadCertHook(model, BadCertHandler, cf) != SECSuccess)
- goto error;
-
- if(SSL_HandshakeCallback(model, HandshakeCallback, cf) != SECSuccess)
- goto error;
-
- {
- const CURLcode rv = nss_load_ca_certificates(cf, data);
- if((rv == CURLE_SSL_CACERT_BADFILE) && !conn_config->verifypeer)
- /* not a fatal error because we are not going to verify the peer */
- infof(data, "WARNING: CA certificates failed to load");
- else if(rv) {
- result = rv;
- goto error;
- }
- }
-
- if(ssl_config->primary.CRLfile) {
- const CURLcode rv = nss_load_crl(ssl_config->primary.CRLfile);
- if(rv) {
- result = rv;
- goto error;
- }
- infof(data, " CRLfile: %s", ssl_config->primary.CRLfile);
- }
-
- if(ssl_config->primary.clientcert) {
- char *nickname = dup_nickname(data, ssl_config->primary.clientcert);
- if(nickname) {
- /* we are not going to use libnsspem.so to read the client cert */
- backend->obj_clicert = NULL;
- }
- else {
- CURLcode rv = cert_stuff(cf, data,
- ssl_config->primary.clientcert,
- ssl_config->key);
- if(rv) {
- /* failf() is already done in cert_stuff() */
- result = rv;
- goto error;
- }
- }
-
- /* store the nickname for SelectClientCert() called during handshake */
- backend->client_nickname = nickname;
- }
- else
- backend->client_nickname = NULL;
-
- if(SSL_GetClientAuthDataHook(model, SelectClientCert,
- (void *)connssl) != SECSuccess) {
- result = CURLE_SSL_CERTPROBLEM;
- goto error;
- }
-
- /* Is there an SSL filter "in front" of us or are we writing directly
- * to the socket? */
- if(connssl_next) {
- struct nss_ssl_backend_data *backend_next =
- (struct nss_ssl_backend_data *)connssl_next->backend;
- /* The filter should be connected by now, with full handshake */
- DEBUGASSERT(backend_next->handle);
- DEBUGASSERT(ssl_connection_complete == connssl_next->state);
- /* We tell our NSS instance to use do IO with the 'next' NSS
- * instance. This NSS instance will take ownership of the next
- * one, including its destruction. We therefore need to `disown`
- * the next filter's handle, once import succeeds. */
- nspr_io = backend->handle;
- second_layer = TRUE;
- }
- else {
- /* wrap OS file descriptor by NSPR's file descriptor abstraction */
- nspr_io = PR_ImportTCPSocket(sockfd);
- if(!nspr_io)
- goto error;
- }
-
- /* create our own NSPR I/O layer */
- nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
- if(!nspr_io_stub) {
- if(!second_layer)
- PR_Close(nspr_io);
- goto error;
- }
-
- /* make the per-connection data accessible from NSPR I/O callbacks */
- nspr_io_stub->secret = (void *)connssl;
-
- /* push our new layer to the NSPR I/O stack */
- if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
- if(!second_layer)
- PR_Close(nspr_io);
- PR_Close(nspr_io_stub);
- goto error;
- }
-
- /* import our model socket onto the current I/O stack */
- backend->handle = SSL_ImportFD(model, nspr_io);
- if(!backend->handle) {
- if(!second_layer)
- PR_Close(nspr_io);
- goto error;
- }
-
- PR_Close(model); /* We don't need this any more */
- model = NULL;
- if(connssl_next) { /* steal the NSS handle we just imported successfully */
- struct nss_ssl_backend_data *backend_next =
- (struct nss_ssl_backend_data *)connssl_next->backend;
- backend_next->handle = NULL;
- }
-
- /* This is the password associated with the cert that we're using */
- if(ssl_config->key_passwd) {
- SSL_SetPKCS11PinArg(backend->handle, ssl_config->key_passwd);
- }
-
-#ifdef SSL_ENABLE_OCSP_STAPLING
- if(conn_config->verifystatus) {
- if(SSL_OptionSet(backend->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
- != SECSuccess)
- goto error;
- }
-#endif
-
-#ifdef SSL_ENABLE_ALPN
- if(SSL_OptionSet(backend->handle, SSL_ENABLE_ALPN,
- connssl->alpn ? PR_TRUE : PR_FALSE)
- != SECSuccess)
- goto error;
-#endif
-
-#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
- if(data->set.ssl.falsestart) {
- if(SSL_OptionSet(backend->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
- != SECSuccess)
- goto error;
-
- if(SSL_SetCanFalseStartCallback(backend->handle, CanFalseStartCallback,
- data) != SECSuccess)
- goto error;
- }
-#endif
-
-#if defined(SSL_ENABLE_ALPN)
- if(connssl->alpn) {
- struct alpn_proto_buf proto;
-
- result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
- if(result || SSL_SetNextProtoNego(backend->handle, proto.data, proto.len)
- != SECSuccess) {
- failf(data, "Error setting ALPN");
- goto error;
- }
- Curl_alpn_to_proto_str(&proto, connssl->alpn);
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
- }
-#endif
-
-
- /* Force handshake on next I/O */
- if(SSL_ResetHandshake(backend->handle, /* asServer */ PR_FALSE)
- != SECSuccess)
- goto error;
-
- /* propagate hostname to the TLS layer */
- if(SSL_SetURL(backend->handle, snihost) != SECSuccess)
- goto error;
-
- /* prevent NSS from re-using the session for a different hostname */
- if(SSL_SetSockPeerID(backend->handle, snihost) != SECSuccess)
- goto error;
-
- return CURLE_OK;
-
-error:
- if(model)
- PR_Close(model);
-
- return nss_fail_connect(cf, data, result);
-}
-
-static CURLcode nss_do_connect(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- CURLcode result = CURLE_SSL_CONNECT_ERROR;
- PRUint32 timeout;
-
- /* check timeout situation */
- const timediff_t time_left = Curl_timeleft(data, NULL, TRUE);
- if(time_left < 0) {
- failf(data, "timed out before SSL handshake");
- result = CURLE_OPERATION_TIMEDOUT;
- goto error;
- }
-
- DEBUGASSERT(backend);
-
- /* Force the handshake now */
- timeout = PR_MillisecondsToInterval((PRUint32) time_left);
- if(SSL_ForceHandshakeWithTimeout(backend->handle, timeout) != SECSuccess) {
- if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
- /* blocking direction is updated by nss_update_connecting_state() */
- return CURLE_AGAIN;
- else if(ssl_config->certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
- result = CURLE_PEER_FAILED_VERIFICATION;
- else if(ssl_config->certverifyresult)
- result = CURLE_PEER_FAILED_VERIFICATION;
- goto error;
- }
-
- result = display_conn_info(data, backend->handle);
- if(result)
- goto error;
-
- if(conn_config->issuercert) {
- SECStatus ret = SECFailure;
- char *nickname = dup_nickname(data, conn_config->issuercert);
- if(nickname) {
- /* we support only nicknames in case of issuercert for now */
- ret = check_issuer_cert(backend->handle, nickname);
- free(nickname);
- }
-
- if(SECFailure == ret) {
- infof(data, "SSL certificate issuer check failed");
- result = CURLE_SSL_ISSUER_ERROR;
- goto error;
- }
- else {
- infof(data, "SSL certificate issuer check ok");
- }
- }
-
- result = cmp_peer_pubkey(connssl, Curl_ssl_cf_is_proxy(cf)?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
- data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
- if(result)
- /* status already printed */
- goto error;
-
- return CURLE_OK;
-
-error:
- return nss_fail_connect(cf, data, result);
-}
-
-static CURLcode nss_connect_common(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- bool *done)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- const bool blocking = (done == NULL);
- CURLcode result;
-
- if(connssl->state == ssl_connection_complete) {
- if(!blocking)
- *done = TRUE;
- return CURLE_OK;
- }
-
- if(connssl->connecting_state == ssl_connect_1) {
- result = nss_setup_connect(cf, data);
- if(result)
- /* we do not expect CURLE_AGAIN from nss_setup_connect() */
- return result;
-
- connssl->connecting_state = ssl_connect_2;
- }
-
- /* enable/disable blocking mode before handshake */
- result = nss_set_blocking(cf, data, blocking);
- if(result)
- return result;
-
- result = nss_do_connect(cf, data);
- switch(result) {
- case CURLE_OK:
- break;
- case CURLE_AGAIN:
- /* CURLE_AGAIN in non-blocking mode is not an error */
- if(!blocking)
- return CURLE_OK;
- else
- return result;
- default:
- return result;
- }
-
- if(blocking) {
- /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
- result = nss_set_blocking(cf, data, /* blocking */ FALSE);
- if(result)
- return result;
- }
- else
- /* signal completed SSL handshake */
- *done = TRUE;
-
- connssl->state = ssl_connection_complete;
-
- /* ssl_connect_done is never used outside, go back to the initial state */
- connssl->connecting_state = ssl_connect_1;
-
- return CURLE_OK;
-}
-
-static CURLcode nss_connect(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- return nss_connect_common(cf, data, /* blocking */ NULL);
-}
-
-static CURLcode nss_connect_nonblocking(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- bool *done)
-{
- return nss_connect_common(cf, data, done);
-}
-
-static ssize_t nss_send(struct Curl_cfilter *cf,
- struct Curl_easy *data, /* transfer */
- const void *mem, /* send this data */
- size_t len, /* amount to write */
- CURLcode *curlcode)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- ssize_t rc;
-
- (void)data;
- DEBUGASSERT(backend);
-
- /* The SelectClientCert() hook uses this for infof() and failf() but the
- handle stored in nss_setup_connect() could have already been freed. */
- backend->data = data;
-
- rc = PR_Send(backend->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
- if(rc < 0) {
- PRInt32 err = PR_GetError();
- if(err == PR_WOULD_BLOCK_ERROR)
- *curlcode = CURLE_AGAIN;
- else {
- /* print the error number and error string */
- const char *err_name = nss_error_to_name(err);
- infof(data, "SSL write: error %d (%s)", err, err_name);
-
- /* print a human-readable message describing the error if available */
- nss_print_error_message(data, err);
-
- *curlcode = (is_cc_error(err))
- ? CURLE_SSL_CERTPROBLEM
- : CURLE_SEND_ERROR;
- }
-
- return -1;
- }
-
- return rc; /* number of bytes */
-}
-
-static bool
-nss_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- PRFileDesc *fd = backend->handle->lower;
- char buf;
-
- (void) data;
-
- /* Returns true in case of error to force reading. */
- return PR_Recv(fd, (void *) &buf, 1, PR_MSG_PEEK, PR_INTERVAL_NO_WAIT) != 0;
-}
-
-static ssize_t nss_recv(struct Curl_cfilter *cf,
- struct Curl_easy *data, /* transfer */
- char *buf, /* store read data here */
- size_t buffersize, /* max amount to read */
- CURLcode *curlcode)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- ssize_t nread;
-
- (void)data;
- DEBUGASSERT(backend);
-
- /* The SelectClientCert() hook uses this for infof() and failf() but the
- handle stored in nss_setup_connect() could have already been freed. */
- backend->data = data;
-
- nread = PR_Recv(backend->handle, buf, (int)buffersize, 0,
- PR_INTERVAL_NO_WAIT);
- if(nread < 0) {
- /* failed SSL read */
- PRInt32 err = PR_GetError();
-
- if(err == PR_WOULD_BLOCK_ERROR)
- *curlcode = CURLE_AGAIN;
- else {
- /* print the error number and error string */
- const char *err_name = nss_error_to_name(err);
- infof(data, "SSL read: errno %d (%s)", err, err_name);
-
- /* print a human-readable message describing the error if available */
- nss_print_error_message(data, err);
-
- *curlcode = (is_cc_error(err))
- ? CURLE_SSL_CERTPROBLEM
- : CURLE_RECV_ERROR;
- }
-
- return -1;
- }
-
- return nread;
-}
-
-static size_t nss_version(char *buffer, size_t size)
-{
- return msnprintf(buffer, size, "NSS/%s", NSS_GetVersion());
-}
-
-/* data might be NULL */
-static int Curl_nss_seed(struct Curl_easy *data)
-{
- /* make sure that NSS is initialized */
- return !!Curl_nss_force_init(data);
-}
-
-/* data might be NULL */
-static CURLcode nss_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
-{
- Curl_nss_seed(data); /* Initiate the seed if not already done */
-
- if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length)))
- /* signal a failure */
- return CURLE_FAILED_INIT;
-
- return CURLE_OK;
-}
-
-static CURLcode nss_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
-{
- PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
- unsigned int SHA256out;
-
- if(!SHA256pw)
- return CURLE_NOT_BUILT_IN;
-
- PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen));
- PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len));
- PK11_DestroyContext(SHA256pw, PR_TRUE);
-
- return CURLE_OK;
-}
-
-static bool nss_cert_status_request(void)
-{
-#ifdef SSL_ENABLE_OCSP_STAPLING
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
-static bool nss_false_start(void)
-{
-#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
-static void *nss_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
-{
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
- (void)info;
- DEBUGASSERT(backend);
- return backend->handle;
-}
-
-static bool nss_attach_data(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
-
- if(!backend->data)
- backend->data = data;
- return TRUE;
-}
-
-static void nss_detach_data(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct nss_ssl_backend_data *backend =
- (struct nss_ssl_backend_data *)connssl->backend;
-
- if(backend->data == data)
- backend->data = NULL;
-}
-
-const struct Curl_ssl Curl_ssl_nss = {
- { CURLSSLBACKEND_NSS, "nss" }, /* info */
-
- SSLSUPP_CA_PATH |
- SSLSUPP_CERTINFO |
- SSLSUPP_PINNEDPUBKEY |
- SSLSUPP_HTTPS_PROXY,
-
- sizeof(struct nss_ssl_backend_data),
-
- nss_init, /* init */
- nss_cleanup, /* cleanup */
- nss_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
- /* NSS has no shutdown function provided and thus always fail */
- Curl_none_shutdown, /* shutdown */
- nss_data_pending, /* data_pending */
- nss_random, /* random */
- nss_cert_status_request, /* cert_status_request */
- nss_connect, /* connect */
- nss_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
- nss_get_internals, /* get_internals */
- nss_close, /* close_one */
- Curl_none_close_all, /* close_all */
- /* NSS has its own session ID cache */
- Curl_none_session_free, /* session_free */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- nss_false_start, /* false_start */
- nss_sha256sum, /* sha256sum */
- nss_attach_data, /* associate_connection */
- nss_detach_data, /* disassociate_connection */
- NULL, /* free_multi_ssl_backend_data */
- nss_recv, /* recv decrypted data */
- nss_send, /* send data to encrypt */
-};
-
-#endif /* USE_NSS */
diff --git a/libs/libcurl/src/vtls/nssg.h b/libs/libcurl/src/vtls/nssg.h
deleted file mode 100644
index 451e41052b..0000000000
--- a/libs/libcurl/src/vtls/nssg.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef HEADER_CURL_NSSG_H
-#define HEADER_CURL_NSSG_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 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.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-#include "curl_setup.h"
-
-#ifdef USE_NSS
-/*
- * This header should only be needed to get included by vtls.c and nss.c
- */
-
-#include "urldata.h"
-
-/* initialize NSS library if not already */
-CURLcode Curl_nss_force_init(struct Curl_easy *data);
-
-extern const struct Curl_ssl Curl_ssl_nss;
-
-#endif /* USE_NSS */
-#endif /* HEADER_CURL_NSSG_H */
diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c
index 1b48688d1c..577069f040 100644
--- a/libs/libcurl/src/vtls/openssl.c
+++ b/libs/libcurl/src/vtls/openssl.c
@@ -190,11 +190,12 @@
* Whether SSL_CTX_set_keylog_callback is available.
* OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
* BoringSSL: supported since d28f59c27bac (committed 2015-11-19)
- * LibreSSL: unsupported in at least 2.7.2 (explicitly check for it since it
- * lies and pretends to be OpenSSL 2.0.0).
+ * LibreSSL: supported since 3.5.0 (released 2022-02-24)
*/
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
!defined(LIBRESSL_VERSION_NUMBER)) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER >= 0x3050000fL) || \
defined(OPENSSL_IS_BORINGSSL)
#define HAVE_KEYLOG_CALLBACK
#endif
@@ -202,11 +203,13 @@
/* Whether SSL_CTX_set_ciphersuites is available.
* OpenSSL: supported since 1.1.1 (commit a53b5be6a05)
* BoringSSL: no
- * LibreSSL: no
+ * LibreSSL: supported since 3.4.1 (released 2021-10-14)
*/
-#if ((OPENSSL_VERSION_NUMBER >= 0x10101000L) && \
- !defined(LIBRESSL_VERSION_NUMBER) && \
- !defined(OPENSSL_IS_BORINGSSL))
+#if ((OPENSSL_VERSION_NUMBER >= 0x10101000L && \
+ !defined(LIBRESSL_VERSION_NUMBER)) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER >= 0x3040100fL)) && \
+ !defined(OPENSSL_IS_BORINGSSL)
#define HAVE_SSL_CTX_SET_CIPHERSUITES
#if !defined(OPENSSL_IS_AWSLC)
#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
@@ -266,7 +269,7 @@
#define HAVE_OPENSSL_VERSION
#endif
-#ifdef OPENSSL_IS_BORINGSSL
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
typedef uint32_t sslerr_t;
#else
typedef unsigned long sslerr_t;
@@ -722,8 +725,8 @@ static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
DEBUGASSERT(data);
nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
- DEBUGF(LOG_CF(data, cf, "bio_cf_out_write(len=%d) -> %d, err=%d",
- blen, (int)nwritten, result));
+ CURL_TRC_CF(data, cf, "bio_cf_out_write(len=%d) -> %d, err=%d",
+ blen, (int)nwritten, result);
BIO_clear_retry_flags(bio);
backend->io_result = result;
if(nwritten < 0) {
@@ -749,8 +752,8 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
return 0;
nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
- DEBUGF(LOG_CF(data, cf, "bio_cf_in_read(len=%d) -> %d, err=%d",
- blen, (int)nread, result));
+ CURL_TRC_CF(data, cf, "bio_cf_in_read(len=%d) -> %d, err=%d",
+ blen, (int)nread, result);
BIO_clear_retry_flags(bio);
backend->io_result = result;
if(nread < 0) {
@@ -996,20 +999,6 @@ static CURLcode ossl_seed(struct Curl_easy *data)
return CURLE_OK;
#endif
-#if defined(HAVE_RAND_EGD) && defined(EGD_SOCKET)
- /* available in OpenSSL 0.9.5 and later */
- /* EGD_SOCKET is set at configure time or not at all */
- {
- /* If there's an option and a define, the option overrides the
- define */
- int ret = RAND_egd(EGD_SOCKET);
- if(-1 != ret) {
- if(rand_enough())
- return CURLE_OK;
- }
- }
-#endif
-
/* fallback to a custom seeding of the PRNG using a hash based on a current
time */
do {
@@ -1705,7 +1694,7 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
static int ossl_init(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
+ (!defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)
const uint64_t flags =
#ifdef OPENSSL_INIT_ENGINE_ALL_BUILTIN
/* not present in BoringSSL */
@@ -1895,6 +1884,9 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
(void)SSL_read(backend->handle, buf, (int)sizeof(buf));
(void)SSL_shutdown(backend->handle);
+
+ ERR_clear_error();
+
SSL_set_connect_state(backend->handle);
}
@@ -2320,7 +2312,11 @@ static CURLcode verifystatus(struct Curl_cfilter *cf,
{
struct ssl_connect_data *connssl = cf->ctx;
int i, ocsp_status;
+#if defined(OPENSSL_IS_AWSLC)
+ const uint8_t *status;
+#else
unsigned char *status;
+#endif
const unsigned char *p;
CURLcode result = CURLE_OK;
OCSP_RESPONSE *rsp = NULL;
@@ -2418,7 +2414,7 @@ static CURLcode verifystatus(struct Curl_cfilter *cf,
goto end;
}
- for(i = 0; i < sk_X509_num(ch); i++) {
+ for(i = 0; i < (int)sk_X509_num(ch); i++) {
X509 *issuer = sk_X509_value(ch, i);
if(X509_check_issued(issuer, cert) == X509_V_OK) {
id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
@@ -3716,6 +3712,15 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
/* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) {
+ /* When a user callback is installed to modify the SSL_CTX,
+ * we need to do the full initialization before calling it.
+ * See: #11800 */
+ if(!backend->x509_store_setup) {
+ result = Curl_ssl_setup_x509_store(cf, data, backend->ctx);
+ if(result)
+ return result;
+ backend->x509_store_setup = TRUE;
+ }
Curl_set_in_callback(data, true);
result = (*data->set.ssl.fsslctx)(data, backend->ctx,
data->set.ssl.fsslctxp);
@@ -3779,7 +3784,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
- infof(data, "SSL re-using session ID");
+ infof(data, "SSL reusing session ID");
}
Curl_ssl_sessionid_unlock(data);
}
@@ -3864,7 +3869,13 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
return CURLE_OK;
}
#endif
- else if(backend->io_result == CURLE_AGAIN) {
+#ifdef SSL_ERROR_WANT_RETRY_VERIFY
+ if(SSL_ERROR_WANT_RETRY_VERIFY == detail) {
+ connssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+ }
+#endif
+ if(backend->io_result == CURLE_AGAIN) {
return CURLE_OK;
}
else {
@@ -3904,11 +3915,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
error_buffer */
strcpy(error_buffer, "SSL certificate verification failed");
}
-#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
- !defined(LIBRESSL_VERSION_NUMBER) && \
- !defined(OPENSSL_IS_BORINGSSL) && \
- !defined(OPENSSL_IS_AWSLC))
-
+#if defined(SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)
/* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on
OpenSSL version above v1.1.1, not LibreSSL, BoringSSL, or AWS-LC */
else if((lib == ERR_LIB_SSL) &&
@@ -4734,7 +4741,10 @@ static CURLcode ossl_sha256sum(const unsigned char *tmp, /* input */
mdctx = EVP_MD_CTX_create();
if(!mdctx)
return CURLE_OUT_OF_MEMORY;
- EVP_DigestInit(mdctx, EVP_sha256());
+ if(!EVP_DigestInit(mdctx, EVP_sha256())) {
+ EVP_MD_CTX_destroy(mdctx);
+ return CURLE_FAILED_INIT;
+ }
EVP_DigestUpdate(mdctx, tmp, tmplen);
EVP_DigestFinal_ex(mdctx, sha256sum, &len);
EVP_MD_CTX_destroy(mdctx);
diff --git a/libs/libcurl/src/vtls/rustls.c b/libs/libcurl/src/vtls/rustls.c
index d928b9d08a..989954bf46 100644
--- a/libs/libcurl/src/vtls/rustls.c
+++ b/libs/libcurl/src/vtls/rustls.c
@@ -104,10 +104,6 @@ read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
ret = EINVAL;
}
*out_n = (int)nread;
- /*
- DEBUGF(LOG_CF(io_ctx->data, io_ctx->cf, "cf->next recv(len=%zu) -> %zd, %d",
- len, nread, result));
- */
return ret;
}
@@ -128,7 +124,7 @@ write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
}
*out_n = (int)nwritten;
/*
- DEBUGF(LOG_CF(io_ctx->data, io_ctx->cf, "cf->next send(len=%zu) -> %zd, %d",
+ CURL_TRC_CFX(io_ctx->data, io_ctx->cf, "cf->next send(len=%zu) -> %zd, %d",
len, nwritten, result));
*/
return ret;
@@ -267,8 +263,8 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
}
out:
- DEBUGF(LOG_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d",
- plainlen, nread, *err));
+ CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d",
+ plainlen, nread, *err);
return nread;
}
@@ -302,7 +298,7 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
DEBUGASSERT(backend);
rconn = backend->conn;
- DEBUGF(LOG_CF(data, cf, "cf_send: %ld plain bytes", plainlen));
+ CURL_TRC_CF(data, cf, "cf_send: %ld plain bytes", plainlen);
io_ctx.cf = cf;
io_ctx.data = data;
@@ -327,8 +323,8 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
io_error = rustls_connection_write_tls(rconn, write_cb, &io_ctx,
&tlswritten);
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
- DEBUGF(LOG_CF(data, cf, "cf_send: EAGAIN after %zu bytes",
- tlswritten_total));
+ CURL_TRC_CF(data, cf, "cf_send: EAGAIN after %zu bytes",
+ tlswritten_total);
*err = CURLE_AGAIN;
return -1;
}
@@ -344,7 +340,7 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
*err = CURLE_WRITE_ERROR;
return -1;
}
- DEBUGF(LOG_CF(data, cf, "cf_send: wrote %zu TLS bytes", tlswritten));
+ CURL_TRC_CF(data, cf, "cf_send: wrote %zu TLS bytes", tlswritten);
tlswritten_total += tlswritten;
}
diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c
index d1b372ba47..843319e4ac 100644
--- a/libs/libcurl/src/vtls/schannel.c
+++ b/libs/libcurl/src/vtls/schannel.c
@@ -793,8 +793,11 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
backend->cred->client_cert_store = client_cert_store;
#endif
- /* Windows 10, 1809 (a.k.a. Windows 10 build 17763) */
- if(curlx_verify_windows_version(10, 0, 17763, PLATFORM_WINNT,
+ /* We support TLS 1.3 starting in Windows 10 version 1809 (OS build 17763) as
+ long as the user did not set a legacy algorithm list
+ (CURLOPT_SSL_CIPHER_LIST). */
+ if(!conn_config->cipher_list &&
+ curlx_verify_windows_version(10, 0, 17763, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL)) {
char *ciphers13 = 0;
@@ -807,9 +810,9 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
SCH_CREDENTIALS credentials = { 0 };
TLS_PARAMETERS tls_parameters = { 0 };
- CRYPTO_SETTINGS crypto_settings[4] = { 0 };
- UNICODE_STRING blocked_ccm_modes[1] = { 0 };
- UNICODE_STRING blocked_gcm_modes[1] = { 0 };
+ CRYPTO_SETTINGS crypto_settings[4] = { { 0 } };
+ UNICODE_STRING blocked_ccm_modes[1] = { { 0 } };
+ UNICODE_STRING blocked_gcm_modes[1] = { { 0 } };
int crypto_settings_idx = 0;
@@ -844,7 +847,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
/* reject too-long cipher names */
if(n > (LONGEST_ALG_ID - 1)) {
- failf(data, "Cipher name too long, not checked.");
+ failf(data, "schannel: Cipher name too long, not checked");
return CURLE_SSL_CIPHER;
}
@@ -872,7 +875,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
disable_aes_ccm_sha256 = FALSE;
}
else {
- failf(data, "Passed in an unknown TLS 1.3 cipher.");
+ failf(data, "schannel: Unknown TLS 1.3 cipher: %s", tmp);
return CURLE_SSL_CIPHER;
}
@@ -887,7 +890,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
if(disable_aes_gcm_sha384 && disable_aes_gcm_sha256
&& disable_chacha_poly && disable_aes_ccm_8_sha256
&& disable_aes_ccm_sha256) {
- failf(data, "All available TLS 1.3 ciphers were disabled.");
+ failf(data, "schannel: All available TLS 1.3 ciphers were disabled");
return CURLE_SSL_CIPHER;
}
@@ -1010,7 +1013,9 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
&backend->cred->time_stamp);
}
else {
- /* Pre-Windows 10 1809 */
+ /* Pre-Windows 10 1809 or the user set a legacy algorithm list. Although MS
+ doesn't document it, currently Schannel will not negotiate TLS 1.3 when
+ SCHANNEL_CRED is used. */
ALG_ID algIds[NUM_CIPHERS];
char *ciphers = conn_config->cipher_list;
SCHANNEL_CRED schannel_cred = { 0 };
@@ -1019,9 +1024,20 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
schannel_cred.grbitEnabledProtocols = enabled_protocols;
if(ciphers) {
+ if((enabled_protocols & SP_PROT_TLS1_3_CLIENT)) {
+ infof(data, "schannel: WARNING: This version of Schannel may "
+ "negotiate a less-secure TLS version than TLS 1.3 because the "
+ "user set an algorithm cipher list.");
+ }
+ if(conn_config->cipher_list13) {
+ failf(data, "schannel: This version of Schannel does not support "
+ "setting an algorithm cipher list and TLS 1.3 cipher list at "
+ "the same time");
+ return CURLE_SSL_CIPHER;
+ }
result = set_ssl_ciphers(&schannel_cred, ciphers, algIds);
if(CURLE_OK != result) {
- failf(data, "Unable to set ciphers to from connection ssl config");
+ failf(data, "schannel: Failed setting algorithm cipher list");
return result;
}
}
@@ -1158,7 +1174,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(cf, data, (void **)&old_cred, NULL)) {
backend->cred = old_cred;
- DEBUGF(infof(data, "schannel: re-using existing credential handle"));
+ DEBUGF(infof(data, "schannel: reusing existing credential handle"));
/* increment the reference counter of the credential/session handle */
backend->cred->refcount++;
@@ -1618,10 +1634,16 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
#ifdef HAS_MANUAL_VERIFY_API
if(conn_config->verifypeer && backend->use_manual_cred_validation) {
+ /* Certificate verification also verifies the hostname if verifyhost */
return Curl_verify_certificate(cf, data);
}
#endif
+ /* Verify the hostname manually when certificate verification is disabled,
+ because in that case Schannel won't verify it. */
+ if(!conn_config->verifypeer && conn_config->verifyhost)
+ return Curl_verify_host(cf, data);
+
return CURLE_OK;
}
@@ -1634,7 +1656,8 @@ valid_cert_encoding(const CERT_CONTEXT *cert_context)
(cert_context->cbCertEncoded > 0);
}
-typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, void *arg);
+typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context,
+ bool reverse_order, void *arg);
static void
traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func,
@@ -1642,19 +1665,32 @@ traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func,
{
const CERT_CONTEXT *current_context = NULL;
bool should_continue = true;
+ bool first = true;
+ bool reverse_order = false;
while(should_continue &&
(current_context = CertEnumCertificatesInStore(
context->hCertStore,
- current_context)) != NULL)
- should_continue = func(current_context, arg);
+ current_context)) != NULL) {
+ /* Windows 11 22H2 OS Build 22621.674 or higher enumerates certificates in
+ leaf-to-root order while all previous versions of Windows enumerate
+ certificates in root-to-leaf order. Determine the order of enumeration
+ by comparing SECPKG_ATTR_REMOTE_CERT_CONTEXT's pbCertContext with the
+ first certificate's pbCertContext. */
+ if(first && context->pbCertEncoded != current_context->pbCertEncoded)
+ reverse_order = true;
+ should_continue = func(current_context, reverse_order, arg);
+ first = false;
+ }
if(current_context)
CertFreeCertificateContext(current_context);
}
static bool
-cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count)
+cert_counter_callback(const CERT_CONTEXT *ccert_context, bool reverse_order,
+ void *certs_count)
{
+ (void)reverse_order; /* unused */
if(valid_cert_encoding(ccert_context))
(*(int *)certs_count)++;
return true;
@@ -1669,14 +1705,16 @@ struct Adder_args
};
static bool
-add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
+add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, bool reverse_order,
+ void *raw_arg)
{
struct Adder_args *args = (struct Adder_args*)raw_arg;
args->result = CURLE_OK;
if(valid_cert_encoding(ccert_context)) {
const char *beg = (const char *) ccert_context->pbCertEncoded;
const char *end = beg + ccert_context->cbCertEncoded;
- int insert_index = (args->certs_count - 1) - args->idx;
+ int insert_index = reverse_order ? (args->certs_count - 1) - args->idx :
+ args->idx;
args->result = Curl_extract_certinfo(args->data, insert_index,
beg, end);
args->idx++;
@@ -1758,7 +1796,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
}
#endif
- /* save the current session data for possible re-use */
+ /* save the current session data for possible reuse */
if(ssl_config->primary.sessionid) {
bool incache;
bool added = FALSE;
diff --git a/libs/libcurl/src/vtls/schannel.h b/libs/libcurl/src/vtls/schannel.h
index b6b9101c78..4066e9ca1b 100644
--- a/libs/libcurl/src/vtls/schannel.h
+++ b/libs/libcurl/src/vtls/schannel.h
@@ -76,6 +76,9 @@
extern const struct Curl_ssl Curl_ssl_schannel;
+CURLcode Curl_verify_host(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
struct Curl_easy *data);
diff --git a/libs/libcurl/src/vtls/schannel_int.h b/libs/libcurl/src/vtls/schannel_int.h
index e158cadc86..97fed9e660 100644
--- a/libs/libcurl/src/vtls/schannel_int.h
+++ b/libs/libcurl/src/vtls/schannel_int.h
@@ -43,6 +43,58 @@
#define HAS_CLIENT_CERT_PATH
#endif
+#ifndef CRYPT_DECODE_NOCOPY_FLAG
+#define CRYPT_DECODE_NOCOPY_FLAG 0x1
+#endif
+
+#ifndef CRYPT_DECODE_ALLOC_FLAG
+#define CRYPT_DECODE_ALLOC_FLAG 0x8000
+#endif
+
+#ifndef CERT_ALT_NAME_DNS_NAME
+#define CERT_ALT_NAME_DNS_NAME 3
+#endif
+
+#ifndef CERT_ALT_NAME_IP_ADDRESS
+#define CERT_ALT_NAME_IP_ADDRESS 8
+#endif
+
+
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+/* Original mingw is missing CERT structs or they're disabled.
+ Refer to w32api-5.0.2-mingw32-dev\include\wincrypt.h. */
+
+/* !checksrc! disable TYPEDEFSTRUCT 4 */
+typedef struct _CERT_OTHER_NAME {
+ LPSTR pszObjId;
+ CRYPT_OBJID_BLOB Value;
+} CERT_OTHER_NAME, *PCERT_OTHER_NAME;
+
+typedef struct _CERT_ALT_NAME_ENTRY {
+ DWORD dwAltNameChoice;
+ union {
+ PCERT_OTHER_NAME pOtherName;
+ LPWSTR pwszRfc822Name;
+ LPWSTR pwszDNSName;
+ CERT_NAME_BLOB DirectoryName;
+ LPWSTR pwszURL;
+ CRYPT_DATA_BLOB IPAddress;
+ LPSTR pszRegisteredID;
+ };
+} CERT_ALT_NAME_ENTRY, *PCERT_ALT_NAME_ENTRY;
+
+typedef struct _CERT_ALT_NAME_INFO {
+ DWORD cAltEntry;
+ PCERT_ALT_NAME_ENTRY rgAltEntry;
+} CERT_ALT_NAME_INFO, *PCERT_ALT_NAME_INFO;
+
+typedef struct _CRYPT_DECODE_PARA {
+ DWORD cbSize;
+ PFN_CRYPT_ALLOC pfnAlloc;
+ PFN_CRYPT_FREE pfnFree;
+} CRYPT_DECODE_PARA, *PCRYPT_DECODE_PARA;
+#endif
+
#ifndef SCH_CREDENTIALS_VERSION
#define SCH_CREDENTIALS_VERSION 0x00000005
diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c
index c8a589948a..35ce35b789 100644
--- a/libs/libcurl/src/vtls/schannel_verify.c
+++ b/libs/libcurl/src/vtls/schannel_verify.c
@@ -39,8 +39,6 @@
#include "schannel.h"
#include "schannel_int.h"
-#ifdef HAS_MANUAL_VERIFY_API
-
#include "vtls.h"
#include "vtls_int.h"
#include "sendf.h"
@@ -56,6 +54,9 @@
#define BACKEND ((struct schannel_ssl_backend_data *)connssl->backend)
+
+#ifdef HAS_MANUAL_VERIFY_API
+
#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */
#define BEGIN_CERT "-----BEGIN CERTIFICATE-----"
#define END_CERT "\n-----END CERTIFICATE-----"
@@ -330,6 +331,8 @@ cleanup:
return result;
}
+#endif /* HAS_MANUAL_VERIFY_API */
+
/*
* Returns the number of characters necessary to populate all the host_names.
* If host_names is not NULL, populate it with all the host names. Each string
@@ -353,10 +356,10 @@ static DWORD cert_get_name_string(struct Curl_easy *data,
LPTSTR current_pos = NULL;
DWORD i;
+#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
/* CERT_NAME_SEARCH_ALL_NAMES_FLAG is available from Windows 8 onwards. */
if(curlx_verify_windows_version(6, 2, 0, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL)) {
-#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
/* CertGetNameString will provide the 8-bit character string without
* any decoding */
DWORD name_flags =
@@ -368,8 +371,8 @@ static DWORD cert_get_name_string(struct Curl_easy *data,
host_names,
length);
return actual_length;
-#endif
}
+#endif
compute_content = host_names != NULL && length != 0;
@@ -457,17 +460,34 @@ static DWORD cert_get_name_string(struct Curl_easy *data,
return actual_length;
}
-static CURLcode verify_host(struct Curl_easy *data,
- CERT_CONTEXT *pCertContextServer,
- const char *conn_hostname)
+/* Verify the server's hostname */
+CURLcode Curl_verify_host(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
+ struct ssl_connect_data *connssl = cf->ctx;
+ SECURITY_STATUS sspi_status;
CURLcode result = CURLE_PEER_FAILED_VERIFICATION;
+ CERT_CONTEXT *pCertContextServer = NULL;
TCHAR *cert_hostname_buff = NULL;
size_t cert_hostname_buff_index = 0;
+ const char *conn_hostname = connssl->hostname;
size_t hostlen = strlen(conn_hostname);
DWORD len = 0;
DWORD actual_len = 0;
+ sspi_status =
+ s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+ &pCertContextServer);
+
+ 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;
+ goto cleanup;
+ }
+
/* Determine the size of the string needed for the cert hostname */
len = cert_get_name_string(data, pCertContextServer, NULL, 0);
if(len == 0) {
@@ -498,10 +518,9 @@ static CURLcode verify_host(struct Curl_easy *data,
goto cleanup;
}
- /* If HAVE_CERT_NAME_SEARCH_ALL_NAMES is available, the output
- * will contain all DNS names, where each name is null-terminated
- * and the last DNS name is double null-terminated. Due to this
- * encoding, use the length of the buffer to iterate over all names.
+ /* cert_hostname_buff contains all DNS names, where each name is
+ * null-terminated and the last DNS name is double null-terminated. Due to
+ * this encoding, use the length of the buffer to iterate over all names.
*/
result = CURLE_PEER_FAILED_VERIFICATION;
while(cert_hostname_buff_index < len &&
@@ -560,9 +579,15 @@ static CURLcode verify_host(struct Curl_easy *data,
cleanup:
Curl_safefree(cert_hostname_buff);
+ if(pCertContextServer)
+ CertFreeCertificateContext(pCertContextServer);
+
return result;
}
+
+#ifdef HAS_MANUAL_VERIFY_API
+/* Verify the server's certificate and hostname */
CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
@@ -721,7 +746,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
if(result == CURLE_OK) {
if(conn_config->verifyhost) {
- result = verify_host(data, pCertContextServer, connssl->hostname);
+ result = Curl_verify_host(cf, data);
}
}
diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c
index 23dc830b82..3a3ae009c8 100644
--- a/libs/libcurl/src/vtls/sectransp.c
+++ b/libs/libcurl/src/vtls/sectransp.c
@@ -845,8 +845,8 @@ static OSStatus bio_cf_in_read(SSLConnectionRef connection,
DEBUGASSERT(data);
nread = Curl_conn_cf_recv(cf->next, data, buf, *dataLength, &result);
- DEBUGF(LOG_CF(data, cf, "bio_read(len=%zu) -> %zd, result=%d",
- *dataLength, nread, result));
+ CURL_TRC_CF(data, cf, "bio_read(len=%zu) -> %zd, result=%d",
+ *dataLength, nread, result);
if(nread < 0) {
switch(result) {
case CURLE_OK:
@@ -885,8 +885,8 @@ static OSStatus bio_cf_out_write(SSLConnectionRef connection,
DEBUGASSERT(data);
nwritten = Curl_conn_cf_send(cf->next, data, buf, *dataLength, &result);
- DEBUGF(LOG_CF(data, cf, "bio_send(len=%zu) -> %zd, result=%d",
- *dataLength, nwritten, result));
+ CURL_TRC_CF(data, cf, "bio_send(len=%zu) -> %zd, result=%d",
+ *dataLength, nwritten, result);
if(nwritten <= 0) {
if(result == CURLE_AGAIN) {
rtn = errSSLWouldBlock;
@@ -1086,7 +1086,6 @@ static OSStatus CopyIdentityWithLabel(char *label,
CFArrayRef keys_list;
CFIndex keys_list_count;
CFIndex i;
- CFStringRef common_name;
/* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
kSecClassIdentity was introduced in Lion. If both exist, let's use them
@@ -1134,6 +1133,7 @@ static OSStatus CopyIdentityWithLabel(char *label,
(SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
err = SecIdentityCopyCertificate(identity, &cert);
if(err == noErr) {
+ CFStringRef common_name = NULL;
OSStatus copy_status = noErr;
#if CURL_BUILD_IOS
common_name = SecCertificateCopySubjectSummary(cert);
@@ -1149,7 +1149,8 @@ static OSStatus CopyIdentityWithLabel(char *label,
status = noErr;
break;
}
- CFRelease(common_name);
+ if(common_name)
+ CFRelease(common_name);
}
CFRelease(cert);
}
@@ -1293,7 +1294,7 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
/* This code was borrowed from nss.c, with some modifications:
* Determine whether the nickname passed in is a filename that needs to
- * be loaded as a PEM or a regular NSS nickname.
+ * be loaded as a PEM or a nickname.
*
* returns 1 for a file
* returns 0 for not a file
@@ -1611,7 +1612,7 @@ static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data,
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",
+ " starting position %zd and ending position %zd",
ciphers,
cipher_start - ciphers,
cipher_end - ciphers);
@@ -1662,7 +1663,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
DEBUGASSERT(backend);
- DEBUGF(LOG_CF(data, cf, "connect_step1"));
+ CURL_TRC_CF(data, cf, "connect_step1");
GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
#endif /* CURL_BUILD_MAC */
@@ -2069,7 +2070,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
- infof(data, "SSL re-using session ID");
+ infof(data, "SSL reusing session ID");
}
/* If there isn't one, then let's make one up! This has to be done prior
to starting the handshake. */
@@ -2293,7 +2294,7 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
/* This is not a PEM file, probably a certificate in DER format. */
rc = append_cert_to_array(data, certbuf, buflen, array);
if(rc != CURLE_OK) {
- DEBUGF(LOG_CF(data, cf, "append_cert for CA failed"));
+ CURL_TRC_CF(data, cf, "append_cert for CA failed");
result = rc;
goto out;
}
@@ -2307,7 +2308,7 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
rc = append_cert_to_array(data, der, derlen, array);
free(der);
if(rc != CURLE_OK) {
- DEBUGF(LOG_CF(data, cf, "append_cert for CA failed"));
+ CURL_TRC_CF(data, cf, "append_cert for CA failed");
result = rc;
goto out;
}
@@ -2323,7 +2324,7 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
goto out;
}
- DEBUGF(LOG_CF(data, cf, "setting %d trust anchors", n));
+ CURL_TRC_CF(data, cf, "setting %d trust anchors", n);
ret = SecTrustSetAnchorCertificates(trust, array);
if(ret != noErr) {
failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
@@ -2345,11 +2346,11 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
switch(trust_eval) {
case kSecTrustResultUnspecified:
/* what does this really mean? */
- DEBUGF(LOG_CF(data, cf, "trust result: Unspecified"));
+ CURL_TRC_CF(data, cf, "trust result: Unspecified");
result = CURLE_OK;
goto out;
case kSecTrustResultProceed:
- DEBUGF(LOG_CF(data, cf, "trust result: Proceed"));
+ CURL_TRC_CF(data, cf, "trust result: Proceed");
result = CURLE_OK;
goto out;
@@ -2382,7 +2383,7 @@ static CURLcode verify_cert(struct Curl_cfilter *cf,
size_t buflen;
if(ca_info_blob) {
- DEBUGF(LOG_CF(data, cf, "verify_peer, CA from config blob"));
+ CURL_TRC_CF(data, cf, "verify_peer, CA from config blob");
certbuf = (unsigned char *)malloc(ca_info_blob->len + 1);
if(!certbuf) {
return CURLE_OUT_OF_MEMORY;
@@ -2392,7 +2393,7 @@ static CURLcode verify_cert(struct Curl_cfilter *cf,
certbuf[ca_info_blob->len]='\0';
}
else if(cafile) {
- DEBUGF(LOG_CF(data, cf, "verify_peer, CA from file '%s'", cafile));
+ CURL_TRC_CF(data, cf, "verify_peer, CA from file '%s'", cafile);
if(read_cert(cafile, &certbuf, &buflen) < 0) {
failf(data, "SSL: failed to read or invalid CA certificate");
return CURLE_SSL_CACERT_BADFILE;
@@ -2432,7 +2433,6 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
SecTrustRef trust;
OSStatus ret;
SecKeyRef keyRef;
- OSStatus success;
ret = SSLCopyPeerTrust(ctx, &trust);
if(ret != noErr || !trust)
@@ -2452,11 +2452,14 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
#elif SECTRANSP_PINNEDPUBKEY_V2
- success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
- &publicKeyBits);
- CFRelease(keyRef);
- if(success != errSecSuccess || !publicKeyBits)
- break;
+ {
+ OSStatus success;
+ success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
+ &publicKeyBits);
+ CFRelease(keyRef);
+ if(success != errSecSuccess || !publicKeyBits)
+ break;
+ }
#endif /* SECTRANSP_PINNEDPUBKEY_V2 */
@@ -2484,7 +2487,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
spkiHeaderLength = 23;
break;
default:
- infof(data, "SSL: unhandled public key length: %d", pubkeylen);
+ infof(data, "SSL: unhandled public key length: %zu", pubkeylen);
#elif SECTRANSP_PINNEDPUBKEY_V2
default:
/* ecDSA secp256r1 pubkeylen == 91 header already included?
@@ -2533,7 +2536,7 @@ static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
|| ssl_connect_2_reading == connssl->connecting_state
|| ssl_connect_2_writing == connssl->connecting_state);
DEBUGASSERT(backend);
- DEBUGF(LOG_CF(data, cf, "connect_step2"));
+ CURL_TRC_CF(data, cf, "connect_step2");
/* Here goes nothing: */
check_handshake:
@@ -3000,7 +3003,7 @@ static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf,
struct ssl_connect_data *connssl = cf->ctx;
CURLcode result;
- DEBUGF(LOG_CF(data, cf, "connect_step3"));
+ CURL_TRC_CF(data, cf, "connect_step3");
/* There is no step 3!
* Well, okay, let's collect server certificates, and if verbose mode is on,
* let's print the details of the server certificates. */
@@ -3109,7 +3112,7 @@ sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
}
if(ssl_connect_done == connssl->connecting_state) {
- DEBUGF(LOG_CF(data, cf, "connected"));
+ CURL_TRC_CF(data, cf, "connected");
connssl->state = ssl_connection_complete;
*done = TRUE;
}
@@ -3156,7 +3159,7 @@ static void sectransp_close(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGASSERT(backend);
if(backend->ssl_ctx) {
- DEBUGF(LOG_CF(data, cf, "close"));
+ CURL_TRC_CF(data, cf, "close");
(void)SSLClose(backend->ssl_ctx);
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
if(SSLCreateContext)
@@ -3202,7 +3205,7 @@ static int sectransp_shutdown(struct Curl_cfilter *cf,
what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
SSL_SHUTDOWN_TIMEOUT);
- DEBUGF(LOG_CF(data, cf, "shutdown"));
+ CURL_TRC_CF(data, cf, "shutdown");
while(loop--) {
if(what < 0) {
/* anything that gets here is fatally bad */
@@ -3264,7 +3267,7 @@ static bool sectransp_data_pending(struct Curl_cfilter *cf,
DEBUGASSERT(backend);
if(backend->ssl_ctx) { /* SSL is in use */
- DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data_pending"));
+ CURL_TRC_CF((struct Curl_easy *)data, cf, "data_pending");
err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
if(err == noErr)
return buffer > 0UL;
@@ -3299,6 +3302,7 @@ static CURLcode sectransp_sha256sum(const unsigned char *tmp, /* input */
unsigned char *sha256sum, /* output */
size_t sha256len)
{
+ (void)sha256len;
assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
(void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
return CURLE_OK;
diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c
index 353775d46e..3e33c16042 100644
--- a/libs/libcurl/src/vtls/vtls.c
+++ b/libs/libcurl/src/vtls/vtls.c
@@ -417,7 +417,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
DEBUGASSERT(ssl_config->primary.sessionid);
if(!ssl_config->primary.sessionid || !data->state.session)
- /* session ID re-use is disabled or the session cache has not been
+ /* session ID reuse is disabled or the session cache has not been
setup */
return TRUE;
@@ -635,19 +635,16 @@ int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
struct ssl_connect_data *connssl = cf->ctx;
curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
- if(sock != CURL_SOCKET_BAD) {
- if(connssl->connecting_state == ssl_connect_2_writing) {
- /* write mode */
- socks[0] = sock;
- return GETSOCK_WRITESOCK(0);
- }
- if(connssl->connecting_state == ssl_connect_2_reading) {
- /* read mode */
- socks[0] = sock;
- return GETSOCK_READSOCK(0);
- }
+ if(sock == CURL_SOCKET_BAD)
+ return GETSOCK_BLANK;
+
+ if(connssl->connecting_state == ssl_connect_2_writing) {
+ /* we are only interested in writing */
+ socks[0] = sock;
+ return GETSOCK_WRITESOCK(0);
}
- return GETSOCK_BLANK;
+ socks[0] = sock;
+ return GETSOCK_READSOCK(0);
}
/* Selects an SSL crypto engine
@@ -883,6 +880,9 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
FILE *fp;
unsigned char *buf = NULL, *pem_ptr = NULL;
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+#endif
/* if a path wasn't specified, don't pin */
if(!pinnedpubkey)
@@ -1240,12 +1240,8 @@ const struct Curl_ssl *Curl_ssl =
&Curl_ssl_sectransp;
#elif defined(USE_GNUTLS)
&Curl_ssl_gnutls;
-#elif defined(USE_GSKIT)
- &Curl_ssl_gskit;
#elif defined(USE_MBEDTLS)
&Curl_ssl_mbedtls;
-#elif defined(USE_NSS)
- &Curl_ssl_nss;
#elif defined(USE_RUSTLS)
&Curl_ssl_rustls;
#elif defined(USE_OPENSSL)
@@ -1268,15 +1264,9 @@ static const struct Curl_ssl *available_backends[] = {
#if defined(USE_GNUTLS)
&Curl_ssl_gnutls,
#endif
-#if defined(USE_GSKIT)
- &Curl_ssl_gskit,
-#endif
#if defined(USE_MBEDTLS)
&Curl_ssl_mbedtls,
#endif
-#if defined(USE_NSS)
- &Curl_ssl_nss,
-#endif
#if defined(USE_OPENSSL)
&Curl_ssl_openssl,
#endif
@@ -1522,6 +1512,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
}
CF_DATA_SAVE(save, cf, data);
+ CURL_TRC_CF(data, cf, "cf_connect()");
(void)connssl;
DEBUGASSERT(data->conn);
DEBUGASSERT(data->conn == cf->conn);
@@ -1551,6 +1542,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
out:
+ CURL_TRC_CF(data, cf, "cf_connect() -> %d, done=%d", result, *done);
CF_DATA_RESTORE(cf, save);
return result;
}
@@ -1601,7 +1593,7 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
/* eof */
*err = CURLE_OK;
}
- DEBUGF(LOG_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len, nread, *err));
+ CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len, nread, *err);
CF_DATA_RESTORE(cf, save);
return nread;
}
@@ -1611,12 +1603,17 @@ static int ssl_cf_get_select_socks(struct Curl_cfilter *cf,
curl_socket_t *socks)
{
struct cf_call_data save;
- int result;
+ int fds = GETSOCK_BLANK;
- CF_DATA_SAVE(save, cf, data);
- result = Curl_ssl->get_select_socks(cf, data, socks);
- CF_DATA_RESTORE(cf, save);
- return result;
+ if(!cf->next->connected) {
+ fds = cf->next->cft->get_select_socks(cf->next, data, socks);
+ }
+ else if(!cf->connected) {
+ CF_DATA_SAVE(save, cf, data);
+ fds = Curl_ssl->get_select_socks(cf, data, socks);
+ CF_DATA_RESTORE(cf, save);
+ }
+ return fds;
}
static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
@@ -1702,7 +1699,7 @@ static bool cf_ssl_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data,
struct Curl_cftype Curl_cft_ssl = {
"SSL",
CF_TYPE_SSL,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
ssl_cf_destroy,
ssl_cf_connect,
ssl_cf_close,
@@ -1720,7 +1717,7 @@ struct Curl_cftype Curl_cft_ssl = {
struct Curl_cftype Curl_cft_ssl_proxy = {
"SSL-PROXY",
CF_TYPE_SSL,
- CURL_LOG_DEFAULT,
+ CURL_LOG_LVL_NONE,
ssl_cf_destroy,
ssl_cf_connect,
ssl_cf_close,
diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h
index 2178e8834f..2ec6162296 100644
--- a/libs/libcurl/src/vtls/vtls.h
+++ b/libs/libcurl/src/vtls/vtls.h
@@ -43,7 +43,7 @@ struct Curl_ssl_session;
#define VTLS_INFOF_NO_ALPN \
"ALPN: server did not agree on a protocol. Uses default."
#define VTLS_INFOF_ALPN_OFFER_1STR \
- "ALPN: offers %s"
+ "ALPN: curl offers %s"
#define VTLS_INFOF_ALPN_ACCEPTED_1STR \
ALPN_ACCEPTED "%s"
#define VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR \
diff --git a/libs/libcurl/src/vtls/vtls_int.h b/libs/libcurl/src/vtls/vtls_int.h
index cdfca617a3..7a78a56cc7 100644
--- a/libs/libcurl/src/vtls/vtls_int.h
+++ b/libs/libcurl/src/vtls/vtls_int.h
@@ -217,8 +217,6 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
#include "openssl.h" /* OpenSSL versions */
#include "gtls.h" /* GnuTLS versions */
-#include "nssg.h" /* NSS versions */
-#include "gskit.h" /* Global Secure ToolKit versions */
#include "wolfssl.h" /* wolfSSL versions */
#include "schannel.h" /* Schannel SSPI version */
#include "sectransp.h" /* SecureTransport (Darwin) version */
diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c
index fc4843790a..231ff35b71 100644
--- a/libs/libcurl/src/vtls/wolfssl.c
+++ b/libs/libcurl/src/vtls/wolfssl.c
@@ -92,9 +92,9 @@
#endif
struct wolfssl_ssl_backend_data {
- SSL_CTX* ctx;
- SSL* handle;
- CURLcode io_result; /* result of last BIO cfilter operation */
+ WOLFSSL_CTX *ctx;
+ WOLFSSL *handle;
+ CURLcode io_result; /* result of last BIO cfilter operation */
};
#ifdef OPENSSL_EXTRA
@@ -180,7 +180,8 @@ wolfssl_log_tls12_secret(SSL *ssl)
}
#endif
- if(SSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) != SSL_SUCCESS) {
+ if(wolfSSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) !=
+ SSL_SUCCESS) {
return;
}
@@ -290,11 +291,11 @@ static int bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen)
DEBUGASSERT(data);
nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
backend->io_result = result;
- DEBUGF(LOG_CF(data, cf, "bio_write(len=%d) -> %zd, %d",
- blen, nwritten, result));
+ CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %zd, %d",
+ blen, nwritten, result);
wolfSSL_BIO_clear_retry_flags(bio);
if(nwritten < 0 && CURLE_AGAIN == result)
- BIO_set_retry_read(bio);
+ BIO_set_retry_write(bio);
return (int)nwritten;
}
@@ -315,8 +316,7 @@ static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
backend->io_result = result;
- DEBUGF(LOG_CF(data, cf, "bio_read(len=%d) -> %zd, %d",
- blen, nread, result));
+ CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %zd, %d", blen, nread, result);
wolfSSL_BIO_clear_retry_flags(bio);
if(nread < 0 && CURLE_AGAIN == result)
BIO_set_retry_read(bio);
@@ -327,17 +327,17 @@ static WOLFSSL_BIO_METHOD *bio_cf_method = NULL;
static void bio_cf_init_methods(void)
{
- bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO");
- wolfSSL_BIO_meth_set_write(bio_cf_method, &bio_cf_out_write);
- wolfSSL_BIO_meth_set_read(bio_cf_method, &bio_cf_in_read);
- wolfSSL_BIO_meth_set_ctrl(bio_cf_method, &bio_cf_ctrl);
- wolfSSL_BIO_meth_set_create(bio_cf_method, &bio_cf_create);
- wolfSSL_BIO_meth_set_destroy(bio_cf_method, &bio_cf_destroy);
+ bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO");
+ wolfSSL_BIO_meth_set_write(bio_cf_method, &bio_cf_out_write);
+ wolfSSL_BIO_meth_set_read(bio_cf_method, &bio_cf_in_read);
+ wolfSSL_BIO_meth_set_ctrl(bio_cf_method, &bio_cf_ctrl);
+ wolfSSL_BIO_meth_set_create(bio_cf_method, &bio_cf_create);
+ wolfSSL_BIO_meth_set_destroy(bio_cf_method, &bio_cf_destroy);
}
static void bio_cf_free_methods(void)
{
- wolfSSL_BIO_meth_free(bio_cf_method);
+ wolfSSL_BIO_meth_free(bio_cf_method);
}
#else /* USE_BIO_CHAIN */
@@ -361,7 +361,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- SSL_METHOD* req_method = NULL;
+ WOLFSSL_METHOD* req_method = NULL;
#ifdef HAVE_LIBOQS
word16 oqsAlg = 0;
size_t idx = 0;
@@ -372,6 +372,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
#else
#define use_sni(x) Curl_nop_stmt
#endif
+ bool imported_native_ca = false;
bool imported_ca_info_blob = false;
DEBUGASSERT(backend);
@@ -445,8 +446,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}
if(backend->ctx)
- SSL_CTX_free(backend->ctx);
- backend->ctx = SSL_CTX_new(req_method);
+ wolfSSL_CTX_free(backend->ctx);
+ backend->ctx = wolfSSL_CTX_new(req_method);
if(!backend->ctx) {
failf(data, "SSL: couldn't create a context");
@@ -507,13 +508,31 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}
}
+#ifndef NO_FILESYSTEM
+ /* load native CA certificates */
+ if(ssl_config->native_ca_store) {
+ if(wolfSSL_CTX_load_system_CA_certs(backend->ctx) != WOLFSSL_SUCCESS) {
+ infof(data, "error importing native CA store, continuing anyway");
+ }
+ else {
+ imported_native_ca = true;
+ infof(data, "successfully imported native CA store");
+ }
+ }
+#endif /* !NO_FILESYSTEM */
+
+ /* load certificate blob */
if(ca_info_blob) {
- if(wolfSSL_CTX_load_verify_buffer(
- backend->ctx, ca_info_blob->data, ca_info_blob->len,
- SSL_FILETYPE_PEM
- ) != SSL_SUCCESS) {
- failf(data, "error importing CA certificate blob");
- return CURLE_SSL_CACERT_BADFILE;
+ if(wolfSSL_CTX_load_verify_buffer(backend->ctx, ca_info_blob->data,
+ ca_info_blob->len,
+ SSL_FILETYPE_PEM) != SSL_SUCCESS) {
+ if(imported_native_ca) {
+ infof(data, "error importing CA certificate blob, continuing anyway");
+ }
+ else {
+ failf(data, "error importing CA certificate blob");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
}
else {
imported_ca_info_blob = true;
@@ -524,10 +543,11 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
#ifndef NO_FILESYSTEM
/* load trusted cacert */
if(conn_config->CAfile) {
- if(1 != SSL_CTX_load_verify_locations(backend->ctx,
- conn_config->CAfile,
- conn_config->CApath)) {
- if(conn_config->verifypeer && !imported_ca_info_blob) {
+ if(1 != wolfSSL_CTX_load_verify_locations(backend->ctx,
+ conn_config->CAfile,
+ conn_config->CApath)) {
+ if(conn_config->verifypeer && !imported_ca_info_blob &&
+ !imported_native_ca) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:"
" CAfile: %s CApath: %s",
@@ -558,17 +578,17 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
if(ssl_config->primary.clientcert && ssl_config->key) {
int file_type = do_file_type(ssl_config->cert_type);
- if(SSL_CTX_use_certificate_file(backend->ctx,
- ssl_config->primary.clientcert,
- file_type) != 1) {
+ if(wolfSSL_CTX_use_certificate_file(backend->ctx,
+ ssl_config->primary.clientcert,
+ file_type) != 1) {
failf(data, "unable to use client certificate (no key or wrong pass"
" phrase?)");
return CURLE_SSL_CONNECT_ERROR;
}
file_type = do_file_type(ssl_config->key_type);
- if(SSL_CTX_use_PrivateKey_file(backend->ctx, ssl_config->key,
- file_type) != 1) {
+ if(wolfSSL_CTX_use_PrivateKey_file(backend->ctx, ssl_config->key,
+ file_type) != 1) {
failf(data, "unable to set private key");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -579,10 +599,9 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
* fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */
- SSL_CTX_set_verify(backend->ctx,
- conn_config->verifypeer?SSL_VERIFY_PEER:
- SSL_VERIFY_NONE,
- NULL);
+ wolfSSL_CTX_set_verify(backend->ctx,
+ conn_config->verifypeer?SSL_VERIFY_PEER:
+ SSL_VERIFY_NONE, NULL);
#ifdef HAVE_SNI
if(sni) {
@@ -631,8 +650,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
/* Let's make an SSL structure */
if(backend->handle)
- SSL_free(backend->handle);
- backend->handle = SSL_new(backend->ctx);
+ wolfSSL_free(backend->handle);
+ backend->handle = wolfSSL_new(backend->ctx);
if(!backend->handle) {
failf(data, "SSL: couldn't create a handle");
return CURLE_OUT_OF_MEMORY;
@@ -692,7 +711,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
infof(data, "Can't use session ID, going on without");
}
else
- infof(data, "SSL re-using session ID");
+ infof(data, "SSL reusing session ID");
}
Curl_ssl_sessionid_unlock(data);
}
@@ -710,7 +729,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}
#else /* USE_BIO_CHAIN */
/* pass the raw socket into the SSL layer */
- if(!SSL_set_fd(backend->handle, (int)Curl_conn_cf_get_socket(cf, data))) {
+ if(!wolfSSL_set_fd(backend->handle,
+ (int)Curl_conn_cf_get_socket(cf, data))) {
failf(data, "SSL: SSL_set_fd failed");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -735,7 +755,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGASSERT(backend);
- ERR_clear_error();
+ wolfSSL_ERR_clear_error();
/* Enable RFC2818 checks */
if(conn_config->verifyhost) {
@@ -745,7 +765,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_SSL_CONNECT_ERROR;
}
- ret = SSL_connect(backend->handle);
+ ret = wolfSSL_connect(backend->handle);
#ifdef OPENSSL_EXTRA
if(Curl_tls_keylog_enabled()) {
@@ -773,7 +793,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
if(ret != 1) {
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
- int detail = SSL_get_error(backend->handle, ret);
+ int detail = wolfSSL_get_error(backend->handle, ret);
if(SSL_ERROR_WANT_READ == detail) {
connssl->connecting_state = ssl_connect_2_reading;
@@ -831,7 +851,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
}
else {
failf(data, "SSL_connect failed with error %d: %s", detail,
- ERR_error_string(detail, error_buffer));
+ wolfSSL_ERR_error_string(detail, error_buffer));
return CURLE_SSL_CONNECT_ERROR;
}
}
@@ -845,7 +865,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
struct Curl_asn1Element *pubkey;
CURLcode result;
- x509 = SSL_get_peer_certificate(backend->handle);
+ x509 = wolfSSL_get_peer_certificate(backend->handle);
if(!x509) {
failf(data, "SSL: failed retrieving server certificate");
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
@@ -931,8 +951,8 @@ wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
bool incache;
bool added = FALSE;
void *old_ssl_sessionid = NULL;
- /* SSL_get1_session allocates memory that has to be freed. */
- SSL_SESSION *our_ssl_sessionid = SSL_get1_session(backend->handle);
+ /* wolfSSL_get1_session allocates memory that has to be freed. */
+ WOLFSSL_SESSION *our_ssl_sessionid = wolfSSL_get1_session(backend->handle);
if(our_ssl_sessionid) {
Curl_ssl_sessionid_lock(data);
@@ -949,7 +969,7 @@ wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
result = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid, 0, NULL);
if(result) {
Curl_ssl_sessionid_unlock(data);
- SSL_SESSION_free(our_ssl_sessionid);
+ wolfSSL_SESSION_free(our_ssl_sessionid);
failf(data, "failed to store ssl session");
return result;
}
@@ -961,7 +981,7 @@ wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
if(!added) {
/* If the session info wasn't added to the cache, free our copy. */
- SSL_SESSION_free(our_ssl_sessionid);
+ wolfSSL_SESSION_free(our_ssl_sessionid);
}
}
}
@@ -987,35 +1007,34 @@ static ssize_t wolfssl_send(struct Curl_cfilter *cf,
DEBUGASSERT(backend);
- ERR_clear_error();
+ wolfSSL_ERR_clear_error();
- rc = SSL_write(backend->handle, mem, memlen);
+ rc = wolfSSL_write(backend->handle, mem, memlen);
if(rc <= 0) {
- int err = SSL_get_error(backend->handle, rc);
+ int err = wolfSSL_get_error(backend->handle, rc);
switch(err) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* there's data pending, re-invoke SSL_write() */
- DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len));
+ CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len);
*curlcode = CURLE_AGAIN;
return -1;
default:
if(backend->io_result == CURLE_AGAIN) {
- DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len));
+ CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len);
*curlcode = CURLE_AGAIN;
return -1;
}
- DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> %d, %d",
- len, rc, err));
+ CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> %d, %d", len, rc, err);
failf(data, "SSL write: %s, errno %d",
- ERR_error_string(err, error_buffer),
+ wolfSSL_ERR_error_string(err, error_buffer),
SOCKERRNO);
*curlcode = CURLE_SEND_ERROR;
return -1;
}
}
- DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> %d", len, rc));
+ CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> %d", len, rc);
return rc;
}
@@ -1033,13 +1052,13 @@ static void wolfssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
char buf[32];
/* Maybe the server has already sent a close notify alert.
Read it to avoid an RST on the TCP connection. */
- (void)SSL_read(backend->handle, buf, (int)sizeof(buf));
- (void)SSL_shutdown(backend->handle);
- SSL_free(backend->handle);
+ (void)wolfSSL_read(backend->handle, buf, (int)sizeof(buf));
+ (void)wolfSSL_shutdown(backend->handle);
+ wolfSSL_free(backend->handle);
backend->handle = NULL;
}
if(backend->ctx) {
- SSL_CTX_free(backend->ctx);
+ wolfSSL_CTX_free(backend->ctx);
backend->ctx = NULL;
}
}
@@ -1058,17 +1077,17 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
DEBUGASSERT(backend);
- ERR_clear_error();
+ wolfSSL_ERR_clear_error();
*curlcode = CURLE_OK;
- nread = SSL_read(backend->handle, buf, buffsize);
+ nread = wolfSSL_read(backend->handle, buf, buffsize);
if(nread <= 0) {
- int err = SSL_get_error(backend->handle, nread);
+ int err = wolfSSL_get_error(backend->handle, nread);
switch(err) {
case SSL_ERROR_ZERO_RETURN: /* no more data */
- DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen));
+ CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
*curlcode = CURLE_OK;
return 0;
case SSL_ERROR_NONE:
@@ -1076,30 +1095,30 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
case SSL_ERROR_WANT_READ:
/* FALLTHROUGH */
case SSL_ERROR_WANT_WRITE:
- /* there's data pending, re-invoke SSL_read() */
- DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen));
+ /* there's data pending, re-invoke wolfSSL_read() */
+ CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
*curlcode = CURLE_AGAIN;
return -1;
default:
if(backend->io_result == CURLE_AGAIN) {
- DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen));
+ CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
*curlcode = CURLE_AGAIN;
return -1;
}
failf(data, "SSL read: %s, errno %d",
- ERR_error_string(err, error_buffer), SOCKERRNO);
+ wolfSSL_ERR_error_string(err, error_buffer), SOCKERRNO);
*curlcode = CURLE_RECV_ERROR;
return -1;
}
}
- DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> %d", blen, nread));
+ CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> %d", blen, nread);
return nread;
}
static void wolfssl_session_free(void *ptr)
{
- SSL_SESSION_free(ptr);
+ wolfSSL_SESSION_free(ptr);
}
@@ -1147,7 +1166,7 @@ static bool wolfssl_data_pending(struct Curl_cfilter *cf,
backend = (struct wolfssl_ssl_backend_data *)ctx->backend;
if(backend->handle) /* SSL is in use */
- return (0 != SSL_pending(backend->handle)) ? TRUE : FALSE;
+ return (0 != wolfSSL_pending(backend->handle)) ? TRUE : FALSE;
else
return FALSE;
}
@@ -1169,8 +1188,8 @@ static int wolfssl_shutdown(struct Curl_cfilter *cf,
backend = (struct wolfssl_ssl_backend_data *)ctx->backend;
if(backend->handle) {
- ERR_clear_error();
- SSL_free(backend->handle);
+ wolfSSL_ERR_clear_error();
+ wolfSSL_free(backend->handle);
backend->handle = NULL;
}
return retval;
@@ -1333,7 +1352,8 @@ static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
{
wc_Sha256 SHA256pw;
(void)unused;
- wc_InitSha256(&SHA256pw);
+ if(wc_InitSha256(&SHA256pw))
+ return CURLE_FAILED_INIT;
wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
wc_Sha256Final(&SHA256pw, sha256sum);
return CURLE_OK;
diff --git a/libs/libcurl/src/vtls/x509asn1.c b/libs/libcurl/src/vtls/x509asn1.c
index 58feb58226..a695922816 100644
--- a/libs/libcurl/src/vtls/x509asn1.c
+++ b/libs/libcurl/src/vtls/x509asn1.c
@@ -24,24 +24,18 @@
#include "curl_setup.h"
-#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \
- defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP)
+#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
+ defined(USE_SCHANNEL) || defined(USE_SECTRANSP)
-#if defined(USE_GSKIT) || defined(USE_WOLFSSL) || defined(USE_SCHANNEL)
+#if defined(USE_WOLFSSL) || defined(USE_SCHANNEL)
#define WANT_PARSEX509 /* uses Curl_parseX509() */
#endif
-#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \
- defined(USE_SCHANNEL) || defined(USE_SECTRANSP)
+#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP)
#define WANT_EXTRACT_CERTINFO /* uses Curl_extract_certinfo() */
#define WANT_PARSEX509 /* ... uses Curl_parseX509() */
#endif
-#if defined(USE_GSKIT)
-#define WANT_VERIFYHOST /* uses Curl_verifyhost () */
-#define WANT_PARSEX509 /* ... uses Curl_parseX509() */
-#endif
-
#include <curl/curl.h>
#include "urldata.h"
#include "strcase.h"
@@ -973,7 +967,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum,
infof(data, " ECC Public Key (%lu bits)", len);
if(data->set.ssl.certinfo) {
char q[sizeof(len) * 8 / 3 + 1];
- (void)msnprintf(q, sizeof(q), "%lu", len);
+ (void)msnprintf(q, sizeof(q), "%zu", len);
if(ssl_push_certinfo(data, certnum, "ECC Public Key", q))
return 1;
}
@@ -1007,7 +1001,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum,
infof(data, " RSA Public Key (%lu bits)", len);
if(data->set.ssl.certinfo) {
char r[sizeof(len) * 8 / 3 + 1];
- msnprintf(r, sizeof(r), "%lu", len);
+ msnprintf(r, sizeof(r), "%zu", len);
if(ssl_push_certinfo(data, certnum, "RSA Public Key", r))
return 1;
}
@@ -1261,8 +1255,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
#endif /* WANT_EXTRACT_CERTINFO */
-#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL
- * or USE_SECTRANSP */
+#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
#ifdef WANT_VERIFYHOST
diff --git a/libs/libcurl/src/vtls/x509asn1.h b/libs/libcurl/src/vtls/x509asn1.h
index 5c747d3af2..646aac390a 100644
--- a/libs/libcurl/src/vtls/x509asn1.h
+++ b/libs/libcurl/src/vtls/x509asn1.h
@@ -27,8 +27,8 @@
#include "curl_setup.h"
-#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \
- defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP)
+#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
+ defined(USE_SCHANNEL) || defined(USE_SECTRANSP)
#include "cfilters.h"
#include "urldata.h"
@@ -76,6 +76,5 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum,
const char *beg, const char *end);
CURLcode Curl_verifyhost(struct Curl_cfilter *cf, struct Curl_easy *data,
const char *beg, const char *end);
-#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL
- * or USE_SECTRANSP */
+#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
#endif /* HEADER_CURL_X509ASN1_H */