summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorCurl Upstream <curl-library@lists.haxx.se>2023-10-11 05:34:19 (GMT)
committerBrad King <brad.king@kitware.com>2023-10-12 19:28:57 (GMT)
commite6a6c1abc1e6b6e3ca9fa77947279509b55e2b01 (patch)
treef0d748647eebb0b8ba55e478ea35c8686dbd1485 /lib
parent017637e40f954e791a895a04855d0411bda61c10 (diff)
downloadCMake-e6a6c1abc1e6b6e3ca9fa77947279509b55e2b01.zip
CMake-e6a6c1abc1e6b6e3ca9fa77947279509b55e2b01.tar.gz
CMake-e6a6c1abc1e6b6e3ca9fa77947279509b55e2b01.tar.bz2
curl 2023-10-11 (d755a5f7)
Code extracted from: https://github.com/curl/curl.git at commit d755a5f7c009dd63a61b2c745180d8ba937cbfeb (curl-8_4_0).
Diffstat (limited to 'lib')
-rw-r--r--lib/CMakeLists.txt51
-rw-r--r--lib/Makefile.inc6
-rw-r--r--lib/base64.c2
-rw-r--r--lib/bufq.c22
-rw-r--r--lib/bufq.h6
-rw-r--r--lib/c-hyper.c16
-rw-r--r--lib/cf-h1-proxy.c289
-rw-r--r--lib/cf-h2-proxy.c79
-rw-r--r--lib/cf-socket.c35
-rw-r--r--lib/conncache.c1
-rw-r--r--lib/connect.c8
-rw-r--r--lib/content_encoding.c151
-rw-r--r--lib/content_encoding.h22
-rw-r--r--lib/cookie.c132
-rw-r--r--lib/cookie.h18
-rw-r--r--lib/curl_config.h.cmake74
-rw-r--r--lib/curl_ctype.h4
-rw-r--r--lib/curl_hmac.h4
-rw-r--r--lib/curl_memrchr.h4
-rw-r--r--lib/curl_ntlm_wb.c2
-rw-r--r--lib/curl_setup.h8
-rw-r--r--lib/curl_sspi.h245
-rw-r--r--lib/curl_threads.c2
-rw-r--r--lib/curl_threads.h3
-rw-r--r--lib/curl_trc.c4
-rw-r--r--lib/doh.c5
-rw-r--r--lib/dynbuf.h1
-rw-r--r--lib/dynhds.c3
-rw-r--r--lib/easy.c46
-rw-r--r--lib/easy_lock.h7
-rw-r--r--lib/escape.c55
-rw-r--r--lib/escape.h5
-rw-r--r--lib/file.c4
-rw-r--r--lib/fopen.c2
-rw-r--r--lib/formdata.c17
-rw-r--r--lib/ftp.c35
-rw-r--r--lib/ftplistparser.c2
-rw-r--r--lib/hmac.c4
-rw-r--r--lib/hostip.c4
-rw-r--r--lib/hostip.h2
-rw-r--r--lib/http.c24
-rw-r--r--lib/http1.c24
-rw-r--r--lib/http1.h2
-rw-r--r--lib/http2.c6
-rw-r--r--lib/http_aws_sigv4.c13
-rw-r--r--lib/http_chunks.c5
-rw-r--r--lib/http_proxy.c108
-rw-r--r--lib/http_proxy.h9
-rw-r--r--lib/idn.c5
-rw-r--r--lib/inet_ntop.c10
-rw-r--r--lib/ldap.c4
-rw-r--r--lib/mime.c6
-rw-r--r--lib/mime.h2
-rw-r--r--lib/mqtt.c108
-rw-r--r--lib/mqtt.h1
-rw-r--r--lib/multi.c85
-rw-r--r--lib/multiif.h9
-rw-r--r--lib/openldap.c21
-rw-r--r--lib/pingpong.c2
-rw-r--r--lib/progress.c9
-rw-r--r--lib/progress.h5
-rw-r--r--lib/rand.c48
-rw-r--r--lib/rand.h7
-rw-r--r--lib/sendf.c205
-rw-r--r--lib/sendf.h65
-rw-r--r--lib/setopt.c2
-rw-r--r--lib/sigpipe.h2
-rw-r--r--lib/smb.c7
-rw-r--r--lib/socks.c8
-rw-r--r--lib/telnet.c5
-rw-r--r--lib/tftp.c7
-rw-r--r--lib/timeval.c14
-rw-r--r--lib/timeval.h18
-rw-r--r--lib/transfer.c45
-rw-r--r--lib/url.c55
-rw-r--r--lib/urlapi.c12
-rw-r--r--lib/urldata.h11
-rw-r--r--lib/vauth/cleartext.c1
-rw-r--r--lib/vquic/curl_ngtcp2.c53
-rw-r--r--lib/vquic/curl_quiche.c13
-rw-r--r--lib/vssh/libssh.c10
-rw-r--r--lib/vssh/libssh2.c16
-rw-r--r--lib/vssh/wolfssh.c1
-rw-r--r--lib/vtls/gtls.c8
-rw-r--r--lib/vtls/mbedtls.c13
-rw-r--r--lib/vtls/openssl.c100
-rw-r--r--lib/vtls/schannel.c48
-rw-r--r--lib/vtls/schannel.h2
-rw-r--r--lib/vtls/schannel_int.h43
-rw-r--r--lib/vtls/sectransp.c16
-rw-r--r--lib/vtls/vtls.c3
-rw-r--r--lib/vtls/wolfssl.c71
-rw-r--r--lib/warnless.c51
93 files changed, 1360 insertions, 1438 deletions
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 9bb8f0b..6f84919 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -56,9 +56,9 @@ add_library(
target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
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)
+ # We must compile these sources separately to avoid memdebug.h redefinitions
+ # applying to them.
+ set_source_files_properties(memdebug.c curl_multibyte.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
endif()
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
@@ -85,19 +85,6 @@ else()
unset(CMAKESONAME)
endif()
-if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
- # on not-Windows and not-crosscompiling, check for writable argv[]
- include(CheckCSourceRuns)
- check_c_source_runs("
-int main(int argc, char **argv)
-{
- (void)argc;
- argv[0][0] = ' ';
- return (argv[0][0] == ' ')?0:1;
-}"
- HAVE_WRITABLE_ARGV)
-endif()
-
## Library definition
# Add "_imp" as a suffix before the extension to avoid conflicting with
@@ -122,18 +109,23 @@ if(NOT DEFINED SHARE_LIB_OBJECT)
endif()
endif()
+if(WIN32)
+ # Define CURL_STATICLIB always, to disable __declspec(dllexport) for exported
+ # libcurl symbols. We handle exports via libcurl.def instead. Except with
+ # symbol hiding disabled or debug mode enabled, when we export _all_ symbols
+ # from libcurl DLL, without using libcurl.def.
+ add_definitions("-DCURL_STATICLIB")
+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}")
+ set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
+ set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
set_target_properties(${LIB_OBJECT} PROPERTIES
@@ -160,12 +152,10 @@ if(BUILD_STATIC_LIBS)
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}")
+ set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
+ set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
set_target_properties(${LIB_STATIC} PROPERTIES
@@ -187,19 +177,20 @@ if(BUILD_SHARED_LIBS)
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)
+ set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES libcurl.rc)
+ if(HIDES_CURL_PRIVATE_SYMBOLS)
+ set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "${CURL_SOURCE_DIR}/libcurl.def")
+ endif()
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}")
+ set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
+ set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
set_target_properties(${LIB_SHARED} PROPERTIES
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index a08180b..e568ef9 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -162,12 +162,12 @@ LIB_CFILES = \
http.c \
http1.c \
http2.c \
+ http_aws_sigv4.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 \
@@ -289,9 +289,9 @@ LIB_HFILES = \
fileinfo.h \
fopen.h \
formdata.h \
- functypes.h \
ftp.h \
ftplistparser.h \
+ functypes.h \
getinfo.h \
gopher.h \
hash.h \
@@ -301,12 +301,12 @@ LIB_HFILES = \
http.h \
http1.h \
http2.h \
+ http_aws_sigv4.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 \
diff --git a/lib/base64.c b/lib/base64.c
index 30db7e5..2a49b5a 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -31,7 +31,7 @@
!defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_POP3) || \
!defined(CURL_DISABLE_IMAP) || \
- !defined(CURL_DISABLE_DOH) || defined(USE_SSL)
+ !defined(CURL_DISABLE_DOH) || defined(USE_SSL) || defined(BUILDING_CURL)
#include "curl/curl.h"
#include "warnless.h"
#include "curl_base64.h"
diff --git a/lib/bufq.c b/lib/bufq.c
index 1555449..d03906d 100644
--- a/lib/bufq.c
+++ b/lib/bufq.c
@@ -144,21 +144,6 @@ static size_t chunk_skip(struct buf_chunk *chunk, size_t amount)
return n;
}
-static void chunk_shift(struct buf_chunk *chunk)
-{
- if(chunk->r_offset) {
- if(!chunk_is_empty(chunk)) {
- size_t n = chunk->w_offset - chunk->r_offset;
- memmove(chunk->x.data, chunk->x.data + chunk->r_offset, n);
- chunk->w_offset -= chunk->r_offset;
- chunk->r_offset = 0;
- }
- else {
- chunk->r_offset = chunk->w_offset = 0;
- }
- }
-}
-
static void chunk_list_free(struct buf_chunk **anchor)
{
struct buf_chunk *chunk;
@@ -504,13 +489,6 @@ void Curl_bufq_skip(struct bufq *q, size_t amount)
}
}
-void Curl_bufq_skip_and_shift(struct bufq *q, size_t amount)
-{
- Curl_bufq_skip(q, amount);
- if(q->tail)
- chunk_shift(q->tail);
-}
-
ssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer,
void *writer_ctx, CURLcode *err)
{
diff --git a/lib/bufq.h b/lib/bufq.h
index 89b5c84..089d61b 100644
--- a/lib/bufq.h
+++ b/lib/bufq.h
@@ -209,12 +209,6 @@ bool Curl_bufq_peek_at(struct bufq *q, size_t offset,
*/
void Curl_bufq_skip(struct bufq *q, size_t amount);
-/**
- * Same as `skip` but shift tail data to the start afterwards,
- * so that further writes will find room in tail.
- */
-void Curl_bufq_skip_and_shift(struct bufq *q, size_t amount);
-
typedef ssize_t Curl_bufq_writer(void *writer_ctx,
const unsigned char *buf, size_t len,
CURLcode *err);
diff --git a/lib/c-hyper.c b/lib/c-hyper.c
index 61ca29a..5726ff1 100644
--- a/lib/c-hyper.c
+++ b/lib/c-hyper.c
@@ -174,8 +174,6 @@ static int hyper_each_header(void *userdata,
if(!data->state.hconnect || !data->set.suppress_connect_headers) {
writetype = CLIENTWRITE_HEADER;
- if(data->set.include_header)
- writetype |= CLIENTWRITE_BODY;
if(data->state.hconnect)
writetype |= CLIENTWRITE_CONNECT;
if(data->req.httpcode/100 == 1)
@@ -248,11 +246,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
if(0 == len)
return HYPER_ITER_CONTINUE;
Curl_debug(data, CURLINFO_DATA_IN, buf, len);
- if(!data->set.http_ce_skip && k->writer_stack)
- /* content-encoded data */
- result = Curl_unencode_write(data, k->writer_stack, buf, len);
- else
- result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
if(result) {
data->state.hresult = result;
@@ -260,7 +254,11 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
}
data->req.bytecount += len;
- Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
+ result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
+ if(result) {
+ data->state.hresult = result;
+ return HYPER_ITER_BREAK;
+ }
return HYPER_ITER_CONTINUE;
}
@@ -314,8 +312,6 @@ static CURLcode status_line(struct Curl_easy *data,
if(!data->state.hconnect || !data->set.suppress_connect_headers) {
writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
- if(data->set.include_header)
- writetype |= CLIENTWRITE_BODY;
result = Curl_client_write(data, writetype,
Curl_dyn_ptr(&data->state.headerb), len);
if(result)
diff --git a/lib/cf-h1-proxy.c b/lib/cf-h1-proxy.c
index e9bc13d..6748021 100644
--- a/lib/cf-h1-proxy.c
+++ b/lib/cf-h1-proxy.c
@@ -34,6 +34,7 @@
#include "dynbuf.h"
#include "sendf.h"
#include "http.h"
+#include "http1.h"
#include "http_proxy.h"
#include "url.h"
#include "select.h"
@@ -64,13 +65,10 @@ typedef enum {
/* struct for HTTP CONNECT tunneling */
struct h1_tunnel_state {
- int sockindex;
- const char *hostname;
- int remote_port;
struct HTTP CONNECT;
struct dynbuf rcvbuf;
- struct dynbuf req;
- size_t nsend;
+ struct dynbuf request_data;
+ size_t nsent;
size_t headerlines;
enum keeponval {
KEEPON_DONE,
@@ -94,46 +92,31 @@ static bool tunnel_is_failed(struct h1_tunnel_state *ts)
return ts && (ts->tunnel_state == H1_TUNNEL_FAILED);
}
-static CURLcode tunnel_reinit(struct h1_tunnel_state *ts,
- struct connectdata *conn,
- struct Curl_easy *data)
+static CURLcode tunnel_reinit(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h1_tunnel_state *ts)
{
(void)data;
+ (void)cf;
DEBUGASSERT(ts);
Curl_dyn_reset(&ts->rcvbuf);
- Curl_dyn_reset(&ts->req);
+ Curl_dyn_reset(&ts->request_data);
ts->tunnel_state = H1_TUNNEL_INIT;
ts->keepon = KEEPON_CONNECT;
ts->cl = 0;
ts->close_connection = FALSE;
-
- if(conn->bits.conn_to_host)
- ts->hostname = conn->conn_to_host.name;
- else if(ts->sockindex == SECONDARYSOCKET)
- ts->hostname = conn->secondaryhostname;
- else
- ts->hostname = conn->host.name;
-
- if(ts->sockindex == SECONDARYSOCKET)
- ts->remote_port = conn->secondary_port;
- else if(conn->bits.conn_to_port)
- ts->remote_port = conn->conn_to_port;
- else
- ts->remote_port = conn->remote_port;
-
return CURLE_OK;
}
-static CURLcode tunnel_init(struct h1_tunnel_state **pts,
+static CURLcode tunnel_init(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+ struct h1_tunnel_state **pts)
{
struct h1_tunnel_state *ts;
CURLcode result;
- if(conn->handler->flags & PROTOPT_NOTCPPROXY) {
- failf(data, "%s cannot be done over CONNECT", conn->handler->scheme);
+ if(cf->conn->handler->flags & PROTOPT_NOTCPPROXY) {
+ failf(data, "%s cannot be done over CONNECT", cf->conn->handler->scheme);
return CURLE_UNSUPPORTED_PROTOCOL;
}
@@ -146,15 +129,14 @@ static CURLcode tunnel_init(struct h1_tunnel_state **pts,
if(!ts)
return CURLE_OUT_OF_MEMORY;
- ts->sockindex = sockindex;
infof(data, "allocate connect buffer");
Curl_dyn_init(&ts->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
- Curl_dyn_init(&ts->req, DYN_HTTP_REQUEST);
+ Curl_dyn_init(&ts->request_data, DYN_HTTP_REQUEST);
*pts = ts;
- connkeep(conn, "HTTP proxy CONNECT");
- return tunnel_reinit(ts, conn, data);
+ connkeep(cf->conn, "HTTP proxy CONNECT");
+ return tunnel_reinit(cf, data, ts);
}
static void h1_tunnel_go_state(struct Curl_cfilter *cf,
@@ -176,7 +158,7 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
switch(new_state) {
case H1_TUNNEL_INIT:
CURL_TRC_CF(data, cf, "new tunnel state 'init'");
- tunnel_reinit(ts, cf->conn, data);
+ tunnel_reinit(cf, data, ts);
break;
case H1_TUNNEL_CONNECT:
@@ -207,7 +189,7 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
CURL_TRC_CF(data, cf, "new tunnel state 'failed'");
ts->tunnel_state = new_state;
Curl_dyn_reset(&ts->rcvbuf);
- Curl_dyn_reset(&ts->req);
+ Curl_dyn_reset(&ts->request_data);
/* restore the protocol pointer */
data->info.httpcode = 0; /* clear it as it might've been used for the
proxy */
@@ -229,171 +211,80 @@ static void tunnel_free(struct Curl_cfilter *cf,
if(ts) {
h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
Curl_dyn_free(&ts->rcvbuf);
- Curl_dyn_free(&ts->req);
+ Curl_dyn_free(&ts->request_data);
free(ts);
cf->ctx = NULL;
}
}
-static CURLcode CONNECT_host(struct Curl_easy *data,
- struct connectdata *conn,
- const char *hostname,
- int remote_port,
- char **connecthostp,
- char **hostp)
-{
- char *hostheader; /* for CONNECT */
- char *host = NULL; /* Host: */
- bool ipv6_ip = conn->bits.ipv6_ip;
-
- /* the hostname may be different */
- if(hostname != conn->host.name)
- ipv6_ip = (strchr(hostname, ':') != NULL);
- hostheader = /* host:port with IPv6 support */
- aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
- remote_port);
- if(!hostheader)
- return CURLE_OUT_OF_MEMORY;
-
- if(!Curl_checkProxyheaders(data, conn, STRCONST("Host"))) {
- host = aprintf("Host: %s\r\n", hostheader);
- if(!host) {
- free(hostheader);
- return CURLE_OUT_OF_MEMORY;
- }
- }
- *connecthostp = hostheader;
- *hostp = host;
- return CURLE_OK;
-}
-
#ifndef USE_HYPER
static CURLcode start_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct h1_tunnel_state *ts)
{
- struct connectdata *conn = cf->conn;
- char *hostheader = NULL;
- char *host = NULL;
- const char *httpv;
+ struct httpreq *req = NULL;
+ int http_minor;
CURLcode result;
- infof(data, "Establish HTTP proxy tunnel to %s:%d",
- ts->hostname, ts->remote_port);
-
/* This only happens if we've looped here due to authentication
reasons, and we don't really use the newly cloned URL here
then. Just free() it. */
Curl_safefree(data->req.newurl);
- result = CONNECT_host(data, conn,
- ts->hostname, ts->remote_port,
- &hostheader, &host);
- if(result)
- goto out;
-
- /* Setup the proxy-authorization header, if any */
- result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
- hostheader, TRUE);
- if(result)
- goto out;
-
- httpv = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
-
- result =
- Curl_dyn_addf(&ts->req,
- "CONNECT %s HTTP/%s\r\n"
- "%s" /* Host: */
- "%s", /* Proxy-Authorization */
- hostheader,
- httpv,
- host?host:"",
- data->state.aptr.proxyuserpwd?
- data->state.aptr.proxyuserpwd:"");
+ result = Curl_http_proxy_create_CONNECT(&req, cf, data, 1);
if(result)
goto out;
- if(!Curl_checkProxyheaders(data, conn, STRCONST("User-Agent"))
- && data->set.str[STRING_USERAGENT])
- result = Curl_dyn_addf(&ts->req, "User-Agent: %s\r\n",
- data->set.str[STRING_USERAGENT]);
- if(result)
- goto out;
-
- if(!Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection")))
- result = Curl_dyn_addn(&ts->req,
- STRCONST("Proxy-Connection: Keep-Alive\r\n"));
- if(result)
- goto out;
-
- result = Curl_add_custom_headers(data, TRUE, &ts->req);
- if(result)
- goto out;
+ infof(data, "Establish HTTP proxy tunnel to %s", req->authority);
- /* CRLF terminate the request */
- result = Curl_dyn_addn(&ts->req, STRCONST("\r\n"));
- if(result)
- goto out;
-
- /* Send the connect request to the proxy */
- result = Curl_buffer_send(&ts->req, data, &ts->CONNECT,
- &data->info.request_size, 0,
- ts->sockindex);
+ Curl_dyn_reset(&ts->request_data);
+ ts->nsent = 0;
ts->headerlines = 0;
+ http_minor = (cf->conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? 0 : 1;
+
+ result = Curl_h1_req_write_head(req, http_minor, &ts->request_data);
out:
if(result)
failf(data, "Failed sending CONNECT to proxy");
- free(host);
- free(hostheader);
+ if(req)
+ Curl_http_req_free(req);
return result;
}
-static CURLcode send_CONNECT(struct Curl_easy *data,
- struct connectdata *conn,
+static CURLcode send_CONNECT(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
struct h1_tunnel_state *ts,
bool *done)
{
- struct SingleRequest *k = &data->req;
- struct HTTP *http = &ts->CONNECT;
+ char *buf = Curl_dyn_ptr(&ts->request_data);
+ size_t request_len = Curl_dyn_len(&ts->request_data);
+ size_t blen = request_len;
CURLcode result = CURLE_OK;
+ ssize_t nwritten;
- if(http->sending != HTTPSEND_REQUEST)
- goto out;
+ if(blen <= ts->nsent)
+ goto out; /* we are done */
- if(!ts->nsend) {
- size_t fillcount;
- k->upload_fromhere = data->state.ulbuf;
- result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
- &fillcount);
- if(result)
- goto out;
- ts->nsend = fillcount;
- }
- if(ts->nsend) {
- ssize_t bytes_written;
- /* write to socket (send away data) */
- result = Curl_write(data,
- conn->writesockfd, /* socket to send to */
- k->upload_fromhere, /* buffer pointer */
- ts->nsend, /* buffer size */
- &bytes_written); /* actually sent */
- if(result)
- goto out;
- /* send to debug callback! */
- Curl_debug(data, CURLINFO_HEADER_OUT,
- k->upload_fromhere, bytes_written);
+ blen -= ts->nsent;
+ buf += ts->nsent;
- ts->nsend -= bytes_written;
- k->upload_fromhere += bytes_written;
+ nwritten = cf->next->cft->do_send(cf->next, data, buf, blen, &result);
+ if(nwritten < 0) {
+ if(result == CURLE_AGAIN) {
+ result = CURLE_OK;
+ }
+ goto out;
}
- if(!ts->nsend)
- http->sending = HTTPSEND_NADA;
+
+ DEBUGASSERT(blen >= (size_t)nwritten);
+ ts->nsent += (size_t)nwritten;
+ Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)nwritten);
out:
if(result)
failf(data, "Failed sending CONNECT to proxy");
- *done = (http->sending != HTTPSEND_REQUEST);
+ *done = (!result && (ts->nsent >= request_len));
return result;
}
@@ -491,7 +382,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
error = SELECT_OK;
*done = FALSE;
- if(!Curl_conn_data_pending(data, ts->sockindex))
+ if(!Curl_conn_data_pending(data, cf->sockindex))
return CURLE_OK;
while(ts->keepon) {
@@ -579,7 +470,6 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
if(!data->set.suppress_connect_headers) {
/* send the header to the callback */
int writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
- (data->set.include_header ? CLIENTWRITE_BODY : 0) |
(ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
result = Curl_client_write(data, writetype, linep, perline);
@@ -670,6 +560,41 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
}
#else /* USE_HYPER */
+
+static CURLcode CONNECT_host(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ char **pauthority,
+ char **phost_header)
+{
+ const char *hostname;
+ int port;
+ bool ipv6_ip;
+ CURLcode result;
+ char *authority; /* for CONNECT, the destination host + port */
+ char *host_header = NULL; /* Host: authority */
+
+ result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
+ if(result)
+ return result;
+
+ authority = aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
+ port);
+ if(!authority)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* If user is not overriding the Host header later */
+ if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("Host"))) {
+ host_header = aprintf("Host: %s\r\n", authority);
+ if(!host_header) {
+ free(authority);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ *pauthority = authority;
+ *phost_header = host_header;
+ return CURLE_OK;
+}
+
/* The Hyper version of CONNECT */
static CURLcode start_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
@@ -686,9 +611,10 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
hyper_task *task = NULL; /* for the handshake */
hyper_clientconn *client = NULL;
hyper_task *sendtask = NULL; /* for the send */
- char *hostheader = NULL; /* for CONNECT */
- char *host = NULL; /* Host: */
+ char *authority = NULL; /* for CONNECT */
+ char *host_header = NULL; /* Host: */
CURLcode result = CURLE_OUT_OF_MEMORY;
+ (void)ts;
io = hyper_io_new();
if(!io) {
@@ -766,27 +692,25 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
goto error;
}
- infof(data, "Establish HTTP proxy tunnel to %s:%d",
- ts->hostname, ts->remote_port);
-
/* This only happens if we've looped here due to authentication
reasons, and we don't really use the newly cloned URL here
then. Just free() it. */
Curl_safefree(data->req.newurl);
- result = CONNECT_host(data, conn, ts->hostname, ts->remote_port,
- &hostheader, &host);
+ result = CONNECT_host(cf, data, &authority, &host_header);
if(result)
goto error;
- if(hyper_request_set_uri(req, (uint8_t *)hostheader,
- strlen(hostheader))) {
+ infof(data, "Establish HTTP proxy tunnel to %s", authority);
+
+ if(hyper_request_set_uri(req, (uint8_t *)authority,
+ strlen(authority))) {
failf(data, "error setting path");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
if(data->set.verbose) {
- char *se = aprintf("CONNECT %s HTTP/1.1\r\n", hostheader);
+ char *se = aprintf("CONNECT %s HTTP/1.1\r\n", authority);
if(!se) {
result = CURLE_OUT_OF_MEMORY;
goto error;
@@ -796,10 +720,10 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
}
/* Setup the proxy-authorization header, if any */
result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
- hostheader, TRUE);
+ authority, TRUE);
if(result)
goto error;
- Curl_safefree(hostheader);
+ Curl_safefree(authority);
/* default is 1.1 */
if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
@@ -816,11 +740,11 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
result = CURLE_OUT_OF_MEMORY;
goto error;
}
- if(host) {
- result = Curl_hyper_header(data, headers, host);
+ if(host_header) {
+ result = Curl_hyper_header(data, headers, host_header);
if(result)
goto error;
- Curl_safefree(host);
+ Curl_safefree(host_header);
}
if(data->state.aptr.proxyuserpwd) {
@@ -874,8 +798,8 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
client = NULL;
error:
- free(host);
- free(hostheader);
+ free(host_header);
+ free(authority);
if(io)
hyper_io_free(io);
if(options)
@@ -890,12 +814,13 @@ error:
return result;
}
-static CURLcode send_CONNECT(struct Curl_easy *data,
- struct connectdata *conn,
+static CURLcode send_CONNECT(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
struct h1_tunnel_state *ts,
bool *done)
{
struct hyptransfer *h = &data->hyp;
+ struct connectdata *conn = cf->conn;
hyper_task *task = NULL;
hyper_error *hypererr = NULL;
CURLcode result = CURLE_OK;
@@ -995,7 +920,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
case H1_TUNNEL_CONNECT:
/* see that the request is completely sent */
CURL_TRC_CF(data, cf, "CONNECT send");
- result = send_CONNECT(data, cf->conn, ts, &done);
+ result = send_CONNECT(cf, data, ts, &done);
if(result || !done)
goto out;
h1_tunnel_go_state(cf, ts, H1_TUNNEL_RECEIVE, data);
@@ -1090,7 +1015,7 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
*done = FALSE;
if(!ts) {
- result = tunnel_init(&ts, data, cf->conn, cf->sockindex);
+ result = tunnel_init(cf, data, &ts);
if(result)
return result;
cf->ctx = ts;
diff --git a/lib/cf-h2-proxy.c b/lib/cf-h2-proxy.c
index a3feefc..dbc895d 100644
--- a/lib/cf-h2-proxy.c
+++ b/lib/cf-h2-proxy.c
@@ -84,7 +84,8 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
{
const char *hostname;
int port;
- bool ipv6_ip = cf->conn->bits.ipv6_ip;
+ bool ipv6_ip;
+ CURLcode result;
ts->state = H2_TUNNEL_INIT;
ts->stream_id = -1;
@@ -92,22 +93,9 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
BUFQ_OPT_SOFT_LIMIT);
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;
- else if(cf->sockindex == SECONDARYSOCKET)
- hostname = cf->conn->secondaryhostname;
- else
- hostname = cf->conn->host.name;
-
- if(cf->sockindex == SECONDARYSOCKET)
- port = cf->conn->secondary_port;
- else if(cf->conn->bits.conn_to_port)
- port = cf->conn->conn_to_port;
- else
- port = cf->conn->remote_port;
-
- if(hostname != cf->conn->host.name)
- ipv6_ip = (strchr(hostname, ':') != NULL);
+ result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
+ if(result)
+ return result;
ts->authority = /* host:port with IPv6 support */
aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"", port);
@@ -233,7 +221,7 @@ 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 || 1) {
+ if(data->state.dselect_bits != bits) {
CURL_TRC_CF(data, cf, "[%d] DRAIN dselect_bits=%x",
tunnel->stream_id, bits);
data->state.dselect_bits = bits;
@@ -309,8 +297,9 @@ 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);
+static int proxy_h2_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,
@@ -355,7 +344,8 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
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);
+ nghttp2_session_callbacks_set_on_frame_send_callback(cbs,
+ proxy_h2_on_frame_send);
#endif
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
cbs, tunnel_recv_callback);
@@ -575,7 +565,8 @@ static ssize_t on_session_send(nghttp2_session *h2,
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
-static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen)
+static int proxy_h2_fr_print(const nghttp2_frame *frame,
+ char *buffer, size_t blen)
{
switch(frame->hd.type) {
case NGHTTP2_DATA: {
@@ -646,8 +637,9 @@ static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen)
}
}
-static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
- void *userp)
+static int proxy_h2_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);
@@ -657,7 +649,7 @@ static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
if(data && Curl_trc_cf_is_verbose(cf, data)) {
char buffer[256];
int len;
- len = fr_print(frame, buffer, sizeof(buffer)-1);
+ len = proxy_h2_fr_print(frame, buffer, sizeof(buffer)-1);
buffer[len] = 0;
CURL_TRC_CF(data, cf, "[%d] -> %s", frame->hd.stream_id, buffer);
}
@@ -680,7 +672,7 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
if(Curl_trc_cf_is_verbose(cf, data)) {
char buffer[256];
int len;
- len = fr_print(frame, buffer, sizeof(buffer)-1);
+ len = proxy_h2_fr_print(frame, buffer, sizeof(buffer)-1);
buffer[len] = 0;
CURL_TRC_CF(data, cf, "[%d] <- %s",frame->hd.stream_id, buffer);
}
@@ -980,38 +972,11 @@ static CURLcode submit_CONNECT(struct Curl_cfilter *cf,
CURLcode result;
struct httpreq *req = NULL;
- infof(data, "Establish HTTP/2 proxy tunnel to %s", ts->authority);
-
- result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT")-1,
- NULL, 0, ts->authority, strlen(ts->authority),
- NULL, 0);
+ result = Curl_http_proxy_create_CONNECT(&req, cf, data, 2);
if(result)
goto out;
- /* Setup the proxy-authorization header, if any */
- result = Curl_http_output_auth(data, cf->conn, req->method, HTTPREQ_GET,
- req->authority, TRUE);
- if(result)
- goto out;
-
- if(data->state.aptr.proxyuserpwd) {
- result = Curl_dynhds_h1_cadd_line(&req->headers,
- data->state.aptr.proxyuserpwd);
- if(result)
- goto out;
- }
-
- if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent"))
- && data->set.str[STRING_USERAGENT]) {
- result = Curl_dynhds_cadd(&req->headers, "User-Agent",
- data->set.str[STRING_USERAGENT]);
- if(result)
- goto out;
- }
-
- result = Curl_dynhds_add_custom(data, TRUE, &req->headers);
- if(result)
- goto out;
+ infof(data, "Establish HTTP/2 proxy tunnel to %s", req->authority);
result = proxy_h2_submit(&ts->stream_id, cf, data, ctx->h2, req,
NULL, ts, tunnel_send_callback, cf);
@@ -1058,7 +1023,7 @@ static CURLcode inspect_response(struct Curl_cfilter *cf,
if(result)
return result;
if(data->req.newurl) {
- /* Inidicator that we should try again */
+ /* Indicator that we should try again */
Curl_safefree(data->req.newurl);
h2_tunnel_go_state(cf, ts, H2_TUNNEL_INIT, data);
return CURLE_OK;
@@ -1195,6 +1160,8 @@ static void cf_h2_proxy_close(struct Curl_cfilter *cf, struct Curl_easy *data)
cf_h2_proxy_ctx_clear(ctx);
CF_DATA_RESTORE(cf, save);
}
+ if(cf->next)
+ cf->next->cft->do_close(cf->next, data);
}
static void cf_h2_proxy_destroy(struct Curl_cfilter *cf,
diff --git a/lib/cf-socket.c b/lib/cf-socket.c
index effe6e6..ce3f9e9 100644
--- a/lib/cf-socket.c
+++ b/lib/cf-socket.c
@@ -781,6 +781,8 @@ struct cf_socket_ctx {
#ifdef DEBUGBUILD
int wblock_percent; /* percent of writes doing EAGAIN */
int wpartial_percent; /* percent of bytes written in send */
+ int rblock_percent; /* percent of reads doing EAGAIN */
+ size_t recv_max; /* max enforced read size */
#endif
BIT(got_first_byte); /* if first byte was received */
BIT(accepted); /* socket was accepted, not connected */
@@ -811,6 +813,18 @@ static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
if(l >= 0 && l <= 100)
ctx->wpartial_percent = (int)l;
}
+ p = getenv("CURL_DBG_SOCK_RBLOCK");
+ if(p) {
+ long l = strtol(p, NULL, 10);
+ if(l >= 0 && l <= 100)
+ ctx->rblock_percent = (int)l;
+ }
+ p = getenv("CURL_DBG_SOCK_RMAX");
+ if(p) {
+ long l = strtol(p, NULL, 10);
+ if(l >= 0)
+ ctx->recv_max = (size_t)l;
+ }
}
#endif
}
@@ -1358,6 +1372,27 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
fdsave = cf->conn->sock[cf->sockindex];
cf->conn->sock[cf->sockindex] = ctx->sock;
+#ifdef DEBUGBUILD
+ /* simulate network blocking/partial reads */
+ if(cf->cft != &Curl_cft_udp && ctx->rblock_percent > 0) {
+ unsigned char c;
+ Curl_rand(data, &c, 1);
+ if(c >= ((100-ctx->rblock_percent)*256/100)) {
+ CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE EWOULDBLOCK", len);
+ *err = CURLE_AGAIN;
+ nread = -1;
+ cf->conn->sock[cf->sockindex] = fdsave;
+ return nread;
+ }
+ }
+ if(cf->cft != &Curl_cft_udp && ctx->recv_max && ctx->recv_max < len) {
+ size_t orig_len = len;
+ len = ctx->recv_max;
+ CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE max read of %zu bytes",
+ orig_len, len);
+ }
+#endif
+
if(ctx->buffer_recv && !Curl_bufq_is_empty(&ctx->recvbuf)) {
CURL_TRC_CF(data, cf, "recv from buffer");
nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
diff --git a/lib/conncache.c b/lib/conncache.c
index a21409c..93d8768 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -107,6 +107,7 @@ int Curl_conncache_init(struct conncache *connc, int size)
connc->closure_handle = curl_easy_init();
if(!connc->closure_handle)
return 1; /* bad */
+ connc->closure_handle->internal = true;
Curl_hash_init(&connc->hash, size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry);
diff --git a/lib/connect.c b/lib/connect.c
index 033fb7b..c7ba3e2 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -634,6 +634,7 @@ evaluate:
/* next attempt was started */
CURL_TRC_CF(data, cf, "%s trying next", baller->name);
++ongoing;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
}
}
@@ -646,7 +647,7 @@ evaluate:
/* Nothing connected, check the time before we might
* start new ballers or return ok. */
if((ongoing || not_started) && Curl_timeleft(data, &now, TRUE) < 0) {
- failf(data, "Connection timeout after %ld ms",
+ failf(data, "Connection timeout after %" CURL_FORMAT_CURL_OFF_T " ms",
Curl_timediff(now, data->progress.t_startsingle));
return CURLE_OPERATION_TIMEDOUT;
}
@@ -823,11 +824,10 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
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,
+ EXPIRE_HAPPY_EYEBALLS);
}
- Curl_expire(data, data->set.happy_eyeballs_timeout,
- EXPIRE_HAPPY_EYEBALLS);
-
return CURLE_OK;
}
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index efbe7cb..be7c075 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -280,9 +280,6 @@ static CURLcode deflate_init_writer(struct Curl_easy *data,
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
- if(!writer->downstream)
- return CURLE_WRITE_ERROR;
-
/* Initialize zlib */
z->zalloc = (alloc_func) zalloc_cb;
z->zfree = (free_func) zfree_cb;
@@ -337,9 +334,6 @@ static CURLcode gzip_init_writer(struct Curl_easy *data,
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
- if(!writer->downstream)
- return CURLE_WRITE_ERROR;
-
/* Initialize zlib */
z->zalloc = (alloc_func) zalloc_cb;
z->zfree = (free_func) zfree_cb;
@@ -647,9 +641,6 @@ static CURLcode brotli_init_writer(struct Curl_easy *data,
struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
- if(!writer->downstream)
- return CURLE_WRITE_ERROR;
-
bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL);
return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
}
@@ -741,9 +732,6 @@ static CURLcode zstd_init_writer(struct Curl_easy *data,
(void)data;
- if(!writer->downstream)
- return CURLE_WRITE_ERROR;
-
zp->zds = ZSTD_createDStream();
zp->decomp = NULL;
return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
@@ -822,8 +810,9 @@ static const struct content_encoding zstd_encoding = {
static CURLcode identity_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) data;
- return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
+ (void)data;
+ (void)writer;
+ return CURLE_OK;
}
static CURLcode identity_unencode_write(struct Curl_easy *data,
@@ -903,51 +892,13 @@ char *Curl_all_content_encodings(void)
}
-/* Real client writer: no downstream. */
-static CURLcode client_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
-{
- (void) data;
- return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
-}
-
-static CURLcode client_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
-{
- struct SingleRequest *k = &data->req;
-
- (void) writer;
-
- if(!nbytes || k->ignorebody)
- return CURLE_OK;
-
- return Curl_client_write(data, CLIENTWRITE_BODY, (char *) buf, nbytes);
-}
-
-static void client_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
-{
- (void) data;
- (void) writer;
-}
-
-static const struct content_encoding client_encoding = {
- NULL,
- NULL,
- client_init_writer,
- client_unencode_write,
- client_close_writer,
- sizeof(struct contenc_writer)
-};
-
-
/* Deferred error dummy writer. */
static CURLcode error_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) data;
- return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
+ (void)data;
+ (void)writer;
+ return CURLE_OK;
}
static CURLcode error_unencode_write(struct Curl_easy *data,
@@ -984,31 +935,6 @@ static const struct content_encoding error_encoding = {
sizeof(struct contenc_writer)
};
-/* Create an unencoding writer stage using the given handler. */
-static struct contenc_writer *
-new_unencoding_writer(struct Curl_easy *data,
- const struct content_encoding *handler,
- struct contenc_writer *downstream,
- int order)
-{
- struct contenc_writer *writer;
-
- DEBUGASSERT(handler->writersize >= sizeof(struct contenc_writer));
- writer = (struct contenc_writer *) calloc(1, handler->writersize);
-
- if(writer) {
- writer->handler = handler;
- writer->downstream = downstream;
- writer->order = order;
- if(handler->init_writer(data, writer)) {
- free(writer);
- writer = NULL;
- }
- }
-
- return writer;
-}
-
/* Write data using an unencoding writer stack. "nbytes" is not
allowed to be 0. */
CURLcode Curl_unencode_write(struct Curl_easy *data,
@@ -1017,23 +943,11 @@ CURLcode Curl_unencode_write(struct Curl_easy *data,
{
if(!nbytes)
return CURLE_OK;
+ if(!writer)
+ return CURLE_WRITE_ERROR;
return writer->handler->unencode_write(data, writer, buf, nbytes);
}
-/* Close and clean-up the connection's writer stack. */
-void Curl_unencode_cleanup(struct Curl_easy *data)
-{
- struct SingleRequest *k = &data->req;
- struct contenc_writer *writer = k->writer_stack;
-
- while(writer) {
- k->writer_stack = writer->downstream;
- writer->handler->close_writer(data, writer);
- free(writer);
- writer = k->writer_stack;
- }
-}
-
/* Find the content encoding by name. */
static const struct content_encoding *find_encoding(const char *name,
size_t len)
@@ -1049,9 +963,6 @@ static const struct content_encoding *find_encoding(const char *name,
return NULL;
}
-/* allow no more than 5 "chained" compression steps */
-#define MAX_ENCODE_STACK 5
-
/* Set-up the unencoding stack from the Content-Encoding header value.
* See RFC 7231 section 3.1.2.2. */
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
@@ -1059,6 +970,7 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
{
struct SingleRequest *k = &data->req;
unsigned int order = is_transfer? 2: 1;
+ CURLcode result;
do {
const char *name;
@@ -1085,41 +997,19 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
if(is_transfer && !data->set.http_transfer_encoding)
/* not requested, ignore */
return CURLE_OK;
- encoding = find_encoding(name, namelen);
-
- if(!k->writer_stack) {
- k->writer_stack = new_unencoding_writer(data, &client_encoding,
- NULL, 0);
-
- if(!k->writer_stack)
- return CURLE_OUT_OF_MEMORY;
- }
+ encoding = find_encoding(name, namelen);
if(!encoding)
encoding = &error_encoding; /* Defer error at stack use. */
- if(k->writer_stack_depth++ >= MAX_ENCODE_STACK) {
- failf(data, "Reject response due to more than %u content encodings",
- MAX_ENCODE_STACK);
- return CURLE_BAD_CONTENT_ENCODING;
- }
- /* Stack the unencoding stage. */
- if(order >= k->writer_stack->order) {
- writer = new_unencoding_writer(data, encoding,
- k->writer_stack, order);
- if(!writer)
- return CURLE_OUT_OF_MEMORY;
- k->writer_stack = writer;
- }
- else {
- struct contenc_writer *w = k->writer_stack;
- while(w->downstream && order < w->downstream->order)
- w = w->downstream;
- writer = new_unencoding_writer(data, encoding,
- w->downstream, order);
- if(!writer)
- return CURLE_OUT_OF_MEMORY;
- w->downstream = writer;
+ result = Curl_client_create_writer(&writer, data, encoding, order);
+ if(result)
+ return result;
+
+ result = Curl_client_add_writer(data, writer);
+ if(result) {
+ Curl_client_free_writer(data, writer);
+ return result;
}
}
} while(*enclist);
@@ -1149,11 +1039,6 @@ CURLcode Curl_unencode_write(struct Curl_easy *data,
return CURLE_NOT_BUILT_IN;
}
-void Curl_unencode_cleanup(struct Curl_easy *data)
-{
- (void) data;
-}
-
char *Curl_all_content_encodings(void)
{
return strdup(CONTENT_ENCODING_DEFAULT); /* Satisfy caller. */
diff --git a/lib/content_encoding.h b/lib/content_encoding.h
index 56e7f97..ef7930c 100644
--- a/lib/content_encoding.h
+++ b/lib/content_encoding.h
@@ -25,26 +25,9 @@
***************************************************************************/
#include "curl_setup.h"
-struct contenc_writer {
- const struct content_encoding *handler; /* Encoding handler. */
- struct contenc_writer *downstream; /* Downstream writer. */
- unsigned int order; /* Ordering within writer stack. */
-};
-
-/* Content encoding writer. */
-struct content_encoding {
- const char *name; /* Encoding name. */
- const char *alias; /* Encoding name alias. */
- CURLcode (*init_writer)(struct Curl_easy *data,
- struct contenc_writer *writer);
- CURLcode (*unencode_write)(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes);
- void (*close_writer)(struct Curl_easy *data,
- struct contenc_writer *writer);
- size_t writersize;
-};
+struct contenc_writer;
+char *Curl_all_content_encodings(void);
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int is_transfer);
@@ -52,6 +35,5 @@ CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes);
void Curl_unencode_cleanup(struct Curl_easy *data);
-char *Curl_all_content_encodings(void);
#endif /* HEADER_CURL_CONTENT_ENCODING_H */
diff --git a/lib/cookie.c b/lib/cookie.c
index 4345a84..af01203 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -112,14 +112,11 @@ static void strstore(char **str, const char *newstr, size_t len);
static void freecookie(struct Cookie *co)
{
- free(co->expirestr);
free(co->domain);
free(co->path);
free(co->spath);
free(co->name);
free(co->value);
- free(co->maxage);
- free(co->version);
free(co);
}
@@ -487,7 +484,7 @@ Curl_cookie_add(struct Curl_easy *data,
struct CookieInfo *c,
bool httpheader, /* TRUE if HTTP header-style line */
bool noexpire, /* if TRUE, skip remove_expired() */
- char *lineptr, /* first character of the line */
+ const char *lineptr, /* first character of the line */
const char *domain, /* default domain */
const char *path, /* full path used when this cookie is set,
used to get default path for the cookie
@@ -718,11 +715,7 @@ Curl_cookie_add(struct Curl_easy *data,
}
}
else if((nlen == 7) && strncasecompare("version", namep, 7)) {
- strstore(&co->version, valuep, vlen);
- if(!co->version) {
- badcookie = TRUE;
- break;
- }
+ /* just ignore */
}
else if((nlen == 7) && strncasecompare("max-age", namep, 7)) {
/*
@@ -734,17 +727,55 @@ Curl_cookie_add(struct Curl_easy *data,
* client should discard the cookie. A value of zero means the
* cookie should be discarded immediately.
*/
- strstore(&co->maxage, valuep, vlen);
- if(!co->maxage) {
- badcookie = TRUE;
+ CURLofft offt;
+ const char *maxage = valuep;
+ offt = curlx_strtoofft((*maxage == '\"')?
+ &maxage[1]:&maxage[0], NULL, 10,
+ &co->expires);
+ switch(offt) {
+ case CURL_OFFT_FLOW:
+ /* overflow, used max value */
+ co->expires = CURL_OFF_T_MAX;
+ break;
+ case CURL_OFFT_INVAL:
+ /* negative or otherwise bad, expire */
+ co->expires = 1;
+ break;
+ case CURL_OFFT_OK:
+ if(!co->expires)
+ /* already expired */
+ co->expires = 1;
+ else if(CURL_OFF_T_MAX - now < co->expires)
+ /* would overflow */
+ co->expires = CURL_OFF_T_MAX;
+ else
+ co->expires += now;
break;
}
}
else if((nlen == 7) && strncasecompare("expires", namep, 7)) {
- strstore(&co->expirestr, valuep, vlen);
- if(!co->expirestr) {
- badcookie = TRUE;
- break;
+ char date[128];
+ if(!co->expires && (vlen < sizeof(date))) {
+ /* copy the date so that it can be null terminated */
+ memcpy(date, valuep, vlen);
+ date[vlen] = 0;
+ /*
+ * Let max-age have priority.
+ *
+ * If the date cannot get parsed for whatever reason, the cookie
+ * will be treated as a session cookie
+ */
+ co->expires = Curl_getdate_capped(date);
+
+ /*
+ * Session cookies have expires set to 0 so if we get that back
+ * from the date parser let's add a second to make it a
+ * non-session cookie
+ */
+ if(co->expires == 0)
+ co->expires = 1;
+ else if(co->expires < 0)
+ co->expires = 0;
}
}
@@ -764,49 +795,6 @@ Curl_cookie_add(struct Curl_easy *data,
break;
} while(1);
- if(co->maxage) {
- CURLofft offt;
- offt = curlx_strtoofft((*co->maxage == '\"')?
- &co->maxage[1]:&co->maxage[0], NULL, 10,
- &co->expires);
- switch(offt) {
- case CURL_OFFT_FLOW:
- /* overflow, used max value */
- co->expires = CURL_OFF_T_MAX;
- break;
- case CURL_OFFT_INVAL:
- /* negative or otherwise bad, expire */
- co->expires = 1;
- break;
- case CURL_OFFT_OK:
- if(!co->expires)
- /* already expired */
- co->expires = 1;
- else if(CURL_OFF_T_MAX - now < co->expires)
- /* would overflow */
- co->expires = CURL_OFF_T_MAX;
- else
- co->expires += now;
- break;
- }
- }
- else if(co->expirestr) {
- /*
- * Note that if the date couldn't get parsed for whatever reason, the
- * cookie will be treated as a session cookie
- */
- co->expires = Curl_getdate_capped(co->expirestr);
-
- /*
- * Session cookies have expires set to 0 so if we get that back from the
- * date parser let's add a second to make it a non-session cookie
- */
- if(co->expires == 0)
- co->expires = 1;
- else if(co->expires < 0)
- co->expires = 0;
- }
-
if(!badcookie && !co->domain) {
if(domain) {
/* no domain was given in the header line, set the default */
@@ -894,7 +882,7 @@ Curl_cookie_add(struct Curl_easy *data,
if(ptr)
*ptr = 0; /* clear it */
- firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
+ firstptr = strtok_r((char *)lineptr, "\t", &tok_buf); /* tokenize on TAB */
/*
* Now loop through the fields and init the struct we already have
@@ -1159,9 +1147,6 @@ Curl_cookie_add(struct Curl_easy *data,
free(clist->domain);
free(clist->path);
free(clist->spath);
- free(clist->expirestr);
- free(clist->version);
- free(clist->maxage);
*clist = *co; /* then store all the new data */
@@ -1224,9 +1209,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
c = calloc(1, sizeof(struct CookieInfo));
if(!c)
return NULL; /* failed to get memory */
- c->filename = strdup(file?file:"none"); /* copy the name just in case */
- if(!c->filename)
- goto fail; /* failed to get memory */
/*
* Initialize the next_expiration time to signal that we don't have enough
* information yet.
@@ -1255,24 +1237,20 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
c->running = FALSE; /* this is not running, this is init */
if(fp) {
- char *lineptr;
- bool headerline;
line = malloc(MAX_COOKIE_LINE);
if(!line)
goto fail;
while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) {
+ char *lineptr = line;
+ bool headerline = FALSE;
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr = &line[11];
headerline = TRUE;
+ while(*lineptr && ISBLANK(*lineptr))
+ lineptr++;
}
- else {
- lineptr = line;
- headerline = FALSE;
- }
- while(*lineptr && ISBLANK(*lineptr))
- lineptr++;
Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
}
@@ -1288,8 +1266,8 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
fclose(handle);
}
data->state.cookie_engine = TRUE;
- c->running = TRUE; /* now, we're running */
}
+ c->running = TRUE; /* now, we're running */
return c;
@@ -1371,14 +1349,11 @@ static struct Cookie *dup_cookie(struct Cookie *src)
{
struct Cookie *d = calloc(sizeof(struct Cookie), 1);
if(d) {
- CLONE(expirestr);
CLONE(domain);
CLONE(path);
CLONE(spath);
CLONE(name);
CLONE(value);
- CLONE(maxage);
- CLONE(version);
d->expires = src->expires;
d->tailmatch = src->tailmatch;
d->secure = src->secure;
@@ -1595,7 +1570,6 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
{
if(c) {
unsigned int i;
- free(c->filename);
for(i = 0; i < COOKIE_HASH_SIZE; i++)
Curl_cookie_freelist(c->cookies[i]);
free(c); /* free the base struct as well */
diff --git a/lib/cookie.h b/lib/cookie.h
index b3c0063..012dd89 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -35,12 +35,6 @@ struct Cookie {
char *spath; /* sanitized cookie path */
char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */
- char *expirestr; /* the plain text version */
-
- /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
- char *version; /* Version = <value> */
- char *maxage; /* Max-Age = <value> */
-
bool tailmatch; /* whether we do tail-matching of the domain name */
bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
@@ -56,17 +50,16 @@ struct Cookie {
#define COOKIE_PREFIX__SECURE (1<<0)
#define COOKIE_PREFIX__HOST (1<<1)
-#define COOKIE_HASH_SIZE 256
+#define COOKIE_HASH_SIZE 63
struct CookieInfo {
/* linked list of cookies we know of */
struct Cookie *cookies[COOKIE_HASH_SIZE];
- char *filename; /* file we read from/write to */
- long numcookies; /* number of cookies in the "jar" */
+ curl_off_t next_expiration; /* the next time at which expiration happens */
+ int numcookies; /* number of cookies in the "jar" */
+ int lastct; /* last creation-time used in the jar */
bool running; /* state info, for cookie adding information */
bool newsession; /* new session, discard session cookies on load */
- int lastct; /* last creation-time used in the jar */
- curl_off_t next_expiration; /* the next time at which expiration happens */
};
/* The maximum sizes we accept for cookies. RFC 6265 section 6.1 says
@@ -75,7 +68,6 @@ struct CookieInfo {
- At least 4096 bytes per cookie (as measured by the sum of the length of
the cookie's name, value, and attributes).
-
In the 6265bis draft document section 5.4 it is phrased even stronger: "If
the sum of the lengths of the name string and the value string is more than
4096 octets, abort these steps and ignore the set-cookie-string entirely."
@@ -116,7 +108,7 @@ struct Curl_easy;
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
struct CookieInfo *c, bool header,
- bool noexpiry, char *lineptr,
+ bool noexpiry, const char *lineptr,
const char *domain, const char *path,
bool secure);
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index 65901a2..0bfb457 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -159,18 +159,21 @@
/* Define to 1 if you have the alarm function. */
#cmakedefine HAVE_ALARM 1
+/* Define to 1 if you have the arc4random function. */
+#cmakedefine HAVE_ARC4RANDOM 1
+
/* Define to 1 if you have the <arpa/inet.h> header file. */
#cmakedefine HAVE_ARPA_INET_H 1
-/* Define to 1 if you have the <arpa/tftp.h> header file. */
-#cmakedefine HAVE_ARPA_TFTP_H 1
-
/* Define to 1 if you have _Atomic support. */
#cmakedefine HAVE_ATOMIC 1
/* Define to 1 if you have the `fchmod' function. */
#cmakedefine HAVE_FCHMOD 1
+/* Define to 1 if you have the `fnmatch' function. */
+#cmakedefine HAVE_FNMATCH 1
+
/* Define to 1 if you have the `basename' function. */
#cmakedefine HAVE_BASENAME 1
@@ -183,6 +186,10 @@
/* Define to 1 if you have the clock_gettime function and monotonic timer. */
#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1
+/* Define to 1 if you have the clock_gettime function and raw monotonic timer.
+ */
+#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC_RAW 1
+
/* Define to 1 if you have the `closesocket' function. */
#cmakedefine HAVE_CLOSESOCKET 1
@@ -198,6 +205,12 @@
/* Define to 1 if you have the freeaddrinfo function. */
#cmakedefine HAVE_FREEADDRINFO 1
+/* Define to 1 if you have the fseeko function. */
+#cmakedefine HAVE_FSEEKO 1
+
+/* Define to 1 if you have the _fseeki64 function. */
+#cmakedefine HAVE__FSEEKI64 1
+
/* Define to 1 if you have the ftruncate function. */
#cmakedefine HAVE_FTRUNCATE 1
@@ -234,9 +247,6 @@
/* Define to 1 if you have the `getpass_r' function. */
#cmakedefine HAVE_GETPASS_R 1
-/* Define to 1 if you have the `getppid' function. */
-#cmakedefine HAVE_GETPPID 1
-
/* Define to 1 if you have the `getpeername' function. */
#cmakedefine HAVE_GETPEERNAME 1
@@ -373,6 +383,9 @@
/* Define to 1 if the compiler supports the 'long long' data type. */
#cmakedefine HAVE_LONGLONG 1
+/* Define to 1 if you have the 'suseconds_t' data type. */
+#cmakedefine HAVE_SUSECONDS_T 1
+
/* Define to 1 if you have the MSG_NOSIGNAL flag. */
#cmakedefine HAVE_MSG_NOSIGNAL 1
@@ -385,6 +398,9 @@
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#cmakedefine HAVE_NETINET_TCP_H 1
+/* Define to 1 if you have the <netinet/udp.h> header file. */
+#cmakedefine HAVE_NETINET_UDP_H 1
+
/* Define to 1 if you have the <linux/tcp.h> header file. */
#cmakedefine HAVE_LINUX_TCP_H 1
@@ -421,9 +437,15 @@
/* Define to 1 if you have the select function. */
#cmakedefine HAVE_SELECT 1
+/* Define to 1 if you have the sched_yield function. */
+#cmakedefine HAVE_SCHED_YIELD 1
+
/* Define to 1 if you have the send function. */
#cmakedefine HAVE_SEND 1
+/* Define to 1 if you have the sendmsg function. */
+#cmakedefine HAVE_SENDMSG 1
+
/* Define to 1 if you have the 'fsetxattr' function. */
#cmakedefine HAVE_FSETXATTR 1
@@ -433,9 +455,6 @@
/* fsetxattr() takes 6 args */
#cmakedefine HAVE_FSETXATTR_6 1
-/* Define to 1 if you have the <setjmp.h> header file. */
-#cmakedefine HAVE_SETJMP_H 1
-
/* Define to 1 if you have the `setlocale' function. */
#cmakedefine HAVE_SETLOCALE 1
@@ -457,14 +476,11 @@
/* Define to 1 if you have the signal function. */
#cmakedefine HAVE_SIGNAL 1
-/* Define to 1 if you have the <signal.h> header file. */
-#cmakedefine HAVE_SIGNAL_H 1
-
/* Define to 1 if you have the sigsetjmp function or macro. */
#cmakedefine HAVE_SIGSETJMP 1
/* Define to 1 if you have the `snprintf' function. */
-#cmakedefine HAVE_SNPRINTF
+#cmakedefine HAVE_SNPRINTF 1
/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
@@ -484,9 +500,6 @@
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
-/* Define to 1 if you have the <stdlib.h> header file. */
-#cmakedefine HAVE_STDLIB_H 1
-
/* Define to 1 if you have the strcasecmp function. */
#cmakedefine HAVE_STRCASECMP 1
@@ -505,9 +518,6 @@
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H 1
-/* Define to 1 if you have the <string.h> header file. */
-#cmakedefine HAVE_STRING_H 1
-
/* Define to 1 if you have the <stropts.h> header file. */
#cmakedefine HAVE_STROPTS_H 1
@@ -517,6 +527,9 @@
/* Define to 1 if you have the strtoll function. */
#cmakedefine HAVE_STRTOLL 1
+/* Define to 1 if you have the memrchr function. */
+#cmakedefine HAVE_MEMRCHR 1
+
/* if struct sockaddr_storage is defined */
#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE 1
@@ -526,6 +539,9 @@
/* Define to 1 if you have the <sys/filio.h> header file. */
#cmakedefine HAVE_SYS_FILIO_H 1
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#cmakedefine HAVE_SYS_WAIT_H 1
+
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#cmakedefine HAVE_SYS_IOCTL_H 1
@@ -568,9 +584,6 @@
/* Define to 1 if you have the <termio.h> header file. */
#cmakedefine HAVE_TERMIO_H 1
-/* Define to 1 if you have the <time.h> header file. */
-#cmakedefine HAVE_TIME_H 1
-
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
@@ -658,6 +671,9 @@ ${SIZEOF_OFF_T_CODE}
/* The size of `curl_off_t', as computed by sizeof. */
${SIZEOF_CURL_OFF_T_CODE}
+/* The size of `curl_socket_t', as computed by sizeof. */
+${SIZEOF_CURL_SOCKET_T_CODE}
+
/* The size of `size_t', as computed by sizeof. */
${SIZEOF_SIZE_T_CODE}
@@ -667,9 +683,6 @@ ${SIZEOF_TIME_T_CODE}
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#cmakedefine TIME_WITH_SYS_TIME 1
-
/* Define if you want to enable c-ares support */
#cmakedefine USE_ARES 1
@@ -735,7 +748,7 @@ ${SIZEOF_TIME_T_CODE}
#cmakedefine USE_MSH3 1
/* if Unix domain sockets are enabled */
-#cmakedefine USE_UNIX_SOCKETS
+#cmakedefine USE_UNIX_SOCKETS 1
/* Define to 1 if you are building a Windows target with large file support. */
#cmakedefine USE_WIN32_LARGE_FILES 1
@@ -792,3 +805,12 @@ ${SIZEOF_TIME_T_CODE}
/* Define to 1 to enable websocket support. */
#cmakedefine USE_WEBSOCKETS 1
+
+/* Define to 1 if OpenSSL has the SSL_CTX_set_srp_username function. */
+#cmakedefine HAVE_OPENSSL_SRP 1
+
+/* Define to 1 if GnuTLS has the gnutls_srp_verifier function. */
+#cmakedefine HAVE_GNUTLS_SRP 1
+
+/* Define to 1 to enable TLS-SRP support. */
+#cmakedefine USE_TLS_SRP 1
diff --git a/lib/curl_ctype.h b/lib/curl_ctype.h
index 1d1d60c..7f0d0cc 100644
--- a/lib/curl_ctype.h
+++ b/lib/curl_ctype.h
@@ -43,5 +43,9 @@
#define ISDIGIT(x) (((x) >= '0') && ((x) <= '9'))
#define ISBLANK(x) (((x) == ' ') || ((x) == '\t'))
#define ISSPACE(x) (ISBLANK(x) || (((x) >= 0xa) && ((x) <= 0x0d)))
+#define ISURLPUNTCS(x) (((x) == '-') || ((x) == '.') || ((x) == '_') || \
+ ((x) == '~'))
+#define ISUNRESERVED(x) (ISALNUM(x) || ISURLPUNTCS(x))
+
#endif /* HEADER_CURL_CTYPE_H */
diff --git a/lib/curl_hmac.h b/lib/curl_hmac.h
index 9438ca7..2ea03dd 100644
--- a/lib/curl_hmac.h
+++ b/lib/curl_hmac.h
@@ -24,8 +24,8 @@
*
***************************************************************************/
-#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
- || !defined(CURL_DISABLE_AWS)
+#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
+ || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)
#include <curl/curl.h>
diff --git a/lib/curl_memrchr.h b/lib/curl_memrchr.h
index a1a4ba0..45bb38c 100644
--- a/lib/curl_memrchr.h
+++ b/lib/curl_memrchr.h
@@ -28,9 +28,7 @@
#ifdef HAVE_MEMRCHR
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif
+#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
index a10e2a1..aa7bea7 100644
--- a/lib/curl_ntlm_wb.c
+++ b/lib/curl_ntlm_wb.c
@@ -39,9 +39,7 @@
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
-#ifdef HAVE_SIGNAL_H
#include <signal.h>
-#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index b43714d..ba14972 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -28,11 +28,6 @@
#define CURL_NO_OLDIES
#endif
-/* define mingw version macros, eg __MINGW{32,64}_{MINOR,MAJOR}_VERSION */
-#ifdef __MINGW32__
-#include <_mingw.h>
-#endif
-
/*
* Disable Visual Studio warnings:
* 4127 "conditional expression is constant"
@@ -830,9 +825,6 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#endif
#if defined(USE_UNIX_SOCKETS) && defined(WIN32)
-# if defined(__MINGW32__) && !defined(LUP_SECURE)
- typedef u_short ADDRESS_FAMILY; /* Classic mingw, 11y+ old mingw-w64 */
-# endif
# if !defined(UNIX_PATH_MAX)
/* Replicating logic present in afunix.h
(distributed with newer Windows 10 SDK versions only) */
diff --git a/lib/curl_sspi.h b/lib/curl_sspi.h
index 9816d59..5af7c24 100644
--- a/lib/curl_sspi.h
+++ b/lib/curl_sspi.h
@@ -70,227 +70,6 @@ extern PSecurityFunctionTable s_pSecFn;
#define ISC_REQ_USE_HTTP_STYLE 0x01000000
#endif
-#ifndef ISC_RET_REPLAY_DETECT
-#define ISC_RET_REPLAY_DETECT 0x00000004
-#endif
-
-#ifndef ISC_RET_SEQUENCE_DETECT
-#define ISC_RET_SEQUENCE_DETECT 0x00000008
-#endif
-
-#ifndef ISC_RET_CONFIDENTIALITY
-#define ISC_RET_CONFIDENTIALITY 0x00000010
-#endif
-
-#ifndef ISC_RET_ALLOCATED_MEMORY
-#define ISC_RET_ALLOCATED_MEMORY 0x00000100
-#endif
-
-#ifndef ISC_RET_STREAM
-#define ISC_RET_STREAM 0x00008000
-#endif
-
-#ifndef SEC_E_INSUFFICIENT_MEMORY
-# define SEC_E_INSUFFICIENT_MEMORY ((HRESULT)0x80090300L)
-#endif
-#ifndef SEC_E_INVALID_HANDLE
-# define SEC_E_INVALID_HANDLE ((HRESULT)0x80090301L)
-#endif
-#ifndef SEC_E_UNSUPPORTED_FUNCTION
-# define SEC_E_UNSUPPORTED_FUNCTION ((HRESULT)0x80090302L)
-#endif
-#ifndef SEC_E_TARGET_UNKNOWN
-# define SEC_E_TARGET_UNKNOWN ((HRESULT)0x80090303L)
-#endif
-#ifndef SEC_E_INTERNAL_ERROR
-# define SEC_E_INTERNAL_ERROR ((HRESULT)0x80090304L)
-#endif
-#ifndef SEC_E_SECPKG_NOT_FOUND
-# define SEC_E_SECPKG_NOT_FOUND ((HRESULT)0x80090305L)
-#endif
-#ifndef SEC_E_NOT_OWNER
-# define SEC_E_NOT_OWNER ((HRESULT)0x80090306L)
-#endif
-#ifndef SEC_E_CANNOT_INSTALL
-# define SEC_E_CANNOT_INSTALL ((HRESULT)0x80090307L)
-#endif
-#ifndef SEC_E_INVALID_TOKEN
-# define SEC_E_INVALID_TOKEN ((HRESULT)0x80090308L)
-#endif
-#ifndef SEC_E_CANNOT_PACK
-# define SEC_E_CANNOT_PACK ((HRESULT)0x80090309L)
-#endif
-#ifndef SEC_E_QOP_NOT_SUPPORTED
-# define SEC_E_QOP_NOT_SUPPORTED ((HRESULT)0x8009030AL)
-#endif
-#ifndef SEC_E_NO_IMPERSONATION
-# define SEC_E_NO_IMPERSONATION ((HRESULT)0x8009030BL)
-#endif
-#ifndef SEC_E_LOGON_DENIED
-# define SEC_E_LOGON_DENIED ((HRESULT)0x8009030CL)
-#endif
-#ifndef SEC_E_UNKNOWN_CREDENTIALS
-# define SEC_E_UNKNOWN_CREDENTIALS ((HRESULT)0x8009030DL)
-#endif
-#ifndef SEC_E_NO_CREDENTIALS
-# define SEC_E_NO_CREDENTIALS ((HRESULT)0x8009030EL)
-#endif
-#ifndef SEC_E_MESSAGE_ALTERED
-# define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL)
-#endif
-#ifndef SEC_E_OUT_OF_SEQUENCE
-# define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L)
-#endif
-#ifndef SEC_E_NO_AUTHENTICATING_AUTHORITY
-# define SEC_E_NO_AUTHENTICATING_AUTHORITY ((HRESULT)0x80090311L)
-#endif
-#ifndef SEC_E_BAD_PKGID
-# define SEC_E_BAD_PKGID ((HRESULT)0x80090316L)
-#endif
-#ifndef SEC_E_CONTEXT_EXPIRED
-# define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L)
-#endif
-#ifndef SEC_E_INCOMPLETE_MESSAGE
-# define SEC_E_INCOMPLETE_MESSAGE ((HRESULT)0x80090318L)
-#endif
-#ifndef SEC_E_INCOMPLETE_CREDENTIALS
-# define SEC_E_INCOMPLETE_CREDENTIALS ((HRESULT)0x80090320L)
-#endif
-#ifndef SEC_E_BUFFER_TOO_SMALL
-# define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L)
-#endif
-#ifndef SEC_E_WRONG_PRINCIPAL
-# define SEC_E_WRONG_PRINCIPAL ((HRESULT)0x80090322L)
-#endif
-#ifndef SEC_E_TIME_SKEW
-# define SEC_E_TIME_SKEW ((HRESULT)0x80090324L)
-#endif
-#ifndef SEC_E_UNTRUSTED_ROOT
-# define SEC_E_UNTRUSTED_ROOT ((HRESULT)0x80090325L)
-#endif
-#ifndef SEC_E_ILLEGAL_MESSAGE
-# define SEC_E_ILLEGAL_MESSAGE ((HRESULT)0x80090326L)
-#endif
-#ifndef SEC_E_CERT_UNKNOWN
-# define SEC_E_CERT_UNKNOWN ((HRESULT)0x80090327L)
-#endif
-#ifndef SEC_E_CERT_EXPIRED
-# define SEC_E_CERT_EXPIRED ((HRESULT)0x80090328L)
-#endif
-#ifndef SEC_E_ENCRYPT_FAILURE
-# define SEC_E_ENCRYPT_FAILURE ((HRESULT)0x80090329L)
-#endif
-#ifndef SEC_E_DECRYPT_FAILURE
-# define SEC_E_DECRYPT_FAILURE ((HRESULT)0x80090330L)
-#endif
-#ifndef SEC_E_ALGORITHM_MISMATCH
-# define SEC_E_ALGORITHM_MISMATCH ((HRESULT)0x80090331L)
-#endif
-#ifndef SEC_E_SECURITY_QOS_FAILED
-# define SEC_E_SECURITY_QOS_FAILED ((HRESULT)0x80090332L)
-#endif
-#ifndef SEC_E_UNFINISHED_CONTEXT_DELETED
-# define SEC_E_UNFINISHED_CONTEXT_DELETED ((HRESULT)0x80090333L)
-#endif
-#ifndef SEC_E_NO_TGT_REPLY
-# define SEC_E_NO_TGT_REPLY ((HRESULT)0x80090334L)
-#endif
-#ifndef SEC_E_NO_IP_ADDRESSES
-# define SEC_E_NO_IP_ADDRESSES ((HRESULT)0x80090335L)
-#endif
-#ifndef SEC_E_WRONG_CREDENTIAL_HANDLE
-# define SEC_E_WRONG_CREDENTIAL_HANDLE ((HRESULT)0x80090336L)
-#endif
-#ifndef SEC_E_CRYPTO_SYSTEM_INVALID
-# define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L)
-#endif
-#ifndef SEC_E_MAX_REFERRALS_EXCEEDED
-# define SEC_E_MAX_REFERRALS_EXCEEDED ((HRESULT)0x80090338L)
-#endif
-#ifndef SEC_E_MUST_BE_KDC
-# define SEC_E_MUST_BE_KDC ((HRESULT)0x80090339L)
-#endif
-#ifndef SEC_E_STRONG_CRYPTO_NOT_SUPPORTED
-# define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED ((HRESULT)0x8009033AL)
-#endif
-#ifndef SEC_E_TOO_MANY_PRINCIPALS
-# define SEC_E_TOO_MANY_PRINCIPALS ((HRESULT)0x8009033BL)
-#endif
-#ifndef SEC_E_NO_PA_DATA
-# define SEC_E_NO_PA_DATA ((HRESULT)0x8009033CL)
-#endif
-#ifndef SEC_E_PKINIT_NAME_MISMATCH
-# define SEC_E_PKINIT_NAME_MISMATCH ((HRESULT)0x8009033DL)
-#endif
-#ifndef SEC_E_SMARTCARD_LOGON_REQUIRED
-# define SEC_E_SMARTCARD_LOGON_REQUIRED ((HRESULT)0x8009033EL)
-#endif
-#ifndef SEC_E_SHUTDOWN_IN_PROGRESS
-# define SEC_E_SHUTDOWN_IN_PROGRESS ((HRESULT)0x8009033FL)
-#endif
-#ifndef SEC_E_KDC_INVALID_REQUEST
-# define SEC_E_KDC_INVALID_REQUEST ((HRESULT)0x80090340L)
-#endif
-#ifndef SEC_E_KDC_UNABLE_TO_REFER
-# define SEC_E_KDC_UNABLE_TO_REFER ((HRESULT)0x80090341L)
-#endif
-#ifndef SEC_E_KDC_UNKNOWN_ETYPE
-# define SEC_E_KDC_UNKNOWN_ETYPE ((HRESULT)0x80090342L)
-#endif
-#ifndef SEC_E_UNSUPPORTED_PREAUTH
-# define SEC_E_UNSUPPORTED_PREAUTH ((HRESULT)0x80090343L)
-#endif
-#ifndef SEC_E_DELEGATION_REQUIRED
-# define SEC_E_DELEGATION_REQUIRED ((HRESULT)0x80090345L)
-#endif
-#ifndef SEC_E_BAD_BINDINGS
-# define SEC_E_BAD_BINDINGS ((HRESULT)0x80090346L)
-#endif
-#ifndef SEC_E_MULTIPLE_ACCOUNTS
-# define SEC_E_MULTIPLE_ACCOUNTS ((HRESULT)0x80090347L)
-#endif
-#ifndef SEC_E_NO_KERB_KEY
-# define SEC_E_NO_KERB_KEY ((HRESULT)0x80090348L)
-#endif
-#ifndef SEC_E_CERT_WRONG_USAGE
-# define SEC_E_CERT_WRONG_USAGE ((HRESULT)0x80090349L)
-#endif
-#ifndef SEC_E_DOWNGRADE_DETECTED
-# define SEC_E_DOWNGRADE_DETECTED ((HRESULT)0x80090350L)
-#endif
-#ifndef SEC_E_SMARTCARD_CERT_REVOKED
-# define SEC_E_SMARTCARD_CERT_REVOKED ((HRESULT)0x80090351L)
-#endif
-#ifndef SEC_E_ISSUING_CA_UNTRUSTED
-# define SEC_E_ISSUING_CA_UNTRUSTED ((HRESULT)0x80090352L)
-#endif
-#ifndef SEC_E_REVOCATION_OFFLINE_C
-# define SEC_E_REVOCATION_OFFLINE_C ((HRESULT)0x80090353L)
-#endif
-#ifndef SEC_E_PKINIT_CLIENT_FAILURE
-# define SEC_E_PKINIT_CLIENT_FAILURE ((HRESULT)0x80090354L)
-#endif
-#ifndef SEC_E_SMARTCARD_CERT_EXPIRED
-# define SEC_E_SMARTCARD_CERT_EXPIRED ((HRESULT)0x80090355L)
-#endif
-#ifndef SEC_E_NO_S4U_PROT_SUPPORT
-# define SEC_E_NO_S4U_PROT_SUPPORT ((HRESULT)0x80090356L)
-#endif
-#ifndef SEC_E_CROSSREALM_DELEGATION_FAILURE
-# define SEC_E_CROSSREALM_DELEGATION_FAILURE ((HRESULT)0x80090357L)
-#endif
-#ifndef SEC_E_REVOCATION_OFFLINE_KDC
-# define SEC_E_REVOCATION_OFFLINE_KDC ((HRESULT)0x80090358L)
-#endif
-#ifndef SEC_E_ISSUING_CA_UNTRUSTED_KDC
-# define SEC_E_ISSUING_CA_UNTRUSTED_KDC ((HRESULT)0x80090359L)
-#endif
-#ifndef SEC_E_KDC_CERT_EXPIRED
-# define SEC_E_KDC_CERT_EXPIRED ((HRESULT)0x8009035AL)
-#endif
-#ifndef SEC_E_KDC_CERT_REVOKED
-# define SEC_E_KDC_CERT_REVOKED ((HRESULT)0x8009035BL)
-#endif
#ifndef SEC_E_INVALID_PARAMETER
# define SEC_E_INVALID_PARAMETER ((HRESULT)0x8009035DL)
#endif
@@ -301,30 +80,6 @@ extern PSecurityFunctionTable s_pSecFn;
# define SEC_E_POLICY_NLTM_ONLY ((HRESULT)0x8009035FL)
#endif
-#ifndef SEC_I_CONTINUE_NEEDED
-# define SEC_I_CONTINUE_NEEDED ((HRESULT)0x00090312L)
-#endif
-#ifndef SEC_I_COMPLETE_NEEDED
-# define SEC_I_COMPLETE_NEEDED ((HRESULT)0x00090313L)
-#endif
-#ifndef SEC_I_COMPLETE_AND_CONTINUE
-# define SEC_I_COMPLETE_AND_CONTINUE ((HRESULT)0x00090314L)
-#endif
-#ifndef SEC_I_LOCAL_LOGON
-# define SEC_I_LOCAL_LOGON ((HRESULT)0x00090315L)
-#endif
-#ifndef SEC_I_CONTEXT_EXPIRED
-# define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L)
-#endif
-#ifndef SEC_I_INCOMPLETE_CREDENTIALS
-# define SEC_I_INCOMPLETE_CREDENTIALS ((HRESULT)0x00090320L)
-#endif
-#ifndef SEC_I_RENEGOTIATE
-# define SEC_I_RENEGOTIATE ((HRESULT)0x00090321L)
-#endif
-#ifndef SEC_I_NO_LSA_CONTEXT
-# define SEC_I_NO_LSA_CONTEXT ((HRESULT)0x00090323L)
-#endif
#ifndef SEC_I_SIGNATURE_NEEDED
# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL)
#endif
diff --git a/lib/curl_threads.c b/lib/curl_threads.c
index e13e294..222d936 100644
--- a/lib/curl_threads.c
+++ b/lib/curl_threads.c
@@ -106,8 +106,6 @@ curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
{
#ifdef _WIN32_WCE
typedef HANDLE curl_win_thread_handle_t;
-#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
- typedef unsigned long curl_win_thread_handle_t;
#else
typedef uintptr_t curl_win_thread_handle_t;
#endif
diff --git a/lib/curl_threads.h b/lib/curl_threads.h
index facbc73..27a478d 100644
--- a/lib/curl_threads.h
+++ b/lib/curl_threads.h
@@ -40,8 +40,7 @@
# define curl_thread_t HANDLE
# define curl_thread_t_null (HANDLE)0
# if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
- (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \
- (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
+ (_WIN32_WINNT < _WIN32_WINNT_VISTA)
# define Curl_mutex_init(m) InitializeCriticalSection(m)
# else
# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1)
diff --git a/lib/curl_trc.c b/lib/curl_trc.c
index 76c35ba..e53b305 100644
--- a/lib/curl_trc.c
+++ b/lib/curl_trc.c
@@ -61,6 +61,10 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type,
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
if(data->set.fdebug) {
bool inCallback = Curl_is_in_callback(data);
+ /* CURLOPT_DEBUGFUNCTION doc says the user may set CURLOPT_PRIVATE to
+ distinguish their handle from internal handles. */
+ if(data->internal)
+ DEBUGASSERT(!data->set.private_data);
Curl_set_in_callback(data, true);
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
Curl_set_in_callback(data, inCallback);
diff --git a/lib/doh.c b/lib/doh.c
index 7a38eab..bb0c89e 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -242,6 +242,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
/* pass in the struct pointer via a local variable to please coverity and
the gcc typecheck helpers */
struct dynbuf *resp = &p->serverdoh;
+ doh->internal = true;
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
@@ -307,6 +308,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
if(data->set.ssl.fsslctxp)
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
+ if(data->set.fdebug)
+ ERROR_CHECK_SETOPT(CURLOPT_DEBUGFUNCTION, data->set.fdebug);
+ if(data->set.debugdata)
+ ERROR_CHECK_SETOPT(CURLOPT_DEBUGDATA, data->set.debugdata);
if(data->set.str[STRING_SSL_EC_CURVES]) {
ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
data->set.str[STRING_SSL_EC_CURVES]);
diff --git a/lib/dynbuf.h b/lib/dynbuf.h
index 6291eab..31a9130 100644
--- a/lib/dynbuf.h
+++ b/lib/dynbuf.h
@@ -89,4 +89,5 @@ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
#define DYN_H1_TRAILER 4096
#define DYN_PINGPPONG_CMD (64*1024)
#define DYN_IMAP_CMD (64*1024)
+#define DYN_MQTT_RECV (64*1024)
#endif
diff --git a/lib/dynhds.c b/lib/dynhds.c
index 007dfc5..979b3e8 100644
--- a/lib/dynhds.c
+++ b/lib/dynhds.c
@@ -344,6 +344,8 @@ size_t Curl_dynhds_cremove(struct dynhds *dynhds, const char *name)
return Curl_dynhds_remove(dynhds, name, strlen(name));
}
+#endif
+
CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
{
CURLcode result = CURLE_OK;
@@ -363,4 +365,3 @@ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
return result;
}
-#endif
diff --git a/lib/easy.c b/lib/easy.c
index 16bbd35..6b4fb8e 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -303,9 +303,6 @@ void curl_global_cleanup(void)
Curl_ssh_cleanup();
-#ifdef USE_WOLFSSH
- (void)wolfSSH_Cleanup();
-#endif
#ifdef DEBUGBUILD
free(leakpointer);
#endif
@@ -925,9 +922,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
if(data->cookies) {
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
- outcurl->cookies = Curl_cookie_init(data,
- data->cookies->filename,
- outcurl->cookies,
+ outcurl->cookies = Curl_cookie_init(data, NULL, outcurl->cookies,
data->set.cookiesession);
if(!outcurl->cookies)
goto fail;
@@ -1088,11 +1083,14 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
CURLcode result = CURLE_OK;
int oldstate;
int newstate;
+ bool recursive = FALSE;
if(!GOOD_EASY_HANDLE(data) || !data->conn)
/* crazy input, don't continue */
return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(Curl_is_in_callback(data))
+ recursive = TRUE;
k = &data->req;
oldstate = k->keepon & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
@@ -1120,34 +1118,9 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
if(!(newstate & KEEP_RECV_PAUSE)) {
Curl_conn_ev_data_pause(data, FALSE);
-
- if(data->state.tempcount) {
- /* there are buffers for sending that can be delivered as the receive
- pausing is lifted! */
- unsigned int i;
- unsigned int count = data->state.tempcount;
- struct tempbuf writebuf[3]; /* there can only be three */
-
- /* copy the structs to allow for immediate re-pausing */
- for(i = 0; i < data->state.tempcount; i++) {
- writebuf[i] = data->state.tempwrite[i];
- Curl_dyn_init(&data->state.tempwrite[i].b, DYN_PAUSE_BUFFER);
- }
- data->state.tempcount = 0;
-
- for(i = 0; i < count; i++) {
- /* even if one function returns error, this loops through and frees
- all buffers */
- if(!result)
- result = Curl_client_write(data, writebuf[i].type,
- Curl_dyn_ptr(&writebuf[i].b),
- Curl_dyn_len(&writebuf[i].b));
- Curl_dyn_free(&writebuf[i].b);
- }
-
- if(result)
- return result;
- }
+ result = Curl_client_unpause(data);
+ if(result)
+ return result;
}
#ifdef USE_HYPER
@@ -1184,6 +1157,11 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
corresponding socket callback, if used */
result = Curl_updatesocket(data);
+ if(recursive)
+ /* this might have called a callback recursively which might have set this
+ to false again on exit */
+ Curl_set_in_callback(data, TRUE);
+
return result;
}
diff --git a/lib/easy_lock.h b/lib/easy_lock.h
index 6399a39..d3fffd0 100644
--- a/lib/easy_lock.h
+++ b/lib/easy_lock.h
@@ -31,13 +31,6 @@
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
#ifdef __MINGW32__
-#ifndef __MINGW64_VERSION_MAJOR
-#if (__MINGW32_MAJOR_VERSION < 5) || \
- (__MINGW32_MAJOR_VERSION == 5 && __MINGW32_MINOR_VERSION == 0)
-/* mingw >= 5.0.1 defines SRWLOCK, and slightly different from MS define */
-typedef PVOID SRWLOCK, *PSRWLOCK;
-#endif
-#endif
#ifndef SRWLOCK_INIT
#define SRWLOCK_INIT NULL
#endif
diff --git a/lib/escape.c b/lib/escape.c
index 56aa2b3..5af00c3 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -38,33 +38,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-/* Portable character check (remember EBCDIC). Do not use isalnum() because
- its behavior is altered by the current locale.
- See https://datatracker.ietf.org/doc/html/rfc3986#section-2.3
-*/
-bool Curl_isunreserved(unsigned char in)
-{
- switch(in) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'i': case 'j':
- case 'k': case 'l': case 'm': case 'n': case 'o':
- case 'p': case 'q': case 'r': case 's': case 't':
- case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F': case 'G': case 'H': case 'I': case 'J':
- case 'K': case 'L': case 'M': case 'N': case 'O':
- case 'P': case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
- case '-': case '.': case '_': case '~':
- return TRUE;
- default:
- break;
- }
- return FALSE;
-}
-
/* for ABI-compatibility with previous versions */
char *curl_escape(const char *string, int inlength)
{
@@ -99,7 +72,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
while(length--) {
unsigned char in = *string++; /* treat the characters unsigned */
- if(Curl_isunreserved(in)) {
+ if(ISUNRESERVED(in)) {
/* append this */
if(Curl_dyn_addn(&d, &in, 1))
return NULL;
@@ -233,3 +206,29 @@ void curl_free(void *p)
{
free(p);
}
+
+/*
+ * Curl_hexencode()
+ *
+ * Converts binary input to lowercase hex-encoded ASCII output.
+ * Null-terminated.
+ */
+void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
+ unsigned char *out, size_t olen) /* output buffer size */
+{
+ const char *hex = "0123456789abcdef";
+ DEBUGASSERT(src && len && (olen >= 3));
+ if(src && len && (olen >= 3)) {
+ while(len-- && (olen >= 3)) {
+ /* clang-tidy warns on this line without this comment: */
+ /* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */
+ *out++ = hex[(*src & 0xF0)>>4];
+ *out++ = hex[*src & 0x0F];
+ ++src;
+ olen -= 2;
+ }
+ *out = 0;
+ }
+ else if(olen)
+ *out = 0;
+}
diff --git a/lib/escape.h b/lib/escape.h
index cdbb712..690e417 100644
--- a/lib/escape.h
+++ b/lib/escape.h
@@ -26,7 +26,7 @@
/* Escape and unescape URL encoding in strings. The functions return a new
* allocated string or NULL if an error occurred. */
-bool Curl_isunreserved(unsigned char in);
+#include "curl_ctype.h"
enum urlreject {
REJECT_NADA = 2,
@@ -38,4 +38,7 @@ CURLcode Curl_urldecode(const char *string, size_t length,
char **ostring, size_t *olen,
enum urlreject ctrl);
+void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
+ unsigned char *out, size_t olen); /* output buffer size */
+
#endif /* HEADER_CURL_ESCAPE_H */
diff --git a/lib/file.c b/lib/file.c
index c751e88..ffa9fb7 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -571,7 +571,9 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
if(result)
return result;
- Curl_pgrsSetDownloadCounter(data, bytecount);
+ result = Curl_pgrsSetDownloadCounter(data, bytecount);
+ if(result)
+ return result;
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
diff --git a/lib/fopen.c b/lib/fopen.c
index b6e3cad..75b8a7a 100644
--- a/lib/fopen.c
+++ b/lib/fopen.c
@@ -64,7 +64,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
fclose(*fh);
*fh = NULL;
- result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix));
+ result = Curl_rand_alnum(data, randsuffix, sizeof(randsuffix));
if(result)
goto fail;
diff --git a/lib/formdata.c b/lib/formdata.c
index 8984b63..e40c4bc 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -789,6 +789,20 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
return res;
}
+/* wrap call to fseeko so it matches the calling convention of callback */
+static int fseeko_wrapper(void *stream, curl_off_t offset, int whence)
+{
+#if defined(HAVE_FSEEKO)
+ return fseeko(stream, (off_t)offset, whence);
+#elif defined(HAVE__FSEEKI64)
+ return _fseeki64(stream, (__int64)offset, whence);
+#else
+ if(offset > LONG_MAX)
+ return -1;
+ return fseek(stream, (long)offset, whence);
+#endif
+}
+
/*
* Curl_getformdata() converts a linked list of "meta data" into a mime
* structure. The input list is in 'post', while the output is stored in
@@ -874,8 +888,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
compatibility: use of "-" pseudo file name should be avoided. */
result = curl_mime_data_cb(part, (curl_off_t) -1,
(curl_read_callback) fread,
- CURLX_FUNCTION_CAST(curl_seek_callback,
- fseek),
+ fseeko_wrapper,
NULL, (void *) stdin);
}
else
diff --git a/lib/ftp.c b/lib/ftp.c
index e24ae9c..518c923 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -2067,6 +2067,31 @@ static bool ftp_213_date(const char *p, int *year, int *month, int *day,
return TRUE;
}
+static CURLcode client_write_header(struct Curl_easy *data,
+ char *buf, size_t blen)
+{
+ /* Some replies from an FTP server are written to the client
+ * as CLIENTWRITE_HEADER, formatted as if they came from a
+ * HTTP conversation.
+ * In all protocols, CLIENTWRITE_HEADER data is only passed to
+ * the body write callback when data->set.include_header is set
+ * via CURLOPT_HEADER.
+ * For historic reasons, FTP never played this game and expects
+ * all its HEADERs to do that always. Set that flag during the
+ * call to Curl_client_write() so it does the right thing.
+ *
+ * Notice that we cannot enable this flag for FTP in general,
+ * as an FTP transfer might involve a HTTP proxy connection and
+ * headers from CONNECT should not automatically be part of the
+ * output. */
+ CURLcode result;
+ int save = data->set.include_header;
+ data->set.include_header = TRUE;
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, buf, blen);
+ data->set.include_header = save? TRUE:FALSE;
+ return result;
+}
+
static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
int ftpcode)
{
@@ -2120,8 +2145,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
- result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf,
- headerbuflen);
+ result = client_write_header(data, headerbuf, headerbuflen);
if(result)
return result;
} /* end of a ridiculous amount of conditionals */
@@ -2331,7 +2355,7 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
char clbuf[128];
int clbuflen = msnprintf(clbuf, sizeof(clbuf),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
- result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, clbuflen);
+ result = client_write_header(data, clbuf, clbuflen);
if(result)
return result;
}
@@ -2365,8 +2389,7 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
#ifdef CURL_FTP_HTTPSTYLE_HEAD
if(ftpcode == 350) {
char buffer[24]= { "Accept-ranges: bytes\r\n" };
- result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer,
- strlen(buffer));
+ result = client_write_header(data, buffer, strlen(buffer));
if(result)
return result;
}
@@ -3457,7 +3480,7 @@ CURLcode ftp_sendquote(struct Curl_easy *data,
/* if a command starts with an asterisk, which a legal FTP command never
can, the command will be allowed to fail without it causing any
aborts or cancels etc. It will cause libcurl to act as if the command
- is successful, whatever the server reponds. */
+ is successful, whatever the server responds. */
if(cmd[0] == '*') {
cmd++;
diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c
index 226d9bc..2a7ca5b 100644
--- a/lib/ftplistparser.c
+++ b/lib/ftplistparser.c
@@ -379,7 +379,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
/* scenario:
* 1. call => OK..
* 2. call => OUT_OF_MEMORY (or other error)
- * 3. (last) call => is skipped RIGHT HERE and the error is hadled later
+ * 3. (last) call => is skipped RIGHT HERE and the error is handled later
* in wc_statemach()
*/
goto fail;
diff --git a/lib/hmac.c b/lib/hmac.c
index 87e7be8..4019b67 100644
--- a/lib/hmac.c
+++ b/lib/hmac.c
@@ -26,8 +26,8 @@
#include "curl_setup.h"
-#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
- || !defined(CURL_DISABLE_AWS)
+#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
+ || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)
#include <curl/curl.h>
diff --git a/lib/hostip.c b/lib/hostip.c
index acb4b51..3cd9a65 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -41,12 +41,8 @@
#include <inet.h>
#endif
-#ifdef HAVE_SETJMP_H
#include <setjmp.h>
-#endif
-#ifdef HAVE_SIGNAL_H
#include <signal.h>
-#endif
#include "urldata.h"
#include "sendf.h"
diff --git a/lib/hostip.h b/lib/hostip.h
index 06d0867..b68f539 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -30,9 +30,7 @@
#include "timeval.h" /* for timediff_t */
#include "asyn.h"
-#ifdef HAVE_SETJMP_H
#include <setjmp.h>
-#endif
/* Allocate enough memory to hold the full name information structs and
* everything. OSF1 is known to require at least 8872 bytes. The buffer
diff --git a/lib/http.c b/lib/http.c
index 4344b9d..40ef70d 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1139,6 +1139,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
data->state.authproblem = TRUE;
}
}
+#else
+ ;
#endif
/* there may be multiple methods on one line, so keep reading */
@@ -1157,8 +1159,6 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
* http_should_fail() determines whether an HTTP response has gotten us
* into an error state or not.
*
- * @param conn all information about the current connection
- *
* @retval FALSE communications should continue
*
* @retval TRUE communications should not continue
@@ -1602,8 +1602,6 @@ CURLcode Curl_http_done(struct Curl_easy *data,
data->state.authhost.multipass = FALSE;
data->state.authproxy.multipass = FALSE;
- Curl_unencode_cleanup(data);
-
/* set the proper values (possibly modified on POST) */
conn->seek_func = data->set.seek_func; /* restore */
conn->seek_client = data->set.seek_client; /* restore */
@@ -3970,18 +3968,23 @@ CURLcode Curl_bump_headersize(struct Curl_easy *data,
bool connect_only)
{
size_t bad = 0;
+ unsigned int max = MAX_HTTP_RESP_HEADER_SIZE;
if(delta < MAX_HTTP_RESP_HEADER_SIZE) {
+ data->info.header_size += (unsigned int)delta;
+ data->req.allheadercount += (unsigned int)delta;
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)
+ if(data->req.allheadercount > max)
+ bad = data->req.allheadercount;
+ else if(data->info.header_size > (max * 20)) {
bad = data->info.header_size;
+ max *= 20;
+ }
}
else
- bad = data->info.header_size + delta;
+ bad = data->req.allheadercount + delta;
if(bad) {
- failf(data, "Too large response headers: %zu > %u",
- bad, MAX_HTTP_RESP_HEADER_SIZE);
+ failf(data, "Too large response headers: %zu > %u", bad, max);
return CURLE_RECV_ERROR;
}
return CURLE_OK;
@@ -4231,7 +4234,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* now, only output this if the header AND body are requested:
*/
writetype = CLIENTWRITE_HEADER |
- (data->set.include_header ? CLIENTWRITE_BODY : 0) |
((k->httpcode/100 == 1) ? CLIENTWRITE_1XX : 0);
headerlen = Curl_dyn_len(&data->state.headerb);
@@ -4563,8 +4565,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/*
* End of header-checks. Write them to the client.
*/
- if(data->set.include_header)
- writetype |= CLIENTWRITE_BODY;
if(k->httpcode/100 == 1)
writetype |= CLIENTWRITE_1XX;
diff --git a/lib/http1.c b/lib/http1.c
index 1ca7d41..182234c 100644
--- a/lib/http1.c
+++ b/lib/http1.c
@@ -318,5 +318,29 @@ out:
return nread;
}
+CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
+ struct dynbuf *dbuf)
+{
+ CURLcode result;
+
+ result = Curl_dyn_addf(dbuf, "%s %s%s%s%s HTTP/1.%d\r\n",
+ req->method,
+ req->scheme? req->scheme : "",
+ req->scheme? "://" : "",
+ req->authority? req->authority : "",
+ req->path? req->path : "",
+ http_minor);
+ if(result)
+ goto out;
+
+ result = Curl_dynhds_h1_dprint(&req->headers, dbuf);
+ if(result)
+ goto out;
+
+ result = Curl_dyn_addn(dbuf, STRCONST("\r\n"));
+
+out:
+ return result;
+}
#endif /* !CURL_DISABLE_HTTP */
diff --git a/lib/http1.h b/lib/http1.h
index b1eaa96..2de302f 100644
--- a/lib/http1.h
+++ b/lib/http1.h
@@ -56,6 +56,8 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
CURLcode Curl_h1_req_dprint(const struct httpreq *req,
struct dynbuf *dbuf);
+CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
+ struct dynbuf *dbuf);
#endif /* !CURL_DISABLE_HTTP */
#endif /* HEADER_CURL_HTTP1_H */
diff --git a/lib/http2.c b/lib/http2.c
index e0cda76..c8b0594 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -1688,7 +1688,7 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
"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 */
+ *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
return -1;
}
else if(stream->error != NGHTTP2_NO_ERROR) {
@@ -2313,7 +2313,7 @@ out:
"h2 windows %d-%d (stream-conn), "
"buffers %zu-%zu (stream-conn)",
stream->id, len, nwritten, *err,
- (ssize_t)stream->upload_left,
+ stream->upload_left,
nghttp2_session_get_stream_remote_window_size(
ctx->h2, stream->id),
nghttp2_session_get_remote_window_size(ctx->h2),
@@ -2425,6 +2425,8 @@ static void cf_h2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
cf_h2_ctx_clear(ctx);
CF_DATA_RESTORE(cf, save);
}
+ if(cf->next)
+ cf->next->cft->do_close(cf->next, data);
}
static void cf_h2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
diff --git a/lib/http_aws_sigv4.c b/lib/http_aws_sigv4.c
index f39d02c..901c22f 100644
--- a/lib/http_aws_sigv4.c
+++ b/lib/http_aws_sigv4.c
@@ -34,6 +34,7 @@
#include "transfer.h"
#include "parsedate.h"
#include "sendf.h"
+#include "escape.h"
#include <time.h>
@@ -63,11 +64,8 @@
static void sha256_to_hex(char *dst, unsigned char *sha)
{
- int i;
-
- for(i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
- msnprintf(dst + (i * 2), SHA256_HEX_LENGTH - (i * 2), "%02x", sha[i]);
- }
+ Curl_hexencode(sha, SHA256_DIGEST_LENGTH,
+ (unsigned char *)dst, SHA256_HEX_LENGTH);
}
static char *find_date_hdr(struct Curl_easy *data, const char *sig_hdr)
@@ -409,6 +407,11 @@ static int compare_func(const void *a, const void *b)
{
const struct pair *aa = a;
const struct pair *bb = b;
+ /* If one element is empty, the other is always sorted higher */
+ if(aa->len == 0)
+ return -1;
+ if(bb->len == 0)
+ return 1;
return strncmp(aa->p, bb->p, aa->len < bb->len ? aa->len : bb->len);
}
diff --git a/lib/http_chunks.c b/lib/http_chunks.c
index bda00d3..2a401d1 100644
--- a/lib/http_chunks.c
+++ b/lib/http_chunks.c
@@ -175,10 +175,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
/* Write the data portion available */
if(!data->set.http_te_skip && !k->ignorebody) {
- if(!data->set.http_ce_skip && k->writer_stack)
- result = Curl_unencode_write(data, k->writer_stack, datap, piece);
- else
- result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
if(result) {
*extrap = result;
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index 60bbfbe..a1d6da9 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -52,6 +52,113 @@
#include "memdebug.h"
+CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf,
+ const char **phostname,
+ int *pport, bool *pipv6_ip)
+{
+ DEBUGASSERT(cf);
+ DEBUGASSERT(cf->conn);
+
+ if(cf->conn->bits.conn_to_host)
+ *phostname = cf->conn->conn_to_host.name;
+ else if(cf->sockindex == SECONDARYSOCKET)
+ *phostname = cf->conn->secondaryhostname;
+ else
+ *phostname = cf->conn->host.name;
+
+ if(cf->sockindex == SECONDARYSOCKET)
+ *pport = cf->conn->secondary_port;
+ else if(cf->conn->bits.conn_to_port)
+ *pport = cf->conn->conn_to_port;
+ else
+ *pport = cf->conn->remote_port;
+
+ if(*phostname != cf->conn->host.name)
+ *pipv6_ip = (strchr(*phostname, ':') != NULL);
+ else
+ *pipv6_ip = cf->conn->bits.ipv6_ip;
+
+ return CURLE_OK;
+}
+
+CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int http_version_major)
+{
+ const char *hostname = NULL;
+ char *authority = NULL;
+ int port;
+ bool ipv6_ip;
+ CURLcode result;
+ struct httpreq *req = NULL;
+
+ result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
+ if(result)
+ goto out;
+
+ authority = aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname,
+ ipv6_ip?"]":"", port);
+ if(!authority) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT")-1,
+ NULL, 0, authority, strlen(authority),
+ NULL, 0);
+ if(result)
+ goto out;
+
+ /* Setup the proxy-authorization header, if any */
+ result = Curl_http_output_auth(data, cf->conn, req->method, HTTPREQ_GET,
+ req->authority, TRUE);
+ if(result)
+ goto out;
+
+ /* If user is not overriding Host: header, we add for HTTP/1.x */
+ if(http_version_major == 1 &&
+ !Curl_checkProxyheaders(data, cf->conn, STRCONST("Host"))) {
+ result = Curl_dynhds_cadd(&req->headers, "Host", authority);
+ if(result)
+ goto out;
+ }
+
+ if(data->state.aptr.proxyuserpwd) {
+ result = Curl_dynhds_h1_cadd_line(&req->headers,
+ data->state.aptr.proxyuserpwd);
+ if(result)
+ goto out;
+ }
+
+ if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent"))
+ && data->set.str[STRING_USERAGENT]) {
+ result = Curl_dynhds_cadd(&req->headers, "User-Agent",
+ data->set.str[STRING_USERAGENT]);
+ if(result)
+ goto out;
+ }
+
+ if(http_version_major == 1 &&
+ !Curl_checkProxyheaders(data, cf->conn, STRCONST("Proxy-Connection"))) {
+ result = Curl_dynhds_cadd(&req->headers, "Proxy-Connection", "Keep-Alive");
+ if(result)
+ goto out;
+ }
+
+ result = Curl_dynhds_add_custom(data, TRUE, &req->headers);
+
+out:
+ if(result && req) {
+ Curl_http_req_free(req);
+ req = NULL;
+ }
+ free(authority);
+ *preq = req;
+ return result;
+}
+
+
struct cf_proxy_ctx {
/* the protocol specific sub-filter we install during connect */
struct Curl_cfilter *cf_protocol;
@@ -105,7 +212,6 @@ connect_sub:
break;
#endif
default:
- 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;
diff --git a/lib/http_proxy.h b/lib/http_proxy.h
index a1a0372..2b5f7ae 100644
--- a/lib/http_proxy.h
+++ b/lib/http_proxy.h
@@ -30,6 +30,15 @@
#include "urldata.h"
+CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf,
+ const char **phostname,
+ int *pport, bool *pipv6_ip);
+
+CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int http_version_major);
+
/* Default proxy timeout in milliseconds */
#define PROXY_TIMEOUT (3600*1000)
diff --git a/lib/idn.c b/lib/idn.c
index 1f31a95..a024691 100644
--- a/lib/idn.c
+++ b/lib/idn.c
@@ -91,6 +91,8 @@ static CURLcode win32_idn_to_ascii(const char *in, char **out)
else
return CURLE_URL_MALFORMAT;
}
+ else
+ return CURLE_URL_MALFORMAT;
return CURLE_OK;
}
@@ -174,6 +176,9 @@ static CURLcode idn_decode(const char *input, char **output)
if(rc != IDN2_OK)
result = CURLE_URL_MALFORMAT;
}
+ else
+ /* a too old libidn2 version */
+ result = CURLE_NOT_BUILT_IN;
#elif defined(USE_WIN32_IDN)
result = win32_idn_to_ascii(input, &decoded);
#endif
diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c
index 135f486..c9cee0c 100644
--- a/lib/inet_ntop.c
+++ b/lib/inet_ntop.c
@@ -96,10 +96,10 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
char *tp;
struct {
- long base;
- long len;
+ int base;
+ int len;
} best, cur;
- unsigned long words[IN6ADDRSZ / INT16SZ];
+ unsigned int words[IN6ADDRSZ / INT16SZ];
int i;
/* Preprocess:
@@ -108,7 +108,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
*/
memset(words, '\0', sizeof(words));
for(i = 0; i < IN6ADDRSZ; i++)
- words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
+ words[i/2] |= ((unsigned int)src[i] << ((1 - (i % 2)) << 3));
best.base = -1;
cur.base = -1;
@@ -159,7 +159,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
tp += strlen(tp);
break;
}
- tp += msnprintf(tp, 5, "%lx", words[i]);
+ tp += msnprintf(tp, 5, "%x", words[i]);
}
/* Was it a trailing run of 0x00's?
diff --git a/lib/ldap.c b/lib/ldap.c
index 33a4dea..239d3fb 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -735,7 +735,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
if(result)
goto quit;
dlsize++;
- Curl_pgrsSetDownloadCounter(data, dlsize);
+ result = Curl_pgrsSetDownloadCounter(data, dlsize);
+ if(result)
+ goto quit;
}
if(ber)
diff --git a/lib/mime.c b/lib/mime.c
index 842b2da..3b27e59 100644
--- a/lib/mime.c
+++ b/lib/mime.c
@@ -1289,9 +1289,9 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
mime->lastpart = NULL;
memset(mime->boundary, '-', MIME_BOUNDARY_DASHES);
- if(Curl_rand_hex(easy,
- (unsigned char *) &mime->boundary[MIME_BOUNDARY_DASHES],
- MIME_RAND_BOUNDARY_CHARS + 1)) {
+ if(Curl_rand_alnum(easy,
+ (unsigned char *) &mime->boundary[MIME_BOUNDARY_DASHES],
+ MIME_RAND_BOUNDARY_CHARS + 1)) {
/* failed to get random separator, bail out */
free(mime);
return NULL;
diff --git a/lib/mime.h b/lib/mime.h
index 04adf2d..0a05c2a 100644
--- a/lib/mime.h
+++ b/lib/mime.h
@@ -27,7 +27,7 @@
#include "curl_setup.h"
#define MIME_BOUNDARY_DASHES 24 /* leading boundary dashes */
-#define MIME_RAND_BOUNDARY_CHARS 16 /* Nb. of random boundary chars. */
+#define MIME_RAND_BOUNDARY_CHARS 22 /* Nb. of random boundary chars. */
#define MAX_ENCODED_LINE_LENGTH 76 /* Maximum encoded line length. */
#define ENCODING_BUFFER_SIZE 256 /* Encoding temp buffers size. */
diff --git a/lib/mqtt.c b/lib/mqtt.c
index 30edf3d..54f8882 100644
--- a/lib/mqtt.c
+++ b/lib/mqtt.c
@@ -109,6 +109,7 @@ static CURLcode mqtt_setup_conn(struct Curl_easy *data,
mq = calloc(1, sizeof(struct MQTT));
if(!mq)
return CURLE_OUT_OF_MEMORY;
+ Curl_dyn_init(&mq->recvbuf, DYN_MQTT_RECV);
data->req.p.mqtt = mq;
return CURLE_OK;
}
@@ -295,12 +296,12 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
/* set initial values for the CONNECT packet */
pos = init_connpack(packet, remain, remain_pos);
- result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
- MQTT_CLIENTID_LEN - clen + 1);
+ result = Curl_rand_alnum(data, (unsigned char *)&client_id[clen],
+ MQTT_CLIENTID_LEN - clen + 1);
/* add client id */
rc = add_client_id(client_id, strlen(client_id), packet, pos + 1);
if(rc) {
- failf(data, "Client ID length mismatched: [%lu]", strlen(client_id));
+ failf(data, "Client ID length mismatched: [%zu]", strlen(client_id));
result = CURLE_WEIRD_SERVER_REPLY;
goto end;
}
@@ -317,7 +318,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
rc = add_user(username, ulen,
(unsigned char *)packet, start_user, remain_pos);
if(rc) {
- failf(data, "Username is too large: [%lu]", ulen);
+ failf(data, "Username is too large: [%zu]", ulen);
result = CURLE_WEIRD_SERVER_REPLY;
goto end;
}
@@ -327,7 +328,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
if(plen) {
rc = add_passwd(passwd, plen, packet, start_pwd, remain_pos);
if(rc) {
- failf(data, "Password is too large: [%lu]", plen);
+ failf(data, "Password is too large: [%zu]", plen);
result = CURLE_WEIRD_SERVER_REPLY;
goto end;
}
@@ -350,36 +351,66 @@ static CURLcode mqtt_disconnect(struct Curl_easy *data)
struct MQTT *mq = data->req.p.mqtt;
result = mqtt_send(data, (char *)"\xe0\x00", 2);
Curl_safefree(mq->sendleftovers);
+ Curl_dyn_free(&mq->recvbuf);
return result;
}
-static CURLcode mqtt_verify_connack(struct Curl_easy *data)
+static CURLcode mqtt_recv_atleast(struct Curl_easy *data, size_t nbytes)
{
+ struct MQTT *mq = data->req.p.mqtt;
+ size_t rlen = Curl_dyn_len(&mq->recvbuf);
CURLcode result;
- struct connectdata *conn = data->conn;
- curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- unsigned char readbuf[MQTT_CONNACK_LEN];
- ssize_t nread;
- result = Curl_read(data, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread);
- if(result)
- goto fail;
+ if(rlen < nbytes) {
+ unsigned char readbuf[1024];
+ ssize_t nread;
- Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
+ DEBUGASSERT(nbytes - rlen < sizeof(readbuf));
+ result = Curl_read(data, data->conn->sock[FIRSTSOCKET],
+ (char *)readbuf, nbytes - rlen, &nread);
+ if(result)
+ return result;
+ DEBUGASSERT(nread >= 0);
+ if(Curl_dyn_addn(&mq->recvbuf, readbuf, (size_t)nread))
+ return CURLE_OUT_OF_MEMORY;
+ rlen = Curl_dyn_len(&mq->recvbuf);
+ }
+ return (rlen >= nbytes)? CURLE_OK : CURLE_AGAIN;
+}
- /* fixme */
- if(nread < MQTT_CONNACK_LEN) {
- result = CURLE_WEIRD_SERVER_REPLY;
+static void mqtt_recv_consume(struct Curl_easy *data, size_t nbytes)
+{
+ struct MQTT *mq = data->req.p.mqtt;
+ size_t rlen = Curl_dyn_len(&mq->recvbuf);
+ if(rlen <= nbytes)
+ Curl_dyn_reset(&mq->recvbuf);
+ else
+ Curl_dyn_tail(&mq->recvbuf, rlen - nbytes);
+}
+
+static CURLcode mqtt_verify_connack(struct Curl_easy *data)
+{
+ struct MQTT *mq = data->req.p.mqtt;
+ CURLcode result;
+ char *ptr;
+
+ result = mqtt_recv_atleast(data, MQTT_CONNACK_LEN);
+ if(result)
goto fail;
- }
/* verify CONNACK */
- if(readbuf[0] != 0x00 || readbuf[1] != 0x00) {
+ DEBUGASSERT(Curl_dyn_len(&mq->recvbuf) >= MQTT_CONNACK_LEN);
+ ptr = Curl_dyn_ptr(&mq->recvbuf);
+ Curl_debug(data, CURLINFO_HEADER_IN, ptr, MQTT_CONNACK_LEN);
+
+ if(ptr[0] != 0x00 || ptr[1] != 0x00) {
failf(data, "Expected %02x%02x but got %02x%02x",
- 0x00, 0x00, readbuf[0], readbuf[1]);
+ 0x00, 0x00, ptr[0], ptr[1]);
+ Curl_dyn_reset(&mq->recvbuf);
result = CURLE_WEIRD_SERVER_REPLY;
+ goto fail;
}
-
+ mqtt_recv_consume(data, MQTT_CONNACK_LEN);
fail:
return result;
}
@@ -452,31 +483,29 @@ fail:
*/
static CURLcode mqtt_verify_suback(struct Curl_easy *data)
{
- CURLcode result;
+ struct MQTT *mq = data->req.p.mqtt;
struct connectdata *conn = data->conn;
- curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- unsigned char readbuf[MQTT_SUBACK_LEN];
- ssize_t nread;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
+ CURLcode result;
+ char *ptr;
- result = Curl_read(data, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread);
+ result = mqtt_recv_atleast(data, MQTT_SUBACK_LEN);
if(result)
goto fail;
- Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
-
- /* fixme */
- if(nread < MQTT_SUBACK_LEN) {
+ /* verify SUBACK */
+ DEBUGASSERT(Curl_dyn_len(&mq->recvbuf) >= MQTT_SUBACK_LEN);
+ ptr = Curl_dyn_ptr(&mq->recvbuf);
+ Curl_debug(data, CURLINFO_HEADER_IN, ptr, MQTT_SUBACK_LEN);
+
+ if(((unsigned char)ptr[0]) != ((mqtt->packetid >> 8) & 0xff) ||
+ ((unsigned char)ptr[1]) != (mqtt->packetid & 0xff) ||
+ ptr[2] != 0x00) {
+ Curl_dyn_reset(&mq->recvbuf);
result = CURLE_WEIRD_SERVER_REPLY;
goto fail;
}
-
- /* verify SUBACK */
- if(readbuf[0] != ((mqtt->packetid >> 8) & 0xff) ||
- readbuf[1] != (mqtt->packetid & 0xff) ||
- readbuf[2] != 0x00)
- result = CURLE_WEIRD_SERVER_REPLY;
-
+ mqtt_recv_consume(data, MQTT_SUBACK_LEN);
fail:
return result;
}
@@ -668,7 +697,9 @@ MQTT_SUBACK_COMING:
mq->npacket -= nread;
k->bytecount += nread;
- Curl_pgrsSetDownloadCounter(data, k->bytecount);
+ result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
+ if(result)
+ goto end;
/* if QoS is set, message contains packet id */
@@ -711,6 +742,7 @@ static CURLcode mqtt_done(struct Curl_easy *data,
(void)status;
(void)premature;
Curl_safefree(mq->sendleftovers);
+ Curl_dyn_free(&mq->recvbuf);
return CURLE_OK;
}
diff --git a/lib/mqtt.h b/lib/mqtt.h
index 6396136..84f1770 100644
--- a/lib/mqtt.h
+++ b/lib/mqtt.h
@@ -56,6 +56,7 @@ struct MQTT {
size_t npacket; /* byte counter */
unsigned char firstbyte;
size_t remaining_length;
+ struct dynbuf recvbuf;
};
#endif /* HEADER_CURL_MQTT_H */
diff --git a/lib/multi.c b/lib/multi.c
index bb57dbc..ff753ac 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -665,7 +665,6 @@ static CURLcode multi_done(struct Curl_easy *data,
{
CURLcode result;
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",
@@ -721,12 +720,7 @@ static CURLcode multi_done(struct Curl_easy *data,
Curl_safefree(data->state.ulbuf);
- /* if the transfer was completed in a paused state there can be buffered
- data left to free */
- for(i = 0; i < data->state.tempcount; i++) {
- Curl_dyn_free(&data->state.tempwrite[i].b);
- }
- data->state.tempcount = 0;
+ Curl_client_cleanup(data);
CONNCACHE_LOCK(data);
Curl_detach_connection(data);
@@ -2131,9 +2125,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
if(!result)
result = protocol_connect(data, &protocol_connected);
- if(!result && !protocol_connected)
+ if(!result && !protocol_connected) {
/* switch to waiting state */
multistate(data, MSTATE_PROTOCONNECTING);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
else if(!result) {
/* protocol connect has completed, go WAITDO or DO */
multistate(data, MSTATE_DO);
@@ -2220,6 +2216,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* DO was not completed in one function call, we must continue
DOING... */
multistate(data, MSTATE_DOING);
+ rc = CURLM_CALL_MULTI_PERFORM;
}
/* after DO, go DO_DONE... or DO_MORE */
@@ -2227,6 +2224,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* we're supposed to do more, but we need to sit down, relax
and wait a little while first */
multistate(data, MSTATE_DOING_MORE);
+ rc = CURLM_CALL_MULTI_PERFORM;
}
else {
/* we're done with the DO, now DID */
@@ -3139,7 +3137,7 @@ static CURLMcode add_next_timeout(struct curltime now,
struct Curl_llist_element *n = e->next;
timediff_t diff;
node = (struct time_node *)e->ptr;
- diff = Curl_timediff(node->time, now);
+ diff = Curl_timediff_us(node->time, now);
if(diff <= 0)
/* remove outdated entry */
Curl_llist_remove(list, e, NULL);
@@ -3422,20 +3420,10 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
/* some time left before expiration */
- timediff_t diff = Curl_timediff(multi->timetree->key, now);
- if(diff <= 0)
- /*
- * Since we only provide millisecond resolution on the returned value
- * and the diff might be less than one millisecond here, we don't
- * return zero as that may cause short bursts of busyloops on fast
- * processors while the diff is still present but less than one
- * millisecond! instead we return 1 until the time is ripe.
- */
- *timeout_ms = 1;
- else
- /* this should be safe even on 64 bit archs, as we don't use that
- overly long timeouts */
- *timeout_ms = (long)diff;
+ timediff_t diff = Curl_timediff_ceil(multi->timetree->key, now);
+ /* this should be safe even on 32 bit archs, as we don't use that
+ overly long timeouts */
+ *timeout_ms = (long)diff;
}
else
/* 0 means immediately */
@@ -3783,41 +3771,26 @@ bool Curl_is_in_callback(struct Curl_easy *easy)
(easy->multi_easy && easy->multi_easy->in_callback));
}
-#ifdef DEBUGBUILD
-void Curl_multi_dump(struct Curl_multi *multi)
-{
- struct Curl_easy *data;
- int i;
- fprintf(stderr, "* Multi status: %d handles, %d alive\n",
- multi->num_easy, multi->num_alive);
- for(data = multi->easyp; data; data = data->next) {
- if(data->mstate < MSTATE_COMPLETED) {
- /* only display handles that are not completed */
- fprintf(stderr, "handle %p, state %s, %d sockets\n",
- (void *)data,
- multi_statename[data->mstate], data->numsocks);
- for(i = 0; i < data->numsocks; i++) {
- curl_socket_t s = data->sockets[i];
- struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
-
- fprintf(stderr, "%d ", (int)s);
- if(!entry) {
- fprintf(stderr, "INTERNAL CONFUSION\n");
- continue;
- }
- fprintf(stderr, "[%s %s] ",
- (entry->action&CURL_POLL_IN)?"RECVING":"",
- (entry->action&CURL_POLL_OUT)?"SENDING":"");
- }
- if(data->numsocks)
- fprintf(stderr, "\n");
- }
- }
-}
-#endif
-
unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
{
DEBUGASSERT(multi);
return multi->max_concurrent_streams;
}
+
+struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
+{
+ struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) *
+ (multi->num_easy + 1));
+ if(a) {
+ int i = 0;
+ struct Curl_easy *e = multi->easyp;
+ while(e) {
+ DEBUGASSERT(i < multi->num_easy);
+ if(!e->internal)
+ a[i++] = e;
+ e = e->next;
+ }
+ a[i] = NULL; /* last entry is a NULL */
+ }
+ return a;
+}
diff --git a/lib/multiif.h b/lib/multiif.h
index 7f08ecc..7a344fa 100644
--- a/lib/multiif.h
+++ b/lib/multiif.h
@@ -62,15 +62,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
/* 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
- * allow easier tracking of the internal handle's state and what sockets
- * they use. Only for research and development DEBUGBUILD enabled builds.
- */
-void Curl_multi_dump(struct Curl_multi *multi);
-#endif
-
/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
diff --git a/lib/openldap.c b/lib/openldap.c
index 41fecf9..3aff306 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -199,11 +199,11 @@ struct ldapreqinfo {
};
/*
- * state()
+ * oldap_state()
*
* This is the ONLY way to change LDAP state!
*/
-static void state(struct Curl_easy *data, ldapstate newstate)
+static void oldap_state(struct Curl_easy *data, ldapstate newstate)
{
struct ldapconninfo *ldapc = data->conn->proto.ldapc;
@@ -444,7 +444,7 @@ static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd,
NULL, NULL, &li->msgid);
if(rc == LDAP_SUCCESS)
- state(data, newstate);
+ oldap_state(data, newstate);
else
result = oldap_map_error(rc,
data->state.aptr.user?
@@ -467,7 +467,7 @@ static CURLcode oldap_perform_mechs(struct Curl_easy *data)
(char **) supportedSASLMechanisms, 0,
NULL, NULL, NULL, 0, &li->msgid);
if(rc == LDAP_SUCCESS)
- state(data, OLDAP_MECHS);
+ oldap_state(data, OLDAP_MECHS);
else
result = oldap_map_error(rc, CURLE_LOGIN_DENIED);
return result;
@@ -480,7 +480,7 @@ static CURLcode oldap_perform_sasl(struct Curl_easy *data)
struct ldapconninfo *li = data->conn->proto.ldapc;
CURLcode result = Curl_sasl_start(&li->sasl, data, TRUE, &progress);
- state(data, OLDAP_SASL);
+ oldap_state(data, OLDAP_SASL);
if(!result && progress != SASL_INPROGRESS)
result = CURLE_LOGIN_DENIED;
return result;
@@ -503,7 +503,7 @@ static CURLcode oldap_ssl_connect(struct Curl_easy *data, ldapstate newstate)
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
if(!result) {
- state(data, newstate);
+ oldap_state(data, newstate);
if(ssldone) {
Sockbuf *sb;
@@ -527,7 +527,7 @@ static CURLcode oldap_perform_starttls(struct Curl_easy *data)
int rc = ldap_start_tls(li->ld, NULL, NULL, &li->msgid);
if(rc == LDAP_SUCCESS)
- state(data, OLDAP_STARTTLS);
+ oldap_state(data, OLDAP_STARTTLS);
else
result = oldap_map_error(rc, CURLE_USE_SSL_FAILED);
return result;
@@ -682,7 +682,7 @@ static CURLcode oldap_state_sasl_resp(struct Curl_easy *data,
else {
result = Curl_sasl_continue(&li->sasl, data, code, &progress);
if(!result && progress != SASL_INPROGRESS)
- state(data, OLDAP_STOP);
+ oldap_state(data, OLDAP_STOP);
}
if(li->servercred)
@@ -710,7 +710,7 @@ static CURLcode oldap_state_bind_resp(struct Curl_easy *data, LDAPMessage *msg,
result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
}
else
- state(data, OLDAP_STOP);
+ oldap_state(data, OLDAP_STOP);
if(bv)
ber_bvfree(bv);
@@ -804,7 +804,8 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
else if(data->state.aptr.user)
result = oldap_perform_bind(data, OLDAP_BIND);
else {
- state(data, OLDAP_STOP); /* Version 3 supported: no bind required */
+ /* Version 3 supported: no bind required */
+ oldap_state(data, OLDAP_STOP);
result = CURLE_OK;
}
}
diff --git a/lib/pingpong.c b/lib/pingpong.c
index 136985f..0081c9c 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -361,7 +361,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
* for "headers". The response lines can be seen as a kind of
* headers.
*/
- result = Curl_client_write(data, CLIENTWRITE_HEADER,
+ result = Curl_client_write(data, CLIENTWRITE_INFO,
pp->linestart_resp, perline);
if(result)
return result;
diff --git a/lib/progress.c b/lib/progress.c
index 6092b78..e783a9c 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -317,9 +317,16 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
/*
* Set the number of downloaded bytes so far.
*/
-void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
+CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
+ if(data->set.max_filesize && (size > data->set.max_filesize)) {
+ failf(data, "Exceeded the maximum allowed file size "
+ "(%" CURL_FORMAT_CURL_OFF_T ")",
+ data->set.max_filesize);
+ return CURLE_FILESIZE_EXCEEDED;
+ }
data->progress.downloaded = size;
+ return CURLE_OK;
}
/*
diff --git a/lib/progress.h b/lib/progress.h
index 0049cd0..fc39e34 100644
--- a/lib/progress.h
+++ b/lib/progress.h
@@ -46,7 +46,10 @@ int Curl_pgrsDone(struct Curl_easy *data);
void Curl_pgrsStartNow(struct Curl_easy *data);
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
-void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
+
+/* It is fine to not check the return code if 'size' is set to 0 */
+CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
+
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
int Curl_pgrsUpdate(struct Curl_easy *data);
diff --git a/lib/rand.c b/lib/rand.c
index a5620ea..6bd9613 100644
--- a/lib/rand.c
+++ b/lib/rand.c
@@ -24,6 +24,8 @@
#include "curl_setup.h"
+#include <limits.h>
+
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
@@ -41,6 +43,7 @@ uint32_t arc4random(void);
#include "sendf.h"
#include "timeval.h"
#include "rand.h"
+#include "escape.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -49,12 +52,7 @@ uint32_t arc4random(void);
#ifdef WIN32
-#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
-# define HAVE_MINGW_ORIGINAL
-#endif
-
-#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 && \
- !defined(HAVE_MINGW_ORIGINAL)
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
# define HAVE_WIN_BCRYPTGENRANDOM
# include <bcrypt.h>
# ifdef _MSC_VER
@@ -234,9 +232,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
size_t num)
{
CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
- const char *hex = "0123456789abcdef";
unsigned char buffer[128];
- unsigned char *bufp = buffer;
DEBUGASSERT(num > 1);
#ifdef __clang_analyzer__
@@ -255,13 +251,37 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
if(result)
return result;
+ Curl_hexencode(buffer, num/2, rnd, num + 1);
+ return result;
+}
+
+/*
+ * Curl_rand_alnum() fills the 'rnd' buffer with a given 'num' size with random
+ * alphanumerical chars PLUS a null-terminating byte.
+ */
+
+static const char alnum[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd,
+ size_t num)
+{
+ CURLcode result = CURLE_OK;
+ const int alnumspace = sizeof(alnum) - 1;
+ unsigned int r;
+ DEBUGASSERT(num > 1);
+
+ num--; /* save one for null-termination */
+
while(num) {
- /* clang-tidy warns on this line without this comment: */
- /* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */
- *rnd++ = hex[(*bufp & 0xF0)>>4];
- *rnd++ = hex[*bufp & 0x0F];
- bufp++;
- num -= 2;
+ do {
+ result = randit(data, &r);
+ if(result)
+ return result;
+ } while(r >= (UINT_MAX - UINT_MAX % alnumspace));
+
+ *rnd++ = alnum[r % alnumspace];
+ num--;
}
*rnd = 0;
diff --git a/lib/rand.h b/lib/rand.h
index 45ce3e7..1d009f5 100644
--- a/lib/rand.h
+++ b/lib/rand.h
@@ -34,6 +34,13 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
size_t num);
+/*
+ * Curl_rand_alnum() fills the 'rnd' buffer with a given 'num' size with random
+ * alphanumerical chars PLUS a null-terminating byte.
+ */
+CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd,
+ size_t num);
+
#ifdef WIN32
/* Random generator shared between the Schannel vtls and Curl_rand*()
functions */
diff --git a/lib/sendf.c b/lib/sendf.c
index d79ad08..0482c5d 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -40,6 +40,7 @@
#include "sendf.h"
#include "cfilters.h"
#include "connect.h"
+#include "content_encoding.h"
#include "vtls/vtls.h"
#include "vssh/ssh.h"
#include "easyif.h"
@@ -213,6 +214,7 @@ CURLcode Curl_write(struct Curl_easy *data,
static CURLcode pausewrite(struct Curl_easy *data,
int type, /* what type of data */
+ bool paused_body,
const char *ptr,
size_t len)
{
@@ -228,7 +230,8 @@ static CURLcode pausewrite(struct Curl_easy *data,
if(s->tempcount) {
for(i = 0; i< s->tempcount; i++) {
- if(s->tempwrite[i].type == type) {
+ if(s->tempwrite[i].type == type &&
+ !!s->tempwrite[i].paused_body == !!paused_body) {
/* data for this type exists */
newtype = FALSE;
break;
@@ -246,6 +249,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
/* store this information in the state struct for later use */
Curl_dyn_init(&s->tempwrite[i].b, DYN_PAUSE_BUFFER);
s->tempwrite[i].type = type;
+ s->tempwrite[i].paused_body = paused_body;
s->tempcount++;
}
@@ -265,6 +269,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
*/
static CURLcode chop_write(struct Curl_easy *data,
int type,
+ bool skip_body_write,
char *optr,
size_t olen)
{
@@ -281,10 +286,12 @@ static CURLcode chop_write(struct Curl_easy *data,
/* If reading is paused, append this data to the already held data for this
type. */
if(data->req.keepon & KEEP_RECV_PAUSE)
- return pausewrite(data, type, ptr, len);
+ return pausewrite(data, type, !skip_body_write, ptr, len);
/* Determine the callback(s) to use. */
- if(type & CLIENTWRITE_BODY) {
+ if(!skip_body_write &&
+ ((type & CLIENTWRITE_BODY) ||
+ ((type & CLIENTWRITE_HEADER) && data->set.include_header))) {
#ifdef USE_WEBSOCKETS
if(conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) {
writebody = Curl_ws_writecb;
@@ -294,7 +301,7 @@ static CURLcode chop_write(struct Curl_easy *data,
#endif
writebody = data->set.fwrite_func;
}
- if((type & CLIENTWRITE_HEADER) &&
+ if((type & (CLIENTWRITE_HEADER|CLIENTWRITE_INFO)) &&
(data->set.fwrite_header || data->set.writeheader)) {
/*
* Write headers to the same callback or to the especially setup
@@ -322,7 +329,7 @@ static CURLcode chop_write(struct Curl_easy *data,
failf(data, "Write callback asked for PAUSE when not supported");
return CURLE_WRITE_ERROR;
}
- return pausewrite(data, type, ptr, len);
+ return pausewrite(data, type, TRUE, ptr, len);
}
if(wrote != chunklen) {
failf(data, "Failure writing output to destination");
@@ -357,13 +364,7 @@ static CURLcode chop_write(struct Curl_easy *data,
Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote)
- /* here we pass in the HEADER bit only since if this was body as well
- then it was passed already and clearly that didn't trigger the
- pause, so this is saved for later with the HEADER bit only */
- return pausewrite(data, CLIENTWRITE_HEADER |
- (type & (CLIENTWRITE_STATUS|CLIENTWRITE_CONNECT|
- CLIENTWRITE_1XX|CLIENTWRITE_TRAILER)),
- optr, olen);
+ return pausewrite(data, type, FALSE, optr, olen);
if(wrote != olen) {
failf(data, "Failed writing header");
return CURLE_WRITE_ERROR;
@@ -397,9 +398,187 @@ CURLcode Curl_client_write(struct Curl_easy *data,
len = convert_lineends(data, ptr, len);
}
#endif
- return chop_write(data, type, ptr, len);
+ /* it is one of those, at least */
+ DEBUGASSERT(type & (CLIENTWRITE_BODY|CLIENTWRITE_HEADER|CLIENTWRITE_INFO));
+ /* BODY is only BODY */
+ DEBUGASSERT(!(type & CLIENTWRITE_BODY) || (type == CLIENTWRITE_BODY));
+ /* INFO is only INFO */
+ DEBUGASSERT(!(type & CLIENTWRITE_INFO) || (type == CLIENTWRITE_INFO));
+
+ if(type == CLIENTWRITE_BODY) {
+ if(data->req.ignorebody)
+ return CURLE_OK;
+
+ if(data->req.writer_stack && !data->set.http_ce_skip)
+ return Curl_unencode_write(data, data->req.writer_stack, ptr, len);
+ }
+ return chop_write(data, type, FALSE, ptr, len);
+}
+
+CURLcode Curl_client_unpause(struct Curl_easy *data)
+{
+ CURLcode result = CURLE_OK;
+
+ if(data->state.tempcount) {
+ /* there are buffers for sending that can be delivered as the receive
+ pausing is lifted! */
+ unsigned int i;
+ unsigned int count = data->state.tempcount;
+ struct tempbuf writebuf[3]; /* there can only be three */
+
+ /* copy the structs to allow for immediate re-pausing */
+ for(i = 0; i < data->state.tempcount; i++) {
+ writebuf[i] = data->state.tempwrite[i];
+ Curl_dyn_init(&data->state.tempwrite[i].b, DYN_PAUSE_BUFFER);
+ }
+ data->state.tempcount = 0;
+
+ for(i = 0; i < count; i++) {
+ /* even if one function returns error, this loops through and frees
+ all buffers */
+ if(!result)
+ result = chop_write(data, writebuf[i].type,
+ !writebuf[i].paused_body,
+ Curl_dyn_ptr(&writebuf[i].b),
+ Curl_dyn_len(&writebuf[i].b));
+ Curl_dyn_free(&writebuf[i].b);
+ }
+ }
+ return result;
}
+void Curl_client_cleanup(struct Curl_easy *data)
+{
+ struct contenc_writer *writer = data->req.writer_stack;
+ size_t i;
+
+ while(writer) {
+ data->req.writer_stack = writer->downstream;
+ writer->handler->close_writer(data, writer);
+ free(writer);
+ writer = data->req.writer_stack;
+ }
+
+ for(i = 0; i < data->state.tempcount; i++) {
+ Curl_dyn_free(&data->state.tempwrite[i].b);
+ }
+ data->state.tempcount = 0;
+
+}
+
+/* Real client writer: no downstream. */
+static CURLcode client_cew_init(struct Curl_easy *data,
+ struct contenc_writer *writer)
+{
+ (void) data;
+ (void)writer;
+ return CURLE_OK;
+}
+
+static CURLcode client_cew_write(struct Curl_easy *data,
+ struct contenc_writer *writer,
+ const char *buf, size_t nbytes)
+{
+ (void)writer;
+ if(!nbytes || data->req.ignorebody)
+ return CURLE_OK;
+ return chop_write(data, CLIENTWRITE_BODY, FALSE, (char *)buf, nbytes);
+}
+
+static void client_cew_close(struct Curl_easy *data,
+ struct contenc_writer *writer)
+{
+ (void) data;
+ (void) writer;
+}
+
+static const struct content_encoding client_cew = {
+ NULL,
+ NULL,
+ client_cew_init,
+ client_cew_write,
+ client_cew_close,
+ sizeof(struct contenc_writer)
+};
+
+/* Create an unencoding writer stage using the given handler. */
+CURLcode Curl_client_create_writer(struct contenc_writer **pwriter,
+ struct Curl_easy *data,
+ const struct content_encoding *ce_handler,
+ int order)
+{
+ struct contenc_writer *writer;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+
+ DEBUGASSERT(ce_handler->writersize >= sizeof(struct contenc_writer));
+ writer = (struct contenc_writer *) calloc(1, ce_handler->writersize);
+ if(!writer)
+ goto out;
+
+ writer->handler = ce_handler;
+ writer->order = order;
+ result = ce_handler->init_writer(data, writer);
+
+out:
+ *pwriter = result? NULL : writer;
+ if(result)
+ free(writer);
+ return result;
+}
+
+void Curl_client_free_writer(struct Curl_easy *data,
+ struct contenc_writer *writer)
+{
+ if(writer) {
+ writer->handler->close_writer(data, writer);
+ free(writer);
+ }
+}
+
+/* allow no more than 5 "chained" compression steps */
+#define MAX_ENCODE_STACK 5
+
+
+static CURLcode init_writer_stack(struct Curl_easy *data)
+{
+ DEBUGASSERT(!data->req.writer_stack);
+ return Curl_client_create_writer(&data->req.writer_stack,
+ data, &client_cew, 0);
+}
+
+CURLcode Curl_client_add_writer(struct Curl_easy *data,
+ struct contenc_writer *writer)
+{
+ CURLcode result;
+
+ if(!data->req.writer_stack) {
+ result = init_writer_stack(data);
+ if(result)
+ return result;
+ }
+
+ if(data->req.writer_stack_depth++ >= MAX_ENCODE_STACK) {
+ failf(data, "Reject response due to more than %u content encodings",
+ MAX_ENCODE_STACK);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Stack the unencoding stage. */
+ if(writer->order >= data->req.writer_stack->order) {
+ writer->downstream = data->req.writer_stack;
+ data->req.writer_stack = writer;
+ }
+ else {
+ struct contenc_writer *w = data->req.writer_stack;
+ while(w->downstream && writer->order < w->downstream->order)
+ w = w->downstream;
+ writer->downstream = w->downstream;
+ w->downstream = writer;
+ }
+ return CURLE_OK;
+}
+
+
/*
* Internal read-from-socket function. This is meant to deal with plain
* sockets, SSL sockets and kerberos sockets.
diff --git a/lib/sendf.h b/lib/sendf.h
index 5ef2b91..9ee00bb 100644
--- a/lib/sendf.h
+++ b/lib/sendf.h
@@ -28,18 +28,67 @@
#include "curl_trc.h"
-
-#define CLIENTWRITE_BODY (1<<0)
-#define CLIENTWRITE_HEADER (1<<1)
-#define CLIENTWRITE_STATUS (1<<2) /* the first "header" is the status line */
-#define CLIENTWRITE_CONNECT (1<<3) /* a CONNECT response */
-#define CLIENTWRITE_1XX (1<<4) /* a 1xx response */
-#define CLIENTWRITE_TRAILER (1<<5) /* a trailer header */
-#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
+/**
+ * Type of data that is being written to the client (application)
+ * - data written can be either BODY or META data
+ * - META data is either INFO or HEADER
+ * - INFO is meta information, e.g. not BODY, that cannot be interpreted
+ * as headers of a response. Example FTP/IMAP pingpong answers.
+ * - HEADER can have additional bits set (more than one)
+ * - STATUS special "header", e.g. response status line in HTTP
+ * - CONNECT header was received during proxying the connection
+ * - 1XX header is part of an intermediate response, e.g. HTTP 1xx code
+ * - TRAILER header is trailing response data, e.g. HTTP trailers
+ * BODY, INFO and HEADER should not be mixed, as this would lead to
+ * confusion on how to interpret/format/convert the data.
+ */
+#define CLIENTWRITE_BODY (1<<0) /* non-meta information, BODY */
+#define CLIENTWRITE_INFO (1<<1) /* meta information, not a HEADER */
+#define CLIENTWRITE_HEADER (1<<2) /* meta information, HEADER */
+#define CLIENTWRITE_STATUS (1<<3) /* a special status HEADER */
+#define CLIENTWRITE_CONNECT (1<<4) /* a CONNECT related HEADER */
+#define CLIENTWRITE_1XX (1<<5) /* a 1xx response related HEADER */
+#define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */
CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
+CURLcode Curl_client_unpause(struct Curl_easy *data);
+void Curl_client_cleanup(struct Curl_easy *data);
+
+struct contenc_writer {
+ const struct content_encoding *handler; /* Encoding handler. */
+ struct contenc_writer *downstream; /* Downstream writer. */
+ unsigned int order; /* Ordering within writer stack. */
+};
+
+/* Content encoding writer. */
+struct content_encoding {
+ const char *name; /* Encoding name. */
+ const char *alias; /* Encoding name alias. */
+ CURLcode (*init_writer)(struct Curl_easy *data,
+ struct contenc_writer *writer);
+ CURLcode (*unencode_write)(struct Curl_easy *data,
+ struct contenc_writer *writer,
+ const char *buf, size_t nbytes);
+ void (*close_writer)(struct Curl_easy *data,
+ struct contenc_writer *writer);
+ size_t writersize;
+};
+
+
+CURLcode Curl_client_create_writer(struct contenc_writer **pwriter,
+ struct Curl_easy *data,
+ const struct content_encoding *ce_handler,
+ int order);
+
+void Curl_client_free_writer(struct Curl_easy *data,
+ struct contenc_writer *writer);
+
+CURLcode Curl_client_add_writer(struct Curl_easy *data,
+ struct contenc_writer *writer);
+
+
/* internal read-function, does plain socket, SSL and krb4 */
CURLcode Curl_read(struct Curl_easy *data, curl_socket_t sockfd,
char *buf, size_t buffersize,
diff --git a/lib/setopt.c b/lib/setopt.c
index 2cef1b3..0d399ad 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -2076,7 +2076,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
else
#endif
result = CURLE_NOT_BUILT_IN;
- break;
+ break;
case CURLOPT_PINNEDPUBLICKEY:
/*
* Set pinned public key for SSL connection.
diff --git a/lib/sigpipe.h b/lib/sigpipe.h
index 48761ad..9b29403 100644
--- a/lib/sigpipe.h
+++ b/lib/sigpipe.h
@@ -25,7 +25,7 @@
***************************************************************************/
#include "curl_setup.h"
-#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && \
+#if defined(HAVE_SIGACTION) && \
(defined(USE_OPENSSL) || defined(USE_MBEDTLS) || defined(USE_WOLFSSL))
#include <signal.h>
diff --git a/lib/smb.c b/lib/smb.c
index afcc99d..32c5137 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -1049,7 +1049,12 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
}
data->req.bytecount += len;
data->req.offset += len;
- Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
+ result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
+ if(result) {
+ req->result = result;
+ next_state = SMB_CLOSE;
+ break;
+ }
next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
break;
diff --git a/lib/socks.c b/lib/socks.c
index c492d66..a7b5ab0 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -587,9 +587,9 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
if(!socks5_resolve_local && hostname_len > 255) {
- infof(data, "SOCKS5: server resolving disabled for hostnames of "
- "length > 255 [actual len=%zu]", hostname_len);
- socks5_resolve_local = TRUE;
+ 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))
@@ -903,7 +903,7 @@ CONNECT_RESOLVE_REMOTE:
}
else {
socksreq[len++] = 3;
- socksreq[len++] = (char) hostname_len; /* one byte address length */
+ socksreq[len++] = (unsigned char) hostname_len; /* one byte length */
memcpy(&socksreq[len], sx->hostname, hostname_len); /* w/o NULL */
len += hostname_len;
}
diff --git a/lib/telnet.c b/lib/telnet.c
index 850f88c..836e255 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -1570,8 +1570,9 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
total_dl += nread;
- Curl_pgrsSetDownloadCounter(data, total_dl);
- result = telrcv(data, (unsigned char *)buf, nread);
+ result = Curl_pgrsSetDownloadCounter(data, total_dl);
+ if(!result)
+ result = telrcv(data, (unsigned char *)buf, nread);
if(result) {
keepon = FALSE;
break;
diff --git a/lib/tftp.c b/lib/tftp.c
index 8ed1b88..e78140d 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -1141,12 +1141,15 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)state->rpacket.data + 4,
state->rbytes-4);
+ if(!result) {
+ k->bytecount += state->rbytes-4;
+ result = Curl_pgrsSetDownloadCounter(data,
+ (curl_off_t) k->bytecount);
+ }
if(result) {
tftp_state_machine(state, TFTP_EVENT_ERROR);
return result;
}
- k->bytecount += state->rbytes-4;
- Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount);
}
break;
case TFTP_EVENT_ERROR:
diff --git a/lib/timeval.c b/lib/timeval.c
index 2de79be..026d9d1 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -210,6 +210,20 @@ timediff_t Curl_timediff(struct curltime newer, struct curltime older)
}
/*
+ * Returns: time difference in number of milliseconds, rounded up.
+ * For too large diffs it returns max value.
+ */
+timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older)
+{
+ timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
+ if(diff >= (TIMEDIFF_T_MAX/1000))
+ return TIMEDIFF_T_MAX;
+ else if(diff <= (TIMEDIFF_T_MIN/1000))
+ return TIMEDIFF_T_MIN;
+ return diff * 1000 + (newer.tv_usec - older.tv_usec + 999)/1000;
+}
+
+/*
* Returns: time difference in number of microseconds. For too large diffs it
* returns max value.
*/
diff --git a/lib/timeval.h b/lib/timeval.h
index 92e484a..33dfb5b 100644
--- a/lib/timeval.h
+++ b/lib/timeval.h
@@ -36,16 +36,24 @@ struct curltime {
struct curltime Curl_now(void);
/*
- * Make sure that the first argument (t1) is the more recent time and t2 is
- * the older time, as otherwise you get a weird negative time-diff back...
+ * Make sure that the first argument (newer) is the more recent time and older
+ * is the older time, as otherwise you get a weird negative time-diff back...
*
* Returns: the time difference in number of milliseconds.
*/
-timediff_t Curl_timediff(struct curltime t1, struct curltime t2);
+timediff_t Curl_timediff(struct curltime newer, struct curltime older);
/*
- * Make sure that the first argument (t1) is the more recent time and t2 is
- * the older time, as otherwise you get a weird negative time-diff back...
+ * Make sure that the first argument (newer) is the more recent time and older
+ * is the older time, as otherwise you get a weird negative time-diff back...
+ *
+ * Returns: the time difference in number of milliseconds, rounded up.
+ */
+timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older);
+
+/*
+ * Make sure that the first argument (newer) is the more recent time and older
+ * is the older time, as otherwise you get a weird negative time-diff back...
*
* Returns: the time difference in number of microseconds.
*/
diff --git a/lib/transfer.c b/lib/transfer.c
index d0602b8..6886764 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -40,9 +40,7 @@
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
-#ifdef HAVE_SIGNAL_H
#include <signal.h>
-#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
@@ -671,7 +669,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
k->bytecount += nread;
max_recv -= nread;
- Curl_pgrsSetDownloadCounter(data, k->bytecount);
+ result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
+ if(result)
+ goto out;
if(!k->chunk && (nread || k->badheader || is_empty_data)) {
/* If this is chunky transfer, it was already written */
@@ -700,19 +700,15 @@ static CURLcode readwrite_data(struct Curl_easy *data,
in http_chunks.c.
Make sure that ALL_CONTENT_ENCODINGS contains all the
encodings handled here. */
- if(data->set.http_ce_skip || !k->writer_stack) {
- if(!k->ignorebody && nread) {
+ if(!k->ignorebody && nread) {
#ifndef CURL_DISABLE_POP3
- if(conn->handler->protocol & PROTO_FAMILY_POP3)
- result = Curl_pop3_write(data, k->str, nread);
- else
+ if(conn->handler->protocol & PROTO_FAMILY_POP3)
+ result = Curl_pop3_write(data, k->str, nread);
+ else
#endif /* CURL_DISABLE_POP3 */
- result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
- nread);
- }
+ result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
+ nread);
}
- else if(!k->ignorebody && nread)
- result = Curl_unencode_write(data, k->writer_stack, k->str, nread);
}
k->badheader = HEADER_NORMAL; /* taken care of now */
@@ -1050,6 +1046,19 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
return CURLE_OK;
}
+static int select_bits_paused(struct Curl_easy *data, int select_bits)
+{
+ /* See issue #11982: we really need to be careful not to progress
+ * a transfer direction when that direction is paused. Not all parts
+ * of our state machine are handling PAUSED transfers correctly. So, we
+ * do not want to go there.
+ * NOTE: we are only interested in PAUSE, not HOLD. */
+ return (((select_bits & CURL_CSELECT_IN) &&
+ (data->req.keepon & KEEP_RECV_PAUSE)) ||
+ ((select_bits & CURL_CSELECT_OUT) &&
+ (data->req.keepon & KEEP_SEND_PAUSE)));
+}
+
/*
* Curl_readwrite() is the low-level function to be called when data is to
* be read and written to/from the connection.
@@ -1068,12 +1077,20 @@ CURLcode Curl_readwrite(struct connectdata *conn,
int didwhat = 0;
int select_bits;
-
if(data->state.dselect_bits) {
+ if(select_bits_paused(data, data->state.dselect_bits)) {
+ /* leave the bits unchanged, so they'll tell us what to do when
+ * this transfer gets unpaused. */
+ DEBUGF(infof(data, "readwrite, dselect_bits, early return on PAUSED"));
+ result = CURLE_OK;
+ goto out;
+ }
select_bits = data->state.dselect_bits;
data->state.dselect_bits = 0;
}
else if(conn->cselect_bits) {
+ /* CAVEAT: adding `select_bits_paused()` check here makes test640 hang
+ * (among others). Which hints at strange state handling in FTP land... */
select_bits = conn->cselect_bits;
conn->cselect_bits = 0;
}
diff --git a/lib/url.c b/lib/url.c
index 4f5673e..61dad44 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -888,8 +888,8 @@ static bool conn_maxage(struct Curl_easy *data,
idletime /= 1000; /* integer seconds is fine */
if(idletime > data->set.maxage_conn) {
- infof(data, "Too old connection (%ld seconds idle), disconnect it",
- idletime);
+ infof(data, "Too old connection (%" CURL_FORMAT_TIMEDIFF_T
+ " seconds idle), disconnect it", idletime);
return TRUE;
}
@@ -898,8 +898,8 @@ static bool conn_maxage(struct Curl_easy *data,
if(data->set.maxlifetime_conn && lifetime > data->set.maxlifetime_conn) {
infof(data,
- "Too old connection (%ld seconds since creation), disconnect it",
- lifetime);
+ "Too old connection (%" CURL_FORMAT_TIMEDIFF_T
+ " seconds since creation), disconnect it", lifetime);
return TRUE;
}
@@ -1169,7 +1169,7 @@ ConnectionExists(struct Curl_easy *data,
foundPendingCandidate = TRUE;
/* Don't pick a connection that hasn't connected yet */
infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T
- "isn't open enough, can't reuse", check->connection_id);
+ " isn't open enough, can't reuse", check->connection_id);
continue;
}
@@ -2033,13 +2033,13 @@ void Curl_free_request_state(struct Curl_easy *data)
{
Curl_safefree(data->req.p.http);
Curl_safefree(data->req.newurl);
-
#ifndef CURL_DISABLE_DOH
if(data->req.doh) {
Curl_close(&data->req.doh->probe[0].easy);
Curl_close(&data->req.doh->probe[1].easy);
}
#endif
+ Curl_client_cleanup(data);
}
@@ -2076,7 +2076,6 @@ static char *detect_proxy(struct Curl_easy *data,
char proxy_env[128];
const char *protop = conn->handler->scheme;
char *envp = proxy_env;
- char *prox;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
@@ -2089,7 +2088,7 @@ static char *detect_proxy(struct Curl_easy *data,
strcpy(envp, "_proxy");
/* read the protocol proxy: */
- prox = curl_getenv(proxy_env);
+ proxy = curl_getenv(proxy_env);
/*
* We don't try the uppercase version of HTTP_PROXY because of
@@ -2103,23 +2102,35 @@ static char *detect_proxy(struct Curl_easy *data,
* This can cause 'internal' http/ftp requests to be
* arbitrarily redirected by any external attacker.
*/
- if(!prox && !strcasecompare("http_proxy", proxy_env)) {
+ if(!proxy && !strcasecompare("http_proxy", proxy_env)) {
/* There was no lowercase variable, try the uppercase version: */
Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
- prox = curl_getenv(proxy_env);
+ proxy = curl_getenv(proxy_env);
}
envp = proxy_env;
- if(prox) {
- proxy = prox; /* use this */
- }
- else {
- envp = (char *)"all_proxy";
- proxy = curl_getenv(envp); /* default proxy to use */
+ if(!proxy) {
+#ifdef USE_WEBSOCKETS
+ /* websocket proxy fallbacks */
+ if(strcasecompare("ws_proxy", proxy_env)) {
+ proxy = curl_getenv("http_proxy");
+ }
+ else if(strcasecompare("wss_proxy", proxy_env)) {
+ proxy = curl_getenv("https_proxy");
+ if(!proxy)
+ proxy = curl_getenv("HTTPS_PROXY");
+ }
if(!proxy) {
- envp = (char *)"ALL_PROXY";
- proxy = curl_getenv(envp);
+#endif
+ envp = (char *)"all_proxy";
+ proxy = curl_getenv(envp); /* default proxy to use */
+ if(!proxy) {
+ envp = (char *)"ALL_PROXY";
+ proxy = curl_getenv(envp);
+ }
+#ifdef USE_WEBSOCKETS
}
+#endif
}
if(proxy)
infof(data, "Uses proxy env variable %s == '%s'", envp, proxy);
@@ -2719,7 +2730,9 @@ static CURLcode override_login(struct Curl_easy *data,
data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
infof(data, "Couldn't find host %s in the %s file; using defaults",
- conn->host.name, data->set.str[STRING_NETRC_FILE]);
+ conn->host.name,
+ (data->set.str[STRING_NETRC_FILE] ?
+ data->set.str[STRING_NETRC_FILE] : ".netrc"));
}
else if(ret < 0) {
failf(data, ".netrc parser error");
@@ -3214,8 +3227,8 @@ static CURLcode resolve_host(struct Curl_easy *data,
if(rc == CURLRESOLV_PENDING)
*async = TRUE;
else if(rc == CURLRESOLV_TIMEDOUT) {
- failf(data, "Failed to resolve host '%s' with timeout after %ld ms",
- connhost->dispname,
+ failf(data, "Failed to resolve host '%s' with timeout after %"
+ CURL_FORMAT_TIMEDIFF_T " ms", connhost->dispname,
Curl_timediff(Curl_now(), data->progress.t_startsingle));
return CURLE_OPERATION_TIMEDOUT;
}
diff --git a/lib/urlapi.c b/lib/urlapi.c
index 80299e7..4efab61 100644
--- a/lib/urlapi.c
+++ b/lib/urlapi.c
@@ -100,7 +100,7 @@ static void free_urlhandle(struct Curl_URL *u)
/*
* Find the separator at the end of the host name, or the '?' in cases like
- * http://www.url.com?id=2380
+ * http://www.example.com?id=2380
*/
static const char *find_host_sep(const char *url)
{
@@ -338,7 +338,7 @@ static char *concat_url(char *base, const char *relurl)
pathsep = strchr(protsep, '/');
if(pathsep) {
/* When people use badly formatted URLs, such as
- "http://www.url.com?dir=/home/daniel" we must not use the first
+ "http://www.example.com?dir=/home/daniel" we must not use the first
slash, if there's a ?-letter before it! */
char *sep = strchr(protsep, '?');
if(sep && (sep < pathsep))
@@ -347,9 +347,9 @@ static char *concat_url(char *base, const char *relurl)
}
else {
/* There was no slash. Now, since we might be operating on a badly
- formatted URL, such as "http://www.url.com?id=2380" which doesn't
- use a slash separator as it is supposed to, we need to check for a
- ?-letter as well! */
+ formatted URL, such as "http://www.example.com?id=2380" which
+ doesn't use a slash separator as it is supposed to, we need to check
+ for a ?-letter as well! */
pathsep = strchr(protsep, '?');
if(pathsep)
*pathsep = 0;
@@ -1865,7 +1865,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if(result)
return CURLUE_OUT_OF_MEMORY;
}
- else if(Curl_isunreserved(*i) ||
+ else if(ISUNRESERVED(*i) ||
((*i == '/') && urlskipslash) ||
((*i == '=') && equalsencode)) {
if((*i == '=') && equalsencode)
diff --git a/lib/urldata.h b/lib/urldata.h
index 4bfb3b4..dff26e6 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -640,7 +640,9 @@ struct SingleRequest {
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 headerbytecount; /* received server headers (not CONNECT
+ headers) */
+ unsigned int allheadercount; /* all received headers (server + CONNECT) */
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
@@ -1260,6 +1262,7 @@ struct tempbuf {
struct dynbuf b;
int type; /* type of the 'tempwrite' buffer as a bitmask that is used with
Curl_client_write() */
+ BIT(paused_body); /* if PAUSE happened before/during BODY write */
};
/* Timers */
@@ -1947,7 +1950,7 @@ struct Curl_easy {
other using the same cache. For easier tracking
in log output.
This may wrap around after LONG_MAX to 0 again, so it
- has no uniqueness guarantuee for very large processings. */
+ has no uniqueness guarantee for very large processings. */
curl_off_t id;
/* first, two fields for the linked list of these */
@@ -2010,6 +2013,10 @@ struct Curl_easy {
#ifdef USE_HYPER
struct hyptransfer hyp;
#endif
+
+ /* internal: true if this easy handle was created for internal use and the
+ user does not have ownership of the handle. */
+ bool internal;
};
#define LIBCURL_NAME "libcurl"
diff --git a/lib/vauth/cleartext.c b/lib/vauth/cleartext.c
index c651fc5..972a874 100644
--- a/lib/vauth/cleartext.c
+++ b/lib/vauth/cleartext.c
@@ -35,7 +35,6 @@
#include "urldata.h"
#include "vauth/vauth.h"
-#include "curl_md5.h"
#include "warnless.h"
#include "strtok.h"
#include "sendf.h"
diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c
index 03e911d..7d681e5 100644
--- a/lib/vquic/curl_ngtcp2.c
+++ b/lib/vquic/curl_ngtcp2.c
@@ -30,7 +30,7 @@
#ifdef USE_OPENSSL
#include <openssl/err.h>
-#ifdef OPENSSL_IS_BORINGSSL
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
#include <ngtcp2/ngtcp2_crypto_boringssl.h>
#else
#include <ngtcp2/ngtcp2_crypto_quictls.h>
@@ -407,7 +407,7 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
goto out;
}
-#ifdef OPENSSL_IS_BORINGSSL
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) {
failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
goto out;
@@ -421,22 +421,24 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
SSL_CTX_set_default_verify_paths(ssl_ctx);
-#ifdef OPENSSL_IS_BORINGSSL
- if(SSL_CTX_set1_curves_list(ssl_ctx, QUIC_GROUPS) != 1) {
- failf(data, "SSL_CTX_set1_curves_list failed");
- goto out;
- }
-#else
- if(SSL_CTX_set_ciphersuites(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);
- goto out;
+ {
+ const char *curves = conn->ssl_config.curves ?
+ conn->ssl_config.curves : QUIC_GROUPS;
+ if(!SSL_CTX_set1_curves_list(ssl_ctx, curves)) {
+ failf(data, "failed setting curves list for QUIC: '%s'", curves);
+ return CURLE_SSL_CIPHER;
+ }
}
- if(SSL_CTX_set1_groups_list(ssl_ctx, QUIC_GROUPS) != 1) {
- failf(data, "SSL_CTX_set1_groups_list failed");
- goto out;
+#ifndef OPENSSL_IS_BORINGSSL
+ {
+ const char *ciphers13 = conn->ssl_config.cipher_list13 ?
+ conn->ssl_config.cipher_list13 : QUIC_CIPHERS;
+ if(SSL_CTX_set_ciphersuites(ssl_ctx, ciphers13) != 1) {
+ failf(data, "failed setting QUIC cipher suite: %s", ciphers13);
+ return CURLE_SSL_CIPHER;
+ }
+ infof(data, "QUIC cipher selection: %s", ciphers13);
}
#endif
@@ -616,15 +618,19 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
- if(wolfSSL_CTX_set_cipher_list(ssl_ctx, QUIC_CIPHERS) != 1) {
+ if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn->ssl_config.cipher_list13 ?
+ conn->ssl_config.cipher_list13 :
+ QUIC_CIPHERS) != 1) {
char error_buffer[256];
ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
- failf(data, "wolfSSL_CTX_set_cipher_list: %s", error_buffer);
+ failf(data, "wolfSSL failed to set ciphers: %s", error_buffer);
goto out;
}
- if(wolfSSL_CTX_set1_groups_list(ssl_ctx, (char *)QUIC_GROUPS) != 1) {
- failf(data, "SSL_CTX_set1_groups_list failed");
+ if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn->ssl_config.curves ?
+ conn->ssl_config.curves :
+ (char *)QUIC_GROUPS) != 1) {
+ failf(data, "wolfSSL failed to set curves");
goto out;
}
@@ -644,10 +650,13 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
const char * const ssl_capath = conn->ssl_config.CApath;
wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
- if(conn->ssl_config.CAfile || conn->ssl_config.CApath) {
+ if(ssl_cafile || ssl_capath) {
/* tell wolfSSL where to find CA certificates that are used to verify
the server's certificate. */
- if(!wolfSSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
+ int rc =
+ wolfSSL_CTX_load_verify_locations_ex(ssl_ctx, ssl_cafile, ssl_capath,
+ WOLFSSL_LOAD_FLAG_IGNORE_ERR);
+ if(SSL_SUCCESS != rc) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:"
" CAfile: %s CApath: %s",
diff --git a/lib/vquic/curl_quiche.c b/lib/vquic/curl_quiche.c
index 3598de1..3f5d327 100644
--- a/lib/vquic/curl_quiche.c
+++ b/lib/vquic/curl_quiche.c
@@ -149,8 +149,8 @@ static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf,
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)) {
+ 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",
@@ -165,7 +165,7 @@ static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf,
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);
+ SSL_CTX_set_default_verify_paths(ctx->sslctx);
}
#endif
}
@@ -178,6 +178,8 @@ static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
unsigned char checkip[16];
+ struct connectdata *conn = data->conn;
+ const char *curves = conn->ssl_config.curves;
DEBUGASSERT(!ctx->sslctx);
ctx->sslctx = SSL_CTX_new(TLS_method());
@@ -196,6 +198,11 @@ static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
SSL_CTX_set_keylog_callback(ctx->sslctx, keylog_callback);
}
+ if(curves && !SSL_CTX_set1_curves_list(ctx->sslctx, curves)) {
+ failf(data, "failed setting curves list for QUIC: '%s'", curves);
+ return CURLE_SSL_CIPHER;
+ }
+
ctx->ssl = SSL_new(ctx->sslctx);
if(!ctx->ssl)
return CURLE_QUIC_CONNECT_ERROR;
diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c
index dea0084..b0f49d6 100644
--- a/lib/vssh/libssh.c
+++ b/lib/vssh/libssh.c
@@ -2567,6 +2567,12 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
struct connectdata *conn = data->conn;
(void)sockindex;
+ /* limit the writes to the maximum specified in Section 3 of
+ * https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-02
+ */
+ if(len > 32768)
+ len = 32768;
+
nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
myssh_block2waitfor(conn, FALSE);
@@ -2654,7 +2660,7 @@ static void sftp_quote(struct Curl_easy *data)
/* if a command starts with an asterisk, which a legal SFTP command never
can, the command will be allowed to fail without it causing any
aborts or cancels etc. It will cause libcurl to act as if the command
- is successful, whatever the server reponds. */
+ is successful, whatever the server responds. */
if(cmd[0] == '*') {
cmd++;
@@ -2828,7 +2834,7 @@ static void sftp_quote_stat(struct Curl_easy *data)
/* if a command starts with an asterisk, which a legal SFTP command never
can, the command will be allowed to fail without it causing any
aborts or cancels etc. It will cause libcurl to act as if the command
- is successful, whatever the server reponds. */
+ is successful, whatever the server responds. */
if(cmd[0] == '*') {
cmd++;
diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c
index 37040b4..f539b39 100644
--- a/lib/vssh/libssh2.c
+++ b/lib/vssh/libssh2.c
@@ -1178,8 +1178,16 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
}
else {
char *err_msg = NULL;
- (void)libssh2_session_last_error(sshc->ssh_session,
- &err_msg, NULL, 0);
+ char unknown[] = "Reason unknown (-1)";
+ if(rc == -1) {
+ /* No error message has been set and the last set error message, if
+ any, is from a previous error so ignore it. #11837 */
+ err_msg = unknown;
+ }
+ else {
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ }
infof(data, "SSH public key authentication failed: %s", err_msg);
state(data, SSH_AUTH_PASS_INIT);
rc = 0; /* clear rc and continue */
@@ -1495,7 +1503,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
/* if a command starts with an asterisk, which a legal SFTP command never
can, the command will be allowed to fail without it causing any
aborts or cancels etc. It will cause libcurl to act as if the command
- is successful, whatever the server reponds. */
+ is successful, whatever the server responds. */
if(cmd[0] == '*') {
cmd++;
@@ -1691,7 +1699,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
/* if a command starts with an asterisk, which a legal SFTP command never
can, the command will be allowed to fail without it causing any
aborts or cancels etc. It will cause libcurl to act as if the command
- is successful, whatever the server reponds. */
+ is successful, whatever the server responds. */
if(cmd[0] == '*') {
cmd++;
diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c
index 306d299..39cee50 100644
--- a/lib/vssh/wolfssh.c
+++ b/lib/vssh/wolfssh.c
@@ -1168,6 +1168,7 @@ CURLcode Curl_ssh_init(void)
}
void Curl_ssh_cleanup(void)
{
+ (void)wolfSSH_Cleanup();
}
#endif /* USE_WOLFSSH */
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index e483469..c538a96 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -1473,7 +1473,6 @@ static int gtls_shutdown(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
struct gtls_ssl_backend_data *backend =
(struct gtls_ssl_backend_data *)connssl->backend;
int retval = 0;
@@ -1536,8 +1535,11 @@ static int gtls_shutdown(struct Curl_cfilter *cf,
gnutls_certificate_free_credentials(backend->gtls.cred);
#ifdef USE_GNUTLS_SRP
- if(ssl_config->primary.username)
- gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
+ {
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ if(ssl_config->primary.username)
+ gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
+ }
#endif
backend->gtls.cred = NULL;
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index f45636e..2f994d7 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -156,7 +156,8 @@ static void mbed_debug(void *context, int level, const char *f_name,
#else
#endif
-static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
+static int mbedtls_bio_cf_write(void *bio,
+ const unsigned char *buf, size_t blen)
{
struct Curl_cfilter *cf = bio;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
@@ -165,7 +166,7 @@ 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);
- CURL_TRC_CF(data, cf, "bio_cf_out_write(len=%zu) -> %zd, err=%d",
+ CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %zd, err=%d",
blen, nwritten, result);
if(nwritten < 0 && CURLE_AGAIN == result) {
nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
@@ -173,7 +174,7 @@ static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
return (int)nwritten;
}
-static int bio_cf_read(void *bio, unsigned char *buf, size_t blen)
+static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen)
{
struct Curl_cfilter *cf = bio;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
@@ -186,7 +187,7 @@ 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);
- CURL_TRC_CF(data, cf, "bio_cf_in_read(len=%zu) -> %zd, err=%d",
+ CURL_TRC_CF(data, cf, "mbedtls_bio_cf_in_read(len=%zu) -> %zd, err=%d",
blen, nread, result);
if(nread < 0 && CURLE_AGAIN == result) {
nread = MBEDTLS_ERR_SSL_WANT_READ;
@@ -591,7 +592,9 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
&backend->ctr_drbg);
- mbedtls_ssl_set_bio(&backend->ssl, cf, bio_cf_write, bio_cf_read,
+ mbedtls_ssl_set_bio(&backend->ssl, cf,
+ mbedtls_bio_cf_write,
+ mbedtls_bio_cf_read,
NULL /* rev_timeout() */);
mbedtls_ssl_conf_ciphersuites(&backend->config,
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index a12e712..9f9c8d1 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -466,7 +466,9 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
X509_get0_signature(&psig, &sigalg, x);
if(sigalg) {
- i2a_ASN1_OBJECT(mem, sigalg->algorithm);
+ const ASN1_OBJECT *sigalgoid = NULL;
+ X509_ALGOR_get0(&sigalgoid, NULL, NULL, sigalg);
+ i2a_ASN1_OBJECT(mem, sigalgoid);
push_certinfo("Signature Algorithm", i);
}
@@ -661,7 +663,7 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
#define BIO_set_shutdown(x,v) ((x)->shutdown=(v))
#endif /* USE_PRE_1_1_API */
-static int bio_cf_create(BIO *bio)
+static int ossl_bio_cf_create(BIO *bio)
{
BIO_set_shutdown(bio, 1);
BIO_set_init(bio, 1);
@@ -672,14 +674,14 @@ static int bio_cf_create(BIO *bio)
return 1;
}
-static int bio_cf_destroy(BIO *bio)
+static int ossl_bio_cf_destroy(BIO *bio)
{
if(!bio)
return 0;
return 1;
}
-static long bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
+static long ossl_bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
{
struct Curl_cfilter *cf = BIO_get_data(bio);
long ret = 1;
@@ -713,7 +715,7 @@ static long bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
return ret;
}
-static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
+static int ossl_bio_cf_out_write(BIO *bio, const char *buf, int blen)
{
struct Curl_cfilter *cf = BIO_get_data(bio);
struct ssl_connect_data *connssl = cf->ctx;
@@ -725,7 +727,7 @@ 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);
- CURL_TRC_CF(data, cf, "bio_cf_out_write(len=%d) -> %d, err=%d",
+ CURL_TRC_CF(data, cf, "ossl_bio_cf_out_write(len=%d) -> %d, err=%d",
blen, (int)nwritten, result);
BIO_clear_retry_flags(bio);
backend->io_result = result;
@@ -736,7 +738,7 @@ static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
return (int)nwritten;
}
-static int bio_cf_in_read(BIO *bio, char *buf, int blen)
+static int ossl_bio_cf_in_read(BIO *bio, char *buf, int blen)
{
struct Curl_cfilter *cf = BIO_get_data(bio);
struct ssl_connect_data *connssl = cf->ctx;
@@ -752,7 +754,7 @@ 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);
- CURL_TRC_CF(data, cf, "bio_cf_in_read(len=%d) -> %d, err=%d",
+ CURL_TRC_CF(data, cf, "ossl_bio_cf_in_read(len=%d) -> %d, err=%d",
blen, (int)nread, result);
BIO_clear_retry_flags(bio);
backend->io_result = result;
@@ -777,42 +779,42 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
#if USE_PRE_1_1_API
-static BIO_METHOD bio_cf_meth_1_0 = {
+static BIO_METHOD ossl_bio_cf_meth_1_0 = {
BIO_TYPE_MEM,
"OpenSSL CF BIO",
- bio_cf_out_write,
- bio_cf_in_read,
+ ossl_bio_cf_out_write,
+ ossl_bio_cf_in_read,
NULL, /* puts is never called */
NULL, /* gets is never called */
- bio_cf_ctrl,
- bio_cf_create,
- bio_cf_destroy,
+ ossl_bio_cf_ctrl,
+ ossl_bio_cf_create,
+ ossl_bio_cf_destroy,
NULL
};
-static BIO_METHOD *bio_cf_method_create(void)
+static BIO_METHOD *ossl_bio_cf_method_create(void)
{
- return &bio_cf_meth_1_0;
+ return &ossl_bio_cf_meth_1_0;
}
-#define bio_cf_method_free(m) Curl_nop_stmt
+#define ossl_bio_cf_method_free(m) Curl_nop_stmt
#else
-static BIO_METHOD *bio_cf_method_create(void)
+static BIO_METHOD *ossl_bio_cf_method_create(void)
{
BIO_METHOD *m = BIO_meth_new(BIO_TYPE_MEM, "OpenSSL CF BIO");
if(m) {
- BIO_meth_set_write(m, &bio_cf_out_write);
- BIO_meth_set_read(m, &bio_cf_in_read);
- BIO_meth_set_ctrl(m, &bio_cf_ctrl);
- BIO_meth_set_create(m, &bio_cf_create);
- BIO_meth_set_destroy(m, &bio_cf_destroy);
+ BIO_meth_set_write(m, &ossl_bio_cf_out_write);
+ BIO_meth_set_read(m, &ossl_bio_cf_in_read);
+ BIO_meth_set_ctrl(m, &ossl_bio_cf_ctrl);
+ BIO_meth_set_create(m, &ossl_bio_cf_create);
+ BIO_meth_set_destroy(m, &ossl_bio_cf_destroy);
}
return m;
}
-static void bio_cf_method_free(BIO_METHOD *m)
+static void ossl_bio_cf_method_free(BIO_METHOD *m)
{
if(m)
BIO_meth_free(m);
@@ -1551,11 +1553,9 @@ fail:
UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
UI_method_set_reader(ui_method, ssl_ui_reader);
UI_method_set_writer(ui_method, ssl_ui_writer);
- /* the typecast below was added to please mingw32 */
- priv_key = (EVP_PKEY *)
- ENGINE_load_private_key(data->state.engine, key_file,
- ui_method,
- key_passwd);
+ priv_key = ENGINE_load_private_key(data->state.engine, key_file,
+ ui_method,
+ key_passwd);
UI_destroy_method(ui_method);
if(!priv_key) {
failf(data, "failed to load private key from crypto engine");
@@ -1878,15 +1878,45 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
if(backend->handle) {
if(cf->next && cf->next->connected) {
- char buf[32];
+ char buf[1024];
+ int nread, err;
+ long sslerr;
+
/* 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);
-
ERR_clear_error();
+ if(SSL_shutdown(backend->handle) == 1) {
+ CURL_TRC_CF(data, cf, "SSL shutdown finished");
+ }
+ else {
+ nread = SSL_read(backend->handle, buf, (int)sizeof(buf));
+ err = SSL_get_error(backend->handle, nread);
+ switch(err) {
+ case SSL_ERROR_NONE: /* this is not an error */
+ case SSL_ERROR_ZERO_RETURN: /* no more data */
+ CURL_TRC_CF(data, cf, "SSL shutdown, EOF from server");
+ break;
+ case SSL_ERROR_WANT_READ:
+ /* SSL has send its notify and now wants to read the reply
+ * from the server. We are not really interested in that. */
+ CURL_TRC_CF(data, cf, "SSL shutdown sent");
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ CURL_TRC_CF(data, cf, "SSL shutdown send blocked");
+ break;
+ default:
+ sslerr = ERR_get_error();
+ CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s', errno %d",
+ (sslerr ?
+ ossl_strerror(sslerr, buf, sizeof(buf)) :
+ SSL_ERROR_to_str(err)),
+ SOCKERRNO);
+ break;
+ }
+ }
+ ERR_clear_error();
SSL_set_connect_state(backend->handle);
}
@@ -1899,7 +1929,7 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
backend->x509_store_setup = FALSE;
}
if(backend->bio_method) {
- bio_cf_method_free(backend->bio_method);
+ ossl_bio_cf_method_free(backend->bio_method);
backend->bio_method = NULL;
}
}
@@ -3789,7 +3819,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
Curl_ssl_sessionid_unlock(data);
}
- backend->bio_method = bio_cf_method_create();
+ backend->bio_method = ossl_bio_cf_method_create();
if(!backend->bio_method)
return CURLE_OUT_OF_MEMORY;
bio = BIO_new(backend->bio_method);
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index f6a5d44..410a5c4 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -68,22 +68,6 @@
# define HAS_ALPN 1
#endif
-#ifndef UNISP_NAME_A
-#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
-#endif
-
-#ifndef UNISP_NAME_W
-#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider"
-#endif
-
-#ifndef UNISP_NAME
-#ifdef UNICODE
-#define UNISP_NAME UNISP_NAME_W
-#else
-#define UNISP_NAME UNISP_NAME_A
-#endif
-#endif
-
#ifndef BCRYPT_CHACHA20_POLY1305_ALGORITHM
#define BCRYPT_CHACHA20_POLY1305_ALGORITHM L"CHACHA20_POLY1305"
#endif
@@ -108,13 +92,6 @@
#define BCRYPT_SHA384_ALGORITHM L"SHA384"
#endif
-/* Workaround broken compilers like MinGW.
- Return the number of elements in a statically sized array.
-*/
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
#ifdef HAS_CLIENT_CERT_PATH
#ifdef UNICODE
#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W
@@ -123,18 +100,6 @@
#endif
#endif
-#ifndef SP_PROT_SSL2_CLIENT
-#define SP_PROT_SSL2_CLIENT 0x00000008
-#endif
-
-#ifndef SP_PROT_SSL3_CLIENT
-#define SP_PROT_SSL3_CLIENT 0x00000008
-#endif
-
-#ifndef SP_PROT_TLS1_CLIENT
-#define SP_PROT_TLS1_CLIENT 0x00000080
-#endif
-
#ifndef SP_PROT_TLS1_0_CLIENT
#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT
#endif
@@ -175,12 +140,6 @@
# define CALG_SHA_256 0x0000800c
#endif
-/* Work around typo in classic MinGW's w32api up to version 5.0,
- see https://osdn.net/projects/mingw/ticket/38391 */
-#if !defined(ALG_CLASS_DHASH) && defined(ALG_CLASS_HASH)
-#define ALG_CLASS_DHASH ALG_CLASS_HASH
-#endif
-
#ifndef PKCS12_NO_PERSIST_KEY
#define PKCS12_NO_PERSIST_KEY 0x00008000
#endif
@@ -769,7 +728,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
}
#endif
- /* allocate memory for the re-usable credential handle */
+ /* allocate memory for the reusable credential handle */
backend->cred = (struct Curl_schannel_cred *)
calloc(1, sizeof(struct Curl_schannel_cred));
if(!backend->cred) {
@@ -1169,7 +1128,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
backend->cred = NULL;
- /* check for an existing re-usable credential handle */
+ /* check for an existing reusable credential handle */
if(ssl_config->primary.sessionid) {
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(cf, data, (void **)&old_cred, NULL)) {
@@ -2752,8 +2711,7 @@ static void schannel_checksum(const unsigned char *input,
if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
break; /* failed */
- /* workaround for original MinGW, should be (const BYTE*) */
- if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0))
+ if(!CryptHashData(hHash, input, (DWORD)inputlen, 0))
break; /* failed */
/* get hash size */
diff --git a/lib/vtls/schannel.h b/lib/vtls/schannel.h
index be23567..b26334b 100644
--- a/lib/vtls/schannel.h
+++ b/lib/vtls/schannel.h
@@ -68,7 +68,7 @@
* BoringSSL's <openssl/x509.h>: So just undefine those defines here
* (and only here).
*/
-#if defined(HAVE_BORINGSSL) || defined(OPENSSL_IS_BORINGSSL)
+#if defined(OPENSSL_IS_BORINGSSL)
# undef X509_NAME
# undef X509_CERT_PAIR
# undef X509_EXTENSIONS
diff --git a/lib/vtls/schannel_int.h b/lib/vtls/schannel_int.h
index edb20bc..a128e04 100644
--- a/lib/vtls/schannel_int.h
+++ b/lib/vtls/schannel_int.h
@@ -28,15 +28,9 @@
#ifdef USE_SCHANNEL
-#ifdef __MINGW32__
-#ifdef __MINGW64_VERSION_MAJOR
+#if defined(__MINGW32__) || defined(CERT_CHAIN_REVOCATION_CHECK_CHAIN)
#define HAS_MANUAL_VERIFY_API
#endif
-#else
-#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
-#define HAS_MANUAL_VERIFY_API
-#endif
-#endif
#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX) \
&& !defined(DISABLE_SCHANNEL_CLIENT_CERT)
@@ -60,41 +54,6 @@
#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/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
index e6a114a..3378f76 100644
--- a/lib/vtls/sectransp.c
+++ b/lib/vtls/sectransp.c
@@ -830,9 +830,9 @@ static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
#endif /* SECTRANSP_PINNEDPUBKEY_V1 */
#endif /* SECTRANSP_PINNEDPUBKEY */
-static OSStatus bio_cf_in_read(SSLConnectionRef connection,
- void *buf,
- size_t *dataLength) /* IN/OUT */
+static OSStatus sectransp_bio_cf_in_read(SSLConnectionRef connection,
+ void *buf,
+ size_t *dataLength) /* IN/OUT */
{
struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
struct ssl_connect_data *connssl = cf->ctx;
@@ -870,9 +870,9 @@ static OSStatus bio_cf_in_read(SSLConnectionRef connection,
return rtn;
}
-static OSStatus bio_cf_out_write(SSLConnectionRef connection,
- const void *buf,
- size_t *dataLength) /* IN/OUT */
+static OSStatus sectransp_bio_cf_out_write(SSLConnectionRef connection,
+ const void *buf,
+ size_t *dataLength) /* IN/OUT */
{
struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
struct ssl_connect_data *connssl = cf->ctx;
@@ -2100,7 +2100,9 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
}
}
- err = SSLSetIOFuncs(backend->ssl_ctx, bio_cf_in_read, bio_cf_out_write);
+ err = SSLSetIOFuncs(backend->ssl_ctx,
+ sectransp_bio_cf_in_read,
+ sectransp_bio_cf_out_write);
if(err != noErr) {
failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 38a20e8..494b660 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -1494,7 +1494,8 @@ static void ssl_cf_close(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data);
cf_close(cf, data);
- cf->next->cft->do_close(cf->next, data);
+ if(cf->next)
+ cf->next->cft->do_close(cf->next, data);
CF_DATA_RESTORE(cf, save);
}
diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
index 5f15720..b1384a6 100644
--- a/lib/vtls/wolfssl.c
+++ b/lib/vtls/wolfssl.c
@@ -229,7 +229,7 @@ static const struct group_name_map gnm[] = {
#ifdef USE_BIO_CHAIN
-static int bio_cf_create(WOLFSSL_BIO *bio)
+static int wolfssl_bio_cf_create(WOLFSSL_BIO *bio)
{
wolfSSL_BIO_set_shutdown(bio, 1);
wolfSSL_BIO_set_init(bio, 1);
@@ -237,14 +237,14 @@ static int bio_cf_create(WOLFSSL_BIO *bio)
return 1;
}
-static int bio_cf_destroy(WOLFSSL_BIO *bio)
+static int wolfssl_bio_cf_destroy(WOLFSSL_BIO *bio)
{
if(!bio)
return 0;
return 1;
}
-static long bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
+static long wolfssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
{
struct Curl_cfilter *cf = BIO_get_data(bio);
long ret = 1;
@@ -278,7 +278,8 @@ static long bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
return ret;
}
-static int bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen)
+static int wolfssl_bio_cf_out_write(WOLFSSL_BIO *bio,
+ const char *buf, int blen)
{
struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
struct ssl_connect_data *connssl = cf->ctx;
@@ -299,7 +300,7 @@ static int bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen)
return (int)nwritten;
}
-static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
+static int wolfssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
{
struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
struct ssl_connect_data *connssl = cf->ctx;
@@ -323,27 +324,27 @@ static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
return (int)nread;
}
-static WOLFSSL_BIO_METHOD *bio_cf_method = NULL;
+static WOLFSSL_BIO_METHOD *wolfssl_bio_cf_method = NULL;
-static void bio_cf_init_methods(void)
+static void wolfssl_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);
+ wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO");
+ wolfSSL_BIO_meth_set_write(wolfssl_bio_cf_method, &wolfssl_bio_cf_out_write);
+ wolfSSL_BIO_meth_set_read(wolfssl_bio_cf_method, &wolfssl_bio_cf_in_read);
+ wolfSSL_BIO_meth_set_ctrl(wolfssl_bio_cf_method, &wolfssl_bio_cf_ctrl);
+ wolfSSL_BIO_meth_set_create(wolfssl_bio_cf_method, &wolfssl_bio_cf_create);
+ wolfSSL_BIO_meth_set_destroy(wolfssl_bio_cf_method, &wolfssl_bio_cf_destroy);
}
-static void bio_cf_free_methods(void)
+static void wolfssl_bio_cf_free_methods(void)
{
- wolfSSL_BIO_meth_free(bio_cf_method);
+ wolfSSL_BIO_meth_free(wolfssl_bio_cf_method);
}
#else /* USE_BIO_CHAIN */
-#define bio_cf_init_methods() Curl_nop_stmt
-#define bio_cf_free_methods() Curl_nop_stmt
+#define wolfssl_bio_cf_init_methods() Curl_nop_stmt
+#define wolfssl_bio_cf_free_methods() Curl_nop_stmt
#endif /* !USE_BIO_CHAIN */
@@ -361,6 +362,10 @@ 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);
+ const char * const ssl_cafile =
+ /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
+ (ca_info_blob ? NULL : conn_config->CAfile);
+ const char * const ssl_capath = conn_config->CApath;
WOLFSSL_METHOD* req_method = NULL;
#ifdef HAVE_LIBOQS
word16 oqsAlg = 0;
@@ -541,20 +546,21 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}
#ifndef NO_FILESYSTEM
- /* load trusted cacert */
- if(conn_config->CAfile) {
- if(1 != wolfSSL_CTX_load_verify_locations(backend->ctx,
- conn_config->CAfile,
- conn_config->CApath)) {
+ /* load trusted cacert from file if not blob */
+ if(ssl_cafile || ssl_capath) {
+ int rc =
+ wolfSSL_CTX_load_verify_locations_ex(backend->ctx,
+ ssl_cafile,
+ ssl_capath,
+ WOLFSSL_LOAD_FLAG_IGNORE_ERR);
+ if(SSL_SUCCESS != rc) {
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",
- conn_config->CAfile?
- conn_config->CAfile: "none",
- conn_config->CApath?
- conn_config->CApath : "none");
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
return CURLE_SSL_CACERT_BADFILE;
}
else {
@@ -568,10 +574,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
/* Everything is fine. */
infof(data, "successfully set certificate verify locations:");
}
- infof(data, " CAfile: %s",
- conn_config->CAfile ? conn_config->CAfile : "none");
- infof(data, " CApath: %s",
- conn_config->CApath ? conn_config->CApath : "none");
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
}
/* Load the client certificate, and private key */
@@ -720,7 +724,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
{
WOLFSSL_BIO *bio;
- bio = BIO_new(bio_cf_method);
+ bio = BIO_new(wolfssl_bio_cf_method);
if(!bio)
return CURLE_OUT_OF_MEMORY;
@@ -1140,14 +1144,14 @@ static int wolfssl_init(void)
Curl_tls_keylog_open();
#endif
ret = (wolfSSL_Init() == SSL_SUCCESS);
- bio_cf_init_methods();
+ wolfssl_bio_cf_init_methods();
return ret;
}
static void wolfssl_cleanup(void)
{
- bio_cf_free_methods();
+ wolfssl_bio_cf_free_methods();
wolfSSL_Cleanup();
#ifdef OPENSSL_EXTRA
Curl_tls_keylog_close();
@@ -1378,6 +1382,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
#ifdef USE_BIO_CHAIN
SSLSUPP_HTTPS_PROXY |
#endif
+ SSLSUPP_CA_PATH |
SSLSUPP_CAINFO_BLOB |
SSLSUPP_SSL_CTX,
diff --git a/lib/warnless.c b/lib/warnless.c
index 65c5ec5..7e077f8 100644
--- a/lib/warnless.c
+++ b/lib/warnless.c
@@ -384,54 +384,3 @@ ssize_t curlx_write(int fd, const void *buf, size_t count)
#endif /* WIN32 */
-#if defined(__INTEL_COMPILER) && defined(__unix__)
-
-int curlx_FD_ISSET(int fd, fd_set *fdset)
-{
- #pragma warning(push)
- #pragma warning(disable:1469) /* clobber ignored */
- return FD_ISSET(fd, fdset);
- #pragma warning(pop)
-}
-
-void curlx_FD_SET(int fd, fd_set *fdset)
-{
- #pragma warning(push)
- #pragma warning(disable:1469) /* clobber ignored */
- FD_SET(fd, fdset);
- #pragma warning(pop)
-}
-
-void curlx_FD_ZERO(fd_set *fdset)
-{
- #pragma warning(push)
- #pragma warning(disable:593) /* variable was set but never used */
- FD_ZERO(fdset);
- #pragma warning(pop)
-}
-
-unsigned short curlx_htons(unsigned short usnum)
-{
-#if (__INTEL_COMPILER == 910) && defined(__i386__)
- return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF));
-#else
- #pragma warning(push)
- #pragma warning(disable:810) /* conversion may lose significant bits */
- return htons(usnum);
- #pragma warning(pop)
-#endif
-}
-
-unsigned short curlx_ntohs(unsigned short usnum)
-{
-#if (__INTEL_COMPILER == 910) && defined(__i386__)
- return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF));
-#else
- #pragma warning(push)
- #pragma warning(disable:810) /* conversion may lose significant bits */
- return ntohs(usnum);
- #pragma warning(pop)
-#endif
-}
-
-#endif /* __INTEL_COMPILER && __unix__ */