summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/linux.yml18
-rw-r--r--Dockerfile2
-rw-r--r--RELEASE-NOTES49
-rw-r--r--docs/examples/cacertinmem.c28
-rw-r--r--docs/examples/usercertinmem.c52
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md15
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md19
-rw-r--r--lib/multi.c42
-rw-r--r--lib/sendf.c4
-rw-r--r--lib/socks.c208
-rw-r--r--lib/vssh/wolfssh.c288
-rw-r--r--lib/vtls/mbedtls.c39
-rw-r--r--lib/vtls/openssl.c35
-rw-r--r--tests/data/Makefile.am6
-rw-r--r--tests/data/test230760
-rw-r--r--tests/data/test75853
-rwxr-xr-xtests/ftpserver.pl7
-rw-r--r--tests/libtest/Makefile.inc2
-rw-r--r--tests/libtest/lib758.c515
-rw-r--r--tests/processhelp.pm47
-rw-r--r--tests/runner.pm8
-rwxr-xr-xtests/runtests.pl3
-rw-r--r--tests/serverhelp.pm27
-rw-r--r--tests/servers.pm2
24 files changed, 1092 insertions, 437 deletions
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 7f1ea5a5e..b479b46e4 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -103,7 +103,12 @@ jobs:
- name: 'mbedtls valgrind'
install_packages: libnghttp2-dev libidn2-dev libldap-dev valgrind
install_steps: mbedtls
- configure: LDFLAGS=-Wl,-rpath,/home/runner/mbedtls/lib --with-mbedtls=/home/runner/mbedtls --enable-debug
+ generate: >-
+ -DCURL_USE_MBEDTLS=ON -DENABLE_DEBUG=ON
+ -DMBEDTLS_INCLUDE_DIR=/home/runner/mbedtls/include
+ -DMBEDTLS_LIBRARY=/home/runner/mbedtls/lib/libmbedtls.a
+ -DMBEDX509_LIBRARY=/home/runner/mbedtls/lib/libmbedx509.a
+ -DMBEDCRYPTO_LIBRARY=/home/runner/mbedtls/lib/libmbedcrypto.a
- name: 'mbedtls clang'
install_packages: libnghttp2-dev libldap-dev clang
@@ -145,7 +150,7 @@ jobs:
- name: 'openssl libssh2 sync-resolver valgrind'
install_packages: zlib1g-dev libidn2-dev libssh2-1-dev libnghttp2-dev libldap-dev valgrind
- configure: --with-openssl --enable-debug --disable-threaded-resolver --with-libssh2
+ generate: -DENABLE_DEBUG=ON -DENABLE_THREADED_RESOLVER=OFF -DCURL_USE_LIBSSH2=ON
- name: 'openssl'
install_packages: zlib1g-dev
@@ -160,7 +165,8 @@ jobs:
- name: 'openssl -O3 libssh valgrind'
install_packages: zlib1g-dev libssh-dev valgrind
- configure: CFLAGS=-O3 --with-openssl --enable-debug --with-libssh
+ CFLAGS: -O3
+ generate: -DENABLE_DEBUG=ON -DCURL_USE_LIBSSH=ON
- name: 'openssl clang krb5 openldap static'
install_steps: openldap-static
@@ -260,12 +266,12 @@ jobs:
- name: 'rustls valgrind'
install_packages: libnghttp2-dev libldap-dev valgrind
install_steps: rust rustls
- configure: --with-rustls --enable-ech --enable-debug
+ generate: -DCURL_USE_RUSTLS=ON -DUSE_ECH=ON -DENABLE_DEBUG=ON
- name: 'rustls'
install_packages: libnghttp2-dev libldap-dev
install_steps: rust rustls skiprun pytest
- generate: -DCURL_USE_RUSTLS=ON -DUSE_ECH=ON -DENABLE_DEBUG=ON
+ configure: --with-rustls --enable-ech --enable-debug
- name: 'IntelC openssl'
install_packages: zlib1g-dev libssl-dev
@@ -700,7 +706,7 @@ jobs:
../.github/scripts/randcurl.pl 60 ../bld/src/curl
- name: 'build examples'
- if: ${{ matrix.build.make-custom-target != 'tidy' }}
+ if: ${{ !contains(matrix.build.install_packages, 'valgrind') && matrix.build.make-custom-target != 'tidy' }}
run: |
if [ "${MATRIX_BUILD}" = 'cmake' ]; then
${MATRIX_MAKE_PREFIX} cmake --build bld --verbose --target curl-examples-build
diff --git a/Dockerfile b/Dockerfile
index b4507ff67..67bd0664a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -24,7 +24,7 @@
# $ ./scripts/maketgz 8.7.1
# To update, get the latest digest e.g. from https://hub.docker.com/_/debian/tags
-FROM debian:bookworm-slim@sha256:135c31f331d2c233a0035301460624091facfe097bdc3b3065f59ede9ad2f937
+FROM debian:bookworm-slim@sha256:b1a741487078b369e78119849663d7f1a5341ef2768798f7b7406c4240f86aef
RUN apt-get update -qq && apt-get install -qq -y --no-install-recommends \
build-essential make autoconf automake libtool git perl zip zlib1g-dev gawk && \
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 9aa5003d0..ce492391b 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -3,8 +3,8 @@ curl and libcurl 8.15.1
Public curl releases: 270
Command line options: 272
curl_easy_setopt() options: 308
- Public functions in libcurl: 97
- Contributors: 3486
+ Public functions in libcurl: 98
+ Contributors: 3488
This release includes the following changes:
@@ -15,6 +15,7 @@ This release includes the following changes:
o curl: make --retry-delay and --retry-max-time accept decimal seconds [112]
o hostip: cache negative name resolves [175]
o ip happy eyeballing: keep attempts running [80]
+ o mbedtls: bump minimum version required to 3.2.0 [180]
o multi: add curl_multi_get_offt [56]
o multi: add CURLMOPT_NETWORK_CHANGED to signal network changed [84]
o netrc: use the NETRC environment variable (first) if set [70]
@@ -22,6 +23,7 @@ This release includes the following changes:
o tls: make default TLS version be minimum 1.2 [71]
o tool_getparam: add support for `--longopt=value` [69]
o vquic: drop msh3 [8]
+ o websocket: support CURLOPT_READFUNCTION [193]
o writeout: add %time{} [74]
This release includes the following bugfixes:
@@ -50,6 +52,7 @@ This release includes the following bugfixes:
o cmake: fix `ENABLE_UNIX_SOCKETS=OFF` with pre-fill enabled on unix
o cmake: fix to disable Schannel and SSPI for non-Windows targets
o cmake: fix to restrict `SystemConfiguration` to macOS [139]
+ o cmake: improve error message for invalid HTTP/3 MultiSSL configs [187]
o cmake: keep websockets disabled if HTTP is disabled
o cmake: make `runtests` targets build the curl tool [32]
o cmake: make the ExternalProject test work [183]
@@ -62,6 +65,7 @@ This release includes the following bugfixes:
o connectdata: remove primary+secondary ip_quadruple [126]
o connection: terminate after goaway [62]
o contrithanks: fix for BSD `sed` tool [98]
+ o cookie: don't treat the leading slash as trailing [185]
o curl-config: remove X prefix use [138]
o curl/system.h: fix for GCC 3.3.x and older [38]
o curl: make the URL indexes 64 bit [117]
@@ -84,6 +88,7 @@ This release includes the following bugfixes:
o CURLOPT: bump remaining macros to `long` [147]
o CURLOPT: drop redundant `long` casts [55]
o CURLOPT: replace `(long)` cast with `L` suffix for `CURLHSTS_*` macros
+ o CURLOPT_HTTP_VERSION: mention new default value [179]
o delta: fix warnings, fix for non-GNU `date` tool [99]
o DEPRECATE.md: drop support for Windows XP/2003 [31]
o DEPRECATE.md: remove leftover "nothing" [57]
@@ -94,6 +99,8 @@ This release includes the following bugfixes:
o doh: rename symbols to avoid collision with mingw-w64 headers [66]
o easy handle: check validity on external calls [28]
o examples: drop long cast for `CURLALTSVC_*`
+ o examples: remove base64 encoded chunks from examples [189]
+ o examples: remove href_extractor.c [186]
o gnutls: some small cleanups [41]
o hmac: return error if init fails [2]
o hostip: do DNS cache pruning in milliseconds [132]
@@ -109,6 +116,7 @@ This release includes the following bugfixes:
o libtests: update format strings to avoid casts, drop some macros [109]
o libtests: use `FMT_SOCKET_T`, drop more casts [136]
o managen: reset text mode at end of table marker [145]
+ o mbedtls: check for feature macros instead of version [166]
o memanalyze: fix warnings [22]
o memory: make function overrides work reliably in unity builds [93]
o multi event: remove only announced [25]
@@ -122,13 +130,17 @@ This release includes the following bugfixes:
o openssl: check SSL_write() length on retries [152]
o openssl: clear errors after a failed `d2i_X509()` [161]
o openssl: output unescaped utf8 x509 issuer/subject DNs [169]
+ o openssl: save and restore OpenSSL error queue in two functions [172]
o openssl: some small cleanups [42]
o openssl: split cert_stuff into smaller sub functions [72]
o parallel-max: bump the max value to 65535 [86]
+ o processhelp.pm: fix to use the correct null device on Windows [164]
o pytest: add SOCKS tests and scoring [9]
o pytest: increase server KeepAliveTimeout [26]
o pytest: relax error check on test_07_22 [16]
+ o resolving: dns error tracing [196]
o runtests: add `--ci` option, show `Env:` only when non-empty [134]
+ o runtests: assume `Time::HiRes`, drop Perl Win32 dependency [163]
o schannel: add an error message for client cert not found [165]
o schannel: assume `CERT_CHAIN_REVOCATION_CHECK_CHAIN` [114]
o schannel: drop fallbacks for 4 macros [121]
@@ -163,6 +175,7 @@ This release includes the following bugfixes:
o tidy-up: move literal to the right side of comparisons [65]
o tidy-up: prefer `ifdef`/`ifndef` for single checks [64]
o tls: CURLINFO_TLS_SSL_PTR testing [79]
+ o TODO: remove session export item [194]
o tool_cb_wrt: stop alloc/free for every chunk windows console output [140]
o tool_operate: avoid superfluous strdup'ing output [1]
o tool_operate: use the correct config pointer [115]
@@ -171,6 +184,7 @@ This release includes the following bugfixes:
o tool_urlglob: polish, cleanups, improvements [141]
o unit-tests: build the unitprotos.h from here [73]
o unit2604: avoid `UNCONST()` [135]
+ o URL-SYNTAX.md: drop link to codepoints.net to pass linkcheck [190]
o urlapi: allow more path characters "raw" when asked to URL encode [146]
o urldata: reduce two long struct fields to unsigned short [174]
o vquic-tls: fix SSL backend type for QUIC connections using gnutls [29]
@@ -210,16 +224,17 @@ advice from friends like these:
adamse on github, Ahmad Gani, Alice Lee Poetics, Ammar Faizi, Anthony Hu,
Berthin Torres Callañaupa, Caolán McNamara, Cole Leavitt, d1r3ct0r,
- Dan Fandrich, Daniel Böhmer, Daniel Stenberg, David Zhuang, devgs on github,
- Dominik Tomecki, Eshan Kelkar, Harry Sintonen, IoannisGS on github,
- Jeroen Ooms, Kai Pastor, Karthik Das, kkmuffme on github,
- letshack9707 on hackerone, lf- on github, LoRd_MuldeR, Michał Petryka,
- nevakrien on github, Oxan van Leeuwen, Paul Gilmartin, Petar Popovic,
- Philippe Antoine, Pino Toscano, Qriist, Qriist on github, Ray Satiro,
- renovate[bot], rm-rmonaghan on github, Roberto Hidalgo, Schrijvers Luc,
+ Dan Fandrich, Daniel Böhmer, Daniel Engberg, Daniel Stenberg, David Zhuang,
+ devgs on github, Dominik Tomecki, Eshan Kelkar, Google Big Sleep,
+ Harry Sintonen, IoannisGS on github, Jelle Raaijmakers, Jeroen Ooms,
+ Kai Pastor, Karthik Das, kkmuffme on github, letshack9707 on hackerone,
+ lf- on github, LoRd_MuldeR, Michał Petryka, nevakrien on github,
+ Oxan van Leeuwen, Paul Gilmartin, Petar Popovic, Philippe Antoine,
+ Pino Toscano, Qriist, Qriist on github, Ray Satiro, renovate[bot],
+ rm-rmonaghan on github, Roberto Hidalgo, Samuel Henrique, Schrijvers Luc,
Sergio Durigan Junior, Stefan Eissing, Tal Regev, Todd Gamblin,
Viktor Szakats, Waldemar Kornewald, yaoy6 on github, ウさん
- (47 contributors)
+ (51 contributors)
References to bug reports and discussions on issues:
@@ -383,13 +398,27 @@ References to bug reports and discussions on issues:
[160] = https://curl.se/bug/?i=18177
[161] = https://curl.se/bug/?i=18190
[162] = https://curl.se/bug/?i=18230
+ [163] = https://curl.se/bug/?i=18287
+ [164] = https://curl.se/bug/?i=18282
[165] = https://curl.se/bug/?i=18124
+ [166] = https://curl.se/bug/?i=18271
[168] = https://curl.se/bug/?i=18170
[169] = https://curl.se/bug/?i=18171
+ [172] = https://curl.se/bug/?i=18190
[173] = https://curl.se/bug/?i=18123
[174] = https://curl.se/bug/?i=18173
[175] = https://curl.se/bug/?i=18157
[176] = https://curl.se/bug/?i=17974
[178] = https://curl.se/bug/?i=18216
+ [179] = https://curl.se/bug/?i=18272
+ [180] = https://curl.se/bug/?i=18254
[183] = https://curl.se/bug/?i=18208
[184] = https://curl.se/bug/?i=18206
+ [185] = https://curl.se/bug/?i=18266
+ [186] = https://curl.se/bug/?i=18264
+ [187] = https://curl.se/bug/?i=18246
+ [189] = https://curl.se/bug/?i=18260
+ [190] = https://curl.se/bug/?i=18259
+ [193] = https://curl.se/bug/?i=17683
+ [194] = https://curl.se/bug/?i=18243
+ [196] = https://curl.se/bug/?i=18247
diff --git a/docs/examples/cacertinmem.c b/docs/examples/cacertinmem.c
index 3a409dc5b..9b39667af 100644
--- a/docs/examples/cacertinmem.c
+++ b/docs/examples/cacertinmem.c
@@ -49,22 +49,22 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *pointer)
/* replace the XXX with the actual CA certificates */
static const char mypem[] =
"-----BEGIN CERTIFICATE-----\n"
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
"-----END CERTIFICATE-----\n";
BIO *cbio = BIO_new_mem_buf(mypem, sizeof(mypem));
diff --git a/docs/examples/usercertinmem.c b/docs/examples/usercertinmem.c
index 49722ca30..536b65b49 100644
--- a/docs/examples/usercertinmem.c
+++ b/docs/examples/usercertinmem.c
@@ -61,36 +61,36 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *pointer)
const char *mypem =
/* replace the XXX with the actual CA certificate */
- "-----BEGIN CERTIFICATE-----\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
+ "-----BEGIN CERTIFICATE-----\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
"-----END CERTIFICATE-----\n";
/* replace the XXX with the actual RSA key */
const char *mykey =
- "-----BEGIN RSA PRIVATE KEY-----\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
+ "-----BEGIN RSA PRIVATE KEY-----\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
"-----END RSA PRIVATE KEY-----\n";
(void)curl; /* avoid warnings */
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md b/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md
index 81edea682..6dc81a086 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md
+++ b/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md
@@ -83,15 +83,14 @@ int main(void)
{
CURL *ch;
CURLcode rv;
- char *mypem = /* example CA cert PEM - shortened */
+ char *mypem = /* CA cert in PEM format, replace the XXXs */
"-----BEGIN CERTIFICATE-----\n"
- "MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290\n"
- "IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB\n"
- "IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA\n"
- "Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO\n"
- "GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk\n"
- "zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW\n"
- "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
"-----END CERTIFICATE-----\n";
curl_global_init(CURL_GLOBAL_ALL);
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md b/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md
index ebf4c2ec3..75e1dc8ed 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md
+++ b/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md
@@ -60,7 +60,9 @@ callbacks to add additional validation code for certificates, and even to
change the actual URI of an HTTPS request.
For OpenSSL, asynchronous certificate verification via *SSL_set_retry_verify*
-is supported. (Added in 8.3.0)
+is supported. When *SSL_set_retry_verify* is set, the transfer is paused.
+When verification should continue, call curl_easy_pause(3) to unpause
+the transfer. (Added in 8.3.0, Pausing added in 8.16.0)
The CURLOPT_SSL_CTX_FUNCTION(3) callback allows the application to reach in
and modify SSL details in the connection without libcurl itself knowing
@@ -134,15 +136,14 @@ int main(void)
{
CURL *ch;
CURLcode rv;
- char *mypem = /* example CA cert PEM - shortened */
+ char *mypem = /* CA cert in PEM format, replace the XXXs */
"-----BEGIN CERTIFICATE-----\n"
- "MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290\n"
- "IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB\n"
- "IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA\n"
- "Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO\n"
- "GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk\n"
- "zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW\n"
- "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
"-----END CERTIFICATE-----\n";
curl_global_init(CURL_GLOBAL_ALL);
diff --git a/lib/multi.c b/lib/multi.c
index d38155cd9..1c09b14b6 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -1026,9 +1026,13 @@ CURLMcode Curl_multi_pollset(struct Curl_easy *data,
case MSTATE_CONNECTING:
case MSTATE_TUNNELING:
- result = mstate_connecting_pollset(data, ps);
- if(!result)
- result = Curl_conn_adjust_pollset(data, data->conn, ps);
+ if(!Curl_xfer_recv_is_paused(data)) {
+ result = mstate_connecting_pollset(data, ps);
+ if(!result)
+ result = Curl_conn_adjust_pollset(data, data->conn, ps);
+ }
+ else
+ expect_sockets = FALSE;
break;
case MSTATE_PROTOCONNECT:
@@ -2434,22 +2438,24 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case MSTATE_CONNECTING:
/* awaiting a completion of an asynch TCP connect */
DEBUGASSERT(data->conn);
- result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &connected);
- if(connected && !result) {
- if(!data->conn->bits.reuse &&
- Curl_conn_is_multiplex(data->conn, FIRSTSOCKET)) {
- /* new connection, can multiplex, wake pending handles */
- process_pending_handles(data->multi);
+ if(!Curl_xfer_recv_is_paused(data)) {
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &connected);
+ if(connected && !result) {
+ if(!data->conn->bits.reuse &&
+ Curl_conn_is_multiplex(data->conn, FIRSTSOCKET)) {
+ /* new connection, can multiplex, wake pending handles */
+ process_pending_handles(data->multi);
+ }
+ rc = CURLM_CALL_MULTI_PERFORM;
+ multistate(data, MSTATE_PROTOCONNECT);
+ }
+ else if(result) {
+ /* failure detected */
+ multi_posttransfer(data);
+ multi_done(data, result, TRUE);
+ stream_error = TRUE;
+ break;
}
- rc = CURLM_CALL_MULTI_PERFORM;
- multistate(data, MSTATE_PROTOCONNECT);
- }
- else if(result) {
- /* failure detected */
- multi_posttransfer(data);
- multi_done(data, result, TRUE);
- stream_error = TRUE;
- break;
}
break;
diff --git a/lib/sendf.c b/lib/sendf.c
index 6bd4b1bfb..43b30ecc7 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -293,9 +293,9 @@ static CURLcode cw_download_write(struct Curl_easy *data,
}
if((type & CLIENTWRITE_EOS) && !data->req.no_body &&
- (data->req.maxdownload > data->req.bytecount)) {
+ (data->req.size > data->req.bytecount)) {
failf(data, "end of response with %" FMT_OFF_T " bytes missing",
- data->req.maxdownload - data->req.bytecount);
+ data->req.size - data->req.bytecount);
return CURLE_PARTIAL_FILE;
}
}
diff --git a/lib/socks.c b/lib/socks.c
index 4f9c98dba..8084489c9 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -529,6 +529,110 @@ CONNECT_REQ_INIT:
return CURLPX_OK; /* Proxy was successful! */
}
+static CURLproxycode socks5_init(struct Curl_cfilter *cf,
+ struct socks_state *sx,
+ struct Curl_easy *data,
+ const bool socks5_resolve_local,
+ const size_t hostname_len)
+{
+ struct connectdata *conn = cf->conn;
+ const unsigned char auth = data->set.socks5auth;
+ unsigned char *socksreq = sx->buffer;
+
+ if(conn->bits.httpproxy)
+ CURL_TRC_CF(data, cf, "SOCKS5: connecting to HTTP proxy %s port %d",
+ sx->hostname, sx->remote_port);
+
+ /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
+ if(!socks5_resolve_local && hostname_len > 255) {
+ failf(data, "SOCKS5: the destination hostname is too long to be "
+ "resolved remotely by the proxy.");
+ return CURLPX_LONG_HOSTNAME;
+ }
+
+ if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
+ infof(data, "warning: unsupported value passed to "
+ "CURLOPT_SOCKS5_AUTH: %u", auth);
+ if(!(auth & CURLAUTH_BASIC))
+ /* disable username/password auth */
+ sx->proxy_user = NULL;
+
+ if(!sx->outstanding) {
+ size_t idx = 0;
+ socksreq[idx++] = 5; /* version */
+ idx++; /* number of authentication methods */
+ socksreq[idx++] = 0; /* no authentication */
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ if(auth & CURLAUTH_GSSAPI)
+ socksreq[idx++] = 1; /* GSS-API */
+#endif
+ if(sx->proxy_user)
+ socksreq[idx++] = 2; /* username/password */
+ /* write the number of authentication methods */
+ socksreq[1] = (unsigned char) (idx - 2);
+
+ sx->outp = socksreq;
+ DEBUGASSERT(idx <= sizeof(sx->buffer));
+ sx->outstanding = idx;
+ }
+
+ return socks_state_send(cf, sx, data, CURLPX_SEND_CONNECT,
+ "initial SOCKS5 request");
+}
+
+static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf,
+ struct socks_state *sx,
+ struct Curl_easy *data)
+{
+ /* Needs username and password */
+ size_t proxy_user_len, proxy_password_len;
+ size_t len = 0;
+ unsigned char *socksreq = sx->buffer;
+
+ if(sx->proxy_user && sx->proxy_password) {
+ proxy_user_len = strlen(sx->proxy_user);
+ proxy_password_len = strlen(sx->proxy_password);
+ }
+ else {
+ proxy_user_len = 0;
+ proxy_password_len = 0;
+ }
+
+ /* username/password request looks like
+ * +----+------+----------+------+----------+
+ * |VER | ULEN | UNAME | PLEN | PASSWD |
+ * +----+------+----------+------+----------+
+ * | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+ * +----+------+----------+------+----------+
+ */
+ socksreq[len++] = 1; /* username/pw subnegotiation version */
+ socksreq[len++] = (unsigned char) proxy_user_len;
+ if(sx->proxy_user && proxy_user_len) {
+ /* the length must fit in a single byte */
+ if(proxy_user_len > 255) {
+ failf(data, "Excessive username length for proxy auth");
+ return CURLPX_LONG_USER;
+ }
+ memcpy(socksreq + len, sx->proxy_user, proxy_user_len);
+ }
+ len += proxy_user_len;
+ socksreq[len++] = (unsigned char) proxy_password_len;
+ if(sx->proxy_password && proxy_password_len) {
+ /* the length must fit in a single byte */
+ if(proxy_password_len > 255) {
+ failf(data, "Excessive password length for proxy auth");
+ return CURLPX_LONG_PASSWD;
+ }
+ memcpy(socksreq + len, sx->proxy_password, proxy_password_len);
+ }
+ len += proxy_password_len;
+ sxstate(sx, cf, data, CONNECT_AUTH_SEND);
+ DEBUGASSERT(len <= sizeof(sx->buffer));
+ sx->outstanding = len;
+ sx->outp = socksreq;
+ return CURLPX_OK;
+}
+
/*
* This function logs in to a SOCKS5 proxy and sends the specifics to the final
* destination server.
@@ -555,66 +659,20 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
*/
struct connectdata *conn = cf->conn;
unsigned char *socksreq = sx->buffer;
- size_t idx;
CURLcode result;
CURLproxycode presult;
bool socks5_resolve_local =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS5);
const size_t hostname_len = strlen(sx->hostname);
size_t len = 0;
- const unsigned char auth = data->set.socks5auth;
bool allow_gssapi = FALSE;
struct Curl_dns_entry *dns = NULL;
switch(sx->state) {
case CONNECT_SOCKS_INIT:
- if(conn->bits.httpproxy)
- CURL_TRC_CF(data, cf, "SOCKS5: connecting to HTTP proxy %s port %d",
- sx->hostname, sx->remote_port);
-
- /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
- if(!socks5_resolve_local && hostname_len > 255) {
- failf(data, "SOCKS5: the destination hostname is too long to be "
- "resolved remotely by the proxy.");
- return CURLPX_LONG_HOSTNAME;
- }
-
- if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
- infof(data, "warning: unsupported value passed to "
- "CURLOPT_SOCKS5_AUTH: %u", auth);
- if(!(auth & CURLAUTH_BASIC))
- /* disable username/password auth */
- sx->proxy_user = NULL;
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
- if(auth & CURLAUTH_GSSAPI)
- allow_gssapi = TRUE;
-#endif
-
- if(!sx->outstanding) {
- idx = 0;
- socksreq[idx++] = 5; /* version */
- idx++; /* number of authentication methods */
- socksreq[idx++] = 0; /* no authentication */
- if(allow_gssapi)
- socksreq[idx++] = 1; /* GSS-API */
- if(sx->proxy_user)
- socksreq[idx++] = 2; /* username/password */
- /* write the number of authentication methods */
- socksreq[1] = (unsigned char) (idx - 2);
-
- sx->outp = socksreq;
- DEBUGASSERT(idx <= sizeof(sx->buffer));
- sx->outstanding = idx;
- }
-
- presult = socks_state_send(cf, sx, data, CURLPX_SEND_CONNECT,
- "initial SOCKS5 request");
- if(CURLPX_OK != presult)
+ presult = socks5_init(cf, sx, data, socks5_resolve_local, hostname_len);
+ if(presult || sx->outstanding)
return presult;
- else if(sx->outstanding) {
- /* remain in sending state */
- return CURLPX_OK;
- }
sxstate(sx, cf, data, CONNECT_SOCKS_READ);
goto CONNECT_SOCKS_READ_INIT;
case CONNECT_SOCKS_SEND:
@@ -635,6 +693,10 @@ CONNECT_SOCKS_READ_INIT:
case CONNECT_SOCKS_READ:
presult = socks_state_recv(cf, sx, data, CURLPX_RECV_CONNECT,
"initial SOCKS5 response");
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ if(data->set.socks5auth & CURLAUTH_GSSAPI)
+ allow_gssapi = TRUE;
+#endif
if(CURLPX_OK != presult)
return presult;
else if(sx->outstanding) {
@@ -690,52 +752,10 @@ CONNECT_SOCKS_READ_INIT:
break;
CONNECT_AUTH_INIT:
- case CONNECT_AUTH_INIT: {
- /* Needs username and password */
- size_t proxy_user_len, proxy_password_len;
- if(sx->proxy_user && sx->proxy_password) {
- proxy_user_len = strlen(sx->proxy_user);
- proxy_password_len = strlen(sx->proxy_password);
- }
- else {
- proxy_user_len = 0;
- proxy_password_len = 0;
- }
-
- /* username/password request looks like
- * +----+------+----------+------+----------+
- * |VER | ULEN | UNAME | PLEN | PASSWD |
- * +----+------+----------+------+----------+
- * | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
- * +----+------+----------+------+----------+
- */
- len = 0;
- socksreq[len++] = 1; /* username/pw subnegotiation version */
- socksreq[len++] = (unsigned char) proxy_user_len;
- if(sx->proxy_user && proxy_user_len) {
- /* the length must fit in a single byte */
- if(proxy_user_len > 255) {
- failf(data, "Excessive username length for proxy auth");
- return CURLPX_LONG_USER;
- }
- memcpy(socksreq + len, sx->proxy_user, proxy_user_len);
- }
- len += proxy_user_len;
- socksreq[len++] = (unsigned char) proxy_password_len;
- if(sx->proxy_password && proxy_password_len) {
- /* the length must fit in a single byte */
- if(proxy_password_len > 255) {
- failf(data, "Excessive password length for proxy auth");
- return CURLPX_LONG_PASSWD;
- }
- memcpy(socksreq + len, sx->proxy_password, proxy_password_len);
- }
- len += proxy_password_len;
- sxstate(sx, cf, data, CONNECT_AUTH_SEND);
- DEBUGASSERT(len <= sizeof(sx->buffer));
- sx->outstanding = len;
- sx->outp = socksreq;
- }
+ case CONNECT_AUTH_INIT:
+ presult = socks5_auth_init(cf, sx, data);
+ if(presult)
+ return presult;
FALLTHROUGH();
case CONNECT_AUTH_SEND:
presult = socks_state_send(cf, sx, data, CURLPX_SEND_AUTH,
diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c
index 556eda0cb..7cd0402a9 100644
--- a/lib/vssh/wolfssh.c
+++ b/lib/vssh/wolfssh.c
@@ -463,6 +463,150 @@ error:
return CURLE_FAILED_INIT;
}
+static CURLcode wssh_sftp_upload_init(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sftp_scp,
+ bool *block)
+{
+ word32 flags;
+ WS_SFTP_FILEATRB createattrs;
+ struct connectdata *conn = data->conn;
+ int rc;
+ if(data->state.resume_from) {
+ WS_SFTP_FILEATRB attrs;
+ if(data->state.resume_from < 0) {
+ rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path,
+ &attrs);
+ if(rc != WS_SUCCESS)
+ return CURLE_SSH;
+
+ if(rc) {
+ data->state.resume_from = 0;
+ }
+ else {
+ curl_off_t size = ((curl_off_t)attrs.sz[1] << 32) | attrs.sz[0];
+ if(size < 0) {
+ failf(data, "Bad file size (%" FMT_OFF_T ")", size);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ data->state.resume_from = size;
+ }
+ }
+ }
+
+ if(data->set.remote_append)
+ /* Try to open for append, but create if nonexisting */
+ flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND;
+ else if(data->state.resume_from > 0)
+ /* If we have restart position then open for append */
+ flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND;
+ else
+ /* Clear file before writing (normal behavior) */
+ flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC;
+
+ memset(&createattrs, 0, sizeof(createattrs));
+ createattrs.per = (word32)data->set.new_file_perms;
+ sshc->handleSz = sizeof(sshc->handle);
+ rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
+ flags, &createattrs,
+ sshc->handle, &sshc->handleSz);
+ if(rc == WS_FATAL_ERROR)
+ rc = wolfSSH_get_error(sshc->ssh_session);
+ if(rc == WS_WANT_READ) {
+ *block = TRUE;
+ conn->waitfor = KEEP_RECV;
+ return CURLE_OK;
+ }
+ else if(rc == WS_WANT_WRITE) {
+ *block = TRUE;
+ conn->waitfor = KEEP_SEND;
+ return CURLE_OK;
+ }
+ else if(rc == WS_SUCCESS) {
+ infof(data, "wolfssh SFTP open succeeded");
+ }
+ else {
+ failf(data, "wolfssh SFTP upload open failed: %d", rc);
+ return CURLE_SSH;
+ }
+ wssh_state(data, sshc, SSH_SFTP_DOWNLOAD_STAT);
+
+ /* If we have a restart point then we need to seek to the correct
+ position. */
+ if(data->state.resume_from > 0) {
+ /* Let's read off the proper amount of bytes from the input. */
+ int seekerr = CURL_SEEKFUNC_OK;
+ if(data->set.seek_func) {
+ Curl_set_in_callback(data, TRUE);
+ seekerr = data->set.seek_func(data->set.seek_client,
+ data->state.resume_from, SEEK_SET);
+ Curl_set_in_callback(data, FALSE);
+ }
+
+ if(seekerr != CURL_SEEKFUNC_OK) {
+ curl_off_t passed = 0;
+
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+ failf(data, "Could not seek stream");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
+ do {
+ char scratch[4*1024];
+ size_t readthisamountnow =
+ (data->state.resume_from - passed >
+ (curl_off_t)sizeof(scratch)) ?
+ sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
+
+ size_t actuallyread;
+ Curl_set_in_callback(data, TRUE);
+ actuallyread = data->state.fread_func(scratch, 1,
+ readthisamountnow,
+ data->state.in);
+ Curl_set_in_callback(data, FALSE);
+
+ passed += actuallyread;
+ if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Failed to read data");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ } while(passed < data->state.resume_from);
+ }
+
+ /* now, decrease the size of the read */
+ if(data->state.infilesize > 0) {
+ data->state.infilesize -= data->state.resume_from;
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ }
+
+ sshc->offset += data->state.resume_from;
+ }
+ if(data->state.infilesize > 0) {
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ }
+ /* upload data */
+ Curl_xfer_setup_send(data, FIRSTSOCKET);
+
+ /* not set by Curl_xfer_setup to preserve keepon bits */
+ data->conn->recv_idx = FIRSTSOCKET;
+
+ /* store this original bitmask setup to use later on if we cannot
+ figure out a "real" bitmask */
+ sshc->orig_waitfor = data->req.keepon;
+
+ /* since we do not really wait for anything at this point, we want the state
+ machine to move on as soon as possible */
+ Curl_multi_mark_dirty(data);
+
+ wssh_state(data, sshc, SSH_STOP);
+
+ return CURLE_OK;
+}
+
/*
* wssh_statemach_act() runs the SSH state machine as far as it can without
* blocking and without reaching the end. The data the pointer 'block' points
@@ -597,148 +741,10 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data,
wssh_state(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
}
break;
- case SSH_SFTP_UPLOAD_INIT: {
- word32 flags;
- WS_SFTP_FILEATRB createattrs;
- if(data->state.resume_from) {
- WS_SFTP_FILEATRB attrs;
- if(data->state.resume_from < 0) {
- rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path,
- &attrs);
- if(rc != WS_SUCCESS)
- break;
-
- if(rc) {
- data->state.resume_from = 0;
- }
- else {
- curl_off_t size = ((curl_off_t)attrs.sz[1] << 32) | attrs.sz[0];
- if(size < 0) {
- failf(data, "Bad file size (%" FMT_OFF_T ")", size);
- return CURLE_BAD_DOWNLOAD_RESUME;
- }
- data->state.resume_from = size;
- }
- }
- }
-
- if(data->set.remote_append)
- /* Try to open for append, but create if nonexisting */
- flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND;
- else if(data->state.resume_from > 0)
- /* If we have restart position then open for append */
- flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND;
- else
- /* Clear file before writing (normal behavior) */
- flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC;
-
- memset(&createattrs, 0, sizeof(createattrs));
- createattrs.per = (word32)data->set.new_file_perms;
- sshc->handleSz = sizeof(sshc->handle);
- rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
- flags, &createattrs,
- sshc->handle, &sshc->handleSz);
- if(rc == WS_FATAL_ERROR)
- rc = wolfSSH_get_error(sshc->ssh_session);
- if(rc == WS_WANT_READ) {
- *block = TRUE;
- conn->waitfor = KEEP_RECV;
- return CURLE_OK;
- }
- else if(rc == WS_WANT_WRITE) {
- *block = TRUE;
- conn->waitfor = KEEP_SEND;
- return CURLE_OK;
- }
- else if(rc == WS_SUCCESS) {
- infof(data, "wolfssh SFTP open succeeded");
- }
- else {
- failf(data, "wolfssh SFTP upload open failed: %d", rc);
- return CURLE_SSH;
- }
- wssh_state(data, sshc, SSH_SFTP_DOWNLOAD_STAT);
-
- /* If we have a restart point then we need to seek to the correct
- position. */
- if(data->state.resume_from > 0) {
- /* Let's read off the proper amount of bytes from the input. */
- int seekerr = CURL_SEEKFUNC_OK;
- if(data->set.seek_func) {
- Curl_set_in_callback(data, TRUE);
- seekerr = data->set.seek_func(data->set.seek_client,
- data->state.resume_from, SEEK_SET);
- Curl_set_in_callback(data, FALSE);
- }
-
- if(seekerr != CURL_SEEKFUNC_OK) {
- curl_off_t passed = 0;
-
- if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
- failf(data, "Could not seek stream");
- return CURLE_FTP_COULDNT_USE_REST;
- }
- /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
- do {
- char scratch[4*1024];
- size_t readthisamountnow =
- (data->state.resume_from - passed >
- (curl_off_t)sizeof(scratch)) ?
- sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
-
- size_t actuallyread;
- Curl_set_in_callback(data, TRUE);
- actuallyread = data->state.fread_func(scratch, 1,
- readthisamountnow,
- data->state.in);
- Curl_set_in_callback(data, FALSE);
-
- passed += actuallyread;
- if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
- /* this checks for greater-than only to make sure that the
- CURL_READFUNC_ABORT return code still aborts */
- failf(data, "Failed to read data");
- return CURLE_FTP_COULDNT_USE_REST;
- }
- } while(passed < data->state.resume_from);
- }
-
- /* now, decrease the size of the read */
- if(data->state.infilesize > 0) {
- data->state.infilesize -= data->state.resume_from;
- data->req.size = data->state.infilesize;
- Curl_pgrsSetUploadSize(data, data->state.infilesize);
- }
-
- sshc->offset += data->state.resume_from;
- }
- if(data->state.infilesize > 0) {
- data->req.size = data->state.infilesize;
- Curl_pgrsSetUploadSize(data, data->state.infilesize);
- }
- /* upload data */
- Curl_xfer_setup_send(data, FIRSTSOCKET);
-
- /* not set by Curl_xfer_setup to preserve keepon bits */
- data->conn->recv_idx = FIRSTSOCKET;
-
- if(result) {
- wssh_state(data, sshc, SSH_SFTP_CLOSE);
- sshc->actualcode = result;
- }
- else {
- /* store this original bitmask setup to use later on if we cannot
- figure out a "real" bitmask */
- sshc->orig_waitfor = data->req.keepon;
-
- /* since we do not really wait for anything at this point, we want the
- state machine to move on as soon as possible */
- Curl_multi_mark_dirty(data);
-
- wssh_state(data, sshc, SSH_STOP);
- }
+ case SSH_SFTP_UPLOAD_INIT:
+ result = wssh_sftp_upload_init(data, sshc, sftp_scp, block);
break;
- }
+
case SSH_SFTP_DOWNLOAD_INIT:
sshc->handleSz = sizeof(sshc->handle);
rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 06ae10232..a820a98b8 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -107,19 +107,6 @@ struct mbed_ssl_backend_data {
#define mbedtls_strerror(a,b,c) b[0] = 0
#endif
-/* PSA can be used independently of TLS 1.3 */
-#if defined(MBEDTLS_USE_PSA_CRYPTO) && MBEDTLS_VERSION_NUMBER >= 0x03060000
-#define HAS_PSA_SUPPORT
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && MBEDTLS_VERSION_NUMBER >= 0x03060000
-#define HAS_TLS13_SUPPORT
-#endif
-
-#if defined(HAS_TLS13_SUPPORT) && defined(MBEDTLS_SSL_SESSION_TICKETS)
-#define HAS_SESSION_TICKETS
-#endif
-
#ifdef HAS_THREADING_SUPPORT
static mbedtls_entropy_context ts_entropy;
@@ -260,7 +247,7 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data,
mbedtls_ssl_protocol_version ver_min = MBEDTLS_SSL_VERSION_TLS1_2;
mbedtls_ssl_protocol_version ver_max =
-#ifdef HAS_TLS13_SUPPORT
+#ifdef MBEDTLS_SSL_PROTO_TLS1_3
MBEDTLS_SSL_VERSION_TLS1_3
#else
MBEDTLS_SSL_VERSION_TLS1_2
@@ -276,7 +263,7 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data,
ver_min = MBEDTLS_SSL_VERSION_TLS1_2;
break;
case CURL_SSLVERSION_TLSv1_3:
-#ifdef HAS_TLS13_SUPPORT
+#ifdef MBEDTLS_SSL_PROTO_TLS1_3
ver_min = MBEDTLS_SSL_VERSION_TLS1_3;
break;
#endif
@@ -290,7 +277,7 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data,
case CURL_SSLVERSION_MAX_DEFAULT:
case CURL_SSLVERSION_MAX_NONE:
case CURL_SSLVERSION_MAX_TLSv1_3:
-#ifdef HAS_TLS13_SUPPORT
+#ifdef MBEDTLS_SSL_PROTO_TLS1_3
ver_max = MBEDTLS_SSL_VERSION_TLS1_3;
break;
#endif
@@ -363,7 +350,7 @@ mbed_set_selected_ciphers(struct Curl_easy *data,
if(!selected)
return CURLE_OUT_OF_MEMORY;
-#ifndef HAS_TLS13_SUPPORT
+#ifndef MBEDTLS_SSL_PROTO_TLS1_3
(void)ciphers13, (void)j;
#else
if(!ciphers13) {
@@ -411,7 +398,7 @@ add_ciphers:
selected[count++] = id;
}
-#ifdef HAS_TLS13_SUPPORT
+#ifdef MBEDTLS_SSL_PROTO_TLS1_3
if(ciphers == ciphers13 && ciphers12) {
ciphers = ciphers12;
goto add_ciphers;
@@ -760,7 +747,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_SSL_CONNECT_ERROR;
}
-#if defined(HAS_SESSION_TICKETS) && MBEDTLS_VERSION_NUMBER >= 0x03060100
+#ifdef MBEDTLS_SSL_SESSION_TICKETS
/* New in mbedTLS 3.6.1, need to enable, default is now disabled */
mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(&backend->config,
MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED);
@@ -799,7 +786,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
mbedtls_bio_cf_read,
NULL /* rev_timeout() */);
-#ifndef HAS_TLS13_SUPPORT
+#ifndef MBEDTLS_SSL_PROTO_TLS1_3
if(conn_config->cipher_list) {
CURLcode result = mbed_set_selected_ciphers(data, backend,
conn_config->cipher_list,
@@ -1149,7 +1136,7 @@ static CURLcode mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> -0x%04X",
len, -nwritten);
result = ((nwritten == MBEDTLS_ERR_SSL_WANT_WRITE)
-#ifdef HAS_TLS13_SUPPORT
+#ifdef MBEDTLS_SSL_PROTO_TLS1_3
|| (nwritten == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
#endif
) ? CURLE_AGAIN : CURLE_SEND_ERROR;
@@ -1219,7 +1206,7 @@ static CURLcode mbedtls_shutdown(struct Curl_cfilter *cf,
* WANT_READ, but has not encountered an EAGAIN. */
if(ret == MBEDTLS_ERR_SSL_WANT_READ)
ret = mbedtls_ssl_read(&backend->ssl, buf, sizeof(buf));
-#ifdef HAS_TLS13_SUPPORT
+#ifdef MBEDTLS_SSL_PROTO_TLS1_3
if(ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
continue;
#endif
@@ -1301,7 +1288,7 @@ static CURLcode mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
CURL_TRC_CF(data, cf, "mbedtls_ssl_read(len=%zu) -> -0x%04X",
buffersize, -nread);
switch(nread) {
-#ifdef HAS_SESSION_TICKETS
+#ifdef MBEDTLS_SSL_SESSION_TICKETS
case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET:
mbed_new_session(cf, data);
FALLTHROUGH();
@@ -1431,7 +1418,7 @@ static int mbedtls_init(void)
#ifdef HAS_THREADING_SUPPORT
entropy_init_mutex(&ts_entropy);
#endif
-#ifdef HAS_PSA_SUPPORT
+#ifdef MBEDTLS_USE_PSA_CRYPTO /* requires mbedTLS 3.6.0+ */
{
int ret;
#ifdef HAS_THREADING_SUPPORT
@@ -1444,7 +1431,7 @@ static int mbedtls_init(void)
if(ret != PSA_SUCCESS)
return 0;
}
-#endif /* HAS_PSA_SUPPORT */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
return 1;
}
@@ -1498,7 +1485,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
SSLSUPP_CERTINFO |
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_SSL_CTX |
-#ifdef HAS_TLS13_SUPPORT
+#ifdef MBEDTLS_SSL_PROTO_TLS1_3 /* requires mbedTLS 3.6.0+ */
SSLSUPP_TLS13_CIPHERSUITES |
#endif
SSLSUPP_HTTPS_PROXY |
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index dc4a6d122..e25c57304 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -61,6 +61,7 @@
#include "../vauth/vauth.h"
#include "keylog.h"
#include "hostcheck.h"
+#include "../transfer.h"
#include "../multiif.h"
#include "../curlx/strparse.h"
#include "../strdup.h"
@@ -850,13 +851,19 @@ static void ossl_keylog_callback(const SSL *ssl, const char *line)
static void
ossl_log_tls12_secret(const SSL *ssl, bool *keylog_done)
{
- const SSL_SESSION *session = SSL_get_session(ssl);
+ const SSL_SESSION *session;
unsigned char client_random[SSL3_RANDOM_SIZE];
unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
int master_key_length = 0;
- if(!session || *keylog_done)
+ ERR_set_mark();
+
+ session = SSL_get_session(ssl);
+
+ if(!session || *keylog_done) {
+ ERR_pop_to_mark();
return;
+ }
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
/* ssl->s3 is not checked in OpenSSL 1.1.0-pre6, but let's assume that
@@ -872,6 +879,8 @@ ossl_log_tls12_secret(const SSL *ssl, bool *keylog_done)
}
#endif
+ ERR_pop_to_mark();
+
/* The handshake has not progressed sufficiently yet, or this is a TLS 1.3
* session (when curl was built with older OpenSSL headers and running with
* newer OpenSSL runtime libraries). */
@@ -3327,10 +3336,8 @@ static CURLcode import_windows_cert_store(struct Curl_easy *data,
continue;
x509 = d2i_X509(NULL, &encoded_cert, (long)pContext->cbCertEncoded);
- if(!x509) {
- ERR_clear_error();
+ if(!x509)
continue;
- }
/* Try to import the certificate. This may fail for legitimate
reasons such as duplicate certificate, which is allowed by MS but
@@ -3661,6 +3668,8 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
!ssl_config->primary.CRLfile &&
!ssl_config->native_ca_store;
+ ERR_set_mark();
+
cached_store = ossl_get_cached_x509_store(cf, data);
if(cached_store && cache_criteria_met && X509_STORE_up_ref(cached_store)) {
SSL_CTX_set_cert_store(ssl_ctx, cached_store);
@@ -3674,6 +3683,8 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
}
}
+ ERR_pop_to_mark();
+
return result;
}
#else /* HAVE_SSL_X509_STORE_SHARE */
@@ -3681,9 +3692,17 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data,
SSL_CTX *ssl_ctx)
{
- X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
+ CURLcode result;
+ X509_STORE *store;
+
+ ERR_set_mark();
+
+ store = SSL_CTX_get_cert_store(ssl_ctx);
+ result = ossl_populate_x509_store(cf, data, store);
- return ossl_populate_x509_store(cf, data, store);
+ ERR_pop_to_mark();
+
+ return result;
}
#endif /* HAVE_SSL_X509_STORE_SHARE */
@@ -4584,7 +4603,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
#ifdef SSL_ERROR_WANT_RETRY_VERIFY
if(SSL_ERROR_WANT_RETRY_VERIFY == detail) {
CURL_TRC_CF(data, cf, "SSL_connect() -> want retry_verify");
- connssl->io_need = CURL_SSL_IO_NEED_RECV;
+ Curl_xfer_pause_recv(data, TRUE);
return CURLE_AGAIN;
}
#endif
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 1c0258e17..950cb2544 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -108,7 +108,7 @@ test718 test719 test720 test721 test722 test723 test724 test725 test726 \
test727 test728 test729 test730 test731 test732 test733 test734 test735 \
test736 test737 test738 test739 test740 test741 test742 test743 test744 \
test745 test746 test747 test748 test749 test750 test751 test752 test753 \
-test754 test755 test756 test757 \
+test754 test755 test756 test757 test758 \
test780 test781 test782 test783 test784 test785 test786 test787 test788 \
test789 test790 test791 test792 test793 test794 test796 test797 \
\
@@ -256,8 +256,8 @@ test2100 test2101 test2102 test2103 test2104 \
\
test2200 test2201 test2202 test2203 test2204 test2205 \
\
-test2300 test2301 test2302 test2303 test2304 test2306 \
-test2308 test2309 \
+test2300 test2301 test2302 test2303 test2304 test2306 test2307 test2308 \
+test2309 \
\
test2400 test2401 test2402 test2403 test2404 test2405 test2406 \
\
diff --git a/tests/data/test2307 b/tests/data/test2307
new file mode 100644
index 000000000..cbb581a4a
--- /dev/null
+++ b/tests/data/test2307
@@ -0,0 +1,60 @@
+<testcase>
+<info>
+<keywords>
+FTP
+EPSV
+RETR
+Range
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+0123456789abcdef
+0123456789abcdef
+0123456789abcdef
+0123456789abcdef
+</data>
+<datacheck nonewline="yes">
+0123456789abcdef
+0123456789abcdef
+0123456789abcdef
+012345678
+</datacheck>
+<size>
+64
+</size>
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+</server>
+<name>
+FTP retrieve a byte-range with end larger than file
+</name>
+<command>
+-r 4-1000 ftp://%HOSTIP:%FTPPORT/%TESTNUMBER
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+QUIT
+</strip>
+<protocol crlf="yes">
+USER anonymous
+PASS ftp@example.com
+PWD
+EPSV
+TYPE I
+SIZE %TESTNUMBER
+REST 4
+RETR %TESTNUMBER
+ABOR
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test758 b/tests/data/test758
new file mode 100644
index 000000000..a807ae9c8
--- /dev/null
+++ b/tests/data/test758
@@ -0,0 +1,53 @@
+<testcase>
+<info>
+<keywords>
+multi
+HTTPS
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6007
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+%repeat[1000 x foobar]%
+</data>
+</reply>
+
+<features>
+OpenSSL
+</features>
+
+# Client-side
+<client>
+<server>
+https
+</server>
+<tool>
+lib%TESTNUMBER
+</tool>
+<name>
+multi_socket interface transfer with callbacks returning error
+</name>
+<command>
+https://localhost:%HTTPSPORT/file%TESTNUMBER
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/ftpserver.pl b/tests/ftpserver.pl
index 927d4c66a..71d6774fd 100755
--- a/tests/ftpserver.pl
+++ b/tests/ftpserver.pl
@@ -51,6 +51,7 @@ BEGIN {
use IPC::Open2;
use Digest::MD5;
use File::Basename;
+use Time::HiRes;
use directories;
@@ -484,7 +485,7 @@ sub sendcontrol {
for(@a) {
sockfilt $_;
- portable_sleep($ctrldelay);
+ Time::HiRes::sleep($ctrldelay);
}
}
my $log;
@@ -521,7 +522,7 @@ sub senddata {
# pause between each byte
for (split(//,$l)) {
sockfiltsecondary $_;
- portable_sleep($datadelay);
+ Time::HiRes::sleep($datadelay);
}
}
}
@@ -3292,7 +3293,7 @@ while(1) {
logmsg("Sleep for $delay seconds\n");
my $twentieths = $delay * 20;
while($twentieths--) {
- portable_sleep(0.05) unless($got_exit_signal);
+ Time::HiRes::sleep(0.05) unless($got_exit_signal);
}
}
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index 5e1462108..6f51040c1 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -71,7 +71,7 @@ TESTS_C = \
lib661.c lib666.c lib667.c lib668.c \
lib670.c lib674.c lib676.c lib677.c lib678.c \
lib694.c lib695.c \
- lib751.c lib753.c \
+ lib751.c lib753.c lib758.c \
lib757.c \
lib1156.c \
lib1301.c lib1308.c \
diff --git a/tests/libtest/lib758.c b/tests/libtest/lib758.c
new file mode 100644
index 000000000..dfcbaebb3
--- /dev/null
+++ b/tests/libtest/lib758.c
@@ -0,0 +1,515 @@
+/***************************************************************************
+ * _ _ ____ _
+ * 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
+ *
+ ***************************************************************************/
+
+/*
+ * The purpose of this test is to make sure that if CURLMOPT_SOCKETFUNCTION or
+ * CURLMOPT_TIMERFUNCTION returns error, the associated transfer should be
+ * aborted correctly.
+ */
+
+#include "first.h"
+
+#include "testtrace.h"
+#include "memdebug.h"
+
+#ifdef USE_OPENSSL
+
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+
+#if ((OPENSSL_VERSION_NUMBER >= 0x30000000L) && \
+ !defined(LIBRESSL_VERSION_NUMBER) && \
+ !defined(OPENSSL_IS_BORINGSSL))
+#define T578_ENABLED
+#endif
+#endif
+
+#ifdef T578_ENABLED
+
+static struct t758_ctx {
+ int socket_calls;
+ int max_socket_calls;
+ int timer_calls;
+ int max_timer_calls;
+ int fake_async_cert_verification_pending;
+ int fake_async_cert_verification_finished;
+ int number_of_cert_verify_callbacks;
+ char buf[1024];
+} t758_ctx;
+
+static const char *t758_tag(void)
+{
+ curl_msnprintf(t758_ctx.buf, sizeof(t758_ctx.buf),
+ "[T758-%d-%d] [%d/%d]",
+ t758_ctx.max_socket_calls, t758_ctx.max_timer_calls,
+ t758_ctx.socket_calls, t758_ctx.timer_calls);
+ return t758_ctx.buf;
+}
+
+static void t758_msg(const char *msg)
+{
+ curl_mfprintf(stderr, "%s %s\n", t758_tag(), msg);
+}
+
+
+struct t758_Sockets {
+ curl_socket_t *sockets;
+ int count; /* number of sockets actually stored in array */
+ int max_count; /* max number of sockets that fit in allocated array */
+};
+
+struct t758_ReadWriteSockets {
+ struct t758_Sockets read, write;
+};
+
+/**
+ * Remove a file descriptor from a sockets array.
+ */
+static void t758_removeFd(struct t758_Sockets *sockets, curl_socket_t fd,
+ int mention)
+{
+ int i;
+
+ if(mention)
+ curl_mfprintf(stderr, "%s remove socket fd %" FMT_SOCKET_T "\n",
+ t758_tag(), fd);
+
+ for(i = 0; i < sockets->count; ++i) {
+ if(sockets->sockets[i] == fd) {
+ if(i < sockets->count - 1)
+ memmove(&sockets->sockets[i], &sockets->sockets[i + 1],
+ sizeof(curl_socket_t) * (sockets->count - (i + 1)));
+ --sockets->count;
+ }
+ }
+}
+
+/**
+ * Add a file descriptor to a sockets array.
+ * Return 0 on success, 1 on error.
+ */
+static int t758_addFd(struct t758_Sockets *sockets, curl_socket_t fd,
+ const char *what)
+{
+ /**
+ * To ensure we only have each file descriptor once, we remove it then add
+ * it again.
+ */
+ curl_mfprintf(stderr, "%s add socket fd %" FMT_SOCKET_T " for %s\n",
+ t758_tag(), fd, what);
+ t758_removeFd(sockets, fd, 0);
+ /*
+ * Allocate array storage when required.
+ */
+ if(!sockets->sockets) {
+ sockets->sockets = malloc(sizeof(curl_socket_t) * 20U);
+ if(!sockets->sockets)
+ return 1;
+ sockets->max_count = 20;
+ }
+ else if(sockets->count + 1 > sockets->max_count) {
+ curl_socket_t *ptr = realloc(sockets->sockets, sizeof(curl_socket_t) *
+ (sockets->max_count + 20));
+ if(!ptr)
+ /* cleanup in test_cleanup */
+ return 1;
+ sockets->sockets = ptr;
+ sockets->max_count += 20;
+ }
+ /*
+ * Add file descriptor to array.
+ */
+ sockets->sockets[sockets->count] = fd;
+ ++sockets->count;
+ return 0;
+}
+
+/**
+ * Callback invoked by curl to poll reading / writing of a socket.
+ */
+static int t758_curlSocketCallback(CURL *easy, curl_socket_t s, int action,
+ void *userp, void *socketp)
+{
+ struct t758_ReadWriteSockets *sockets = userp;
+
+ (void)easy;
+ (void)socketp;
+
+ t758_ctx.socket_calls++;
+ t758_msg("-> CURLMOPT_SOCKETFUNCTION");
+ if(t758_ctx.socket_calls == t758_ctx.max_socket_calls) {
+ t758_msg("<- CURLMOPT_SOCKETFUNCTION returns error");
+ return -1;
+ }
+
+ if(action == CURL_POLL_IN || action == CURL_POLL_INOUT)
+ if(t758_addFd(&sockets->read, s, "read"))
+ return -1; /* bail out */
+
+ if(action == CURL_POLL_OUT || action == CURL_POLL_INOUT)
+ if(t758_addFd(&sockets->write, s, "write"))
+ return -1;
+
+ if(action == CURL_POLL_REMOVE) {
+ t758_removeFd(&sockets->read, s, 1);
+ t758_removeFd(&sockets->write, s, 0);
+ }
+
+ return 0;
+}
+
+/**
+ * Callback invoked by curl to set a timeout.
+ */
+static int t758_curlTimerCallback(CURLM *multi, long timeout_ms, void *userp)
+{
+ struct curltime *timeout = userp;
+
+ (void)multi; /* unused */
+ t758_ctx.timer_calls++;
+ t758_msg("-> CURLMOPT_TIMERFUNCTION");
+ if(t758_ctx.timer_calls == t758_ctx.max_timer_calls) {
+ t758_msg("<- CURLMOPT_TIMERFUNCTION returns error");
+ return -1;
+ }
+ if(timeout_ms != -1) {
+ *timeout = curlx_now();
+ timeout->tv_usec += (int)timeout_ms * 1000;
+ }
+ else {
+ timeout->tv_sec = -1;
+ }
+ return 0;
+}
+
+static int t758_cert_verify_callback(X509_STORE_CTX *ctx, void *arg)
+{
+ SSL * ssl;
+ (void)arg; /* unused */
+ ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx,
+ SSL_get_ex_data_X509_STORE_CTX_idx());
+ t758_ctx.number_of_cert_verify_callbacks++;
+ if(!t758_ctx.fake_async_cert_verification_pending) {
+ t758_ctx.fake_async_cert_verification_pending = 1;
+ t758_msg(" initial t758_cert_verify_callback");
+ return SSL_set_retry_verify(ssl);
+ }
+ else if(t758_ctx.fake_async_cert_verification_finished) {
+ t758_msg(" final t758_cert_verify_callback");
+ return 1; /* success */
+ }
+ else {
+ t758_msg(" pending t758_cert_verify_callback");
+ return SSL_set_retry_verify(ssl);
+ }
+}
+
+static CURLcode
+t758_set_ssl_ctx_callback(CURL *curl, void *ssl_ctx, void *clientp)
+{
+ SSL_CTX *ctx = (SSL_CTX *) ssl_ctx;
+ (void)curl; /* unused */
+ SSL_CTX_set_cert_verify_callback(ctx, t758_cert_verify_callback, clientp);
+ return CURLE_OK;
+}
+
+/**
+ * Check for curl completion.
+ */
+static int t758_checkForCompletion(CURLM *curl, int *success)
+{
+ int result = 0;
+ *success = 0;
+ while(1) {
+ int numMessages;
+ CURLMsg *message = curl_multi_info_read(curl, &numMessages);
+ if(!message)
+ break;
+ if(message->msg == CURLMSG_DONE) {
+ result = 1;
+ if(message->data.result == CURLE_OK)
+ *success = 1;
+ else
+ *success = 0;
+ }
+ else {
+ curl_mfprintf(stderr, "%s got an unexpected message from curl: %i\n",
+ t758_tag(), message->msg);
+ result = 1;
+ *success = 0;
+ }
+ }
+ return result;
+}
+
+static ssize_t t758_getMicroSecondTimeout(struct curltime *timeout)
+{
+ struct curltime now;
+ ssize_t result;
+ now = curlx_now();
+ result = (ssize_t)((timeout->tv_sec - now.tv_sec) * 1000000 +
+ timeout->tv_usec - now.tv_usec);
+ if(result < 0)
+ result = 0;
+
+ return result;
+}
+
+/**
+ * Update a fd_set with all of the sockets in use.
+ */
+static void t758_updateFdSet(struct t758_Sockets *sockets, fd_set* fdset,
+ curl_socket_t *maxFd)
+{
+ int i;
+ for(i = 0; i < sockets->count; ++i) {
+#ifdef __DJGPP__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warith-conversion"
+#endif
+ FD_SET(sockets->sockets[i], fdset);
+#ifdef __DJGPP__
+#pragma GCC diagnostic pop
+#endif
+ if(*maxFd < sockets->sockets[i] + 1) {
+ *maxFd = sockets->sockets[i] + 1;
+ }
+ }
+}
+
+static CURLMcode t758_saction(CURLM *curl, curl_socket_t s,
+ int evBitmask, const char *info)
+{
+ int numhandles = 0;
+ CURLMcode result = curl_multi_socket_action(curl, s, evBitmask, &numhandles);
+ if(result != CURLM_OK) {
+ curl_mfprintf(stderr, "%s Curl error on %s (%i) %s\n",
+ t758_tag(), info, result, curl_multi_strerror(result));
+ }
+ return result;
+}
+
+/**
+ * Invoke curl when a file descriptor is set.
+ */
+static CURLMcode t758_checkFdSet(CURLM *curl, struct t758_Sockets *sockets,
+ fd_set *fdset, int evBitmask,
+ const char *name)
+{
+ int i;
+ CURLMcode result = CURLM_OK;
+ for(i = 0; i < sockets->count; ++i) {
+ if(FD_ISSET(sockets->sockets[i], fdset)) {
+ result = t758_saction(curl, sockets->sockets[i], evBitmask, name);
+ if(result)
+ break;
+ }
+ }
+ return result;
+}
+
+static CURLcode t758_one(const char *URL, int timer_fail_at,
+ int socket_fail_at)
+{
+ CURLcode res = CURLE_OK;
+ CURL *curl = NULL; CURLM *m = NULL;
+ struct t758_ReadWriteSockets sockets = {{NULL, 0, 0}, {NULL, 0, 0}};
+ int success = 0;
+ struct curltime timeout = {0};
+ timeout.tv_sec = (time_t)-1;
+
+ /* set the limits */
+ memset(&t758_ctx, 0, sizeof(t758_ctx));
+ t758_ctx.max_timer_calls = timer_fail_at;
+ t758_ctx.max_socket_calls = socket_fail_at;
+
+ t758_msg("start");
+ start_test_timing();
+
+ if(curl_global_sslset(CURLSSLBACKEND_OPENSSL, NULL, NULL) != CURLSSLSET_OK) {
+ t758_msg("could not set OpenSSL as backend");
+ res = CURLE_FAILED_INIT;
+ return res;
+ }
+
+ res_global_init(CURL_GLOBAL_ALL);
+ if(res != CURLE_OK)
+ return res;
+
+ curl_global_trace("all");
+
+
+ easy_init(curl);
+ debug_config.nohex = TRUE;
+ debug_config.tracetime = TRUE;
+ test_setopt(curl, CURLOPT_DEBUGDATA, &debug_config);
+ easy_setopt(curl, CURLOPT_DEBUGFUNCTION, libtest_debug_cb);
+ easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ /* specify target */
+ easy_setopt(curl, CURLOPT_URL, URL);
+
+ /* go verbose */
+ easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, t758_set_ssl_ctx_callback);
+
+ multi_init(m);
+
+ multi_setopt(m, CURLMOPT_SOCKETFUNCTION, t758_curlSocketCallback);
+ multi_setopt(m, CURLMOPT_SOCKETDATA, &sockets);
+
+ multi_setopt(m, CURLMOPT_TIMERFUNCTION, t758_curlTimerCallback);
+ multi_setopt(m, CURLMOPT_TIMERDATA, &timeout);
+
+ multi_add_handle(m, curl);
+
+ if(t758_saction(m, CURL_SOCKET_TIMEOUT, 0, "timeout")) {
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+ while(!t758_checkForCompletion(m, &success)) {
+ fd_set readSet, writeSet;
+ curl_socket_t maxFd = 0;
+ struct timeval tv = {0};
+ tv.tv_sec = 10;
+
+ if(t758_ctx.fake_async_cert_verification_pending &&
+ !t758_ctx.fake_async_cert_verification_finished) {
+ if(sockets.read.count || sockets.write.count) {
+ t758_msg("during verification there should be no sockets scheduled");
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+ if(t758_ctx.number_of_cert_verify_callbacks != 1) {
+ t758_msg("expecting exactly one cert verify callback here");
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+ t758_ctx.fake_async_cert_verification_finished = 1;
+ if(t758_saction(m, CURL_SOCKET_TIMEOUT, 0, "timeout")) {
+ t758_msg("spurious retry cert action");
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+ curl_easy_pause(curl, CURLPAUSE_CONT);
+ if(t758_saction(m, CURL_SOCKET_TIMEOUT, 0, "timeout")) {
+ t758_msg("unblocking transfer after cert verification finished");
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+ if(t758_ctx.number_of_cert_verify_callbacks != 2) {
+ t758_msg("this should have triggered the callback again, right?");
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+ t758_msg("TEST: all fine?");
+ }
+ FD_ZERO(&readSet);
+ FD_ZERO(&writeSet);
+ t758_updateFdSet(&sockets.read, &readSet, &maxFd);
+ t758_updateFdSet(&sockets.write, &writeSet, &maxFd);
+
+ if(timeout.tv_sec != (time_t)-1) {
+ int usTimeout = curlx_sztosi(t758_getMicroSecondTimeout(&timeout));
+ tv.tv_sec = usTimeout / 1000000;
+ tv.tv_usec = usTimeout % 1000000;
+ }
+ else if(maxFd <= 0) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+ }
+
+ select_test((int)maxFd, &readSet, &writeSet, NULL, &tv);
+
+ /* Check the sockets for reading / writing */
+ if(t758_checkFdSet(m, &sockets.read, &readSet, CURL_CSELECT_IN,
+ "read")) {
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+ if(t758_checkFdSet(m, &sockets.write, &writeSet, CURL_CSELECT_OUT,
+ "write")) {
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+
+ if(timeout.tv_sec != (time_t)-1 &&
+ t758_getMicroSecondTimeout(&timeout) == 0) {
+ /* Curl's timer has elapsed. */
+ if(t758_saction(m, CURL_SOCKET_TIMEOUT, 0, "timeout")) {
+ res = TEST_ERR_BAD_TIMEOUT;
+ goto test_cleanup;
+ }
+ }
+
+ abort_on_test_timeout();
+ }
+ if(success && t758_ctx.number_of_cert_verify_callbacks != 2) {
+ t758_msg("unexpected invocations of cert verify callback");
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+
+ if(!success) {
+ t758_msg("Error getting file.");
+ res = TEST_ERR_MAJOR_BAD;
+ }
+
+test_cleanup:
+
+ /* proper cleanup sequence */
+ t758_msg("cleanup");
+ curl_multi_remove_handle(m, curl);
+ curl_easy_cleanup(curl);
+ curl_multi_cleanup(m);
+ curl_global_cleanup();
+
+ /* free local memory */
+ free(sockets.read.sockets);
+ free(sockets.write.sockets);
+ t758_msg("done");
+
+ return res;
+}
+
+static CURLcode test_lib758(const char *URL)
+{
+ CURLcode rc;
+ /* rerun the same transfer multiple times and make it fail in different
+ callback calls */
+ rc = t758_one(URL, 0, 0); /* no callback fails */
+ if(rc)
+ curl_mfprintf(stderr, "%s FAILED: %d\n", t758_tag(), rc);
+
+ return rc;
+}
+
+#else /* T578_ENABLED */
+static CURLcode test_lib758(const char *URL)
+{
+ (void)URL;
+ return CURLE_OK;
+}
+#endif
diff --git a/tests/processhelp.pm b/tests/processhelp.pm
index 571ed5b34..43513aae0 100644
--- a/tests/processhelp.pm
+++ b/tests/processhelp.pm
@@ -27,11 +27,12 @@ package processhelp;
use strict;
use warnings;
+use Time::HiRes;
+
BEGIN {
use base qw(Exporter);
our @EXPORT = qw(
- portable_sleep
pidfromfile
pidexists
pidwait
@@ -42,17 +43,6 @@ BEGIN {
set_advisor_read_lock
clear_advisor_read_lock
);
-
- # portable sleeping needs Time::HiRes
- eval {
- no warnings "all";
- require Time::HiRes;
- };
- # portable sleeping falls back to native Sleep on Windows
- eval {
- no warnings "all";
- require Win32;
- }
}
use serverhelp qw(
@@ -65,26 +55,9 @@ use pathhelp qw(
os_is_win
);
-#######################################################################
-# portable_sleep uses Time::HiRes::sleep if available and falls back
-# to the classic approach of using select(undef, undef, undef, ...).
-# even though that one is not portable due to being implemented using
-# select on Windows: https://perldoc.perl.org/perlport.html#select
-# Therefore it uses Win32::Sleep on Windows systems instead.
-#
-sub portable_sleep {
- my ($seconds) = @_;
-
- if($Time::HiRes::VERSION) {
- Time::HiRes::sleep($seconds);
- }
- elsif(os_is_win()) {
- Win32::Sleep($seconds*1000);
- }
- else {
- select(undef, undef, undef, $seconds);
- }
-}
+use globalconfig qw(
+ $dev_null
+ );
#######################################################################
# pidfromfile returns the pid stored in the given pidfile. The value
@@ -143,7 +116,7 @@ sub pidexists {
if($^O ne 'MSWin32') {
my $filter = "PID eq $pid";
# https://ss64.com/nt/tasklist.html
- my $result = `tasklist -fi \"$filter\" 2>nul`;
+ my $result = `tasklist -fi \"$filter\" 2>$dev_null`;
if(index($result, "$pid") != -1) {
return -$pid;
}
@@ -173,7 +146,7 @@ sub pidterm {
$pid -= 4194304;
if($^O ne 'MSWin32') {
# https://ss64.com/nt/taskkill.html
- my $cmd = "taskkill -f -t -pid $pid >nul 2>&1";
+ my $cmd = "taskkill -f -t -pid $pid >$dev_null 2>&1";
print "Executing: '$cmd'\n";
system($cmd);
return;
@@ -198,7 +171,7 @@ sub pidkill {
$pid -= 4194304;
if($^O ne 'MSWin32') {
# https://ss64.com/nt/taskkill.html
- my $cmd = "taskkill -f -t -pid $pid >nul 2>&1";
+ my $cmd = "taskkill -f -t -pid $pid >$dev_null 2>&1";
print "Executing: '$cmd'\n";
system($cmd);
return;
@@ -234,7 +207,7 @@ sub pidwait {
last;
}
}
- portable_sleep(0.2);
+ Time::HiRes::sleep(0.2);
}
return $pid;
}
@@ -342,7 +315,7 @@ sub killpid {
last if(not scalar(@signalled));
# give any zombies of us a chance to move on to the afterlife
pidwait(0, &WNOHANG);
- portable_sleep(0.05);
+ Time::HiRes::sleep(0.05);
}
}
diff --git a/tests/runner.pm b/tests/runner.pm
index a208eba3a..18f3c5098 100644
--- a/tests/runner.pm
+++ b/tests/runner.pm
@@ -39,6 +39,7 @@ use warnings;
use 5.006;
use File::Basename;
+use Time::HiRes;
BEGIN {
use base qw(Exporter);
@@ -84,9 +85,6 @@ use Storable qw(
use pathhelp qw(
exe_ext
);
-use processhelp qw(
- portable_sleep
- );
use servers qw(
checkcmd
initserverconfig
@@ -419,7 +417,7 @@ sub waitlockunlock {
my $lockretry = $serverlogslocktimeout * 20;
my @locks;
while((@locks = logslocked()) && $lockretry--) {
- portable_sleep(0.05);
+ Time::HiRes::sleep(0.05);
}
if(($lockretry < 0) &&
($serverlogslocktimeout >= $defserverlogslocktimeout)) {
@@ -1092,7 +1090,7 @@ sub singletest_clean {
}
}
- portable_sleep($postcommanddelay) if($postcommanddelay);
+ Time::HiRes::sleep($postcommanddelay) if($postcommanddelay);
my @killtestservers = getpart("client", "killserver");
if(@killtestservers) {
diff --git a/tests/runtests.pl b/tests/runtests.pl
index 407a37946..a470597bf 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -92,9 +92,6 @@ use pathhelp qw(
exe_ext
sys_native_current_path
);
-use processhelp qw(
- portable_sleep
- );
use appveyor;
use azure;
diff --git a/tests/serverhelp.pm b/tests/serverhelp.pm
index fd762935a..1a3c99775 100644
--- a/tests/serverhelp.pm
+++ b/tests/serverhelp.pm
@@ -29,6 +29,8 @@ package serverhelp;
use strict;
use warnings;
+use Time::HiRes;
+
BEGIN {
use base qw(Exporter);
@@ -52,13 +54,6 @@ BEGIN {
datasockf_pidfilename
datasockf_logfilename
);
-
- # sub second timestamping needs Time::HiRes
- eval {
- no warnings "all";
- require Time::HiRes;
- import Time::HiRes qw( gettimeofday );
- }
}
use globalconfig;
@@ -81,20 +76,10 @@ our $logfile; # server log file name, for logmsg
# logmsg is general message logging subroutine for our test servers.
#
sub logmsg {
- my $now;
- # sub second timestamping needs Time::HiRes
- if($Time::HiRes::VERSION) {
- my ($seconds, $usec) = gettimeofday();
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
- localtime($seconds);
- $now = sprintf("%02d:%02d:%02d.%06d ", $hour, $min, $sec, $usec);
- }
- else {
- my $seconds = time();
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
- localtime($seconds);
- $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec);
- }
+ my ($seconds, $usec) = Time::HiRes::gettimeofday();
+ my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
+ localtime($seconds);
+ my $now = sprintf("%02d:%02d:%02d.%06d ", $hour, $min, $sec, $usec);
# we see warnings on Windows run that $logfile is used uninitialized
# TODO: not found yet where this comes from
$logfile = "serverhelp_uninitialized.log" if(!$logfile);
diff --git a/tests/servers.pm b/tests/servers.pm
index 02415c6ff..94809d3e7 100644
--- a/tests/servers.pm
+++ b/tests/servers.pm
@@ -380,7 +380,7 @@ sub startnew {
logmsg "startnew: failed to write fake $pidfile with pid=$child\n";
}
# could/should do a while connect fails sleep a bit and loop
- portable_sleep($timeout);
+ Time::HiRes::sleep($timeout);
if(checkdied($child)) {
logmsg "startnew: child process has failed to start\n" if($verbose);
return (-1,-1);