Compare commits

...

No commits in common. 'c9' and 'c10-beta' have entirely different histories.
c9 ... c10-beta

@ -1 +1 @@
d38ab79ef7a6d92df91ca8dfcf9a5eaf7e25b725 SOURCES/curl-7.76.1.tar.xz
94de342de8f75adf02d49aa782b003c3f7147d16 SOURCES/curl-8.9.1.tar.xz

2
.gitignore vendored

@ -1 +1 @@
SOURCES/curl-7.76.1.tar.xz
SOURCES/curl-8.9.1.tar.xz

@ -1,133 +0,0 @@
From 2281afef6757ed66c9e8a9a737aa91cb9e2950ef Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Fri, 30 Apr 2021 18:14:45 +0200
Subject: [PATCH 1/2] http2: fix resource leaks in set_transfer_url()
... detected by Coverity:
Error: RESOURCE_LEAK (CWE-772):
lib/http2.c:480: alloc_fn: Storage is returned from allocation function "curl_url". [Note: The source code implementation of the function has been overridden by a builtin model.]
lib/http2.c:480: var_assign: Assigning: "u" = storage returned from "curl_url()".
lib/http2.c:486: noescape: Resource "u" is not freed or pointed-to in "curl_url_set". [Note: The source code implementation of the function has been overridden by a builtin model.]
lib/http2.c:488: leaked_storage: Variable "u" going out of scope leaks the storage it points to.
Error: RESOURCE_LEAK (CWE-772):
lib/http2.c:480: alloc_fn: Storage is returned from allocation function "curl_url". [Note: The source code implementation of the function has been overridden by a builtin model.]
lib/http2.c:480: var_assign: Assigning: "u" = storage returned from "curl_url()".
lib/http2.c:493: noescape: Resource "u" is not freed or pointed-to in "curl_url_set". [Note: The source code implementation of the function has been overridden by a builtin model.]
lib/http2.c:495: leaked_storage: Variable "u" going out of scope leaks the storage it points to.
Error: RESOURCE_LEAK (CWE-772):
lib/http2.c:480: alloc_fn: Storage is returned from allocation function "curl_url". [Note: The source code implementation of the function has been overridden by a builtin model.]
lib/http2.c:480: var_assign: Assigning: "u" = storage returned from "curl_url()".
lib/http2.c:500: noescape: Resource "u" is not freed or pointed-to in "curl_url_set". [Note: The source code implementation of the function has been overridden by a builtin model.]
lib/http2.c:502: leaked_storage: Variable "u" going out of scope leaks the storage it points to.
Error: RESOURCE_LEAK (CWE-772):
lib/http2.c:480: alloc_fn: Storage is returned from allocation function "curl_url". [Note: The source code implementation of the function has been overridden by a builtin model.]
lib/http2.c:480: var_assign: Assigning: "u" = storage returned from "curl_url()".
lib/http2.c:505: noescape: Resource "u" is not freed or pointed-to in "curl_url_get". [Note: The source code implementation of the function has been overridden by a builtin model.]
lib/http2.c:507: leaked_storage: Variable "u" going out of scope leaks the storage it points to.
Closes #6986
Upstream-commit: 31931704707324af4b4edb24cc877829f7e9949e
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/http2.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/lib/http2.c b/lib/http2.c
index ce9a0d3..d5ba89b 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -500,32 +500,42 @@ static int set_transfer_url(struct Curl_easy *data,
CURLU *u = curl_url();
CURLUcode uc;
char *url;
+ int rc = 0;
v = curl_pushheader_byname(hp, ":scheme");
if(v) {
uc = curl_url_set(u, CURLUPART_SCHEME, v, 0);
- if(uc)
- return 1;
+ if(uc) {
+ rc = 1;
+ goto fail;
+ }
}
v = curl_pushheader_byname(hp, ":authority");
if(v) {
uc = curl_url_set(u, CURLUPART_HOST, v, 0);
- if(uc)
- return 2;
+ if(uc) {
+ rc = 2;
+ goto fail;
+ }
}
v = curl_pushheader_byname(hp, ":path");
if(v) {
uc = curl_url_set(u, CURLUPART_PATH, v, 0);
- if(uc)
- return 3;
+ if(uc) {
+ rc = 3;
+ goto fail;
+ }
}
uc = curl_url_get(u, CURLUPART_URL, &url, 0);
if(uc)
- return 4;
+ rc = 4;
+ fail:
curl_url_cleanup(u);
+ if(rc)
+ return rc;
if(data->state.url_alloc)
free(data->state.url);
--
2.30.2
From 92ad72983f8462be1d5a5228672657ddf4d7ed72 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Fri, 30 Apr 2021 18:18:02 +0200
Subject: [PATCH 2/2] http2: fix a resource leak in push_promise()
... detected by Coverity:
Error: RESOURCE_LEAK (CWE-772):
lib/http2.c:532: alloc_fn: Storage is returned from allocation function "duphandle".
lib/http2.c:532: var_assign: Assigning: "newhandle" = storage returned from "duphandle(data)".
lib/http2.c:552: noescape: Resource "newhandle" is not freed or pointed-to in "set_transfer_url".
lib/http2.c:555: leaked_storage: Variable "newhandle" going out of scope leaks the storage it points to.
Closes #6986
Upstream-commit: 3a6058cb976981ec1db870f9657c73c9a1162822
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/http2.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/http2.c b/lib/http2.c
index d5ba89b..d0f69ea 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -581,6 +581,7 @@ static int push_promise(struct Curl_easy *data,
rv = set_transfer_url(newhandle, &heads);
if(rv) {
+ (void)Curl_close(&newhandle);
rv = CURL_PUSH_DENY;
goto fail;
}
--
2.30.2

@ -0,0 +1,35 @@
From 3eec5afbd0b6377eca893c392569b2faf094d970 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 5 Aug 2024 00:17:17 +0200
Subject: [PATCH] sigpipe: init the struct so that first apply ignores
Initializes 'no_signal' to TRUE, so that a call to sigpipe_apply() after
init ignores the signal (unless CURLOPT_NOSIGNAL) is set.
I have read the existing code multiple times now and I think it gets the
initial state reversed this missing to ignore.
Regression from 17e6f06ea37136c36d27
Reported-by: Rasmus Thomsen
Fixes #14344
Closes #14390
---
lib/sigpipe.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/sigpipe.h b/lib/sigpipe.h
index b91a2f513..d78afd905 100644
--- a/lib/sigpipe.h
+++ b/lib/sigpipe.h
@@ -39,6 +39,7 @@ struct sigpipe_ignore {
static void sigpipe_init(struct sigpipe_ignore *ig)
{
memset(ig, 0, sizeof(*ig));
+ ig->no_signal = TRUE;
}
/*
--
2.45.2

@ -1,31 +0,0 @@
From 886f7458bbf005299f3f8224103d1903cd6fa7a4 Mon Sep 17 00:00:00 2001
From: Harry Sintonen <sintonen@iki.fi>
Date: Fri, 7 May 2021 13:09:57 +0200
Subject: [PATCH] telnet: check sscanf() for correct number of matches
CVE-2021-22898
Bug: https://curl.se/docs/CVE-2021-22898.html
Upstream-commit: 39ce47f219b09c380b81f89fe54ac586c8db6bde
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/telnet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/telnet.c b/lib/telnet.c
index f96a4cb..4551435 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -921,7 +921,7 @@ static void suboption(struct Curl_easy *data)
size_t tmplen = (strlen(v->data) + 1);
/* Add the variable only if it fits */
if(len + tmplen < (int)sizeof(temp)-6) {
- if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
+ if(sscanf(v->data, "%127[^,],%127s", varname, varval) == 2) {
msnprintf((char *)&temp[len], sizeof(temp) - len,
"%c%s%c%s", CURL_NEW_ENV_VAR, varname,
CURL_NEW_ENV_VALUE, varval);
--
2.31.1

File diff suppressed because it is too large Load Diff

@ -1,44 +0,0 @@
From 39b68b3f82535d06e50443db4c191dbaa00df4eb Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <patrick@monnerat.net>
Date: Fri, 23 Apr 2021 00:33:46 +0200
Subject: [PATCH] vtls: reset ssl use flag upon negotiation failure
Fixes the segfault in ldaps disconnect.
Reported-by: Illarion Taev
Fixes #6934
Closes #6937
Upstream-commit: a4554b2c5e7c5788c8198001598818599c60ff7d
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/vtls/vtls.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 22cfb88..fa8a6fa 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -315,6 +315,8 @@ Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
if(!result)
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
+ else
+ conn->ssl[sockindex].use = FALSE;
return result;
}
@@ -338,7 +340,9 @@ Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
/* mark this is being ssl requested from here on. */
conn->ssl[sockindex].use = TRUE;
result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
- if(!result && *done)
+ if(result)
+ conn->ssl[sockindex].use = FALSE;
+ else if(*done)
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
return result;
}
--
2.31.1

@ -1,279 +0,0 @@
From 30c7b4dd01734b6ba20bfc7790b9fe8bc0500214 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 19 Jun 2021 00:42:28 +0200
Subject: [PATCH] vtls: fix connection reuse checks for issuer cert and case
sensitivity
CVE-2021-22924
Reported-by: Harry Sintonen
Bug: https://curl.se/docs/CVE-2021-22924.html
Upstream-commit: 5ea3145850ebff1dc2b13d17440300a01ca38161
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/url.c | 10 ++++++----
lib/urldata.h | 4 ++--
lib/vtls/gtls.c | 10 +++++-----
lib/vtls/nss.c | 4 ++--
lib/vtls/openssl.c | 18 +++++++++---------
lib/vtls/vtls.c | 26 +++++++++++++++++++++-----
6 files changed, 45 insertions(+), 27 deletions(-)
diff --git a/lib/url.c b/lib/url.c
index 9f2c9f2..bdcb095 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -3723,6 +3723,8 @@ static CURLcode create_conn(struct Curl_easy *data,
*/
data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
+ data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+ data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
data->set.ssl.primary.cipher_list =
@@ -3747,8 +3749,11 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.primary.pinned_key =
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
+ data->set.proxy_ssl.primary.issuercert =
+ data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+ data->set.proxy_ssl.primary.issuercert_blob =
+ data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
- data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
@@ -3757,7 +3762,6 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
#endif
data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
- data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
data->set.ssl.key = data->set.str[STRING_KEY];
data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
@@ -3771,9 +3775,7 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
#endif
#endif
-
data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
- data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
&conn->ssl_config)) {
diff --git a/lib/urldata.h b/lib/urldata.h
index 2bb7d81..7cf63d0 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -246,6 +246,7 @@ struct ssl_primary_config {
long version_max; /* max supported version the client wants to use*/
char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* certificate to verify peer against */
+ char *issuercert; /* optional issuer certificate filename */
char *clientcert;
char *random_file; /* path to file containing "random" data */
char *egdsocket; /* path to file containing the EGD daemon socket */
@@ -253,6 +254,7 @@ struct ssl_primary_config {
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
char *pinned_key;
struct curl_blob *cert_blob;
+ struct curl_blob *issuercert_blob;
char *curves; /* list of curves to use */
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
@@ -264,8 +266,6 @@ struct ssl_config_data {
struct ssl_primary_config primary;
long certverifyresult; /* result from the certificate verification */
char *CRLfile; /* CRL to check certificate revocation */
- char *issuercert;/* optional issuer certificate filename */
- struct curl_blob *issuercert_blob;
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
void *fsslctxp; /* parameter for call back */
char *cert_type; /* format for certificate (default: PEM)*/
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index ea54fe3..ccc5ce8 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -849,7 +849,7 @@ gtls_connect_step3(struct Curl_easy *data,
if(!chainp) {
if(SSL_CONN_CONFIG(verifypeer) ||
SSL_CONN_CONFIG(verifyhost) ||
- SSL_SET_OPTION(issuercert)) {
+ SSL_CONN_CONFIG(issuercert)) {
#ifdef HAVE_GNUTLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
&& SSL_SET_OPTION(username) != NULL
@@ -1033,21 +1033,21 @@ gtls_connect_step3(struct Curl_easy *data,
gnutls_x509_crt_t format */
gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
- if(SSL_SET_OPTION(issuercert)) {
+ if(SSL_CONN_CONFIG(issuercert)) {
gnutls_x509_crt_init(&x509_issuer);
- issuerp = load_file(SSL_SET_OPTION(issuercert));
+ issuerp = load_file(SSL_CONN_CONFIG(issuercert));
gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
gnutls_x509_crt_deinit(x509_issuer);
unload_file(issuerp);
if(rc <= 0) {
failf(data, "server certificate issuer check failed (IssuerCert: %s)",
- SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
+ SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_ISSUER_ERROR;
}
infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
- SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
+ SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
}
size = sizeof(certname);
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index ae3945c..b0b1e8c 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -2156,9 +2156,9 @@ static CURLcode nss_do_connect(struct Curl_easy *data,
if(result)
goto error;
- if(SSL_SET_OPTION(issuercert)) {
+ if(SSL_CONN_CONFIG(issuercert)) {
SECStatus ret = SECFailure;
- char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
+ char *nickname = dup_nickname(data, SSL_CONN_CONFIG(issuercert));
if(nickname) {
/* we support only nicknames in case of issuercert for now */
ret = check_issuer_cert(backend->handle, nickname);
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 2404393..be7b811 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -3872,10 +3872,10 @@ static CURLcode servercert(struct Curl_easy *data,
deallocating the certificate. */
/* e.g. match issuer name with provided issuer certificate */
- if(SSL_SET_OPTION(issuercert) || SSL_SET_OPTION(issuercert_blob)) {
- if(SSL_SET_OPTION(issuercert_blob))
- fp = BIO_new_mem_buf(SSL_SET_OPTION(issuercert_blob)->data,
- (int)SSL_SET_OPTION(issuercert_blob)->len);
+ if(SSL_CONN_CONFIG(issuercert) || SSL_CONN_CONFIG(issuercert_blob)) {
+ if(SSL_CONN_CONFIG(issuercert_blob))
+ fp = BIO_new_mem_buf(SSL_CONN_CONFIG(issuercert_blob)->data,
+ (int)SSL_CONN_CONFIG(issuercert_blob)->len);
else {
fp = BIO_new(BIO_s_file());
if(fp == NULL) {
@@ -3889,10 +3889,10 @@ static CURLcode servercert(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
- if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) {
+ if(BIO_read_filename(fp, SSL_CONN_CONFIG(issuercert)) <= 0) {
if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -3904,7 +3904,7 @@ static CURLcode servercert(struct Curl_easy *data,
if(!issuer) {
if(strict)
failf(data, "SSL: Unable to read issuer cert (%s)",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(issuer);
X509_free(backend->server_cert);
@@ -3915,7 +3915,7 @@ static CURLcode servercert(struct Curl_easy *data,
if(X509_check_issued(issuer, backend->server_cert) != X509_V_OK) {
if(strict)
failf(data, "SSL: Certificate issuer check failed (%s)",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(issuer);
X509_free(backend->server_cert);
@@ -3924,7 +3924,7 @@ static CURLcode servercert(struct Curl_easy *data,
}
infof(data, " SSL certificate issuer check ok (%s)\n",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(issuer);
}
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index fa8a6fa..1aa6fc8 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -125,6 +125,16 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
return !memcmp(first->data, second->data, first->len); /* same data */
}
+static bool safecmp(char *a, char *b)
+{
+ if(a && b)
+ return !strcmp(a, b);
+ else if(!a && !b)
+ return TRUE; /* match */
+ return FALSE; /* no match */
+}
+
+
bool
Curl_ssl_config_matches(struct ssl_primary_config *data,
struct ssl_primary_config *needle)
@@ -135,11 +145,13 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
(data->verifyhost == needle->verifyhost) &&
(data->verifystatus == needle->verifystatus) &&
blobcmp(data->cert_blob, needle->cert_blob) &&
- Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
- Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
- Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
- Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
- Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
+ blobcmp(data->issuercert_blob, needle->issuercert_blob) &&
+ safecmp(data->CApath, needle->CApath) &&
+ safecmp(data->CAfile, needle->CAfile) &&
+ safecmp(data->issuercert, needle->issuercert) &&
+ safecmp(data->clientcert, needle->clientcert) &&
+ safecmp(data->random_file, needle->random_file) &&
+ safecmp(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
Curl_safe_strcasecompare(data->curves, needle->curves) &&
@@ -161,8 +173,10 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
dest->sessionid = source->sessionid;
CLONE_BLOB(cert_blob);
+ CLONE_BLOB(issuercert_blob);
CLONE_STRING(CApath);
CLONE_STRING(CAfile);
+ CLONE_STRING(issuercert);
CLONE_STRING(clientcert);
CLONE_STRING(random_file);
CLONE_STRING(egdsocket);
@@ -178,6 +192,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
{
Curl_safefree(sslc->CApath);
Curl_safefree(sslc->CAfile);
+ Curl_safefree(sslc->issuercert);
Curl_safefree(sslc->clientcert);
Curl_safefree(sslc->random_file);
Curl_safefree(sslc->egdsocket);
@@ -185,6 +200,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
Curl_safefree(sslc->cipher_list13);
Curl_safefree(sslc->pinned_key);
Curl_safefree(sslc->cert_blob);
+ Curl_safefree(sslc->issuercert_blob);
Curl_safefree(sslc->curves);
}
--
2.31.1

@ -1,47 +0,0 @@
From 3dbac7fb8b39a4f9aa871401d9d2790f0583ba01 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 12 Jun 2021 18:25:15 +0200
Subject: [PATCH] telnet: fix option parser to not send uninitialized contents
CVE-2021-22925
Reported-by: Red Hat Product Security
Bug: https://curl.se/docs/CVE-2021-22925.html
Upstream-commit: 894f6ec730597eb243618d33cc84d71add8d6a8a
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/telnet.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/lib/telnet.c b/lib/telnet.c
index fdd137f..567c22c 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -922,12 +922,17 @@ static void suboption(struct Curl_easy *data)
size_t tmplen = (strlen(v->data) + 1);
/* Add the variable only if it fits */
if(len + tmplen < (int)sizeof(temp)-6) {
- if(sscanf(v->data, "%127[^,],%127s", varname, varval) == 2) {
- msnprintf((char *)&temp[len], sizeof(temp) - len,
- "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
- CURL_NEW_ENV_VALUE, varval);
- len += tmplen;
- }
+ int rv;
+ char sep[2] = "";
+ varval[0] = 0;
+ rv = sscanf(v->data, "%127[^,]%1[,]%127s", varname, sep, varval);
+ if(rv == 1)
+ len += msnprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%s", CURL_NEW_ENV_VAR, varname);
+ else if(rv >= 2)
+ len += msnprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
+ CURL_NEW_ENV_VALUE, varval);
}
}
msnprintf((char *)&temp[len], sizeof(temp) - len,
--
2.31.1

@ -1,33 +0,0 @@
From bb7619897e53ed424e0712ca5a4c93d5fae99715 Mon Sep 17 00:00:00 2001
From: z2_ on hackerone <>
Date: Tue, 24 Aug 2021 09:50:33 +0200
Subject: [PATCH] mqtt: clear the leftovers pointer when sending succeeds
CVE-2021-22945
Bug: https://curl.se/docs/CVE-2021-22945.html
Upstream-commit: 43157490a5054bd24256fe12876931e8abc9df49
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/mqtt.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/mqtt.c b/lib/mqtt.c
index d88fa73..f3fc045 100644
--- a/lib/mqtt.c
+++ b/lib/mqtt.c
@@ -128,6 +128,10 @@ static CURLcode mqtt_send(struct Curl_easy *data,
mq->sendleftovers = sendleftovers;
mq->nsend = nsend;
}
+ else {
+ mq->sendleftovers = NULL;
+ mq->nsend = 0;
+ }
return result;
}
--
2.31.1

@ -1,331 +0,0 @@
From 64f8bdbf7da9e6b65716ce0d020c6c01d0aba77d Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <patrick@monnerat.net>
Date: Wed, 8 Sep 2021 11:56:22 +0200
Subject: [PATCH] ftp,imap,pop3: do not ignore --ssl-reqd
In imap and pop3, check if TLS is required even when capabilities
request has failed.
In ftp, ignore preauthentication (230 status of server greeting) if TLS
is required.
Bug: https://curl.se/docs/CVE-2021-22946.html
CVE-2021-22946
Upstream-commit: 364f174724ef115c63d5e5dc1d3342c8a43b1cca
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/ftp.c | 9 ++++---
lib/imap.c | 24 ++++++++----------
lib/pop3.c | 33 +++++++++++-------------
tests/data/Makefile.inc | 2 ++
tests/data/test984 | 56 +++++++++++++++++++++++++++++++++++++++++
tests/data/test985 | 54 +++++++++++++++++++++++++++++++++++++++
tests/data/test986 | 53 ++++++++++++++++++++++++++++++++++++++
7 files changed, 195 insertions(+), 36 deletions(-)
create mode 100644 tests/data/test984
create mode 100644 tests/data/test985
create mode 100644 tests/data/test986
diff --git a/lib/ftp.c b/lib/ftp.c
index 5ef1e2e..71f998e 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -2678,9 +2678,12 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
/* we have now received a full FTP server response */
switch(ftpc->state) {
case FTP_WAIT220:
- if(ftpcode == 230)
- /* 230 User logged in - already! */
- return ftp_state_user_resp(data, ftpcode, ftpc->state);
+ if(ftpcode == 230) {
+ /* 230 User logged in - already! Take as 220 if TLS required. */
+ if(data->set.use_ssl <= CURLUSESSL_TRY ||
+ conn->bits.ftp_use_control_ssl)
+ return ftp_state_user_resp(data, ftpcode, ftpc->state);
+ }
else if(ftpcode != 220) {
failf(data, "Got a %03d ftp-server response when 220 was expected",
ftpcode);
diff --git a/lib/imap.c b/lib/imap.c
index e50d7fd..feb7445 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -935,22 +935,18 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
line += wordlen;
}
}
- else if(imapcode == IMAP_RESP_OK) {
- if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
- /* We don't have a SSL/TLS connection yet, but SSL is requested */
- if(imapc->tls_supported)
- /* Switch to TLS connection now */
- result = imap_perform_starttls(data, conn);
- else if(data->set.use_ssl == CURLUSESSL_TRY)
- /* Fallback and carry on with authentication */
- result = imap_perform_authentication(data, conn);
- else {
- failf(data, "STARTTLS not supported.");
- result = CURLE_USE_SSL_FAILED;
- }
+ else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* PREAUTH is not compatible with STARTTLS. */
+ if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) {
+ /* Switch to TLS connection now */
+ result = imap_perform_starttls(data, conn);
}
- else
+ else if(data->set.use_ssl <= CURLUSESSL_TRY)
result = imap_perform_authentication(data, conn);
+ else {
+ failf(data, "STARTTLS not available.");
+ result = CURLE_USE_SSL_FAILED;
+ }
}
else
result = imap_perform_authentication(data, conn);
diff --git a/lib/pop3.c b/lib/pop3.c
index 6168b12..7698d1c 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -740,28 +740,23 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
}
}
}
- else if(pop3code == '+') {
- if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
- /* We don't have a SSL/TLS connection yet, but SSL is requested */
- if(pop3c->tls_supported)
- /* Switch to TLS connection now */
- result = pop3_perform_starttls(data, conn);
- else if(data->set.use_ssl == CURLUSESSL_TRY)
- /* Fallback and carry on with authentication */
- result = pop3_perform_authentication(data, conn);
- else {
- failf(data, "STLS not supported.");
- result = CURLE_USE_SSL_FAILED;
- }
- }
- else
- result = pop3_perform_authentication(data, conn);
- }
else {
/* Clear text is supported when CAPA isn't recognised */
- pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
+ if(pop3code != '+')
+ pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
- result = pop3_perform_authentication(data, conn);
+ if(!data->set.use_ssl || conn->ssl[FIRSTSOCKET].use)
+ result = pop3_perform_authentication(data, conn);
+ else if(pop3code == '+' && pop3c->tls_supported)
+ /* Switch to TLS connection now */
+ result = pop3_perform_starttls(data, conn);
+ else if(data->set.use_ssl <= CURLUSESSL_TRY)
+ /* Fallback and carry on with authentication */
+ result = pop3_perform_authentication(data, conn);
+ else {
+ failf(data, "STLS not supported.");
+ result = CURLE_USE_SSL_FAILED;
+ }
}
return result;
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index d083baf..163ce59 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -117,6 +117,8 @@ test945 test946 test947 test948 test949 test950 test951 test952 test953 \
test954 test955 test956 test957 test958 test959 test960 test961 test962 \
test963 test964 test965 test966 test967 test968 test969 test970 test971 \
\
+test984 test985 test986 \
+\
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
test1016 test1017 test1018 test1019 test1020 test1021 test1022 test1023 \
diff --git a/tests/data/test984 b/tests/data/test984
new file mode 100644
index 0000000..e573f23
--- /dev/null
+++ b/tests/data/test984
@@ -0,0 +1,56 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY CAPABILITY A001 BAD Not implemented
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+imap
+</server>
+ <name>
+IMAP require STARTTLS with failing capabilities
+ </name>
+ <command>
+imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret --ssl-reqd
+</command>
+<file name="log/upload%TESTNUMBER">
+Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
+From: Fred Foobar <foobar@example.COM>
+Subject: afternoon meeting
+To: joe@example.com
+Message-Id: <B27397-0100000@example.COM>
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
+
+Hello Joe, do you think we can meet at 3:30 tomorrow?
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 64 is CURLE_USE_SSL_FAILED
+<errorcode>
+64
+</errorcode>
+<protocol>
+A001 CAPABILITY
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test985 b/tests/data/test985
new file mode 100644
index 0000000..d0db4aa
--- /dev/null
+++ b/tests/data/test985
@@ -0,0 +1,54 @@
+<testcase>
+<info>
+<keywords>
+POP3
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY CAPA -ERR Not implemented
+</servercmd>
+<data nocheck="yes">
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+pop3
+</server>
+ <name>
+POP3 require STARTTLS with failing capabilities
+ </name>
+ <command>
+pop3://%HOSTIP:%POP3PORT/%TESTNUMBER -u user:secret --ssl-reqd
+ </command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 64 is CURLE_USE_SSL_FAILED
+<errorcode>
+64
+</errorcode>
+<protocol>
+CAPA
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test986 b/tests/data/test986
new file mode 100644
index 0000000..a709437
--- /dev/null
+++ b/tests/data/test986
@@ -0,0 +1,53 @@
+<testcase>
+<info>
+<keywords>
+FTP
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY welcome 230 Welcome
+REPLY AUTH 500 unknown command
+</servercmd>
+</reply>
+
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+ftp
+</server>
+ <name>
+FTP require STARTTLS while preauthenticated
+ </name>
+<file name="log/test%TESTNUMBER.txt">
+data
+ to
+ see
+that FTPS
+works
+ so does it?
+</file>
+ <command>
+--ssl-reqd --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -u user:secret
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+# 64 is CURLE_USE_SSL_FAILED
+<errorcode>
+64
+</errorcode>
+<protocol>
+AUTH SSL
+AUTH TLS
+</protocol>
+</verify>
+</testcase>
--
2.31.1

@ -1,354 +0,0 @@
From a1ec463c8207bde97b3575d12e396e999a55a8d0 Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <patrick@monnerat.net>
Date: Tue, 7 Sep 2021 13:26:42 +0200
Subject: [PATCH] ftp,imap,pop3,smtp: reject STARTTLS server response
pipelining
If a server pipelines future responses within the STARTTLS response, the
former are preserved in the pingpong cache across TLS negotiation and
used as responses to the encrypted commands.
This fix detects pipelined STARTTLS responses and rejects them with an
error.
CVE-2021-22947
Bug: https://curl.se/docs/CVE-2021-22947.html
Upstream-commit: 8ef147c43646e91fdaad5d0e7b60351f842e5c68
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/ftp.c | 3 +++
lib/imap.c | 4 +++
lib/pop3.c | 4 +++
lib/smtp.c | 4 +++
tests/data/Makefile.inc | 2 +-
tests/data/test980 | 52 ++++++++++++++++++++++++++++++++++++
tests/data/test981 | 59 +++++++++++++++++++++++++++++++++++++++++
tests/data/test982 | 57 +++++++++++++++++++++++++++++++++++++++
tests/data/test983 | 52 ++++++++++++++++++++++++++++++++++++
9 files changed, 236 insertions(+), 1 deletion(-)
create mode 100644 tests/data/test980
create mode 100644 tests/data/test981
create mode 100644 tests/data/test982
create mode 100644 tests/data/test983
diff --git a/lib/ftp.c b/lib/ftp.c
index 71f998e..e920138 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -2740,6 +2740,9 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
case FTP_AUTH:
/* we have gotten the response to a previous AUTH command */
+ if(pp->cache_size)
+ return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */
+
/* RFC2228 (page 5) says:
*
* If the server is willing to accept the named security mechanism,
diff --git a/lib/imap.c b/lib/imap.c
index feb7445..09bc5d6 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -964,6 +964,10 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
+ /* Pipelining in response is forbidden. */
+ if(data->conn->proto.imapc.pp.cache_size)
+ return CURLE_WEIRD_SERVER_REPLY;
+
if(imapcode != IMAP_RESP_OK) {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied");
diff --git a/lib/pop3.c b/lib/pop3.c
index 7698d1c..dccfced 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -771,6 +771,10 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
CURLcode result = CURLE_OK;
(void)instate; /* no use for this yet */
+ /* Pipelining in response is forbidden. */
+ if(data->conn->proto.pop3c.pp.cache_size)
+ return CURLE_WEIRD_SERVER_REPLY;
+
if(pop3code != '+') {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied");
diff --git a/lib/smtp.c b/lib/smtp.c
index 1defb25..1f89777 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -834,6 +834,10 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
CURLcode result = CURLE_OK;
(void)instate; /* no use for this yet */
+ /* Pipelining in response is forbidden. */
+ if(data->conn->proto.smtpc.pp.cache_size)
+ return CURLE_WEIRD_SERVER_REPLY;
+
if(smtpcode != 220) {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied, code %d", smtpcode);
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 163ce59..42b0569 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -117,7 +117,7 @@ test945 test946 test947 test948 test949 test950 test951 test952 test953 \
test954 test955 test956 test957 test958 test959 test960 test961 test962 \
test963 test964 test965 test966 test967 test968 test969 test970 test971 \
\
-test984 test985 test986 \
+test980 test981 test982 test983 test984 test985 test986 \
\
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
diff --git a/tests/data/test980 b/tests/data/test980
new file mode 100644
index 0000000..97567f8
--- /dev/null
+++ b/tests/data/test980
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA STARTTLS
+AUTH PLAIN
+REPLY STARTTLS 454 currently unavailable\r\n235 Authenticated\r\n250 2.1.0 Sender ok\r\n250 2.1.5 Recipient ok\r\n354 Enter mail\r\n250 2.0.0 Accepted
+REPLY AUTH 535 5.7.8 Authentication credentials invalid
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+smtp
+</server>
+ <name>
+SMTP STARTTLS pipelined server response
+ </name>
+<stdin>
+mail body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -u user:secret --ssl --sasl-ir -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 8 is CURLE_WEIRD_SERVER_REPLY
+<errorcode>
+8
+</errorcode>
+<protocol>
+EHLO %TESTNUMBER
+STARTTLS
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test981 b/tests/data/test981
new file mode 100644
index 0000000..2b98ce4
--- /dev/null
+++ b/tests/data/test981
@@ -0,0 +1,59 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA STARTTLS
+REPLY STARTTLS A002 BAD currently unavailable\r\nA003 OK Authenticated\r\nA004 OK Accepted
+REPLY LOGIN A003 BAD Authentication credentials invalid
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+imap
+</server>
+ <name>
+IMAP STARTTLS pipelined server response
+ </name>
+ <command>
+imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret --ssl
+</command>
+<file name="log/upload%TESTNUMBER">
+Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
+From: Fred Foobar <foobar@example.COM>
+Subject: afternoon meeting
+To: joe@example.com
+Message-Id: <B27397-0100000@example.COM>
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
+
+Hello Joe, do you think we can meet at 3:30 tomorrow?
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 8 is CURLE_WEIRD_SERVER_REPLY
+<errorcode>
+8
+</errorcode>
+<protocol>
+A001 CAPABILITY
+A002 STARTTLS
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test982 b/tests/data/test982
new file mode 100644
index 0000000..9e07cc0
--- /dev/null
+++ b/tests/data/test982
@@ -0,0 +1,57 @@
+<testcase>
+<info>
+<keywords>
+POP3
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA STLS USER
+REPLY STLS -ERR currently unavailable\r\n+OK user accepted\r\n+OK authenticated
+REPLY PASS -ERR Authentication credentials invalid
+</servercmd>
+<data nocheck="yes">
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+pop3
+</server>
+ <name>
+POP3 STARTTLS pipelined server response
+ </name>
+ <command>
+pop3://%HOSTIP:%POP3PORT/%TESTNUMBER -u user:secret --ssl
+ </command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 8 is CURLE_WEIRD_SERVER_REPLY
+<errorcode>
+8
+</errorcode>
+<protocol>
+CAPA
+STLS
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test983 b/tests/data/test983
new file mode 100644
index 0000000..300ec45
--- /dev/null
+++ b/tests/data/test983
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+FTP
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY AUTH 500 unknown command\r\n500 unknown command\r\n331 give password\r\n230 Authenticated\r\n257 "/"\r\n200 OK\r\n200 OK\r\n200 OK\r\n226 Transfer complete
+REPLY PASS 530 Login incorrect
+</servercmd>
+</reply>
+
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+ftp
+</server>
+ <name>
+FTP STARTTLS pipelined server response
+ </name>
+<file name="log/test%TESTNUMBER.txt">
+data
+ to
+ see
+that FTPS
+works
+ so does it?
+</file>
+ <command>
+--ssl --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -u user:secret -P %CLIENTIP
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+# 8 is CURLE_WEIRD_SERVER_REPLY
+<errorcode>
+8
+</errorcode>
+<protocol>
+AUTH SSL
+</protocol>
+</verify>
+</testcase>
--
2.31.1

@ -1,148 +0,0 @@
From 85d1103c2fc0c9b1bdfae470dbafd45758e1c2f0 Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <patrick@monnerat.net>
Date: Mon, 25 Apr 2022 11:44:05 +0200
Subject: [PATCH] url: check sasl additional parameters for connection reuse.
Also move static function safecmp() as non-static Curl_safecmp() since
its purpose is needed at several places.
Bug: https://curl.se/docs/CVE-2022-22576.html
CVE-2022-22576
Closes #8746
Upstream-commit: 852aa5ad351ea53e5f01d2f44b5b4370c2bf5425
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/strcase.c | 10 ++++++++++
lib/strcase.h | 2 ++
lib/url.c | 13 ++++++++++++-
lib/urldata.h | 1 +
lib/vtls/vtls.c | 21 ++++++---------------
5 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/lib/strcase.c b/lib/strcase.c
index dd46ca1..692a3f1 100644
--- a/lib/strcase.c
+++ b/lib/strcase.c
@@ -251,6 +251,16 @@ void Curl_strntolower(char *dest, const char *src, size_t n)
} while(*src++ && --n);
}
+/* Compare case-sensitive NUL-terminated strings, taking care of possible
+ * null pointers. Return true if arguments match.
+ */
+bool Curl_safecmp(char *a, char *b)
+{
+ if(a && b)
+ return !strcmp(a, b);
+ return !a && !b;
+}
+
/* --- public functions --- */
int curl_strequal(const char *first, const char *second)
diff --git a/lib/strcase.h b/lib/strcase.h
index b628656..382b80a 100644
--- a/lib/strcase.h
+++ b/lib/strcase.h
@@ -48,4 +48,6 @@ char Curl_raw_toupper(char in);
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);
+
#endif /* HEADER_CURL_STRCASE_H */
diff --git a/lib/url.c b/lib/url.c
index adef2cd..94e3406 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -768,6 +768,7 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->passwd);
Curl_safefree(conn->sasl_authzid);
Curl_safefree(conn->options);
+ Curl_safefree(conn->oauth_bearer);
Curl_dyn_free(&conn->trailer);
Curl_safefree(conn->host.rawalloc); /* host name buffer */
Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
@@ -1310,7 +1311,9 @@ ConnectionExists(struct Curl_easy *data,
/* 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)) {
+ strcmp(needle->passwd, check->passwd) ||
+ !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) ||
+ !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) {
/* one of them was different */
continue;
}
@@ -3554,6 +3557,14 @@ static CURLcode create_conn(struct Curl_easy *data,
}
}
+ if(data->set.str[STRING_BEARER]) {
+ conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
+ if(!conn->oauth_bearer) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ }
+
#ifdef USE_UNIX_SOCKETS
if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
diff --git a/lib/urldata.h b/lib/urldata.h
index cc8a600..03da59a 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -991,6 +991,7 @@ struct connectdata {
char *passwd; /* password string, allocated */
char *options; /* options string, allocated */
char *sasl_authzid; /* authorisation identity string, allocated */
+ char *oauth_bearer; /* OAUTH2 bearer, allocated */
unsigned char httpversion; /* the HTTP version*10 reported by the server */
struct curltime now; /* "current" time */
struct curltime created; /* creation time */
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 03b85ba..a40ac06 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -125,15 +125,6 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
return !memcmp(first->data, second->data, first->len); /* same data */
}
-static bool safecmp(char *a, char *b)
-{
- if(a && b)
- return !strcmp(a, b);
- else if(!a && !b)
- return TRUE; /* match */
- return FALSE; /* no match */
-}
-
bool
Curl_ssl_config_matches(struct ssl_primary_config *data,
@@ -146,12 +137,12 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
(data->verifystatus == needle->verifystatus) &&
blobcmp(data->cert_blob, needle->cert_blob) &&
blobcmp(data->issuercert_blob, needle->issuercert_blob) &&
- safecmp(data->CApath, needle->CApath) &&
- safecmp(data->CAfile, needle->CAfile) &&
- safecmp(data->issuercert, needle->issuercert) &&
- safecmp(data->clientcert, needle->clientcert) &&
- safecmp(data->random_file, needle->random_file) &&
- safecmp(data->egdsocket, needle->egdsocket) &&
+ Curl_safecmp(data->CApath, needle->CApath) &&
+ Curl_safecmp(data->CAfile, needle->CAfile) &&
+ Curl_safecmp(data->issuercert, needle->issuercert) &&
+ Curl_safecmp(data->clientcert, needle->clientcert) &&
+ Curl_safecmp(data->random_file, needle->random_file) &&
+ Curl_safecmp(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
Curl_safe_strcasecompare(data->curves, needle->curves) &&
--
2.34.1

@ -1,40 +0,0 @@
From 187d0795030ccb4f410eb6089e265ac3571e56dd Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 25 Apr 2022 11:48:00 +0200
Subject: [PATCH] conncache: include the zone id in the "bundle" hashkey
Make connections to two separate IPv6 zone ids create separate
connections.
Reported-by: Harry Sintonen
Bug: https://curl.se/docs/CVE-2022-27775.html
Closes #8747
Upstream-commit: 058f98dc3fe595f21dc26a5b9b1699e519ba5705
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/conncache.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/lib/conncache.c b/lib/conncache.c
index cd5756a..9b9f683 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -159,8 +159,12 @@ static void hashkey(struct connectdata *conn, char *buf,
/* report back which name we used */
*hostp = hostname;
- /* put the number first so that the hostname gets cut off if too long */
- msnprintf(buf, len, "%ld%s", port, hostname);
+ /* put the numbers first so that the hostname gets cut off if too long */
+#ifdef ENABLE_IPV6
+ msnprintf(buf, len, "%u/%ld/%s", conn->scope_id, port, hostname);
+#else
+ msnprintf(buf, len, "%ld/%s", port, hostname);
+#endif
}
/* Returns number of connections currently held in the connection cache.
--
2.34.1

@ -1,243 +0,0 @@
From 2be87227d4b4024c91ff6c856520cac9c9619555 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 25 Apr 2022 13:05:40 +0200
Subject: [PATCH 1/2] http: avoid auth/cookie on redirects same host diff port
CVE-2022-27776
Reported-by: Harry Sintonen
Bug: https://curl.se/docs/CVE-2022-27776.html
Closes #8749
Upstream-commit: 6e659993952aa5f90f48864be84a1bbb047fc258
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/http.c | 33 +++++++++++++++++++++------------
lib/urldata.h | 16 +++++++++-------
2 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/lib/http.c b/lib/http.c
index 799d4fb..0791dcf 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -775,6 +775,21 @@ output_auth_headers(struct Curl_easy *data,
return CURLE_OK;
}
+/*
+ * allow_auth_to_host() tells if autentication, cookies or other "sensitive
+ * data" can (still) be sent to this host.
+ */
+static bool 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)));
+}
+
/**
* Curl_http_output_auth() setups the authentication headers for the
* host/proxy and the correct authentication
@@ -847,15 +862,11 @@ Curl_http_output_auth(struct Curl_easy *data,
with it */
authproxy->done = TRUE;
- /* To prevent the user+password to get sent to other than the original
- host due to a location-follow, we do some weirdo checks here */
- if(!data->state.this_is_a_follow ||
- conn->bits.netrc ||
- !data->state.first_host ||
- data->set.allow_auth_to_other_hosts ||
- strcasecompare(data->state.first_host, conn->host.name)) {
+ /* To prevent the user+password to get sent to other than the original host
+ due to a location-follow */
+ if(allow_auth_to_host(data)
+ || conn->bits.netrc)
result = output_auth_headers(data, conn, authhost, request, path, FALSE);
- }
else
authhost->done = TRUE;
@@ -1906,10 +1917,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
checkprefix("Cookie:", compare)) &&
/* be careful of sending this potentially sensitive header to
other hosts */
- (data->state.this_is_a_follow &&
- data->state.first_host &&
- !data->set.allow_auth_to_other_hosts &&
- !strcasecompare(data->state.first_host, conn->host.name)))
+ !allow_auth_to_host(data))
;
else {
#ifdef USE_HYPER
@@ -2081,6 +2089,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
data->state.first_remote_port = conn->remote_port;
+ data->state.first_remote_protocol = conn->handler->protocol;
}
Curl_safefree(data->state.aptr.host);
diff --git a/lib/urldata.h b/lib/urldata.h
index 03da59a..f92052a 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1336,14 +1336,16 @@ struct UrlState {
char *ulbuf; /* allocated upload buffer or NULL */
curl_off_t current_speed; /* the ProgressShow() function sets this,
bytes / second */
- char *first_host; /* host name of the first (not followed) request.
- if set, this should be the host name that we will
- sent authorization to, no else. Used to make Location:
- following not keep sending user+password... This is
- strdup() data.
- */
+
+ /* host name, port number and protocol of the first (not followed) request.
+ if set, this should be the host name that we will sent authorization to,
+ no else. Used to make Location: following not keep sending user+password.
+ This is strdup()ed data. */
+ char *first_host;
+ int first_remote_port;
+ unsigned int first_remote_protocol;
+
int retrycount; /* number of retries on a new connection */
- int first_remote_port; /* remote port of the first (not followed) request */
struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
long sessionage; /* number of the most recent session */
struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */
--
2.34.1
From c0d12f1634785596746e5d461319dcb95b5b6ae8 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 25 Apr 2022 13:05:47 +0200
Subject: [PATCH 2/2] test898: verify the fix for CVE-2022-27776
Do not pass on Authorization headers on redirects to another port
Upstream-commit: afe752e0504ab60bf63787ede0b992cbe1065f78
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/data/Makefile.inc | 2 +-
tests/data/test898 | 90 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 91 insertions(+), 1 deletion(-)
create mode 100644 tests/data/test898
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 59d46bc..7ae2cf8 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -106,7 +106,7 @@ test854 test855 test856 test857 test858 test859 test860 test861 test862 \
test863 test864 test865 test866 test867 test868 test869 test870 test871 \
test872 test873 test874 test875 test876 test877 test878 test879 test880 \
test881 test882 test883 test884 test885 test886 test887 test888 test889 \
-test890 test891 test892 test893 test894 test895 test896 \
+test890 test891 test892 test893 test894 test895 test896 test898 \
\
test900 test901 test902 test903 test904 test905 test906 test907 test908 \
test909 test910 test911 test912 test913 test914 test915 test916 test917 \
diff --git a/tests/data/test898 b/tests/data/test898
new file mode 100644
index 0000000..5cbb7d8
--- /dev/null
+++ b/tests/data/test898
@@ -0,0 +1,90 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+--location
+Authorization
+Cookie
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Connection: close
+Content-Type: text/html
+
+hey
+</data2>
+
+<datacheck>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002
+
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Connection: close
+Content-Type: text/html
+
+hey
+</datacheck>
+
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP with custom auth and cookies redirected to HTTP on a diff port
+ </name>
+ <command>
+-x http://%HOSTIP:%HTTPPORT http://firsthost.com -L -H "Authorization: Basic am9lOnNlY3JldA==" -H "Cookie: userpwd=am9lOnNlY3JldA=="
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET http://firsthost.com/ HTTP/1.1
+Host: firsthost.com
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+Authorization: Basic am9lOnNlY3JldA==
+Cookie: userpwd=am9lOnNlY3JldA==
+
+GET http://firsthost.com:9999/a/path/%TESTNUMBER0002 HTTP/1.1
+Host: firsthost.com:9999
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
--
2.34.1

@ -1,635 +0,0 @@
From ecee0926868d138312e9608531b232f697e50cad Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 25 Apr 2022 16:24:33 +0200
Subject: [PATCH 1/4] connect: store "conn_remote_port" in the info struct
To make it available after the connection ended.
Upstream-commit: 08b8ef4e726ba10f45081ecda5b3cea788d3c839
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/connect.c | 1 +
lib/urldata.h | 6 +++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/lib/connect.c b/lib/connect.c
index 64f9511..7518807 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -619,6 +619,7 @@ void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
data->info.conn_scheme = conn->handler->scheme;
data->info.conn_protocol = conn->handler->protocol;
data->info.conn_primary_port = conn->port;
+ data->info.conn_remote_port = conn->remote_port;
data->info.conn_local_port = local_port;
}
diff --git a/lib/urldata.h b/lib/urldata.h
index f92052a..5218f76 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1167,7 +1167,11 @@ struct PureInfo {
reused, in the connection cache. */
char conn_primary_ip[MAX_IPADR_LEN];
- int conn_primary_port;
+ int conn_primary_port; /* this is the destination port to the connection,
+ which might have been a proxy */
+ int conn_remote_port; /* this is the "remote port", which is the port
+ number of the used URL, independent of proxy or
+ not */
char conn_local_ip[MAX_IPADR_LEN];
int conn_local_port;
const char *conn_scheme;
--
2.34.1
From 12c129f8d0b165d83ed954f68717d88ffc1cfc5f Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 25 Apr 2022 16:24:33 +0200
Subject: [PATCH 2/4] transfer: redirects to other protocols or ports clear
auth
... unless explicitly permitted.
Bug: https://curl.se/docs/CVE-2022-27774.html
Reported-by: Harry Sintonen
Closes #8748
Upstream-commit: 620ea21410030a9977396b4661806bc187231b79
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/transfer.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 48 insertions(+), 1 deletion(-)
diff --git a/lib/transfer.c b/lib/transfer.c
index 1f8019b..752fe14 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -1641,10 +1641,57 @@ CURLcode Curl_follow(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
else {
-
uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
if(uc)
return Curl_uc_to_curlcode(uc);
+
+ /* Clear auth if this redirects to a different port number or protocol,
+ unless permitted */
+ if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
+ char *portnum;
+ int port;
+ bool clear = FALSE;
+
+ if(data->set.use_port && data->state.allow_port)
+ /* a custom port is used */
+ port = (int)data->set.use_port;
+ else {
+ uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
+ CURLU_DEFAULT_PORT);
+ if(uc) {
+ free(newurl);
+ return Curl_uc_to_curlcode(uc);
+ }
+ port = atoi(portnum);
+ free(portnum);
+ }
+ if(port != data->info.conn_remote_port) {
+ infof(data, "Clear auth, redirects to port from %u to %u",
+ data->info.conn_remote_port, port);
+ clear = TRUE;
+ }
+ else {
+ char *scheme;
+ const struct Curl_handler *p;
+ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
+ if(uc) {
+ free(newurl);
+ return Curl_uc_to_curlcode(uc);
+ }
+
+ p = Curl_builtin_scheme(scheme);
+ if(p && (p->protocol != data->info.conn_protocol)) {
+ infof(data, "Clear auth, redirects scheme from %s to %s",
+ data->info.conn_scheme, scheme);
+ clear = TRUE;
+ }
+ free(scheme);
+ }
+ if(clear) {
+ Curl_safefree(data->state.aptr.user);
+ Curl_safefree(data->state.aptr.passwd);
+ }
+ }
}
if(type == FOLLOW_FAKE) {
--
2.34.1
From 83bf4314d88cc16469afeaaefd6686a50371d1b7 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 25 Apr 2022 16:24:33 +0200
Subject: [PATCH 3/4] tests: verify the fix for CVE-2022-27774
- Test 973 redirects from HTTP to FTP, clear auth
- Test 974 redirects from HTTP to HTTP different port, clear auth
- Test 975 redirects from HTTP to FTP, permitted to keep auth
- Test 976 redirects from HTTP to HTTP different port, permitted to keep
auth
Upstream-commit: 5295e8d64ac6949ecb3f9e564317a608f51b90d8
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/data/Makefile.inc | 1 +
tests/data/test973 | 88 +++++++++++++++++++++++++++++++++++++++++
tests/data/test974 | 87 ++++++++++++++++++++++++++++++++++++++++
tests/data/test975 | 88 +++++++++++++++++++++++++++++++++++++++++
tests/data/test976 | 88 +++++++++++++++++++++++++++++++++++++++++
5 files changed, 352 insertions(+)
create mode 100644 tests/data/test973
create mode 100644 tests/data/test974
create mode 100644 tests/data/test975
create mode 100644 tests/data/test976
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 7ae2cf8..175fc43 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -116,6 +116,7 @@ test936 test937 test938 test939 test940 test941 test942 test943 test944 \
test945 test946 test947 test948 test949 test950 test951 test952 test953 \
test954 test955 test956 test957 test958 test959 test960 test961 test962 \
test963 test964 test965 test966 test967 test968 test969 test970 test971 \
+test973 test974 test975 test976 \
\
test980 test981 test982 test983 test984 test985 test986 \
\
diff --git a/tests/data/test973 b/tests/data/test973
new file mode 100644
index 0000000..6ced107
--- /dev/null
+++ b/tests/data/test973
@@ -0,0 +1,88 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+FTP
+--location
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER0002
+
+</data>
+<data2>
+data
+ to
+ see
+that FTP
+works
+ so does it?
+</data2>
+
+<datacheck>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER0002
+
+data
+ to
+ see
+that FTP
+works
+ so does it?
+</datacheck>
+
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+ftp
+</server>
+ <name>
+HTTP with auth redirected to FTP w/o auth
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -L -u joe:secret
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic am9lOnNlY3JldA==
+User-Agent: curl/%VERSION
+Accept: */*
+
+USER anonymous
+PASS ftp@example.com
+PWD
+CWD a
+CWD path
+EPSV
+TYPE I
+SIZE %TESTNUMBER0002
+RETR %TESTNUMBER0002
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test974 b/tests/data/test974
new file mode 100644
index 0000000..ac4e641
--- /dev/null
+++ b/tests/data/test974
@@ -0,0 +1,87 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+--location
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Connection: close
+Content-Type: text/html
+
+hey
+</data2>
+
+<datacheck>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002
+
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Connection: close
+Content-Type: text/html
+
+hey
+</datacheck>
+
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP with auth redirected to HTTP on a diff port w/o auth
+ </name>
+ <command>
+-x http://%HOSTIP:%HTTPPORT http://firsthost.com -L -u joe:secret
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET http://firsthost.com/ HTTP/1.1
+Host: firsthost.com
+Authorization: Basic am9lOnNlY3JldA==
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://firsthost.com:9999/a/path/%TESTNUMBER0002 HTTP/1.1
+Host: firsthost.com:9999
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test975 b/tests/data/test975
new file mode 100644
index 0000000..85e03e4
--- /dev/null
+++ b/tests/data/test975
@@ -0,0 +1,88 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+FTP
+--location-trusted
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER0002
+
+</data>
+<data2>
+data
+ to
+ see
+that FTP
+works
+ so does it?
+</data2>
+
+<datacheck>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER0002
+
+data
+ to
+ see
+that FTP
+works
+ so does it?
+</datacheck>
+
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+ftp
+</server>
+ <name>
+HTTP with auth redirected to FTP allowing auth to continue
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --location-trusted -u joe:secret
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic am9lOnNlY3JldA==
+User-Agent: curl/%VERSION
+Accept: */*
+
+USER joe
+PASS secret
+PWD
+CWD a
+CWD path
+EPSV
+TYPE I
+SIZE %TESTNUMBER0002
+RETR %TESTNUMBER0002
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test976 b/tests/data/test976
new file mode 100644
index 0000000..c4dd61e
--- /dev/null
+++ b/tests/data/test976
@@ -0,0 +1,88 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+--location-trusted
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Connection: close
+Content-Type: text/html
+
+hey
+</data2>
+
+<datacheck>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002
+
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Connection: close
+Content-Type: text/html
+
+hey
+</datacheck>
+
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP with auth redirected to HTTP on a diff port --location-trusted
+ </name>
+ <command>
+-x http://%HOSTIP:%HTTPPORT http://firsthost.com --location-trusted -u joe:secret
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET http://firsthost.com/ HTTP/1.1
+Host: firsthost.com
+Authorization: Basic am9lOnNlY3JldA==
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://firsthost.com:9999/a/path/%TESTNUMBER0002 HTTP/1.1
+Host: firsthost.com:9999
+Authorization: Basic am9lOnNlY3JldA==
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
--
2.34.1
From 443ce415aa60caaf8b1c9b0b71fff8d26263daca Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 25 Apr 2022 17:59:15 +0200
Subject: [PATCH 4/4] openssl: don't leak the SRP credentials in redirects
either
Follow-up to 620ea21410030
Reported-by: Harry Sintonen
Closes #8751
Upstream-commit: 139a54ed0a172adaaf1a78d6f4fff50b2c3f9e08
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/http.c | 10 +++++-----
lib/http.h | 6 ++++++
lib/vtls/openssl.c | 3 ++-
3 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/lib/http.c b/lib/http.c
index 0791dcf..4433824 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -776,10 +776,10 @@ output_auth_headers(struct Curl_easy *data,
}
/*
- * allow_auth_to_host() tells if autentication, cookies or other "sensitive
- * data" can (still) be sent to this host.
+ * Curl_allow_auth_to_host() tells if authentication, cookies or other
+ * "sensitive data" can (still) be sent to this host.
*/
-static bool allow_auth_to_host(struct Curl_easy *data)
+bool Curl_allow_auth_to_host(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
return (!data->state.this_is_a_follow ||
@@ -864,7 +864,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(allow_auth_to_host(data)
+ if(Curl_allow_auth_to_host(data)
|| conn->bits.netrc)
result = output_auth_headers(data, conn, authhost, request, path, FALSE);
else
@@ -1917,7 +1917,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
checkprefix("Cookie:", compare)) &&
/* be careful of sending this potentially sensitive header to
other hosts */
- !allow_auth_to_host(data))
+ !Curl_allow_auth_to_host(data))
;
else {
#ifdef USE_HYPER
diff --git a/lib/http.h b/lib/http.h
index 07e963d..9000bae 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -317,4 +317,10 @@ 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/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 1bafe96..97c5666 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -2857,7 +2857,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
#ifdef USE_OPENSSL_SRP
- if(ssl_authtype == CURL_TLSAUTH_SRP) {
+ if((ssl_authtype == CURL_TLSAUTH_SRP) &&
+ Curl_allow_auth_to_host(data)) {
char * const ssl_username = SSL_SET_OPTION(username);
infof(data, "Using TLS-SRP username: %s\n", ssl_username);
--
2.34.1

@ -1,461 +0,0 @@
From 50481ac42b4beae6ea85345e37b051124ac00f11 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 28 Jan 2022 16:48:38 +0100
Subject: [PATCH 1/3] setopt: fix the TLSAUTH #ifdefs for proxy-disabled builds
Closes #8350
Upstream-commit: 96629ba2c212cda2bd1b7b04e2a9fc01ef70b75d
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/setopt.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/setopt.c b/lib/setopt.c
index 08827d1..9eaa187 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * 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
@@ -2699,30 +2699,30 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
+#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLSAUTH_USERNAME:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
va_arg(param, char *));
-#ifndef CURL_DISABLE_PROXY
if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
!data->set.proxy_ssl.authtype)
data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
-#endif
break;
+#endif
case CURLOPT_TLSAUTH_PASSWORD:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
va_arg(param, char *));
if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
+#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLSAUTH_PASSWORD:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
va_arg(param, char *));
-#ifndef CURL_DISABLE_PROXY
if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
!data->set.proxy_ssl.authtype)
data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
-#endif
break;
+#endif
case CURLOPT_TLSAUTH_TYPE:
argptr = va_arg(param, char *);
if(!argptr ||
--
2.34.1
From 931fbabcae0b5d1a91657e6bb85f4f23fce7ac3d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 9 May 2022 23:13:53 +0200
Subject: [PATCH 2/3] tls: check more TLS details for connection reuse
CVE-2022-27782
Reported-by: Harry Sintonen
Bug: https://curl.se/docs/CVE-2022-27782.html
Closes #8825
Upstream-commit: f18af4f874cecab82a9797e8c7541e0990c7a64c
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/setopt.c | 29 +++++++++++++++++------------
lib/url.c | 23 ++++++++++++++++-------
lib/urldata.h | 13 +++++++------
lib/vtls/openssl.c | 10 +++++-----
lib/vtls/vtls.c | 21 +++++++++++++++++++++
5 files changed, 66 insertions(+), 30 deletions(-)
diff --git a/lib/setopt.c b/lib/setopt.c
index 8e1bf12..7aa6fdb 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -2268,6 +2268,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_SSL_OPTIONS:
arg = va_arg(param, long);
+ data->set.ssl.primary.ssl_options = (unsigned char)(arg & 0xff);
data->set.ssl.enable_beast =
(bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
@@ -2281,6 +2282,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_SSL_OPTIONS:
arg = va_arg(param, long);
+ data->set.proxy_ssl.primary.ssl_options = (unsigned char)(arg & 0xff);
data->set.proxy_ssl.enable_beast =
(bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
@@ -2696,49 +2698,52 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_TLSAUTH_USERNAME:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
- data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ if(data->set.str[STRING_TLSAUTH_USERNAME] &&
+ !data->set.ssl.primary.authtype)
+ data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLSAUTH_USERNAME:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
va_arg(param, char *));
if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
- !data->set.proxy_ssl.authtype)
- data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ !data->set.proxy_ssl.primary.authtype)
+ data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to
+ SRP */
break;
#endif
case CURLOPT_TLSAUTH_PASSWORD:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
- data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ if(data->set.str[STRING_TLSAUTH_USERNAME] &&
+ !data->set.ssl.primary.authtype)
+ data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default */
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLSAUTH_PASSWORD:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
va_arg(param, char *));
if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
- !data->set.proxy_ssl.authtype)
- data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ !data->set.proxy_ssl.primary.authtype)
+ data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default */
break;
#endif
case CURLOPT_TLSAUTH_TYPE:
argptr = va_arg(param, char *);
if(!argptr ||
strncasecompare(argptr, "SRP", strlen("SRP")))
- data->set.ssl.authtype = CURL_TLSAUTH_SRP;
+ data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP;
else
- data->set.ssl.authtype = CURL_TLSAUTH_NONE;
+ data->set.ssl.primary.authtype = CURL_TLSAUTH_NONE;
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLSAUTH_TYPE:
argptr = va_arg(param, char *);
if(!argptr ||
strncasecompare(argptr, "SRP", strlen("SRP")))
- data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
+ data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP;
else
- data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
+ data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_NONE;
break;
#endif
#endif
diff --git a/lib/url.c b/lib/url.c
index 94e3406..5ebf5e2 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -540,7 +540,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->ssl.primary.verifypeer = TRUE;
set->ssl.primary.verifyhost = TRUE;
#ifdef USE_TLS_SRP
- set->ssl.authtype = CURL_TLSAUTH_NONE;
+ set->ssl.primary.authtype = CURL_TLSAUTH_NONE;
#endif
set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
type */
@@ -1719,11 +1719,17 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
+ conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options;
+#ifdef USE_TLS_SRP
+#endif
#ifndef CURL_DISABLE_PROXY
conn->proxy_ssl_config.verifystatus =
data->set.proxy_ssl.primary.verifystatus;
conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
+ conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
+#ifdef USE_TLS_SRP
+#endif
#endif
conn->ip_version = data->set.ipver;
conn->bits.connect_only = data->set.connect_only;
@@ -3764,7 +3770,8 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.str[STRING_SSL_ISSUERCERT_PROXY];
data->set.proxy_ssl.primary.issuercert_blob =
data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
- data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
+ data->set.proxy_ssl.primary.CRLfile =
+ data->set.str[STRING_SSL_CRLFILE_PROXY];
data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
@@ -3772,18 +3779,20 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
#endif
- data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+ data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
data->set.ssl.key = data->set.str[STRING_KEY];
data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
#ifdef USE_TLS_SRP
- data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
- data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+ data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
+ data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
#ifndef CURL_DISABLE_PROXY
- data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
- data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
+ data->set.proxy_ssl.primary.username =
+ data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+ data->set.proxy_ssl.primary.password =
+ data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
#endif
#endif
data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
diff --git a/lib/urldata.h b/lib/urldata.h
index 5218f76..e006495 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -253,9 +253,16 @@ struct ssl_primary_config {
char *cipher_list; /* list of ciphers to use */
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
char *pinned_key;
+ char *CRLfile; /* CRL to check certificate revocation */
struct curl_blob *cert_blob;
struct curl_blob *issuercert_blob;
+#ifdef USE_TLS_SRP
+ char *username; /* TLS username (for, e.g., SRP) */
+ char *password; /* TLS password (for, e.g., SRP) */
+ enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */
+#endif
char *curves; /* list of curves to use */
+ unsigned char ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
BIT(verifystatus); /* set TRUE if certificate status must be checked */
@@ -265,7 +272,6 @@ struct ssl_primary_config {
struct ssl_config_data {
struct ssl_primary_config primary;
long certverifyresult; /* result from the certificate verification */
- char *CRLfile; /* CRL to check certificate revocation */
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
void *fsslctxp; /* parameter for call back */
char *cert_type; /* format for certificate (default: PEM)*/
@@ -273,11 +279,6 @@ struct ssl_config_data {
struct curl_blob *key_blob;
char *key_type; /* format for private key (default: PEM) */
char *key_passwd; /* plain text private key password */
-#ifdef USE_TLS_SRP
- char *username; /* TLS username (for, e.g., SRP) */
- char *password; /* TLS password (for, e.g., SRP) */
- enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */
-#endif
BIT(certinfo); /* gather lots of certificate info */
BIT(falsestart);
BIT(enable_beast); /* allow this flaw for interoperability's sake*/
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 97c5666..a4ef9d1 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -2546,7 +2546,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
const long int ssl_version = SSL_CONN_CONFIG(version);
#ifdef USE_OPENSSL_SRP
- const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype);
+ const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(primary.authtype);
#endif
char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
@@ -2554,7 +2554,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+ const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
char error_buffer[256];
struct ssl_backend_data *backend = connssl->backend;
bool imported_native_ca = false;
@@ -2859,15 +2859,15 @@ 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)) {
- char * const ssl_username = SSL_SET_OPTION(username);
-
+ 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\n", ssl_username);
if(!SSL_CTX_set_srp_username(backend->ctx, ssl_username)) {
failf(data, "Unable to set SRP user name");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- if(!SSL_CTX_set_srp_password(backend->ctx, SSL_SET_OPTION(password))) {
+ if(!SSL_CTX_set_srp_password(backend->ctx, ssl_password)) {
failf(data, "failed setting SRP password");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index a40ac06..e2d3438 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -132,6 +132,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
{
if((data->version == needle->version) &&
(data->version_max == needle->version_max) &&
+ (data->ssl_options == needle->ssl_options) &&
(data->verifypeer == needle->verifypeer) &&
(data->verifyhost == needle->verifyhost) &&
(data->verifystatus == needle->verifystatus) &&
@@ -143,9 +144,15 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
Curl_safecmp(data->clientcert, needle->clientcert) &&
Curl_safecmp(data->random_file, needle->random_file) &&
Curl_safecmp(data->egdsocket, needle->egdsocket) &&
+#ifdef USE_TLS_SRP
+ Curl_safecmp(data->username, needle->username) &&
+ Curl_safecmp(data->password, needle->password) &&
+ (data->authtype == needle->authtype) &&
+#endif
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
Curl_safe_strcasecompare(data->curves, needle->curves) &&
+ Curl_safe_strcasecompare(data->CRLfile, needle->CRLfile) &&
Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
return TRUE;
@@ -162,6 +169,10 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
dest->verifyhost = source->verifyhost;
dest->verifystatus = source->verifystatus;
dest->sessionid = source->sessionid;
+ dest->ssl_options = source->ssl_options;
+#ifdef USE_TLS_SRP
+ dest->authtype = source->authtype;
+#endif
CLONE_BLOB(cert_blob);
CLONE_BLOB(issuercert_blob);
@@ -175,6 +186,11 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
CLONE_STRING(cipher_list13);
CLONE_STRING(pinned_key);
CLONE_STRING(curves);
+ CLONE_STRING(CRLfile);
+#ifdef USE_TLS_SRP
+ CLONE_STRING(username);
+ CLONE_STRING(password);
+#endif
return TRUE;
}
@@ -193,6 +209,11 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
Curl_safefree(sslc->cert_blob);
Curl_safefree(sslc->issuercert_blob);
Curl_safefree(sslc->curves);
+ Curl_safefree(sslc->CRLfile);
+#ifdef USE_TLS_SRP
+ Curl_safefree(sslc->username);
+ Curl_safefree(sslc->password);
+#endif
}
#ifdef USE_SSL
--
2.34.1
From 5e9832048b30492e02dd222cd8bfe997e03cffa1 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 9 May 2022 23:13:53 +0200
Subject: [PATCH 3/3] url: check SSH config match on connection reuse
CVE-2022-27782
Reported-by: Harry Sintonen
Bug: https://curl.se/docs/CVE-2022-27782.html
Closes #8825
Upstream-commit: 1645e9b44505abd5cbaf65da5282c3f33b5924a5
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/url.c | 11 +++++++++++
lib/vssh/ssh.h | 6 +++---
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/lib/url.c b/lib/url.c
index 5ebf5e2..c713e54 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1073,6 +1073,12 @@ static void prune_dead_connections(struct Curl_easy *data)
}
}
+static bool ssh_config_matches(struct connectdata *one,
+ struct connectdata *two)
+{
+ return (Curl_safecmp(one->proto.sshc.rsa, two->proto.sshc.rsa) &&
+ Curl_safecmp(one->proto.sshc.rsa_pub, two->proto.sshc.rsa_pub));
+}
/*
* Given one filled in connection struct (named needle), this function should
* detect if there already is one that has all the significant details
@@ -1319,6 +1325,11 @@ ConnectionExists(struct Curl_easy *data,
}
}
+ if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) {
+ if(!ssh_config_matches(needle, check))
+ continue;
+ }
+
if((needle->handler->flags&PROTOPT_SSL)
#ifndef CURL_DISABLE_PROXY
|| !needle->bits.httpproxy || needle->bits.tunnel_proxy
diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h
index 7972081..30d82e5 100644
--- a/lib/vssh/ssh.h
+++ b/lib/vssh/ssh.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * 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
@@ -131,8 +131,8 @@ struct ssh_conn {
/* common */
const char *passphrase; /* pass-phrase to use */
- char *rsa_pub; /* path name */
- char *rsa; /* path name */
+ char *rsa_pub; /* strdup'ed public key file */
+ char *rsa; /* strdup'ed private key file */
bool authed; /* the connection has been authenticated fine */
bool acceptfail; /* used by the SFTP_QUOTE (continue if
quote command fails) */
--
2.34.1

@ -1,101 +0,0 @@
From 85a8c0e9992cee271145ecf009f60b9bee9b7a60 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Wed, 15 Sep 2021 09:59:14 +0200
Subject: [PATCH] tests/sshserver.pl: make it work with openssh-8.7p1
... by not using options with no argument where an argument is required:
=== Start of file tests/log/ssh_server.log
curl_sshd_config line 6: no argument after keyword "DenyGroups"
curl_sshd_config line 7: no argument after keyword "AllowGroups"
curl_sshd_config line 10: Deprecated option AuthorizedKeysFile2
curl_sshd_config line 29: Deprecated option KeyRegenerationInterval
curl_sshd_config line 39: Deprecated option RhostsRSAAuthentication
curl_sshd_config line 40: Deprecated option RSAAuthentication
curl_sshd_config line 41: Deprecated option ServerKeyBits
curl_sshd_config line 45: Deprecated option UseLogin
curl_sshd_config line 56: no argument after keyword "AcceptEnv"
curl_sshd_config: terminating, 3 bad configuration options
=== End of file tests/log/ssh_server.log
=== Start of file log/sftp_server.log
curl_sftp_config line 33: Unsupported option "rhostsrsaauthentication"
curl_sftp_config line 34: Unsupported option "rsaauthentication"
curl_sftp_config line 52: no argument after keyword "sendenv"
curl_sftp_config: terminating, 1 bad configuration options
Connection closed.
Connection closed
=== End of file log/sftp_server.log
Closes #7724
Upstream-commit: ab78d2c679dfb37b27e89f42ad050c3153fa7513
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/sshserver.pl | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/tests/sshserver.pl b/tests/sshserver.pl
index 9441939..2afaace 100644
--- a/tests/sshserver.pl
+++ b/tests/sshserver.pl
@@ -428,9 +428,7 @@ if ($sshdid =~ /OpenSSH-Windows/) {
# ssh daemon configuration file options we might use and version support
#
# AFSTokenPassing : OpenSSH 1.2.1 and later [1]
-# AcceptEnv : OpenSSH 3.9.0 and later
# AddressFamily : OpenSSH 4.0.0 and later
-# AllowGroups : OpenSSH 1.2.1 and later
# AllowTcpForwarding : OpenSSH 2.3.0 and later
# AllowUsers : OpenSSH 1.2.1 and later
# AuthorizedKeysFile : OpenSSH 2.9.9 and later
@@ -441,7 +439,6 @@ if ($sshdid =~ /OpenSSH-Windows/) {
# ClientAliveCountMax : OpenSSH 2.9.0 and later
# ClientAliveInterval : OpenSSH 2.9.0 and later
# Compression : OpenSSH 3.3.0 and later
-# DenyGroups : OpenSSH 1.2.1 and later
# DenyUsers : OpenSSH 1.2.1 and later
# ForceCommand : OpenSSH 4.4.0 and later [3]
# GatewayPorts : OpenSSH 2.1.0 and later
@@ -534,9 +531,6 @@ if ($sshdid =~ /OpenSSH-Windows/) {
push @cfgarr, "AllowUsers $username";
}
-push @cfgarr, 'DenyGroups';
-push @cfgarr, 'AllowGroups';
-push @cfgarr, '#';
push @cfgarr, "AuthorizedKeysFile $clipubkeyf_config";
push @cfgarr, "AuthorizedKeysFile2 $clipubkeyf_config";
push @cfgarr, "HostKey $hstprvkeyf_config";
@@ -684,9 +678,6 @@ push @cfgarr, '#';
#***************************************************************************
# Options that might be supported or not in sshd OpenSSH 2.9.9 and later
#
-if(sshd_supports_opt('AcceptEnv','')) {
- push @cfgarr, 'AcceptEnv';
-}
if(sshd_supports_opt('AddressFamily','any')) {
# Address family must be specified before ListenAddress
splice @cfgarr, 14, 0, 'AddressFamily any';
@@ -873,7 +864,6 @@ if ($sshdid =~ /OpenSSH-Windows/) {
# RemoteForward : OpenSSH 1.2.1 and later [3]
# RhostsRSAAuthentication : OpenSSH 1.2.1 and later
# RSAAuthentication : OpenSSH 1.2.1 and later
-# SendEnv : OpenSSH 3.9.0 and later
# ServerAliveCountMax : OpenSSH 3.8.0 and later
# ServerAliveInterval : OpenSSH 3.8.0 and later
# SmartcardDevice : OpenSSH 2.9.9 and later [1][3]
@@ -1028,10 +1018,6 @@ if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) ||
push @cfgarr, 'RekeyLimit 1G';
}
-if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) {
- push @cfgarr, 'SendEnv';
-}
-
if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) ||
(($sshid =~ /SunSSH/) && ($sshvernum >= 120))) {
push @cfgarr, 'ServerAliveCountMax 3';
--
2.34.1

@ -1,70 +0,0 @@
From d36661703e16bd740a3a928041b1e697a6617b98 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 9 Jun 2022 09:27:24 +0200
Subject: [PATCH] krb5: return error properly on decode errors
Bug: https://curl.se/docs/CVE-2022-32208.html
CVE-2022-32208
Reported-by: Harry Sintonen
Closes #9051
Upstream-commit: 6ecdf5136b52af747e7bda08db9a748256b1cd09
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/krb5.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/lib/krb5.c b/lib/krb5.c
index 787137c..6f9e1f7 100644
--- a/lib/krb5.c
+++ b/lib/krb5.c
@@ -146,11 +146,8 @@ krb5_decode(void *app_data, void *buf, int len,
enc.value = buf;
enc.length = len;
maj = gss_unwrap(&min, *context, &enc, &dec, NULL, NULL);
- if(maj != GSS_S_COMPLETE) {
- if(len >= 4)
- strcpy(buf, "599 ");
+ if(maj != GSS_S_COMPLETE)
return -1;
- }
memcpy(buf, dec.value, dec.length);
len = curlx_uztosi(dec.length);
@@ -523,6 +520,7 @@ static CURLcode read_data(struct connectdata *conn,
{
int len;
CURLcode result;
+ int nread;
result = socket_read(fd, &len, sizeof(len));
if(result)
@@ -531,7 +529,10 @@ static CURLcode read_data(struct connectdata *conn,
if(len) {
/* only realloc if there was a length */
len = ntohl(len);
- buf->data = Curl_saferealloc(buf->data, len);
+ if(len > CURL_MAX_INPUT_LENGTH)
+ len = 0;
+ else
+ buf->data = Curl_saferealloc(buf->data, len);
}
if(!len || !buf->data)
return CURLE_OUT_OF_MEMORY;
@@ -539,8 +540,11 @@ static CURLcode read_data(struct connectdata *conn,
result = socket_read(fd, buf->data, len);
if(result)
return result;
- buf->size = conn->mech->decode(conn->app_data, buf->data, len,
- conn->data_prot, conn);
+ nread = conn->mech->decode(conn->app_data, buf->data, len,
+ conn->data_prot, conn);
+ if(nread < 0)
+ return CURLE_RECV_ERROR;
+ buf->size = (size_t)nread;
buf->index = 0;
return CURLE_OK;
}
--
2.35.3

@ -1,143 +0,0 @@
From 24dedf9b260eebb7feae6fc273208b551fe54a79 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 16 May 2022 16:28:13 +0200
Subject: [PATCH 1/2] content_encoding: return error on too many compression
steps
The max allowed steps is arbitrarily set to 5.
Bug: https://curl.se/docs/CVE-2022-32206.html
CVE-2022-32206
Reported-by: Harry Sintonen
Closes #9049
Upstream-commit: 3a09fbb7f264c67c438d01a30669ce325aa508e2
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/content_encoding.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index c03637a..6f994b3 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -1024,12 +1024,16 @@ static const struct content_encoding *find_encoding(const char *name,
return NULL;
}
+/* allow no more than 5 "chained" compression steps */
+#define MAX_ENCODE_STACK 5
+
/* Set-up the unencoding stack from the Content-Encoding header value.
* See RFC 7231 section 3.1.2.2. */
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked)
{
struct SingleRequest *k = &data->req;
+ int counter = 0;
do {
const char *name;
@@ -1064,6 +1068,11 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
if(!encoding)
encoding = &error_encoding; /* Defer error at stack use. */
+ if(++counter >= MAX_ENCODE_STACK) {
+ failf(data, "Reject response due to %u content encodings",
+ counter);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
/* Stack the unencoding stage. */
writer = new_unencoding_writer(data, encoding, k->writer_stack);
if(!writer)
--
2.35.3
From b3cd74f01871281f0989860e04c546d896f0e72f Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 16 May 2022 16:29:07 +0200
Subject: [PATCH 2/2] test387: verify rejection of compression chain attack
Upstream-commit: 7230b19a2e17a164f61f82e4e409a9777ea2421a
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/data/Makefile.inc | 1 +
tests/data/test387 | 53 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
create mode 100644 tests/data/test387
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 98d5516..9b5f4fb 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -62,6 +62,7 @@ test343 test344 test345 test346 test347 test348 test349 test350 test351 \
test352 test353 test354 test355 test356 test357 test358 test359 test360 \
test361 test362 \
\
+test387 \
test393 test394 test395 test396 test397 \
\
test400 test401 test402 test403 test404 test405 test406 test407 test408 \
diff --git a/tests/data/test387 b/tests/data/test387
new file mode 100644
index 0000000..015ec25
--- /dev/null
+++ b/tests/data/test387
@@ -0,0 +1,53 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+gzip
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Transfer-Encoding: gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+Response with overly long compression chain
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -sS
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+
+# CURLE_BAD_CONTENT_ENCODING is 61
+<errorcode>
+61
+</errorcode>
+<stderr mode="text">
+curl: (61) Reject response due to 5 content encodings
+</stderr>
+</verify>
+</testcase>
--
2.35.3

@ -1,425 +0,0 @@
From 36b47377c2d1a8d141d1ef810102748f27384f5c Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 25 May 2022 10:09:53 +0200
Subject: [PATCH 1/3] fopen: add Curl_fopen() for better overwriting of files
Bug: https://curl.se/docs/CVE-2022-32207.html
CVE-2022-32207
Reported-by: Harry Sintonen
Closes #9050
Upstream-commit: 20f9dd6bae50b7223171b17ba7798946e74f877f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
CMakeLists.txt | 1 +
configure.ac | 1 +
lib/Makefile.inc | 2 +
lib/cookie.c | 17 ++----
lib/curl_config.h.cmake | 3 ++
lib/fopen.c | 113 ++++++++++++++++++++++++++++++++++++++++
lib/fopen.h | 30 +++++++++++
7 files changed, 154 insertions(+), 13 deletions(-)
create mode 100644 lib/fopen.c
create mode 100644 lib/fopen.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b77de6d..a0bfaad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -982,6 +982,7 @@ elseif(HAVE_LIBSOCKET)
set(CMAKE_REQUIRED_LIBRARIES socket)
endif()
+check_symbol_exists(fchmod "${CURL_INCLUDES}" HAVE_FCHMOD)
check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME)
check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET)
check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT)
diff --git a/configure.ac b/configure.ac
index d431870..7433bb9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4516,6 +4516,7 @@ AC_CHECK_DECLS([getpwuid_r], [], [AC_DEFINE(HAVE_DECL_GETPWUID_R_MISSING, 1, "Se
AC_CHECK_FUNCS([fnmatch \
+ fchmod \
geteuid \
getpass_r \
getppid \
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index e8f110f..5139b03 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -130,6 +130,7 @@ LIB_CFILES = \
escape.c \
file.c \
fileinfo.c \
+ fopen.c \
formdata.c \
ftp.c \
ftplistparser.c \
@@ -261,6 +262,7 @@ LIB_HFILES = \
escape.h \
file.h \
fileinfo.h \
+ fopen.h \
formdata.h \
ftp.h \
ftplistparser.h \
diff --git a/lib/cookie.c b/lib/cookie.c
index 8a6aa1a..cb0c03b 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -97,8 +97,8 @@ Example set of cookies:
#include "curl_memrchr.h"
#include "inet_pton.h"
#include "parsedate.h"
-#include "rand.h"
#include "rename.h"
+#include "fopen.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -1537,17 +1537,8 @@ static int cookie_output(struct Curl_easy *data,
use_stdout = TRUE;
}
else {
- unsigned char randsuffix[9];
-
- if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
- return 2;
-
- tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
- if(!tempstore)
- return 1;
-
- out = fopen(tempstore, FOPEN_WRITETEXT);
- if(!out)
+ error = Curl_fopen(data, filename, &out, &tempstore);
+ if(error)
goto error;
}
@@ -1594,7 +1585,7 @@ static int cookie_output(struct Curl_easy *data,
if(!use_stdout) {
fclose(out);
out = NULL;
- if(Curl_rename(tempstore, filename)) {
+ if(tempstore && Curl_rename(tempstore, filename)) {
unlink(tempstore);
goto error;
}
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index d2a0f43..c254359 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -148,6 +148,9 @@
/* Define to 1 if you have the <assert.h> header file. */
#cmakedefine HAVE_ASSERT_H 1
+/* Define to 1 if you have the `fchmod' function. */
+#cmakedefine HAVE_FCHMOD 1
+
/* Define to 1 if you have the `basename' function. */
#cmakedefine HAVE_BASENAME 1
diff --git a/lib/fopen.c b/lib/fopen.c
new file mode 100644
index 0000000..ad3691b
--- /dev/null
+++ b/lib/fopen.c
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * _ _ ____ _
+ * 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"
+
+#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
+ defined(USE_HSTS)
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include "urldata.h"
+#include "rand.h"
+#include "fopen.h"
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/*
+ * Curl_fopen() opens a file for writing with a temp name, to be renamed
+ * to the final name when completed. If there is an existing file using this
+ * name at the time of the open, this function will clone the mode from that
+ * file. if 'tempname' is non-NULL, it needs a rename after the file is
+ * written.
+ */
+CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
+ FILE **fh, char **tempname)
+{
+ CURLcode result = CURLE_WRITE_ERROR;
+ unsigned char randsuffix[9];
+ char *tempstore = NULL;
+ struct_stat sb;
+ int fd = -1;
+ *tempname = NULL;
+
+ if(stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode)) {
+ /* a non-regular file, fallback to direct fopen() */
+ *fh = fopen(filename, FOPEN_WRITETEXT);
+ if(*fh)
+ return CURLE_OK;
+ goto fail;
+ }
+
+ result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix));
+ if(result)
+ goto fail;
+
+ tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
+ if(!tempstore) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
+ }
+
+ result = CURLE_WRITE_ERROR;
+ fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if(fd == -1)
+ goto fail;
+
+#ifdef HAVE_FCHMOD
+ {
+ struct_stat nsb;
+ if((fstat(fd, &nsb) != -1) &&
+ (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) {
+ /* if the user and group are the same, clone the original mode */
+ if(fchmod(fd, sb.st_mode) == -1)
+ goto fail;
+ }
+ }
+#endif
+
+ *fh = fdopen(fd, FOPEN_WRITETEXT);
+ if(!*fh)
+ goto fail;
+
+ *tempname = tempstore;
+ return CURLE_OK;
+
+fail:
+ if(fd != -1) {
+ close(fd);
+ unlink(tempstore);
+ }
+
+ free(tempstore);
+
+ *tempname = NULL;
+ return result;
+}
+
+#endif /* ! disabled */
diff --git a/lib/fopen.h b/lib/fopen.h
new file mode 100644
index 0000000..289e55f
--- /dev/null
+++ b/lib/fopen.h
@@ -0,0 +1,30 @@
+#ifndef HEADER_CURL_FOPEN_H
+#define HEADER_CURL_FOPEN_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
+ *
+ ***************************************************************************/
+
+CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
+ FILE **fh, char **tempname);
+
+#endif
--
2.35.3
From bd7af48238b058e9b46fdf2e1333b355920c341c Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 25 May 2022 10:09:53 +0200
Subject: [PATCH 2/3] altsvc: use Curl_fopen()
Upstream-commit: fab970a5d19c1faa2052239ec1e2602b892cbeb2
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/altsvc.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/lib/altsvc.c b/lib/altsvc.c
index 242733b..4dc4078 100644
--- a/lib/altsvc.c
+++ b/lib/altsvc.c
@@ -34,7 +34,7 @@
#include "parsedate.h"
#include "sendf.h"
#include "warnless.h"
-#include "rand.h"
+#include "fopen.h"
#include "rename.h"
/* The last 3 #include files should be in this order */
@@ -329,8 +329,7 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
struct Curl_llist_element *n;
CURLcode result = CURLE_OK;
FILE *out;
- char *tempstore;
- unsigned char randsuffix[9];
+ char *tempstore = NULL;
if(!altsvc)
/* no cache activated */
@@ -344,17 +343,8 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
/* marked as read-only, no file or zero length file name */
return CURLE_OK;
- if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
- return CURLE_FAILED_INIT;
-
- tempstore = aprintf("%s.%s.tmp", file, randsuffix);
- if(!tempstore)
- return CURLE_OUT_OF_MEMORY;
-
- out = fopen(tempstore, FOPEN_WRITETEXT);
- if(!out)
- result = CURLE_WRITE_ERROR;
- else {
+ result = Curl_fopen(data, file, &out, &tempstore);
+ if(!result) {
fputs("# Your alt-svc cache. https://curl.se/docs/alt-svc.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n",
out);
@@ -366,10 +356,10 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
break;
}
fclose(out);
- if(!result && Curl_rename(tempstore, file))
+ if(!result && tempstore && Curl_rename(tempstore, file))
result = CURLE_WRITE_ERROR;
- if(result)
+ if(result && tempstore)
unlink(tempstore);
}
free(tempstore);
--
2.35.3
From 2011622a36fa715f38277422241e77e25dfdf0d0 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 25 May 2022 10:09:54 +0200
Subject: [PATCH 3/3] hsts: use Curl_fopen()
Upstream-commit: d64115d7bb8ae4c136b620912da523c063f1d2ee
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/hsts.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/lib/hsts.c b/lib/hsts.c
index b9fa6f7..9d54c82 100644
--- a/lib/hsts.c
+++ b/lib/hsts.c
@@ -35,7 +35,7 @@
#include "sendf.h"
#include "strtoofft.h"
#include "parsedate.h"
-#include "rand.h"
+#include "fopen.h"
#include "rename.h"
/* The last 3 #include files should be in this order */
@@ -316,8 +316,7 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
struct Curl_llist_element *n;
CURLcode result = CURLE_OK;
FILE *out;
- char *tempstore;
- unsigned char randsuffix[9];
+ char *tempstore = NULL;
if(!h)
/* no cache activated */
@@ -331,17 +330,8 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
/* marked as read-only, no file or zero length file name */
goto skipsave;
- if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
- return CURLE_FAILED_INIT;
-
- tempstore = aprintf("%s.%s.tmp", file, randsuffix);
- if(!tempstore)
- return CURLE_OUT_OF_MEMORY;
-
- out = fopen(tempstore, FOPEN_WRITETEXT);
- if(!out)
- result = CURLE_WRITE_ERROR;
- else {
+ result = Curl_fopen(data, file, &out, &tempstore);
+ if(!result) {
fputs("# Your HSTS cache. https://curl.se/docs/hsts.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n",
out);
@@ -353,10 +343,10 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
break;
}
fclose(out);
- if(!result && Curl_rename(tempstore, file))
+ if(!result && tempstore && Curl_rename(tempstore, file))
result = CURLE_WRITE_ERROR;
- if(result)
+ if(result && tempstore)
unlink(tempstore);
}
free(tempstore);
--
2.35.3

@ -1,186 +0,0 @@
From c2acc48854be9f8590e57a7b44b649fb8537bed4 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 4 May 2021 16:14:13 +0200
Subject: [PATCH] openldap: replace ldap_ prefix on private functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Since openldap itself uses that prefix and with OpenĹDAP 2.5.4 (at
least) there's a symbol collision because of that.
The private functions now use the 'oldap_' prefix where it previously
used 'ldap_'.
Reported-by: 3eka on github
Fixes #7004
Closes #7005
Upstream-commit: 8bdde6b14ce3b5fd71c772a578fcbd4b6fa6df19
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/openldap.c | 67 +++++++++++++++++++++++++-------------------------
1 file changed, 34 insertions(+), 33 deletions(-)
diff --git a/lib/openldap.c b/lib/openldap.c
index b515554..5a32c74 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -76,16 +76,16 @@ extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
LDAP **ld);
#endif
-static CURLcode ldap_setup_connection(struct Curl_easy *data,
- struct connectdata *conn);
-static CURLcode ldap_do(struct Curl_easy *data, bool *done);
-static CURLcode ldap_done(struct Curl_easy *data, CURLcode, bool);
-static CURLcode ldap_connect(struct Curl_easy *data, bool *done);
-static CURLcode ldap_connecting(struct Curl_easy *data, bool *done);
-static CURLcode ldap_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead);
+static CURLcode oldap_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static CURLcode oldap_do(struct Curl_easy *data, bool *done);
+static CURLcode oldap_done(struct Curl_easy *data, CURLcode, bool);
+static CURLcode oldap_connect(struct Curl_easy *data, bool *done);
+static CURLcode oldap_connecting(struct Curl_easy *data, bool *done);
+static CURLcode oldap_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
-static Curl_recv ldap_recv;
+static Curl_recv oldap_recv;
/*
* LDAP protocol handler.
@@ -93,18 +93,18 @@ static Curl_recv ldap_recv;
const struct Curl_handler Curl_handler_ldap = {
"LDAP", /* scheme */
- ldap_setup_connection, /* setup_connection */
- ldap_do, /* do_it */
- ldap_done, /* done */
+ oldap_setup_connection, /* setup_connection */
+ oldap_do, /* do_it */
+ oldap_done, /* done */
ZERO_NULL, /* do_more */
- ldap_connect, /* connect_it */
- ldap_connecting, /* connecting */
+ oldap_connect, /* connect_it */
+ oldap_connecting, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- ldap_disconnect, /* disconnect */
+ oldap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
@@ -121,18 +121,18 @@ const struct Curl_handler Curl_handler_ldap = {
const struct Curl_handler Curl_handler_ldaps = {
"LDAPS", /* scheme */
- ldap_setup_connection, /* setup_connection */
- ldap_do, /* do_it */
- ldap_done, /* done */
+ oldap_setup_connection, /* setup_connection */
+ oldap_do, /* do_it */
+ oldap_done, /* done */
ZERO_NULL, /* do_more */
- ldap_connect, /* connect_it */
- ldap_connecting, /* connecting */
+ oldap_connect, /* connect_it */
+ oldap_connecting, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- ldap_disconnect, /* disconnect */
+ oldap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
@@ -173,8 +173,8 @@ struct ldapreqinfo {
int nument;
};
-static CURLcode ldap_setup_connection(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode oldap_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct ldapconninfo *li;
LDAPURLDesc *lud;
@@ -209,7 +209,7 @@ static CURLcode ldap_setup_connection(struct Curl_easy *data,
static Sockbuf_IO ldapsb_tls;
#endif
-static CURLcode ldap_connect(struct Curl_easy *data, bool *done)
+static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
@@ -257,7 +257,7 @@ static CURLcode ldap_connect(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
-static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
+static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
@@ -356,14 +356,15 @@ static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
if(info)
ldap_memfree(info);
- conn->recv[FIRSTSOCKET] = ldap_recv;
+ conn->recv[FIRSTSOCKET] = oldap_recv;
*done = TRUE;
return CURLE_OK;
}
-static CURLcode ldap_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead_connection)
+static CURLcode oldap_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
struct ldapconninfo *li = conn->proto.ldapc;
(void) dead_connection;
@@ -384,7 +385,7 @@ static CURLcode ldap_disconnect(struct Curl_easy *data,
return CURLE_OK;
}
-static CURLcode ldap_do(struct Curl_easy *data, bool *done)
+static CURLcode oldap_do(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
@@ -429,8 +430,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
-static CURLcode ldap_done(struct Curl_easy *data, CURLcode res,
- bool premature)
+static CURLcode oldap_done(struct Curl_easy *data, CURLcode res,
+ bool premature)
{
struct connectdata *conn = data->conn;
struct ldapreqinfo *lr = data->req.p.ldap;
@@ -452,8 +453,8 @@ static CURLcode ldap_done(struct Curl_easy *data, CURLcode res,
return CURLE_OK;
}
-static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
- size_t len, CURLcode *err)
+static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
+ size_t len, CURLcode *err)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
--
2.35.3

@ -1,136 +0,0 @@
From fbc2ac6f06ec13cc872ce7adb870f4d7c7d5dded Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 29 Aug 2022 00:09:17 +0200
Subject: [PATCH 1/2] cookie: reject cookies with "control bytes"
Rejects 0x01 - 0x1f (except 0x09) plus 0x7f
Reported-by: Axel Chong
Bug: https://curl.se/docs/CVE-2022-35252.html
CVE-2022-35252
Closes #9381
Upstream-commit: 8dfc93e573ca740544a2d79ebb0ed786592c65c3
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/cookie.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/lib/cookie.c b/lib/cookie.c
index cb0c03b..e0470a1 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -383,6 +383,30 @@ static void strstore(char **str, const char *newstr)
*str = strdup(newstr);
}
+/*
+ RFC 6265 section 4.1.1 says a server should accept this range:
+
+ cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
+
+ But Firefox and Chrome as of June 2022 accept space, comma and double-quotes
+ fine. The prime reason for filtering out control bytes is that some HTTP
+ servers return 400 for requests that contain such.
+*/
+static int invalid_octets(const char *p)
+{
+ /* Reject all bytes \x01 - \x1f (*except* \x09, TAB) + \x7f */
+ static const char badoctets[] = {
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x0a"
+ "\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;
+ /* scan for all the octets that are *not* in cookie-octet */
+ len = strcspn(p, badoctets);
+ vlen = strlen(p);
+ return (len != vlen);
+}
+
/*
* remove_expired() removes expired cookies.
*/
@@ -567,6 +591,11 @@ Curl_cookie_add(struct Curl_easy *data,
badcookie = TRUE;
break;
}
+ if(invalid_octets(whatptr) || invalid_octets(name)) {
+ infof(data, "invalid octets in name/value, cookie dropped");
+ badcookie = TRUE;
+ break;
+ }
}
else if(!len) {
/* this was a "<name>=" with no content, and we must allow
--
2.37.1
From 1a3e2bd48572761236934651091c899a4d460ef5 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 29 Aug 2022 00:09:17 +0200
Subject: [PATCH 2/2] test8: verify that "ctrl-byte cookies" are ignored
Upstream-commit: 2fc031d834d488854ffc58bf7dbcef7fa7c1fc28
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/data/test8 | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/tests/data/test8 b/tests/data/test8
index a8548e6..8587611 100644
--- a/tests/data/test8
+++ b/tests/data/test8
@@ -46,6 +46,36 @@ Set-Cookie: trailingspace = removed; path=/we/want;
Set-Cookie: nocookie=yes; path=/WE;
Set-Cookie: blexp=yesyes; domain=%HOSTIP; domain=%HOSTIP; expiry=totally bad;
Set-Cookie: partialip=nono; domain=.0.0.1;
+Set-Cookie: cookie1=%hex[%01-junk]hex%
+Set-Cookie: cookie2=%hex[%02-junk]hex%
+Set-Cookie: cookie3=%hex[%03-junk]hex%
+Set-Cookie: cookie4=%hex[%04-junk]hex%
+Set-Cookie: cookie5=%hex[%05-junk]hex%
+Set-Cookie: cookie6=%hex[%06-junk]hex%
+Set-Cookie: cookie7=%hex[%07-junk]hex%
+Set-Cookie: cookie8=%hex[%08-junk]hex%
+Set-Cookie: cookie9=%hex[junk-%09-]hex%
+Set-Cookie: cookie11=%hex[%0b-junk]hex%
+Set-Cookie: cookie12=%hex[%0c-junk]hex%
+Set-Cookie: cookie14=%hex[%0e-junk]hex%
+Set-Cookie: cookie15=%hex[%0f-junk]hex%
+Set-Cookie: cookie16=%hex[%10-junk]hex%
+Set-Cookie: cookie17=%hex[%11-junk]hex%
+Set-Cookie: cookie18=%hex[%12-junk]hex%
+Set-Cookie: cookie19=%hex[%13-junk]hex%
+Set-Cookie: cookie20=%hex[%14-junk]hex%
+Set-Cookie: cookie21=%hex[%15-junk]hex%
+Set-Cookie: cookie22=%hex[%16-junk]hex%
+Set-Cookie: cookie23=%hex[%17-junk]hex%
+Set-Cookie: cookie24=%hex[%18-junk]hex%
+Set-Cookie: cookie25=%hex[%19-junk]hex%
+Set-Cookie: cookie26=%hex[%1a-junk]hex%
+Set-Cookie: cookie27=%hex[%1b-junk]hex%
+Set-Cookie: cookie28=%hex[%1c-junk]hex%
+Set-Cookie: cookie29=%hex[%1d-junk]hex%
+Set-Cookie: cookie30=%hex[%1e-junk]hex%
+Set-Cookie: cookie31=%hex[%1f-junk]hex%
+Set-Cookie: cookie31=%hex[%7f-junk]hex%
</file>
<precheck>
@@ -60,7 +90,7 @@ GET /we/want/%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
-Cookie: name with space=is weird but; trailingspace=removed; cookie=perhaps; cookie=yes; foobar=name; blexp=yesyes
+Cookie: name with space=is weird but; trailingspace=removed; cookie=perhaps; cookie=yes; foobar=name; blexp=yesyes; cookie9=junk- -
</protocol>
</verify>
--
2.37.1

@ -1,251 +0,0 @@
From 08a53016db649bdf4f65c42a9704d35e052be7eb Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 15 Sep 2022 09:22:45 +0200
Subject: [PATCH 1/2] setopt: when POST is set, reset the 'upload' field
Reported-by: RobBotic1 on github
Fixes #9507
Closes #9511
Upstream-commit: a64e3e59938abd7d667e4470a18072a24d7e9de9
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/setopt.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/setopt.c b/lib/setopt.c
index d5e3b50..b8793b4 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -628,6 +628,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
}
else
data->set.method = HTTPREQ_GET;
+ data->set.upload = FALSE;
break;
case CURLOPT_HTTPPOST:
--
2.37.3
From a5e36349807b98d31a16bd220f6434289465e16a Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 15 Sep 2022 09:23:33 +0200
Subject: [PATCH 2/2] test1948: verify PUT + POST reusing the same handle
Reproduced #9507, verifies the fix
Upstream-commit: 1edb15925e350be3b891f8a8de86600b22c0bb20
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/data/Makefile.inc | 1 +
tests/data/test1948 | 73 +++++++++++++++++++++++++++++++++++
tests/libtest/Makefile.inc | 5 +++
tests/libtest/lib1948.c | 79 ++++++++++++++++++++++++++++++++++++++
4 files changed, 158 insertions(+)
create mode 100644 tests/data/test1948
create mode 100644 tests/libtest/lib1948.c
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 818ee08..0cfab9b 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -217,6 +217,7 @@ test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \
test1916 test1917 test1918 \
\
test1933 test1934 test1935 test1936 \
+test1948 \
\
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
diff --git a/tests/data/test1948 b/tests/data/test1948
new file mode 100644
index 0000000..639523d
--- /dev/null
+++ b/tests/data/test1948
@@ -0,0 +1,73 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+HTTP PUT
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 01 Nov 2001 14:49:00 GMT
+Content-Type: text/html
+Content-Length: 6
+
+hello
+</data>
+<datacheck>
+HTTP/1.1 200 OK
+Date: Thu, 01 Nov 2001 14:49:00 GMT
+Content-Type: text/html
+Content-Length: 6
+
+hello
+HTTP/1.1 200 OK
+Date: Thu, 01 Nov 2001 14:49:00 GMT
+Content-Type: text/html
+Content-Length: 6
+
+hello
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+
+<name>
+CURLOPT_POST after CURLOPT_UPLOAD reusing handle
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+PUT /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 22
+Expect: 100-continue
+
+This is test PUT data
+POST /1948 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 22
+Content-Type: application/x-www-form-urlencoded
+
+This is test PUT data
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index 83a8af4..3192eca 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -61,6 +61,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \
lib1591 lib1592 lib1593 lib1594 lib1596 \
lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \
lib1915 lib1916 lib1917 lib1918 lib1933 lib1934 lib1935 lib1936 \
+ lib1948 \
lib3010
chkdecimalpoint_SOURCES = chkdecimalpoint.c ../../lib/mprintf.c \
@@ -690,6 +691,10 @@ lib1936_SOURCES = lib1936.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1936_LDADD = $(TESTUTIL_LIBS)
lib1936_CPPFLAGS = $(AM_CPPFLAGS)
+lib1948_SOURCES = lib1948.c $(SUPPORTFILES)
+lib1948_LDADD = $(TESTUTIL_LIBS)
+lib1948_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1948
+
lib3010_SOURCES = lib3010.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib3010_LDADD = $(TESTUTIL_LIBS)
lib3010_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/tests/libtest/lib1948.c b/tests/libtest/lib1948.c
new file mode 100644
index 0000000..7c891a2
--- /dev/null
+++ b/tests/libtest/lib1948.c
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * _ _ ____ _
+ * 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.haxx.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 "test.h"
+
+typedef struct
+{
+ char *buf;
+ size_t len;
+} put_buffer;
+
+static size_t put_callback(char *ptr, size_t size, size_t nmemb, void *stream)
+{
+ put_buffer *putdata = (put_buffer *)stream;
+ size_t totalsize = size * nmemb;
+ size_t tocopy = (putdata->len < totalsize) ? putdata->len : totalsize;
+ memcpy(ptr, putdata->buf, tocopy);
+ putdata->len -= tocopy;
+ putdata->buf += tocopy;
+ return tocopy;
+}
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OUT_OF_MEMORY;
+
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+
+ curl = curl_easy_init();
+ if(curl) {
+ const char *testput = "This is test PUT data\n";
+ put_buffer pbuf;
+
+ /* PUT */
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, put_callback);
+ pbuf.buf = (char *)testput;
+ pbuf.len = strlen(testput);
+ curl_easy_setopt(curl, CURLOPT_READDATA, &pbuf);
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, (long)strlen(testput));
+ res = curl_easy_setopt(curl, CURLOPT_URL, URL);
+ if(!res)
+ res = curl_easy_perform(curl);
+ if(!res) {
+ /* POST */
+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, testput);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(testput));
+ res = curl_easy_perform(curl);
+ }
+ curl_easy_cleanup(curl);
+ }
+
+ curl_global_cleanup();
+ return (int)res;
+}
--
2.37.3

@ -1,81 +0,0 @@
From 5cdcf1dbd39c64e18a81fc912a36942a3ec87565 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 19 Dec 2022 08:38:37 +0100
Subject: [PATCH] smb/telnet: do not free the protocol struct in *_done()
It is managed by the generic layer.
Reported-by: Trail of Bits
Closes #10112
Upstream-commit: 4f20188ac644afe174be6005ef4f6ffba232b8b2
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/smb.c | 14 ++------------
lib/telnet.c | 3 ---
2 files changed, 2 insertions(+), 15 deletions(-)
diff --git a/lib/smb.c b/lib/smb.c
index 039d680..f682c1f 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -60,8 +60,6 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done);
static CURLcode smb_connection_state(struct Curl_easy *data, bool *done);
static CURLcode smb_do(struct Curl_easy *data, bool *done);
static CURLcode smb_request_state(struct Curl_easy *data, bool *done);
-static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
- bool premature);
static CURLcode smb_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead);
static int smb_getsock(struct Curl_easy *data, struct connectdata *conn,
@@ -76,7 +74,7 @@ const struct Curl_handler Curl_handler_smb = {
"SMB", /* scheme */
smb_setup_connection, /* setup_connection */
smb_do, /* do_it */
- smb_done, /* done */
+ ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
smb_connect, /* connect_it */
smb_connection_state, /* connecting */
@@ -103,7 +101,7 @@ const struct Curl_handler Curl_handler_smbs = {
"SMBS", /* scheme */
smb_setup_connection, /* setup_connection */
smb_do, /* do_it */
- smb_done, /* done */
+ ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
smb_connect, /* connect_it */
smb_connection_state, /* connecting */
@@ -941,14 +939,6 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
-static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
- bool premature)
-{
- (void) premature;
- Curl_safefree(data->req.p.smb);
- return status;
-}
-
static CURLcode smb_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead)
{
diff --git a/lib/telnet.c b/lib/telnet.c
index 923c7f8..48cd0d7 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -1248,9 +1248,6 @@ static CURLcode telnet_done(struct Curl_easy *data,
curl_slist_free_all(tn->telnet_vars);
tn->telnet_vars = NULL;
-
- Curl_safefree(data->req.p.telnet);
-
return CURLE_OK;
}
--
2.38.1

@ -1,678 +0,0 @@
From 95f873ff983a1ae57415b3c16a881e74432cf8b8 Mon Sep 17 00:00:00 2001
From: Fabian Keil <fk@fabiankeil.de>
Date: Tue, 9 Feb 2021 14:04:32 +0100
Subject: [PATCH 1/4] runtests.pl: support the nonewline attribute for the data
part
Added to FILEFORMAT
Closes #8239
Upstream-commit: 736847611a40c01e7c290407e22e2f0f5f8efd6a
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/FILEFORMAT.md | 5 ++++-
tests/runtests.pl | 7 +++++++
tests/server/getpart.c | 11 ++++++++++-
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md
index b75a02a..0b98787 100644
--- a/tests/FILEFORMAT.md
+++ b/tests/FILEFORMAT.md
@@ -185,7 +185,7 @@ which are treated together as a single identifier.
## `<reply>`
-### `<data [nocheck="yes"] [sendzero="yes"] [base64="yes"] [hex="yes"]>`
+### `<data [nocheck="yes"] [sendzero="yes"] [base64="yes"] [hex="yes"] [nonewline="yes"]>`
data to be sent to the client on its request and later verified that it
arrived safely. Set `nocheck="yes"` to prevent the test script from verifying
@@ -211,6 +211,9 @@ much sense for other sections than "data").
`hex=yes` means that the data is a sequence of hex pairs. It will get decoded
and used as "raw" data.
+`nonewline=yes` means that the last byte (the trailing newline character)
+should be cut off from the data before sending or comparing it.
+
For FTP file listings, the `<data>` section will be used *only* if you make
sure that there has been a CWD done first to a directory named `test-[num]`
where [num] is the test case number. Otherwise the ftp server can't know from
diff --git a/tests/runtests.pl b/tests/runtests.pl
index 40315aa..2e1500d 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -3837,6 +3837,13 @@ sub singletest {
else {
# check against the data section
@reply = getpart("reply", "data");
+ if(@reply) {
+ my %hash = getpartattr("reply", "data");
+ if($hash{'nonewline'}) {
+ # cut off the final newline from the final line of the data
+ chomp($reply[$#reply]);
+ }
+ }
# get the mode attribute
my $filemode=$replyattr{'mode'};
if($filemode && ($filemode eq "text") && $has_textaware) {
diff --git a/tests/server/getpart.c b/tests/server/getpart.c
index 32b55bc..f8fe3f6 100644
--- a/tests/server/getpart.c
+++ b/tests/server/getpart.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * 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
@@ -295,6 +295,7 @@ int getpart(char **outbuf, size_t *outlen,
size_t outalloc = 256;
int in_wanted_part = 0;
int base64 = 0;
+ int nonewline = 0;
int error;
enum {
@@ -360,6 +361,8 @@ int getpart(char **outbuf, size_t *outlen,
if(error)
return error;
}
+ if(nonewline)
+ (*outlen)--;
break;
}
}
@@ -377,6 +380,8 @@ int getpart(char **outbuf, size_t *outlen,
if(error)
return error;
}
+ if(nonewline)
+ (*outlen)--;
break;
}
}
@@ -451,6 +456,10 @@ int getpart(char **outbuf, size_t *outlen,
/* bit rough test, but "mostly" functional, */
/* treat wanted part data as base64 encoded */
base64 = 1;
+ if(strstr(patt, "nonewline=")) {
+ show(("* setting nonewline\n"));
+ nonewline = 1;
+ }
}
continue;
}
--
2.39.1
From 6e244e1bcb04012e11c537253e76e6f968d8bb72 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 1 Dec 2022 09:21:04 +0100
Subject: [PATCH 2/4] runtests: do CRLF replacements per section only
The `crlf="yes"` attribute and "hyper mode" are now only applied on a
subset of dedicated sections: data, datacheck, stdout and protocol.
Updated test 2500 accordingly.
Also made test1 use crlf="yes" for <protocol>, mostly because it is
often used as a template test case. Going forward, using this attribute
we should be able to write test cases using linefeeds only and avoid
mixed line ending encodings.
Follow-up to ca15b7512e8d11
Fixes #10009
Closes #10010
Upstream-commit: 2f34a7347f315513bfda9ef14770d287fb246bcd
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/FILEFORMAT.md | 22 +++++++++++++++------
tests/data/test1 | 14 ++++++-------
tests/runtests.pl | 48 ++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 68 insertions(+), 16 deletions(-)
diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md
index c1fbc57..dcb5695 100644
--- a/tests/FILEFORMAT.md
+++ b/tests/FILEFORMAT.md
@@ -185,7 +185,7 @@ which are treated together as a single identifier.
## `<reply>`
-### `<data [nocheck="yes"] [sendzero="yes"] [base64="yes"] [hex="yes"] [nonewline="yes"]>`
+### `<data [nocheck="yes"] [sendzero="yes"] [base64="yes"] [hex="yes"] [nonewline="yes"] [crlf="yes"]>`
data to be sent to the client on its request and later verified that it
arrived safely. Set `nocheck="yes"` to prevent the test script from verifying
@@ -214,12 +214,16 @@ and used as "raw" data.
`nonewline=yes` means that the last byte (the trailing newline character)
should be cut off from the data before sending or comparing it.
+`crlf=yes` forces *header* newlines to become CRLF even if not written so in
+the source file. Note that this makes runtests.pl parse and "guess" what is a
+header and what is not in order to apply the CRLF line endings appropriately.
+
For FTP file listings, the `<data>` section will be used *only* if you make
sure that there has been a CWD done first to a directory named `test-[num]`
where [num] is the test case number. Otherwise the ftp server can't know from
which test file to load the list content.
-### `<dataNUM>`
+### `<dataNUM [crlf="yes"]>`
Send back this contents instead of the <data> one. The num is set by:
@@ -243,7 +247,7 @@ The connect section is used instead of the 'data' for all CONNECT
requests. The remainder of the rules for the data section then apply but with
a connect prefix.
-### `<datacheck [mode="text"] [nonewline="yes"]>`
+### `<datacheck [mode="text"] [nonewline="yes"] [crlf="yes"]>`
if the data is sent but this is what should be checked afterwards. If
`nonewline=yes` is set, runtests will cut off the trailing newline from the
data before comparing with the one actually received by the client.
@@ -251,7 +255,7 @@ data before comparing with the one actually received by the client.
Use the `mode="text"` attribute if the output is in text mode on platforms
that have a text/binary difference.
-### `<datacheckNUM [nonewline="yes"] [mode="text"]>`
+### `<datacheckNUM [nonewline="yes"] [mode="text"] [crlf="yes"]>`
The contents of numbered datacheck sections are appended to the non-numbered
one.
@@ -528,13 +532,16 @@ changing protocol data such as port numbers or user-agent strings.
One perl op per line that operates on the protocol dump. This is pretty
advanced. Example: `s/^EPRT .*/EPRT stripped/`.
-### `<protocol [nonewline="yes"]>`
+### `<protocol [nonewline="yes"] crlf="yes">`
the protocol dump curl should transmit, if 'nonewline' is set, we will cut off
the trailing newline of this given data before comparing with the one actually
sent by the client The `<strip>` and `<strippart>` rules are applied before
comparisons are made.
+`crlf=yes` forces the newlines to become CRLF even if not written so in the
+test.
+
### `<proxy [nonewline="yes"]>`
The protocol dump curl should transmit to a HTTP proxy (when the http-proxy
@@ -551,7 +558,7 @@ have a text/binary difference.
If 'nonewline' is set, we will cut off the trailing newline of this given data
before comparing with the one actually received by the client
-### `<stdout [mode="text"] [nonewline="yes"]>`
+### `<stdout [mode="text"] [nonewline="yes"] [crlf="yes"]>`
This verifies that this data was passed to stdout.
Use the mode="text" attribute if the output is in text mode on platforms that
@@ -560,6 +567,9 @@ have a text/binary difference.
If 'nonewline' is set, we will cut off the trailing newline of this given data
before comparing with the one actually received by the client
+`crlf=yes` forces the newlines to become CRLF even if not written so in the
+test.
+
### `<file name="log/filename" [mode="text"]>`
The file's contents must be identical to this after the test is complete. Use
the mode="text" attribute if the output is in text mode on platforms that have
diff --git a/tests/data/test1 b/tests/data/test1
index f39a08b..700bed8 100644
--- a/tests/data/test1
+++ b/tests/data/test1
@@ -9,7 +9,7 @@ HTTP GET
#
# Server-side
<reply>
-<data>
+<data crlf="yes">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -42,12 +42,12 @@ http://%HOSTIP:%HTTPPORT/%TESTNUMBER
#
# Verify data after the test has been "shot"
<verify>
-<protocol>
-GET /%TESTNUMBER HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-User-Agent: curl/%VERSION
-Accept: */*
-
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
</protocol>
</verify>
</testcase>
diff --git a/tests/runtests.pl b/tests/runtests.pl
index 72a9989..b12a42d 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -3410,7 +3410,13 @@ sub subBase64 {
my $prevupdate;
sub subNewlines {
- my ($thing) = @_;
+ my ($force, $thing) = @_;
+
+ if($force) {
+ # enforce CRLF newline
+ $$thing =~ s/\x0d*\x0a/\x0d\x0a/;
+ return;
+ }
# When curl is built with Hyper, it gets all response headers delivered as
# name/value pairs and curl "invents" the newlines when it saves the
@@ -3424,7 +3430,7 @@ sub subNewlines {
# skip curl error messages
($$thing !~ /^curl: \(\d+\) /))) {
# enforce CRLF newline
- $$thing =~ s/\x0a/\x0d\x0a/;
+ $$thing =~ s/\x0d*\x0a/\x0d\x0a/;
$prevupdate = 1;
}
else {
@@ -3496,6 +3502,7 @@ sub prepro {
my (@entiretest) = @_;
my $show = 1;
my @out;
+ my $data_crlf;
for my $s (@entiretest) {
my $f = $s;
if($s =~ /^ *%if (.*)/) {
@@ -3519,9 +3526,19 @@ sub prepro {
next;
}
if($show) {
+ # The processor does CRLF replacements in the <data*> sections if
+ # necessary since those parts might be read by separate servers.
+ if($s =~ /^ *<data(.*)\>/) {
+ if($1 =~ /crlf="yes"/ || $has_hyper) {
+ $data_crlf = 1;
+ }
+ }
+ elsif(($s =~ /^ *<\/data/) && $data_crlf) {
+ $data_crlf = 0;
+ }
subVariables(\$s, $testnum, "%");
subBase64(\$s);
- subNewlines(\$s) if($has_hyper);
+ subNewlines(0, \$s) if($data_crlf);
push @out, $s;
}
}
@@ -3830,6 +3847,11 @@ sub singletest {
# of the datacheck
chomp($replycheckpart[$#replycheckpart]);
}
+ if($replycheckpartattr{'crlf'} ||
+ ($has_hyper && ($keywords{"HTTP"}
+ || $keywords{"HTTPS"}))) {
+ map subNewlines(0, \$_), @replycheckpart;
+ }
push(@reply, @replycheckpart);
}
}
@@ -3851,6 +3873,11 @@ sub singletest {
map s/\r\n/\n/g, @reply;
map s/\n/\r\n/g, @reply;
}
+ if($replyattr{'crlf'} ||
+ ($has_hyper && ($keywords{"HTTP"}
+ || $keywords{"HTTPS"}))) {
+ map subNewlines(0, \$_), @reply;
+ }
}
# this is the valid protocol blurb curl should generate
@@ -4287,6 +4314,12 @@ sub singletest {
chomp($validstdout[$#validstdout]);
}
+ if($hash{'crlf'} ||
+ ($has_hyper && ($keywords{"HTTP"}
+ || $keywords{"HTTPS"}))) {
+ map subNewlines(0, \$_), @validstdout;
+ }
+
$res = compare($testnum, $testname, "stdout", \@actual, \@validstdout);
if($res) {
return $errorreturncode;
@@ -4381,6 +4414,10 @@ sub singletest {
}
}
+ if($hash{'crlf'}) {
+ map subNewlines(1, \$_), @protstrip;
+ }
+
if((!$out[0] || ($out[0] eq "")) && $protstrip[0]) {
logmsg "\n $testnum: protocol FAILED!\n".
" There was no content at all in the file $SERVERIN.\n".
@@ -4512,6 +4549,11 @@ sub singletest {
map s/\r\n/\n/g, @outfile;
map s/\n/\r\n/g, @outfile;
}
+ if($hash{'crlf'} ||
+ ($has_hyper && ($keywords{"HTTP"}
+ || $keywords{"HTTPS"}))) {
+ map subNewlines(0, \$_), @outfile;
+ }
my $strip;
for $strip (@stripfile) {
--
2.39.1
From 228ed11bf33c63d9208a3fb38fe5a0d19c0764bd Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 27 Dec 2022 11:50:23 +0100
Subject: [PATCH 3/4] runtests: support crlf="yes" for verify/proxy
Upstream-commit: dc0725244a3163f1e2d5f51165db3a1a430f3ba0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/FILEFORMAT.md | 4 ++--
tests/runtests.pl | 5 +++++
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md
index dcb5695..6646793 100644
--- a/tests/FILEFORMAT.md
+++ b/tests/FILEFORMAT.md
@@ -532,7 +532,7 @@ changing protocol data such as port numbers or user-agent strings.
One perl op per line that operates on the protocol dump. This is pretty
advanced. Example: `s/^EPRT .*/EPRT stripped/`.
-### `<protocol [nonewline="yes"] crlf="yes">`
+### `<protocol [nonewline="yes"][crlf="yes"]>`
the protocol dump curl should transmit, if 'nonewline' is set, we will cut off
the trailing newline of this given data before comparing with the one actually
@@ -542,7 +542,7 @@ comparisons are made.
`crlf=yes` forces the newlines to become CRLF even if not written so in the
test.
-### `<proxy [nonewline="yes"]>`
+### `<proxy [nonewline="yes"][crlf="yes"]>`
The protocol dump curl should transmit to a HTTP proxy (when the http-proxy
server is used), if 'nonewline' is set, we will cut off the trailing newline
diff --git a/tests/runtests.pl b/tests/runtests.pl
index b12a42d..5cdc83d 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -4510,6 +4510,11 @@ sub singletest {
}
}
+ if($hash{'crlf'} ||
+ ($has_hyper && ($keywords{"HTTP"} || $keywords{"HTTPS"}))) {
+ map subNewlines(0, \$_), @protstrip;
+ }
+
$res = compare($testnum, $testname, "proxy", \@out, \@protstrip);
if($res) {
return $errorreturncode;
--
2.39.1
From bc5fc958b017895728962c9d44c469418cbec1a0 Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <patrick@monnerat.net>
Date: Mon, 13 Feb 2023 08:33:09 +0100
Subject: [PATCH 4/4] content_encoding: do not reset stage counter for each
header
Test 418 verifies
Closes #10492
Upstream-commit: 119fb187192a9ea13dc90d9d20c215fc82799ab9
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/content_encoding.c | 7 +-
lib/urldata.h | 1 +
tests/data/Makefile.inc | 1 +
tests/data/test387 | 2 +-
tests/data/test418 | 152 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 158 insertions(+), 5 deletions(-)
create mode 100644 tests/data/test418
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index bfc13e2..94344d6 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -1033,7 +1033,6 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked)
{
struct SingleRequest *k = &data->req;
- int counter = 0;
do {
const char *name;
@@ -1068,9 +1067,9 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
if(!encoding)
encoding = &error_encoding; /* Defer error at stack use. */
- if(++counter >= MAX_ENCODE_STACK) {
- failf(data, "Reject response due to %u content encodings",
- counter);
+ if(k->writer_stack_depth++ >= MAX_ENCODE_STACK) {
+ failf(data, "Reject response due to more than %u content encodings",
+ MAX_ENCODE_STACK);
return CURLE_BAD_CONTENT_ENCODING;
}
/* Stack the unencoding stage. */
diff --git a/lib/urldata.h b/lib/urldata.h
index 5b4b34f..8c8c20b 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -700,6 +700,7 @@ struct SingleRequest {
#ifndef CURL_DISABLE_DOH
struct dohdata *doh; /* DoH specific data for this request */
#endif
+ unsigned char writer_stack_depth; /* Unencoding stack depth. */
BIT(header); /* incoming data has HTTP header */
BIT(content_range); /* set TRUE if Content-Range: was found */
BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index fb51cd6..86b6f85 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -67,6 +67,7 @@ test393 test394 test395 test396 test397 \
\
test400 test401 test402 test403 test404 test405 test406 test407 test408 \
test409 test410 \
+ test418 \
\
test430 test431 test432 test433 test434 \
\
diff --git a/tests/data/test387 b/tests/data/test387
index 015ec25..644fc7f 100644
--- a/tests/data/test387
+++ b/tests/data/test387
@@ -47,7 +47,7 @@ Accept: */*
61
</errorcode>
<stderr mode="text">
-curl: (61) Reject response due to 5 content encodings
+curl: (61) Reject response due to more than 5 content encodings
</stderr>
</verify>
</testcase>
diff --git a/tests/data/test418 b/tests/data/test418
new file mode 100644
index 0000000..50e974e
--- /dev/null
+++ b/tests/data/test418
@@ -0,0 +1,152 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+gzip
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+Response with multiple Transfer-Encoding headers
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -sS
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+
+# CURLE_BAD_CONTENT_ENCODING is 61
+<errorcode>
+61
+</errorcode>
+<stderr mode="text">
+curl: (61) Reject response due to more than 5 content encodings
+</stderr>
+</verify>
+</testcase>
--
2.39.1

@ -1,59 +0,0 @@
From c9828d86040737a47da862197b5def7ff6b0e3c4 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 6 Mar 2023 12:07:33 +0100
Subject: [PATCH] telnet: only accept option arguments in ascii
To avoid embedded telnet negotiation commands etc.
Reported-by: Harry Sintonen
Closes #10728
Upstream-commit: 538b1e79a6e7b0bb829ab4cecc828d32105d0684
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/telnet.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/lib/telnet.c b/lib/telnet.c
index 22bc81e..baea885 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -770,6 +770,17 @@ static void printsub(struct Curl_easy *data,
}
}
+static bool str_is_nonascii(const char *str)
+{
+ size_t len = strlen(str);
+ while(len--) {
+ if(*str & 0x80)
+ return TRUE;
+ str++;
+ }
+ return FALSE;
+}
+
static CURLcode check_telnet_options(struct Curl_easy *data)
{
struct curl_slist *head;
@@ -784,6 +795,8 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
/* Add the user name as an environment variable if it
was given on the command line */
if(conn->bits.user_passwd) {
+ if(str_is_nonascii(data->conn->user))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
beg = curl_slist_append(tn->telnet_vars, option_arg);
if(!beg) {
@@ -798,6 +811,8 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
for(head = data->set.telnet_options; head; head = head->next) {
if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
option_keyword, option_arg) == 2) {
+ if(str_is_nonascii(option_arg))
+ continue;
/* Terminal type */
if(strcasecompare(option_keyword, "TTYPE")) {
--
2.39.2

File diff suppressed because it is too large Load Diff

@ -1,230 +0,0 @@
From e8705acd69383c13191c9dd4867d5118e58c54ba Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 6 Oct 2022 00:49:10 +0200
Subject: [PATCH 1/2] strcase: add Curl_timestrcmp
This is a strcmp() alternative function for comparing "secrets",
designed to take the same time no matter the content to not leak
match/non-match info to observers based on how fast it is.
The time this function takes is only a function of the shortest input
string.
Reported-by: Trail of Bits
Closes #9658
Upstream-commit: ed5095ed94281989e103c72e032200b83be37878
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/strcase.c | 22 ++++++++++++++++++++++
lib/strcase.h | 1 +
2 files changed, 23 insertions(+)
diff --git a/lib/strcase.c b/lib/strcase.c
index f932485..c73907d 100644
--- a/lib/strcase.c
+++ b/lib/strcase.c
@@ -261,6 +261,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/lib/strcase.h b/lib/strcase.h
index d245929..11a67a1 100644
--- a/lib/strcase.h
+++ b/lib/strcase.h
@@ -49,5 +49,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 */
--
2.39.2
From 9cfaea212ff347937a38f6b5d6b885ed8ba1b931 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 9 Mar 2023 17:47:06 +0100
Subject: [PATCH 2/2] ftp: add more conditions for connection reuse
Reported-by: Harry Sintonen
Closes #10730
Upstream-commit: 8f4608468b890dce2dad9f91d5607ee7e9c1aba1
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/ftp.c | 28 ++++++++++++++++++++++++++--
lib/ftp.h | 5 +++++
lib/setopt.c | 2 +-
lib/url.c | 12 ++++++++++++
lib/urldata.h | 4 ++--
5 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/lib/ftp.c b/lib/ftp.c
index 9442832..df15bc0 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -4086,6 +4086,8 @@ static CURLcode ftp_disconnect(struct Curl_easy *data,
}
freedirs(ftpc);
+ Curl_safefree(ftpc->account);
+ Curl_safefree(ftpc->alternative_to_user);
Curl_safefree(ftpc->prevpath);
Curl_safefree(ftpc->server_os);
Curl_pp_disconnect(pp);
@@ -4346,11 +4348,31 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
{
char *type;
struct FTP *ftp;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
- data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1);
+ ftp = calloc(sizeof(struct FTP), 1);
if(NULL == ftp)
return CURLE_OUT_OF_MEMORY;
+ /* clone connection related data that is FTP specific */
+ if(data->set.str[STRING_FTP_ACCOUNT]) {
+ ftpc->account = strdup(data->set.str[STRING_FTP_ACCOUNT]);
+ if(!ftpc->account) {
+ free(ftp);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]) {
+ ftpc->alternative_to_user =
+ strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
+ if(!ftpc->alternative_to_user) {
+ Curl_safefree(ftpc->account);
+ free(ftp);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ data->req.p.ftp = ftp;
+
ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
/* FTP URLs support an extension like ";type=<typecode>" that
@@ -4385,7 +4407,9 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
/* get some initial data into the ftp struct */
ftp->transfer = PPTRANSFER_BODY;
ftp->downloadsize = 0;
- conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
+ ftpc->known_filesize = -1; /* unknown size for now */
+ ftpc->use_ssl = data->set.use_ssl;
+ ftpc->ccc = data->set.ftp_ccc;
return CURLE_OK;
}
diff --git a/lib/ftp.h b/lib/ftp.h
index 7f6f432..3f33e27 100644
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -115,6 +115,8 @@ struct FTP {
struct */
struct ftp_conn {
struct pingpong pp;
+ char *account;
+ char *alternative_to_user;
char *entrypath; /* the PWD reply when we logged on */
char *file; /* url-decoded file name (or path) */
char **dirs; /* realloc()ed array for path components */
@@ -144,6 +146,9 @@ struct ftp_conn {
ftpstate state; /* always use ftp.c:state() to change state! */
ftpstate state_saved; /* transfer type saved to be reloaded after
data connection is established */
+ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
+ IMAP or POP3 or others! (type: curl_usessl)*/
+ unsigned char ccc; /* ccc level for this connection */
curl_off_t retr_size_saved; /* Size of retrieved file saved */
char *server_os; /* The target server operating system. */
curl_off_t known_filesize; /* file size is different from -1, if wildcard
diff --git a/lib/setopt.c b/lib/setopt.c
index 3339a67..6fc111d 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -2264,7 +2264,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < CURLUSESSL_NONE) || (arg >= CURLUSESSL_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.use_ssl = (curl_usessl)arg;
+ data->set.use_ssl = (unsigned char)arg;
break;
case CURLOPT_SSL_OPTIONS:
diff --git a/lib/url.c b/lib/url.c
index 61ba832..4e21838 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1329,6 +1329,18 @@ ConnectionExists(struct Curl_easy *data,
if(!ssh_config_matches(needle, check))
continue;
}
+#ifndef CURL_DISABLE_FTP
+ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) {
+ /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
+ if(Curl_timestrcmp(needle->proto.ftpc.account,
+ check->proto.ftpc.account) ||
+ Curl_timestrcmp(needle->proto.ftpc.alternative_to_user,
+ check->proto.ftpc.alternative_to_user) ||
+ (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) ||
+ (needle->proto.ftpc.ccc != check->proto.ftpc.ccc))
+ continue;
+ }
+#endif
if((needle->handler->flags&PROTOPT_SSL)
#ifndef CURL_DISABLE_PROXY
diff --git a/lib/urldata.h b/lib/urldata.h
index 9d9ca92..4e2f5b9 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1749,8 +1749,6 @@ struct UserDefined {
void *ssh_keyfunc_userp; /* custom pointer to callback */
enum CURL_NETRC_OPTION
use_netrc; /* defined in include/curl.h */
- curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
- IMAP or POP3 or others! */
long new_file_perms; /* Permissions to use when creating remote files */
long new_directory_perms; /* Permissions to use when creating remote dirs */
long ssh_auth_types; /* allowed SSH auth types */
@@ -1793,6 +1791,8 @@ struct UserDefined {
CURLU *uh; /* URL handle for the current parsed URL */
void *trailer_data; /* pointer to pass to trailer data callback */
curl_trailer_callback trailer_callback; /* trailing data callback */
+ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
+ IMAP or POP3 or others! (type: curl_usessl)*/
BIT(is_fread_set); /* has read callback been set to non-NULL? */
BIT(is_fwrite_set); /* has write callback been set to non-NULL? */
BIT(free_referer); /* set TRUE if 'referer' points to a string we
--
2.39.2

@ -1,54 +0,0 @@
From 9d6dd7bc1dea42ae8e710aeae714e2a2c290de61 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 10 Mar 2023 09:22:43 +0100
Subject: [PATCH] url: only reuse connections with same GSS delegation
Reported-by: Harry Sintonen
Closes #10731
Upstream-commit: cb49e67303dbafbab1cebf4086e3ec15b7d56ee5
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/url.c | 6 ++++++
lib/urldata.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/lib/url.c b/lib/url.c
index 3b11b7e..cbbc7f3 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1325,6 +1325,11 @@ ConnectionExists(struct Curl_easy *data,
}
}
+ /* GSS delegation differences do not actually affect every connection
+ and auth method, but this check takes precaution before efficiency */
+ if(needle->gssapi_delegation != check->gssapi_delegation)
+ continue;
+
if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) {
if(!ssh_config_matches(needle, check))
continue;
@@ -1785,6 +1790,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->fclosesocket = data->set.fclosesocket;
conn->closesocket_client = data->set.closesocket_client;
conn->lastused = Curl_now(); /* used now */
+ conn->gssapi_delegation = data->set.gssapi_delegation;
return conn;
error:
diff --git a/lib/urldata.h b/lib/urldata.h
index ce90304..9e16f26 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -995,6 +995,7 @@ struct connectdata {
char *sasl_authzid; /* authorisation identity string, allocated */
char *oauth_bearer; /* OAUTH2 bearer, allocated */
unsigned char httpversion; /* the HTTP version*10 reported by the server */
+ unsigned char gssapi_delegation; /* inherited from set.gssapi_delegation */
struct curltime now; /* "current" time */
struct curltime created; /* creation time */
struct curltime lastused; /* when returned to the connection cache */
--
2.39.2

@ -1,30 +0,0 @@
From 133e25afe4b8961b9c12334ee0bd3374db9a1fd4 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 10 Mar 2023 08:22:51 +0100
Subject: [PATCH] url: fix the SSH connection reuse check
Reported-by: Harry Sintonen
Closes #10735
Upstream-commit: af369db4d3833272b8ed443f7fcc2e757a0872eb
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/url.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/url.c b/lib/url.c
index 0c31486..3b11b7e 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1330,7 +1330,7 @@ ConnectionExists(struct Curl_easy *data,
if(needle->gssapi_delegation != check->gssapi_delegation)
continue;
- if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) {
+ if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
if(!ssh_config_matches(needle, check))
continue;
}
--
2.39.2

@ -1,420 +0,0 @@
From 47f0d37bfc008c088416f3dcca802c9e087d9bf1 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 25 Apr 2023 08:28:01 +0200
Subject: [PATCH] lib: unify the upload/method handling
By making sure we set state.upload based on the set.method value and not
independently as set.upload, we reduce confusion and mixup risks, both
internally and externally.
---
lib/curl_rtmp.c | 4 ++--
lib/file.c | 4 ++--
lib/ftp.c | 8 ++++----
lib/http.c | 4 ++--
lib/imap.c | 6 +++---
lib/rtsp.c | 4 ++--
lib/setopt.c | 6 ++----
lib/smb.c | 6 +++---
lib/smtp.c | 4 ++--
lib/tftp.c | 8 ++++----
lib/transfer.c | 4 ++--
lib/urldata.h | 2 +-
lib/vssh/libssh.c | 6 +++---
lib/vssh/libssh2.c | 6 +++---
lib/vssh/wolfssh.c | 2 +-
15 files changed, 36 insertions(+), 38 deletions(-)
diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c
index 2679a2cdc1afe..406fb42ac0f44 100644
--- a/lib/curl_rtmp.c
+++ b/lib/curl_rtmp.c
@@ -231,7 +231,7 @@ static CURLcode rtmp_connect(struct Curl_easy *data, bool *done)
/* We have to know if it's a write before we send the
* connect request packet
*/
- if(data->set.upload)
+ if(data->state.upload)
r->Link.protocol |= RTMP_FEATURE_WRITE;
/* For plain streams, use the buffer toggle trick to keep data flowing */
@@ -263,7 +263,7 @@ static CURLcode rtmp_do(struct Curl_easy *data, bool *done)
if(!RTMP_ConnectStream(r, 0))
return CURLE_FAILED_INIT;
- if(data->set.upload) {
+ if(data->state.upload) {
Curl_pgrsSetUploadSize(data, data->state.infilesize);
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
}
diff --git a/lib/file.c b/lib/file.c
index 51c5d07ce40ab..c751e8861a99b 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -240,7 +240,7 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
file->freepath = real_path; /* free this when done */
file->fd = fd;
- if(!data->set.upload && (fd == -1)) {
+ if(!data->state.upload && (fd == -1)) {
failf(data, "Couldn't open file %s", data->state.up.path);
file_done(data, CURLE_FILE_COULDNT_READ_FILE, FALSE);
return CURLE_FILE_COULDNT_READ_FILE;
@@ -422,7 +422,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
Curl_pgrsStartNow(data);
- if(data->set.upload)
+ if(data->state.upload)
return file_upload(data);
file = data->req.p.file;
diff --git a/lib/ftp.c b/lib/ftp.c
index f50d7baf622f8..4ff68cc454cbc 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -1381,7 +1381,7 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
data->set.str[STRING_CUSTOMREQUEST]?
data->set.str[STRING_CUSTOMREQUEST]:
(data->state.list_only?"NLST":"LIST"));
- else if(data->set.upload)
+ else if(data->state.upload)
result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
conn->proto.ftpc.file);
else
@@ -3368,7 +3368,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
/* the response code from the transfer showed an error already so no
use checking further */
;
- else if(data->set.upload) {
+ else if(data->state.upload) {
if((-1 != data->state.infilesize) &&
(data->state.infilesize != data->req.writebytecount) &&
!data->set.crlf &&
@@ -3640,7 +3640,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
connected back to us */
}
}
- else if(data->set.upload) {
+ else if(data->state.upload) {
result = ftp_nb_type(data, conn, data->state.prefer_ascii,
FTP_STOR_TYPE);
if(result)
@@ -4217,7 +4217,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
ftpc->file = NULL; /* instead of point to a zero byte,
we make it a NULL pointer */
- if(data->set.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) {
+ if(data->state.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) {
/* We need a file name when uploading. Return error! */
failf(data, "Uploading to a URL without a file name!");
free(rawPath);
diff --git a/lib/http.c b/lib/http.c
index 80e43f6f361e8..bffdd3468536d 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -2112,7 +2112,7 @@ void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
Curl_HttpReq httpreq = data->state.httpreq;
const char *request;
if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
- data->set.upload)
+ data->state.upload)
httpreq = HTTPREQ_PUT;
/* Now set the 'request' pointer to the proper request string */
@@ -2423,7 +2423,7 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
(((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
http->postsize < 0) ||
- ((data->set.upload || httpreq == HTTPREQ_POST) &&
+ ((data->state.upload || httpreq == HTTPREQ_POST) &&
data->state.infilesize == -1))) {
if(conn->bits.authneg)
/* don't enable chunked during auth neg */
diff --git a/lib/imap.c b/lib/imap.c
index c2f675d4b2618..1952e66a1efcd 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -1511,11 +1511,11 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
result = status; /* use the already set error code */
}
else if(!data->set.connect_only && !imap->custom &&
- (imap->uid || imap->mindex || data->set.upload ||
+ (imap->uid || imap->mindex || data->state.upload ||
data->set.mimepost.kind != MIMEKIND_NONE)) {
/* Handle responses after FETCH or APPEND transfer has finished */
- if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
+ if(!data->state.upload && data->set.mimepost.kind == MIMEKIND_NONE)
state(data, IMAP_FETCH_FINAL);
else {
/* End the APPEND command first by sending an empty line */
@@ -1581,7 +1581,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
selected = TRUE;
/* Start the first command in the DO phase */
- if(data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
+ if(data->state.upload || data->set.mimepost.kind != MIMEKIND_NONE)
/* APPEND can be executed directly */
result = imap_perform_append(data);
else if(imap->custom && (selected || !imap->mailbox))
diff --git a/lib/rtsp.c b/lib/rtsp.c
index ea99d720ec4eb..ccd7264b00e74 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -493,7 +493,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
- if(data->set.upload) {
+ if(data->state.upload) {
putsize = data->state.infilesize;
data->state.httpreq = HTTPREQ_PUT;
@@ -512,7 +512,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
result =
Curl_dyn_addf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
- (data->set.upload ? putsize : postsize));
+ (data->state.upload ? putsize : postsize));
if(result)
return result;
}
diff --git a/lib/setopt.c b/lib/setopt.c
index 38f5711e44191..0c3b9634d1192 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -333,8 +333,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* We want to sent data to the remote host. If this is HTTP, that equals
* using the PUT request.
*/
- data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
- if(data->set.upload) {
+ arg = va_arg(param, long);
+ if(arg) {
/* If this is HTTP, PUT is what's needed to "upload" */
data->set.method = HTTPREQ_PUT;
data->set.opt_no_body = FALSE; /* this is implied */
@@ -628,7 +628,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
}
else
data->set.method = HTTPREQ_GET;
- data->set.upload = FALSE;
break;
case CURLOPT_HTTPPOST:
@@ -888,7 +887,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
if(va_arg(param, long)) {
data->set.method = HTTPREQ_GET;
- data->set.upload = FALSE; /* switch off upload */
data->set.opt_no_body = FALSE; /* this is implied */
}
break;
diff --git a/lib/smb.c b/lib/smb.c
index a1e444ee6b97e..d6822213529bc 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -530,7 +530,7 @@ static CURLcode smb_send_open(struct Curl_easy *data)
byte_count = strlen(req->path);
msg.name_length = smb_swap16((unsigned short)byte_count);
msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL);
- if(data->set.upload) {
+ if(data->state.upload) {
msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE);
msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF);
}
@@ -813,7 +813,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
smb_m = (const struct smb_nt_create_response*) msg;
req->fid = smb_swap16(smb_m->fid);
data->req.offset = 0;
- if(data->set.upload) {
+ if(data->state.upload) {
data->req.size = data->state.infilesize;
Curl_pgrsSetUploadSize(data, data->req.size);
next_state = SMB_UPLOAD;
diff --git a/lib/smtp.c b/lib/smtp.c
index 7a030308d4689..c182cace742d7 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -1419,7 +1419,7 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
result = status; /* use the already set error code */
}
else if(!data->set.connect_only && data->set.mail_rcpt &&
- (data->set.upload || data->set.mimepost.kind)) {
+ (data->state.upload || data->set.mimepost.kind)) {
/* Calculate the EOB taking into account any terminating CRLF from the
previous line of the email or the CRLF of the DATA command when there
is "no mail data". RFC-5321, sect. 4.1.1.4.
@@ -1511,7 +1511,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
smtp->eob = 2;
/* Start the first command in the DO phase */
- if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
+ if((data->state.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
/* MAIL transfer */
result = smtp_perform_mail(data);
else
diff --git a/lib/tftp.c b/lib/tftp.c
index 164d3c723c5b9..8ed1b887b4d21 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -370,7 +370,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
/* tsize should be ignored on upload: Who cares about the size of the
remote file? */
- if(!data->set.upload) {
+ if(!data->state.upload) {
if(!tsize) {
failf(data, "invalid tsize -:%s:- value in OACK packet", value);
return CURLE_TFTP_ILLEGAL;
@@ -451,7 +451,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
return result;
}
- if(data->set.upload) {
+ if(data->state.upload) {
/* If we are uploading, send an WRQ */
setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
state->data->req.upload_fromhere =
@@ -486,7 +486,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
if(!data->set.tftp_no_options) {
char buf[64];
/* add tsize option */
- if(data->set.upload && (data->state.infilesize != -1))
+ if(data->state.upload && (data->state.infilesize != -1))
msnprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
data->state.infilesize);
else
@@ -540,7 +540,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
break;
case TFTP_EVENT_OACK:
- if(data->set.upload) {
+ if(data->state.upload) {
result = tftp_connect_for_tx(state, event);
}
else {
diff --git a/lib/transfer.c b/lib/transfer.c
index e9ab8fbf09510..cb69f3365855a 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -1293,6 +1293,7 @@ void Curl_init_CONNECT(struct Curl_easy *data)
{
data->state.fread_func = data->set.fread_func_set;
data->state.in = data->set.in_set;
+ data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
}
/*
@@ -1801,7 +1801,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
data->state.httpreq != HTTPREQ_POST_MIME) ||
!(data->set.keep_post & CURL_REDIR_POST_303))) {
data->state.httpreq = HTTPREQ_GET;
- data->set.upload = false;
infof(data, "Switch to %s\n",
data->set.opt_no_body?"HEAD":"GET");
}
@@ -1770,7 +1770,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
/* if we're talking upload, we can't do the checks below, unless the protocol
is HTTP as when uploading over HTTP we will still get a response */
- if(data->set.upload &&
+ if(data->state.upload &&
!(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)))
return CURLE_OK;
diff --git a/lib/urldata.h b/lib/urldata.h
index cca992a0295aa..a8580bdb66fe8 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1494,6 +1494,7 @@ struct UrlState {
BIT(url_alloc); /* URL string is malloc()'ed */
BIT(referer_alloc); /* referer string is malloc()ed */
BIT(wildcard_resolve); /* Set to true if any resolve change is a wildcard */
+ BIT(upload); /* upload request */
};
/*
@@ -1838,7 +1839,6 @@ struct UserDefined {
BIT(http_auto_referer); /* set "correct" referer when following
location: */
BIT(opt_no_body); /* as set with CURLOPT_NOBODY */
- BIT(upload); /* upload request */
BIT(verbose); /* output verbosity */
BIT(krb); /* Kerberos connection requested */
BIT(reuse_forbid); /* forbidden to be reused, close after use */
diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c
index b31f741ba9492..d60edaa303642 100644
--- a/lib/vssh/libssh.c
+++ b/lib/vssh/libssh.c
@@ -1209,7 +1209,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
case SSH_SFTP_TRANS_INIT:
- if(data->set.upload)
+ if(data->state.upload)
state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(protop->path[strlen(protop->path)-1] == '/')
@@ -1802,7 +1802,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
/* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
ssh_set_blocking(sshc->ssh_session, 1);
- if(data->set.upload) {
+ if(data->state.upload) {
if(data->state.infilesize < 0) {
failf(data, "SCP requires a known file size for upload");
sshc->actualcode = CURLE_UPLOAD_FAILED;
@@ -1907,7 +1907,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
case SSH_SCP_DONE:
- if(data->set.upload)
+ if(data->state.upload)
state(data, SSH_SCP_SEND_EOF);
else
state(data, SSH_SCP_CHANNEL_FREE);
diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c
index f1154dc47a74e..f2e5352d1fd3a 100644
--- a/lib/vssh/libssh2.c
+++ b/lib/vssh/libssh2.c
@@ -2019,7 +2019,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
}
case SSH_SFTP_TRANS_INIT:
- if(data->set.upload)
+ if(data->state.upload)
state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(sshp->path[strlen(sshp->path)-1] == '/')
@@ -2691,7 +2691,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
- if(data->set.upload) {
+ if(data->state.upload) {
if(data->state.infilesize < 0) {
failf(data, "SCP requires a known file size for upload");
sshc->actualcode = CURLE_UPLOAD_FAILED;
@@ -2831,7 +2831,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
break;
case SSH_SCP_DONE:
- if(data->set.upload)
+ if(data->state.upload)
state(data, SSH_SCP_SEND_EOF);
else
state(data, SSH_SCP_CHANNEL_FREE);
diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c
index 17d59ecd23bc8..2ca91b7363b1d 100644
--- a/lib/vssh/wolfssh.c
+++ b/lib/vssh/wolfssh.c
@@ -557,7 +557,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
}
break;
case SSH_SFTP_TRANS_INIT:
- if(data->set.upload)
+ if(data->state.upload)
state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')

@ -1,304 +0,0 @@
From 199f2d440d8659b42670c1b796220792b01a97bf Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 24 Apr 2023 21:07:02 +0200
Subject: [PATCH] hostcheck: fix host name wildcard checking
The leftmost "label" of the host name can now only match against single
'*'. Like the browsers have worked for a long time.
- extended unit test 1397 for this
- move some SOURCE variables from unit/Makefile.am to unit/Makefile.inc
Reported-by: Hiroki Kurosawa
Closes #11018
---
lib/hostcheck.c | 50 +++++++--------
tests/data/test1397 | 10 ++-
tests/unit/Makefile.am | 94 ----------------------------
tests/unit/Makefile.inc | 94 ++++++++++++++++++++++++++++
tests/unit/unit1397.c | 134 ++++++++++++++++++++++++----------------
5 files changed, 202 insertions(+), 180 deletions(-)
diff --git a/lib/hostcheck.c b/lib/hostcheck.c
index e827dc58f378c..d061c6356f97f 100644
--- a/lib/hostcheck.c
+++ b/lib/hostcheck.c
@@ -43,6 +43,17 @@
/* The last #include file should be: */
#include "memdebug.h"
+/* check the two input strings with given length, but do not
+ assume they end in nul-bytes */
+static int pmatch(const char *hostname, size_t hostlen,
+ const char *pattern, size_t patternlen)
+{
+ if(hostlen != patternlen)
+ return CURL_HOST_NOMATCH;
+ return strncasecompare(hostname, pattern, hostlen) ?
+ CURL_HOST_MATCH : CURL_HOST_NOMATCH;
+}
+
/*
* Match a hostname against a wildcard pattern.
* E.g.
@@ -65,26 +76,27 @@
static int hostmatch(char *hostname, char *pattern)
{
- const char *pattern_label_end, *pattern_wildcard, *hostname_label_end;
- int wildcard_enabled;
- size_t prefixlen, suffixlen;
+ size_t hostlen, patternlen;
+ const char *pattern_label_end;
struct in_addr ignored;
#ifdef ENABLE_IPV6
struct sockaddr_in6 si6;
#endif
+ DEBUGASSERT(pattern);
+ DEBUGASSERT(hostname);
+
+ hostlen = strlen(hostname);
+ patternlen = strlen(pattern);
+
/* normalize pattern and hostname by stripping off trailing dots */
- size_t len = strlen(hostname);
- if(hostname[len-1]=='.')
- hostname[len-1] = 0;
- len = strlen(pattern);
- if(pattern[len-1]=='.')
- pattern[len-1] = 0;
-
- pattern_wildcard = strchr(pattern, '*');
- if(pattern_wildcard == NULL)
- return strcasecompare(pattern, hostname) ?
- CURL_HOST_MATCH : CURL_HOST_NOMATCH;
+ if(hostname[hostlen-1]=='.')
+ hostname[hostlen-1] = 0;
+ if(pattern[patternlen-1]=='.')
+ pattern[patternlen-1] = 0;
+
+ if(strncmp(pattern, "*.", 2))
+ return pmatch(hostname, hostlen, pattern, patternlen);
/* detect IP address as hostname and fail the match if so */
if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0)
@@ -96,34 +108,20 @@ static int hostmatch(char *hostname, char *pattern)
/* We require at least 2 dots in pattern to avoid too wide wildcard
match. */
- wildcard_enabled = 1;
pattern_label_end = strchr(pattern, '.');
- if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL ||
- pattern_wildcard > pattern_label_end ||
- strncasecompare(pattern, "xn--", 4)) {
- wildcard_enabled = 0;
+ if(pattern_label_end == NULL ||
+ (strrchr(pattern, '.') == pattern_label_end))
+ return pmatch(pattern, patternlen, hostname, hostlen);
+
+ const char *hostname_label_end = strchr(hostname, '.');
+ if(hostname_label_end != NULL) {
+ size_t skiphost = hostname_label_end - hostname;
+ size_t skiplen = pattern_label_end - pattern;
+ return pmatch(hostname_label_end, hostlen - skiphost,
+ pattern_label_end, patternlen - skiplen);
}
- if(!wildcard_enabled)
- return strcasecompare(pattern, hostname) ?
- CURL_HOST_MATCH : CURL_HOST_NOMATCH;
-
- hostname_label_end = strchr(hostname, '.');
- if(hostname_label_end == NULL ||
- !strcasecompare(pattern_label_end, hostname_label_end))
- return CURL_HOST_NOMATCH;
- /* The wildcard must match at least one character, so the left-most
- label of the hostname is at least as large as the left-most label
- of the pattern. */
- if(hostname_label_end - hostname < pattern_label_end - pattern)
- return CURL_HOST_NOMATCH;
-
- prefixlen = pattern_wildcard - pattern;
- suffixlen = pattern_label_end - (pattern_wildcard + 1);
- return strncasecompare(pattern, hostname, prefixlen) &&
- strncasecompare(pattern_wildcard + 1, hostname_label_end - suffixlen,
- suffixlen) ?
- CURL_HOST_MATCH : CURL_HOST_NOMATCH;
+ return CURL_HOST_NOMATCH;
}
int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
diff --git a/tests/data/test1397 b/tests/data/test1397
index 84f962abebee3..f31b2c2a3f330 100644
--- a/tests/data/test1397
+++ b/tests/data/test1397
@@ -2,8 +2,7 @@
<info>
<keywords>
unittest
-ssl
-wildcard
+Curl_cert_hostcheck
</keywords>
</info>
@@ -15,9 +14,9 @@ none
<features>
unittest
</features>
- <name>
-Check wildcard certificate matching function Curl_cert_hostcheck
- </name>
+<name>
+Curl_cert_hostcheck unit tests
+</name>
</client>
</testcase>
diff --git a/tests/unit/unit1397.c b/tests/unit/unit1397.c
index 2f3d3aa4d09e1..3ae75618d5d10 100644
--- a/tests/unit/unit1397.c
+++ b/tests/unit/unit1397.c
@@ -21,8 +21,6 @@
***************************************************************************/
#include "curlcheck.h"
-#include "hostcheck.h" /* from the lib dir */
-
static CURLcode unit_setup(void)
{
return CURLE_OK;
@@ -30,50 +28,93 @@ static CURLcode unit_setup(void)
static void unit_stop(void)
{
- /* done before shutting down and exiting */
}
-UNITTEST_START
-
/* only these backends define the tested functions */
-#if defined(USE_OPENSSL) || defined(USE_GSKIT)
-
- /* here you start doing things and checking that the results are good */
+#if defined(USE_OPENSSL) || defined(USE_GSKIT) || defined(USE_SCHANNEL)
+#include "hostcheck.h"
+struct testcase {
+ const char *host;
+ const char *pattern;
+ bool match;
+};
-fail_unless(Curl_cert_hostcheck("www.example.com", "www.example.com"),
- "good 1");
-fail_unless(Curl_cert_hostcheck("*.example.com", "www.example.com"),
- "good 2");
-fail_unless(Curl_cert_hostcheck("xxx*.example.com", "xxxwww.example.com"),
- "good 3");
-fail_unless(Curl_cert_hostcheck("f*.example.com", "foo.example.com"),
- "good 4");
-fail_unless(Curl_cert_hostcheck("192.168.0.0", "192.168.0.0"),
- "good 5");
-
-fail_if(Curl_cert_hostcheck("xxx.example.com", "www.example.com"), "bad 1");
-fail_if(Curl_cert_hostcheck("*", "www.example.com"), "bad 2");
-fail_if(Curl_cert_hostcheck("*.*.com", "www.example.com"), "bad 3");
-fail_if(Curl_cert_hostcheck("*.example.com", "baa.foo.example.com"), "bad 4");
-fail_if(Curl_cert_hostcheck("f*.example.com", "baa.example.com"), "bad 5");
-fail_if(Curl_cert_hostcheck("*.com", "example.com"), "bad 6");
-fail_if(Curl_cert_hostcheck("*fail.com", "example.com"), "bad 7");
-fail_if(Curl_cert_hostcheck("*.example.", "www.example."), "bad 8");
-fail_if(Curl_cert_hostcheck("*.example.", "www.example"), "bad 9");
-fail_if(Curl_cert_hostcheck("", "www"), "bad 10");
-fail_if(Curl_cert_hostcheck("*", "www"), "bad 11");
-fail_if(Curl_cert_hostcheck("*.168.0.0", "192.168.0.0"), "bad 12");
-fail_if(Curl_cert_hostcheck("www.example.com", "192.168.0.0"), "bad 13");
-
-#ifdef ENABLE_IPV6
-fail_if(Curl_cert_hostcheck("*::3285:a9ff:fe46:b619",
- "fe80::3285:a9ff:fe46:b619"), "bad 14");
-fail_unless(Curl_cert_hostcheck("fe80::3285:a9ff:fe46:b619",
- "fe80::3285:a9ff:fe46:b619"), "good 6");
-#endif
+static struct testcase tests[] = {
+ {"", "", FALSE},
+ {"a", "", FALSE},
+ {"", "b", FALSE},
+ {"a", "b", FALSE},
+ {"aa", "bb", FALSE},
+ {"\xff", "\xff", TRUE},
+ {"aa.aa.aa", "aa.aa.bb", FALSE},
+ {"aa.aa.aa", "aa.aa.aa", TRUE},
+ {"aa.aa.aa", "*.aa.bb", FALSE},
+ {"aa.aa.aa", "*.aa.aa", TRUE},
+ {"192.168.0.1", "192.168.0.1", TRUE},
+ {"192.168.0.1", "*.168.0.1", FALSE},
+ {"192.168.0.1", "*.0.1", FALSE},
+ {"h.ello", "*.ello", FALSE},
+ {"h.ello.", "*.ello", FALSE},
+ {"h.ello", "*.ello.", FALSE},
+ {"h.e.llo", "*.e.llo", TRUE},
+ {"h.e.llo", " *.e.llo", FALSE},
+ {" h.e.llo", "*.e.llo", TRUE},
+ {"h.e.llo.", "*.e.llo", TRUE},
+ {"*.e.llo.", "*.e.llo", TRUE},
+ {"************.e.llo.", "*.e.llo", TRUE},
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
+ "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
+ "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
+ ".e.llo.", "*.e.llo", TRUE},
+ {"\xfe\xfe.e.llo.", "*.e.llo", TRUE},
+ {"h.e.llo.", "*.e.llo.", TRUE},
+ {"h.e.llo", "*.e.llo.", TRUE},
+ {".h.e.llo", "*.e.llo.", FALSE},
+ {"h.e.llo", "*.*.llo.", FALSE},
+ {"h.e.llo", "h.*.llo", FALSE},
+ {"h.e.llo", "h.e.*", FALSE},
+ {"hello", "*.ello", FALSE},
+ {"hello", "**llo", FALSE},
+ {"bar.foo.example.com", "*.example.com", FALSE},
+ {"foo.example.com", "*.example.com", TRUE},
+ {"baz.example.net", "b*z.example.net", FALSE},
+ {"foobaz.example.net", "*baz.example.net", FALSE},
+ {"xn--l8j.example.local", "x*.example.local", FALSE},
+ {"xn--l8j.example.net", "*.example.net", TRUE},
+ {"xn--l8j.example.net", "*j.example.net", FALSE},
+ {"xn--l8j.example.net", "xn--l8j.example.net", TRUE},
+ {"xn--l8j.example.net", "xn--l8j.*.net", FALSE},
+ {"xl8j.example.net", "*.example.net", TRUE},
+ {"fe80::3285:a9ff:fe46:b619", "*::3285:a9ff:fe46:b619", FALSE},
+ {"fe80::3285:a9ff:fe46:b619", "fe80::3285:a9ff:fe46:b619", TRUE},
+ {NULL, NULL, FALSE}
+};
-#endif
+UNITTEST_START
+{
+ int i;
+ for(i = 0; tests[i].host; i++) {
+ if(tests[i].match != Curl_cert_hostcheck(tests[i].pattern,
+ strlen(tests[i].pattern),
+ tests[i].host,
+ strlen(tests[i].host))) {
+ fprintf(stderr,
+ "HOST: %s\n"
+ "PTRN: %s\n"
+ "did %sMATCH\n",
+ tests[i].host,
+ tests[i].pattern,
+ tests[i].match ? "NOT ": "");
+ unitfail++;
+ }
+ }
+}
+UNITTEST_STOP
+#else
- /* you end the test code like this: */
+UNITTEST_START
UNITTEST_STOP
+#endif

@ -1,169 +0,0 @@
From be17dc9d31e805c03372b690dde67838b3bfc12d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 24 May 2023 16:34:11 +0200
Subject: [PATCH] libssh: when keyboard-interactive auth fails, try password
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The state machine had a mistake in that it would not carry on to that
next step.
This also adds a verbose output what methods that are available from the
server and renames the macros that change to the next auth methods to
try.
Reported-by: 左潇峰
Fixes #11196
Closes #11197
---
lib/vssh/libssh.c | 43 +++++++++++++++++++++++++++----------------
1 file changed, 27 insertions(+), 16 deletions(-)
diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c
index 7ebe61321419f..1cecb649cb623 100644
--- a/lib/vssh/libssh.c
+++ b/lib/vssh/libssh.c
@@ -565,7 +565,7 @@ static int myssh_is_known(struct Curl_easy *data)
break; \
}
-#define MOVE_TO_LAST_AUTH \
+#define MOVE_TO_PASSWD_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
rc = SSH_OK; \
state(data, SSH_AUTH_PASS_INIT); \
@@ -575,25 +575,25 @@ static int myssh_is_known(struct Curl_easy *data)
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \
}
-#define MOVE_TO_TERTIARY_AUTH \
+#define MOVE_TO_KEY_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
rc = SSH_OK; \
state(data, SSH_AUTH_KEY_INIT); \
break; \
} \
else { \
- MOVE_TO_LAST_AUTH; \
+ MOVE_TO_PASSWD_AUTH; \
}
-#define MOVE_TO_SECONDARY_AUTH \
+#define MOVE_TO_GSSAPI_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
rc = SSH_OK; \
state(data, SSH_AUTH_GSSAPI); \
break; \
} \
else { \
- MOVE_TO_TERTIARY_AUTH; \
+ MOVE_TO_KEY_AUTH; \
}
static
int myssh_auth_interactive(struct connectdata *conn)
@@ -740,6 +740,16 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
+ if(sshc->auth_methods)
+ infof(data, "SSH authentication methods available: %s%s%s%s",
+ sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY ?
+ "public key, ": "",
+ sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC ?
+ "GSSAPI, " : "",
+ sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE ?
+ "keyboard-interactive, " : "",
+ sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD ?
+ "password": "");
if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
state(data, SSH_AUTH_PKEY_INIT);
infof(data, "Authentication using SSH public key file\n");
@@ -761,8 +761,8 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
case SSH_AUTH_PKEY_INIT:
if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) {
- MOVE_TO_SECONDARY_AUTH;
+ MOVE_TO_GSSAPI_AUTH;
}
/* Two choices, (1) private key was given on CMD,
* (2) use the "default" keys. */
@@ -776,7 +776,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
if(rc != SSH_OK) {
- MOVE_TO_SECONDARY_AUTH;
+ MOVE_TO_GSSAPI_AUTH;
}
}
@@ -826,7 +836,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
- MOVE_TO_SECONDARY_AUTH;
+ MOVE_TO_GSSAPI_AUTH;
}
break;
case SSH_AUTH_PKEY:
@@ -828,13 +828,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
else {
infof(data, "Failed public key authentication (rc: %d)\n", rc);
- MOVE_TO_SECONDARY_AUTH;
+ MOVE_TO_GSSAPI_AUTH;
}
break;
case SSH_AUTH_GSSAPI:
if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) {
- MOVE_TO_TERTIARY_AUTH;
+ MOVE_TO_KEY_AUTH;
}
rc = ssh_userauth_gssapi(sshc->ssh_session);
@@ -851,7 +851,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
- MOVE_TO_TERTIARY_AUTH;
+ MOVE_TO_KEY_AUTH;
break;
case SSH_AUTH_KEY_INIT:
@@ -859,13 +859,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_AUTH_KEY);
}
else {
- MOVE_TO_LAST_AUTH;
+ MOVE_TO_PASSWD_AUTH;
}
break;
case SSH_AUTH_KEY:
-
- /* Authentication failed. Continue with keyboard-interactive now. */
+ /* keyboard-interactive authentication */
rc = myssh_auth_interactive(conn);
if(rc == SSH_AGAIN) {
break;
@@ -873,13 +873,15 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == SSH_OK) {
sshc->authed = TRUE;
infof(data, "completed keyboard interactive authentication\n");
+ state(data, SSH_AUTH_DONE);
+ }
+ else {
+ MOVE_TO_PASSWD_AUTH;
}
- state(data, SSH_AUTH_DONE);
break;
case SSH_AUTH_PASS_INIT:
if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) {
- /* Host key authentication is intentionally not implemented */
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
}
state(data, SSH_AUTH_PASS);

@ -1,136 +0,0 @@
From 1d66562c67fc0099d0fd882c693e51dd0b10c45c Mon Sep 17 00:00:00 2001
From: Jay Satiro <raysatiro@yahoo.com>
Date: Sat, 30 Sep 2023 03:40:02 -0400
Subject: [PATCH] socks: return error if hostname too long for remote resolve
Prior to this change the state machine attempted to change the remote
resolve to a local resolve if the hostname was longer than 255
characters. Unfortunately that did not work as intended and caused a
security issue.
Name resolvers cannot resolve hostnames longer than 255 characters.
Bug: https://curl.se/docs/CVE-2023-38545.html
---
lib/socks.c | 8 +++---
tests/data/Makefile.inc | 2 +-
tests/data/test728 | 64 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+), 5 deletions(-)
create mode 100644 tests/data/test728
diff --git a/lib/socks.c b/lib/socks.c
index c492d663c..a7b5ab07e 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -531,13 +531,13 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
infof(data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
hostname, remote_port);
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
if(!socks5_resolve_local && hostname_len > 255) {
- infof(data, "SOCKS5: server resolving disabled for hostnames of "
- "length > 255 [actual len=%zu]\n", hostname_len);
- socks5_resolve_local = TRUE;
+ failf(data, "SOCKS5: the destination hostname is too long to be "
+ "resolved remotely by the proxy.");
+ return CURLPX_LONG_HOSTNAME;
}
if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
infof(data,
"warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
@@ -855,7 +855,7 @@ CONNECT_RESOLVE_REMOTE:
if(!socks5_resolve_local) {
socksreq[len++] = 3; /* ATYP: domain name = 3 */
- socksreq[len++] = (char) hostname_len; /* one byte address length */
+ socksreq[len++] = (unsigned char) hostname_len; /* one byte length */
memcpy(&socksreq[len], hostname, hostname_len); /* address w/o NULL */
len += hostname_len;
infof(data, "SOCKS5 connect to %s:%d (remotely resolved)\n",
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 081e344d4..62ee53578 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -99,7 +99,7 @@ test672 test673 test674 test675 test676 test677 test678 test679 test680 \
\
test700 test701 test702 test703 test704 test705 test706 test707 test708 \
test709 test710 test711 test712 test713 test714 test715 test716 test717 \
-test718 \
+test718 test728 \
\
test800 test801 test802 test803 test804 test805 test806 test807 test808 \
test809 test810 test811 test812 test813 test814 test815 test816 test817 \
diff --git a/tests/data/test728 b/tests/data/test728
new file mode 100644
index 000000000..05bcf2883
--- /dev/null
+++ b/tests/data/test728
@@ -0,0 +1,64 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+SOCKS5
+SOCKS5h
+followlocation
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+# The hostname in this redirect is 256 characters and too long (> 255) for
+# SOCKS5 remote resolve. curl must return error CURLE_PROXY in this case.
+<data>
+HTTP/1.1 301 Moved Permanently
+Location: http://AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/
+Content-Length: 0
+Connection: close
+
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+proxy
+</features>
+<server>
+http
+socks5
+</server>
+ <name>
+SOCKS5h with HTTP redirect to hostname too long
+ </name>
+ <command>
+--no-progress-meter --location --proxy socks5h://%HOSTIP:%SOCKSPORT http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+<errorcode>
+97
+</errorcode>
+# the error message is verified because error code CURLE_PROXY (97) may be
+# returned for any number of reasons and we need to make sure it is
+# specifically for the reason below so that we know the check is working.
+<stderr mode="text">
+curl: (97) SOCKS5: the destination hostname is too long to be resolved remotely by the proxy.
+</stderr>
+</verify>
+</testcase>
--
2.42.0

@ -1,123 +0,0 @@
From 61275672b46d9abb3285740467b882e22ed75da8 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 14 Sep 2023 23:28:32 +0200
Subject: [PATCH] cookie: remove unnecessary struct fields
Plus: reduce the hash table size from 256 to 63. It seems unlikely to
make much of a speed difference for most use cases but saves 1.5KB of
data per instance.
Closes #11862
---
lib/cookie.c | 13 +------------
lib/cookie.h | 13 ++++---------
lib/easy.c | 4 +---
3 files changed, 6 insertions(+), 24 deletions(-)
diff --git a/lib/cookie.c b/lib/cookie.c
index 4345a84c6fd9d..e39c89a94a960 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -119,7 +119,6 @@ static void freecookie(struct Cookie *co)
free(co->name);
free(co->value);
free(co->maxage);
- free(co->version);
free(co);
}
@@ -717,11 +716,7 @@ Curl_cookie_add(struct Curl_easy *data,
}
}
else if(strcasecompare("version", name)) {
- strstore(&co->version, whatptr);
- if(!co->version) {
- badcookie = TRUE;
- break;
- }
+ /* just ignore */
}
else if(strcasecompare("max-age", name)) {
/* Defined in RFC2109:
@@ -1159,7 +1154,6 @@ Curl_cookie_add(struct Curl_easy *data,
free(clist->path);
free(clist->spath);
free(clist->expirestr);
- free(clist->version);
free(clist->maxage);
*clist = *co; /* then store all the new data */
@@ -1223,9 +1217,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
c = calloc(1, sizeof(struct CookieInfo));
if(!c)
return NULL; /* failed to get memory */
- c->filename = strdup(file?file:"none"); /* copy the name just in case */
- if(!c->filename)
- goto fail; /* failed to get memory */
}
else {
/* we got an already existing one, use that */
@@ -1378,7 +1369,6 @@ static struct Cookie *dup_cookie(struct Cookie *src)
CLONE(name);
CLONE(value);
CLONE(maxage);
- CLONE(version);
d->expires = src->expires;
d->tailmatch = src->tailmatch;
d->secure = src->secure;
@@ -1595,7 +1585,6 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
{
if(c) {
unsigned int i;
- free(c->filename);
for(i = 0; i < COOKIE_HASH_SIZE; i++)
Curl_cookie_freelist(c->cookies[i]);
free(c); /* free the base struct as well */
diff --git a/lib/cookie.h b/lib/cookie.h
index b3c0063b2cfb2..41e9e7a6914e0 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -36,11 +36,7 @@ struct Cookie {
char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */
-
- /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
- char *version; /* Version = <value> */
char *maxage; /* Max-Age = <value> */
-
bool tailmatch; /* whether we do tail-matching of the domain name */
bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
@@ -56,14 +52,13 @@ struct Cookie {
#define COOKIE_PREFIX__SECURE (1<<0)
#define COOKIE_PREFIX__HOST (1<<1)
-#define COOKIE_HASH_SIZE 256
+#define COOKIE_HASH_SIZE 63
struct CookieInfo {
/* linked list of cookies we know of */
struct Cookie *cookies[COOKIE_HASH_SIZE];
- char *filename; /* file we read from/write to */
- long numcookies; /* number of cookies in the "jar" */
+ int numcookies; /* number of cookies in the "jar" */
bool running; /* state info, for cookie adding information */
bool newsession; /* new session, discard session cookies on load */
int lastct; /* last creation-time used in the jar */
diff --git a/lib/easy.c b/lib/easy.c
index 16bbd35251d40..03195481f9780 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -925,9 +925,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
if(data->cookies) {
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
- outcurl->cookies = Curl_cookie_init(data,
- data->cookies->filename,
- outcurl->cookies,
+ outcurl->cookies = Curl_cookie_init(data, NULL, outcurl->cookies,
data->set.cookiesession);
if(!outcurl->cookies)
goto fail;

@ -1,31 +0,0 @@
From 35eb2614d86316ba9f5a6806ce64f56680fa1e97 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Tue, 5 Sep 2023 17:33:41 +0200
Subject: [PATCH] libssh: cap SFTP packet size sent
Due to libssh limitations
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Closes #11804
---
lib/vssh/libssh.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c
index dea0084575859b..7c6a2e53f338fa 100644
--- a/lib/vssh/libssh.c
+++ b/lib/vssh/libssh.c
@@ -2567,6 +2567,12 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
struct connectdata *conn = data->conn;
(void)sockindex;
+ /* limit the writes to the maximum specified in Section 3 of
+ * https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-02
+ */
+ if(len > 32768)
+ len = 32768;
+
nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
myssh_block2waitfor(conn, FALSE);

@ -1,48 +0,0 @@
From 2b0994c29a721c91c572cff7808c572a24d251eb Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 23 Nov 2023 08:15:47 +0100
Subject: [PATCH] cookie: lowercase the domain names before PSL checks
Reported-by: Harry Sintonen
Closes #12387
---
lib/cookie.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/lib/cookie.c b/lib/cookie.c
index 568cf537ad1b1f..9095cea3e97f22 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -1027,15 +1027,23 @@ Curl_cookie_add(struct Curl_easy *data,
* dereference it.
*/
if(data && (domain && co->domain && !isip(co->domain))) {
- const psl_ctx_t *psl = Curl_psl_use(data);
- int acceptable;
-
- if(psl) {
- acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain);
- Curl_psl_release(data);
+ bool acceptable = FALSE;
+ char lcase[256];
+ char lcookie[256];
+ size_t dlen = strlen(domain);
+ size_t clen = strlen(co->domain);
+ if((dlen < sizeof(lcase)) && (clen < sizeof(lcookie))) {
+ const psl_ctx_t *psl = Curl_psl_use(data);
+ if(psl) {
+ /* the PSL check requires lowercase domain name and pattern */
+ Curl_strntolower(lcase, domain, dlen + 1);
+ Curl_strntolower(lcookie, co->domain, clen + 1);
+ acceptable = psl_is_cookie_domain_acceptable(psl, lcase, lcookie);
+ Curl_psl_release(data);
+ }
+ else
+ acceptable = !bad_domain(domain);
}
- else
- acceptable = !bad_domain(domain);
if(!acceptable) {
infof(data, "cookie '%s' dropped, domain '%s' must not "

@ -1,14 +0,0 @@
diff -up curl-7.76.1/lib/vtls/openssl.c.ignore_unexpected_eof curl-7.76.1/lib/vtls/openssl.c
--- curl-7.76.1/lib/vtls/openssl.c.ignore_unexpected_eof 2024-06-17 07:03:17.428620354 +0200
+++ curl-7.76.1/lib/vtls/openssl.c 2024-06-17 07:03:54.125799894 +0200
@@ -2761,6 +2761,10 @@ static CURLcode ossl_connect_step1(struc
return CURLE_SSL_CONNECT_ERROR;
}
+#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
+ ctx_options |= SSL_OP_IGNORE_UNEXPECTED_EOF;
+#endif
+
SSL_CTX_set_options(backend->ctx, ctx_options);
#ifdef HAS_NPN

@ -1,80 +0,0 @@
From deca8039991886a559b67bcd6701db800a5cf764 Mon Sep 17 00:00:00 2001
From: Stefan Eissing <stefan@eissing.org>
Date: Wed, 6 Mar 2024 09:36:08 +0100
Subject: [PATCH] http2: push headers better cleanup
- provide common cleanup method for push headers
Closes #13054
---
lib/http2.c | 34 +++++++++++++++-------------------
1 file changed, 15 insertions(+), 19 deletions(-)
diff --git a/lib/http2.c b/lib/http2.c
index c63ecd38371ab4..96868728a53a1f 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -271,6 +271,15 @@ static CURLcode http2_data_setup(struct Curl_cfilter *cf,
return bitmap;
}
+static void free_push_headers(struct HTTP *http)
+{
+ size_t i;
+ for(i = 0; i<http->push_headers_used; i++)
+ free(http->push_headers[i]);
+ Curl_safefree(http->push_headers);
+ http->push_headers_used = 0;
+}
+
/*
* http2_stream_free() free HTTP2 stream related data
*/
@@ -306,11 +315,7 @@ static void http2_data_done(struct Curl_cfilter *cf,
{
if(http) {
Curl_dyn_free(&http->header_recvbuf);
- for(; http->push_headers_used > 0; --http->push_headers_used) {
- free(http->push_headers[http->push_headers_used - 1]);
- }
- free(http->push_headers);
- http->push_headers = NULL;
+ free_push_headers(http);
}
}
@@ -860,7 +861,6 @@ static int push_promise(struct Curl_cfilter *cf,
struct curl_pushheaders heads;
CURLMcode rc;
struct http_conn *httpc;
- size_t i;
/* clone the parent */
struct Curl_easy *newhandle = duphandle(data);
if(!newhandle) {
@@ -905,11 +905,7 @@ static int push_promise(struct Curl_cfilter *cf,
Curl_set_in_callback(data, false);
/* free the headers again */
- for(i = 0; i<stream->push_headers_used; i++)
- free(stream->push_headers[i]);
- free(stream->push_headers);
- stream->push_headers = NULL;
- stream->push_headers_used = 0;
+ free_push_headers(stream);
if(rv) {
DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
@@ -1426,10 +1422,10 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
stream->push_headers_alloc) {
char **headp;
stream->push_headers_alloc *= 2;
- headp = Curl_saferealloc(stream->push_headers,
- stream->push_headers_alloc * sizeof(char *));
+ headp = realloc(stream->push_headers,
+ stream->push_headers_alloc * sizeof(char *));
if(!headp) {
- stream->push_headers = NULL;
+ free_push_headers(stream);
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
stream->push_headers = headp;

@ -1,7 +1,7 @@
From 2a4754a3a7cf60ecc36d83cbe50b8c337cb87632 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Fri, 12 Apr 2013 12:04:05 +0200
Subject: [PATCH] prevent multilib conflicts on the curl-config script
From 84b7e1cf486761e99361f5dcf5879cd7baf51b58 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Thu, 1 Feb 2024 13:01:23 +0100
Subject: [PATCH 2/2] prevent multilib conflicts on the curl-config script
---
curl-config.in | 23 +++++------------------
@ -10,75 +10,76 @@ Subject: [PATCH] prevent multilib conflicts on the curl-config script
3 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/curl-config.in b/curl-config.in
index 150004d..95d0759 100644
index 54f92d9..15a60da 100644
--- a/curl-config.in
+++ b/curl-config.in
@@ -76,7 +76,7 @@ while test $# -gt 0; do
;;
@@ -78,7 +78,7 @@ while test $# -gt 0; do
;;
--cc)
- echo "@CC@"
+ echo "gcc"
;;
--cc)
- echo '@CC@'
+ echo "gcc"
;;
--prefix)
@@ -155,32 +155,19 @@ while test $# -gt 0; do
;;
--prefix)
@@ -157,33 +157,20 @@ while test $# -gt 0; do
;;
--libs)
- if test "X@libdir@" != "X/usr/lib" -a "X@libdir@" != "X/usr/lib64"; then
- CURLLIBDIR="-L@libdir@ "
- else
- CURLLIBDIR=""
- fi
- if test "X@ENABLE_SHARED@" = "Xno"; then
- echo ${CURLLIBDIR}-lcurl @LIBCURL_LIBS@
- else
- echo ${CURLLIBDIR}-lcurl
- fi
+ echo -lcurl
;;
--ssl-backends)
echo "@SSL_BACKENDS@"
;;
--libs)
- if test "X@libdir@" != "X/usr/lib" -a "X@libdir@" != "X/usr/lib64"; then
- CURLLIBDIR="-L@libdir@ "
- else
- CURLLIBDIR=""
- fi
- if test "X@ENABLE_SHARED@" = "Xno"; then
- echo "${CURLLIBDIR}-lcurl @LIBCURL_LIBS@"
- else
- echo "${CURLLIBDIR}-lcurl"
- fi
+ echo -lcurl
;;
--static-libs)
- if test "X@ENABLE_STATIC@" != "Xno" ; then
- echo @libdir@/libcurl.@libext@ @LDFLAGS@ @LIBCURL_LIBS@
- else
- echo "curl was built with static libraries disabled" >&2
- exit 1
- fi
+ echo "curl was built with static libraries disabled" >&2
+ exit 1
;;
--ssl-backends)
echo '@SSL_BACKENDS@'
;;
--configure)
- echo @CONFIGURE_OPTIONS@
+ pkg-config libcurl --variable=configure_options | sed 's/^"//;s/"$//'
;;
--static-libs)
- if test "X@ENABLE_STATIC@" != "Xno" ; then
- echo "@libdir@/libcurl.@libext@" @LDFLAGS@ @LIBCURL_LIBS@
- else
- echo 'curl was built with static libraries disabled' >&2
- exit 1
- fi
+ echo "curl was built with static libraries disabled" >&2
+ exit 1
;;
*)
--configure)
- echo @CONFIGURE_OPTIONS@
+ pkg-config libcurl --variable=configure_options | sed 's/^"//;s/"$//'
;;
*)
diff --git a/docs/curl-config.1 b/docs/curl-config.1
index 14a9d2b..ffcc004 100644
--- a/docs/curl-config.1
+++ b/docs/curl-config.1
@@ -70,7 +70,9 @@ no, one or several names. If more than one name, they will appear
comma-separated. (Added in 7.58.0)
.IP "--static-libs"
Shows the complete set of libs and other linker options you will need in order
-to link your application with libcurl statically. (Added in 7.17.1)
+to link your application with libcurl statically. Note that Fedora/RHEL libcurl
index c142cb9..0e189b4 100644
--- a/docs/curl-config.md
+++ b/docs/curl-config.md
@@ -48,7 +48,9 @@ no, one or several names. If more than one name, they will appear
## --static-libs
Shows the complete set of libs and other linker options you need in order to
-link your application with libcurl statically. (Added in 7.17.1)
+link your application with libcurl statically. Note that Fedora/RHEL libcurl
+packages do not provide any static libraries, thus cannot be linked statically.
+(Added in 7.17.1)
.IP "--version"
Outputs version information about the installed libcurl.
.IP "--vernum"
## --version
diff --git a/libcurl.pc.in b/libcurl.pc.in
index 2ba9c39..f8f8b00 100644
index 9db6b0f..dcac692 100644
--- a/libcurl.pc.in
+++ b/libcurl.pc.in
@@ -29,6 +29,7 @@ libdir=@libdir@
@@ -31,6 +31,7 @@ libdir=@libdir@
includedir=@includedir@
supported_protocols="@SUPPORT_PROTOCOLS@"
supported_features="@SUPPORT_FEATURES@"
@ -87,5 +88,5 @@ index 2ba9c39..f8f8b00 100644
Name: libcurl
URL: https://curl.se/
--
2.26.2
2.43.0

@ -1,61 +0,0 @@
From 3602ee9dcc74683f91fe4f9ca228aa17a6474403 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Wed, 31 Oct 2012 11:38:30 +0100
Subject: [PATCH] prevent configure script from discarding -g in CFLAGS
(#496778)
---
m4/curl-compilers.m4 | 26 ++++++--------------------
1 file changed, 6 insertions(+), 20 deletions(-)
diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4
index c64db4bc6..d115a4aed 100644
--- a/m4/curl-compilers.m4
+++ b/m4/curl-compilers.m4
@@ -106,18 +106,11 @@ AC_DEFUN([CURL_CHECK_COMPILER_CLANG], [
clangvhi=`echo $clangver | cut -d . -f1`
clangvlo=`echo $clangver | cut -d . -f2`
compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null`
- flags_dbg_all="-g -g0 -g1 -g2 -g3"
- flags_dbg_all="$flags_dbg_all -ggdb"
- flags_dbg_all="$flags_dbg_all -gstabs"
- flags_dbg_all="$flags_dbg_all -gstabs+"
- flags_dbg_all="$flags_dbg_all -gcoff"
- flags_dbg_all="$flags_dbg_all -gxcoff"
- flags_dbg_all="$flags_dbg_all -gdwarf-2"
- flags_dbg_all="$flags_dbg_all -gvms"
+ flags_dbg_all=""
flags_dbg_yes="-g"
flags_dbg_off=""
- flags_opt_all="-O -O0 -O1 -O2 -Os -O3 -O4"
- flags_opt_yes="-Os"
+ flags_opt_all=""
+ flags_opt_yes=""
flags_opt_off="-O0"
else
AC_MSG_RESULT([no])
@@ -175,18 +168,11 @@ AC_DEFUN([CURL_CHECK_COMPILER_GNU_C], [
gccvhi=`echo $gccver | cut -d . -f1`
gccvlo=`echo $gccver | cut -d . -f2`
compiler_num=`(expr $gccvhi "*" 100 + $gccvlo) 2>/dev/null`
- flags_dbg_all="-g -g0 -g1 -g2 -g3"
- flags_dbg_all="$flags_dbg_all -ggdb"
- flags_dbg_all="$flags_dbg_all -gstabs"
- flags_dbg_all="$flags_dbg_all -gstabs+"
- flags_dbg_all="$flags_dbg_all -gcoff"
- flags_dbg_all="$flags_dbg_all -gxcoff"
- flags_dbg_all="$flags_dbg_all -gdwarf-2"
- flags_dbg_all="$flags_dbg_all -gvms"
+ flags_dbg_all=""
flags_dbg_yes="-g"
flags_dbg_off=""
- flags_opt_all="-O -O0 -O1 -O2 -O3 -Os -Og -Ofast"
- flags_opt_yes="-O2"
+ flags_opt_all=""
+ flags_opt_yes=""
flags_opt_off="-O0"
CURL_CHECK_DEF([_WIN32], [], [silent])
else
--
1.7.1

@ -0,0 +1,30 @@
From d506d885aa16b4a87acbac082eea41dccdc7b69f Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Wed, 15 Feb 2023 10:42:38 +0100
Subject: [PATCH] Revert "runtests: consider warnings fatal and error on them"
While it might be useful for upstream developers, it is not so useful
for downstream consumers.
This reverts upstream commit 22f795c834cfdbacbb1b55426028a581e3cf67a8.
---
tests/runtests.pl | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tests/runtests.pl b/tests/runtests.pl
index 71644ad18..0cf85c3fe 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -55,8 +55,7 @@
# given, this won't be a problem.
use strict;
-# Promote all warnings to fatal
-use warnings FATAL => 'all';
+use warnings;
use 5.006;
use POSIX qw(strftime);
--
2.39.1

@ -1,39 +0,0 @@
From f55cca0e86f59ec11ffafd5c0503c39ca3723e2e Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Mon, 4 Feb 2019 17:32:56 +0100
Subject: [PATCH] libtest: compile lib1560.c with -fno-builtin-strcmp
... to prevent valgrind from reporting false positives on x86_64:
Conditional jump or move depends on uninitialised value(s)
at 0x10BCAA: part2id (lib1560.c:489)
by 0x10BCAA: updateurl (lib1560.c:521)
by 0x10BCAA: set_parts (lib1560.c:630)
by 0x10BCAA: test (lib1560.c:802)
by 0x4923412: (below main) (in /usr/lib64/libc-2.28.9000.so)
Conditional jump or move depends on uninitialised value(s)
at 0x10BCC3: part2id (lib1560.c:491)
by 0x10BCC3: updateurl (lib1560.c:521)
by 0x10BCC3: set_parts (lib1560.c:630)
by 0x10BCC3: test (lib1560.c:802)
by 0x4923412: (below main) (in /usr/lib64/libc-2.28.9000.so)
---
tests/libtest/Makefile.inc | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index 080421b..ea3b806 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -593,6 +593,7 @@ lib1559_SOURCES = lib1559.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1559_LDADD = $(TESTUTIL_LIBS)
lib1560_SOURCES = lib1560.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1560_CFLAGS = $(AM_CFLAGS) -fno-builtin-strcmp
lib1560_LDADD = $(TESTUTIL_LIBS)
lib1564_SOURCES = lib1564.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
--
2.17.2

@ -0,0 +1,11 @@
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEJ+3q8i86vOtQ25oSXMkI/bceEsIFAmap30kACgkQXMkI/bce
EsKX+wf/brccw5rGTAbmjj7WGBfbAmwrSsDexTXRiEBXT/+qhkWIplN6wdtsZ86I
tUraaapoyvRKLa3Wxlv9fSF/xXji+5lhO/W9pfWxwZNeSZFiOgKcK/Li4Fx0c7t4
WpxkAbRvbJreA40BR32qSgnNNjKU5QX/ivf67B1EFL71kgsCW/QczB6mcuxszlkN
ro39Jb8hDtnAD3hHXrTEaW3lOEgf/Jo/a1Zii3+W3OkW+uZHwzUoqe+HLGHYM2vW
Q3hBVQaEWmNIwArA73s/kOiFATLthUTvSJO56ebLQJFHJf61cwqSsg2o07i5SqEc
QlKzV/h7ydbBWdHiSTpCMxue7tLUZw==
=EiUG
-----END PGP SIGNATURE-----

@ -0,0 +1,77 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2
mQGiBD6tnnoRBACRPnFBVoapBrTpPrCNZ2rq3DcmW6n/soQJW47+zP+vcrcxQ1WJ
QiWSzLGO+QOIUZSYfnliR22r8HkFX9EUSW3IAcRMJMsaO3wMJ0a+78a9QqWLp6RV
0arcQkuuCvG79h+yJ6NnoAXe1geRt8vNGsaWtsS91CtYlTSs6JVtaRLnYwCg/Ly1
EFgvNZ6SJRc/8I5rRv0lrz8D/0goih2kZ5z4SI+r2hgABNcN7g565YwGKaQDbIch
soh3OBzgETWc3wuAZqmCzQXPXMpMx+ziqX6XDzDKNiGL1CdrBJQd0II8UutWVDje
f9UxLfo02YQ8diGYeq0u9k1RezC13w4TVUmQfg0Uqn4xM6DNzO1O6yCK8rlNwsvL
gHNJA/9m1pfzjpvdxtmJNKRU3C4cRCjXhxNdM7laSEj0/wOGaR2QWWEge51orWwo
SLQUIe4BDPvtRStQHC+tI7qr7d12rMMEBXviJC5EkGBOzlgWr9virjM/u/pkGMc2
m5r3pVuWH/JSsHsV952y2kWP64uP4zdLXOpVzX/xs0sYJ9nOPLQnRGFuaWVsIFN0
ZW5iZXJnIChIYXh4KSA8ZGFuaWVsQGhheHguc2U+iF4EExECAB4CHgECF4AFAlQU
ki4FCwkIBwMFFQoJCAsFFgIDAQAACgkQeOEcayedXJEOOwCggCsNHdAQPAlPte3w
i2IZEekkM0YAoOXXPFAWjUwIHjZY41l7WgzACbANiFkEExECABkFAj6tnnoECwcD
AgMVAgMDFgIBAh4BAheAAAoJEHjhHGsnnVyRjngAoO1y3LoSOEgD8vR062cdYDmv
jLvVAJ0dmp1UiuQp+oMyq2VbWyw8LXN1XLkBDQQ+rZ59EAQAmYsA8gPjJ75gOIPb
XNg9Z31QzIz65qS9XdNsFNAdKxnY4b72nhc0oaS9/7Dcdf2Q+1mDa2p72DWk+9iz
7knmBL++csBP2z9eMe5h8oV53prqNOHDHyL3WLOa25ga9381gZnzWoQME74iSBBM
wDw8vbLEgIZ34JaQ7Oe+9N3+6n8AAwcD/Av+Ms+3gCc5pLp4nx36qqi36fodaG9+
dwIcMbr9bivEtjmDHeuPsD6X1J9+Y/ikUBIDpMPv33lJxLoubOtpLhEuN2XN/ojT
rueVPDKA1f+GyfHnyfpf/78IgX1hGVqu/3RBWKPpXFwSZA4q8vFR+FaPC5WbU68t
FLJpYuC9ZO/LiEYEGBECAAYFAj6tnn0ACgkQeOEcayedXJGtPQCgxrbd59afemZ9
OIadZD8kUGC29dUAoJ94aGUkWCwoEiPyEZRGXv9XRlfxmQENBFcGhyIBCAC79AIx
5hHixKmNtqbryuZTDwlt9XXkEn/QSrQD3pzgbsbBiWyqOV4hfscvtmoqA7koOw4h
zZ/b8pJPA36eNzqMFIbkWpIit/BwA5bTKRkKXeD2kBFkjIN+iDuXawwhv7eNKH9O
poAUe0K/esK/kvbMO721q24IgkOjB1Vtr/Y4Xkg7+VWVP0LFh7C/2Nwq6n2bktsA
Ey9uCDD1hl8BdckN/XxpuUqSfxbF85GvYzzON67zOxxo6jqRXXcJ2PdPq0o9Ak0d
6Fe7g9ZxOAeuYEbFTCZHBBccx84K0Bhn5tpqoq8Mq3f3mZfGBoe4J6wr17cxEDC8
tTHUpDqk0CoLERUxABEBAAG0IERhbmllbCBTdGVuYmVyZyA8ZGFuaWVsQGhheHgu
c2U+iQE3BBMBCgAhBQJXBociAhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJ
EPn+r/nTShvbHoAIAJDwb7dcAX4VGPa2oSuQqVnHsjDE7g8ATmcZq2IAzAG6bZg1
svuhNyPQnL7kNrsz6Ew+yE4vH8mOjDUbc3feY4MzmtEMaB6VS0Xlna6cdtWkv4Y+
Us4TuYSdftPZuZgI3nN/sXLlxWJCZgCPJJaGM6dXgyTFatk2P1LE98Qif7+ZMqfv
+BA5L6cy2cAwJ5qbvLtuT25rTxooN54JETfwdhUD1NEIqTQxeC4E5lFvwedjAjLh
Gswau8WMCdM/HzGbuQ9Gp3/RafYoAvMV6r6sskvUrWubCHj0u+uNgOpUHvlrwcFg
rBirzQdElumCWqbJVCH0V5NcP/zSz1U1W8wSRqS5AQ0EVwaHIgEIALyCqpnax0cL
y7EK3UiU2Kkryb7LPsZkia9hTcIZjNg0B8XAdqDYpHiquYtX0cz5I1sSZMBJ/xJP
BF2ce/bmOTJtyW3GaF9a+M2zboZSzx9nlv9xx0o3bXBrBlL2vaG2TW+x2G53GA0/
0chbj35PR+fvJx8ob/fHwCkfzGb1qCzwovhwGVUNHqI5bxK/xVwXfiycbllE3Hmf
09BGeXKR7gQtaal8byKKlqCtayteEaPNQt6czYxZkVAOvY4ZDQKSZJUNwGFog3bG
6rHr1J/0un6nAvX+wMuvRkUDiQxZZCel7e0Qcg3gPrYh+adlr0Tn7wyCP7/BULz8
67fQfzc2ENkAEQEAAYkBHwQYAQoACQUCVwaHIgIbDAAKCRD5/q/500ob27KaB/9H
a+iDip6mxFdoqy7TAefBy7KgbMQxxT926IcFqf70aJDzeVQI3lGCqN9GW03d+wPr
LoyeQBQKNxxfQ9fEOvp1AXGWFIYYtEZIvQBpIqaSaA7W5IzqfDuO9xG89DNn8zKK
nh/mbYJov/fywhBU6JH7bqdFSHbqoG9TY64s0BkV6shIVOubXLSG5G7LxXhw+xrb
0zl4ie2wCeCBOLdbGHc+o2sKo1rBEz6UBK2DesPfkzxBO7lfa9HTcN03UJPHXmzb
2mCbeFV8yPsTAoaGv4qZH1+FX+9Lv374xTSXa4CjQzSxd0dkZGG+YQjocoPftgsC
OVsiqW0WhRVIEJ+hBAMUmQENBFcGiPEBCAC7sCnaZqWxfXNgBC7P28BSDUs9w4y/
PEFsOv9bpgbgZagX1FnhG0eV71nm0p8v9T8Bft1eXaBd977Dq9pgk5qKO0xZo8fC
8prFqB5db7fMUvPZCuJTTb6lGMz4OdfT6aHqUvJ+LFF1mKn8Eqt1Q4snHGSL1PI3
/+435qDRQsU15GdYrj1waNJKk79aes9oguaI2/OTQqzIcOFK5tJjlSOD1ryOIH1e
8vD+5MMpGvsRxv3sQHeTZkfZbkzSLFg/LKpoiQkyql1+BLNhBYq8oaE/jlvQrTEk
bAyKpMScdyHwmkWWKjyZtXTrAtlComnki4yC2lAV9MXINHHvNJBcIXvVABEBAAG0
IERhbmllbCBTdGVuYmVyZyA8ZGFuaWVsQGhheHguc2U+iQE3BBMBCgAhBQJXBojx
AhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEFzJCP23HhLCOKkH/1CyoKiN
2PCgTlWoYQspv/AAmsj+cFwZobI167KowA+o3zxQqxg0MV3ds8G+iig9OIuYurlQ
L5Jr3CbDltaiXdWtVteRh/VKp61EwyXq77vjJbx81hvOuaXWWLSlU0KB3w7Hj6aD
/mt16DpOcY9Aw90mKyvafRTqMF7TcT7J5HeGn2NL45dPkAhiMDEgEnw9yBTxK/x6
UoQGPgiOWxSSN7Foj3mhUOflp8W0rnkLbJ4icpym6WuLKRMKAefDvk8GVlAWuXAb
9gloL1P6u3uNHllq/IODR2bZUBI0QNKhvt0iSj7WKsc/kaqscl+AE9jd/6kXd6vh
TNFWdzeco/2mGlaIRgQQEQoABgUCVwaJ/AAKCRB44RxrJ51ckWcaAKCJ6+arS/3k
IMcO14Jz8dVf2BH3OACgwTenVSsK66qi+VfGCoALpzpiLDO5AQ0EVwaI8QEIAOxQ
AEvF3idxcn80tbUhJg1J98fAS7Hx3WhlFG74uAikZQl1KZrprBu70RWTb7Nm1tvZ
eXW65IlY7kk42bhfYDs1JrIPWOWKvVwKWDxoEbYgW/yvy1TOuXH276zbxLl5OEE8
sQuOfXZsFSX2IPF9hsgNGaNzor8Ke7Y5BuCQLcGZWW5dLFbbKRKjXG8CaWmsJVoI
c2nyXCAss2q9oCJ13X/5z+Ei392rwi1d3NxAYkSiDQan+fkWkCvZH+dHmFjQ1AND
KielxcW1VfilK1hu9ziBBDf8TCEud/q0woIAH7rvIft4i3CqjymonByE4/OjfH8j
4EteQ8qoknMCjjwNVqkAEQEAAYkBHwQYAQoACQUCVwaI8QIbDAAKCRBcyQj9tx4S
wupjB/9TV4anbZK58bN7QJ5qGnU3GNjlvWFZXMw1u1xVc7abDJyqmFeJcJ4qLUkv
BA0OsvlVnMWmeCmzsXhlQVM4Bv6IWyr7JBWgkK5q2CWVB59V7v7znf5kWnMGFhDF
PlLsGbxDWLMoZGH+Iy84whMJFgferwCJy1dND/bHXPztfhvFXi8NNlJUFJa8Xtmu
gm78C+nwNHcFpVC70HPr3oa8U1ODXMp7L8W/dL3eLYXmRCNd0urHgYrzDt6V/zf5
ymvPk5w4HBocn2oRCJj/FXKhFAUptmpTE3g1yvYULmuFcNGAnPAExmAmd6NqsCmb
j/qx4ytjt5uxt6Jm6IXV9cry8i6x
=Phs/
-----END PGP PUBLIC KEY BLOCK-----

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save