aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/curl/lib
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2022-12-02 16:18:16 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2022-12-02 16:18:16 +0300
commit22a73deb46c33ab8539b522286f0fb9b3364f856 (patch)
treeaf3cf69e9e6ebc887a5add5491b2fcebbfdff06a /contrib/libs/curl/lib
parent2e7d246d83a0077f08e6fed36594fc2087949502 (diff)
downloadydb-22a73deb46c33ab8539b522286f0fb9b3364f856.tar.gz
Update contrib/libs/curl to 7.86.0
Diffstat (limited to 'contrib/libs/curl/lib')
-rw-r--r--contrib/libs/curl/lib/altsvc.c33
-rw-r--r--contrib/libs/curl/lib/amigaos.c2
-rw-r--r--contrib/libs/curl/lib/asyn-ares.c10
-rw-r--r--contrib/libs/curl/lib/asyn-thread.c2
-rw-r--r--contrib/libs/curl/lib/asyn.h2
-rw-r--r--contrib/libs/curl/lib/base64.c4
-rw-r--r--contrib/libs/curl/lib/c-hyper.c24
-rw-r--r--contrib/libs/curl/lib/conncache.c2
-rw-r--r--contrib/libs/curl/lib/conncache.h1
-rw-r--r--contrib/libs/curl/lib/connect.c35
-rw-r--r--contrib/libs/curl/lib/content_encoding.c70
-rw-r--r--contrib/libs/curl/lib/content_encoding.h3
-rw-r--r--contrib/libs/curl/lib/cookie.c14
-rw-r--r--contrib/libs/curl/lib/curl_addrinfo.c2
-rw-r--r--contrib/libs/curl/lib/curl_config-linux.h63
-rw-r--r--contrib/libs/curl/lib/curl_ctype.c132
-rw-r--r--contrib/libs/curl/lib/curl_ctype.h40
-rw-r--r--contrib/libs/curl/lib/curl_des.c2
-rw-r--r--contrib/libs/curl/lib/curl_get_line.c6
-rw-r--r--contrib/libs/curl/lib/curl_hmac.h2
-rw-r--r--contrib/libs/curl/lib/curl_ntlm_core.c2
-rw-r--r--contrib/libs/curl/lib/curl_ntlm_wb.c2
-rw-r--r--contrib/libs/curl/lib/curl_path.c3
-rw-r--r--contrib/libs/curl/lib/curl_range.c2
-rw-r--r--contrib/libs/curl/lib/curl_setup.h16
-rw-r--r--contrib/libs/curl/lib/curl_setup_once.h27
-rw-r--r--contrib/libs/curl/lib/curl_sha256.h1
-rw-r--r--contrib/libs/curl/lib/doh.c4
-rw-r--r--contrib/libs/curl/lib/dotdot.c184
-rw-r--r--contrib/libs/curl/lib/dynbuf.c17
-rw-r--r--contrib/libs/curl/lib/dynbuf.h6
-rw-r--r--contrib/libs/curl/lib/easy.c36
-rw-r--r--contrib/libs/curl/lib/easy_lock.h2
-rw-r--r--contrib/libs/curl/lib/easyif.h3
-rw-r--r--contrib/libs/curl/lib/easyoptions.c3
-rw-r--r--contrib/libs/curl/lib/formdata.c6
-rw-r--r--contrib/libs/curl/lib/ftp.c16
-rw-r--r--contrib/libs/curl/lib/ftplistparser.c4
-rw-r--r--contrib/libs/curl/lib/functypes.h115
-rw-r--r--contrib/libs/curl/lib/h2h3.c2
-rw-r--r--contrib/libs/curl/lib/headers.c6
-rw-r--r--contrib/libs/curl/lib/hostip.c35
-rw-r--r--contrib/libs/curl/lib/hostip6.c6
-rw-r--r--contrib/libs/curl/lib/hsts.c6
-rw-r--r--contrib/libs/curl/lib/http.c169
-rw-r--r--contrib/libs/curl/lib/http.h20
-rw-r--r--contrib/libs/curl/lib/http2.c2
-rw-r--r--contrib/libs/curl/lib/http_aws_sigv4.c538
-rw-r--r--contrib/libs/curl/lib/http_chunks.c2
-rw-r--r--contrib/libs/curl/lib/http_digest.c4
-rw-r--r--contrib/libs/curl/lib/http_negotiate.c2
-rw-r--r--contrib/libs/curl/lib/http_ntlm.c2
-rw-r--r--contrib/libs/curl/lib/http_proxy.c6
-rw-r--r--contrib/libs/curl/lib/idn_win32.c8
-rw-r--r--contrib/libs/curl/lib/imap.c4
-rw-r--r--contrib/libs/curl/lib/memdebug.h3
-rw-r--r--contrib/libs/curl/lib/mime.c9
-rw-r--r--contrib/libs/curl/lib/mime.h5
-rw-r--r--contrib/libs/curl/lib/mprintf.c11
-rw-r--r--contrib/libs/curl/lib/mqtt.c26
-rw-r--r--contrib/libs/curl/lib/multi.c8
-rw-r--r--contrib/libs/curl/lib/multihandle.h10
-rw-r--r--contrib/libs/curl/lib/netrc.c34
-rw-r--r--contrib/libs/curl/lib/netrc.h8
-rw-r--r--contrib/libs/curl/lib/noproxy.c222
-rw-r--r--contrib/libs/curl/lib/noproxy.h (renamed from contrib/libs/curl/lib/dotdot.h)25
-rw-r--r--contrib/libs/curl/lib/openldap.c4
-rw-r--r--contrib/libs/curl/lib/pingpong.c2
-rw-r--r--contrib/libs/curl/lib/rand.c4
-rw-r--r--contrib/libs/curl/lib/rand.h2
-rw-r--r--contrib/libs/curl/lib/rtsp.c2
-rw-r--r--contrib/libs/curl/lib/select.h3
-rw-r--r--contrib/libs/curl/lib/sendf.c19
-rw-r--r--contrib/libs/curl/lib/setopt.c177
-rw-r--r--contrib/libs/curl/lib/setup-win32.h15
-rw-r--r--contrib/libs/curl/lib/smb.c2
-rw-r--r--contrib/libs/curl/lib/socketpair.h2
-rw-r--r--contrib/libs/curl/lib/strcase.c28
-rw-r--r--contrib/libs/curl/lib/strcase.h2
-rw-r--r--contrib/libs/curl/lib/strerror.c4
-rw-r--r--contrib/libs/curl/lib/strtoofft.c6
-rw-r--r--contrib/libs/curl/lib/timediff.c2
-rw-r--r--contrib/libs/curl/lib/transfer.c10
-rw-r--r--contrib/libs/curl/lib/url.c319
-rw-r--r--contrib/libs/curl/lib/url.h3
-rw-r--r--contrib/libs/curl/lib/urlapi-int.h6
-rw-r--r--contrib/libs/curl/lib/urlapi.c909
-rw-r--r--contrib/libs/curl/lib/urldata.h71
-rw-r--r--contrib/libs/curl/lib/vauth/digest.c8
-rw-r--r--contrib/libs/curl/lib/vauth/digest_sspi.c12
-rw-r--r--contrib/libs/curl/lib/vauth/gsasl.c3
-rw-r--r--contrib/libs/curl/lib/vauth/ntlm.c6
-rw-r--r--contrib/libs/curl/lib/vauth/ntlm.h3
-rw-r--r--contrib/libs/curl/lib/vauth/vauth.c17
-rw-r--r--contrib/libs/curl/lib/vauth/vauth.h8
-rw-r--r--contrib/libs/curl/lib/version.c13
-rw-r--r--contrib/libs/curl/lib/vquic/msh3.c10
-rw-r--r--contrib/libs/curl/lib/vquic/ngtcp2.c16
-rw-r--r--contrib/libs/curl/lib/vquic/quiche.c4
-rw-r--r--contrib/libs/curl/lib/vssh/libssh.c5
-rw-r--r--contrib/libs/curl/lib/vssh/libssh2.c2
-rw-r--r--contrib/libs/curl/lib/vssh/ssh.h4
-rw-r--r--contrib/libs/curl/lib/vtls/bearssl.c32
-rw-r--r--contrib/libs/curl/lib/vtls/keylog.c1
-rw-r--r--contrib/libs/curl/lib/vtls/openssl.c762
-rw-r--r--contrib/libs/curl/lib/vtls/openssl.h3
-rw-r--r--contrib/libs/curl/lib/vtls/rustls.c6
-rw-r--r--contrib/libs/curl/lib/vtls/schannel.h12
-rw-r--r--contrib/libs/curl/lib/vtls/sectransp.c6
-rw-r--r--contrib/libs/curl/lib/vtls/vtls.c4
-rw-r--r--contrib/libs/curl/lib/vtls/wolfssl.c22
-rw-r--r--contrib/libs/curl/lib/vtls/x509asn1.c3
-rw-r--r--contrib/libs/curl/lib/warnless.c2
-rw-r--r--contrib/libs/curl/lib/wildcard.h1
-rw-r--r--contrib/libs/curl/lib/ws.c757
-rw-r--r--contrib/libs/curl/lib/ws.h69
116 files changed, 3360 insertions, 2094 deletions
diff --git a/contrib/libs/curl/lib/altsvc.c b/contrib/libs/curl/lib/altsvc.c
index 2c0b3bdc43..7bca840151 100644
--- a/contrib/libs/curl/lib/altsvc.c
+++ b/contrib/libs/curl/lib/altsvc.c
@@ -52,15 +52,7 @@
#define MAX_ALTSVC_ALPNLENSTR "10"
#define MAX_ALTSVC_ALPNLEN 10
-#if defined(USE_QUICHE) && !defined(UNITTESTS)
-#define H3VERSION "h3-29"
-#elif defined(USE_NGTCP2) && !defined(UNITTESTS)
-#define H3VERSION "h3-29"
-#elif defined(USE_MSH3) && !defined(UNITTESTS)
-#define H3VERSION "h3-29"
-#else
#define H3VERSION "h3"
-#endif
static enum alpnid alpn2alpnid(char *name)
{
@@ -470,6 +462,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
struct altsvc *as;
unsigned short dstport = srcport; /* the same by default */
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+ size_t entries = 0;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
@@ -480,11 +473,10 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
DEBUGASSERT(asi);
- /* Flush all cached alternatives for this source origin, if any */
- altsvc_flush(asi, srcalpnid, srchost, srcport);
-
/* "clear" is a magic keyword */
if(strcasecompare(alpnbuf, "clear")) {
+ /* Flush cached alternatives for this source origin */
+ altsvc_flush(asi, srcalpnid, srchost, srcport);
return CURLE_OK;
}
@@ -502,6 +494,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
bool quoted = FALSE;
time_t maxage = 24 * 3600; /* default is 24 hours */
bool persist = FALSE;
+ bool valid = TRUE;
p++;
if(*p != ':') {
/* host name starts here */
@@ -511,7 +504,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
len = p - hostp;
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
infof(data, "Excessive alt-svc host name, ignoring.");
- dstalpnid = ALPN_none;
+ valid = FALSE;
}
else {
memcpy(namebuf, hostp, len);
@@ -528,10 +521,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
unsigned long port = strtoul(++p, &end_ptr, 10);
if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
infof(data, "Unknown alt-svc port number, ignoring.");
- dstalpnid = ALPN_none;
+ valid = FALSE;
}
+ else
+ dstport = curlx_ultous(port);
p = end_ptr;
- dstport = curlx_ultous(port);
}
if(*p++ != '\"')
break;
@@ -583,7 +577,12 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
persist = TRUE;
}
}
- if(dstalpnid) {
+ if(dstalpnid && valid) {
+ if(!entries++)
+ /* Flush cached alternatives for this source origin, if any - when
+ this is the first entry of the line. */
+ altsvc_flush(asi, srcalpnid, srchost, srcport);
+
as = altsvc_createid(srchost, dsthost,
srcalpnid, dstalpnid,
srcport, dstport);
@@ -597,10 +596,6 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
Curl_alpnid2str(dstalpnid));
}
}
- else {
- infof(data, "Unknown alt-svc protocol \"%s\", skipping.",
- alpnbuf);
- }
}
else
break;
diff --git a/contrib/libs/curl/lib/amigaos.c b/contrib/libs/curl/lib/amigaos.c
index c235a77f43..42b0c39b37 100644
--- a/contrib/libs/curl/lib/amigaos.c
+++ b/contrib/libs/curl/lib/amigaos.c
@@ -26,6 +26,8 @@
#ifdef __AMIGA__
+#include <curl/curl.h>
+
#include "hostip.h"
#include "amigaos.h"
diff --git a/contrib/libs/curl/lib/asyn-ares.c b/contrib/libs/curl/lib/asyn-ares.c
index fb933b5edf..33edba1395 100644
--- a/contrib/libs/curl/lib/asyn-ares.c
+++ b/contrib/libs/curl/lib/asyn-ares.c
@@ -746,7 +746,7 @@ static void addrinfo_cb(void *arg, int status, int timeouts,
* Curl_resolver_getaddrinfo() - when using ares
*
* Returns name information about the given hostname and port number. If
- * successful, the 'hostent' is returned and the forth argument will point to
+ * successful, the 'hostent' is returned and the fourth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
@@ -779,13 +779,17 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
int pf = PF_INET;
memset(&hints, 0, sizeof(hints));
#ifdef CURLRES_IPV6
- if(Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */
hints.ai_family = pf;
hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM;
+ /* Since the service is a numerical one, set the hint flags
+ * accordingly to save a call to getservbyname in inside C-Ares
+ */
+ hints.ai_flags = ARES_AI_NUMERICSERV;
msnprintf(service, sizeof(service), "%d", port);
res->num_pending = 1;
ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
@@ -794,7 +798,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
#else
#ifdef HAVE_CARES_IPV6
- if(Curl_ipv6works(data)) {
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
res->num_pending = 2;
diff --git a/contrib/libs/curl/lib/asyn-thread.c b/contrib/libs/curl/lib/asyn-thread.c
index 248d63576e..0e4ebdc8b5 100644
--- a/contrib/libs/curl/lib/asyn-thread.c
+++ b/contrib/libs/curl/lib/asyn-thread.c
@@ -811,7 +811,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
*waitp = 0; /* default to synchronous response */
#ifdef CURLRES_IPV6
- if(Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */
diff --git a/contrib/libs/curl/lib/asyn.h b/contrib/libs/curl/lib/asyn.h
index 80ca54d787..1aab21aaa7 100644
--- a/contrib/libs/curl/lib/asyn.h
+++ b/contrib/libs/curl/lib/asyn.h
@@ -148,7 +148,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
* Curl_resolver_getaddrinfo() - when using this resolver
*
* Returns name information about the given hostname and port number. If
- * successful, the 'hostent' is returned and the forth argument will point to
+ * successful, the 'hostent' is returned and the fourth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*
diff --git a/contrib/libs/curl/lib/base64.c b/contrib/libs/curl/lib/base64.c
index 53ebc3db30..52654c2bc3 100644
--- a/contrib/libs/curl/lib/base64.c
+++ b/contrib/libs/curl/lib/base64.c
@@ -47,7 +47,7 @@
static const char base64[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-/* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648
+/* The Base 64 encoding with a URL and filename safe alphabet, RFC 4648
section 5 */
static const char base64url[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
@@ -138,7 +138,7 @@ CURLcode Curl_base64_decode(const char *src,
/* Calculate the size of the decoded string */
rawlen = (numQuantums * 3) - padding;
- /* Allocate our buffer including room for a zero terminator */
+ /* Allocate our buffer including room for a null-terminator */
newstr = malloc(rawlen + 1);
if(!newstr)
return CURLE_OUT_OF_MEMORY;
diff --git a/contrib/libs/curl/lib/c-hyper.c b/contrib/libs/curl/lib/c-hyper.c
index 3c9c163163..ab6740ca4a 100644
--- a/contrib/libs/curl/lib/c-hyper.c
+++ b/contrib/libs/curl/lib/c-hyper.c
@@ -54,6 +54,7 @@
#include "multiif.h"
#include "progress.h"
#include "content_encoding.h"
+#include "ws.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -471,6 +472,24 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
if(result)
break;
+ k->deductheadercount =
+ (100 <= http_status && 199 >= http_status)?k->headerbytecount:0;
+#ifdef USE_WEBSOCKETS
+ if(k->upgr101 == UPGR101_WS) {
+ if(http_status == 101) {
+ /* verify the response */
+ result = Curl_ws_accept(data);
+ if(result)
+ return result;
+ }
+ else {
+ failf(data, "Expected 101, got %u", k->httpcode);
+ result = CURLE_HTTP_RETURNED_ERROR;
+ break;
+ }
+ }
+#endif
+
/* Curl_http_auth_act() checks what authentication methods that are
* available and decides which one (if any) to use. It will set 'newurl'
* if an auth method was picked. */
@@ -918,7 +937,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
result = CURLE_OUT_OF_MEMORY;
goto error;
}
- if(conn->negnpn == CURL_HTTP_VERSION_2) {
+ if(conn->alpn == CURL_HTTP_VERSION_2) {
hyper_clientconn_options_http2(options, 1);
h2 = TRUE;
}
@@ -1123,6 +1142,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(result)
goto error;
+ if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
+ result = Curl_ws_request(data, headers);
+
result = Curl_add_timecondition(data, headers);
if(result)
goto error;
diff --git a/contrib/libs/curl/lib/conncache.c b/contrib/libs/curl/lib/conncache.c
index 2a399c8814..a557ac6dc9 100644
--- a/contrib/libs/curl/lib/conncache.c
+++ b/contrib/libs/curl/lib/conncache.c
@@ -498,7 +498,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
conn = curr->ptr;
if(!CONN_INUSE(conn) && !conn->bits.close &&
- !conn->bits.connect_only) {
+ !conn->connect_only) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused);
diff --git a/contrib/libs/curl/lib/conncache.h b/contrib/libs/curl/lib/conncache.h
index 6ec2757433..94664bc357 100644
--- a/contrib/libs/curl/lib/conncache.h
+++ b/contrib/libs/curl/lib/conncache.h
@@ -31,6 +31,7 @@
* be shared.
*/
+#include <curl/curl.h>
#include "timeval.h"
struct connectdata;
diff --git a/contrib/libs/curl/lib/connect.c b/contrib/libs/curl/lib/connect.c
index be9f72117c..ac007c61b0 100644
--- a/contrib/libs/curl/lib/connect.c
+++ b/contrib/libs/curl/lib/connect.c
@@ -625,7 +625,8 @@ void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
else
data->info.conn_local_ip[0] = 0;
data->info.conn_scheme = conn->handler->scheme;
- data->info.conn_protocol = conn->handler->protocol;
+ /* conn_protocol can only provide "old" protocols */
+ data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK;
data->info.conn_primary_port = conn->port;
data->info.conn_remote_port = conn->remote_port;
data->info.conn_local_port = local_port;
@@ -761,18 +762,10 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
char local_ip[MAX_IPADR_LEN] = "";
int local_port = -1;
- if(conn->transport == TRNSPRT_TCP) {
- if(!conn->bits.reuse && !conn->bits.tcp_fastopen)
- Curl_conninfo_remote(data, conn, sockfd);
- Curl_conninfo_local(data, sockfd, local_ip, &local_port);
- } /* end of TCP-only section */
-#ifdef ENABLE_QUIC
- else if(conn->transport == TRNSPRT_QUIC) {
- if(!conn->bits.reuse)
- Curl_conninfo_remote(data, conn, sockfd);
- Curl_conninfo_local(data, sockfd, local_ip, &local_port);
- }
-#endif
+ if(!conn->bits.reuse &&
+ (conn->transport != TRNSPRT_TCP || !conn->bits.tcp_fastopen))
+ Curl_conninfo_remote(data, conn, sockfd);
+ Curl_conninfo_local(data, sockfd, local_ip, &local_port);
/* persist connection info in session handle */
Curl_persistconninfo(data, conn, local_ip, local_port);
@@ -1046,7 +1039,6 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
(conn->tempsock[1] == CURL_SOCKET_BAD)) {
/* no more addresses to try */
const char *hostname;
- char buffer[STRERROR_LEN];
CURLcode failreason = result;
/* if the first address family runs out of addresses to try before the
@@ -1073,11 +1065,7 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
"%" CURL_FORMAT_TIMEDIFF_T " ms: %s",
hostname, conn->port,
Curl_timediff(now, data->progress.t_startsingle),
-#ifdef ENABLE_QUIC
- (conn->transport == TRNSPRT_QUIC) ?
- curl_easy_strerror(result) :
-#endif
- Curl_strerror(error, buffer, sizeof(buffer)));
+ curl_easy_strerror(result));
Curl_quic_disconnect(data, conn, 0);
Curl_quic_disconnect(data, conn, 1);
@@ -1209,6 +1197,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
#ifdef TCP_FASTOPEN_CONNECT
int optval = 1;
#endif
+ const char *ipmsg;
char buffer[STRERROR_LEN];
curl_socket_t *sockp = &conn->tempsock[tempindex];
*sockp = CURL_SOCKET_BAD;
@@ -1226,7 +1215,13 @@ static CURLcode singleipconnect(struct Curl_easy *data,
Curl_closesocket(data, conn, sockfd);
return CURLE_OK;
}
- infof(data, " Trying %s:%d...", ipaddress, port);
+#ifdef ENABLE_IPV6
+ if(addr.family == AF_INET6)
+ ipmsg = " Trying [%s]:%d...";
+ else
+#endif
+ ipmsg = " Trying %s:%d...";
+ infof(data, ipmsg, ipaddress, port);
#ifdef ENABLE_IPV6
is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
diff --git a/contrib/libs/curl/lib/content_encoding.c b/contrib/libs/curl/lib/content_encoding.c
index e3c7ab9b1d..39bb9b5b13 100644
--- a/contrib/libs/curl/lib/content_encoding.c
+++ b/contrib/libs/curl/lib/content_encoding.c
@@ -28,7 +28,7 @@
#include <curl/curl.h>
#include <stddef.h>
-#ifdef HAVE_ZLIB_H
+#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
@@ -82,8 +82,9 @@ typedef enum {
ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
} zlibInitState;
-/* Writer parameters. */
-struct zlib_params {
+/* Deflate and gzip writer. */
+struct zlib_writer {
+ struct contenc_writer super;
zlibInitState zlib_init; /* zlib init state */
uInt trailerlen; /* Remaining trailer byte count. */
z_stream z; /* State structure for zlib. */
@@ -135,7 +136,7 @@ exit_zlib(struct Curl_easy *data,
}
static CURLcode process_trailer(struct Curl_easy *data,
- struct zlib_params *zp)
+ struct zlib_writer *zp)
{
z_stream *z = &zp->z;
CURLcode result = CURLE_OK;
@@ -162,7 +163,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
struct contenc_writer *writer,
zlibInitState started)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
uInt nread = z->avail_in;
Bytef *orig_in = z->next_in;
@@ -265,7 +266,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
static CURLcode deflate_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(!writer->downstream)
@@ -285,7 +286,7 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
/* Set the compressed input when this function is called */
@@ -302,7 +303,7 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data,
static void deflate_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
@@ -314,7 +315,7 @@ static const struct content_encoding deflate_encoding = {
deflate_init_writer,
deflate_unencode_write,
deflate_close_writer,
- sizeof(struct zlib_params)
+ sizeof(struct zlib_writer)
};
@@ -322,7 +323,7 @@ static const struct content_encoding deflate_encoding = {
static CURLcode gzip_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(!writer->downstream)
@@ -439,7 +440,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(zp->zlib_init == ZLIB_INIT_GZIP) {
@@ -566,7 +567,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
static void gzip_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
@@ -578,15 +579,16 @@ static const struct content_encoding gzip_encoding = {
gzip_init_writer,
gzip_unencode_write,
gzip_close_writer,
- sizeof(struct zlib_params)
+ sizeof(struct zlib_writer)
};
#endif /* HAVE_LIBZ */
#ifdef HAVE_BROTLI
-/* Writer parameters. */
-struct brotli_params {
+/* Brotli writer. */
+struct brotli_writer {
+ struct contenc_writer super;
BrotliDecoderState *br; /* State structure for brotli. */
};
@@ -631,7 +633,7 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
static CURLcode brotli_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct brotli_params *bp = (struct brotli_params *) &writer->params;
+ struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
if(!writer->downstream)
@@ -645,7 +647,7 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct brotli_params *bp = (struct brotli_params *) &writer->params;
+ struct brotli_writer *bp = (struct brotli_writer *) writer;
const uint8_t *src = (const uint8_t *) buf;
char *decomp;
uint8_t *dst;
@@ -692,7 +694,8 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
static void brotli_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct brotli_params *bp = (struct brotli_params *) &writer->params;
+ struct brotli_writer *bp = (struct brotli_writer *) writer;
+
(void) data;
if(bp->br) {
@@ -707,14 +710,15 @@ static const struct content_encoding brotli_encoding = {
brotli_init_writer,
brotli_unencode_write,
brotli_close_writer,
- sizeof(struct brotli_params)
+ sizeof(struct brotli_writer)
};
#endif
#ifdef HAVE_ZSTD
-/* Writer parameters. */
-struct zstd_params {
+/* Zstd writer. */
+struct zstd_writer {
+ struct contenc_writer super;
ZSTD_DStream *zds; /* State structure for zstd. */
void *decomp;
};
@@ -722,7 +726,8 @@ struct zstd_params {
static CURLcode zstd_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zstd_params *zp = (struct zstd_params *)&writer->params;
+ struct zstd_writer *zp = (struct zstd_writer *) writer;
+
(void)data;
if(!writer->downstream)
@@ -738,7 +743,7 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
- struct zstd_params *zp = (struct zstd_params *)&writer->params;
+ struct zstd_writer *zp = (struct zstd_writer *) writer;
ZSTD_inBuffer in;
ZSTD_outBuffer out;
size_t errorCode;
@@ -777,7 +782,8 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
static void zstd_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zstd_params *zp = (struct zstd_params *)&writer->params;
+ struct zstd_writer *zp = (struct zstd_writer *) writer;
+
(void)data;
if(zp->decomp) {
@@ -796,7 +802,7 @@ static const struct content_encoding zstd_encoding = {
zstd_init_writer,
zstd_unencode_write,
zstd_close_writer,
- sizeof(struct zstd_params)
+ sizeof(struct zstd_writer)
};
#endif
@@ -829,7 +835,7 @@ static const struct content_encoding identity_encoding = {
identity_init_writer,
identity_unencode_write,
identity_close_writer,
- 0
+ sizeof(struct contenc_writer)
};
@@ -921,7 +927,7 @@ static const struct content_encoding client_encoding = {
client_init_writer,
client_unencode_write,
client_close_writer,
- 0
+ sizeof(struct contenc_writer)
};
@@ -964,7 +970,7 @@ static const struct content_encoding error_encoding = {
error_init_writer,
error_unencode_write,
error_close_writer,
- 0
+ sizeof(struct contenc_writer)
};
/* Create an unencoding writer stage using the given handler. */
@@ -973,8 +979,10 @@ new_unencoding_writer(struct Curl_easy *data,
const struct content_encoding *handler,
struct contenc_writer *downstream)
{
- size_t sz = offsetof(struct contenc_writer, params) + handler->paramsize;
- struct contenc_writer *writer = (struct contenc_writer *)calloc(1, sz);
+ struct contenc_writer *writer;
+
+ DEBUGASSERT(handler->writersize >= sizeof(struct contenc_writer));
+ writer = (struct contenc_writer *) calloc(1, handler->writersize);
if(writer) {
writer->handler = handler;
@@ -1044,7 +1052,7 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
size_t namelen;
/* Parse a single encoding name. */
- while(ISSPACE(*enclist) || *enclist == ',')
+ while(ISBLANK(*enclist) || *enclist == ',')
enclist++;
name = enclist;
diff --git a/contrib/libs/curl/lib/content_encoding.h b/contrib/libs/curl/lib/content_encoding.h
index 81bddd1be1..3c278cf727 100644
--- a/contrib/libs/curl/lib/content_encoding.h
+++ b/contrib/libs/curl/lib/content_encoding.h
@@ -28,7 +28,6 @@
struct contenc_writer {
const struct content_encoding *handler; /* Encoding handler. */
struct contenc_writer *downstream; /* Downstream writer. */
- void *params; /* Encoding-specific storage (variable length). */
};
/* Content encoding writer. */
@@ -42,7 +41,7 @@ struct content_encoding {
const char *buf, size_t nbytes);
void (*close_writer)(struct Curl_easy *data,
struct contenc_writer *writer);
- size_t paramsize;
+ size_t writersize;
};
diff --git a/contrib/libs/curl/lib/cookie.c b/contrib/libs/curl/lib/cookie.c
index ab790a1cdb..8eaedeeb7f 100644
--- a/contrib/libs/curl/lib/cookie.c
+++ b/contrib/libs/curl/lib/cookie.c
@@ -458,11 +458,10 @@ static int invalid_octets(const char *p)
"\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
"\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f"
};
- size_t vlen, len;
+ size_t len;
/* scan for all the octets that are *not* in cookie-octet */
len = strcspn(p, badoctets);
- vlen = strlen(p);
- return (len != vlen);
+ return (p[len] != '\0');
}
/*
@@ -538,7 +537,7 @@ Curl_cookie_add(struct Curl_easy *data,
do {
/* we have a <what>=<this> pair or a stand-alone word here */
name[0] = what[0] = 0; /* init the buffers */
- if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%"
+ if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\t\r\n=] =%"
MAX_NAME_TXT "[^;\r\n]",
name, what)) {
/*
@@ -592,6 +591,13 @@ Curl_cookie_add(struct Curl_easy *data,
while(*whatptr && ISBLANK(*whatptr))
whatptr++;
+ /* Reject cookies with a TAB inside the content */
+ if(strchr(whatptr, '\t')) {
+ freecookie(co);
+ infof(data, "cookie contains TAB, dropping");
+ return NULL;
+ }
+
/*
* Check if we have a reserved prefix set before anything else, as we
* otherwise have to test for the prefix in both the cookie name and
diff --git a/contrib/libs/curl/lib/curl_addrinfo.c b/contrib/libs/curl/lib/curl_addrinfo.c
index 34c594a162..a844101b92 100644
--- a/contrib/libs/curl/lib/curl_addrinfo.c
+++ b/contrib/libs/curl/lib/curl_addrinfo.c
@@ -279,7 +279,7 @@ Curl_he2ai(const struct hostent *he, int port)
for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
size_t ss_size;
- size_t namelen = strlen(he->h_name) + 1; /* include zero termination */
+ size_t namelen = strlen(he->h_name) + 1; /* include null-terminatior */
#ifdef ENABLE_IPV6
if(he->h_addrtype == AF_INET6)
ss_size = sizeof(struct sockaddr_in6);
diff --git a/contrib/libs/curl/lib/curl_config-linux.h b/contrib/libs/curl/lib/curl_config-linux.h
index 8d065ebdd4..765dd67d61 100644
--- a/contrib/libs/curl/lib/curl_config-linux.h
+++ b/contrib/libs/curl/lib/curl_config-linux.h
@@ -390,12 +390,6 @@
/* Define to 1 if you have the `ssh2' library (-lssh2). */
/* #undef HAVE_LIBSSH2 */
-/* Define to 1 if you have the <libssh2.h> header file. */
-/* #undef HAVE_LIBSSH2_H */
-
-/* Define to 1 if you have the <libssh/libssh.h> header file. */
-/* #undef HAVE_LIBSSH_LIBSSH_H */
-
/* Define to 1 if you have the `ssl' library (-lssl). */
#define HAVE_LIBSSL 1
@@ -569,6 +563,9 @@
/* Define to 1 if you have the sigsetjmp function or macro. */
#define HAVE_SIGSETJMP 1
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
@@ -746,9 +743,6 @@
/* Define to 1 if you have the <x509.h> header file. */
/* #undef HAVE_X509_H */
-/* if you have the zlib.h header file */
-#define HAVE_ZLIB_H 1
-
/* if libzstd is in use */
/* #undef HAVE_ZSTD */
@@ -800,54 +794,6 @@
/* a suitable file to read random data from */
#define RANDOM_FILE "/dev/urandom"
-/* Define to the type of arg 1 for recv. */
-#define RECV_TYPE_ARG1 int
-
-/* Define to the type of arg 2 for recv. */
-#define RECV_TYPE_ARG2 void *
-
-/* Define to the type of arg 3 for recv. */
-#define RECV_TYPE_ARG3 size_t
-
-/* Define to the type of arg 4 for recv. */
-#define RECV_TYPE_ARG4 int
-
-/* Define to the function return type for recv. */
-#define RECV_TYPE_RETV ssize_t
-
-/* Define to the type qualifier of arg 5 for select. */
-#define SELECT_QUAL_ARG5
-
-/* Define to the type of arg 1 for select. */
-#define SELECT_TYPE_ARG1 int
-
-/* Define to the type of args 2, 3 and 4 for select. */
-#define SELECT_TYPE_ARG234 fd_set *
-
-/* Define to the type of arg 5 for select. */
-#define SELECT_TYPE_ARG5 struct timeval *
-
-/* Define to the function return type for select. */
-#define SELECT_TYPE_RETV int
-
-/* Define to the type qualifier of arg 2 for send. */
-#define SEND_QUAL_ARG2 const
-
-/* Define to the type of arg 1 for send. */
-#define SEND_TYPE_ARG1 int
-
-/* Define to the type of arg 2 for send. */
-#define SEND_TYPE_ARG2 void *
-
-/* Define to the type of arg 3 for send. */
-#define SEND_TYPE_ARG3 size_t
-
-/* Define to the type of arg 4 for send. */
-#define SEND_TYPE_ARG4 int
-
-/* Define to the function return type for send. */
-#define SEND_TYPE_RETV ssize_t
-
/* Size of curl_off_t in number of bytes */
#define SIZEOF_CURL_OFF_T 8
@@ -971,6 +917,9 @@
/* Use Unix domain sockets */
#define USE_UNIX_SOCKETS 1
+/* enable websockets support */
+/* #undef USE_WEBSOCKETS */
+
/* Define to 1 if you are building a Windows target with crypto API support.
*/
/* #undef USE_WIN32_CRYPTO */
diff --git a/contrib/libs/curl/lib/curl_ctype.c b/contrib/libs/curl/lib/curl_ctype.c
deleted file mode 100644
index e1a8445151..0000000000
--- a/contrib/libs/curl/lib/curl_ctype.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-#include "curl_setup.h"
-
-#undef _U
-#define _U (1<<0) /* upper case */
-#undef _L
-#define _L (1<<1) /* lower case */
-#undef _N
-#define _N (1<<2) /* decimal numerical digit */
-#undef _S
-#define _S (1<<3) /* space */
-#undef _P
-#define _P (1<<4) /* punctuation */
-#undef _C
-#define _C (1<<5) /* control */
-#undef _X
-#define _X (1<<6) /* hexadecimal letter */
-#undef _B
-#define _B (1<<7) /* blank */
-
-static const unsigned char ascii[128] = {
- _C, _C, _C, _C, _C, _C, _C, _C,
- _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C,
- _C, _C, _C, _C, _C, _C, _C, _C,
- _C, _C, _C, _C, _C, _C, _C, _C,
- _S|_B, _P, _P, _P, _P, _P, _P, _P,
- _P, _P, _P, _P, _P, _P, _P, _P,
- _N, _N, _N, _N, _N, _N, _N, _N,
- _N, _N, _P, _P, _P, _P, _P, _P,
- _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
- _U, _U, _U, _U, _U, _U, _U, _U,
- _U, _U, _U, _U, _U, _U, _U, _U,
- _U, _U, _U, _P, _P, _P, _P, _P,
- _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
- _L, _L, _L, _L, _L, _L, _L, _L,
- _L, _L, _L, _L, _L, _L, _L, _L,
- _L, _L, _L, _P, _P, _P, _P, _C
-};
-
-int Curl_isspace(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & _S);
-}
-
-int Curl_isdigit(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & _N);
-}
-
-int Curl_isalnum(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_N|_U|_L));
-}
-
-int Curl_isxdigit(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_N|_X));
-}
-
-int Curl_isgraph(int c)
-{
- if((c < 0) || (c >= 0x80) || (c == ' '))
- return FALSE;
- return (ascii[c] & (_N|_X|_U|_L|_P|_S));
-}
-
-int Curl_isprint(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_N|_X|_U|_L|_P|_S));
-}
-
-int Curl_isalpha(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_U|_L));
-}
-
-int Curl_isupper(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_U));
-}
-
-int Curl_islower(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_L));
-}
-
-int Curl_iscntrl(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_C));
-}
-
diff --git a/contrib/libs/curl/lib/curl_ctype.h b/contrib/libs/curl/lib/curl_ctype.h
index c70945a8d2..dc6b8cab86 100644
--- a/contrib/libs/curl/lib/curl_ctype.h
+++ b/contrib/libs/curl/lib/curl_ctype.h
@@ -24,32 +24,24 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#define ISLOWHEXALHA(x) (((x) >= 'a') && ((x) <= 'f'))
+#define ISUPHEXALHA(x) (((x) >= 'A') && ((x) <= 'F'))
-int Curl_isspace(int c);
-int Curl_isdigit(int c);
-int Curl_isalnum(int c);
-int Curl_isxdigit(int c);
-int Curl_isgraph(int c);
-int Curl_isprint(int c);
-int Curl_isalpha(int c);
-int Curl_isupper(int c);
-int Curl_islower(int c);
-int Curl_iscntrl(int c);
+#define ISLOWCNTRL(x) ((x) >= 0 && ((x) <= 0x1f))
+#define IS7F(x) ((x) == 0x7f)
-#define ISSPACE(x) (Curl_isspace((int) ((unsigned char)x)))
-#define ISDIGIT(x) (Curl_isdigit((int) ((unsigned char)x)))
-#define ISALNUM(x) (Curl_isalnum((int) ((unsigned char)x)))
-#define ISXDIGIT(x) (Curl_isxdigit((int) ((unsigned char)x)))
-#define ISGRAPH(x) (Curl_isgraph((int) ((unsigned char)x)))
-#define ISALPHA(x) (Curl_isalpha((int) ((unsigned char)x)))
-#define ISPRINT(x) (Curl_isprint((int) ((unsigned char)x)))
-#define ISUPPER(x) (Curl_isupper((int) ((unsigned char)x)))
-#define ISLOWER(x) (Curl_islower((int) ((unsigned char)x)))
-#define ISCNTRL(x) (Curl_iscntrl((int) ((unsigned char)x)))
-#define ISASCII(x) (((x) >= 0) && ((x) <= 0x80))
+#define ISLOWPRINT(x) (((x) >= 9) && ((x) <= 0x0d))
-#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
- (((unsigned char)x) == '\t'))
+#define ISPRINT(x) (ISLOWPRINT(x) || (((x) >= ' ') && ((x) <= 0x7e)))
+#define ISGRAPH(x) (ISLOWPRINT(x) || (((x) > ' ') && ((x) <= 0x7e)))
+#define ISCNTRL(x) (ISLOWCNTRL(x) || IS7F(x))
+#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
+#define ISXDIGIT(x) (ISDIGIT(x) || ISLOWHEXALHA(x) || ISUPHEXALHA(x))
+#define ISALNUM(x) (ISDIGIT(x) || ISLOWER(x) || ISUPPER(x))
+#define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
+#define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
+#define ISDIGIT(x) (((x) >= '0') && ((x) <= '9'))
+#define ISBLANK(x) (((x) == ' ') || ((x) == '\t'))
+#define ISSPACE(x) (ISBLANK(x) || (((x) >= 0xa) && ((x) <= 0x0d)))
#endif /* HEADER_CURL_CTYPE_H */
diff --git a/contrib/libs/curl/lib/curl_des.c b/contrib/libs/curl/lib/curl_des.c
index 6d52cd3635..a2bf648c29 100644
--- a/contrib/libs/curl/lib/curl_des.c
+++ b/contrib/libs/curl/lib/curl_des.c
@@ -41,7 +41,7 @@
*
* The function is a port of the Java based oddParity() function over at:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
*
* Parameters:
*
diff --git a/contrib/libs/curl/lib/curl_get_line.c b/contrib/libs/curl/lib/curl_get_line.c
index 6a26bb254f..22e3705f4c 100644
--- a/contrib/libs/curl/lib/curl_get_line.c
+++ b/contrib/libs/curl/lib/curl_get_line.c
@@ -25,7 +25,7 @@
#include "curl_setup.h"
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
- !defined(CURL_DISABLE_HSTS)
+ !defined(CURL_DISABLE_HSTS) || !defined(CURL_DISABLE_NETRC)
#include "curl_get_line.h"
#include "curl_memory.h"
@@ -33,8 +33,8 @@
#include "memdebug.h"
/*
- * get_line() makes sure to only return complete whole lines that fit in 'len'
- * bytes and end with a newline.
+ * Curl_get_line() makes sure to only return complete whole lines that fit in
+ * 'len' bytes and end with a newline.
*/
char *Curl_get_line(char *buf, int len, FILE *input)
{
diff --git a/contrib/libs/curl/lib/curl_hmac.h b/contrib/libs/curl/lib/curl_hmac.h
index 77dce0f165..36c0bd62e5 100644
--- a/contrib/libs/curl/lib/curl_hmac.h
+++ b/contrib/libs/curl/lib/curl_hmac.h
@@ -26,6 +26,8 @@
#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include <curl/curl.h>
+
#define HMAC_MD5_LENGTH 16
typedef CURLcode (* HMAC_hinit_func)(void *context);
diff --git a/contrib/libs/curl/lib/curl_ntlm_core.c b/contrib/libs/curl/lib/curl_ntlm_core.c
index a977c2e0af..14c9f34d21 100644
--- a/contrib/libs/curl/lib/curl_ntlm_core.c
+++ b/contrib/libs/curl/lib/curl_ntlm_core.c
@@ -29,7 +29,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
diff --git a/contrib/libs/curl/lib/curl_ntlm_wb.c b/contrib/libs/curl/lib/curl_ntlm_wb.c
index f1eb9c6319..33dcf0ce25 100644
--- a/contrib/libs/curl/lib/curl_ntlm_wb.c
+++ b/contrib/libs/curl/lib/curl_ntlm_wb.c
@@ -30,7 +30,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
diff --git a/contrib/libs/curl/lib/curl_path.c b/contrib/libs/curl/lib/curl_path.c
index 92e3464956..67065809ba 100644
--- a/contrib/libs/curl/lib/curl_path.c
+++ b/contrib/libs/curl/lib/curl_path.c
@@ -122,7 +122,8 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
bool relativePath = false;
static const char WHITESPACE[] = " \t\r\n";
- if(!*cp) {
+ DEBUGASSERT(homedir);
+ if(!*cp || !homedir) {
*cpp = NULL;
*path = NULL;
return CURLE_QUOTE_ERROR;
diff --git a/contrib/libs/curl/lib/curl_range.c b/contrib/libs/curl/lib/curl_range.c
index 9e03c3d4a6..dd92d05b39 100644
--- a/contrib/libs/curl/lib/curl_range.c
+++ b/contrib/libs/curl/lib/curl_range.c
@@ -47,7 +47,7 @@ CURLcode Curl_range(struct Curl_easy *data)
from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
if(to_t == CURL_OFFT_FLOW)
diff --git a/contrib/libs/curl/lib/curl_setup.h b/contrib/libs/curl/lib/curl_setup.h
index 16a648ef32..5ad6f3b02e 100644
--- a/contrib/libs/curl/lib/curl_setup.h
+++ b/contrib/libs/curl/lib/curl_setup.h
@@ -158,8 +158,6 @@
/* please, do it beyond the point further indicated in this file. */
/* ================================================================ */
-#include <curl/curl.h>
-
/*
* Disable other protocols when http is the only one desired.
*/
@@ -219,7 +217,7 @@
/* ================================================================ */
/* No system header file shall be included in this file before this */
-/* point. The only allowed ones are those included from curl/system.h */
+/* point. */
/* ================================================================ */
/*
@@ -246,6 +244,8 @@
# include "setup-win32.h"
#endif
+#include <curl/system.h>
+
/*
* Use getaddrinfo to resolve the IPv4 address literal. If the current network
* interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
@@ -322,8 +322,10 @@
#include <assert.h>
#endif
-#ifdef __TANDEM /* for nsr-tandem-nsk systems */
-#include <floss.h>
+#ifdef __TANDEM /* for ns*-tandem-nsk systems */
+# if ! defined __LP64
+# include <floss.h> /* FLOSS is only used for 32-bit builds. */
+# endif
#endif
#ifndef STDC_HEADERS /* no standard C headers! */
@@ -740,12 +742,12 @@
#define SHUT_RDWR 0x02
#endif
-/* Define S_ISREG if not defined by system headers, f.e. MSVC */
+/* Define S_ISREG if not defined by system headers, e.g. MSVC */
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
-/* Define S_ISDIR if not defined by system headers, f.e. MSVC */
+/* Define S_ISDIR if not defined by system headers, e.g. MSVC */
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
diff --git a/contrib/libs/curl/lib/curl_setup_once.h b/contrib/libs/curl/lib/curl_setup_once.h
index e9730c9282..f09b00f9f2 100644
--- a/contrib/libs/curl/lib/curl_setup_once.h
+++ b/contrib/libs/curl/lib/curl_setup_once.h
@@ -33,7 +33,6 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
-#include <ctype.h>
#include <time.h>
#ifdef HAVE_ERRNO_H
@@ -88,6 +87,8 @@
#include <sys/socket.h>
#endif
+#include "functypes.h"
+
#ifdef __hpux
# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
# ifdef OLD_APP32_64BIT_OFF_T
@@ -150,20 +151,10 @@ struct timeval {
* SEND_TYPE_RETV must also be defined.
*/
-#if !defined(RECV_TYPE_ARG1) || \
- !defined(RECV_TYPE_ARG2) || \
- !defined(RECV_TYPE_ARG3) || \
- !defined(RECV_TYPE_ARG4) || \
- !defined(RECV_TYPE_RETV)
- /* */
- Error Missing_definition_of_return_and_arguments_types_of_recv
- /* */
-#else
#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \
(RECV_TYPE_ARG2)(y), \
(RECV_TYPE_ARG3)(z), \
(RECV_TYPE_ARG4)(0))
-#endif
#else /* HAVE_RECV */
#ifndef sread
/* */
@@ -180,21 +171,10 @@ struct timeval {
(SEND_TYPE_ARG3)(z))
#elif defined(HAVE_SEND)
-#if !defined(SEND_TYPE_ARG1) || \
- !defined(SEND_QUAL_ARG2) || \
- !defined(SEND_TYPE_ARG2) || \
- !defined(SEND_TYPE_ARG3) || \
- !defined(SEND_TYPE_ARG4) || \
- !defined(SEND_TYPE_RETV)
- /* */
- Error Missing_definition_of_return_and_arguments_types_of_send
- /* */
-#else
#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
(SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \
(SEND_TYPE_ARG3)(z), \
(SEND_TYPE_ARG4)(SEND_4TH_ARG))
-#endif
#else /* HAVE_SEND */
#ifndef swrite
/* */
@@ -229,9 +209,6 @@ struct timeval {
# define sfcntl fcntl
#endif
-#define TOLOWER(x) (tolower((int) ((unsigned char)x)))
-
-
/*
* 'bool' stuff compatible with HP-UX headers.
*/
diff --git a/contrib/libs/curl/lib/curl_sha256.h b/contrib/libs/curl/lib/curl_sha256.h
index 9530b056da..7f296dc8f0 100644
--- a/contrib/libs/curl/lib/curl_sha256.h
+++ b/contrib/libs/curl/lib/curl_sha256.h
@@ -26,6 +26,7 @@
***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include <curl/curl.h>
#include "curl_hmac.h"
extern const struct HMAC_params Curl_HMAC_SHA256[1];
diff --git a/contrib/libs/curl/lib/doh.c b/contrib/libs/curl/lib/doh.c
index a86e157fc0..3b1d5d60ef 100644
--- a/contrib/libs/curl/lib/doh.c
+++ b/contrib/libs/curl/lib/doh.c
@@ -396,7 +396,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
goto error;
dohp->pending++;
- if(Curl_ipv6works(data)) {
+ if((conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* create IPv6 DoH request */
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
@@ -792,7 +792,7 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
#endif
CURLcode result = CURLE_OK;
int i;
- size_t hostlen = strlen(hostname) + 1; /* include zero terminator */
+ size_t hostlen = strlen(hostname) + 1; /* include null-terminator */
if(!de)
/* no input == no output! */
diff --git a/contrib/libs/curl/lib/dotdot.c b/contrib/libs/curl/lib/dotdot.c
deleted file mode 100644
index 0b045315d0..0000000000
--- a/contrib/libs/curl/lib/dotdot.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-#include "curl_setup.h"
-
-#include <curl/curl.h>
-
-#include "dotdot.h"
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
-/*
- * "Remove Dot Segments"
- * https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4
- */
-
-/*
- * Curl_dedotdotify()
- * @unittest: 1395
- *
- * This function gets a null-terminated path with dot and dotdot sequences
- * passed in and strips them off according to the rules in RFC 3986 section
- * 5.2.4.
- *
- * The function handles a query part ('?' + stuff) appended but it expects
- * that fragments ('#' + stuff) have already been cut off.
- *
- * RETURNS
- *
- * an allocated dedotdotified output string
- */
-char *Curl_dedotdotify(const char *input)
-{
- size_t inlen = strlen(input);
- char *clone;
- size_t clen = inlen; /* the length of the cloned input */
- char *out = malloc(inlen + 1);
- char *outptr;
- char *orgclone;
- char *queryp;
- if(!out)
- return NULL; /* out of memory */
-
- *out = 0; /* null-terminates, for inputs like "./" */
-
- /* get a cloned copy of the input */
- clone = strdup(input);
- if(!clone) {
- free(out);
- return NULL;
- }
- orgclone = clone;
- outptr = out;
-
- if(!*clone) {
- /* zero length string, return that */
- free(out);
- return clone;
- }
-
- /*
- * To handle query-parts properly, we must find it and remove it during the
- * dotdot-operation and then append it again at the end to the output
- * string.
- */
- queryp = strchr(clone, '?');
- if(queryp)
- *queryp = 0;
-
- do {
-
- /* A. If the input buffer begins with a prefix of "../" or "./", then
- remove that prefix from the input buffer; otherwise, */
-
- if(!strncmp("./", clone, 2)) {
- clone += 2;
- clen -= 2;
- }
- else if(!strncmp("../", clone, 3)) {
- clone += 3;
- clen -= 3;
- }
-
- /* B. if the input buffer begins with a prefix of "/./" or "/.", where
- "." is a complete path segment, then replace that prefix with "/" in
- the input buffer; otherwise, */
- else if(!strncmp("/./", clone, 3)) {
- clone += 2;
- clen -= 2;
- }
- else if(!strcmp("/.", clone)) {
- clone[1]='/';
- clone++;
- clen -= 1;
- }
-
- /* C. if the input buffer begins with a prefix of "/../" or "/..", where
- ".." is a complete path segment, then replace that prefix with "/" in
- the input buffer and remove the last segment and its preceding "/" (if
- any) from the output buffer; otherwise, */
-
- else if(!strncmp("/../", clone, 4)) {
- clone += 3;
- clen -= 3;
- /* remove the last segment from the output buffer */
- while(outptr > out) {
- outptr--;
- if(*outptr == '/')
- break;
- }
- *outptr = 0; /* null-terminate where it stops */
- }
- else if(!strcmp("/..", clone)) {
- clone[2]='/';
- clone += 2;
- clen -= 2;
- /* remove the last segment from the output buffer */
- while(outptr > out) {
- outptr--;
- if(*outptr == '/')
- break;
- }
- *outptr = 0; /* null-terminate where it stops */
- }
-
- /* D. if the input buffer consists only of "." or "..", then remove
- that from the input buffer; otherwise, */
-
- else if(!strcmp(".", clone) || !strcmp("..", clone)) {
- *clone = 0;
- *out = 0;
- }
-
- else {
- /* E. move the first path segment in the input buffer to the end of
- the output buffer, including the initial "/" character (if any) and
- any subsequent characters up to, but not including, the next "/"
- character or the end of the input buffer. */
-
- do {
- *outptr++ = *clone++;
- clen--;
- } while(*clone && (*clone != '/'));
- *outptr = 0;
- }
-
- } while(*clone);
-
- if(queryp) {
- size_t qlen;
- /* There was a query part, append that to the output. The 'clone' string
- may now have been altered so we copy from the original input string
- from the correct index. */
- size_t oindex = queryp - orgclone;
- qlen = strlen(&input[oindex]);
- memcpy(outptr, &input[oindex], qlen + 1); /* include the end zero byte */
- }
-
- free(orgclone);
- return out;
-}
diff --git a/contrib/libs/curl/lib/dynbuf.c b/contrib/libs/curl/lib/dynbuf.c
index 3b907dbe2e..0b1cf9afd8 100644
--- a/contrib/libs/curl/lib/dynbuf.c
+++ b/contrib/libs/curl/lib/dynbuf.c
@@ -128,7 +128,6 @@ void Curl_dyn_reset(struct dynbuf *s)
s->leng = 0;
}
-#ifdef USE_NGTCP2
/*
* Specify the size of the tail to keep (number of bytes from the end of the
* buffer). The rest will be dropped.
@@ -153,7 +152,6 @@ CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail)
return CURLE_OK;
}
-#endif
/*
* Appends a buffer with length.
@@ -255,3 +253,18 @@ size_t Curl_dyn_len(const struct dynbuf *s)
DEBUGASSERT(!s->leng || s->bufr);
return s->leng;
}
+
+/*
+ * Set a new (smaller) length.
+ */
+CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t set)
+{
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ if(set > s->leng)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ s->leng = set;
+ s->bufr[s->leng] = 0;
+ return CURLE_OK;
+}
diff --git a/contrib/libs/curl/lib/dynbuf.h b/contrib/libs/curl/lib/dynbuf.h
index c1e97235de..04a728c779 100644
--- a/contrib/libs/curl/lib/dynbuf.h
+++ b/contrib/libs/curl/lib/dynbuf.h
@@ -24,6 +24,8 @@
*
***************************************************************************/
+#include <curl/curl.h>
+
#ifndef BUILDING_LIBCURL
/* this renames the functions so that the tool code can use the same code
without getting symbol collisions */
@@ -38,12 +40,13 @@
#define Curl_dyn_len(a) curlx_dyn_len(a)
#define Curl_dyn_reset(a) curlx_dyn_reset(a)
#define Curl_dyn_tail(a,b) curlx_dyn_tail(a,b)
+#define Curl_dyn_setlen(a,b) curlx_dyn_setlen(a,b)
#define curlx_dynbuf dynbuf /* for the struct name */
#endif
struct dynbuf {
char *bufr; /* point to a null-terminated allocated buffer */
- size_t leng; /* number of bytes *EXCLUDING* the zero terminator */
+ size_t leng; /* number of bytes *EXCLUDING* the null-terminator */
size_t allc; /* size of the current allocation */
size_t toobig; /* size limit for the buffer */
#ifdef DEBUGBUILD
@@ -63,6 +66,7 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
WARN_UNUSED_RESULT;
void Curl_dyn_reset(struct dynbuf *s);
CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail);
+CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t set);
char *Curl_dyn_ptr(const struct dynbuf *s);
unsigned char *Curl_dyn_uptr(const struct dynbuf *s);
size_t Curl_dyn_len(const struct dynbuf *s);
diff --git a/contrib/libs/curl/lib/easy.c b/contrib/libs/curl/lib/easy.c
index 148b3615e3..b8ac1ef8a8 100644
--- a/contrib/libs/curl/lib/easy.c
+++ b/contrib/libs/curl/lib/easy.c
@@ -944,7 +944,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
goto fail;
}
-#ifdef USE_ALTSVC
+#ifndef CURL_DISABLE_ALTSVC
if(data->asi) {
outcurl->asi = Curl_altsvc_init();
if(!outcurl->asi)
@@ -1171,8 +1171,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
}
-static CURLcode easy_connection(struct Curl_easy *data,
- curl_socket_t *sfd,
+static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd,
struct connectdata **connp)
{
if(!data)
@@ -1231,11 +1230,12 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
}
/*
- * Sends data over the connected socket. Use after successful
- * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ * Sends data over the connected socket.
+ *
+ * This is the private internal version of curl_easy_send()
*/
-CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
- size_t buflen, size_t *n)
+CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
+ size_t buflen, ssize_t *n)
{
curl_socket_t sfd;
CURLcode result;
@@ -1243,9 +1243,6 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
struct connectdata *c = NULL;
SIGPIPE_VARIABLE(pipe_st);
- if(Curl_is_in_callback(data))
- return CURLE_RECURSIVE_API_CALL;
-
result = easy_connection(data, &sfd, &c);
if(result)
return result;
@@ -1267,8 +1264,25 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
if(!result && !n1)
return CURLE_AGAIN;
- *n = (size_t)n1;
+ *n = n1;
+
+ return result;
+}
+
+/*
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
+ size_t buflen, size_t *n)
+{
+ ssize_t written = 0;
+ CURLcode result;
+ if(Curl_is_in_callback(data))
+ return CURLE_RECURSIVE_API_CALL;
+ result = Curl_senddata(data, buffer, buflen, &written);
+ *n = (size_t)written;
return result;
}
diff --git a/contrib/libs/curl/lib/easy_lock.h b/contrib/libs/curl/lib/easy_lock.h
index 4c22be5f8a..d96e56b8d8 100644
--- a/contrib/libs/curl/lib/easy_lock.h
+++ b/contrib/libs/curl/lib/easy_lock.h
@@ -47,7 +47,7 @@ typedef PVOID SRWLOCK, *PSRWLOCK;
#define curl_simple_lock_lock(m) AcquireSRWLockExclusive(m)
#define curl_simple_lock_unlock(m) ReleaseSRWLockExclusive(m)
-#elif defined (HAVE_ATOMIC)
+#elif defined(HAVE_ATOMIC) && defined(HAVE_STDATOMIC_H)
#include <stdatomic.h>
#if defined(HAVE_SCHED_YIELD)
#include <sched.h>
diff --git a/contrib/libs/curl/lib/easyif.h b/contrib/libs/curl/lib/easyif.h
index 615df3f067..205382cd07 100644
--- a/contrib/libs/curl/lib/easyif.h
+++ b/contrib/libs/curl/lib/easyif.h
@@ -27,6 +27,9 @@
/*
* Prototypes for library-wide functions provided by easy.c
*/
+CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
+ size_t buflen, ssize_t *n);
+
#ifdef CURLDEBUG
CURL_EXTERN CURLcode curl_easy_perform_ev(struct Curl_easy *easy);
#endif
diff --git a/contrib/libs/curl/lib/easyoptions.c b/contrib/libs/curl/lib/easyoptions.c
index 412aefd990..e59b63af7a 100644
--- a/contrib/libs/curl/lib/easyoptions.c
+++ b/contrib/libs/curl/lib/easyoptions.c
@@ -354,6 +354,7 @@ struct curl_easyoption Curl_easyopts[] = {
{"WRITEDATA", CURLOPT_WRITEDATA, CURLOT_CBPTR, 0},
{"WRITEFUNCTION", CURLOPT_WRITEFUNCTION, CURLOT_FUNCTION, 0},
{"WRITEHEADER", CURLOPT_HEADERDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
+ {"WS_OPTIONS", CURLOPT_WS_OPTIONS, CURLOT_LONG, 0},
{"XFERINFODATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, 0},
{"XFERINFOFUNCTION", CURLOPT_XFERINFOFUNCTION, CURLOT_FUNCTION, 0},
{"XOAUTH2_BEARER", CURLOPT_XOAUTH2_BEARER, CURLOT_STRING, 0},
@@ -367,6 +368,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
- return ((CURLOPT_LASTENTRY%10000) != (319 + 1));
+ return ((CURLOPT_LASTENTRY%10000) != (320 + 1));
}
#endif
diff --git a/contrib/libs/curl/lib/formdata.c b/contrib/libs/curl/lib/formdata.c
index f5ed3653df..46542b4329 100644
--- a/contrib/libs/curl/lib/formdata.c
+++ b/contrib/libs/curl/lib/formdata.c
@@ -251,8 +251,10 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
}
}
else {
- /* This is not array-state, get next option */
- option = va_arg(params, CURLformoption);
+ /* This is not array-state, get next option. This gets an 'int' with
+ va_arg() because CURLformoption might be a smaller type than int and
+ might cause compiler warnings and wrong behavior. */
+ option = (CURLformoption)va_arg(params, int);
if(CURLFORM_END == option)
break;
}
diff --git a/contrib/libs/curl/lib/ftp.c b/contrib/libs/curl/lib/ftp.c
index 0473a8af00..f1a25b23dc 100644
--- a/contrib/libs/curl/lib/ftp.c
+++ b/contrib/libs/curl/lib/ftp.c
@@ -516,11 +516,9 @@ static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
}
else {
/* Add timeout to multi handle and break out of the loop */
- if(*connected == FALSE) {
- Curl_expire(data, data->set.accepttimeout > 0 ?
- data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT,
- EXPIRE_FTP_ACCEPT);
- }
+ Curl_expire(data, data->set.accepttimeout ?
+ data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT,
+ EXPIRE_FTP_ACCEPT);
}
return result;
@@ -2131,9 +2129,11 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
default:
infof(data, "unsupported MDTM reply format");
break;
- case 550: /* "No such file or directory" */
- failf(data, "Given file does not exist");
- result = CURLE_REMOTE_FILE_NOT_FOUND;
+ case 550: /* 550 is used for several different problems, e.g.
+ "No such file or directory" or "Permission denied".
+ It does not mean that the file does not exist at all. */
+ infof(data, "MDTM failed: file does not exist or permission problem,"
+ " continuing");
break;
}
diff --git a/contrib/libs/curl/lib/ftplistparser.c b/contrib/libs/curl/lib/ftplistparser.c
index 09476e55f4..40f5f3f189 100644
--- a/contrib/libs/curl/lib/ftplistparser.c
+++ b/contrib/libs/curl/lib/ftplistparser.c
@@ -422,7 +422,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
char *endptr = finfo->b_data + 6;
/* here we can deal with directory size, pass the leading
whitespace and then the digits */
- while(ISSPACE(*endptr))
+ while(ISBLANK(*endptr))
endptr++;
while(ISDIGIT(*endptr))
endptr++;
@@ -894,7 +894,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
parser->item_length++;
switch(parser->state.NT.sub.time) {
case PL_WINNT_TIME_PRESPACE:
- if(!ISSPACE(c)) {
+ if(!ISBLANK(c)) {
parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
}
break;
diff --git a/contrib/libs/curl/lib/functypes.h b/contrib/libs/curl/lib/functypes.h
new file mode 100644
index 0000000000..8891b1d5d6
--- /dev/null
+++ b/contrib/libs/curl/lib/functypes.h
@@ -0,0 +1,115 @@
+#ifndef HEADER_CURL_FUNCTYPES_H
+#define HEADER_CURL_FUNCTYPES_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+/* defaults:
+
+ ssize_t recv(int, void *, size_t, int);
+ ssize_t send(int, const void *, size_t, int);
+
+ If other argument or return types are needed:
+
+ 1. For systems that run configure or cmake, the alternatives are provided
+ here.
+ 2. For systems with config-*.h files, define them there.
+*/
+
+#ifdef WIN32
+/* int recv(SOCKET, char *, int, int) */
+#define RECV_TYPE_ARG1 SOCKET
+#define RECV_TYPE_ARG2 char *
+#define RECV_TYPE_ARG3 int
+#define RECV_TYPE_RETV int
+
+/* int send(SOCKET, const char *, int, int); */
+#define SEND_TYPE_ARG1 SOCKET
+#define SEND_TYPE_ARG2 char *
+#define SEND_TYPE_ARG3 int
+#define SEND_TYPE_RETV int
+
+#elif defined(__AMIGA__) /* Any AmigaOS flavour */
+
+/* long recv(long, char *, long, long); */
+#define RECV_TYPE_ARG1 long
+#define RECV_TYPE_ARG2 char *
+#define RECV_TYPE_ARG3 long
+#define RECV_TYPE_ARG4 long
+#define RECV_TYPE_RETV long
+
+/* int send(int, const char *, int, int); */
+#define SEND_TYPE_ARG1 int
+#define SEND_TYPE_ARG2 char *
+#define SEND_TYPE_ARG3 int
+#define SEND_TYPE_RETV int
+#endif
+
+
+#ifndef RECV_TYPE_ARG1
+#define RECV_TYPE_ARG1 int
+#endif
+
+#ifndef RECV_TYPE_ARG2
+#define RECV_TYPE_ARG2 void *
+#endif
+
+#ifndef RECV_TYPE_ARG3
+#define RECV_TYPE_ARG3 size_t
+#endif
+
+#ifndef RECV_TYPE_ARG4
+#define RECV_TYPE_ARG4 int
+#endif
+
+#ifndef RECV_TYPE_RETV
+#define RECV_TYPE_RETV ssize_t
+#endif
+
+#ifndef SEND_QUAL_ARG2
+#define SEND_QUAL_ARG2 const
+#endif
+
+#ifndef SEND_TYPE_ARG1
+#define SEND_TYPE_ARG1 int
+#endif
+
+#ifndef SEND_TYPE_ARG2
+#define SEND_TYPE_ARG2 void *
+#endif
+
+#ifndef SEND_TYPE_ARG3
+#define SEND_TYPE_ARG3 size_t
+#endif
+
+#ifndef SEND_TYPE_ARG4
+#define SEND_TYPE_ARG4 int
+#endif
+
+#ifndef SEND_TYPE_RETV
+#define SEND_TYPE_RETV ssize_t
+#endif
+
+#endif /* HEADER_CURL_FUNCTYPES_H */
diff --git a/contrib/libs/curl/lib/h2h3.c b/contrib/libs/curl/lib/h2h3.c
index 5d26bf0f21..50254ad0fa 100644
--- a/contrib/libs/curl/lib/h2h3.c
+++ b/contrib/libs/curl/lib/h2h3.c
@@ -191,7 +191,7 @@ CURLcode Curl_pseudo_headers(struct Curl_easy *data,
vptr = Curl_checkheaders(data, STRCONST(H2H3_PSEUDO_SCHEME));
if(vptr) {
vptr += sizeof(H2H3_PSEUDO_SCHEME);
- while(*vptr && ISSPACE(*vptr))
+ while(*vptr && ISBLANK(*vptr))
vptr++;
nva[2].value = vptr;
infof(data, "set pseudo header %s to %s", H2H3_PSEUDO_SCHEME, vptr);
diff --git a/contrib/libs/curl/lib/headers.c b/contrib/libs/curl/lib/headers.c
index d1e0ed7544..978c918f4f 100644
--- a/contrib/libs/curl/lib/headers.c
+++ b/contrib/libs/curl/lib/headers.c
@@ -207,7 +207,7 @@ static CURLcode namevalue(char *header, size_t hlen, unsigned int type,
return CURLE_BAD_FUNCTION_ARGUMENT;
/* skip all leading space letters */
- while(*header && ISSPACE(*header))
+ while(*header && ISBLANK(*header))
header++;
*value = header;
@@ -237,7 +237,7 @@ static CURLcode unfold_value(struct Curl_easy *data, const char *value,
vlen--;
/* save only one leading space */
- while((vlen > 1) && ISSPACE(value[0]) && ISSPACE(value[1])) {
+ while((vlen > 1) && ISBLANK(value[0]) && ISBLANK(value[1])) {
vlen--;
value++;
}
@@ -259,7 +259,7 @@ static CURLcode unfold_value(struct Curl_easy *data, const char *value,
/* put the data at the end of the previous data, not the newline */
memcpy(&newhs->value[olen], value, vlen);
- newhs->value[olen + vlen] = 0; /* zero terminate at newline */
+ newhs->value[olen + vlen] = 0; /* null-terminate at newline */
/* insert this node into the list of headers */
Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail,
diff --git a/contrib/libs/curl/lib/hostip.c b/contrib/libs/curl/lib/hostip.c
index d5224bfd45..5d087b7ff1 100644
--- a/contrib/libs/curl/lib/hostip.c
+++ b/contrib/libs/curl/lib/hostip.c
@@ -181,7 +181,7 @@ create_hostcache_id(const char *name, int port, char *ptr, size_t buflen)
len = buflen - 7;
/* store and lower case the name */
while(len--)
- *ptr++ = (char)TOLOWER(*name++);
+ *ptr++ = Curl_raw_tolower(*name++);
msnprintf(ptr, 7, ":%u", port);
}
@@ -297,6 +297,31 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
}
}
+ /* See if the returned entry matches the required resolve mode */
+ if(dns && data->conn->ip_version != CURL_IPRESOLVE_WHATEVER) {
+ int pf = PF_INET;
+ bool found = false;
+ struct Curl_addrinfo *addr = dns->addr;
+
+#ifdef PF_INET6
+ if(data->conn->ip_version == CURL_IPRESOLVE_V6)
+ pf = PF_INET6;
+#endif
+
+ while(addr) {
+ if(addr->ai_family == pf) {
+ found = true;
+ break;
+ }
+ addr = addr->ai_next;
+ }
+
+ if(!found) {
+ infof(data, "Hostname in DNS cache doesn't have needed family, zapped");
+ dns = NULL; /* the memory deallocation is being handled by the hash */
+ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
+ }
+ }
return dns;
}
@@ -546,7 +571,11 @@ bool Curl_ipv6works(struct Curl_easy *data)
have the info kept for fast re-use */
DEBUGASSERT(data);
DEBUGASSERT(data->multi);
- return data->multi->ipv6_works;
+ if(data->multi->ipv6_up == IPV6_UNKNOWN) {
+ bool works = Curl_ipv6works(NULL);
+ data->multi->ipv6_up = works ? IPV6_WORKS : IPV6_DEAD;
+ }
+ return data->multi->ipv6_up == IPV6_WORKS;
}
else {
int ipv6_works = -1;
@@ -584,7 +613,7 @@ bool Curl_host_is_ipnum(const char *hostname)
}
-/* return TRUE if 'part' is a case insentive tail of 'full' */
+/* return TRUE if 'part' is a case insensitive tail of 'full' */
static bool tailmatch(const char *full, const char *part)
{
size_t plen = strlen(part);
diff --git a/contrib/libs/curl/lib/hostip6.c b/contrib/libs/curl/lib/hostip6.c
index d9868628c3..c62c254c72 100644
--- a/contrib/libs/curl/lib/hostip6.c
+++ b/contrib/libs/curl/lib/hostip6.c
@@ -96,8 +96,8 @@ static void dump_addrinfo(struct connectdata *conn,
* non-ares version).
*
* Returns name information about the given hostname and port number. If
- * successful, the 'addrinfo' is returned and the forth argument will point to
- * memory we need to free after use. That memory *MUST* be freed with
+ * successful, the 'addrinfo' is returned and the fourth argument will point
+ * to memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
@@ -117,7 +117,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
*waitp = 0; /* synchronous response only */
- if(Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
diff --git a/contrib/libs/curl/lib/hsts.c b/contrib/libs/curl/lib/hsts.c
index 4ba0f30726..e3b686ebfa 100644
--- a/contrib/libs/curl/lib/hsts.c
+++ b/contrib/libs/curl/lib/hsts.c
@@ -156,7 +156,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
return CURLE_OK;
do {
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(Curl_strncasecompare("max-age=", p, 8)) {
bool quoted = FALSE;
@@ -167,7 +167,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
return CURLE_BAD_FUNCTION_ARGUMENT;
p += 8;
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(*p == '\"') {
p++;
@@ -200,7 +200,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
p++;
}
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(*p == ';')
p++;
diff --git a/contrib/libs/curl/lib/http.c b/contrib/libs/curl/lib/http.c
index 48571ab52c..ea0a53632d 100644
--- a/contrib/libs/curl/lib/http.c
+++ b/contrib/libs/curl/lib/http.c
@@ -84,6 +84,7 @@
#include "strdup.h"
#include "altsvc.h"
#include "hsts.h"
+#include "ws.h"
#include "c-hyper.h"
/* The last 3 #include files should be in this order */
@@ -114,6 +115,10 @@ static int https_getsock(struct Curl_easy *data,
#endif
static CURLcode http_setup_conn(struct Curl_easy *data,
struct connectdata *conn);
+#ifdef USE_WEBSOCKETS
+static CURLcode ws_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn);
+#endif
/*
* HTTP handler interface.
@@ -142,6 +147,32 @@ const struct Curl_handler Curl_handler_http = {
PROTOPT_USERPWDCTRL
};
+#ifdef USE_WEBSOCKETS
+const struct Curl_handler Curl_handler_ws = {
+ "WS", /* scheme */
+ ws_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ PORT_HTTP, /* defport */
+ CURLPROTO_WS, /* protocol */
+ CURLPROTO_HTTP, /* family */
+ PROTOPT_CREDSPERREQUEST | /* flags */
+ PROTOPT_USERPWDCTRL
+};
+#endif
+
#ifdef USE_SSL
/*
* HTTPS handler interface.
@@ -166,11 +197,38 @@ const struct Curl_handler Curl_handler_https = {
PORT_HTTPS, /* defport */
CURLPROTO_HTTPS, /* protocol */
CURLPROTO_HTTP, /* family */
- PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */
+ PROTOPT_USERPWDCTRL
+};
+
+#ifdef USE_WEBSOCKETS
+const struct Curl_handler Curl_handler_wss = {
+ "WSS", /* scheme */
+ ws_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ https_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ https_getsock, /* proto_getsock */
+ http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ PORT_HTTPS, /* defport */
+ CURLPROTO_WSS, /* protocol */
+ CURLPROTO_HTTP, /* family */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */
PROTOPT_USERPWDCTRL
};
#endif
+#endif
+
static CURLcode http_setup_conn(struct Curl_easy *data,
struct connectdata *conn)
{
@@ -205,6 +263,16 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
return CURLE_OK;
}
+#ifdef USE_WEBSOCKETS
+static CURLcode ws_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ /* websockets is 1.1 only (for now) */
+ data->state.httpwant = CURL_HTTP_VERSION_1_1;
+ return http_setup_conn(data, conn);
+}
+#endif
+
#ifndef CURL_DISABLE_PROXY
/*
* checkProxyHeaders() checks the linked list of custom proxy headers
@@ -653,21 +721,6 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
return result;
}
-/*
- * Curl_allow_auth_to_host() tells if authentication, cookies or other
- * "sensitive data" can (still) be sent to this host.
- */
-bool Curl_allow_auth_to_host(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- return (!data->state.this_is_a_follow ||
- data->set.allow_auth_to_other_hosts ||
- (data->state.first_host &&
- strcasecompare(data->state.first_host, conn->host.name) &&
- (data->state.first_remote_port == conn->remote_port) &&
- (data->state.first_remote_protocol == conn->handler->protocol)));
-}
-
#ifndef CURL_DISABLE_HTTP_AUTH
/*
* Output the correct authentication header depending on the auth type
@@ -866,7 +919,7 @@ Curl_http_output_auth(struct Curl_easy *data,
/* To prevent the user+password to get sent to other than the original host
due to a location-follow */
- if(Curl_allow_auth_to_host(data)
+ if(Curl_auth_allowed_to_host(data)
#ifndef CURL_DISABLE_NETRC
|| conn->bits.netrc
#endif
@@ -1518,7 +1571,7 @@ CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
}
#endif
- if(conn->given->protocol & CURLPROTO_HTTPS) {
+ if(conn->given->flags & PROTOPT_SSL) {
/* perform SSL initialization */
result = https_connecting(data, done);
if(result)
@@ -1643,6 +1696,7 @@ CURLcode Curl_http_done(struct Curl_easy *data,
Curl_mime_cleanpart(&http->form);
Curl_dyn_reset(&data->state.headerb);
Curl_hyper_done(data);
+ Curl_ws_done(data);
if(status)
return status;
@@ -1919,7 +1973,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
checkprefix("Cookie:", compare)) &&
/* be careful of sending this potentially sensitive header to
other hosts */
- !Curl_allow_auth_to_host(data))
+ !Curl_auth_allowed_to_host(data))
;
else {
#ifdef USE_HYPER
@@ -2151,9 +2205,9 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
[brackets] if the host name is a plain IPv6-address. RFC2732-style. */
const char *host = conn->host.name;
- if(((conn->given->protocol&CURLPROTO_HTTPS) &&
+ if(((conn->given->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS)) &&
(conn->remote_port == PORT_HTTPS)) ||
- ((conn->given->protocol&CURLPROTO_HTTP) &&
+ ((conn->given->protocol&(CURLPROTO_HTTP|CURLPROTO_WS)) &&
(conn->remote_port == PORT_HTTP)) )
/* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
the port number in the host string */
@@ -2702,6 +2756,13 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending HTTP request");
+#ifdef USE_WEBSOCKETS
+ else if((conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) &&
+ !(data->set.connect_only))
+ /* Set up the transfer for two-way since without CONNECT_ONLY set, this
+ request probably wants to send data too post upgrade */
+ Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, FIRSTSOCKET);
+#endif
else
/* HTTP GET/HEAD download: */
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
@@ -2731,7 +2792,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
const char *host = data->state.aptr.cookiehost ?
data->state.aptr.cookiehost : conn->host.name;
const bool secure_context =
- conn->handler->protocol&CURLPROTO_HTTPS ||
+ conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
strcasecompare("localhost", host) ||
!strcmp(host, "127.0.0.1") ||
!strcmp(host, "[::1]") ? TRUE : FALSE;
@@ -3044,7 +3105,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(conn->transport != TRNSPRT_QUIC) {
if(conn->httpversion < 20) { /* unless the connection is re-used and
already http2 */
- switch(conn->negnpn) {
+ switch(conn->alpn) {
case CURL_HTTP_VERSION_2:
conn->httpversion = 20; /* we know we're on HTTP/2 now */
@@ -3256,6 +3317,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
}
result = Curl_http_cookies(data, conn, &req);
+ if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
+ result = Curl_ws_request(data, &req);
if(!result)
result = Curl_add_timecondition(data, &req);
if(!result)
@@ -3520,15 +3583,15 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
else if(checkprefix("Retry-After:", headp)) {
/* Retry-After = HTTP-date / delay-seconds */
curl_off_t retry_after = 0; /* zero for unknown or "now" */
- time_t date = Curl_getdate_capped(headp + strlen("Retry-After:"));
- if(-1 == date) {
- /* not a date, try it as a decimal number */
- (void)curlx_strtoofft(headp + strlen("Retry-After:"),
- NULL, 10, &retry_after);
+ /* Try it as a decimal number, if it works it is not a date */
+ (void)curlx_strtoofft(headp + strlen("Retry-After:"),
+ NULL, 10, &retry_after);
+ if(!retry_after) {
+ time_t date = Curl_getdate_capped(headp + strlen("Retry-After:"));
+ if(-1 != date)
+ /* convert date to number of seconds into the future */
+ retry_after = date - time(NULL);
}
- else
- /* convert date to number of seconds into the future */
- retry_after = date - time(NULL);
data->info.retry_after = retry_after; /* store it */
}
else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
@@ -3540,7 +3603,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
The second format was added since Sun's webserver
JavaWebServer/1.1.1 obviously sends the header this way!
The third added since some servers use that!
- The forth means the requested range was unsatisfied.
+ The fourth means the requested range was unsatisfied.
*/
char *ptr = headp + strlen("Content-Range:");
@@ -3568,7 +3631,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
const char *host = data->state.aptr.cookiehost?
data->state.aptr.cookiehost:conn->host.name;
const bool secure_context =
- conn->handler->protocol&CURLPROTO_HTTPS ||
+ conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
strcasecompare("localhost", host) ||
!strcmp(host, "127.0.0.1") ||
!strcmp(host, "[::1]") ? TRUE : FALSE;
@@ -3652,7 +3715,14 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
#ifndef CURL_DISABLE_HSTS
/* If enabled, the header is incoming and this is over HTTPS */
else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
- (conn->handler->flags & PROTOPT_SSL)) {
+ ((conn->handler->flags & PROTOPT_SSL) ||
+#ifdef CURLDEBUG
+ /* allow debug builds to circumvent the HTTPS restriction */
+ getenv("CURL_HSTS_HTTP")
+#else
+ 0
+#endif
+ )) {
CURLcode check =
Curl_hsts_parse(data->hsts, data->state.up.hostname,
headp + strlen("Strict-Transport-Security:"));
@@ -3734,7 +3804,7 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
connclose(conn, "HTTP/1.0 close after body");
}
else if(conn->httpversion == 20 ||
- (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
+ (k->upgr101 == UPGR101_H2 && k->httpcode == 101)) {
DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
/* HTTP/2 cannot avoid multiplexing since it is a core functionality
of the protocol */
@@ -3960,9 +4030,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
break;
case 101:
/* Switching Protocols */
- if(k->upgr101 == UPGR101_REQUESTED) {
+ if(k->upgr101 == UPGR101_H2) {
/* Switching to HTTP/2 */
- infof(data, "Received 101");
+ infof(data, "Received 101, Switching to HTTP/2");
k->upgr101 = UPGR101_RECEIVED;
/* we'll get more headers (HTTP/2 response) */
@@ -3976,8 +4046,21 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
return result;
*nread = 0;
}
+#ifdef USE_WEBSOCKETS
+ else if(k->upgr101 == UPGR101_WS) {
+ /* verify the response */
+ result = Curl_ws_accept(data);
+ if(result)
+ return result;
+ k->header = FALSE; /* no more header to parse! */
+ if(data->set.connect_only) {
+ k->keepon &= ~KEEP_RECV; /* read no more content */
+ *nread = 0;
+ }
+ }
+#endif
else {
- /* Switching to another protocol (e.g. WebSocket) */
+ /* Not switching to another protocol */
k->header = FALSE; /* no more header to parse! */
}
break;
@@ -4070,6 +4153,16 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
return CURLE_HTTP_RETURNED_ERROR;
}
+#ifdef USE_WEBSOCKETS
+ /* All non-101 HTTP status codes are bad when wanting to upgrade to
+ websockets */
+ if(data->req.upgr101 == UPGR101_WS) {
+ failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+#endif
+
+
data->req.deductheadercount =
(100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
diff --git a/contrib/libs/curl/lib/http.h b/contrib/libs/curl/lib/http.h
index 2ac287eca8..f7cbb34244 100644
--- a/contrib/libs/curl/lib/http.h
+++ b/contrib/libs/curl/lib/http.h
@@ -24,6 +24,7 @@
*
***************************************************************************/
#include "curl_setup.h"
+#include "ws.h"
typedef enum {
HTTPREQ_GET,
@@ -50,6 +51,15 @@ extern const struct Curl_handler Curl_handler_http;
extern const struct Curl_handler Curl_handler_https;
#endif
+#ifdef USE_WEBSOCKETS
+extern const struct Curl_handler Curl_handler_ws;
+
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_wss;
+#endif
+#endif /* websockets */
+
+
/* Header specific functions */
bool Curl_compareheader(const char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */
@@ -218,6 +228,10 @@ struct HTTP {
HTTPSEND_BODY /* sending body */
} sending;
+#ifdef USE_WEBSOCKETS
+ struct websocket ws;
+#endif
+
#ifndef CURL_DISABLE_HTTP
struct dynbuf send_buffer; /* used if the request couldn't be sent in one
chunk, points to an allocated send_buffer
@@ -367,10 +381,4 @@ Curl_http_output_auth(struct Curl_easy *data,
bool proxytunnel); /* TRUE if this is the request setting
up the proxy tunnel */
-/*
- * Curl_allow_auth_to_host() tells if authentication, cookies or other
- * "sensitive data" can (still) be sent to this host.
- */
-bool Curl_allow_auth_to_host(struct Curl_easy *data);
-
#endif /* HEADER_CURL_HTTP_H */
diff --git a/contrib/libs/curl/lib/http2.c b/contrib/libs/curl/lib/http2.c
index 3a70528e4a..b7409b027d 100644
--- a/contrib/libs/curl/lib/http2.c
+++ b/contrib/libs/curl/lib/http2.c
@@ -1392,7 +1392,7 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
free(base64);
- k->upgr101 = UPGR101_REQUESTED;
+ k->upgr101 = UPGR101_H2;
return result;
}
diff --git a/contrib/libs/curl/lib/http_aws_sigv4.c b/contrib/libs/curl/lib/http_aws_sigv4.c
index d144fb817a..440eb385f8 100644
--- a/contrib/libs/curl/lib/http_aws_sigv4.c
+++ b/contrib/libs/curl/lib/http_aws_sigv4.c
@@ -44,6 +44,8 @@
#include "curl_memory.h"
#include "memdebug.h"
+#include "slist.h"
+
#define HMAC_SHA256(k, kl, d, dl, o) \
do { \
ret = Curl_hmacit(Curl_HMAC_SHA256, \
@@ -51,49 +53,241 @@
(unsigned int)kl, \
(unsigned char *)d, \
(unsigned int)dl, o); \
- if(ret != CURLE_OK) { \
+ if(ret) { \
goto fail; \
} \
} while(0)
+#define TIMESTAMP_SIZE 17
+
static void sha256_to_hex(char *dst, unsigned char *sha, size_t dst_l)
{
int i;
DEBUGASSERT(dst_l >= 65);
for(i = 0; i < 32; ++i) {
- curl_msnprintf(dst + (i * 2), dst_l - (i * 2), "%02x", sha[i]);
+ msnprintf(dst + (i * 2), dst_l - (i * 2), "%02x", sha[i]);
+ }
+}
+
+static char *find_date_hdr(struct Curl_easy *data, const char *sig_hdr)
+{
+ char *tmp = Curl_checkheaders(data, sig_hdr, strlen(sig_hdr));
+
+ if(tmp)
+ return tmp;
+ return Curl_checkheaders(data, STRCONST("Date"));
+}
+
+/* remove whitespace, and lowercase all headers */
+static void trim_headers(struct curl_slist *head)
+{
+ struct curl_slist *l;
+ for(l = head; l; l = l->next) {
+ char *value; /* to read from */
+ char *store;
+ size_t colon = strcspn(l->data, ":");
+ Curl_strntolower(l->data, l->data, colon);
+
+ value = &l->data[colon];
+ if(!*value)
+ continue;
+ ++value;
+ store = value;
+
+ /* skip leading whitespace */
+ while(*value && ISBLANK(*value))
+ value++;
+
+ while(*value) {
+ int space = 0;
+ while(*value && ISBLANK(*value)) {
+ value++;
+ space++;
+ }
+ if(space) {
+ /* replace any number of consecutive whitespace with a single space,
+ unless at the end of the string, then nothing */
+ if(*value)
+ *store++ = ' ';
+ }
+ else
+ *store++ = *value++;
+ }
+ *store = 0; /* null terminate */
}
}
+/* maximum lenth for the aws sivg4 parts */
+#define MAX_SIGV4_LEN 64
+#define MAX_SIGV4_LEN_TXT "64"
+
+#define DATE_HDR_KEY_LEN (MAX_SIGV4_LEN + sizeof("X--Date"))
+
+#define MAX_HOST_LEN 255
+/* FQDN + host: */
+#define FULL_HOST_LEN (MAX_HOST_LEN + sizeof("host:"))
+
+/* string been x-PROVIDER-date:TIMESTAMP, I need +1 for ':' */
+#define DATE_FULL_HDR_LEN (DATE_HDR_KEY_LEN + TIMESTAMP_SIZE + 1)
+
+/* timestamp should point to a buffer of at last TIMESTAMP_SIZE bytes */
+static CURLcode make_headers(struct Curl_easy *data,
+ const char *hostname,
+ char *timestamp,
+ char *provider1,
+ char **date_header,
+ struct dynbuf *canonical_headers,
+ struct dynbuf *signed_headers)
+{
+ char date_hdr_key[DATE_HDR_KEY_LEN];
+ char date_full_hdr[DATE_FULL_HDR_LEN];
+ struct curl_slist *head = NULL;
+ struct curl_slist *tmp_head = NULL;
+ CURLcode ret = CURLE_OUT_OF_MEMORY;
+ struct curl_slist *l;
+ int again = 1;
+
+ /* provider1 mid */
+ Curl_strntolower(provider1, provider1, strlen(provider1));
+ provider1[0] = Curl_raw_toupper(provider1[0]);
+
+ msnprintf(date_hdr_key, DATE_HDR_KEY_LEN, "X-%s-Date", provider1);
+
+ /* provider1 lowercase */
+ Curl_strntolower(provider1, provider1, 1); /* first byte only */
+ msnprintf(date_full_hdr, DATE_FULL_HDR_LEN,
+ "x-%s-date:%s", provider1, timestamp);
+
+ if(Curl_checkheaders(data, STRCONST("Host"))) {
+ head = NULL;
+ }
+ else {
+ char full_host[FULL_HOST_LEN + 1];
+
+ if(data->state.aptr.host) {
+ size_t pos;
+
+ if(strlen(data->state.aptr.host) > FULL_HOST_LEN) {
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ strcpy(full_host, data->state.aptr.host);
+ /* remove /r/n as the separator for canonical request must be '\n' */
+ pos = strcspn(full_host, "\n\r");
+ full_host[pos] = 0;
+ }
+ else {
+ if(strlen(hostname) > MAX_HOST_LEN) {
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ msnprintf(full_host, FULL_HOST_LEN, "host:%s", hostname);
+ }
+
+ head = curl_slist_append(NULL, full_host);
+ if(!head)
+ goto fail;
+ }
+
+
+ for(l = data->set.headers; l; l = l->next) {
+ tmp_head = curl_slist_append(head, l->data);
+ if(!tmp_head)
+ goto fail;
+ head = tmp_head;
+ }
+
+ trim_headers(head);
+
+ *date_header = find_date_hdr(data, date_hdr_key);
+ if(!*date_header) {
+ tmp_head = curl_slist_append(head, date_full_hdr);
+ if(!tmp_head)
+ goto fail;
+ head = tmp_head;
+ *date_header = curl_maprintf("%s: %s", date_hdr_key, timestamp);
+ }
+ else {
+ char *value;
+
+ *date_header = strdup(*date_header);
+ if(!*date_header)
+ goto fail;
+
+ value = strchr(*date_header, ':');
+ if(!value)
+ goto fail;
+ ++value;
+ while(ISBLANK(*value))
+ ++value;
+ strncpy(timestamp, value, TIMESTAMP_SIZE - 1);
+ timestamp[TIMESTAMP_SIZE - 1] = 0;
+ }
+
+ /* alpha-sort in a case sensitive manner */
+ do {
+ again = 0;
+ for(l = head; l; l = l->next) {
+ struct curl_slist *next = l->next;
+
+ if(next && strcmp(l->data, next->data) > 0) {
+ char *tmp = l->data;
+
+ l->data = next->data;
+ next->data = tmp;
+ again = 1;
+ }
+ }
+ } while(again);
+
+ for(l = head; l; l = l->next) {
+ char *tmp;
+
+ if(Curl_dyn_add(canonical_headers, l->data))
+ goto fail;
+ if(Curl_dyn_add(canonical_headers, "\n"))
+ goto fail;
+
+ tmp = strchr(l->data, ':');
+ if(tmp)
+ *tmp = 0;
+
+ if(l != head) {
+ if(Curl_dyn_add(signed_headers, ";"))
+ goto fail;
+ }
+ if(Curl_dyn_add(signed_headers, l->data))
+ goto fail;
+ }
+
+ ret = CURLE_OK;
+fail:
+ curl_slist_free_all(head);
+
+ return ret;
+}
+
CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
{
CURLcode ret = CURLE_OUT_OF_MEMORY;
struct connectdata *conn = data->conn;
size_t len;
- const char *tmp0;
- const char *tmp1;
- char *provider0_low = NULL;
- char *provider0_up = NULL;
- char *provider1_low = NULL;
- char *provider1_mid = NULL;
- char *region = NULL;
- char *service = NULL;
+ const char *arg;
+ char provider0[MAX_SIGV4_LEN + 1]="";
+ char provider1[MAX_SIGV4_LEN + 1]="";
+ char region[MAX_SIGV4_LEN + 1]="";
+ char service[MAX_SIGV4_LEN + 1]="";
const char *hostname = conn->host.name;
-#ifdef DEBUGBUILD
- char *force_timestamp;
-#endif
time_t clock;
struct tm tm;
- char timestamp[17];
+ char timestamp[TIMESTAMP_SIZE];
char date[9];
- const char *content_type = Curl_checkheaders(data, STRCONST("Content-Type"));
- char *canonical_headers = NULL;
- char *signed_headers = NULL;
- Curl_HttpReq httpreq;
- const char *method;
- size_t post_data_len;
- const char *post_data = data->set.postfields ? data->set.postfields : "";
+ struct dynbuf canonical_headers;
+ struct dynbuf signed_headers;
+ char *date_header = NULL;
+ const char *post_data = data->set.postfields;
+ size_t post_data_len = 0;
unsigned char sha_hash[32];
char sha_hex[65];
char *canonical_request = NULL;
@@ -101,10 +295,9 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
char *credential_scope = NULL;
char *str_to_sign = NULL;
const char *user = data->state.aptr.user ? data->state.aptr.user : "";
- const char *passwd = data->state.aptr.passwd ? data->state.aptr.passwd : "";
char *secret = NULL;
- unsigned char tmp_sign0[32] = {0};
- unsigned char tmp_sign1[32] = {0};
+ unsigned char sign0[32] = {0};
+ unsigned char sign1[32] = {0};
char *auth_headers = NULL;
DEBUGASSERT(!proxy);
@@ -115,6 +308,10 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
return CURLE_OK;
}
+ /* we init thoses buffers here, so goto fail will free initialized dynbuf */
+ Curl_dyn_init(&canonical_headers, CURL_MAX_HTTP_HEADER);
+ Curl_dyn_init(&signed_headers, CURL_MAX_HTTP_HEADER);
+
/*
* Parameters parsing
* Google and Outscale use the same OSC or GOOG,
@@ -122,223 +319,154 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
* AWS is the default because most of non-amazon providers
* are still using aws:amz as a prefix.
*/
- tmp0 = data->set.str[STRING_AWS_SIGV4] ?
+ arg = data->set.str[STRING_AWS_SIGV4] ?
data->set.str[STRING_AWS_SIGV4] : "aws:amz";
- tmp1 = strchr(tmp0, ':');
- len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
- if(len < 1) {
- infof(data, "first provider can't be empty");
+
+ /* provider1[:provider2[:region[:service]]]
+
+ No string can be longer than N bytes of non-whitespace
+ */
+ (void)sscanf(arg, "%" MAX_SIGV4_LEN_TXT "[^:]"
+ ":%" MAX_SIGV4_LEN_TXT "[^:]"
+ ":%" MAX_SIGV4_LEN_TXT "[^:]"
+ ":%" MAX_SIGV4_LEN_TXT "s",
+ provider0, provider1, region, service);
+ if(!provider0[0]) {
+ failf(data, "first provider can't be empty");
ret = CURLE_BAD_FUNCTION_ARGUMENT;
goto fail;
}
- provider0_low = malloc(len + 1);
- provider0_up = malloc(len + 1);
- if(!provider0_low || !provider0_up) {
- goto fail;
- }
- Curl_strntolower(provider0_low, tmp0, len);
- provider0_low[len] = '\0';
- Curl_strntoupper(provider0_up, tmp0, len);
- provider0_up[len] = '\0';
-
- if(tmp1) {
- tmp0 = tmp1 + 1;
- tmp1 = strchr(tmp0, ':');
- len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
- if(len < 1) {
- infof(data, "second provider can't be empty");
- ret = CURLE_BAD_FUNCTION_ARGUMENT;
- goto fail;
- }
- provider1_low = malloc(len + 1);
- provider1_mid = malloc(len + 1);
- if(!provider1_low || !provider1_mid) {
- goto fail;
- }
- Curl_strntolower(provider1_low, tmp0, len);
- provider1_low[len] = '\0';
- Curl_strntolower(provider1_mid, tmp0, len);
- provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
- provider1_mid[len] = '\0';
-
- if(tmp1) {
- tmp0 = tmp1 + 1;
- tmp1 = strchr(tmp0, ':');
- len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
- if(len < 1) {
- infof(data, "region can't be empty");
- ret = CURLE_BAD_FUNCTION_ARGUMENT;
- goto fail;
- }
- region = Curl_memdup(tmp0, len + 1);
- if(!region) {
- goto fail;
- }
- region[len] = '\0';
-
- if(tmp1) {
- tmp0 = tmp1 + 1;
- service = strdup(tmp0);
- if(!service) {
- goto fail;
- }
- if(strlen(service) < 1) {
- infof(data, "service can't be empty");
- ret = CURLE_BAD_FUNCTION_ARGUMENT;
- goto fail;
- }
- }
- }
- }
- else {
- provider1_low = Curl_memdup(provider0_low, len + 1);
- provider1_mid = Curl_memdup(provider0_low, len + 1);
- if(!provider1_low || !provider1_mid) {
- goto fail;
- }
- provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
- }
+ else if(!provider1[0])
+ strcpy(provider1, provider0);
- if(!service) {
- tmp0 = hostname;
- tmp1 = strchr(tmp0, '.');
- if(!tmp1) {
- infof(data, "service missing in parameters or hostname");
+ if(!service[0]) {
+ char *hostdot = strchr(hostname, '.');
+ if(!hostdot) {
+ failf(data, "service missing in parameters and hostname");
ret = CURLE_URL_MALFORMAT;
goto fail;
}
- len = tmp1 - tmp0;
- service = Curl_memdup(tmp0, len + 1);
- if(!service) {
+ len = hostdot - hostname;
+ if(len > MAX_SIGV4_LEN) {
+ failf(data, "service too long in hostname");
+ ret = CURLE_URL_MALFORMAT;
goto fail;
}
+ strncpy(service, hostname, len);
service[len] = '\0';
- if(!region) {
- tmp0 = tmp1 + 1;
- tmp1 = strchr(tmp0, '.');
- if(!tmp1) {
- infof(data, "region missing in parameters or hostname");
+ if(!region[0]) {
+ const char *reg = hostdot + 1;
+ const char *hostreg = strchr(reg, '.');
+ if(!hostreg) {
+ failf(data, "region missing in parameters and hostname");
ret = CURLE_URL_MALFORMAT;
goto fail;
}
- len = tmp1 - tmp0;
- region = Curl_memdup(tmp0, len + 1);
- if(!region) {
+ len = hostreg - reg;
+ if(len > MAX_SIGV4_LEN) {
+ failf(data, "region too long in hostname");
+ ret = CURLE_URL_MALFORMAT;
goto fail;
}
+ strncpy(region, reg, len);
region[len] = '\0';
}
}
#ifdef DEBUGBUILD
- force_timestamp = getenv("CURL_FORCETIME");
- if(force_timestamp)
- clock = 0;
- else
- time(&clock);
+ {
+ char *force_timestamp = getenv("CURL_FORCETIME");
+ if(force_timestamp)
+ clock = 0;
+ else
+ time(&clock);
+ }
#else
time(&clock);
#endif
ret = Curl_gmtime(clock, &tm);
- if(ret != CURLE_OK) {
+ if(ret) {
goto fail;
}
if(!strftime(timestamp, sizeof(timestamp), "%Y%m%dT%H%M%SZ", &tm)) {
+ ret = CURLE_OUT_OF_MEMORY;
goto fail;
}
+
+ ret = make_headers(data, hostname, timestamp, provider1,
+ &date_header, &canonical_headers, &signed_headers);
+ if(ret)
+ goto fail;
+ ret = CURLE_OUT_OF_MEMORY;
+
memcpy(date, timestamp, sizeof(date));
date[sizeof(date) - 1] = 0;
- if(content_type) {
- content_type = strchr(content_type, ':');
- if(!content_type) {
- ret = CURLE_FAILED_INIT;
- goto fail;
- }
- content_type++;
- /* Skip whitespace now */
- while(*content_type == ' ' || *content_type == '\t')
- ++content_type;
-
- canonical_headers = curl_maprintf("content-type:%s\n"
- "host:%s\n"
- "x-%s-date:%s\n",
- content_type,
- hostname,
- provider1_low, timestamp);
- signed_headers = curl_maprintf("content-type;host;x-%s-date",
- provider1_low);
- }
- else {
- canonical_headers = curl_maprintf("host:%s\n"
- "x-%s-date:%s\n",
- hostname,
- provider1_low, timestamp);
- signed_headers = curl_maprintf("host;x-%s-date", provider1_low);
- }
-
- if(!canonical_headers || !signed_headers) {
- goto fail;
+ if(post_data) {
+ if(data->set.postfieldsize < 0)
+ post_data_len = strlen(post_data);
+ else
+ post_data_len = (size_t)data->set.postfieldsize;
}
-
- if(data->set.postfieldsize < 0)
- post_data_len = strlen(post_data);
- else
- post_data_len = (size_t)data->set.postfieldsize;
if(Curl_sha256it(sha_hash, (const unsigned char *) post_data,
- post_data_len)) {
+ post_data_len))
goto fail;
- }
sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
- Curl_http_method(data, conn, &method, &httpreq);
-
- canonical_request =
- curl_maprintf("%s\n" /* HTTPRequestMethod */
- "%s\n" /* CanonicalURI */
- "%s\n" /* CanonicalQueryString */
- "%s\n" /* CanonicalHeaders */
- "%s\n" /* SignedHeaders */
- "%s", /* HashedRequestPayload in hex */
- method,
- data->state.up.path,
- data->state.up.query ? data->state.up.query : "",
- canonical_headers,
- signed_headers,
- sha_hex);
- if(!canonical_request) {
- goto fail;
+ {
+ Curl_HttpReq httpreq;
+ const char *method;
+
+ Curl_http_method(data, conn, &method, &httpreq);
+
+ canonical_request =
+ curl_maprintf("%s\n" /* HTTPRequestMethod */
+ "%s\n" /* CanonicalURI */
+ "%s\n" /* CanonicalQueryString */
+ "%s\n" /* CanonicalHeaders */
+ "%s\n" /* SignedHeaders */
+ "%s", /* HashedRequestPayload in hex */
+ method,
+ data->state.up.path,
+ data->state.up.query ? data->state.up.query : "",
+ Curl_dyn_ptr(&canonical_headers),
+ Curl_dyn_ptr(&signed_headers),
+ sha_hex);
+ if(!canonical_request)
+ goto fail;
}
- request_type = curl_maprintf("%s4_request", provider0_low);
- if(!request_type) {
+ /* provider 0 lowercase */
+ Curl_strntolower(provider0, provider0, strlen(provider0));
+ request_type = curl_maprintf("%s4_request", provider0);
+ if(!request_type)
goto fail;
- }
credential_scope = curl_maprintf("%s/%s/%s/%s",
date, region, service, request_type);
- if(!credential_scope) {
+ if(!credential_scope)
goto fail;
- }
if(Curl_sha256it(sha_hash, (unsigned char *) canonical_request,
- strlen(canonical_request))) {
+ strlen(canonical_request)))
goto fail;
- }
sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
+ /* provider 0 uppercase */
+ Curl_strntoupper(provider0, provider0, strlen(provider0));
+
/*
- * Google allow to use rsa key instead of HMAC, so this code might change
- * In the future, but for now we support only HMAC version
+ * Google allows using RSA key instead of HMAC, so this code might change
+ * in the future. For now we ony support HMAC.
*/
str_to_sign = curl_maprintf("%s4-HMAC-SHA256\n" /* Algorithm */
"%s\n" /* RequestDateTime */
"%s\n" /* CredentialScope */
"%s", /* HashedCanonicalRequest in hex */
- provider0_up,
+ provider0,
timestamp,
credential_scope,
sha_hex);
@@ -346,36 +474,33 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
goto fail;
}
- secret = curl_maprintf("%s4%s", provider0_up, passwd);
- if(!secret) {
+ /* provider 0 uppercase */
+ secret = curl_maprintf("%s4%s", provider0,
+ data->state.aptr.passwd ?
+ data->state.aptr.passwd : "");
+ if(!secret)
goto fail;
- }
- HMAC_SHA256(secret, strlen(secret),
- date, strlen(date), tmp_sign0);
- HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
- region, strlen(region), tmp_sign1);
- HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
- service, strlen(service), tmp_sign0);
- HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
- request_type, strlen(request_type), tmp_sign1);
- HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
- str_to_sign, strlen(str_to_sign), tmp_sign0);
+ HMAC_SHA256(secret, strlen(secret), date, strlen(date), sign0);
+ HMAC_SHA256(sign0, sizeof(sign0), region, strlen(region), sign1);
+ HMAC_SHA256(sign1, sizeof(sign1), service, strlen(service), sign0);
+ HMAC_SHA256(sign0, sizeof(sign0), request_type, strlen(request_type), sign1);
+ HMAC_SHA256(sign1, sizeof(sign1), str_to_sign, strlen(str_to_sign), sign0);
- sha256_to_hex(sha_hex, tmp_sign0, sizeof(sha_hex));
+ sha256_to_hex(sha_hex, sign0, sizeof(sha_hex));
+ /* provider 0 uppercase */
auth_headers = curl_maprintf("Authorization: %s4-HMAC-SHA256 "
"Credential=%s/%s, "
"SignedHeaders=%s, "
"Signature=%s\r\n"
- "X-%s-Date: %s\r\n",
- provider0_up,
+ "%s\r\n",
+ provider0,
user,
credential_scope,
- signed_headers,
+ Curl_dyn_ptr(&signed_headers),
sha_hex,
- provider1_mid,
- timestamp);
+ date_header);
if(!auth_headers) {
goto fail;
}
@@ -386,19 +511,14 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
ret = CURLE_OK;
fail:
- free(provider0_low);
- free(provider0_up);
- free(provider1_low);
- free(provider1_mid);
- free(region);
- free(service);
- free(canonical_headers);
- free(signed_headers);
+ Curl_dyn_free(&canonical_headers);
+ Curl_dyn_free(&signed_headers);
free(canonical_request);
free(request_type);
free(credential_scope);
free(str_to_sign);
free(secret);
+ free(date_header);
return ret;
}
diff --git a/contrib/libs/curl/lib/http_chunks.c b/contrib/libs/curl/lib/http_chunks.c
index 290dbe8faa..0b836851ac 100644
--- a/contrib/libs/curl/lib/http_chunks.c
+++ b/contrib/libs/curl/lib/http_chunks.c
@@ -125,7 +125,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
while(length) {
switch(ch->state) {
case CHUNK_HEX:
- if(isxdigit_ascii(*datap)) {
+ if(ISXDIGIT(*datap)) {
if(ch->hexindex < CHUNK_MAXNUM_LEN) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
diff --git a/contrib/libs/curl/lib/http_digest.c b/contrib/libs/curl/lib/http_digest.c
index c2472e103b..a71c6b7cfb 100644
--- a/contrib/libs/curl/lib/http_digest.c
+++ b/contrib/libs/curl/lib/http_digest.c
@@ -58,11 +58,11 @@ CURLcode Curl_input_digest(struct Curl_easy *data,
digest = &data->state.digest;
}
- if(!checkprefix("Digest", header) || !ISSPACE(header[6]))
+ if(!checkprefix("Digest", header) || !ISBLANK(header[6]))
return CURLE_BAD_CONTENT_ENCODING;
header += strlen("Digest");
- while(*header && ISSPACE(*header))
+ while(*header && ISBLANK(*header))
header++;
return Curl_auth_decode_digest_http_message(header, digest);
diff --git a/contrib/libs/curl/lib/http_negotiate.c b/contrib/libs/curl/lib/http_negotiate.c
index 0ac4ead097..5909f85b0d 100644
--- a/contrib/libs/curl/lib/http_negotiate.c
+++ b/contrib/libs/curl/lib/http_negotiate.c
@@ -84,7 +84,7 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
/* Obtain the input token, if any */
header += strlen("Negotiate");
- while(*header && ISSPACE(*header))
+ while(*header && ISBLANK(*header))
header++;
len = strlen(header);
diff --git a/contrib/libs/curl/lib/http_ntlm.c b/contrib/libs/curl/lib/http_ntlm.c
index a1f0f20cbb..5a6a977905 100644
--- a/contrib/libs/curl/lib/http_ntlm.c
+++ b/contrib/libs/curl/lib/http_ntlm.c
@@ -29,7 +29,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
diff --git a/contrib/libs/curl/lib/http_proxy.c b/contrib/libs/curl/lib/http_proxy.c
index 64b2dfe08a..d1933df0e3 100644
--- a/contrib/libs/curl/lib/http_proxy.c
+++ b/contrib/libs/curl/lib/http_proxy.c
@@ -212,10 +212,8 @@ void Curl_connect_done(struct Curl_easy *data)
Curl_dyn_free(&s->rcvbuf);
Curl_dyn_free(&s->req);
- /* restore the protocol pointer, if not already done */
- if(s->prot_save)
- data->req.p.http = s->prot_save;
- s->prot_save = NULL;
+ /* restore the protocol pointer */
+ data->req.p.http = s->prot_save;
data->info.httpcode = 0; /* clear it as it might've been used for the
proxy */
data->req.ignorebody = FALSE;
diff --git a/contrib/libs/curl/lib/idn_win32.c b/contrib/libs/curl/lib/idn_win32.c
index dacba01d7a..2433d927ee 100644
--- a/contrib/libs/curl/lib/idn_win32.c
+++ b/contrib/libs/curl/lib/idn_win32.c
@@ -67,10 +67,10 @@ WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
#define IDN_MAX_LENGTH 255
-bool curl_win32_idn_to_ascii(const char *in, char **out);
-bool curl_win32_ascii_to_idn(const char *in, char **out);
+bool Curl_win32_idn_to_ascii(const char *in, char **out);
+bool Curl_win32_ascii_to_idn(const char *in, char **out);
-bool curl_win32_idn_to_ascii(const char *in, char **out)
+bool Curl_win32_idn_to_ascii(const char *in, char **out)
{
bool success = FALSE;
@@ -93,7 +93,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out)
return success;
}
-bool curl_win32_ascii_to_idn(const char *in, char **out)
+bool Curl_win32_ascii_to_idn(const char *in, char **out)
{
bool success = FALSE;
diff --git a/contrib/libs/curl/lib/imap.c b/contrib/libs/curl/lib/imap.c
index 12ee2a47eb..ffa08bf7a4 100644
--- a/contrib/libs/curl/lib/imap.c
+++ b/contrib/libs/curl/lib/imap.c
@@ -1886,8 +1886,8 @@ static char *imap_atom(const char *str, bool escape_only)
*/
static bool imap_is_bchar(char ch)
{
- /* Peforming the alnum check with this macro is faster because of ASCII
- artihmetic */
+ /* Performing the alnum check with this macro is faster because of ASCII
+ arithmetic */
if(ISALNUM(ch))
return true;
diff --git a/contrib/libs/curl/lib/memdebug.h b/contrib/libs/curl/lib/memdebug.h
index 7a99e9c58a..7fc90e83a0 100644
--- a/contrib/libs/curl/lib/memdebug.h
+++ b/contrib/libs/curl/lib/memdebug.h
@@ -30,6 +30,9 @@
* as well as the library. Do not mix with library internals!
*/
+#include <curl/curl.h>
+#include "functypes.h"
+
#if defined(__GNUC__) && __GNUC__ >= 3
# define ALLOC_FUNC __attribute__((malloc))
# define ALLOC_SIZE(s) __attribute__((alloc_size(s)))
diff --git a/contrib/libs/curl/lib/mime.c b/contrib/libs/curl/lib/mime.c
index 11e614dc32..042141fc80 100644
--- a/contrib/libs/curl/lib/mime.c
+++ b/contrib/libs/curl/lib/mime.c
@@ -31,8 +31,9 @@
#include "urldata.h"
#include "sendf.h"
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
- !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
+#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
+ !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_IMAP))
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
#include <libgen.h>
@@ -1924,8 +1925,8 @@ void Curl_mime_unpause(curl_mimepart *part)
}
-#else /* !CURL_DISABLE_HTTP && !CURL_DISABLE_MIME ||
- !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
+#else /* !CURL_DISABLE_MIME && (!CURL_DISABLE_HTTP ||
+ !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP) */
/* Mime not compiled in: define stubs for externally-referenced functions. */
curl_mime *curl_mime_init(CURL *easy)
diff --git a/contrib/libs/curl/lib/mime.h b/contrib/libs/curl/lib/mime.h
index fe1a61c060..bafde29f40 100644
--- a/contrib/libs/curl/lib/mime.h
+++ b/contrib/libs/curl/lib/mime.h
@@ -134,8 +134,9 @@ struct curl_mimepart {
CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
- !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
+#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
+ !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_IMAP))
/* Prototypes. */
void Curl_mime_initpart(struct curl_mimepart *part, struct Curl_easy *easy);
diff --git a/contrib/libs/curl/lib/mprintf.c b/contrib/libs/curl/lib/mprintf.c
index 30347de250..8a7c17a7ff 100644
--- a/contrib/libs/curl/lib/mprintf.c
+++ b/contrib/libs/curl/lib/mprintf.c
@@ -318,6 +318,11 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
flags |= FLAGS_PREC;
precision = strtol(fmt, &fmt, 10);
}
+ if((flags & (FLAGS_PREC | FLAGS_PRECPARAM)) ==
+ (FLAGS_PREC | FLAGS_PRECPARAM))
+ /* it is not permitted to use both kinds of precision for the same
+ argument */
+ return 1;
break;
case 'h':
flags |= FLAGS_SHORT;
@@ -956,7 +961,7 @@ static int dprintf_formatf(
else
*fptr++ = 'f';
- *fptr = 0; /* and a final zero termination */
+ *fptr = 0; /* and a final null-termination */
#ifdef __clang__
#pragma clang diagnostic push
@@ -964,7 +969,11 @@ static int dprintf_formatf(
#endif
/* NOTE NOTE NOTE!! Not all sprintf implementations return number of
output characters */
+#ifdef HAVE_SNPRINTF
+ (snprintf)(work, sizeof(work), formatbuf, p->data.dnum);
+#else
(sprintf)(work, formatbuf, p->data.dnum);
+#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
diff --git a/contrib/libs/curl/lib/mqtt.c b/contrib/libs/curl/lib/mqtt.c
index 7320747af0..4f3d14386f 100644
--- a/contrib/libs/curl/lib/mqtt.c
+++ b/contrib/libs/curl/lib/mqtt.c
@@ -186,7 +186,7 @@ static int add_passwd(const char *passwd, const size_t plen,
return 0;
}
-/* add user to the CONN packet */
+/* add user to the CONNECT packet */
static int add_user(const char *username, const size_t ulen,
unsigned char *pkt, const size_t start, int remain_pos)
{
@@ -204,7 +204,7 @@ static int add_user(const char *username, const size_t ulen,
return 0;
}
-/* add client ID to the CONN packet */
+/* add client ID to the CONNECT packet */
static int add_client_id(const char *client_id, const size_t client_id_len,
char *pkt, const size_t start)
{
@@ -216,7 +216,7 @@ static int add_client_id(const char *client_id, const size_t client_id_len,
return 0;
}
-/* Set initial values of CONN packet */
+/* Set initial values of CONNECT packet */
static int init_connpack(char *packet, char *remain, int remain_pos)
{
/* Fixed header starts */
@@ -293,7 +293,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
memset(packet, 0, packetlen);
- /* set initial values for CONN pack */
+ /* set initial values for the CONNECT packet */
pos = init_connpack(packet, remain, remain_pos);
result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
@@ -389,10 +389,18 @@ static CURLcode mqtt_get_topic(struct Curl_easy *data,
char **topic, size_t *topiclen)
{
char *path = data->state.up.path;
- if(strlen(path) > 1)
- return Curl_urldecode(path + 1, 0, topic, topiclen, REJECT_NADA);
- failf(data, "No MQTT topic found. Forgot to URL encode it?");
- return CURLE_URL_MALFORMAT;
+ CURLcode result = CURLE_URL_MALFORMAT;
+ if(strlen(path) > 1) {
+ result = Curl_urldecode(path + 1, 0, topic, topiclen, REJECT_NADA);
+ if(!result && (*topiclen > 0xffff)) {
+ failf(data, "Too long MQTT topic");
+ result = CURLE_URL_MALFORMAT;
+ }
+ }
+ else
+ failf(data, "No MQTT topic found. Forgot to URL encode it?");
+
+ return result;
}
static CURLcode mqtt_subscribe(struct Curl_easy *data)
@@ -690,7 +698,7 @@ static CURLcode mqtt_do(struct Curl_easy *data, bool *done)
result = mqtt_connect(data);
if(result) {
- failf(data, "Error %d sending MQTT CONN request", result);
+ failf(data, "Error %d sending MQTT CONNECT request", result);
return result;
}
mqstate(data, MQTT_FIRST, MQTT_CONNACK);
diff --git a/contrib/libs/curl/lib/multi.c b/contrib/libs/curl/lib/multi.c
index f78ff72c42..7a54387253 100644
--- a/contrib/libs/curl/lib/multi.c
+++ b/contrib/libs/curl/lib/multi.c
@@ -45,7 +45,6 @@
#include "multihandle.h"
#include "sigpipe.h"
#include "vtls/vtls.h"
-#include "connect.h"
#include "http_proxy.h"
#include "http2.h"
#include "socketpair.h"
@@ -417,7 +416,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
/* -1 means it not set by user, use the default value */
multi->maxconnects = -1;
multi->max_concurrent_streams = 100;
- multi->ipv6_works = Curl_ipv6works(NULL);
#ifdef USE_WINSOCK
multi->wsa_event = WSACreateEvent();
@@ -755,7 +753,7 @@ static int close_connect_only(struct Curl_easy *data,
if(data->state.lastconnect_id != conn->connection_id)
return 0;
- if(!conn->bits.connect_only)
+ if(!conn->connect_only)
return 1;
connclose(conn, "Removing connect-only easy handle");
@@ -853,7 +851,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
Curl_detach_connection(data);
if(data->set.connect_only && !data->multi_easy) {
- /* This removes a handle that was part the multi inteface that used
+ /* This removes a handle that was part the multi interface that used
CONNECT_ONLY, that connection is now left alive but since this handle
has bits.close set nothing can use that transfer anymore and it is
forbidden from reuse. And this easy handle cannot find the connection
@@ -2146,7 +2144,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
}
- if(data->set.connect_only) {
+ if(data->set.connect_only == 1) {
/* keep connection open for application to use the socket */
connkeep(data->conn, "CONNECT_ONLY");
multistate(data, MSTATE_DONE);
diff --git a/contrib/libs/curl/lib/multihandle.h b/contrib/libs/curl/lib/multihandle.h
index 76a67a89a0..a997784ea3 100644
--- a/contrib/libs/curl/lib/multihandle.h
+++ b/contrib/libs/curl/lib/multihandle.h
@@ -150,11 +150,13 @@ struct Curl_multi {
0 is used for read, 1 is used for write */
#endif
#endif
- /* multiplexing wanted */
- bool multiplexing;
- bool recheckstate; /* see Curl_multi_connchanged */
+#define IPV6_UNKNOWN 0
+#define IPV6_DEAD 1
+#define IPV6_WORKS 2
+ unsigned char ipv6_up; /* IPV6_* defined */
+ bool multiplexing; /* multiplexing wanted */
+ bool recheckstate; /* see Curl_multi_connchanged */
bool in_callback; /* true while executing a callback */
- bool ipv6_works;
#ifdef USE_OPENSSL
bool ssl_seeded;
#endif
diff --git a/contrib/libs/curl/lib/netrc.c b/contrib/libs/curl/lib/netrc.c
index 62a6a10df8..4461b8492f 100644
--- a/contrib/libs/curl/lib/netrc.c
+++ b/contrib/libs/curl/lib/netrc.c
@@ -33,6 +33,7 @@
#include "netrc.h"
#include "strtok.h"
#include "strcase.h"
+#include "curl_get_line.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -58,8 +59,6 @@ enum host_lookup_state {
static int parsenetrc(const char *host,
char **loginp,
char **passwordp,
- bool *login_changed,
- bool *password_changed,
char *netrcfile)
{
FILE *file;
@@ -84,7 +83,7 @@ static int parsenetrc(const char *host,
char netrcbuffer[4096];
int netrcbuffsize = (int)sizeof(netrcbuffer);
- while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
+ while(!done && Curl_get_line(netrcbuffer, netrcbuffsize, file)) {
char *tok;
char *tok_end;
bool quoted;
@@ -96,7 +95,7 @@ static int parsenetrc(const char *host,
}
tok = netrcbuffer;
while(tok) {
- while(ISSPACE(*tok))
+ while(ISBLANK(*tok))
tok++;
/* tok is first non-space letter */
if(!*tok || (*tok == '#'))
@@ -198,9 +197,9 @@ static int parsenetrc(const char *host,
/* we are now parsing sub-keywords concerning "our" host */
if(state_login) {
if(specific_login) {
- state_our_login = strcasecompare(login, tok);
+ state_our_login = !Curl_timestrcmp(login, tok);
}
- else if(!login || strcmp(login, tok)) {
+ else if(!login || Curl_timestrcmp(login, tok)) {
if(login_alloc) {
free(login);
login_alloc = FALSE;
@@ -216,7 +215,7 @@ static int parsenetrc(const char *host,
}
else if(state_password) {
if((state_our_login || !specific_login)
- && (!password || strcmp(password, tok))) {
+ && (!password || Curl_timestrcmp(password, tok))) {
if(password_alloc) {
free(password);
password_alloc = FALSE;
@@ -243,24 +242,20 @@ static int parsenetrc(const char *host,
} /* switch (state) */
tok = ++tok_end;
}
- } /* while fgets() */
+ } /* while Curl_get_line() */
out:
if(!retcode) {
/* success */
- *login_changed = FALSE;
- *password_changed = FALSE;
if(login_alloc) {
if(*loginp)
free(*loginp);
*loginp = login;
- *login_changed = TRUE;
}
if(password_alloc) {
if(*passwordp)
free(*passwordp);
*passwordp = password;
- *password_changed = TRUE;
}
}
else {
@@ -281,11 +276,7 @@ static int parsenetrc(const char *host,
* *loginp and *passwordp MUST be allocated if they aren't NULL when passed
* in.
*/
-int Curl_parsenetrc(const char *host,
- char **loginp,
- char **passwordp,
- bool *login_changed,
- bool *password_changed,
+int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
char *netrcfile)
{
int retcode = 1;
@@ -334,8 +325,7 @@ int Curl_parsenetrc(const char *host,
free(homea);
return -1;
}
- retcode = parsenetrc(host, loginp, passwordp, login_changed,
- password_changed, filealloc);
+ retcode = parsenetrc(host, loginp, passwordp, filealloc);
free(filealloc);
#ifdef WIN32
if(retcode == NETRC_FILE_MISSING) {
@@ -345,16 +335,14 @@ int Curl_parsenetrc(const char *host,
free(homea);
return -1;
}
- retcode = parsenetrc(host, loginp, passwordp, login_changed,
- password_changed, filealloc);
+ retcode = parsenetrc(host, loginp, passwordp, filealloc);
free(filealloc);
}
#endif
free(homea);
}
else
- retcode = parsenetrc(host, loginp, passwordp, login_changed,
- password_changed, netrcfile);
+ retcode = parsenetrc(host, loginp, passwordp, netrcfile);
return retcode;
}
diff --git a/contrib/libs/curl/lib/netrc.h b/contrib/libs/curl/lib/netrc.h
index 53e315b61a..53d0056721 100644
--- a/contrib/libs/curl/lib/netrc.h
+++ b/contrib/libs/curl/lib/netrc.h
@@ -28,12 +28,8 @@
#ifndef CURL_DISABLE_NETRC
/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
-int Curl_parsenetrc(const char *host,
- char **loginp,
- char **passwordp,
- bool *login_changed,
- bool *password_changed,
- char *filename);
+int Curl_parsenetrc(const char *host, char **loginp,
+ char **passwordp, char *filename);
/* Assume: (*passwordp)[0]=0, host[0] != 0.
* If (*loginp)[0] = 0, search for login and password within a machine
* section in the netrc.
diff --git a/contrib/libs/curl/lib/noproxy.c b/contrib/libs/curl/lib/noproxy.c
new file mode 100644
index 0000000000..81f1e09934
--- /dev/null
+++ b/contrib/libs/curl/lib/noproxy.c
@@ -0,0 +1,222 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_PROXY
+
+#include "inet_pton.h"
+#include "strcase.h"
+#include "noproxy.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+/*
+ * Curl_cidr4_match() returns TRUE if the given IPv4 address is within the
+ * specified CIDR address range.
+ */
+UNITTEST bool Curl_cidr4_match(const char *ipv4, /* 1.2.3.4 address */
+ const char *network, /* 1.2.3.4 address */
+ unsigned int bits)
+{
+ unsigned int address = 0;
+ unsigned int check = 0;
+
+ if(bits > 32)
+ /* strange input */
+ return FALSE;
+
+ if(1 != Curl_inet_pton(AF_INET, ipv4, &address))
+ return FALSE;
+ if(1 != Curl_inet_pton(AF_INET, network, &check))
+ return FALSE;
+
+ if(bits && (bits != 32)) {
+ unsigned int mask = 0xffffffff << (32 - bits);
+ unsigned int haddr = htonl(address);
+ unsigned int hcheck = htonl(check);
+#if 0
+ fprintf(stderr, "Host %s (%x) network %s (%x) bits %u mask %x => %x\n",
+ ipv4, haddr, network, hcheck, bits, mask,
+ (haddr ^ hcheck) & mask);
+#endif
+ if((haddr ^ hcheck) & mask)
+ return FALSE;
+ return TRUE;
+ }
+ return (address == check);
+}
+
+UNITTEST bool Curl_cidr6_match(const char *ipv6,
+ const char *network,
+ unsigned int bits)
+{
+#ifdef ENABLE_IPV6
+ int bytes;
+ int rest;
+ unsigned char address[16];
+ unsigned char check[16];
+
+ if(!bits)
+ bits = 128;
+
+ bytes = bits/8;
+ rest = bits & 0x07;
+ if(1 != Curl_inet_pton(AF_INET6, ipv6, address))
+ return FALSE;
+ if(1 != Curl_inet_pton(AF_INET6, network, check))
+ return FALSE;
+ if((bytes > 16) || ((bytes == 16) && rest))
+ return FALSE;
+ if(bytes && memcmp(address, check, bytes))
+ return FALSE;
+ if(rest && !((address[bytes] ^ check[bytes]) & (0xff << (8 - rest))))
+ return FALSE;
+
+ return TRUE;
+#else
+ (void)ipv6;
+ (void)network;
+ (void)bits;
+ return FALSE;
+#endif
+}
+
+enum nametype {
+ TYPE_HOST,
+ TYPE_IPV4,
+ TYPE_IPV6
+};
+
+/****************************************************************
+* Checks if the host is in the noproxy list. returns TRUE if it matches and
+* therefore the proxy should NOT be used.
+****************************************************************/
+bool Curl_check_noproxy(const char *name, const char *no_proxy)
+{
+ /* no_proxy=domain1.dom,host.domain2.dom
+ * (a comma-separated list of hosts which should
+ * not be proxied, or an asterisk to override
+ * all proxy variables)
+ */
+ if(no_proxy && no_proxy[0]) {
+ const char *p = no_proxy;
+ size_t namelen;
+ enum nametype type = TYPE_HOST;
+ char hostip[128];
+ if(!strcmp("*", no_proxy))
+ return TRUE;
+
+ /* NO_PROXY was specified and it wasn't just an asterisk */
+
+ if(name[0] == '[') {
+ char *endptr;
+ /* IPv6 numerical address */
+ endptr = strchr(name, ']');
+ if(!endptr)
+ return FALSE;
+ name++;
+ namelen = endptr - name;
+ if(namelen >= sizeof(hostip))
+ return FALSE;
+ memcpy(hostip, name, namelen);
+ hostip[namelen] = 0;
+ name = hostip;
+ type = TYPE_IPV6;
+ }
+ else {
+ unsigned int address;
+ if(1 == Curl_inet_pton(AF_INET, name, &address))
+ type = TYPE_IPV4;
+ namelen = strlen(name);
+ }
+
+ while(*p) {
+ const char *token;
+ size_t tokenlen = 0;
+ bool match = FALSE;
+
+ /* pass blanks */
+ while(*p && ISBLANK(*p))
+ p++;
+
+ token = p;
+ /* pass over the pattern */
+ while(*p && !ISBLANK(*p) && (*p != ',')) {
+ p++;
+ tokenlen++;
+ }
+
+ if(tokenlen) {
+ switch(type) {
+ case TYPE_HOST:
+ if(*token == '.') {
+ ++token;
+ --tokenlen;
+ /* tailmatch */
+ match = (tokenlen <= namelen) &&
+ strncasecompare(token, name + (namelen - tokenlen), namelen);
+ }
+ else
+ match = (tokenlen == namelen) &&
+ strncasecompare(token, name, namelen);
+ break;
+ case TYPE_IPV4:
+ /* FALLTHROUGH */
+ case TYPE_IPV6: {
+ const char *check = token;
+ char *slash = strchr(check, '/');
+ unsigned int bits = 0;
+ char checkip[128];
+ /* if the slash is part of this token, use it */
+ if(slash && (slash < &check[tokenlen])) {
+ bits = atoi(slash + 1);
+ /* copy the check name to a temp buffer */
+ if(tokenlen >= sizeof(checkip))
+ break;
+ memcpy(checkip, check, tokenlen);
+ checkip[ slash - check ] = 0;
+ check = checkip;
+ }
+ if(type == TYPE_IPV6)
+ match = Curl_cidr6_match(name, check, bits);
+ else
+ match = Curl_cidr4_match(name, check, bits);
+ break;
+ }
+ }
+ if(match)
+ return TRUE;
+ } /* if(tokenlen) */
+ while(*p == ',')
+ p++;
+ } /* while(*p) */
+ } /* NO_PROXY was specified and it wasn't just an asterisk */
+
+ return FALSE;
+}
+
+#endif /* CURL_DISABLE_PROXY */
diff --git a/contrib/libs/curl/lib/dotdot.h b/contrib/libs/curl/lib/noproxy.h
index 4ffe72de83..8800a21276 100644
--- a/contrib/libs/curl/lib/dotdot.h
+++ b/contrib/libs/curl/lib/noproxy.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_DOTDOT_H
-#define HEADER_CURL_DOTDOT_H
+#ifndef HEADER_CURL_NOPROXY_H
+#define HEADER_CURL_NOPROXY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -23,5 +23,22 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-char *Curl_dedotdotify(const char *input);
-#endif /* HEADER_CURL_DOTDOT_H */
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_PROXY
+
+#ifdef DEBUGBUILD
+
+UNITTEST bool Curl_cidr4_match(const char *ipv4, /* 1.2.3.4 address */
+ const char *network, /* 1.2.3.4 address */
+ unsigned int bits);
+UNITTEST bool Curl_cidr6_match(const char *ipv6,
+ const char *network,
+ unsigned int bits);
+#endif
+
+bool Curl_check_noproxy(const char *name, const char *no_proxy);
+
+#endif
+
+#endif /* HEADER_CURL_NOPROXY_H */
diff --git a/contrib/libs/curl/lib/openldap.c b/contrib/libs/curl/lib/openldap.c
index d1adf27c86..7027c88054 100644
--- a/contrib/libs/curl/lib/openldap.c
+++ b/contrib/libs/curl/lib/openldap.c
@@ -1068,8 +1068,8 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
if(!binary) {
/* check for leading or trailing whitespace */
- if(ISSPACE(bvals[i].bv_val[0]) ||
- ISSPACE(bvals[i].bv_val[bvals[i].bv_len - 1]))
+ if(ISBLANK(bvals[i].bv_val[0]) ||
+ ISBLANK(bvals[i].bv_val[bvals[i].bv_len - 1]))
binval = 1;
else {
/* check for unprintable characters */
diff --git a/contrib/libs/curl/lib/pingpong.c b/contrib/libs/curl/lib/pingpong.c
index 74a678a1a4..d4e6be98c4 100644
--- a/contrib/libs/curl/lib/pingpong.c
+++ b/contrib/libs/curl/lib/pingpong.c
@@ -330,7 +330,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
else if(gotbytes <= 0) {
keepon = FALSE;
result = CURLE_RECV_ERROR;
- failf(data, "response reading failed");
+ failf(data, "response reading failed (errno: %d)", SOCKERRNO);
}
else {
/* we got a whole chunk of data, which can be anything from one
diff --git a/contrib/libs/curl/lib/rand.c b/contrib/libs/curl/lib/rand.c
index c6fd47e7f6..2e7e7e8238 100644
--- a/contrib/libs/curl/lib/rand.c
+++ b/contrib/libs/curl/lib/rand.c
@@ -212,7 +212,7 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
/*
* Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
- * hexadecimal digits PLUS a zero terminating byte. It must be an odd number
+ * hexadecimal digits PLUS a null-terminating byte. It must be an odd number
* size.
*/
@@ -235,7 +235,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
/* make sure it fits in the local buffer and that it is an odd number! */
return CURLE_BAD_FUNCTION_ARGUMENT;
- num--; /* save one for zero termination */
+ num--; /* save one for null-termination */
result = Curl_rand(data, buffer, num/2);
if(result)
diff --git a/contrib/libs/curl/lib/rand.h b/contrib/libs/curl/lib/rand.h
index 99f25b94e1..30fc29615a 100644
--- a/contrib/libs/curl/lib/rand.h
+++ b/contrib/libs/curl/lib/rand.h
@@ -42,7 +42,7 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
/*
* Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
- * hexadecimal digits PLUS a zero terminating byte. It must be an odd number
+ * hexadecimal digits PLUS a null-terminating byte. It must be an odd number
* size.
*/
CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
diff --git a/contrib/libs/curl/lib/rtsp.c b/contrib/libs/curl/lib/rtsp.c
index 5a6644b26c..6d3bf97e6c 100644
--- a/contrib/libs/curl/lib/rtsp.c
+++ b/contrib/libs/curl/lib/rtsp.c
@@ -794,7 +794,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
/* Find the first non-space letter */
start = header + 8;
- while(*start && ISSPACE(*start))
+ while(*start && ISBLANK(*start))
start++;
if(!*start) {
diff --git a/contrib/libs/curl/lib/select.h b/contrib/libs/curl/lib/select.h
index eaff7d9b1c..f2cf8bbd9f 100644
--- a/contrib/libs/curl/lib/select.h
+++ b/contrib/libs/curl/lib/select.h
@@ -36,8 +36,7 @@
* Definition of pollfd struct and constants for platforms lacking them.
*/
-#if !defined(HAVE_STRUCT_POLLFD) && \
- !defined(HAVE_SYS_POLL_H) && \
+#if !defined(HAVE_SYS_POLL_H) && \
!defined(HAVE_POLL_H) && \
!defined(POLLIN)
diff --git a/contrib/libs/curl/lib/sendf.c b/contrib/libs/curl/lib/sendf.c
index 2fe7169dd2..d26b7e7cd7 100644
--- a/contrib/libs/curl/lib/sendf.c
+++ b/contrib/libs/curl/lib/sendf.c
@@ -48,6 +48,7 @@
#include "strdup.h"
#include "http2.h"
#include "headers.h"
+#include "ws.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -534,6 +535,7 @@ static CURLcode chop_write(struct Curl_easy *data,
curl_write_callback writebody = NULL;
char *ptr = optr;
size_t len = olen;
+ void *writebody_ptr = data->set.out;
if(!len)
return CURLE_OK;
@@ -544,8 +546,18 @@ static CURLcode chop_write(struct Curl_easy *data,
return pausewrite(data, type, ptr, len);
/* Determine the callback(s) to use. */
- if(type & CLIENTWRITE_BODY)
+ if(type & CLIENTWRITE_BODY) {
+#ifdef USE_WEBSOCKETS
+ if(conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) {
+ struct HTTP *ws = data->req.p.http;
+ writebody = Curl_ws_writecb;
+ ws->ws.data = data;
+ writebody_ptr = ws;
+ }
+ else
+#endif
writebody = data->set.fwrite_func;
+ }
if((type & CLIENTWRITE_HEADER) &&
(data->set.fwrite_header || data->set.writeheader)) {
/*
@@ -563,7 +575,7 @@ static CURLcode chop_write(struct Curl_easy *data,
if(writebody) {
size_t wrote;
Curl_set_in_callback(data, true);
- wrote = writebody(ptr, 1, chunklen, data->set.out);
+ wrote = writebody(ptr, 1, chunklen, writebody_ptr);
Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote) {
@@ -723,9 +735,10 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type,
static const char s_infotype[CURLINFO_END][3] = {
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
if(data->set.fdebug) {
+ bool inCallback = Curl_is_in_callback(data);
Curl_set_in_callback(data, true);
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
- Curl_set_in_callback(data, false);
+ Curl_set_in_callback(data, inCallback);
}
else {
switch(type) {
diff --git a/contrib/libs/curl/lib/setopt.c b/contrib/libs/curl/lib/setopt.c
index d5e3b50c82..5b5975485c 100644
--- a/contrib/libs/curl/lib/setopt.c
+++ b/contrib/libs/curl/lib/setopt.c
@@ -148,81 +148,36 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
#define C_SSLVERSION_VALUE(x) (x & 0xffff)
#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
-static CURLcode protocol2num(char *str, curl_off_t *val)
+static CURLcode protocol2num(const char *str, curl_prot_t *val)
{
- bool found_comma = FALSE;
- static struct scheme {
- const char *name;
- long bit;
- } const protos[] = {
- { "dict", CURLPROTO_DICT },
- { "file", CURLPROTO_FILE },
- { "ftp", CURLPROTO_FTP },
- { "ftps", CURLPROTO_FTPS },
- { "gopher", CURLPROTO_GOPHER },
- { "gophers", CURLPROTO_GOPHERS },
- { "http", CURLPROTO_HTTP },
- { "https", CURLPROTO_HTTPS },
- { "imap", CURLPROTO_IMAP },
- { "imaps", CURLPROTO_IMAPS },
- { "ldap", CURLPROTO_LDAP },
- { "ldaps", CURLPROTO_LDAPS },
- { "mqtt", CURLPROTO_MQTT },
- { "pop3", CURLPROTO_POP3 },
- { "pop3s", CURLPROTO_POP3S },
- { "rtmp", CURLPROTO_RTMP },
- { "rtmpe", CURLPROTO_RTMPE },
- { "rtmps", CURLPROTO_RTMPS },
- { "rtmpt", CURLPROTO_RTMPT },
- { "rtmpte", CURLPROTO_RTMPTE },
- { "rtmpts", CURLPROTO_RTMPTS },
- { "rtsp", CURLPROTO_RTSP },
- { "scp", CURLPROTO_SCP },
- { "sftp", CURLPROTO_SFTP },
- { "smb", CURLPROTO_SMB },
- { "smbs", CURLPROTO_SMBS },
- { "smtp", CURLPROTO_SMTP },
- { "smtps", CURLPROTO_SMTPS },
- { "telnet", CURLPROTO_TELNET },
- { "tftp", CURLPROTO_TFTP },
- { NULL, 0 }
- };
-
if(!str)
return CURLE_BAD_FUNCTION_ARGUMENT;
- else if(curl_strequal(str, "all")) {
- *val = ~0;
+
+ if(curl_strequal(str, "all")) {
+ *val = ~(curl_prot_t) 0;
return CURLE_OK;
}
*val = 0;
do {
+ const char *token = str;
size_t tlen;
- struct scheme const *pp;
- char *token;
- token = strchr(str, ',');
- found_comma = token ? TRUE : FALSE;
- if(!token)
- token = strchr(str, '\0');
- tlen = token - str;
+
+ str = strchr(str, ',');
+ tlen = str? (size_t) (str - token): strlen(token);
if(tlen) {
- for(pp = protos; pp->name; pp++) {
- if((strlen(pp->name) == tlen) &&
- curl_strnequal(str, pp->name, tlen)) {
- *val |= pp->bit;
- break;
- }
- }
- if(!(pp->name))
- /* protocol name didn't match */
- return CURLE_BAD_FUNCTION_ARGUMENT;
+ const struct Curl_handler *h = Curl_builtin_scheme(token, tlen);
+
+ if(!h)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+
+ *val |= h->protocol;
}
- if(found_comma)
- str = token + 1;
- } while(found_comma);
+ } while(str++);
+
if(!*val)
- /* no matching protocol */
+ /* no protocol listed */
return CURLE_BAD_FUNCTION_ARGUMENT;
return CURLE_OK;
}
@@ -696,8 +651,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
}
else
data->set.method = HTTPREQ_GET;
+ data->set.upload = FALSE;
break;
+#ifndef CURL_DISABLE_MIME
case CURLOPT_HTTPPOST:
/*
* Set to make us do HTTP POST
@@ -706,6 +663,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.method = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
break;
+#endif
case CURLOPT_AWS_SIGV4:
/*
@@ -721,18 +679,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.httpauth = CURLAUTH_AWS_SIGV4;
break;
- case CURLOPT_MIMEPOST:
- /*
- * Set to make us do MIME/form POST
- */
- result = Curl_mime_set_subparts(&data->set.mimepost,
- va_arg(param, curl_mime *), FALSE);
- if(!result) {
- data->set.method = HTTPREQ_POST_MIME;
- data->set.opt_no_body = FALSE; /* this is implied */
- }
- break;
-
case CURLOPT_REFERER:
/*
* String to set in the HTTP Referer: field.
@@ -754,13 +700,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
va_arg(param, char *));
break;
- case CURLOPT_HTTPHEADER:
- /*
- * Set a list with HTTP headers to use (or replace internals with)
- */
- data->set.headers = va_arg(param, struct curl_slist *);
- break;
-
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXYHEADER:
/*
@@ -998,6 +937,36 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif /* CURL_DISABLE_HTTP */
+#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_IMAP)
+# if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MIME)
+ case CURLOPT_HTTPHEADER:
+ /*
+ * Set a list with HTTP headers to use (or replace internals with)
+ */
+ data->set.headers = va_arg(param, struct curl_slist *);
+ break;
+# endif
+
+# ifndef CURL_DISABLE_MIME
+ case CURLOPT_MIMEPOST:
+ /*
+ * Set to make us do MIME POST
+ */
+ result = Curl_mime_set_subparts(&data->set.mimepost,
+ va_arg(param, curl_mime *), FALSE);
+ if(!result) {
+ data->set.method = HTTPREQ_POST_MIME;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ break;
+
+ case CURLOPT_MIME_OPTIONS:
+ data->set.mime_options = (unsigned int)va_arg(param, long);
+ break;
+# endif
+#endif
+
case CURLOPT_HTTPAUTH:
/*
* Set HTTP Authentication type BITMASK.
@@ -2430,9 +2399,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_CONNECT_ONLY:
/*
- * No data transfer, set up connection and let application use the socket
+ * No data transfer.
+ * (1) - only do connection
+ * (2) - do first get request but get no content
*/
- data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ arg = va_arg(param, long);
+ if(arg > 2)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.connect_only = (unsigned char)arg;
break;
case CURLOPT_SOCKOPTFUNCTION:
@@ -2640,31 +2614,35 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
transfer, which thus helps the app which takes URLs from users or other
external inputs and want to restrict what protocol(s) to deal
with. Defaults to CURLPROTO_ALL. */
- data->set.allowed_protocols = (curl_off_t)va_arg(param, long);
+ data->set.allowed_protocols = (curl_prot_t)va_arg(param, long);
break;
case CURLOPT_REDIR_PROTOCOLS:
/* set the bitmask for the protocols that libcurl is allowed to follow to,
as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
to be set in both bitmasks to be allowed to get redirected to. */
- data->set.redir_protocols = (curl_off_t)va_arg(param, long);
+ data->set.redir_protocols = (curl_prot_t)va_arg(param, long);
break;
- case CURLOPT_PROTOCOLS_STR:
+ case CURLOPT_PROTOCOLS_STR: {
+ curl_prot_t prot;
argptr = va_arg(param, char *);
- result = protocol2num(argptr, &bigsize);
+ result = protocol2num(argptr, &prot);
if(result)
return result;
- data->set.allowed_protocols = bigsize;
+ data->set.allowed_protocols = prot;
break;
+ }
- case CURLOPT_REDIR_PROTOCOLS_STR:
+ case CURLOPT_REDIR_PROTOCOLS_STR: {
+ curl_prot_t prot;
argptr = va_arg(param, char *);
- result = protocol2num(argptr, &bigsize);
+ result = protocol2num(argptr, &prot);
if(result)
return result;
- data->set.redir_protocols = bigsize;
+ data->set.redir_protocols = prot;
break;
+ }
case CURLOPT_DEFAULT_PROTOCOL:
/* Set the protocol to use when the URL doesn't include any protocol */
@@ -2694,13 +2672,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
- !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
- case CURLOPT_MIME_OPTIONS:
- data->set.mime_options = (unsigned int)va_arg(param, long);
- break;
-#endif
-
case CURLOPT_SASL_AUTHZID:
/* Authorization identity (identity to act as) */
result = Curl_setstropt(&data->set.str[STRING_SASL_AUTHZID],
@@ -2952,7 +2923,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
break;
case CURLOPT_SSL_ENABLE_NPN:
- data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_SSL_ENABLE_ALPN:
data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
@@ -3128,6 +3098,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_PREREQDATA:
data->set.prereq_userp = va_arg(param, void *);
break;
+#ifdef USE_WEBSOCKETS
+ case CURLOPT_WS_OPTIONS: {
+ bool raw;
+ arg = va_arg(param, long);
+ raw = (arg & CURLWS_RAW_MODE);
+ data->set.ws_raw_mode = raw;
+ break;
+ }
+#endif
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
diff --git a/contrib/libs/curl/lib/setup-win32.h b/contrib/libs/curl/lib/setup-win32.h
index c16928db90..bc5f8efc3c 100644
--- a/contrib/libs/curl/lib/setup-win32.h
+++ b/contrib/libs/curl/lib/setup-win32.h
@@ -37,10 +37,21 @@
#ifdef HAVE_WINDOWS_H
# if defined(UNICODE) && !defined(_UNICODE)
-# define _UNICODE
+# error "UNICODE is defined but _UNICODE is not defined"
# endif
# if defined(_UNICODE) && !defined(UNICODE)
-# define UNICODE
+# error "_UNICODE is defined but UNICODE is not defined"
+# endif
+/*
+ * Don't include unneeded stuff in Windows headers to avoid compiler
+ * warnings and macro clashes.
+ * Make sure to define this macro before including any Windows headers.
+ */
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# ifndef NOGDI
+# define NOGDI
# endif
# include <winerror.h>
# include <windows.h>
diff --git a/contrib/libs/curl/lib/smb.c b/contrib/libs/curl/lib/smb.c
index 039d680041..a62e858143 100644
--- a/contrib/libs/curl/lib/smb.c
+++ b/contrib/libs/curl/lib/smb.c
@@ -34,7 +34,7 @@
#include <process.h>
#ifdef CURL_WINDOWS_APP
#define getpid GetCurrentProcessId
-#elif !defined(MSDOS)
+#elif defined(WIN32)
#define getpid _getpid
#endif
#endif
diff --git a/contrib/libs/curl/lib/socketpair.h b/contrib/libs/curl/lib/socketpair.h
index f91a3c6511..de70df673a 100644
--- a/contrib/libs/curl/lib/socketpair.h
+++ b/contrib/libs/curl/lib/socketpair.h
@@ -26,6 +26,8 @@
#include "curl_setup.h"
#ifndef HAVE_SOCKETPAIR
+#include <curl/curl.h>
+
int Curl_socketpair(int domain, int type, int protocol,
curl_socket_t socks[2]);
#else
diff --git a/contrib/libs/curl/lib/strcase.c b/contrib/libs/curl/lib/strcase.c
index f932485204..09d2a8a961 100644
--- a/contrib/libs/curl/lib/strcase.c
+++ b/contrib/libs/curl/lib/strcase.c
@@ -28,8 +28,6 @@
#include "strcase.h"
-static char raw_tolower(char in);
-
/* Mapping table to go from lowercase to uppercase for plain ASCII.*/
static const unsigned char touppermap[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
@@ -79,7 +77,7 @@ char Curl_raw_toupper(char in)
/* Portable, consistent tolower. Do not use tolower() because its behavior is
altered by the current locale. */
-static char raw_tolower(char in)
+char Curl_raw_tolower(char in)
{
return tolowermap[(unsigned char) in];
}
@@ -165,7 +163,7 @@ void Curl_strntolower(char *dest, const char *src, size_t n)
return;
do {
- *dest++ = raw_tolower(*src);
+ *dest++ = Curl_raw_tolower(*src);
} while(*src++ && --n);
}
@@ -179,6 +177,28 @@ bool Curl_safecmp(char *a, char *b)
return !a && !b;
}
+/*
+ * Curl_timestrcmp() returns 0 if the two strings are identical. The time this
+ * function spends is a function of the shortest string, not of the contents.
+ */
+int Curl_timestrcmp(const char *a, const char *b)
+{
+ int match = 0;
+ int i = 0;
+
+ if(a && b) {
+ while(1) {
+ match |= a[i]^b[i];
+ if(!a[i] || !b[i])
+ break;
+ i++;
+ }
+ }
+ else
+ return a || b;
+ return match;
+}
+
/* --- public functions --- */
int curl_strequal(const char *first, const char *second)
diff --git a/contrib/libs/curl/lib/strcase.h b/contrib/libs/curl/lib/strcase.h
index d245929227..65a575385d 100644
--- a/contrib/libs/curl/lib/strcase.h
+++ b/contrib/libs/curl/lib/strcase.h
@@ -43,6 +43,7 @@ int Curl_safe_strcasecompare(const char *first, const char *second);
int Curl_strncasecompare(const char *first, const char *second, size_t max);
char Curl_raw_toupper(char in);
+char Curl_raw_tolower(char in);
/* checkprefix() is a shorter version of the above, used when the first
argument is the string literal */
@@ -52,5 +53,6 @@ void Curl_strntoupper(char *dest, const char *src, size_t n);
void Curl_strntolower(char *dest, const char *src, size_t n);
bool Curl_safecmp(char *a, char *b);
+int Curl_timestrcmp(const char *first, const char *second);
#endif /* HEADER_CURL_STRCASE_H */
diff --git a/contrib/libs/curl/lib/strerror.c b/contrib/libs/curl/lib/strerror.c
index 02f8986d18..4889097775 100644
--- a/contrib/libs/curl/lib/strerror.c
+++ b/contrib/libs/curl/lib/strerror.c
@@ -476,7 +476,7 @@ curl_url_strerror(CURLUcode error)
return "Port number was not a decimal number between 0 and 65535";
case CURLUE_UNSUPPORTED_SCHEME:
- return "This libcurl build doesn't support the given URL scheme";
+ return "Unsupported URL scheme";
case CURLUE_URLDECODE:
return "URL decode error, most likely because of rubbish in the input";
@@ -530,7 +530,7 @@ curl_url_strerror(CURLUcode error)
return "Bad file:// URL";
case CURLUE_BAD_SLASHES:
- return "Unsupported number of slashes";
+ return "Unsupported number of slashes following scheme";
case CURLUE_BAD_SCHEME:
return "Bad scheme";
diff --git a/contrib/libs/curl/lib/strtoofft.c b/contrib/libs/curl/lib/strtoofft.c
index 30908fdd92..30deb8c05b 100644
--- a/contrib/libs/curl/lib/strtoofft.c
+++ b/contrib/libs/curl/lib/strtoofft.c
@@ -87,7 +87,7 @@ static curl_off_t strtooff(const char *nptr, char **endptr, int base)
/* Skip leading whitespace. */
end = (char *)nptr;
- while(ISSPACE(end[0])) {
+ while(ISBLANK(end[0])) {
end++;
}
@@ -222,9 +222,9 @@ CURLofft curlx_strtoofft(const char *str, char **endp, int base,
errno = 0;
*num = 0; /* clear by default */
- while(*str && ISSPACE(*str))
+ while(*str && ISBLANK(*str))
str++;
- if('-' == *str) {
+ if(('-' == *str) || (ISSPACE(*str))) {
if(endp)
*endp = (char *)str; /* didn't actually move */
return CURL_OFFT_INVAL; /* nothing parsed */
diff --git a/contrib/libs/curl/lib/timediff.c b/contrib/libs/curl/lib/timediff.c
index 27fd911638..c5893187dd 100644
--- a/contrib/libs/curl/lib/timediff.c
+++ b/contrib/libs/curl/lib/timediff.c
@@ -24,6 +24,8 @@
#include "timediff.h"
+#include <limits.h>
+
/*
* Converts number of milliseconds into a timeval structure.
*
diff --git a/contrib/libs/curl/lib/transfer.c b/contrib/libs/curl/lib/transfer.c
index 6560d9607d..441da73429 100644
--- a/contrib/libs/curl/lib/transfer.c
+++ b/contrib/libs/curl/lib/transfer.c
@@ -1439,6 +1439,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
if(result)
return result;
+ data->state.requests = 0;
data->state.followlocation = 0; /* reset the location-follow counter */
data->state.this_is_a_follow = FALSE; /* reset this */
data->state.errorbuf = FALSE; /* no error has occurred */
@@ -1636,7 +1637,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
if((type != FOLLOW_RETRY) &&
(data->req.httpcode != 401) && (data->req.httpcode != 407) &&
- Curl_is_absolute_url(newurl, NULL, 0))
+ Curl_is_absolute_url(newurl, NULL, 0, FALSE))
/* If this is not redirect due to a 401 or 407 response and an absolute
URL: don't allow a custom port number */
disallowport = TRUE;
@@ -1648,8 +1649,11 @@ CURLcode Curl_follow(struct Curl_easy *data,
CURLU_ALLOW_SPACE |
(data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
if(uc) {
- if(type != FOLLOW_FAKE)
+ if(type != FOLLOW_FAKE) {
+ failf(data, "The redirect target URL could not be parsed: %s",
+ curl_url_strerror(uc));
return Curl_uc_to_curlcode(uc);
+ }
/* the URL could not be parsed for some reason, but since this is FAKE
mode, just duplicate the field as-is */
@@ -1696,7 +1700,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
return Curl_uc_to_curlcode(uc);
}
- p = Curl_builtin_scheme(scheme);
+ p = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
if(p && (p->protocol != data->info.conn_protocol)) {
infof(data, "Clear auth, redirects scheme from %s to %s",
data->info.conn_scheme, scheme);
diff --git a/contrib/libs/curl/lib/url.c b/contrib/libs/curl/lib/url.c
index ec3fb77b01..7b6d694449 100644
--- a/contrib/libs/curl/lib/url.c
+++ b/contrib/libs/curl/lib/url.c
@@ -73,8 +73,8 @@
#endif
#elif defined(USE_WIN32_IDN)
-/* prototype for curl_win32_idn_to_ascii() */
-bool curl_win32_idn_to_ascii(const char *in, char **out);
+/* prototype for Curl_win32_idn_to_ascii() */
+bool Curl_win32_idn_to_ascii(const char *in, char **out);
#endif /* USE_LIBIDN2 */
#include "doh.h"
@@ -106,6 +106,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "urlapi-int.h"
#include "system_win32.h"
#include "hsts.h"
+#include "noproxy.h"
/* And now for the protocols */
#include "ftp.h"
@@ -128,7 +129,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "http_proxy.h"
#include "conncache.h"
#include "multihandle.h"
-#include "dotdot.h"
#include "strdup.h"
#include "setopt.h"
#include "altsvc.h"
@@ -168,7 +168,7 @@ static void conn_free(struct connectdata *conn);
*
* Returns the family as a single bit protocol identifier.
*/
-static unsigned int get_protocol_family(const struct Curl_handler *h)
+static curl_prot_t get_protocol_family(const struct Curl_handler *h)
{
DEBUGASSERT(h);
DEBUGASSERT(h->family);
@@ -192,6 +192,16 @@ static const struct Curl_handler * const protocols[] = {
&Curl_handler_http,
#endif
+#ifdef USE_WEBSOCKETS
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_wss,
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+ &Curl_handler_ws,
+#endif
+#endif
+
#ifndef CURL_DISABLE_FTP
&Curl_handler_ftp,
#endif
@@ -568,11 +578,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->new_file_perms = 0644; /* Default permissions */
set->new_directory_perms = 0755; /* Default permissions */
-
- /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
- define since we internally only use the lower 16 bits for the passed
- in bitmask to not conflict with the private bits */
- set->allowed_protocols = (unsigned int)CURLPROTO_ALL;
+ set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP |
CURLPROTO_FTPS;
@@ -623,7 +629,6 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->tcp_keepidle = 60;
set->tcp_fastopen = FALSE;
set->tcp_nodelay = TRUE;
- set->ssl_enable_npn = TRUE;
set->ssl_enable_alpn = TRUE;
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */
@@ -746,15 +751,6 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
DEBUGASSERT(data);
infof(data, "Closing connection %ld", conn->connection_id);
-#ifndef USE_HYPER
- if(conn->connect_state && conn->connect_state->prot_save) {
- /* If this was closed with a CONNECT in progress, cleanup this temporary
- struct arrangement */
- data->req.p.http = NULL;
- Curl_safefree(conn->connect_state->prot_save);
- }
-#endif
-
/* possible left-overs from the async name resolvers */
Curl_resolver_cancel(data);
@@ -869,7 +865,7 @@ void Curl_disconnect(struct Curl_easy *data,
/* Cleanup NEGOTIATE connection-related data */
Curl_http_auth_cleanup_negotiate(conn);
- if(conn->bits.connect_only)
+ if(conn->connect_only)
/* treat the connection as dead in CONNECT_ONLY situations */
dead_connection = TRUE;
@@ -953,19 +949,11 @@ socks_proxy_info_matches(const struct proxy_info *data,
/* the user information is case-sensitive
or at least it is not defined as case-insensitive
see https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1 */
- if(!data->user != !needle->user)
- return FALSE;
- /* curl_strequal does a case insentive comparison, so do not use it here! */
- if(data->user &&
- needle->user &&
- strcmp(data->user, needle->user) != 0)
- return FALSE;
- if(!data->passwd != !needle->passwd)
- return FALSE;
- /* curl_strequal does a case insentive comparison, so do not use it here! */
- if(data->passwd &&
- needle->passwd &&
- strcmp(data->passwd, needle->passwd) != 0)
+
+ /* curl_strequal does a case insensitive comparison,
+ so do not use it here! */
+ if(Curl_timestrcmp(data->user, needle->user) ||
+ Curl_timestrcmp(data->passwd, needle->passwd))
return FALSE;
return TRUE;
}
@@ -1215,7 +1203,7 @@ ConnectionExists(struct Curl_easy *data,
check = curr->ptr;
curr = curr->next;
- if(check->bits.connect_only || check->bits.close)
+ if(check->connect_only || check->bits.close)
/* connect-only or to-be-closed connections will not be reused */
continue;
@@ -1367,10 +1355,10 @@ ConnectionExists(struct Curl_easy *data,
if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
/* This protocol requires credentials per connection,
so verify that we're using the same name and password as well */
- if(strcmp(needle->user, check->user) ||
- strcmp(needle->passwd, check->passwd) ||
- !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) ||
- !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd) ||
+ Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
+ Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
/* one of them was different */
continue;
}
@@ -1446,8 +1434,8 @@ ConnectionExists(struct Curl_easy *data,
possible. (Especially we must not reuse the same connection if
partway through a handshake!) */
if(wantNTLMhttp) {
- if(strcmp(needle->user, check->user) ||
- strcmp(needle->passwd, check->passwd)) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd)) {
/* we prefer a credential match, but this is at least a connection
that can be reused and "upgraded" to NTLM */
@@ -1469,8 +1457,10 @@ ConnectionExists(struct Curl_easy *data,
if(!check->http_proxy.user || !check->http_proxy.passwd)
continue;
- if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
- strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
+ if(Curl_timestrcmp(needle->http_proxy.user,
+ check->http_proxy.user) ||
+ Curl_timestrcmp(needle->http_proxy.passwd,
+ check->http_proxy.passwd))
continue;
}
else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
@@ -1642,7 +1632,7 @@ CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
#elif defined(USE_WIN32_IDN)
char *ace_hostname = NULL;
- if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
+ if(Curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
host->encalloc = ace_hostname;
/* change the name pointer to point to the encoded hostname */
host->name = host->encalloc;
@@ -1673,7 +1663,7 @@ void Curl_free_idnconverted_hostname(struct hostname *host)
}
#elif defined(USE_WIN32_IDN)
free(host->encalloc); /* must be freed with free() since this was
- allocated by curl_win32_idn_to_ascii */
+ allocated by Curl_win32_idn_to_ascii */
host->encalloc = NULL;
#else
(void)host;
@@ -1799,7 +1789,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
#endif
conn->ip_version = data->set.ipver;
- conn->bits.connect_only = data->set.connect_only;
+ conn->connect_only = data->set.connect_only;
conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
@@ -1843,15 +1833,18 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
}
/* returns the handler if the given scheme is built-in */
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
+ size_t schemelen)
{
const struct Curl_handler * const *pp;
const struct Curl_handler *p;
/* Scan protocol handler table and match against 'scheme'. The handler may
be changed later when the protocol specific setup function is called. */
+ if(schemelen == CURL_ZERO_TERMINATED)
+ schemelen = strlen(scheme);
for(pp = protocols; (p = *pp) != NULL; pp++)
- if(strcasecompare(p->scheme, scheme))
- /* Protocol found in table. Check if allowed */
+ if(strncasecompare(p->scheme, scheme, schemelen) && !p->scheme[schemelen])
+ /* Protocol found in table. */
return p;
return NULL; /* not found */
}
@@ -1861,7 +1854,8 @@ static CURLcode findprotocol(struct Curl_easy *data,
struct connectdata *conn,
const char *protostr)
{
- const struct Curl_handler *p = Curl_builtin_scheme(protostr);
+ const struct Curl_handler *p = Curl_builtin_scheme(protostr,
+ CURL_ZERO_TERMINATED);
if(p && /* Protocol found in table. Check if allowed */
(data->set.allowed_protocols & p->protocol)) {
@@ -1985,7 +1979,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
- !Curl_is_absolute_url(data->state.url, NULL, 0)) {
+ !Curl_is_absolute_url(data->state.url, NULL, 0, TRUE)) {
char *url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
data->state.url);
if(!url)
@@ -2033,10 +2027,56 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
failf(data, "Too long host name (maximum is %d)", MAX_URL_LEN);
return CURLE_URL_MALFORMAT;
}
+ hostname = data->state.up.hostname;
+
+ if(hostname && hostname[0] == '[') {
+ /* This looks like an IPv6 address literal. See if there is an address
+ scope. */
+ size_t hlen;
+ conn->bits.ipv6_ip = TRUE;
+ /* cut off the brackets! */
+ hostname++;
+ hlen = strlen(hostname);
+ hostname[hlen - 1] = 0;
+
+ zonefrom_url(uh, data, conn);
+ }
+
+ /* make sure the connect struct gets its own copy of the host name */
+ conn->host.rawalloc = strdup(hostname ? hostname : "");
+ if(!conn->host.rawalloc)
+ return CURLE_OUT_OF_MEMORY;
+ conn->host.name = conn->host.rawalloc;
+
+ /*************************************************************
+ * IDN-convert the hostnames
+ *************************************************************/
+ result = Curl_idnconvert_hostname(data, &conn->host);
+ if(result)
+ return result;
+ if(conn->bits.conn_to_host) {
+ result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
+ if(result)
+ return result;
+ }
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.httpproxy) {
+ result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
+ if(result)
+ return result;
+ }
+ if(conn->bits.socksproxy) {
+ result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
+ if(result)
+ return result;
+ }
+#endif
#ifndef CURL_DISABLE_HSTS
+ /* HSTS upgrade */
if(data->hsts && strcasecompare("http", data->state.up.scheme)) {
- if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) {
+ /* This MUST use the IDN decoded name */
+ if(Curl_hsts(data->hsts, conn->host.name, TRUE)) {
char *url;
Curl_safefree(data->state.up.scheme);
uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0);
@@ -2087,7 +2127,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return Curl_uc_to_curlcode(uc);
}
- if(!data->state.aptr.user) {
+ if(!data->set.str[STRING_USERNAME]) {
/* we don't use the URL API's URL decoder option here since it rejects
control codes and we want to allow them for some schemes in the user
and password fields */
@@ -2142,26 +2182,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
(void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
- hostname = data->state.up.hostname;
- if(hostname && hostname[0] == '[') {
- /* This looks like an IPv6 address literal. See if there is an address
- scope. */
- size_t hlen;
- conn->bits.ipv6_ip = TRUE;
- /* cut off the brackets! */
- hostname++;
- hlen = strlen(hostname);
- hostname[hlen - 1] = 0;
-
- zonefrom_url(uh, data, conn);
- }
-
- /* make sure the connect struct gets its own copy of the host name */
- conn->host.rawalloc = strdup(hostname ? hostname : "");
- if(!conn->host.rawalloc)
- return CURLE_OUT_OF_MEMORY;
- conn->host.name = conn->host.rawalloc;
-
#ifdef ENABLE_IPV6
if(data->set.scope_id)
/* Override any scope that was set above. */
@@ -2259,83 +2279,6 @@ void Curl_free_request_state(struct Curl_easy *data)
#ifndef CURL_DISABLE_PROXY
-/****************************************************************
-* Checks if the host is in the noproxy list. returns true if it matches
-* and therefore the proxy should NOT be used.
-****************************************************************/
-static bool check_noproxy(const char *name, const char *no_proxy)
-{
- /* no_proxy=domain1.dom,host.domain2.dom
- * (a comma-separated list of hosts which should
- * not be proxied, or an asterisk to override
- * all proxy variables)
- */
- if(no_proxy && no_proxy[0]) {
- size_t tok_start;
- size_t tok_end;
- const char *separator = ", ";
- size_t no_proxy_len;
- size_t namelen;
- char *endptr;
- if(strcasecompare("*", no_proxy)) {
- return TRUE;
- }
-
- /* NO_PROXY was specified and it wasn't just an asterisk */
-
- no_proxy_len = strlen(no_proxy);
- if(name[0] == '[') {
- /* IPv6 numerical address */
- endptr = strchr(name, ']');
- if(!endptr)
- return FALSE;
- name++;
- namelen = endptr - name;
- }
- else
- namelen = strlen(name);
-
- for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
- while(tok_start < no_proxy_len &&
- strchr(separator, no_proxy[tok_start]) != NULL) {
- /* Look for the beginning of the token. */
- ++tok_start;
- }
-
- if(tok_start == no_proxy_len)
- break; /* It was all trailing separator chars, no more tokens. */
-
- for(tok_end = tok_start; tok_end < no_proxy_len &&
- strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
- /* Look for the end of the token. */
- ;
-
- /* To match previous behavior, where it was necessary to specify
- * ".local.com" to prevent matching "notlocal.com", we will leave
- * the '.' off.
- */
- if(no_proxy[tok_start] == '.')
- ++tok_start;
-
- if((tok_end - tok_start) <= namelen) {
- /* Match the last part of the name to the domain we are checking. */
- const char *checkn = name + namelen - (tok_end - tok_start);
- if(strncasecompare(no_proxy + tok_start, checkn,
- tok_end - tok_start)) {
- if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
- /* We either have an exact match, or the previous character is a .
- * so it is within the same domain, so no proxy for this host.
- */
- return TRUE;
- }
- }
- } /* if((tok_end - tok_start) <= namelen) */
- } /* for(tok_start = 0; tok_start < no_proxy_len;
- tok_start = tok_end + 1) */
- } /* NO_PROXY was specified and it wasn't just an asterisk */
-
- return FALSE;
-}
#ifndef CURL_DISABLE_HTTP
/****************************************************************
@@ -2375,7 +2318,7 @@ static char *detect_proxy(struct Curl_easy *data,
/* Now, build <protocol>_proxy and check for such a one to use */
while(*protop)
- *envp++ = (char)tolower((int)*protop++);
+ *envp++ = Curl_raw_tolower(*protop++);
/* append _proxy */
strcpy(envp, "_proxy");
@@ -2704,8 +2647,8 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
}
}
- if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
- data->set.str[STRING_NOPROXY] : no_proxy)) {
+ if(Curl_check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
+ data->set.str[STRING_NOPROXY] : no_proxy)) {
Curl_safefree(proxy);
Curl_safefree(socksproxy);
}
@@ -2902,15 +2845,15 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
(psep && psep > osep ? (size_t)(psep - osep) :
(size_t)(login + len - osep)) - 1 : 0);
- /* Allocate the user portion buffer */
- if(userp && ulen) {
+ /* Allocate the user portion buffer, which can be zero length */
+ if(userp) {
ubuf = malloc(ulen + 1);
if(!ubuf)
result = CURLE_OUT_OF_MEMORY;
}
/* Allocate the password portion buffer */
- if(!result && passwdp && plen) {
+ if(!result && passwdp && psep) {
pbuf = malloc(plen + 1);
if(!pbuf) {
free(ubuf);
@@ -2995,14 +2938,6 @@ static CURLcode override_login(struct Curl_easy *data,
char **passwdp = &conn->passwd;
char **optionsp = &conn->options;
-#ifndef CURL_DISABLE_NETRC
- if(data->set.use_netrc == CURL_NETRC_REQUIRED && data->state.aptr.user) {
- Curl_safefree(*userp);
- Curl_safefree(*passwdp);
- Curl_safefree(data->state.aptr.user); /* disable user+password */
- }
-#endif
-
if(data->set.str[STRING_OPTIONS]) {
free(*optionsp);
*optionsp = strdup(data->set.str[STRING_OPTIONS]);
@@ -3011,22 +2946,23 @@ static CURLcode override_login(struct Curl_easy *data,
}
#ifndef CURL_DISABLE_NETRC
+ if(data->set.use_netrc == CURL_NETRC_REQUIRED) {
+ Curl_safefree(*userp);
+ Curl_safefree(*passwdp);
+ }
conn->bits.netrc = FALSE;
if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
- bool netrc_user_changed = FALSE;
- bool netrc_passwd_changed = FALSE;
int ret;
bool url_provided = FALSE;
- if(data->state.up.user) {
- /* there was a user name in the URL */
- userp = &data->state.up.user;
+ if(data->state.aptr.user) {
+ /* there was a user name in the URL. Use the URL decoded version */
+ userp = &data->state.aptr.user;
url_provided = TRUE;
}
ret = Curl_parsenetrc(conn->host.name,
userp, passwdp,
- &netrc_user_changed, &netrc_passwd_changed,
data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
infof(data, "Couldn't find host %s in the %s file; using defaults",
@@ -3059,9 +2995,13 @@ static CURLcode override_login(struct Curl_easy *data,
/* for updated strings, we update them in the URL */
if(*userp) {
- CURLcode result = Curl_setstropt(&data->state.aptr.user, *userp);
- if(result)
- return result;
+ CURLcode result;
+ if(data->state.aptr.user != *userp) {
+ /* nothing to do then */
+ result = Curl_setstropt(&data->state.aptr.user, *userp);
+ if(result)
+ return result;
+ }
}
if(data->state.aptr.user) {
uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user,
@@ -3493,9 +3433,9 @@ static CURLcode resolve_proxy(struct Curl_easy *data,
}
#endif
-static CURLcode resolve_ip(struct Curl_easy *data,
- struct connectdata *conn,
- bool *async)
+static CURLcode resolve_host(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *async)
{
struct Curl_dns_entry *hostaddr = NULL;
struct hostname *connhost;
@@ -3561,7 +3501,7 @@ static CURLcode resolve_fresh(struct Curl_easy *data,
return resolve_proxy(data, conn, async);
#endif
- return resolve_ip(data, conn, async);
+ return resolve_host(data, conn, async);
}
/*************************************************************
@@ -3790,29 +3730,6 @@ static CURLcode create_conn(struct Curl_easy *data,
if(result)
goto out;
- /*************************************************************
- * IDN-convert the hostnames
- *************************************************************/
- result = Curl_idnconvert_hostname(data, &conn->host);
- if(result)
- goto out;
- if(conn->bits.conn_to_host) {
- result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
- if(result)
- goto out;
- }
-#ifndef CURL_DISABLE_PROXY
- if(conn->bits.httpproxy) {
- result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
- if(result)
- goto out;
- }
- if(conn->bits.socksproxy) {
- result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
- if(result)
- goto out;
- }
-#endif
/*************************************************************
* Check whether the host and the "connect to host" are equal.
@@ -4025,13 +3942,11 @@ static CURLcode create_conn(struct Curl_easy *data,
be able to do that if we have reached the limit of how many
connections we are allowed to open. */
- if(conn->handler->flags & PROTOPT_ALPN_NPN) {
+ if(conn->handler->flags & PROTOPT_ALPN) {
/* The protocol wants it, so set the bits if enabled in the easy handle
(default) */
if(data->set.ssl_enable_alpn)
conn->bits.tls_enable_alpn = TRUE;
- if(data->set.ssl_enable_npn)
- conn->bits.tls_enable_npn = TRUE;
}
if(waitpipe)
diff --git a/contrib/libs/curl/lib/url.h b/contrib/libs/curl/lib/url.h
index e3b2940305..ba4270d523 100644
--- a/contrib/libs/curl/lib/url.h
+++ b/contrib/libs/curl/lib/url.h
@@ -46,7 +46,8 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme);
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
+ size_t schemelen);
bool Curl_is_ASCII_name(const char *hostname);
CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
diff --git a/contrib/libs/curl/lib/urlapi-int.h b/contrib/libs/curl/lib/urlapi-int.h
index a03aa888af..43a83ef6e4 100644
--- a/contrib/libs/curl/lib/urlapi-int.h
+++ b/contrib/libs/curl/lib/urlapi-int.h
@@ -25,10 +25,12 @@
***************************************************************************/
#include "curl_setup.h"
-bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen);
+size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
+ bool guess_scheme);
#ifdef DEBUGBUILD
-CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname, bool);
+CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
+ bool has_scheme);
#endif
#endif /* HEADER_CURL_URLAPI_INT_H */
diff --git a/contrib/libs/curl/lib/urlapi.c b/contrib/libs/curl/lib/urlapi.c
index dee4b5aa09..7dac81c85c 100644
--- a/contrib/libs/curl/lib/urlapi.c
+++ b/contrib/libs/curl/lib/urlapi.c
@@ -27,12 +27,12 @@
#include "urldata.h"
#include "urlapi-int.h"
#include "strcase.h"
-#include "dotdot.h"
#include "url.h"
#include "escape.h"
#include "curl_ctype.h"
#include "inet_pton.h"
#include "inet_ntop.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -68,9 +68,6 @@ struct Curl_URL {
char *path;
char *query;
char *fragment;
-
- char *scratch; /* temporary scratch area */
- char *temppath; /* temporary path pointer */
long portnum; /* the numerical version */
};
@@ -88,8 +85,6 @@ static void free_urlhandle(struct Curl_URL *u)
free(u->path);
free(u->query);
free(u->fragment);
- free(u->scratch);
- free(u->temppath);
}
/*
@@ -121,95 +116,50 @@ static const char *find_host_sep(const char *url)
}
/*
- * Decide in an encoding-independent manner whether a character in an
- * URL must be escaped. The same criterion must be used in strlen_url()
- * and strcpy_url().
+ * Decide in an encoding-independent manner whether a character in a URL must
+ * be escaped. This is used in urlencode_str().
*/
static bool urlchar_needs_escaping(int c)
{
return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c));
}
-/*
- * strlen_url() returns the length of the given URL if the spaces within the
- * URL were properly URL encoded.
- * URL encoding should be skipped for host names, otherwise IDN resolution
- * will fail.
- */
-static size_t strlen_url(const char *url, bool relative)
-{
- const unsigned char *ptr;
- size_t newlen = 0;
- bool left = TRUE; /* left side of the ? */
- const unsigned char *host_sep = (const unsigned char *) url;
-
- if(!relative)
- host_sep = (const unsigned char *) find_host_sep(url);
-
- for(ptr = (unsigned char *)url; *ptr; ptr++) {
-
- if(ptr < host_sep) {
- ++newlen;
- continue;
- }
-
- if(*ptr == ' ') {
- if(left)
- newlen += 3;
- else
- newlen++;
- continue;
- }
-
- if (*ptr == '?')
- left = FALSE;
-
- if(urlchar_needs_escaping(*ptr))
- newlen += 2;
-
- newlen++;
- }
-
- return newlen;
-}
-
-/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in
- * the source URL accordingly.
+/* urlencode_str() writes data into an output dynbuf and URL-encodes the
+ * spaces in the source URL accordingly.
+ *
* URL encoding should be skipped for host names, otherwise IDN resolution
* will fail.
- *
- * Returns TRUE if something was updated.
*/
-static bool strcpy_url(char *output, const char *url, bool relative)
+static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
+ size_t len, bool relative,
+ bool query)
{
/* we must add this with whitespace-replacing */
- bool left = TRUE;
+ bool left = !query;
const unsigned char *iptr;
- char *optr = output;
const unsigned char *host_sep = (const unsigned char *) url;
- bool changed = FALSE;
if(!relative)
host_sep = (const unsigned char *) find_host_sep(url);
for(iptr = (unsigned char *)url; /* read from here */
- *iptr; /* until zero byte */
- iptr++) {
+ len; iptr++, len--) {
if(iptr < host_sep) {
- *optr++ = *iptr;
+ if(Curl_dyn_addn(o, iptr, 1))
+ return CURLUE_OUT_OF_MEMORY;
continue;
}
if(*iptr == ' ') {
if(left) {
- *optr++='%'; /* add a '%' */
- *optr++='2'; /* add a '2' */
- *optr++='0'; /* add a '0' */
+ if(Curl_dyn_addn(o, "%20", 3))
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ else {
+ if(Curl_dyn_addn(o, "+", 1))
+ return CURLUE_OUT_OF_MEMORY;
}
- else
- *optr++='+'; /* add a '+' here */
- changed = TRUE;
continue;
}
@@ -217,24 +167,28 @@ static bool strcpy_url(char *output, const char *url, bool relative)
left = FALSE;
if(urlchar_needs_escaping(*iptr)) {
- msnprintf(optr, 4, "%%%02x", *iptr);
- changed = TRUE;
- optr += 3;
+ if(Curl_dyn_addf(o, "%%%02x", *iptr))
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ else {
+ if(Curl_dyn_addn(o, iptr, 1))
+ return CURLUE_OUT_OF_MEMORY;
}
- else
- *optr++ = *iptr;
}
- *optr = 0; /* null-terminate output buffer */
- return changed;
+ return CURLUE_OK;
}
/*
- * Returns true if the given URL is absolute (as opposed to relative). Returns
- * the scheme in the buffer if TRUE and 'buf' is non-NULL. The buflen must
- * be larger than MAX_SCHEME_LEN if buf is set.
+ * Returns the length of the scheme if the given URL is absolute (as opposed
+ * to relative). Stores the scheme in the buffer if TRUE and 'buf' is
+ * non-NULL. The buflen must be larger than MAX_SCHEME_LEN if buf is set.
+ *
+ * If 'guess_scheme' is TRUE, it means the URL might be provided without
+ * scheme.
*/
-bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
+size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
+ bool guess_scheme)
{
int i;
DEBUGASSERT(!buf || (buflen > MAX_SCHEME_LEN));
@@ -242,8 +196,8 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
if(buf)
buf[0] = 0; /* always leave a defined value in buf */
#ifdef WIN32
- if(STARTS_WITH_DRIVE_PREFIX(url))
- return FALSE;
+ if(guess_scheme && STARTS_WITH_DRIVE_PREFIX(url))
+ return 0;
#endif
for(i = 0; i < MAX_SCHEME_LEN; ++i) {
char s = url[i];
@@ -256,16 +210,22 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
break;
}
}
- if(i && (url[i] == ':') && (url[i + 1] == '/')) {
+ if(i && (url[i] == ':') && ((url[i + 1] == '/') || !guess_scheme)) {
+ /* If this does not guess scheme, the scheme always ends with the colon so
+ that this also detects data: URLs etc. In guessing mode, data: could
+ be the host name "data" with a specified port number. */
+
+ /* the length of the scheme is the name part only */
+ size_t len = i;
if(buf) {
buf[i] = 0;
while(i--) {
- buf[i] = (char)TOLOWER(url[i]);
+ buf[i] = Curl_raw_tolower(url[i]);
}
}
- return TRUE;
+ return len;
}
- return FALSE;
+ return 0;
}
/*
@@ -273,34 +233,26 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
* URL-encodes any spaces.
* The returned pointer must be freed by the caller unless NULL
* (returns NULL on out of memory).
+ *
+ * Note that this function destroys the 'base' string.
*/
-static char *concat_url(const char *base, const char *relurl)
+static char *concat_url(char *base, const char *relurl)
{
/***
TRY to append this new path to the old URL
to the right of the host part. Oh crap, this is doomed to cause
problems in the future...
*/
- char *newest;
+ struct dynbuf newest;
char *protsep;
char *pathsep;
- size_t newlen;
bool host_changed = FALSE;
-
const char *useurl = relurl;
- size_t urllen;
-
- /* we must make our own copy of the URL to play with, as it may
- point to read-only data */
- char *url_clone = strdup(base);
-
- if(!url_clone)
- return NULL; /* skip out of this NOW */
/* protsep points to the start of the host name */
- protsep = strstr(url_clone, "//");
+ protsep = strstr(base, "//");
if(!protsep)
- protsep = url_clone;
+ protsep = base;
else
protsep += 2; /* pass the slashes */
@@ -393,38 +345,24 @@ static char *concat_url(const char *base, const char *relurl)
}
}
- /* If the new part contains a space, this is a mighty stupid redirect
- but we still make an effort to do "right". To the left of a '?'
- letter we replace each space with %20 while it is replaced with '+'
- on the right side of the '?' letter.
- */
- newlen = strlen_url(useurl, !host_changed);
-
- urllen = strlen(url_clone);
-
- newest = malloc(urllen + 1 + /* possible slash */
- newlen + 1 /* zero byte */);
-
- if(!newest) {
- free(url_clone); /* don't leak this */
- return NULL;
- }
+ Curl_dyn_init(&newest, CURL_MAX_INPUT_LENGTH);
/* copy over the root url part */
- memcpy(newest, url_clone, urllen);
+ if(Curl_dyn_add(&newest, base))
+ return NULL;
/* check if we need to append a slash */
if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
;
- else
- newest[urllen++]='/';
+ else {
+ if(Curl_dyn_addn(&newest, "/", 1))
+ return NULL;
+ }
/* then append the new piece on the right side */
- strcpy_url(&newest[urllen], useurl, !host_changed);
+ urlencode_str(&newest, useurl, strlen(useurl), !host_changed, FALSE);
- free(url_clone);
-
- return newest;
+ return Curl_dyn_ptr(&newest);
}
/* scan for byte values < 31 or 127 */
@@ -458,7 +396,7 @@ static bool junkscan(const char *part, unsigned int flags)
*
*/
static CURLUcode parse_hostname_login(struct Curl_URL *u,
- char **hostname,
+ struct dynbuf *host,
unsigned int flags)
{
CURLUcode result = CURLUE_OK;
@@ -468,27 +406,31 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
char *optionsp = NULL;
const struct Curl_handler *h = NULL;
- /* At this point, we're hoping all the other special cases have
- * been taken care of, so conn->host.name is at most
- * [user[:password][;options]]@]hostname
+ /* At this point, we assume all the other special cases have been taken
+ * care of, so the host is at most
+ *
+ * [user[:password][;options]]@]hostname
*
* We need somewhere to put the embedded details, so do that first.
*/
- char *ptr = strchr(*hostname, '@');
- char *login = *hostname;
+ char *login = Curl_dyn_ptr(host);
+ char *ptr;
+
+ DEBUGASSERT(login);
+ ptr = strchr(login, '@');
if(!ptr)
goto out;
/* We will now try to extract the
* possible login information in a string like:
* ftp://user:password@ftp.my.site:8021/README */
- *hostname = ++ptr;
+ ptr++;
/* if this is a known scheme, get some details */
if(u->scheme)
- h = Curl_builtin_scheme(u->scheme);
+ h = Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
/* We could use the login information in the URL so extract it. Only parse
options if the handler says we should. Note that 'h' might be NULL! */
@@ -530,6 +472,10 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
u->options = optionsp;
}
+ /* move the name to the start of the host buffer */
+ if(Curl_dyn_tail(host, strlen(ptr)))
+ return CURLUE_OUT_OF_MEMORY;
+
return CURLUE_OK;
out:
@@ -543,13 +489,13 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
return result;
}
-UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
+UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
bool has_scheme)
{
char *portptr = NULL;
char endbracket;
int len;
-
+ char *hostname = Curl_dyn_ptr(host);
/*
* Find the end of an IPv6 address, either on the ']' ending bracket or
* a percent-encoded zone index.
@@ -586,6 +532,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
char *rest;
long port;
char portbuf[7];
+ size_t keep = portptr - hostname;
/* Browser behavior adaptation. If there's a colon with no digits after,
just cut off the name there which makes us ignore the colon and just
@@ -594,15 +541,15 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
Don't do it if the URL has no scheme, to make something that looks like
a scheme not work!
*/
- if(!portptr[1]) {
- *portptr = '\0';
+ Curl_dyn_setlen(host, keep);
+ portptr++;
+ if(!*portptr)
return has_scheme ? CURLUE_OK : CURLUE_BAD_PORT_NUMBER;
- }
- if(!ISDIGIT(portptr[1]))
+ if(!ISDIGIT(*portptr))
return CURLUE_BAD_PORT_NUMBER;
- port = strtol(portptr + 1, &rest, 10); /* Port number must be decimal */
+ port = strtol(portptr, &rest, 10); /* Port number must be decimal */
if(port > 0xffff)
return CURLUE_BAD_PORT_NUMBER;
@@ -610,7 +557,6 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
if(rest[0])
return CURLUE_BAD_PORT_NUMBER;
- *portptr++ = '\0'; /* cut off the name there */
*rest = 0;
/* generate a new port number string to get rid of leading zeroes etc */
msnprintf(portbuf, sizeof(portbuf), "%ld", port);
@@ -623,12 +569,15 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
return CURLUE_OK;
}
-static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
+static CURLUcode hostname_check(struct Curl_URL *u, char *hostname,
+ size_t hlen) /* length of hostname */
{
size_t len;
- size_t hlen = strlen(hostname);
+ DEBUGASSERT(hostname);
- if(hostname[0] == '[') {
+ if(!hostname[0])
+ return CURLUE_NO_HOST;
+ else if(hostname[0] == '[') {
const char *l = "0123456789abcdefABCDEF:.";
if(hlen < 4) /* '[::]' is the shortest possible valid string */
return CURLUE_BAD_IPV6;
@@ -687,13 +636,11 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
}
else {
/* letters from the second string are not ok */
- len = strcspn(hostname, " \r\n\t/:#?!@");
+ len = strcspn(hostname, " \r\n\t/:#?!@{}[]\\$\'\"^`*<>=;,");
if(hlen != len)
/* hostname with bad content */
return CURLUE_BAD_HOSTNAME;
}
- if(!hostname[0])
- return CURLUE_NO_HOST;
return CURLUE_OK;
}
@@ -787,79 +734,230 @@ static bool ipv4_normalize(const char *hostname, char *outp, size_t olen)
return TRUE;
}
-/* return strdup'ed version in 'outp', possibly percent decoded */
-static CURLUcode decode_host(char *hostname, char **outp)
+/* if necessary, replace the host content with a URL decoded version */
+static CURLUcode decode_host(struct dynbuf *host)
{
char *per = NULL;
- if(hostname[0] != '[')
+ const char *hostname = Curl_dyn_ptr(host);
+ if(hostname[0] == '[')
/* only decode if not an ipv6 numerical */
- per = strchr(hostname, '%');
- if(!per) {
- *outp = strdup(hostname);
- if(!*outp)
- return CURLUE_OUT_OF_MEMORY;
- }
+ return CURLUE_OK;
+ per = strchr(hostname, '%');
+ if(!per)
+ /* nothing to decode */
+ return CURLUE_OK;
else {
- /* might be encoded */
+ /* encoded */
size_t dlen;
- CURLcode result = Curl_urldecode(hostname, 0, outp, &dlen, REJECT_CTRL);
+ char *decoded;
+ CURLcode result = Curl_urldecode(hostname, 0, &decoded, &dlen,
+ REJECT_CTRL);
if(result)
return CURLUE_BAD_HOSTNAME;
+ Curl_dyn_reset(host);
+ result = Curl_dyn_addn(host, decoded, dlen);
+ free(decoded);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
return CURLUE_OK;
}
-static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
+/*
+ * "Remove Dot Segments"
+ * https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4
+ */
+
+/*
+ * dedotdotify()
+ * @unittest: 1395
+ *
+ * This function gets a null-terminated path with dot and dotdot sequences
+ * passed in and strips them off according to the rules in RFC 3986 section
+ * 5.2.4.
+ *
+ * The function handles a query part ('?' + stuff) appended but it expects
+ * that fragments ('#' + stuff) have already been cut off.
+ *
+ * RETURNS
+ *
+ * an allocated dedotdotified output string
+ */
+UNITTEST char *dedotdotify(const char *input, size_t clen);
+UNITTEST char *dedotdotify(const char *input, size_t clen)
{
- char *path;
- bool path_alloced = FALSE;
+ char *out = malloc(clen + 1);
+ char *outptr;
+ const char *orginput = input;
+ char *queryp;
+ if(!out)
+ return NULL; /* out of memory */
+
+ *out = 0; /* null-terminates, for inputs like "./" */
+ outptr = out;
+
+ if(!*input)
+ /* zero length input string, return that */
+ return out;
+
+ /*
+ * To handle query-parts properly, we must find it and remove it during the
+ * dotdot-operation and then append it again at the end to the output
+ * string.
+ */
+ queryp = strchr(input, '?');
+
+ do {
+ bool dotdot = TRUE;
+ if(*input == '.') {
+ /* A. If the input buffer begins with a prefix of "../" or "./", then
+ remove that prefix from the input buffer; otherwise, */
+
+ if(!strncmp("./", input, 2)) {
+ input += 2;
+ clen -= 2;
+ }
+ else if(!strncmp("../", input, 3)) {
+ input += 3;
+ clen -= 3;
+ }
+ /* D. if the input buffer consists only of "." or "..", then remove
+ that from the input buffer; otherwise, */
+
+ else if(!strcmp(".", input) || !strcmp("..", input) ||
+ !strncmp(".?", input, 2) || !strncmp("..?", input, 3)) {
+ *out = 0;
+ break;
+ }
+ else
+ dotdot = FALSE;
+ }
+ else if(*input == '/') {
+ /* B. if the input buffer begins with a prefix of "/./" or "/.", where
+ "." is a complete path segment, then replace that prefix with "/" in
+ the input buffer; otherwise, */
+ if(!strncmp("/./", input, 3)) {
+ input += 2;
+ clen -= 2;
+ }
+ else if(!strcmp("/.", input) || !strncmp("/.?", input, 3)) {
+ *outptr++ = '/';
+ *outptr = 0;
+ break;
+ }
+
+ /* C. if the input buffer begins with a prefix of "/../" or "/..",
+ where ".." is a complete path segment, then replace that prefix with
+ "/" in the input buffer and remove the last segment and its
+ preceding "/" (if any) from the output buffer; otherwise, */
+
+ else if(!strncmp("/../", input, 4)) {
+ input += 3;
+ clen -= 3;
+ /* remove the last segment from the output buffer */
+ while(outptr > out) {
+ outptr--;
+ if(*outptr == '/')
+ break;
+ }
+ *outptr = 0; /* null-terminate where it stops */
+ }
+ else if(!strcmp("/..", input) || !strncmp("/..?", input, 4)) {
+ /* remove the last segment from the output buffer */
+ while(outptr > out) {
+ outptr--;
+ if(*outptr == '/')
+ break;
+ }
+ *outptr++ = '/';
+ *outptr = 0; /* null-terminate where it stops */
+ break;
+ }
+ else
+ dotdot = FALSE;
+ }
+ else
+ dotdot = FALSE;
+
+ if(!dotdot) {
+ /* E. move the first path segment in the input buffer to the end of
+ the output buffer, including the initial "/" character (if any) and
+ any subsequent characters up to, but not including, the next "/"
+ character or the end of the input buffer. */
+
+ do {
+ *outptr++ = *input++;
+ clen--;
+ } while(*input && (*input != '/') && (*input != '?'));
+ *outptr = 0;
+ }
+
+ /* continue until end of input string OR, if there is a terminating
+ query part, stop there */
+ } while(*input && (!queryp || (input < queryp)));
+
+ if(queryp) {
+ size_t qlen;
+ /* There was a query part, append that to the output. */
+ size_t oindex = queryp - orginput;
+ qlen = strlen(&orginput[oindex]);
+ memcpy(outptr, &orginput[oindex], qlen + 1); /* include zero byte */
+ }
+
+ return out;
+}
+
+static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
+{
+ const char *path;
+ size_t pathlen;
bool uncpath = FALSE;
- char *hostname;
char *query = NULL;
char *fragment = NULL;
- CURLUcode result;
- bool url_has_scheme = FALSE;
char schemebuf[MAX_SCHEME_LEN + 1];
const char *schemep = NULL;
size_t schemelen = 0;
size_t urllen;
+ CURLUcode result = CURLUE_OK;
+ size_t fraglen = 0;
+ struct dynbuf host;
DEBUGASSERT(url);
+ Curl_dyn_init(&host, CURL_MAX_INPUT_LENGTH);
+
/*************************************************************
* Parse the URL.
************************************************************/
/* allocate scratch area */
urllen = strlen(url);
- if(urllen > CURL_MAX_INPUT_LENGTH)
+ if(urllen > CURL_MAX_INPUT_LENGTH) {
/* excessive input length */
- return CURLUE_MALFORMED_INPUT;
-
- path = u->scratch = malloc(urllen * 2 + 2);
- if(!path)
- return CURLUE_OUT_OF_MEMORY;
-
- hostname = &path[urllen + 1];
- hostname[0] = 0;
-
- if(Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf))) {
- url_has_scheme = TRUE;
- schemelen = strlen(schemebuf);
+ result = CURLUE_MALFORMED_INPUT;
+ goto fail;
}
+ schemelen = Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf),
+ flags & (CURLU_GUESS_SCHEME|
+ CURLU_DEFAULT_SCHEME));
+
/* handle the file: scheme */
- if(url_has_scheme && !strcmp(schemebuf, "file")) {
- if(urllen <= 6)
+ if(schemelen && !strcmp(schemebuf, "file")) {
+ if(urllen <= 6) {
/* file:/ is not enough to actually be a complete file: URL */
- return CURLUE_BAD_FILE_URL;
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
+ }
/* path has been allocated large enough to hold this */
- strcpy(path, &url[5]);
+ path = (char *)&url[5];
- u->scheme = strdup("file");
- if(!u->scheme)
- return CURLUE_OUT_OF_MEMORY;
+ schemep = u->scheme = strdup("file");
+ if(!u->scheme) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
/* Extra handling URLs with an authority component (i.e. that start with
* "file://")
@@ -869,7 +967,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
*/
if(path[0] == '/' && path[1] == '/') {
/* swallow the two slashes */
- char *ptr = &path[2];
+ const char *ptr = &path[2];
/*
* According to RFC 8089, a file: URL can be reliably dereferenced if:
@@ -905,13 +1003,17 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
chars, and the delimiting slash character must be appended to the
host name */
path = strpbrk(ptr, "/\\:*?\"<>|");
- if(!path || *path != '/')
- return CURLUE_BAD_FILE_URL;
+ if(!path || *path != '/') {
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
+ }
len = path - ptr;
if(len) {
- memcpy(hostname, ptr, len);
- hostname[len] = 0;
+ if(Curl_dyn_addn(&host, ptr, len)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
uncpath = TRUE;
}
@@ -919,7 +1021,8 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
#else
/* Invalid file://hostname/, expected localhost or 127.0.0.1 or
none */
- return CURLUE_BAD_FILE_URL;
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
#endif
}
}
@@ -928,7 +1031,8 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
}
if(!uncpath)
- hostname = NULL; /* no host for file: URLs by default */
+ /* no host for file: URLs by default */
+ Curl_dyn_reset(&host);
#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
/* Don't allow Windows drive letters when not in Windows.
@@ -936,13 +1040,14 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
STARTS_WITH_URL_DRIVE_PREFIX(path)) {
/* File drive letters are only accepted in MSDOS/Windows */
- return CURLUE_BAD_FILE_URL;
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
}
#else
/* If the path starts with a slash and a drive letter, ditch the slash */
if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) {
/* This cannot be done with strcpy, as the memory chunks overlap! */
- memmove(path, &path[1], strlen(&path[1]) + 1);
+ path++;
}
#endif
@@ -952,32 +1057,39 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
const char *p;
const char *hostp;
size_t len;
- path[0] = 0;
- if(url_has_scheme) {
+ if(schemelen) {
int i = 0;
p = &url[schemelen + 1];
while(p && (*p == '/') && (i < 4)) {
p++;
i++;
}
- if((i < 1) || (i>3))
- /* less than one or more than three slashes */
- return CURLUE_BAD_SLASHES;
schemep = schemebuf;
- if(!Curl_builtin_scheme(schemep) &&
- !(flags & CURLU_NON_SUPPORT_SCHEME))
- return CURLUE_UNSUPPORTED_SCHEME;
+ if(!Curl_builtin_scheme(schemep, CURL_ZERO_TERMINATED) &&
+ !(flags & CURLU_NON_SUPPORT_SCHEME)) {
+ result = CURLUE_UNSUPPORTED_SCHEME;
+ goto fail;
+ }
- if(junkscan(schemep, flags))
- return CURLUE_BAD_SCHEME;
+ if((i < 1) || (i>3)) {
+ /* less than one or more than three slashes */
+ result = CURLUE_BAD_SLASHES;
+ goto fail;
+ }
+ if(junkscan(schemep, flags)) {
+ result = CURLUE_BAD_SCHEME;
+ goto fail;
+ }
}
else {
/* no scheme! */
- if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME)))
- return CURLUE_BAD_SCHEME;
+ if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME))) {
+ result = CURLUE_BAD_SCHEME;
+ goto fail;
+ }
if(flags & CURLU_DEFAULT_SCHEME)
schemep = DEFAULT_SCHEME;
@@ -994,122 +1106,169 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
len = p - hostp;
if(len) {
- memcpy(hostname, hostp, len);
- hostname[len] = 0;
+ if(Curl_dyn_addn(&host, hostp, len)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
}
else {
- if(!(flags & CURLU_NO_AUTHORITY))
- return CURLUE_NO_HOST;
+ if(!(flags & CURLU_NO_AUTHORITY)) {
+ result = CURLUE_NO_HOST;
+ goto fail;
+ }
}
- strcpy(path, p);
+ path = (char *)p;
if(schemep) {
u->scheme = strdup(schemep);
- if(!u->scheme)
- return CURLUE_OUT_OF_MEMORY;
+ if(!u->scheme) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
}
}
- if((flags & CURLU_URLENCODE) && path[0]) {
- /* worst case output length is 3x the original! */
- char *newp = malloc(strlen(path) * 3);
- if(!newp)
- return CURLUE_OUT_OF_MEMORY;
- path_alloced = TRUE;
- strcpy_url(newp, path, TRUE); /* consider it relative */
- u->temppath = path = newp;
- }
-
fragment = strchr(path, '#');
if(fragment) {
- *fragment++ = 0;
- if(junkscan(fragment, flags))
- return CURLUE_BAD_FRAGMENT;
- if(fragment[0]) {
- u->fragment = strdup(fragment);
- if(!u->fragment)
- return CURLUE_OUT_OF_MEMORY;
+ fraglen = strlen(fragment);
+ if(fraglen > 1) {
+ /* skip the leading '#' in the copy but include the terminating null */
+ u->fragment = Curl_memdup(fragment + 1, fraglen);
+ if(!u->fragment) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+
+ if(junkscan(u->fragment, flags)) {
+ result = CURLUE_BAD_FRAGMENT;
+ goto fail;
+ }
}
}
query = strchr(path, '?');
- if(query) {
- *query++ = 0;
- if(junkscan(query, flags))
- return CURLUE_BAD_QUERY;
- /* done even if the query part is a blank string */
- u->query = strdup(query);
- if(!u->query)
- return CURLUE_OUT_OF_MEMORY;
- }
+ if(query && (!fragment || (query < fragment))) {
+ size_t qlen = strlen(query) - fraglen; /* includes '?' */
+ pathlen = strlen(path) - qlen - fraglen;
+ if(qlen > 1) {
+ if(qlen && (flags & CURLU_URLENCODE)) {
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ /* skip the leading question mark */
+ if(urlencode_str(&enc, query + 1, qlen - 1, TRUE, TRUE)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ u->query = Curl_dyn_ptr(&enc);
+ }
+ else {
+ u->query = Curl_memdup(query + 1, qlen);
+ if(!u->query) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ u->query[qlen - 1] = 0;
+ }
- if(junkscan(path, flags))
- return CURLUE_BAD_PATH;
+ if(junkscan(u->query, flags)) {
+ result = CURLUE_BAD_QUERY;
+ goto fail;
+ }
+ }
+ else {
+ /* single byte query */
+ u->query = strdup("");
+ if(!u->query) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ }
+ }
+ else
+ pathlen = strlen(path) - fraglen;
+
+ if(pathlen && (flags & CURLU_URLENCODE)) {
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(urlencode_str(&enc, path, pathlen, TRUE, FALSE)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ pathlen = Curl_dyn_len(&enc);
+ path = u->path = Curl_dyn_ptr(&enc);
+ }
- if(!path[0])
- /* if there's no path left set, unset */
+ if(!pathlen) {
+ /* there is no path left, unset */
path = NULL;
+ }
else {
+ if(!u->path) {
+ u->path = Curl_memdup(path, pathlen + 1);
+ if(!u->path) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ u->path[pathlen] = 0;
+ path = u->path;
+ }
+ else if(flags & CURLU_URLENCODE)
+ /* it might have encoded more than just the path so cut it */
+ u->path[pathlen] = 0;
+
+ if(junkscan(u->path, flags)) {
+ result = CURLUE_BAD_PATH;
+ goto fail;
+ }
+
if(!(flags & CURLU_PATH_AS_IS)) {
/* remove ../ and ./ sequences according to RFC3986 */
- char *newp = Curl_dedotdotify(path);
- if(!newp)
- return CURLUE_OUT_OF_MEMORY;
-
- if(strcmp(newp, path)) {
- /* if we got a new version */
- if(path_alloced)
- Curl_safefree(u->temppath);
- u->temppath = path = newp;
- path_alloced = TRUE;
+ char *newp = dedotdotify((char *)path, pathlen);
+ if(!newp) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
}
- else
- free(newp);
+ free(u->path);
+ u->path = newp;
}
-
- u->path = path_alloced?path:strdup(path);
- if(!u->path)
- return CURLUE_OUT_OF_MEMORY;
- u->temppath = NULL; /* used now */
}
- if(hostname) {
+ if(Curl_dyn_len(&host)) {
char normalized_ipv4[sizeof("255.255.255.255") + 1];
/*
* Parse the login details and strip them out of the host name.
*/
- result = parse_hostname_login(u, &hostname, flags);
- if(result)
- return result;
-
- result = Curl_parse_port(u, hostname, url_has_scheme);
+ result = parse_hostname_login(u, &host, flags);
+ if(!result)
+ result = Curl_parse_port(u, &host, schemelen);
if(result)
- return result;
+ goto fail;
- if(junkscan(hostname, flags))
- return CURLUE_BAD_HOSTNAME;
+ if(junkscan(Curl_dyn_ptr(&host), flags)) {
+ result = CURLUE_BAD_HOSTNAME;
+ goto fail;
+ }
- if(0 == strlen(hostname) && (flags & CURLU_NO_AUTHORITY)) {
- /* Skip hostname check, it's allowed to be empty. */
- u->host = strdup("");
+ if(ipv4_normalize(Curl_dyn_ptr(&host),
+ normalized_ipv4, sizeof(normalized_ipv4))) {
+ Curl_dyn_reset(&host);
+ if(Curl_dyn_add(&host, normalized_ipv4)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
}
else {
- if(ipv4_normalize(hostname, normalized_ipv4, sizeof(normalized_ipv4)))
- u->host = strdup(normalized_ipv4);
- else {
- result = decode_host(hostname, &u->host);
- if(result)
- return result;
- result = hostname_check(u, u->host);
- if(result)
- return result;
- }
+ result = decode_host(&host);
+ if(!result)
+ result = hostname_check(u, Curl_dyn_ptr(&host), Curl_dyn_len(&host));
+ if(result)
+ goto fail;
}
- if(!u->host)
- return CURLUE_OUT_OF_MEMORY;
+
if((flags & CURLU_GUESS_SCHEME) && !schemep) {
+ const char *hostname = Curl_dyn_ptr(&host);
/* legacy curl-style guess based on host name */
if(checkprefix("ftp.", hostname))
schemep = "ftp";
@@ -1127,27 +1286,26 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
schemep = "http";
u->scheme = strdup(schemep);
- if(!u->scheme)
- return CURLUE_OUT_OF_MEMORY;
+ if(!u->scheme) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ }
+ }
+ else if(flags & CURLU_NO_AUTHORITY) {
+ /* allowed to be empty. */
+ if(Curl_dyn_add(&host, "")) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
}
}
- Curl_safefree(u->scratch);
- Curl_safefree(u->temppath);
-
- return CURLUE_OK;
-}
+ u->host = Curl_dyn_ptr(&host);
-/*
- * Parse the URL and set the relevant members of the Curl_URL struct.
- */
-static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
-{
- CURLUcode result = seturl(url, u, flags);
- if(result) {
- free_urlhandle(u);
- memset(u, 0, sizeof(struct Curl_URL));
- }
+ return result;
+ fail:
+ Curl_dyn_free(&host);
+ free_urlhandle(u);
return result;
}
@@ -1165,8 +1323,6 @@ static CURLUcode parseurl_and_replace(const char *url, CURLU *u,
free_urlhandle(u);
*u = tmpurl;
}
- else
- free_urlhandle(&tmpurl);
return result;
}
@@ -1265,7 +1421,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
/* there's no stored port number, but asked to deliver
a default one for the scheme */
const struct Curl_handler *h =
- Curl_builtin_scheme(u->scheme);
+ Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
if(h) {
msnprintf(portbuf, sizeof(portbuf), "%u", h->defport);
ptr = portbuf;
@@ -1275,7 +1431,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
/* there is a stored port number, but ask to inhibit if
it matches the default one for the scheme */
const struct Curl_handler *h =
- Curl_builtin_scheme(u->scheme);
+ Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
if(h && (h->defport == u->portnum) &&
(flags & CURLU_NO_DEFAULT_PORT))
ptr = NULL;
@@ -1321,7 +1477,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
else
return CURLUE_NO_SCHEME;
- h = Curl_builtin_scheme(scheme);
+ h = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
if(!port && (flags & CURLU_DEFAULT_PORT)) {
/* there's no stored port number, but asked to deliver
a default one for the scheme */
@@ -1344,14 +1500,13 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
if(u->host[0] == '[') {
if(u->zoneid) {
/* make it '[ host %25 zoneid ]' */
+ struct dynbuf enc;
size_t hostlen = strlen(u->host);
- size_t alen = hostlen + 3 + strlen(u->zoneid) + 1;
- allochost = malloc(alen);
- if(!allochost)
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(Curl_dyn_addf(&enc, "%.*s%%25%s]", (int)hostlen - 1, u->host,
+ u->zoneid))
return CURLUE_OUT_OF_MEMORY;
- memcpy(allochost, u->host, hostlen - 1);
- msnprintf(&allochost[hostlen - 1], alen - hostlen + 1,
- "%%25%s]", u->zoneid);
+ allochost = Curl_dyn_ptr(&enc);
}
}
else if(urlencode) {
@@ -1362,32 +1517,32 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
else {
/* only encode '%' in output host name */
char *host = u->host;
- size_t pcount = 0;
+ bool percent = FALSE;
/* first, count number of percents present in the name */
while(*host) {
- if(*host == '%')
- pcount++;
+ if(*host == '%') {
+ percent = TRUE;
+ break;
+ }
host++;
}
- /* if there were percents, encode the host name */
- if(pcount) {
- size_t hostlen = strlen(u->host);
- size_t alen = hostlen + 2 * pcount + 1;
- char *o = allochost = malloc(alen);
- if(!allochost)
- return CURLUE_OUT_OF_MEMORY;
-
+ /* if there were percent(s), encode the host name */
+ if(percent) {
+ struct dynbuf enc;
+ CURLcode result;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
host = u->host;
while(*host) {
- if(*host == '%') {
- memcpy(o, "%25", 3);
- o += 3;
- host++;
- continue;
- }
- *o++ = *host++;
+ if(*host == '%')
+ result = Curl_dyn_addn(&enc, "%25", 3);
+ else
+ result = Curl_dyn_addn(&enc, host, 1);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
+ host++;
}
- *o = '\0';
+ free(u->host);
+ u->host = Curl_dyn_ptr(&enc);
}
}
@@ -1420,13 +1575,15 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
break;
}
if(ptr) {
- *part = strdup(ptr);
+ size_t partlen = strlen(ptr);
+ size_t i = 0;
+ *part = Curl_memdup(ptr, partlen + 1);
if(!*part)
return CURLUE_OUT_OF_MEMORY;
if(plusdecode) {
/* convert + to space */
- char *plus;
- for(plus = *part; *plus; ++plus) {
+ char *plus = *part;
+ for(i = 0; i < partlen; ++plus, i++) {
if(*plus == '+')
*plus = ' ';
}
@@ -1443,18 +1600,16 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
return CURLUE_URLDECODE;
}
*part = decoded;
+ partlen = dlen;
}
if(urlencode) {
- /* worst case output length is 3x the original! */
- char *newp = malloc(strlen(*part) * 3);
- if(!newp)
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(urlencode_str(&enc, *part, partlen, TRUE,
+ what == CURLUPART_QUERY))
return CURLUE_OUT_OF_MEMORY;
- if(strcpy_url(newp, *part, TRUE)) { /* consider it relative */
- free(*part);
- *part = newp;
- }
- else
- free(newp);
+ free(*part);
+ *part = Curl_dyn_ptr(&enc);
}
return CURLUE_OK;
@@ -1532,7 +1687,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
return CURLUE_BAD_SCHEME;
if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
/* verify that it is a fine scheme */
- !Curl_builtin_scheme(part))
+ !Curl_builtin_scheme(part, CURL_ZERO_TERMINATED))
return CURLUE_UNSUPPORTED_SCHEME;
storep = &u->scheme;
urlencode = FALSE; /* never */
@@ -1598,7 +1753,9 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
/* if the new thing is absolute or the old one is not
* (we could not get an absolute url in 'oldurl'),
* then replace the existing with the new. */
- if(Curl_is_absolute_url(part, NULL, 0)
+ if(Curl_is_absolute_url(part, NULL, 0,
+ flags & (CURLU_GUESS_SCHEME|
+ CURLU_DEFAULT_SCHEME))
|| curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
return parseurl_and_replace(part, u, flags);
}
@@ -1628,14 +1785,16 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if(urlencode) {
const unsigned char *i;
- char *o;
- char *enc = malloc(nalloc * 3 + 1); /* for worst case! */
- if(!enc)
- return CURLUE_OUT_OF_MEMORY;
- for(i = (const unsigned char *)part, o = enc; *i; i++) {
+ struct dynbuf enc;
+
+ Curl_dyn_init(&enc, nalloc * 3 + 1);
+
+ for(i = (const unsigned char *)part; *i; i++) {
+ CURLcode result;
if((*i == ' ') && plusencode) {
- *o = '+';
- o++;
+ result = Curl_dyn_addn(&enc, "+", 1);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
else if(Curl_isunreserved(*i) ||
((*i == '/') && urlskipslash) ||
@@ -1643,16 +1802,17 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if((*i == '=') && equalsencode)
/* only skip the first equals sign */
equalsencode = FALSE;
- *o = *i;
- o++;
+ result = Curl_dyn_addn(&enc, i, 1);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
else {
- msnprintf(o, 4, "%%%02x", *i);
- o += 3;
+ result = Curl_dyn_addf(&enc, "%%%02x", *i);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
}
- *o = 0; /* null-terminate */
- newp = enc;
+ newp = Curl_dyn_ptr(&enc);
}
else {
char *p;
@@ -1664,8 +1824,8 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
/* make sure percent encoded are lower case */
if((*p == '%') && ISXDIGIT(p[1]) && ISXDIGIT(p[2]) &&
(ISUPPER(p[1]) || ISUPPER(p[2]))) {
- p[1] = (char)TOLOWER(p[1]);
- p[2] = (char)TOLOWER(p[2]);
+ p[1] = Curl_raw_tolower(p[1]);
+ p[2] = Curl_raw_tolower(p[2]);
p += 3;
}
else
@@ -1674,34 +1834,41 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
}
if(appendquery) {
- /* Append the string onto the old query. Add a '&' separator if none is
- present at the end of the exsting query already */
+ /* Append the 'newp' string onto the old query. Add a '&' separator if
+ none is present at the end of the existing query already */
+
size_t querylen = u->query ? strlen(u->query) : 0;
bool addamperand = querylen && (u->query[querylen -1] != '&');
if(querylen) {
- size_t newplen = strlen(newp);
- char *p = malloc(querylen + addamperand + newplen + 1);
- if(!p) {
- free((char *)newp);
- return CURLUE_OUT_OF_MEMORY;
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+
+ if(Curl_dyn_addn(&enc, u->query, querylen)) /* add original query */
+ goto nomem;
+
+ if(addamperand) {
+ if(Curl_dyn_addn(&enc, "&", 1))
+ goto nomem;
}
- strcpy(p, u->query); /* original query */
- if(addamperand)
- p[querylen] = '&'; /* ampersand */
- strcpy(&p[querylen + addamperand], newp); /* new suffix */
+ if(Curl_dyn_add(&enc, newp))
+ goto nomem;
free((char *)newp);
free(*storep);
- *storep = p;
+ *storep = Curl_dyn_ptr(&enc);
return CURLUE_OK;
+ nomem:
+ free((char *)newp);
+ return CURLUE_OUT_OF_MEMORY;
}
}
if(what == CURLUPART_HOST) {
- if(0 == strlen(newp) && (flags & CURLU_NO_AUTHORITY)) {
+ size_t n = strlen(newp);
+ if(!n && (flags & CURLU_NO_AUTHORITY)) {
/* Skip hostname check, it's allowed to be empty. */
}
else {
- if(hostname_check(u, (char *)newp)) {
+ if(hostname_check(u, (char *)newp, n)) {
free((char *)newp);
return CURLUE_BAD_HOSTNAME;
}
diff --git a/contrib/libs/curl/lib/urldata.h b/contrib/libs/curl/lib/urldata.h
index a9aee8f303..323a53a0d0 100644
--- a/contrib/libs/curl/lib/urldata.h
+++ b/contrib/libs/curl/lib/urldata.h
@@ -53,6 +53,33 @@
#define PORT_GOPHER 70
#define PORT_MQTT 1883
+#ifdef USE_WEBSOCKETS
+/* CURLPROTO_GOPHERS (29) is the highest publicly used protocol bit number,
+ * the rest are internal information. If we use higher bits we only do this on
+ * platforms that have a >= 64 bit type and then we use such a type for the
+ * protocol fields in the protocol handler.
+ */
+#define CURLPROTO_WS (1<<30)
+#define CURLPROTO_WSS ((curl_prot_t)1<<31)
+#else
+#define CURLPROTO_WS 0
+#define CURLPROTO_WSS 0
+#endif
+
+/* This should be undefined once we need bit 32 or higher */
+#define PROTO_TYPE_SMALL
+
+#ifndef PROTO_TYPE_SMALL
+typedef curl_off_t curl_prot_t;
+#else
+typedef unsigned int curl_prot_t;
+#endif
+
+/* This mask is for all the old protocols that are provided and defined in the
+ public header and shall exclude protocols added since which are not exposed
+ in the API */
+#define CURLPROTO_MASK (0x3ffffff)
+
#define DICT_MATCH "/MATCH:"
#define DICT_MATCH2 "/M:"
#define DICT_MATCH3 "/FIND:"
@@ -66,7 +93,8 @@
/* Convenience defines for checking protocols or their SSL based version. Each
protocol handler should only ever have a single CURLPROTO_ in its protocol
field. */
-#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS)
+#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_WS| \
+ CURLPROTO_WSS)
#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS)
#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S)
#define PROTO_FAMILY_SMB (CURLPROTO_SMB|CURLPROTO_SMBS)
@@ -157,10 +185,10 @@ typedef CURLcode (*Curl_datastream)(struct Curl_easy *data,
# endif
#endif
-#ifdef HAVE_LIBSSH2_H
+#ifdef USE_LIBSSH2
#error #include <libssh2.h>
#error #include <libssh2_sftp.h>
-#endif /* HAVE_LIBSSH2_H */
+#endif /* USE_LIBSSH2 */
#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
#define READBUFFER_MAX CURL_MAX_READ_SIZE
@@ -507,9 +535,7 @@ struct ConnectBits {
connection */
BIT(multiplex); /* connection is multiplexed */
BIT(tcp_fastopen); /* use TCP Fast Open */
- BIT(tls_enable_npn); /* TLS NPN extension? */
BIT(tls_enable_alpn); /* TLS ALPN extension? */
- BIT(connect_only);
#ifndef CURL_DISABLE_DOH
BIT(doh);
#endif
@@ -554,7 +580,7 @@ struct Curl_async {
struct Curl_dns_entry *dns;
struct thread_data *tdata;
void *resolver; /* resolver state, if it is used in the URL state -
- ares_channel f.e. */
+ ares_channel e.g. */
int port;
int status; /* if done is TRUE, this is the status from the callback */
BIT(done); /* set TRUE when the lookup is complete */
@@ -575,8 +601,9 @@ enum expect100 {
enum upgrade101 {
UPGR101_INIT, /* default state */
- UPGR101_REQUESTED, /* upgrade requested */
- UPGR101_RECEIVED, /* response received */
+ UPGR101_WS, /* upgrade to WebSockets requested */
+ UPGR101_H2, /* upgrade to HTTP/2 requested */
+ UPGR101_RECEIVED, /* 101 response received */
UPGR101_WORKING /* talking upgraded protocol */
};
@@ -779,10 +806,10 @@ struct Curl_handler {
void (*attach)(struct Curl_easy *data, struct connectdata *conn);
int defport; /* Default port. */
- unsigned int protocol; /* See CURLPROTO_* - this needs to be the single
- specific protocol bit */
- unsigned int family; /* single bit for protocol family; basically the
- non-TLS name of the protocol this is */
+ curl_prot_t protocol; /* See CURLPROTO_* - this needs to be the single
+ specific protocol bit */
+ curl_prot_t family; /* single bit for protocol family; basically the
+ non-TLS name of the protocol this is */
unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */
};
@@ -803,7 +830,7 @@ struct Curl_handler {
url query strings (?foo=bar) ! */
#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per
request instead of per connection */
-#define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */
+#define PROTOPT_ALPN (1<<8) /* set ALPN for this */
#define PROTOPT_STREAM (1<<9) /* a protocol with individual logical streams */
#define PROTOPT_URLOPTIONS (1<<10) /* allow options part in the userinfo field
of the URL */
@@ -1118,11 +1145,12 @@ struct connectdata {
unsigned short localport;
unsigned short secondary_port; /* secondary socket remote port to connect to
(ftp) */
- unsigned char negnpn; /* APLN or NPN TLS negotiated protocol,
- a CURL_HTTP_VERSION* value */
+ unsigned char alpn; /* APLN TLS negotiated protocol, a CURL_HTTP_VERSION*
+ value */
unsigned char transport; /* one of the TRNSPRT_* defines */
unsigned char ip_version; /* copied from the Curl_easy at creation time */
unsigned char httpversion; /* the HTTP version*10 reported by the server */
+ unsigned char connect_only;
};
/* The end of connectdata. */
@@ -1336,7 +1364,7 @@ struct UrlState {
This is strdup()ed data. */
char *first_host;
int first_remote_port;
- unsigned int first_remote_protocol;
+ curl_prot_t first_remote_protocol;
int retrycount; /* number of retries on a new connection */
struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
@@ -1767,8 +1795,8 @@ struct UserDefined {
#ifdef ENABLE_IPV6
unsigned int scope_id; /* Scope id for IPv6 */
#endif
- curl_off_t allowed_protocols;
- curl_off_t redir_protocols;
+ curl_prot_t allowed_protocols;
+ curl_prot_t redir_protocols;
unsigned int mime_options; /* Mime option flags. */
#ifndef CURL_DISABLE_RTSP
@@ -1817,6 +1845,8 @@ struct UserDefined {
BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
recipients */
#endif
+ unsigned char connect_only; /* make connection/request, then let
+ application use the socket */
BIT(is_fread_set); /* has read callback been set to non-NULL? */
#ifndef CURL_DISABLE_TFTP
BIT(tftp_no_options); /* do not send TFTP options requests */
@@ -1862,7 +1892,6 @@ struct UserDefined {
BIT(no_signal); /* do not use any signal/alarm handler */
BIT(tcp_nodelay); /* whether to enable TCP_NODELAY or not */
BIT(ignorecl); /* ignore content length */
- BIT(connect_only); /* make connection, let application use the socket */
BIT(http_te_skip); /* pass the raw body data to the user, even when
transfer-encoded (chunked, compressed) */
BIT(http_ce_skip); /* pass the raw body data to the user, even when
@@ -1875,7 +1904,6 @@ struct UserDefined {
BIT(sasl_ir); /* Enable/disable SASL initial response */
BIT(tcp_keepalive); /* use TCP keepalives */
BIT(tcp_fastopen); /* use TCP Fast Open */
- BIT(ssl_enable_npn); /* TLS NPN extension? */
BIT(ssl_enable_alpn);/* TLS ALPN extension? */
BIT(path_as_is); /* allow dotdots? */
BIT(pipewait); /* wait for multiplex status before starting a new
@@ -1895,6 +1923,9 @@ struct UserDefined {
BIT(doh_verifystatus); /* DoH certificate status verification */
#endif
BIT(http09_allowed); /* allow HTTP/0.9 responses */
+#ifdef USE_WEBSOCKETS
+ BIT(ws_raw_mode);
+#endif
};
struct Names {
diff --git a/contrib/libs/curl/lib/vauth/digest.c b/contrib/libs/curl/lib/vauth/digest.c
index 962aa624a3..f945e8b6c9 100644
--- a/contrib/libs/curl/lib/vauth/digest.c
+++ b/contrib/libs/curl/lib/vauth/digest.c
@@ -382,7 +382,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
return CURLE_BAD_CONTENT_ENCODING;
- /* Generate 32 random hex chars, 32 bytes + 1 zero termination */
+ /* Generate 32 random hex chars, 32 bytes + 1 null-termination */
result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce));
if(result)
return result;
@@ -521,7 +521,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
char content[DIGEST_MAX_CONTENT_LENGTH];
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Extract a value=content pair */
@@ -561,7 +561,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
token = strtok_r(tmp, ",", &tok_buf);
while(token) {
/* Pass additional spaces here */
- while(*token && ISSPACE(*token))
+ while(*token && ISBLANK(*token))
token++;
if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH)) {
foundAuth = TRUE;
@@ -622,7 +622,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
break; /* We're done here */
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Allow the list to be comma-separated */
diff --git a/contrib/libs/curl/lib/vauth/digest_sspi.c b/contrib/libs/curl/lib/vauth/digest_sspi.c
index af463848a6..89a9db52c7 100644
--- a/contrib/libs/curl/lib/vauth/digest_sspi.c
+++ b/contrib/libs/curl/lib/vauth/digest_sspi.c
@@ -259,7 +259,7 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
char content[DIGEST_MAX_CONTENT_LENGTH];
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Extract a value=content pair */
@@ -292,7 +292,7 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
break; /* We're done here */
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Allow the list to be comma-separated */
@@ -333,7 +333,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
char value[DIGEST_MAX_VALUE_LENGTH];
char content[DIGEST_MAX_CONTENT_LENGTH];
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(!Curl_auth_digest_get_pair(p, value, content, &p))
@@ -345,7 +345,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
break;
}
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(',' == *p)
@@ -431,8 +431,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
has changed then delete that context. */
if((userp && !digest->user) || (!userp && digest->user) ||
(passwdp && !digest->passwd) || (!passwdp && digest->passwd) ||
- (userp && digest->user && strcmp(userp, digest->user)) ||
- (passwdp && digest->passwd && strcmp(passwdp, digest->passwd))) {
+ (userp && digest->user && Curl_timestrcmp(userp, digest->user)) ||
+ (passwdp && digest->passwd && Curl_timestrcmp(passwdp, digest->passwd))) {
if(digest->http_context) {
s_pSecFn->DeleteSecurityContext(digest->http_context);
Curl_safefree(digest->http_context);
diff --git a/contrib/libs/curl/lib/vauth/gsasl.c b/contrib/libs/curl/lib/vauth/gsasl.c
index 7219400eab..f96a6dca29 100644
--- a/contrib/libs/curl/lib/vauth/gsasl.c
+++ b/contrib/libs/curl/lib/vauth/gsasl.c
@@ -36,7 +36,8 @@
#error #include <gsasl.h>
-/* The last #include files should be: */
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
diff --git a/contrib/libs/curl/lib/vauth/ntlm.c b/contrib/libs/curl/lib/vauth/ntlm.c
index edaacbb9ed..c10fa6caaf 100644
--- a/contrib/libs/curl/lib/vauth/ntlm.c
+++ b/contrib/libs/curl/lib/vauth/ntlm.c
@@ -29,7 +29,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
@@ -600,7 +600,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
/* A safer but less compatible alternative is:
* Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
- * See https://davenport.sourceforge.io/ntlm.html#ntlmVersion2 */
+ * See https://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
}
if(unicode) {
@@ -658,7 +658,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
/* LanManager response */
/* NT response */
- 0, /* zero termination */
+ 0, /* null-termination */
0, 0, 0, /* type-3 long, the 24 upper bits */
SHORTPAIR(0x18), /* LanManager response length, twice */
diff --git a/contrib/libs/curl/lib/vauth/ntlm.h b/contrib/libs/curl/lib/vauth/ntlm.h
index 97325d975c..4dfda55453 100644
--- a/contrib/libs/curl/lib/vauth/ntlm.h
+++ b/contrib/libs/curl/lib/vauth/ntlm.h
@@ -34,7 +34,8 @@
/* Stuff only required for curl_ntlm_msgs.c */
#ifdef BUILDING_CURL_NTLM_MSGS_C
-/* Flag bits definitions based on https://davenport.sourceforge.io/ntlm.html */
+/* Flag bits definitions based on
+ https://davenport.sourceforge.net/ntlm.html */
#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
/* Indicates that Unicode strings are supported for use in security buffer
diff --git a/contrib/libs/curl/lib/vauth/vauth.c b/contrib/libs/curl/lib/vauth/vauth.c
index 9d6363df07..58fe05139d 100644
--- a/contrib/libs/curl/lib/vauth/vauth.c
+++ b/contrib/libs/curl/lib/vauth/vauth.c
@@ -27,6 +27,8 @@
#include <curl/curl.h>
#include "vauth.h"
+#include "urldata.h"
+#include "strcase.h"
#include "curl_multibyte.h"
#include "curl_printf.h"
@@ -144,3 +146,18 @@ bool Curl_auth_user_contains_domain(const char *user)
return valid;
}
+
+/*
+ * Curl_auth_ollowed_to_host() tells if authentication, cookies or other
+ * "sensitive data" can (still) be sent to this host.
+ */
+bool Curl_auth_allowed_to_host(struct Curl_easy *data)
+{
+ struct connectdata *conn = data->conn;
+ return (!data->state.this_is_a_follow ||
+ data->set.allow_auth_to_other_hosts ||
+ (data->state.first_host &&
+ strcasecompare(data->state.first_host, conn->host.name) &&
+ (data->state.first_remote_port == conn->remote_port) &&
+ (data->state.first_remote_protocol == conn->handler->protocol)));
+}
diff --git a/contrib/libs/curl/lib/vauth/vauth.h b/contrib/libs/curl/lib/vauth/vauth.h
index 1c4b5b5dc6..af27f01dfb 100644
--- a/contrib/libs/curl/lib/vauth/vauth.h
+++ b/contrib/libs/curl/lib/vauth/vauth.h
@@ -54,6 +54,12 @@ struct gsasldata;
#define GSS_ERROR(status) ((status) & 0x80000000)
#endif
+/*
+ * Curl_auth_allowed_to_host() tells if authentication, cookies or other
+ * "sensitive data" can (still) be sent to this host.
+ */
+bool Curl_auth_allowed_to_host(struct Curl_easy *data);
+
/* This is used to build a SPN string */
#if !defined(USE_WINDOWS_SSPI)
char *Curl_auth_build_spn(const char *service, const char *host,
@@ -224,7 +230,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
CURLcode Curl_auth_create_spnego_message(struct negotiatedata *nego,
char **outptr, size_t *outlen);
-/* This is used to clean up the SPNEGO specifiec data */
+/* This is used to clean up the SPNEGO specific data */
void Curl_auth_cleanup_spnego(struct negotiatedata *nego);
#endif /* USE_SPNEGO */
diff --git a/contrib/libs/curl/lib/version.c b/contrib/libs/curl/lib/version.c
index 1f74e177d5..8d7be114f4 100644
--- a/contrib/libs/curl/lib/version.c
+++ b/contrib/libs/curl/lib/version.c
@@ -53,7 +53,7 @@
#include <librtmp/rtmp.h>
#endif
-#ifdef HAVE_ZLIB_H
+#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
@@ -338,6 +338,11 @@ static const char * const protocols[] = {
#endif
#ifdef USE_LIBRTMP
"rtmp",
+ "rtmpe",
+ "rtmps",
+ "rtmpt",
+ "rtmpte",
+ "rtmpts",
#endif
#ifndef CURL_DISABLE_RTSP
"rtsp",
@@ -367,6 +372,12 @@ static const char * const protocols[] = {
#ifndef CURL_DISABLE_TFTP
"tftp",
#endif
+#ifdef USE_WEBSOCKETS
+ "ws",
+#endif
+#if defined(USE_SSL) && defined(USE_WEBSOCKETS)
+ "wss",
+#endif
NULL
};
diff --git a/contrib/libs/curl/lib/vquic/msh3.c b/contrib/libs/curl/lib/vquic/msh3.c
index 8f66bcf493..7a70ee57d4 100644
--- a/contrib/libs/curl/lib/vquic/msh3.c
+++ b/contrib/libs/curl/lib/vquic/msh3.c
@@ -114,7 +114,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
socklen_t addrlen)
{
struct quicsocket *qs = &conn->hequic[sockindex];
- bool unsecure = !conn->ssl_config.verifypeer;
+ bool insecure = !conn->ssl_config.verifypeer;
memset(qs, 0, sizeof(*qs));
(void)sockfd;
@@ -132,7 +132,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
qs->conn = MsH3ConnectionOpen(qs->api,
conn->host.name,
(uint16_t)conn->remote_port,
- unsecure);
+ insecure);
if(!qs->conn) {
failf(data, "can't create msh3 connection");
if(qs->api) {
@@ -381,9 +381,6 @@ static void MSH3_CALL msh3_shutdown(MSH3_REQUEST *Request, void *IfContext)
(void)stream;
}
-static_assert(sizeof(MSH3_HEADER) == sizeof(struct h2h3pseudo),
- "Sizes must match for cast below to work");
-
static ssize_t msh3_stream_send(struct Curl_easy *data,
int sockindex,
const void *mem,
@@ -396,6 +393,9 @@ static ssize_t msh3_stream_send(struct Curl_easy *data,
struct h2h3req *hreq;
(void)sockindex;
+ /* Sizes must match for cast below to work" */
+ DEBUGASSERT(sizeof(MSH3_HEADER) == sizeof(struct h2h3pseudo));
+
H3BUGF(infof(data, "msh3_stream_send %zu", len));
if(!stream->req) {
diff --git a/contrib/libs/curl/lib/vquic/ngtcp2.c b/contrib/libs/curl/lib/vquic/ngtcp2.c
index 11787cee5f..feabd5fa89 100644
--- a/contrib/libs/curl/lib/vquic/ngtcp2.c
+++ b/contrib/libs/curl/lib/vquic/ngtcp2.c
@@ -760,6 +760,7 @@ static ngtcp2_callbacks ng_callbacks = {
NULL, /* version_negotiation */
cb_recv_rx_key,
NULL, /* recv_tx_key */
+ NULL, /* early_data_rejected */
};
/*
@@ -1703,6 +1704,11 @@ static CURLcode ng_has_connected(struct Curl_easy *data,
}
else
infof(data, "Skipped certificate verification");
+#ifdef USE_OPENSSL
+ if(data->set.ssl.certinfo)
+ /* asked to gather certificate info */
+ (void)Curl_ossl_certchain(data, conn->quic->ssl);
+#endif
return result;
}
@@ -1828,15 +1834,17 @@ static CURLcode do_sendmsg(size_t *psent, struct Curl_easy *data, int sockfd,
size_t pktlen, size_t gsolen)
{
#ifdef HAVE_SENDMSG
- struct iovec msg_iov = {(void *)pkt, pktlen};
+ struct iovec msg_iov;
struct msghdr msg = {0};
- uint8_t msg_ctrl[32];
ssize_t sent;
#if defined(__linux__) && defined(UDP_SEGMENT)
+ uint8_t msg_ctrl[32];
struct cmsghdr *cm;
#endif
*psent = 0;
+ msg_iov.iov_base = (uint8_t *)pkt;
+ msg_iov.iov_len = pktlen;
msg.msg_iov = &msg_iov;
msg.msg_iovlen = 1;
@@ -1981,9 +1989,9 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
ngtcp2_ssize outlen;
uint8_t *outpos = qs->pktbuf;
size_t max_udp_payload_size =
- ngtcp2_conn_get_max_udp_payload_size(qs->qconn);
+ ngtcp2_conn_get_max_tx_udp_payload_size(qs->qconn);
size_t path_max_udp_payload_size =
- ngtcp2_conn_get_path_max_udp_payload_size(qs->qconn);
+ ngtcp2_conn_get_path_max_tx_udp_payload_size(qs->qconn);
size_t max_pktcnt =
CURLMIN(MAX_PKT_BURST, qs->pktbuflen / max_udp_payload_size);
size_t pktcnt = 0;
diff --git a/contrib/libs/curl/lib/vquic/quiche.c b/contrib/libs/curl/lib/vquic/quiche.c
index 034794f8e7..5a3d6fe378 100644
--- a/contrib/libs/curl/lib/vquic/quiche.c
+++ b/contrib/libs/curl/lib/vquic/quiche.c
@@ -416,6 +416,10 @@ static CURLcode quiche_has_connected(struct Curl_easy *data,
qs->cfg = NULL;
qs->conn = NULL;
}
+ if(data->set.ssl.certinfo)
+ /* asked to gather certificate info */
+ (void)Curl_ossl_certchain(data, qs->ssl);
+
return CURLE_OK;
fail:
quiche_h3_config_free(qs->h3config);
diff --git a/contrib/libs/curl/lib/vssh/libssh.c b/contrib/libs/curl/lib/vssh/libssh.c
index 331aef366b..dc98aa0413 100644
--- a/contrib/libs/curl/lib/vssh/libssh.c
+++ b/contrib/libs/curl/lib/vssh/libssh.c
@@ -963,10 +963,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
rc = sftp_init(sshc->sftp_session);
if(rc != SSH_OK) {
- rc = sftp_get_error(sshc->sftp_session);
failf(data, "Failure initializing sftp session: %s",
ssh_get_error(sshc->ssh_session));
- MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
+ MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(SSH_FX_FAILURE));
break;
}
state(data, SSH_SFTP_REALPATH);
@@ -1667,7 +1666,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(from_t == CURL_OFFT_FLOW) {
return CURLE_RANGE_ERROR;
}
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
if(to_t == CURL_OFFT_FLOW) {
diff --git a/contrib/libs/curl/lib/vssh/libssh2.c b/contrib/libs/curl/lib/vssh/libssh2.c
index 7632888b9f..0536f5a09e 100644
--- a/contrib/libs/curl/lib/vssh/libssh2.c
+++ b/contrib/libs/curl/lib/vssh/libssh2.c
@@ -2506,7 +2506,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
if(to_t == CURL_OFFT_FLOW)
diff --git a/contrib/libs/curl/lib/vssh/ssh.h b/contrib/libs/curl/lib/vssh/ssh.h
index 88ac106134..33f369bf42 100644
--- a/contrib/libs/curl/lib/vssh/ssh.h
+++ b/contrib/libs/curl/lib/vssh/ssh.h
@@ -26,10 +26,10 @@
#include "curl_setup.h"
-#if defined(HAVE_LIBSSH2_H)
+#if defined(USE_LIBSSH2)
#error #include <libssh2.h>
#error #include <libssh2_sftp.h>
-#elif defined(HAVE_LIBSSH_LIBSSH_H)
+#elif defined(USE_LIBSSH)
#error #include <libssh/libssh.h>
#error #include <libssh/sftp.h>
#elif defined(USE_WOLFSSH)
diff --git a/contrib/libs/curl/lib/vtls/bearssl.c b/contrib/libs/curl/lib/vtls/bearssl.c
index f14eb66a20..1221ce8c84 100644
--- a/contrib/libs/curl/lib/vtls/bearssl.c
+++ b/contrib/libs/curl/lib/vtls/bearssl.c
@@ -76,9 +76,9 @@ struct cafile_parser {
#define CAFILE_SOURCE_PATH 1
#define CAFILE_SOURCE_BLOB 2
struct cafile_source {
- const int type;
- const char * const data;
- const size_t len;
+ int type;
+ const char *data;
+ size_t len;
};
static void append_dn(void *ctx, const void *buf, size_t len)
@@ -618,11 +618,11 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
}
if(ca_info_blob) {
- struct cafile_source source = {
- CAFILE_SOURCE_BLOB,
- ca_info_blob->data,
- ca_info_blob->len,
- };
+ struct cafile_source source;
+ source.type = CAFILE_SOURCE_BLOB;
+ source.data = ca_info_blob->data;
+ source.len = ca_info_blob->len;
+
ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
if(ret != CURLE_OK) {
if(verifypeer) {
@@ -635,11 +635,11 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
}
if(ssl_cafile) {
- struct cafile_source source = {
- CAFILE_SOURCE_PATH,
- ssl_cafile,
- 0,
- };
+ struct cafile_source source;
+ source.type = CAFILE_SOURCE_PATH;
+ source.data = ssl_cafile;
+ source.len = 0;
+
ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
if(ret != CURLE_OK) {
if(verifypeer) {
@@ -875,14 +875,14 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data,
#ifdef USE_HTTP2
if(!strcmp(protocol, ALPN_H2))
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
else
#endif
if(!strcmp(protocol, ALPN_HTTP_1_1))
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
else
infof(data, "ALPN, unrecognized protocol %s", protocol);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
else
diff --git a/contrib/libs/curl/lib/vtls/keylog.c b/contrib/libs/curl/lib/vtls/keylog.c
index 7471217921..1952a690ca 100644
--- a/contrib/libs/curl/lib/vtls/keylog.c
+++ b/contrib/libs/curl/lib/vtls/keylog.c
@@ -24,6 +24,7 @@
#include "curl_setup.h"
#include "keylog.h"
+#include <curl/curl.h>
/* The last #include files should be: */
#include "curl_memory.h"
diff --git a/contrib/libs/curl/lib/vtls/openssl.c b/contrib/libs/curl/lib/vtls/openssl.c
index 4daae3788e..fe55490309 100644
--- a/contrib/libs/curl/lib/vtls/openssl.c
+++ b/contrib/libs/curl/lib/vtls/openssl.c
@@ -29,7 +29,7 @@
#include "curl_setup.h"
-#ifdef USE_OPENSSL
+#if defined(USE_QUICHE) || defined(USE_OPENSSL)
#include <limits.h>
@@ -55,6 +55,7 @@
#include "slist.h"
#include "select.h"
#include "vtls.h"
+#include "vauth/vauth.h"
#include "keylog.h"
#include "strcase.h"
#include "hostcheck.h"
@@ -271,6 +272,344 @@ struct ssl_backend_data {
#endif
};
+#define push_certinfo(_label, _num) \
+do { \
+ long info_len = BIO_get_mem_data(mem, &ptr); \
+ Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
+ if(1 != BIO_reset(mem)) \
+ break; \
+} while(0)
+
+static void pubkey_show(struct Curl_easy *data,
+ BIO *mem,
+ int num,
+ const char *type,
+ const char *name,
+ const BIGNUM *bn)
+{
+ char *ptr;
+ char namebuf[32];
+
+ msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
+
+ if(bn)
+ BN_print(mem, bn);
+ push_certinfo(namebuf, num);
+}
+
+#ifdef HAVE_OPAQUE_RSA_DSA_DH
+#define print_pubkey_BN(_type, _name, _num) \
+ pubkey_show(data, mem, _num, #_type, #_name, _name)
+
+#else
+#define print_pubkey_BN(_type, _name, _num) \
+do { \
+ if(_type->_name) { \
+ pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \
+ } \
+} while(0)
+#endif
+
+static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
+{
+ int i, ilen;
+
+ ilen = (int)len;
+ if(ilen < 0)
+ return 1; /* buffer too big */
+
+ i = i2t_ASN1_OBJECT(buf, ilen, a);
+
+ if(i >= ilen)
+ return 1; /* buffer too small */
+
+ return 0;
+}
+
+static void X509V3_ext(struct Curl_easy *data,
+ int certnum,
+ CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
+{
+ int i;
+
+ if((int)sk_X509_EXTENSION_num(exts) <= 0)
+ /* no extensions, bail out */
+ return;
+
+ for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
+ ASN1_OBJECT *obj;
+ X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+ BUF_MEM *biomem;
+ char namebuf[128];
+ BIO *bio_out = BIO_new(BIO_s_mem());
+
+ if(!bio_out)
+ return;
+
+ obj = X509_EXTENSION_get_object(ext);
+
+ asn1_object_dump(obj, namebuf, sizeof(namebuf));
+
+ if(!X509V3_EXT_print(bio_out, ext, 0, 0))
+ ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
+
+ BIO_get_mem_ptr(bio_out, &biomem);
+ Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
+ biomem->length);
+ BIO_free(bio_out);
+ }
+}
+
+#ifdef OPENSSL_IS_BORINGSSL
+typedef size_t numcert_t;
+#else
+typedef int numcert_t;
+#endif
+
+CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
+{
+ CURLcode result;
+ STACK_OF(X509) *sk;
+ int i;
+ numcert_t numcerts;
+ BIO *mem;
+
+ DEBUGASSERT(ssl);
+
+ sk = SSL_get_peer_cert_chain(ssl);
+ if(!sk) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ numcerts = sk_X509_num(sk);
+
+ result = Curl_ssl_init_certinfo(data, (int)numcerts);
+ if(result) {
+ return result;
+ }
+
+ mem = BIO_new(BIO_s_mem());
+ if(!mem) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ for(i = 0; i < (int)numcerts; i++) {
+ ASN1_INTEGER *num;
+ X509 *x = sk_X509_value(sk, i);
+ EVP_PKEY *pubkey = NULL;
+ int j;
+ char *ptr;
+ const ASN1_BIT_STRING *psig = NULL;
+
+ X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
+ push_certinfo("Subject", i);
+
+ X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
+ push_certinfo("Issuer", i);
+
+ BIO_printf(mem, "%lx", X509_get_version(x));
+ push_certinfo("Version", i);
+
+ num = X509_get_serialNumber(x);
+ if(num->type == V_ASN1_NEG_INTEGER)
+ BIO_puts(mem, "-");
+ for(j = 0; j < num->length; j++)
+ BIO_printf(mem, "%02x", num->data[j]);
+ push_certinfo("Serial Number", i);
+
+#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
+ {
+ const X509_ALGOR *sigalg = NULL;
+ X509_PUBKEY *xpubkey = NULL;
+ ASN1_OBJECT *pubkeyoid = NULL;
+
+ X509_get0_signature(&psig, &sigalg, x);
+ if(sigalg) {
+ i2a_ASN1_OBJECT(mem, sigalg->algorithm);
+ push_certinfo("Signature Algorithm", i);
+ }
+
+ xpubkey = X509_get_X509_PUBKEY(x);
+ if(xpubkey) {
+ X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
+ if(pubkeyoid) {
+ i2a_ASN1_OBJECT(mem, pubkeyoid);
+ push_certinfo("Public Key Algorithm", i);
+ }
+ }
+
+ X509V3_ext(data, i, X509_get0_extensions(x));
+ }
+#else
+ {
+ /* before OpenSSL 1.0.2 */
+ X509_CINF *cinf = x->cert_info;
+
+ i2a_ASN1_OBJECT(mem, cinf->signature->algorithm);
+ push_certinfo("Signature Algorithm", i);
+
+ i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm);
+ push_certinfo("Public Key Algorithm", i);
+
+ X509V3_ext(data, i, cinf->extensions);
+
+ psig = x->signature;
+ }
+#endif
+
+ ASN1_TIME_print(mem, X509_get0_notBefore(x));
+ push_certinfo("Start date", i);
+
+ ASN1_TIME_print(mem, X509_get0_notAfter(x));
+ push_certinfo("Expire date", i);
+
+ pubkey = X509_get_pubkey(x);
+ if(!pubkey)
+ infof(data, " Unable to load public key");
+ else {
+ int pktype;
+#ifdef HAVE_OPAQUE_EVP_PKEY
+ pktype = EVP_PKEY_id(pubkey);
+#else
+ pktype = pubkey->type;
+#endif
+ switch(pktype) {
+ case EVP_PKEY_RSA:
+ {
+#ifndef HAVE_EVP_PKEY_GET_PARAMS
+ RSA *rsa;
+#ifdef HAVE_OPAQUE_EVP_PKEY
+ rsa = EVP_PKEY_get0_RSA(pubkey);
+#else
+ rsa = pubkey->pkey.rsa;
+#endif /* HAVE_OPAQUE_EVP_PKEY */
+#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
+
+ {
+#ifdef HAVE_OPAQUE_RSA_DSA_DH
+ DECLARE_PKEY_PARAM_BIGNUM(n);
+ DECLARE_PKEY_PARAM_BIGNUM(e);
+#ifdef HAVE_EVP_PKEY_GET_PARAMS
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e);
+#else
+ RSA_get0_key(rsa, &n, &e, NULL);
+#endif /* HAVE_EVP_PKEY_GET_PARAMS */
+ BIO_printf(mem, "%d", BN_num_bits(n));
+#else
+ BIO_printf(mem, "%d", BN_num_bits(rsa->n));
+#endif /* HAVE_OPAQUE_RSA_DSA_DH */
+ push_certinfo("RSA Public Key", i);
+ print_pubkey_BN(rsa, n, i);
+ print_pubkey_BN(rsa, e, i);
+ FREE_PKEY_PARAM_BIGNUM(n);
+ FREE_PKEY_PARAM_BIGNUM(e);
+ }
+
+ break;
+ }
+ case EVP_PKEY_DSA:
+ {
+#ifndef OPENSSL_NO_DSA
+#ifndef HAVE_EVP_PKEY_GET_PARAMS
+ DSA *dsa;
+#ifdef HAVE_OPAQUE_EVP_PKEY
+ dsa = EVP_PKEY_get0_DSA(pubkey);
+#else
+ dsa = pubkey->pkey.dsa;
+#endif /* HAVE_OPAQUE_EVP_PKEY */
+#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
+ {
+#ifdef HAVE_OPAQUE_RSA_DSA_DH
+ DECLARE_PKEY_PARAM_BIGNUM(p);
+ DECLARE_PKEY_PARAM_BIGNUM(q);
+ DECLARE_PKEY_PARAM_BIGNUM(g);
+ DECLARE_PKEY_PARAM_BIGNUM(pub_key);
+#ifdef HAVE_EVP_PKEY_GET_PARAMS
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
+#else
+ DSA_get0_pqg(dsa, &p, &q, &g);
+ DSA_get0_key(dsa, &pub_key, NULL);
+#endif /* HAVE_EVP_PKEY_GET_PARAMS */
+#endif /* HAVE_OPAQUE_RSA_DSA_DH */
+ print_pubkey_BN(dsa, p, i);
+ print_pubkey_BN(dsa, q, i);
+ print_pubkey_BN(dsa, g, i);
+ print_pubkey_BN(dsa, pub_key, i);
+ FREE_PKEY_PARAM_BIGNUM(p);
+ FREE_PKEY_PARAM_BIGNUM(q);
+ FREE_PKEY_PARAM_BIGNUM(g);
+ FREE_PKEY_PARAM_BIGNUM(pub_key);
+ }
+#endif /* !OPENSSL_NO_DSA */
+ break;
+ }
+ case EVP_PKEY_DH:
+ {
+#ifndef HAVE_EVP_PKEY_GET_PARAMS
+ DH *dh;
+#ifdef HAVE_OPAQUE_EVP_PKEY
+ dh = EVP_PKEY_get0_DH(pubkey);
+#else
+ dh = pubkey->pkey.dh;
+#endif /* HAVE_OPAQUE_EVP_PKEY */
+#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
+ {
+#ifdef HAVE_OPAQUE_RSA_DSA_DH
+ DECLARE_PKEY_PARAM_BIGNUM(p);
+ DECLARE_PKEY_PARAM_BIGNUM(q);
+ DECLARE_PKEY_PARAM_BIGNUM(g);
+ DECLARE_PKEY_PARAM_BIGNUM(pub_key);
+#ifdef HAVE_EVP_PKEY_GET_PARAMS
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
+#else
+ DH_get0_pqg(dh, &p, &q, &g);
+ DH_get0_key(dh, &pub_key, NULL);
+#endif /* HAVE_EVP_PKEY_GET_PARAMS */
+ print_pubkey_BN(dh, p, i);
+ print_pubkey_BN(dh, q, i);
+ print_pubkey_BN(dh, g, i);
+#else
+ print_pubkey_BN(dh, p, i);
+ print_pubkey_BN(dh, g, i);
+#endif /* HAVE_OPAQUE_RSA_DSA_DH */
+ print_pubkey_BN(dh, pub_key, i);
+ FREE_PKEY_PARAM_BIGNUM(p);
+ FREE_PKEY_PARAM_BIGNUM(q);
+ FREE_PKEY_PARAM_BIGNUM(g);
+ FREE_PKEY_PARAM_BIGNUM(pub_key);
+ }
+ break;
+ }
+ }
+ EVP_PKEY_free(pubkey);
+ }
+
+ if(psig) {
+ for(j = 0; j < psig->length; j++)
+ BIO_printf(mem, "%02x:", psig->data[j]);
+ push_certinfo("Signature", i);
+ }
+
+ PEM_write_bio_X509(mem, x);
+ push_certinfo("Cert", i);
+ }
+
+ BIO_free(mem);
+
+ return CURLE_OK;
+}
+
+#endif /* quiche or OpenSSL */
+
+#ifdef USE_OPENSSL
+
static bool ossl_associate_connection(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
@@ -2254,72 +2593,6 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
# define HAS_ALPN 1
#endif
-/* Check for OpenSSL 1.0.1 which has NPN support. */
-#undef HAS_NPN
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L \
- && !defined(OPENSSL_NO_TLSEXT) \
- && !defined(OPENSSL_NO_NEXTPROTONEG)
-# define HAS_NPN 1
-#endif
-
-#ifdef HAS_NPN
-
-/*
- * in is a list of length prefixed strings. this function has to select
- * the protocol we want to use from the list and write its string into out.
- */
-
-static int
-select_next_protocol(unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen,
- const char *key, unsigned int keylen)
-{
- unsigned int i;
- for(i = 0; i + keylen <= inlen; i += in[i] + 1) {
- if(memcmp(&in[i + 1], key, keylen) == 0) {
- *out = (unsigned char *) &in[i + 1];
- *outlen = in[i];
- return 0;
- }
- }
- return -1;
-}
-
-static int
-select_next_proto_cb(SSL *ssl,
- unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen,
- void *arg)
-{
- struct Curl_easy *data = (struct Curl_easy *)arg;
- struct connectdata *conn = data->conn;
- (void)ssl;
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
- !select_next_protocol(out, outlen, in, inlen, ALPN_H2, ALPN_H2_LENGTH)) {
- infof(data, "NPN, negotiated HTTP2 (%s)", ALPN_H2);
- conn->negnpn = CURL_HTTP_VERSION_2;
- return SSL_TLSEXT_ERR_OK;
- }
-#endif
-
- if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1,
- ALPN_HTTP_1_1_LENGTH)) {
- infof(data, "NPN, negotiated HTTP1.1");
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- return SSL_TLSEXT_ERR_OK;
- }
-
- infof(data, "NPN, no overlap, use HTTP1.1");
- *out = (unsigned char *)ALPN_HTTP_1_1;
- *outlen = ALPN_HTTP_1_1_LENGTH;
- conn->negnpn = CURL_HTTP_VERSION_1_1;
-
- return SSL_TLSEXT_ERR_OK;
-}
-#endif /* HAS_NPN */
-
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
static CURLcode
set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
@@ -2810,11 +3083,6 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
SSL_CTX_set_options(backend->ctx, ctx_options);
-#ifdef HAS_NPN
- if(conn->bits.tls_enable_npn)
- SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, data);
-#endif
-
#ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) {
int cur = 0;
@@ -2904,7 +3172,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#ifdef USE_OPENSSL_SRP
if((ssl_authtype == CURL_TLSAUTH_SRP) &&
- Curl_allow_auth_to_host(data)) {
+ Curl_auth_allowed_to_host(data)) {
char * const ssl_username = SSL_SET_OPTION(primary.username);
char * const ssl_password = SSL_SET_OPTION(primary.password);
infof(data, "Using TLS-SRP username: %s", ssl_username);
@@ -3442,19 +3710,19 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
#ifdef USE_HTTP2
if(len == ALPN_H2_LENGTH &&
!memcmp(ALPN_H2, neg_protocol, len)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(len == ALPN_HTTP_1_1_LENGTH &&
!memcmp(ALPN_HTTP_1_1, neg_protocol, ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
}
}
else
infof(data, VTLS_INFOF_NO_ALPN);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
#endif
@@ -3463,342 +3731,6 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
}
}
-static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
-{
- int i, ilen;
-
- ilen = (int)len;
- if(ilen < 0)
- return 1; /* buffer too big */
-
- i = i2t_ASN1_OBJECT(buf, ilen, a);
-
- if(i >= ilen)
- return 1; /* buffer too small */
-
- return 0;
-}
-
-#define push_certinfo(_label, _num) \
-do { \
- long info_len = BIO_get_mem_data(mem, &ptr); \
- Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
- if(1 != BIO_reset(mem)) \
- break; \
-} while(0)
-
-static void pubkey_show(struct Curl_easy *data,
- BIO *mem,
- int num,
- const char *type,
- const char *name,
- const BIGNUM *bn)
-{
- char *ptr;
- char namebuf[32];
-
- msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
-
- if(bn)
- BN_print(mem, bn);
- push_certinfo(namebuf, num);
-}
-
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
-#define print_pubkey_BN(_type, _name, _num) \
- pubkey_show(data, mem, _num, #_type, #_name, _name)
-
-#else
-#define print_pubkey_BN(_type, _name, _num) \
-do { \
- if(_type->_name) { \
- pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \
- } \
-} while(0)
-#endif
-
-static void X509V3_ext(struct Curl_easy *data,
- int certnum,
- CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
-{
- int i;
-
- if((int)sk_X509_EXTENSION_num(exts) <= 0)
- /* no extensions, bail out */
- return;
-
- for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
- ASN1_OBJECT *obj;
- X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
- BUF_MEM *biomem;
- char namebuf[128];
- BIO *bio_out = BIO_new(BIO_s_mem());
-
- if(!bio_out)
- return;
-
- obj = X509_EXTENSION_get_object(ext);
-
- asn1_object_dump(obj, namebuf, sizeof(namebuf));
-
- if(!X509V3_EXT_print(bio_out, ext, 0, 0))
- ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
-
- BIO_get_mem_ptr(bio_out, &biomem);
- Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
- biomem->length);
- BIO_free(bio_out);
- }
-}
-
-#ifdef OPENSSL_IS_BORINGSSL
-typedef size_t numcert_t;
-#else
-typedef int numcert_t;
-#endif
-
-static CURLcode get_cert_chain(struct Curl_easy *data,
- struct ssl_connect_data *connssl)
-{
- CURLcode result;
- STACK_OF(X509) *sk;
- int i;
- numcert_t numcerts;
- BIO *mem;
- struct ssl_backend_data *backend = connssl->backend;
-
- DEBUGASSERT(backend);
-
- sk = SSL_get_peer_cert_chain(backend->handle);
- if(!sk) {
- return CURLE_OUT_OF_MEMORY;
- }
-
- numcerts = sk_X509_num(sk);
-
- result = Curl_ssl_init_certinfo(data, (int)numcerts);
- if(result) {
- return result;
- }
-
- mem = BIO_new(BIO_s_mem());
- if(!mem) {
- return CURLE_OUT_OF_MEMORY;
- }
-
- for(i = 0; i < (int)numcerts; i++) {
- ASN1_INTEGER *num;
- X509 *x = sk_X509_value(sk, i);
- EVP_PKEY *pubkey = NULL;
- int j;
- char *ptr;
- const ASN1_BIT_STRING *psig = NULL;
-
- X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
- push_certinfo("Subject", i);
-
- X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
- push_certinfo("Issuer", i);
-
- BIO_printf(mem, "%lx", X509_get_version(x));
- push_certinfo("Version", i);
-
- num = X509_get_serialNumber(x);
- if(num->type == V_ASN1_NEG_INTEGER)
- BIO_puts(mem, "-");
- for(j = 0; j < num->length; j++)
- BIO_printf(mem, "%02x", num->data[j]);
- push_certinfo("Serial Number", i);
-
-#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
- {
- const X509_ALGOR *sigalg = NULL;
- X509_PUBKEY *xpubkey = NULL;
- ASN1_OBJECT *pubkeyoid = NULL;
-
- X509_get0_signature(&psig, &sigalg, x);
- if(sigalg) {
- i2a_ASN1_OBJECT(mem, sigalg->algorithm);
- push_certinfo("Signature Algorithm", i);
- }
-
- xpubkey = X509_get_X509_PUBKEY(x);
- if(xpubkey) {
- X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
- if(pubkeyoid) {
- i2a_ASN1_OBJECT(mem, pubkeyoid);
- push_certinfo("Public Key Algorithm", i);
- }
- }
-
- X509V3_ext(data, i, X509_get0_extensions(x));
- }
-#else
- {
- /* before OpenSSL 1.0.2 */
- X509_CINF *cinf = x->cert_info;
-
- i2a_ASN1_OBJECT(mem, cinf->signature->algorithm);
- push_certinfo("Signature Algorithm", i);
-
- i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm);
- push_certinfo("Public Key Algorithm", i);
-
- X509V3_ext(data, i, cinf->extensions);
-
- psig = x->signature;
- }
-#endif
-
- ASN1_TIME_print(mem, X509_get0_notBefore(x));
- push_certinfo("Start date", i);
-
- ASN1_TIME_print(mem, X509_get0_notAfter(x));
- push_certinfo("Expire date", i);
-
- pubkey = X509_get_pubkey(x);
- if(!pubkey)
- infof(data, " Unable to load public key");
- else {
- int pktype;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- pktype = EVP_PKEY_id(pubkey);
-#else
- pktype = pubkey->type;
-#endif
- switch(pktype) {
- case EVP_PKEY_RSA:
- {
-#ifndef HAVE_EVP_PKEY_GET_PARAMS
- RSA *rsa;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- rsa = EVP_PKEY_get0_RSA(pubkey);
-#else
- rsa = pubkey->pkey.rsa;
-#endif /* HAVE_OPAQUE_EVP_PKEY */
-#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
-
- {
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
- DECLARE_PKEY_PARAM_BIGNUM(n);
- DECLARE_PKEY_PARAM_BIGNUM(e);
-#ifdef HAVE_EVP_PKEY_GET_PARAMS
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e);
-#else
- RSA_get0_key(rsa, &n, &e, NULL);
-#endif /* HAVE_EVP_PKEY_GET_PARAMS */
- BIO_printf(mem, "%d", BN_num_bits(n));
-#else
- BIO_printf(mem, "%d", BN_num_bits(rsa->n));
-#endif /* HAVE_OPAQUE_RSA_DSA_DH */
- push_certinfo("RSA Public Key", i);
- print_pubkey_BN(rsa, n, i);
- print_pubkey_BN(rsa, e, i);
- FREE_PKEY_PARAM_BIGNUM(n);
- FREE_PKEY_PARAM_BIGNUM(e);
- }
-
- break;
- }
- case EVP_PKEY_DSA:
- {
-#ifndef OPENSSL_NO_DSA
-#ifndef HAVE_EVP_PKEY_GET_PARAMS
- DSA *dsa;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- dsa = EVP_PKEY_get0_DSA(pubkey);
-#else
- dsa = pubkey->pkey.dsa;
-#endif /* HAVE_OPAQUE_EVP_PKEY */
-#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
- {
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
- DECLARE_PKEY_PARAM_BIGNUM(p);
- DECLARE_PKEY_PARAM_BIGNUM(q);
- DECLARE_PKEY_PARAM_BIGNUM(g);
- DECLARE_PKEY_PARAM_BIGNUM(pub_key);
-#ifdef HAVE_EVP_PKEY_GET_PARAMS
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
-#else
- DSA_get0_pqg(dsa, &p, &q, &g);
- DSA_get0_key(dsa, &pub_key, NULL);
-#endif /* HAVE_EVP_PKEY_GET_PARAMS */
-#endif /* HAVE_OPAQUE_RSA_DSA_DH */
- print_pubkey_BN(dsa, p, i);
- print_pubkey_BN(dsa, q, i);
- print_pubkey_BN(dsa, g, i);
- print_pubkey_BN(dsa, pub_key, i);
- FREE_PKEY_PARAM_BIGNUM(p);
- FREE_PKEY_PARAM_BIGNUM(q);
- FREE_PKEY_PARAM_BIGNUM(g);
- FREE_PKEY_PARAM_BIGNUM(pub_key);
- }
-#endif /* !OPENSSL_NO_DSA */
- break;
- }
- case EVP_PKEY_DH:
- {
-#ifndef HAVE_EVP_PKEY_GET_PARAMS
- DH *dh;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- dh = EVP_PKEY_get0_DH(pubkey);
-#else
- dh = pubkey->pkey.dh;
-#endif /* HAVE_OPAQUE_EVP_PKEY */
-#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
- {
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
- DECLARE_PKEY_PARAM_BIGNUM(p);
- DECLARE_PKEY_PARAM_BIGNUM(q);
- DECLARE_PKEY_PARAM_BIGNUM(g);
- DECLARE_PKEY_PARAM_BIGNUM(pub_key);
-#ifdef HAVE_EVP_PKEY_GET_PARAMS
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
-#else
- DH_get0_pqg(dh, &p, &q, &g);
- DH_get0_key(dh, &pub_key, NULL);
-#endif /* HAVE_EVP_PKEY_GET_PARAMS */
- print_pubkey_BN(dh, p, i);
- print_pubkey_BN(dh, q, i);
- print_pubkey_BN(dh, g, i);
-#else
- print_pubkey_BN(dh, p, i);
- print_pubkey_BN(dh, g, i);
-#endif /* HAVE_OPAQUE_RSA_DSA_DH */
- print_pubkey_BN(dh, pub_key, i);
- FREE_PKEY_PARAM_BIGNUM(p);
- FREE_PKEY_PARAM_BIGNUM(q);
- FREE_PKEY_PARAM_BIGNUM(g);
- FREE_PKEY_PARAM_BIGNUM(pub_key);
- }
- break;
- }
- }
- EVP_PKEY_free(pubkey);
- }
-
- if(psig) {
- for(j = 0; j < psig->length; j++)
- BIO_printf(mem, "%02x:", psig->data[j]);
- push_certinfo("Signature", i);
- }
-
- PEM_write_bio_X509(mem, x);
- push_certinfo("Cert", i);
- }
-
- BIO_free(mem);
-
- return CURLE_OK;
-}
-
/*
* Heavily modified from:
* https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
@@ -3893,8 +3825,8 @@ static CURLcode servercert(struct Curl_easy *data,
}
if(data->set.ssl.certinfo)
- /* we've been asked to gather certificate info! */
- (void)get_cert_chain(data, connssl);
+ /* asked to gather certificate info */
+ (void)Curl_ossl_certchain(data, connssl->backend->handle);
backend->server_cert = SSL_get1_peer_certificate(backend->handle);
if(!backend->server_cert) {
@@ -4437,7 +4369,7 @@ static size_t ossl_version(char *buffer, size_t size)
}
count = msnprintf(buffer, size, "%s/%s", OSSL_PACKAGE, ver);
for(p = buffer; *p; ++p) {
- if(ISSPACE(*p))
+ if(ISBLANK(*p))
*p = '_';
}
return count;
diff --git a/contrib/libs/curl/lib/vtls/openssl.h b/contrib/libs/curl/lib/vtls/openssl.h
index cb47f4ea81..9df4ecddba 100644
--- a/contrib/libs/curl/lib/vtls/openssl.h
+++ b/contrib/libs/curl/lib/vtls/openssl.h
@@ -31,6 +31,7 @@
* This header should only be needed to get included by vtls.c, openssl.c
* and ngtcp2.c
*/
+#include <openssl/ssl.h>
#include "urldata.h"
@@ -53,5 +54,7 @@ CURLcode Curl_ossl_set_client_cert(struct Curl_easy *data,
const struct curl_blob *key_blob,
const char *key_type, char *key_passwd);
+CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl);
+
#endif /* USE_OPENSSL */
#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/contrib/libs/curl/lib/vtls/rustls.c b/contrib/libs/curl/lib/vtls/rustls.c
index be4af98502..77a49f1ab4 100644
--- a/contrib/libs/curl/lib/vtls/rustls.c
+++ b/contrib/libs/curl/lib/vtls/rustls.c
@@ -415,20 +415,20 @@ cr_set_negotiated_alpn(struct Curl_easy *data, struct connectdata *conn,
#ifdef USE_HTTP2
if(len == ALPN_H2_LENGTH && 0 == memcmp(ALPN_H2, protocol, len)) {
infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, ALPN_H2);
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(len == ALPN_HTTP_1_1_LENGTH &&
0 == memcmp(ALPN_HTTP_1_1, protocol, len)) {
infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, ALPN_HTTP_1_1);
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
}
else {
infof(data, "ALPN, negotiated an unrecognized protocol");
}
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
diff --git a/contrib/libs/curl/lib/vtls/schannel.h b/contrib/libs/curl/lib/vtls/schannel.h
index e6dc0e9359..2acf4dc8ce 100644
--- a/contrib/libs/curl/lib/vtls/schannel.h
+++ b/contrib/libs/curl/lib/vtls/schannel.h
@@ -83,17 +83,23 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data,
/* structs to expose only in schannel.c and schannel_verify.c */
#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+#include <wincrypt.h>
+
#ifdef __MINGW32__
#ifdef __MINGW64_VERSION_MAJOR
#define HAS_MANUAL_VERIFY_API
#endif
#else
-#include <wincrypt.h>
#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)
+#define HAS_CLIENT_CERT_PATH
+#endif
+
#ifndef SCH_CREDENTIALS_VERSION
#define SCH_CREDENTIALS_VERSION 0x00000005
@@ -155,6 +161,9 @@ struct Curl_schannel_cred {
CredHandle cred_handle;
TimeStamp time_stamp;
TCHAR *sni_hostname;
+#ifdef HAS_CLIENT_CERT_PATH
+ HCERTSTORE client_cert_store;
+#endif
int refcount;
};
@@ -179,6 +188,7 @@ struct ssl_backend_data {
CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool recv_renegotiating; /* true if recv is doing renegotiation */
bool use_alpn; /* true if ALPN is used for this connection */
#ifdef HAS_MANUAL_VERIFY_API
bool use_manual_cred_validation; /* true if manual cred validation is used */
diff --git a/contrib/libs/curl/lib/vtls/sectransp.c b/contrib/libs/curl/lib/vtls/sectransp.c
index a18ca4ee9d..c764e3631b 100644
--- a/contrib/libs/curl/lib/vtls/sectransp.c
+++ b/contrib/libs/curl/lib/vtls/sectransp.c
@@ -2847,18 +2847,18 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
#ifdef USE_HTTP2
if(chosenProtocol &&
!CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(chosenProtocol &&
!CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
}
else
infof(data, VTLS_INFOF_NO_ALPN);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
/* chosenProtocol is a reference to the string within alpnArr
diff --git a/contrib/libs/curl/lib/vtls/vtls.c b/contrib/libs/curl/lib/vtls/vtls.c
index 8048ba7a41..9dee5aa3b3 100644
--- a/contrib/libs/curl/lib/vtls/vtls.c
+++ b/contrib/libs/curl/lib/vtls/vtls.c
@@ -146,8 +146,8 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
Curl_safecmp(data->issuercert, needle->issuercert) &&
Curl_safecmp(data->clientcert, needle->clientcert) &&
#ifdef USE_TLS_SRP
- Curl_safecmp(data->username, needle->username) &&
- Curl_safecmp(data->password, needle->password) &&
+ !Curl_timestrcmp(data->username, needle->username) &&
+ !Curl_timestrcmp(data->password, needle->password) &&
(data->authtype == needle->authtype) &&
#endif
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
diff --git a/contrib/libs/curl/lib/vtls/wolfssl.c b/contrib/libs/curl/lib/vtls/wolfssl.c
index b4f07971e6..b068639c80 100644
--- a/contrib/libs/curl/lib/vtls/wolfssl.c
+++ b/contrib/libs/curl/lib/vtls/wolfssl.c
@@ -763,17 +763,17 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
!memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
#ifdef USE_HTTP2
else if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
protocol_len == ALPN_H2_LENGTH &&
!memcmp(protocol, ALPN_H2, ALPN_H2_LENGTH))
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
#endif
else
infof(data, "ALPN, unrecognized protocol %.*s", protocol_len,
protocol);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
else if(rc == SSL_ALPN_NOT_FOUND)
@@ -811,8 +811,10 @@ wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
+ bool added = FALSE;
void *old_ssl_sessionid = NULL;
- SSL_SESSION *our_ssl_sessionid = SSL_get_session(backend->handle);
+ /* SSL_get1_session allocates memory that has to be freed. */
+ SSL_SESSION *our_ssl_sessionid = SSL_get1_session(backend->handle);
bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;
if(our_ssl_sessionid) {
@@ -832,11 +834,20 @@ wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
0, sockindex, NULL);
if(result) {
Curl_ssl_sessionid_unlock(data);
+ SSL_SESSION_free(our_ssl_sessionid);
failf(data, "failed to store ssl session");
return result;
}
+ else {
+ added = TRUE;
+ }
}
Curl_ssl_sessionid_unlock(data);
+
+ if(!added) {
+ /* If the session info wasn't added to the cache, free our copy. */
+ SSL_SESSION_free(our_ssl_sessionid);
+ }
}
}
@@ -956,8 +967,7 @@ static ssize_t wolfssl_recv(struct Curl_easy *data,
static void wolfssl_session_free(void *ptr)
{
- (void)ptr;
- /* wolfSSL reuses sessions on own, no free */
+ SSL_SESSION_free(ptr);
}
diff --git a/contrib/libs/curl/lib/vtls/x509asn1.c b/contrib/libs/curl/lib/vtls/x509asn1.c
index d5661b0976..0cfcbe87da 100644
--- a/contrib/libs/curl/lib/vtls/x509asn1.c
+++ b/contrib/libs/curl/lib/vtls/x509asn1.c
@@ -45,6 +45,7 @@
#include <curl/curl.h>
#include "urldata.h"
#include "strcase.h"
+#include "curl_ctype.h"
#include "hostcheck.h"
#include "vtls/vtls.h"
#include "sendf.h"
@@ -716,7 +717,7 @@ static ssize_t encodeDN(char *buf, size_t buflen, struct Curl_asn1Element *dn)
/* Encode delimiter.
If attribute has a short uppercase name, delimiter is ", ". */
if(l) {
- for(p3 = str; isupper(*p3); p3++)
+ for(p3 = str; ISUPPER(*p3); p3++)
;
for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) {
if(l < buflen)
diff --git a/contrib/libs/curl/lib/warnless.c b/contrib/libs/curl/lib/warnless.c
index 51187aa52e..b00d7a5a26 100644
--- a/contrib/libs/curl/lib/warnless.c
+++ b/contrib/libs/curl/lib/warnless.c
@@ -39,6 +39,8 @@
#include "warnless.h"
+#include <limits.h>
+
#define CURL_MASK_UCHAR ((unsigned char)~0)
#define CURL_MASK_SCHAR (CURL_MASK_UCHAR >> 1)
diff --git a/contrib/libs/curl/lib/wildcard.h b/contrib/libs/curl/lib/wildcard.h
index f9d2167bf2..21e933b9a4 100644
--- a/contrib/libs/curl/lib/wildcard.h
+++ b/contrib/libs/curl/lib/wildcard.h
@@ -27,6 +27,7 @@
#include "curl_setup.h"
#ifndef CURL_DISABLE_FTP
+#include <curl/curl.h>
#include "llist.h"
/* list of wildcard process states */
diff --git a/contrib/libs/curl/lib/ws.c b/contrib/libs/curl/lib/ws.c
new file mode 100644
index 0000000000..a673446625
--- /dev/null
+++ b/contrib/libs/curl/lib/ws.c
@@ -0,0 +1,757 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+#include <curl/curl.h>
+
+#ifdef USE_WEBSOCKETS
+
+#include "urldata.h"
+#include "dynbuf.h"
+#include "rand.h"
+#include "curl_base64.h"
+#include "sendf.h"
+#include "multiif.h"
+#include "ws.h"
+#include "easyif.h"
+#include "transfer.h"
+#include "nonblock.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+struct wsfield {
+ const char *name;
+ const char *val;
+};
+
+CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req)
+{
+ unsigned int i;
+ CURLcode result = CURLE_OK;
+ unsigned char rand[16];
+ char *randstr;
+ size_t randlen;
+ char keyval[40];
+ struct SingleRequest *k = &data->req;
+ struct wsfield heads[]= {
+ {
+ /* The request MUST contain an |Upgrade| header field whose value
+ MUST include the "websocket" keyword. */
+ "Upgrade:", "websocket"
+ },
+ {
+ /* The request MUST contain a |Connection| header field whose value
+ MUST include the "Upgrade" token. */
+ "Connection:", "Upgrade",
+ },
+ {
+ /* The request MUST include a header field with the name
+ |Sec-WebSocket-Version|. The value of this header field MUST be
+ 13. */
+ "Sec-WebSocket-Version:", "13",
+ },
+ {
+ /* The request MUST include a header field with the name
+ |Sec-WebSocket-Key|. The value of this header field MUST be a nonce
+ consisting of a randomly selected 16-byte value that has been
+ base64-encoded (see Section 4 of [RFC4648]). The nonce MUST be
+ selected randomly for each connection. */
+ "Sec-WebSocket-Key:", NULL,
+ }
+ };
+ heads[3].val = &keyval[0];
+
+ /* 16 bytes random */
+ result = Curl_rand(data, (unsigned char *)rand, sizeof(rand));
+ if(result)
+ return result;
+ result = Curl_base64_encode((char *)rand, sizeof(rand), &randstr, &randlen);
+ if(result)
+ return result;
+ DEBUGASSERT(randlen < sizeof(keyval));
+ if(randlen >= sizeof(keyval))
+ return CURLE_FAILED_INIT;
+ strcpy(keyval, randstr);
+ free(randstr);
+ for(i = 0; !result && (i < sizeof(heads)/sizeof(heads[0])); i++) {
+ if(!Curl_checkheaders(data, STRCONST(heads[i].name))) {
+#ifdef USE_HYPER
+ char field[128];
+ msnprintf(field, sizeof(field), "%s %s", heads[i].name,
+ heads[i].val);
+ result = Curl_hyper_header(data, req, field);
+#else
+ (void)data;
+ result = Curl_dyn_addf(req, "%s %s\r\n", heads[i].name,
+ heads[i].val);
+#endif
+ }
+ }
+ k->upgr101 = UPGR101_WS;
+ Curl_dyn_init(&data->req.p.http->ws.buf, MAX_WS_SIZE * 2);
+ return result;
+}
+
+CURLcode Curl_ws_accept(struct Curl_easy *data)
+{
+ struct SingleRequest *k = &data->req;
+ struct HTTP *ws = data->req.p.http;
+ struct connectdata *conn = data->conn;
+ struct websocket *wsp = &data->req.p.http->ws;
+ CURLcode result;
+
+ /* Verify the Sec-WebSocket-Accept response.
+
+ The sent value is the base64 encoded version of a SHA-1 hash done on the
+ |Sec-WebSocket-Key| header field concatenated with
+ the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".
+ */
+
+ /* If the response includes a |Sec-WebSocket-Extensions| header field and
+ this header field indicates the use of an extension that was not present
+ in the client's handshake (the server has indicated an extension not
+ requested by the client), the client MUST Fail the WebSocket Connection.
+ */
+
+ /* If the response includes a |Sec-WebSocket-Protocol| header field
+ and this header field indicates the use of a subprotocol that was
+ not present in the client's handshake (the server has indicated a
+ subprotocol not requested by the client), the client MUST Fail
+ the WebSocket Connection. */
+
+ /* 4 bytes random */
+ result = Curl_rand(data, (unsigned char *)&ws->ws.mask, sizeof(ws->ws.mask));
+ if(result)
+ return result;
+
+ infof(data, "Received 101, switch to WebSocket; mask %02x%02x%02x%02x",
+ ws->ws.mask[0], ws->ws.mask[1], ws->ws.mask[2], ws->ws.mask[3]);
+ k->upgr101 = UPGR101_RECEIVED;
+
+ if(data->set.connect_only)
+ /* switch off non-blocking sockets */
+ (void)curlx_nonblock(conn->sock[FIRSTSOCKET], FALSE);
+
+ wsp->oleft = 0;
+ return result;
+}
+
+#define WSBIT_FIN 0x80
+#define WSBIT_OPCODE_CONT 0
+#define WSBIT_OPCODE_TEXT (1)
+#define WSBIT_OPCODE_BIN (2)
+#define WSBIT_OPCODE_CLOSE (8)
+#define WSBIT_OPCODE_PING (9)
+#define WSBIT_OPCODE_PONG (0xa)
+#define WSBIT_OPCODE_MASK (0xf)
+
+#define WSBIT_MASK 0x80
+
+/* remove the spent bytes from the beginning of the buffer as that part has
+ now been delivered to the application */
+static void ws_decode_clear(struct Curl_easy *data)
+{
+ struct websocket *wsp = &data->req.p.http->ws;
+ size_t spent = wsp->usedbuf;
+ size_t len = Curl_dyn_len(&wsp->buf);
+ size_t keep = len - spent;
+ DEBUGASSERT(len >= spent);
+ Curl_dyn_tail(&wsp->buf, keep);
+}
+
+/* ws_decode() decodes a binary frame into structured WebSocket data,
+
+ wpkt - the incoming raw data. If NULL, work on the already buffered data.
+ ilen - the size of the provided data, perhaps too little, perhaps too much
+ out - stored pointed to extracted data
+ olen - stored length of the extracted data
+ oleft - number of unread bytes pending to that belongs to this frame
+ more - if there is more data in there
+ flags - stored bitmask about the frame
+
+ Returns CURLE_AGAIN if there is only a partial frame in the buffer. Then it
+ stores the first part in the ->extra buffer to be used in the next call
+ when more data is provided.
+*/
+
+static CURLcode ws_decode(struct Curl_easy *data,
+ unsigned char *wpkt, size_t ilen,
+ unsigned char **out, size_t *olen,
+ curl_off_t *oleft,
+ bool *more,
+ unsigned int *flags)
+{
+ bool fin;
+ unsigned char opcode;
+ curl_off_t total;
+ size_t dataindex = 2;
+ curl_off_t plen; /* size of data in the buffer */
+ curl_off_t payloadsize;
+ struct websocket *wsp = &data->req.p.http->ws;
+ unsigned char *p;
+ CURLcode result;
+
+ *olen = 0;
+
+ /* add the incoming bytes, if any */
+ if(wpkt) {
+ result = Curl_dyn_addn(&wsp->buf, wpkt, ilen);
+ if(result)
+ return result;
+ }
+
+ plen = Curl_dyn_len(&wsp->buf);
+ if(plen < 2) {
+ /* the smallest possible frame is two bytes */
+ infof(data, "WS: plen == %u, EAGAIN", (int)plen);
+ return CURLE_AGAIN;
+ }
+
+ p = Curl_dyn_uptr(&wsp->buf);
+
+ fin = p[0] & WSBIT_FIN;
+ opcode = p[0] & WSBIT_OPCODE_MASK;
+ infof(data, "WS:%d received FIN bit %u", __LINE__, (int)fin);
+ *flags = 0;
+ switch(opcode) {
+ case WSBIT_OPCODE_CONT:
+ if(!fin)
+ *flags |= CURLWS_CONT;
+ infof(data, "WS: received OPCODE CONT");
+ break;
+ case WSBIT_OPCODE_TEXT:
+ infof(data, "WS: received OPCODE TEXT");
+ *flags |= CURLWS_TEXT;
+ break;
+ case WSBIT_OPCODE_BIN:
+ infof(data, "WS: received OPCODE BINARY");
+ *flags |= CURLWS_BINARY;
+ break;
+ case WSBIT_OPCODE_CLOSE:
+ infof(data, "WS: received OPCODE CLOSE");
+ *flags |= CURLWS_CLOSE;
+ break;
+ case WSBIT_OPCODE_PING:
+ infof(data, "WS: received OPCODE PING");
+ *flags |= CURLWS_PING;
+ break;
+ case WSBIT_OPCODE_PONG:
+ infof(data, "WS: received OPCODE PONG");
+ *flags |= CURLWS_PONG;
+ break;
+ }
+
+ if(p[1] & WSBIT_MASK) {
+ /* A client MUST close a connection if it detects a masked frame. */
+ failf(data, "WS: masked input frame");
+ return CURLE_RECV_ERROR;
+ }
+ payloadsize = p[1];
+ if(payloadsize == 126) {
+ if(plen < 4) {
+ infof(data, "WS:%d plen == %u, EAGAIN", __LINE__, (int)plen);
+ return CURLE_AGAIN; /* not enough data available */
+ }
+ payloadsize = (p[2] << 8) | p[3];
+ dataindex += 2;
+ }
+ else if(payloadsize == 127) {
+ /* 64 bit payload size */
+ if(plen < 10)
+ return CURLE_AGAIN;
+ if(p[2] & 80) {
+ failf(data, "WS: too large frame");
+ return CURLE_RECV_ERROR;
+ }
+ dataindex += 8;
+ payloadsize = ((curl_off_t)p[2] << 56) |
+ (curl_off_t)p[3] << 48 |
+ (curl_off_t)p[4] << 40 |
+ (curl_off_t)p[5] << 32 |
+ (curl_off_t)p[6] << 24 |
+ (curl_off_t)p[7] << 16 |
+ (curl_off_t)p[8] << 8 |
+ p[9];
+ }
+
+ total = dataindex + payloadsize;
+ if(total > plen) {
+ /* deliver a partial frame */
+ *oleft = total - dataindex;
+ payloadsize = total - dataindex;
+ }
+ else {
+ *oleft = 0;
+ if(plen > total)
+ /* there is another fragment after */
+ *more = TRUE;
+ }
+
+ /* point to the payload */
+ *out = &p[dataindex];
+
+ /* return the payload length */
+ *olen = payloadsize;
+
+ /* number of bytes "used" from the buffer */
+ wsp->usedbuf = dataindex + payloadsize;
+ infof(data, "WS: received %zu bytes payload (%zu left)",
+ payloadsize, *oleft);
+ return CURLE_OK;
+}
+
+/* Curl_ws_writecb() is the write callback for websocket traffic. The
+ websocket data is provided to this raw, in chunks. This function should
+ handle/decode the data and call the "real" underlying callback accordingly.
+*/
+size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
+ size_t nitems, void *userp)
+{
+ struct HTTP *ws = (struct HTTP *)userp;
+ struct Curl_easy *data = ws->ws.data;
+ void *writebody_ptr = data->set.out;
+ if(data->set.ws_raw_mode)
+ return data->set.fwrite_func(buffer, size, nitems, writebody_ptr);
+ else if(nitems) {
+ unsigned char *frame = NULL;
+ size_t flen = 0;
+ size_t wrote = 0;
+ CURLcode result;
+ bool more; /* there's is more to parse in the buffer */
+ curl_off_t oleft;
+
+ decode:
+ more = FALSE;
+ oleft = ws->ws.frame.bytesleft;
+ if(!oleft) {
+ unsigned int recvflags;
+ result = ws_decode(data, (unsigned char *)buffer, nitems,
+ &frame, &flen, &oleft, &more, &recvflags);
+ if(result == CURLE_AGAIN)
+ /* insufficient amount of data, keep it for later */
+ return nitems;
+ else if(result) {
+ infof(data, "WS: decode error %d", (int)result);
+ return nitems - 1;
+ }
+ /* Store details about the frame to be reachable with curl_ws_meta()
+ from within the write callback */
+ ws->ws.frame.age = 0;
+ ws->ws.frame.offset = 0;
+ ws->ws.frame.flags = recvflags;
+ ws->ws.frame.bytesleft = oleft;
+ }
+ else {
+ if(nitems > (size_t)ws->ws.frame.bytesleft) {
+ nitems = ws->ws.frame.bytesleft;
+ more = TRUE;
+ }
+ else
+ more = FALSE;
+ ws->ws.frame.offset += nitems;
+ ws->ws.frame.bytesleft -= nitems;
+ frame = (unsigned char *)buffer;
+ flen = nitems;
+ }
+ if((ws->ws.frame.flags & CURLWS_PING) && !oleft) {
+ /* auto-respond to PINGs, only works for single-frame payloads atm */
+ size_t bytes;
+ infof(data, "WS: auto-respond to PING with a PONG");
+ DEBUGASSERT(frame);
+ /* send back the exact same content as a PONG */
+ result = curl_ws_send(data, frame, flen, &bytes, 0, CURLWS_PONG);
+ if(result)
+ return result;
+ }
+ else {
+ /* deliver the decoded frame to the user callback */
+ Curl_set_in_callback(data, true);
+ wrote = data->set.fwrite_func((char *)frame, 1, flen, writebody_ptr);
+ Curl_set_in_callback(data, false);
+ if(wrote != flen)
+ return 0;
+ }
+ if(oleft)
+ ws->ws.frame.offset += flen;
+ /* the websocket frame has been delivered */
+ ws_decode_clear(data);
+ if(more) {
+ /* there's more websocket data to deal with in the buffer */
+ buffer = NULL; /* the buffer as been drained already */
+ goto decode;
+ }
+ }
+ return nitems;
+}
+
+
+CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
+ size_t buflen, size_t *nread,
+ struct curl_ws_frame **metap)
+{
+ size_t bytes;
+ CURLcode result;
+ struct websocket *wsp = &data->req.p.http->ws;
+
+ *nread = 0;
+ *metap = NULL;
+ /* get a download buffer */
+ result = Curl_preconnect(data);
+ if(result)
+ return result;
+
+ do {
+ bool drain = FALSE; /* if there is pending buffered data to drain */
+ char *inbuf = data->state.buffer;
+ bytes = wsp->stillbuffer;
+ if(!bytes) {
+ result = curl_easy_recv(data, data->state.buffer,
+ data->set.buffer_size, &bytes);
+ if(result)
+ return result;
+ }
+ else {
+ /* the pending bytes can be found here */
+ inbuf = wsp->stillb;
+ drain = TRUE;
+ }
+ if(bytes) {
+ unsigned char *out;
+ size_t olen;
+ bool more;
+ unsigned int recvflags;
+ curl_off_t oleft = wsp->frame.bytesleft;
+
+ infof(data, "WS: got %u websocket bytes to decode", (int)bytes);
+ if(!oleft && !drain) {
+ result = ws_decode(data, (unsigned char *)inbuf, bytes,
+ &out, &olen, &oleft, &more, &recvflags);
+ if(result == CURLE_AGAIN)
+ /* a packet fragment only */
+ break;
+ else if(result)
+ return result;
+ wsp->frame.offset = 0;
+ wsp->frame.bytesleft = oleft;
+ wsp->frame.flags = recvflags;
+ }
+ else {
+ olen = oleft;
+ out = (unsigned char *)wsp->stillb;
+ recvflags = wsp->frame.flags;
+ if((curl_off_t)buflen < oleft)
+ /* there is still data left after this */
+ wsp->frame.bytesleft -= buflen;
+ else
+ wsp->frame.bytesleft = 0;
+ }
+
+ /* auto-respond to PINGs */
+ if((recvflags & CURLWS_PING) && !oleft) {
+ infof(data, "WS: auto-respond to PING with a PONG");
+ /* send back the exact same content as a PONG */
+ result = curl_ws_send(data, out, olen, &bytes, 0, CURLWS_PONG);
+ if(result)
+ return result;
+ }
+ else {
+ if(olen < buflen) {
+ /* copy the payload to the user buffer */
+ memcpy(buffer, out, olen);
+ *nread = olen;
+ if(!oleft)
+ /* websocket frame has been delivered */
+ ws_decode_clear(data);
+ }
+ else {
+ /* copy a partial payload */
+ memcpy(buffer, out, buflen);
+ *nread = buflen;
+ /* remember what is left and where */
+ wsp->stillbuffer = olen - buflen;
+ wsp->stillb = (char *)buffer + buflen;
+ }
+ wsp->frame.offset += *nread;
+ }
+ }
+ else
+ *nread = bytes;
+ break;
+ } while(1);
+ *metap = &wsp->frame;
+ return CURLE_OK;
+}
+
+static void ws_xor(struct Curl_easy *data,
+ const unsigned char *source,
+ unsigned char *dest,
+ size_t len)
+{
+ struct websocket *wsp = &data->req.p.http->ws;
+ size_t i;
+ /* append payload after the mask, XOR appropriately */
+ for(i = 0; i < len; i++) {
+ dest[i] = source[i] ^ wsp->mask[wsp->xori];
+ wsp->xori++;
+ wsp->xori &= 3;
+ }
+}
+
+/***
+ RFC 6455 Section 5.2
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-------+-+-------------+-------------------------------+
+ |F|R|R|R| opcode|M| Payload len | Extended payload length |
+ |I|S|S|S| (4) |A| (7) | (16/64) |
+ |N|V|V|V| |S| | (if payload len==126/127) |
+ | |1|2|3| |K| | |
+ +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+ | Extended payload length continued, if payload len == 127 |
+ + - - - - - - - - - - - - - - - +-------------------------------+
+ | |Masking-key, if MASK set to 1 |
+ +-------------------------------+-------------------------------+
+ | Masking-key (continued) | Payload Data |
+ +-------------------------------- - - - - - - - - - - - - - - - +
+ : Payload Data continued ... :
+ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+ | Payload Data continued ... |
+ +---------------------------------------------------------------+
+*/
+
+static size_t ws_packethead(struct Curl_easy *data,
+ size_t len, unsigned int flags)
+{
+ struct HTTP *ws = data->req.p.http;
+ unsigned char *out = (unsigned char *)data->state.ulbuf;
+ unsigned char firstbyte = 0;
+ int outi;
+ unsigned char opcode;
+ if(flags & CURLWS_TEXT) {
+ opcode = WSBIT_OPCODE_TEXT;
+ infof(data, "WS: send OPCODE TEXT");
+ }
+ else if(flags & CURLWS_CLOSE) {
+ opcode = WSBIT_OPCODE_CLOSE;
+ infof(data, "WS: send OPCODE CLOSE");
+ }
+ else if(flags & CURLWS_PING) {
+ opcode = WSBIT_OPCODE_PING;
+ infof(data, "WS: send OPCODE PING");
+ }
+ else if(flags & CURLWS_PONG) {
+ opcode = WSBIT_OPCODE_PONG;
+ infof(data, "WS: send OPCODE PONG");
+ }
+ else {
+ opcode = WSBIT_OPCODE_BIN;
+ infof(data, "WS: send OPCODE BINARY");
+ }
+
+ if(!(flags & CURLWS_CONT)) {
+ /* if not marked as continuing, assume this is the final fragment */
+ firstbyte |= WSBIT_FIN | opcode;
+ ws->ws.contfragment = FALSE;
+ }
+ else if(ws->ws.contfragment) {
+ /* the previous fragment was not a final one and this isn't either, keep a
+ CONT opcode and no FIN bit */
+ firstbyte |= WSBIT_OPCODE_CONT;
+ }
+ else {
+ ws->ws.contfragment = TRUE;
+ }
+ out[0] = firstbyte;
+ if(len > 65535) {
+ out[1] = 127 | WSBIT_MASK;
+ out[2] = (len >> 8) & 0xff;
+ out[3] = len & 0xff;
+ outi = 10;
+ }
+ else if(len > 126) {
+ out[1] = 126 | WSBIT_MASK;
+ out[2] = (len >> 8) & 0xff;
+ out[3] = len & 0xff;
+ outi = 4;
+ }
+ else {
+ out[1] = (unsigned char)len | WSBIT_MASK;
+ outi = 2;
+ }
+
+ infof(data, "WS: send FIN bit %u (byte %02x)",
+ firstbyte & WSBIT_FIN ? 1 : 0,
+ firstbyte);
+ infof(data, "WS: send payload len %u", (int)len);
+
+ /* 4 bytes mask */
+ memcpy(&out[outi], &ws->ws.mask, 4);
+
+ if(data->set.upload_buffer_size < (len + 10))
+ return 0;
+
+ /* pass over the mask */
+ outi += 4;
+
+ ws->ws.xori = 0;
+ /* return packet size */
+ return outi;
+}
+
+CURL_EXTERN CURLcode curl_ws_send(struct Curl_easy *data, const void *buffer,
+ size_t buflen, size_t *sent,
+ curl_off_t totalsize,
+ unsigned int sendflags)
+{
+ CURLcode result;
+ size_t headlen;
+ char *out;
+ ssize_t written;
+ struct websocket *wsp = &data->req.p.http->ws;
+
+ if(!data->set.ws_raw_mode) {
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
+ }
+ else {
+ if(totalsize || sendflags)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ if(data->set.ws_raw_mode) {
+ if(!buflen)
+ /* nothing to do */
+ return CURLE_OK;
+ /* raw mode sends exactly what was requested, and this is from within
+ the write callback */
+ if(Curl_is_in_callback(data))
+ result = Curl_write(data, data->conn->writesockfd, buffer, buflen,
+ &written);
+ else
+ result = Curl_senddata(data, buffer, buflen, &written);
+
+ infof(data, "WS: wanted to send %zu bytes, sent %zu bytes",
+ buflen, written);
+ *sent = written;
+ return result;
+ }
+
+ if(buflen > (data->set.upload_buffer_size - 10))
+ /* don't do more than this in one go */
+ buflen = data->set.upload_buffer_size - 10;
+
+ if(sendflags & CURLWS_OFFSET) {
+ if(totalsize) {
+ /* a frame series 'totalsize' bytes big, this is the first */
+ headlen = ws_packethead(data, totalsize, sendflags);
+ wsp->sleft = totalsize - buflen;
+ }
+ else {
+ headlen = 0;
+ if((curl_off_t)buflen > wsp->sleft) {
+ infof(data, "WS: unaligned frame size (sending %zu instead of %zu)",
+ buflen, wsp->sleft);
+ wsp->sleft = 0;
+ }
+ else
+ wsp->sleft -= buflen;
+ }
+ }
+ else
+ headlen = ws_packethead(data, buflen, sendflags);
+
+ /* headlen is the size of the frame header */
+ out = data->state.ulbuf;
+ if(buflen)
+ /* for PING and PONG etc there might not be a payload */
+ ws_xor(data, buffer, (unsigned char *)out + headlen, buflen);
+
+ if(data->set.connect_only)
+ result = Curl_senddata(data, out, buflen + headlen, &written);
+ else
+ result = Curl_write(data, data->conn->writesockfd, out,
+ buflen + headlen, &written);
+
+ infof(data, "WS: wanted to send %zu bytes, sent %zu bytes",
+ headlen + buflen, written);
+ *sent = written;
+
+ return result;
+}
+
+void Curl_ws_done(struct Curl_easy *data)
+{
+ struct websocket *wsp = &data->req.p.http->ws;
+ DEBUGASSERT(wsp);
+ Curl_dyn_free(&wsp->buf);
+}
+
+CURL_EXTERN struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
+{
+ /* we only return something for websocket, called from within the callback
+ when not using raw mode */
+ if(GOOD_EASY_HANDLE(data) && Curl_is_in_callback(data) && data->req.p.http &&
+ !data->set.ws_raw_mode)
+ return &data->req.p.http->ws.frame;
+ return NULL;
+}
+
+#else
+
+CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *nread,
+ struct curl_ws_frame **metap)
+{
+ (void)curl;
+ (void)buffer;
+ (void)buflen;
+ (void)nread;
+ (void)metap;
+ return CURLE_OK;
+}
+
+CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *sent,
+ curl_off_t framesize,
+ unsigned int sendflags)
+{
+ (void)curl;
+ (void)buffer;
+ (void)buflen;
+ (void)sent;
+ (void)framesize;
+ (void)sendflags;
+ return CURLE_OK;
+}
+
+CURL_EXTERN struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
+{
+ (void)data;
+ return NULL;
+}
+#endif /* USE_WEBSOCKETS */
diff --git a/contrib/libs/curl/lib/ws.h b/contrib/libs/curl/lib/ws.h
new file mode 100644
index 0000000000..341242e50e
--- /dev/null
+++ b/contrib/libs/curl/lib/ws.h
@@ -0,0 +1,69 @@
+#ifndef HEADER_CURL_WS_H
+#define HEADER_CURL_WS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_WEBSOCKETS
+
+#ifdef USE_HYPER
+#define REQTYPE void
+#else
+#define REQTYPE struct dynbuf
+#endif
+
+/* this is the largest single fragment size we support */
+#define MAX_WS_SIZE 65535
+
+/* part of 'struct HTTP', when used in the 'struct SingleRequest' in the
+ Curl_easy struct */
+struct websocket {
+ bool contfragment; /* set TRUE if the previous fragment sent was not final */
+ unsigned char mask[4]; /* 32 bit mask for this connection */
+ struct Curl_easy *data; /* used for write callback handling */
+ struct dynbuf buf;
+ size_t usedbuf; /* number of leading bytes in 'buf' the most recent complete
+ websocket frame uses */
+ struct curl_ws_frame frame; /* the struct used for frame state */
+ curl_off_t oleft; /* outstanding number of payload bytes left from the
+ server */
+ curl_off_t stillbuffer; /* number of bytes left in the buffer to deliver in
+ the next curl_ws_recv() call */
+ char *stillb; /* the stillbuffer pending bytes are here */
+ curl_off_t sleft; /* outstanding number of payload bytes left to send */
+ unsigned int xori; /* xor index */
+};
+
+CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req);
+CURLcode Curl_ws_accept(struct Curl_easy *data);
+
+size_t Curl_ws_writecb(char *buffer, size_t size, size_t nitems, void *userp);
+void Curl_ws_done(struct Curl_easy *data);
+
+#else
+#define Curl_ws_request(x,y) CURLE_OK
+#define Curl_ws_done(x) Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_WS_H */