1
0
forked from rpms/curl

Compare commits

..

No commits in common. "c8-beta" and "c8" have entirely different histories.
c8-beta ... c8

12 changed files with 2368 additions and 68 deletions

View File

@ -41,7 +41,7 @@ index e827dc58f378c..d061c6356f97f 100644
/*
* Match a hostname against a wildcard pattern.
* E.g.
@@ -65,26 +76,27 @@
@@ -65,26 +76,31 @@
static int hostmatch(char *hostname, char *pattern)
{
@ -73,10 +73,14 @@ index e827dc58f378c..d061c6356f97f 100644
- if(pattern_wildcard == NULL)
- return strcasecompare(pattern, hostname) ?
- CURL_HOST_MATCH : CURL_HOST_NOMATCH;
+ if(hostname[hostlen-1]=='.')
+ if(hostname[hostlen-1]=='.') {
+ hostname[hostlen-1] = 0;
+ if(pattern[patternlen-1]=='.')
+ hostlen--;
+ }
+ if(pattern[patternlen-1]=='.') {
+ pattern[patternlen-1] = 0;
+ patternlen--;
+ }
+
+ if(strncmp(pattern, "*.", 2))
+ return pmatch(hostname, hostlen, pattern, patternlen);
@ -170,7 +174,7 @@ index 2f3d3aa4d09e1..3ae75618d5d10 100644
static CURLcode unit_setup(void)
{
return CURLE_OK;
@@ -30,50 +28,93 @@ static CURLcode unit_setup(void)
@@ -30,50 +28,91 @@ static CURLcode unit_setup(void)
static void unit_stop(void)
{
@ -281,9 +285,7 @@ index 2f3d3aa4d09e1..3ae75618d5d10 100644
+ 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))) {
+ tests[i].host)) {
+ fprintf(stderr,
+ "HOST: %s\n"
+ "PTRN: %s\n"

View File

@ -153,7 +153,7 @@ index 7ebe61321419f..1cecb649cb623 100644
if(rc == SSH_OK) {
sshc->authed = TRUE;
infof(data, "completed keyboard interactive authentication\n");
+ state(data, SSH_AUTH_DONE);
+ state(conn, SSH_AUTH_DONE);
+ }
+ else {
+ MOVE_TO_PASSWD_AUTH;

View File

@ -0,0 +1,80 @@
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 http2_perform_getsock(conn, sock, numsocks);
}
+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,
http->header_recvbuf = NULL; /* clear the pointer */
Curl_add_buffer_free(http->trailer_recvbuf);
http->trailer_recvbuf = NULL; /* clear the pointer */
- 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) {
@@ -904,11 +904,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) {
/* denied, kill off the new handle again */
@@ -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;

View File

@ -0,0 +1,146 @@
From eb9a604f8d7db859555adc0ddacdabd1ed986106 Mon Sep 17 00:00:00 2001
From: amkatyal <amkatyal@cisco.com>
Date: Fri, 26 Jul 2019 21:28:41 +0530
Subject: [PATCH] asyn-thread: create a socketpair to wait on
Closes #4157
---
lib/asyn-thread.c | 76 ++++++++++++++++++++++++++++++++++++++++-------
lib/multi.c | 0
2 files changed, 65 insertions(+), 11 deletions(-)
mode change 100644 => 100755 lib/asyn-thread.c
mode change 100644 => 100755 lib/multi.c
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
old mode 100644
new mode 100755
index 5f33c9affd0f27..f17638e44e6b18
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -163,6 +163,9 @@ struct thread_sync_data {
char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
int port;
+#ifdef HAVE_SOCKETPAIR
+ curl_socket_t sock_pair[2]; /* socket pair */
+#endif
int sock_error;
Curl_addrinfo *res;
#ifdef HAVE_GETADDRINFO
@@ -197,6 +200,16 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
if(tsd->res)
Curl_freeaddrinfo(tsd->res);
+#ifdef HAVE_SOCKETPAIR
+ /* close socket pair */
+ if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
+ sclose(tsd->sock_pair[0]);
+ }
+
+ if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
+ sclose(tsd->sock_pair[1]);
+ }
+#endif
memset(tsd, 0, sizeof(*tsd));
}
@@ -230,6 +243,14 @@ int init_thread_sync_data(struct thread_data * td,
Curl_mutex_init(tsd->mtx);
+#ifdef HAVE_SOCKETPAIR
+ /* create socket pair */
+ if(socketpair(AF_LOCAL, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
+ tsd->sock_pair[0] = CURL_SOCKET_BAD;
+ tsd->sock_pair[1] = CURL_SOCKET_BAD;
+ goto err_exit;
+ }
+#endif
tsd->sock_error = CURL_ASYNC_SUCCESS;
/* Copying hostname string because original can be destroyed by parent
@@ -297,6 +318,9 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
struct thread_data *td = tsd->td;
char service[12];
int rc;
+#ifdef HAVE_SOCKETPAIR
+ char buf[1];
+#endif
snprintf(service, sizeof(service), "%d", tsd->port);
@@ -298,6 +322,16 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
free(td);
}
else {
+#ifdef HAVE_SOCKETPAIR
+ if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
+ /* DNS has been resolved, signal client task */
+ buf[0] = 1;
+ if(write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
+ /* update sock_erro to errno */
+ tsd->sock_error = SOCKERRNO;
+ }
+ }
+#endif
tsd->done = 1;
Curl_mutex_release(tsd->mtx);
}
@@ -595,23 +629,43 @@ int Curl_resolver_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
+ int ret_val = 0;
time_t milli;
timediff_t ms;
struct Curl_easy *data = conn->data;
struct resdata *reslv = (struct resdata *)data->state.resolver;
+#ifdef HAVE_SOCKETPAIR
+ struct thread_data *td = (struct thread_data*)conn->async.os_specific;
+ int loop_idx;
+#else
(void)socks;
(void)numsocks;
- ms = Curl_timediff(Curl_now(), reslv->start);
- if(ms < 3)
- milli = 0;
- else if(ms <= 50)
- milli = ms/3;
- else if(ms <= 250)
- milli = 50;
- else
- milli = 200;
- Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
- return 0;
+#endif
+
+#ifdef HAVE_SOCKETPAIR
+ if(td) {
+ /* return read fd to client for polling the DNS resolution status */
+ socks[0] = td->tsd.sock_pair[0];
+ ret_val = GETSOCK_READSOCK(0);
+ }
+ else {
+#endif
+ ms = Curl_timediff(Curl_now(), reslv->start);
+ if(ms < 3)
+ milli = 0;
+ else if(ms <= 50)
+ milli = ms/3;
+ else if(ms <= 250)
+ milli = 50;
+ else
+ milli = 200;
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
+#ifdef HAVE_SOCKETPAIR
+ }
+#endif
+
+
+ return ret_val;
}
#ifndef HAVE_GETADDRINFO
diff --git a/lib/multi.c b/lib/multi.c
old mode 100644
new mode 100755

View File

@ -0,0 +1,279 @@
diff -up curl-7.61.1/lib/curl_md5.h.RHEL-32335 curl-7.61.1/lib/curl_md5.h
--- curl-7.61.1/lib/curl_md5.h.RHEL-32335 2024-04-10 10:09:36.758098940 +0200
+++ curl-7.61.1/lib/curl_md5.h 2024-04-10 10:10:22.426370509 +0200
@@ -49,8 +49,8 @@ typedef struct {
extern const MD5_params Curl_DIGEST_MD5[1];
extern const HMAC_params Curl_HMAC_MD5[1];
-void Curl_md5it(unsigned char *output,
- const unsigned char *input);
+void Curl_md5it(unsigned char *output, const unsigned char *input,
+ const size_t len);
MD5_context * Curl_MD5_init(const MD5_params *md5params);
int Curl_MD5_update(MD5_context *context,
diff -up curl-7.61.1/lib/curl_ntlm_core.h.RHEL-32335 curl-7.61.1/lib/curl_ntlm_core.h
--- curl-7.61.1/lib/curl_ntlm_core.h.RHEL-32335 2024-04-10 09:52:39.872042425 +0200
+++ curl-7.61.1/lib/curl_ntlm_core.h 2024-04-10 09:54:46.230795176 +0200
@@ -48,9 +48,9 @@
#endif
/* Define USE_NTLM2SESSION in order to make the type-3 message include the
- NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a
- Crypto engine that we have curl_ssl_md5sum() for. */
-#if defined(USE_NTRESPONSES) && !defined(USE_WIN32_CRYPTO)
+ NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and
+ MD5 support */
+#if defined(USE_NTRESPONSES) && !defined(CURL_DISABLE_CRYPTO_AUTH)
#define USE_NTLM2SESSION
#endif
diff -up curl-7.61.1/lib/curl_sha256.h.RHEL-32335 curl-7.61.1/lib/curl_sha256.h
--- curl-7.61.1/lib/curl_sha256.h.RHEL-32335 2024-04-10 10:13:40.975551190 +0200
+++ curl-7.61.1/lib/curl_sha256.h 2024-04-10 10:14:00.251665815 +0200
@@ -24,8 +24,8 @@
#ifndef CURL_DISABLE_CRYPTO_AUTH
-void Curl_sha256it(unsigned char *outbuffer,
- const unsigned char *input);
+void Curl_sha256it(unsigned char *outbuffer, const unsigned char *input,
+ const size_t len);
#endif
diff -up curl-7.61.1/lib/md5.c.RHEL-32335 curl-7.61.1/lib/md5.c
--- curl-7.61.1/lib/md5.c.RHEL-32335 2024-04-10 10:10:39.831474009 +0200
+++ curl-7.61.1/lib/md5.c 2024-04-10 10:13:29.963485706 +0200
@@ -519,12 +519,13 @@ const MD5_params Curl_DIGEST_MD5[] = {
/*
* @unittest: 1601
*/
-void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
- const unsigned char *input)
+void Curl_md5it(unsigned char *outbuffer, const unsigned char *input,
+ const size_t len)
{
MD5_CTX ctx;
+
MD5_Init(&ctx);
- MD5_Update(&ctx, input, curlx_uztoui(strlen((char *)input)));
+ MD5_Update(&ctx, input, curlx_uztoui(len));
MD5_Final(outbuffer, &ctx);
}
diff -up curl-7.61.1/lib/sha256.c.RHEL-32335 curl-7.61.1/lib/sha256.c
--- curl-7.61.1/lib/sha256.c.RHEL-32335 2024-04-10 10:14:32.047854892 +0200
+++ curl-7.61.1/lib/sha256.c 2024-04-10 10:15:23.010157942 +0200
@@ -255,12 +255,13 @@ static int SHA256_Final(unsigned char *o
#endif
-void Curl_sha256it(unsigned char *outbuffer, /* 32 unsigned chars */
- const unsigned char *input)
+void Curl_sha256it(unsigned char *outbuffer, const unsigned char *input,
+ const size_t len)
{
SHA256_CTX ctx;
+
SHA256_Init(&ctx);
- SHA256_Update(&ctx, input, curlx_uztoui(strlen((char *)input)));
+ SHA256_Update(&ctx, input, curlx_uztoui(len));
SHA256_Final(outbuffer, &ctx);
}
diff -up curl-7.61.1/lib/vauth/digest.c.RHEL-32335 curl-7.61.1/lib/vauth/digest.c
--- curl-7.61.1/lib/vauth/digest.c.RHEL-32335 2024-04-10 10:15:31.737209838 +0200
+++ curl-7.61.1/lib/vauth/digest.c 2024-04-10 10:20:11.293872233 +0200
@@ -62,7 +62,7 @@
what ultimately goes over the network.
*/
#define CURL_OUTPUT_DIGEST_CONV(a, b) \
- result = Curl_convert_to_network(a, (char *)b, strlen((const char *)b)); \
+ result = Curl_convert_to_network(a, b, strlen(b)); \
if(result) { \
free(b); \
return result; \
@@ -687,12 +687,12 @@ static CURLcode _Curl_auth_create_digest
struct digestdata *digest,
char **outptr, size_t *outlen,
void (*convert_to_ascii)(unsigned char *, unsigned char *),
- void (*hash)(unsigned char *, const unsigned char *))
+ void (*hash)(unsigned char *, const unsigned char *,
+ const size_t))
{
CURLcode result;
unsigned char hashbuf[32]; /* 32 bytes/256 bits */
unsigned char request_digest[65];
- unsigned char *hashthis;
unsigned char ha1[65]; /* 64 digits and 1 zero byte */
unsigned char ha2[65]; /* 64 digits and 1 zero byte */
char userh[65];
@@ -700,6 +700,7 @@ static CURLcode _Curl_auth_create_digest
size_t cnonce_sz = 0;
char *userp_quoted;
char *response = NULL;
+ char *hashthis = NULL;
char *tmp = NULL;
if(!digest->nc)
@@ -721,12 +722,12 @@ static CURLcode _Curl_auth_create_digest
}
if(digest->userhash) {
- hashthis = (unsigned char *) aprintf("%s:%s", userp, digest->realm);
+ hashthis = aprintf("%s:%s", userp, digest->realm);
if(!hashthis)
return CURLE_OUT_OF_MEMORY;
CURL_OUTPUT_DIGEST_CONV(data, hashthis);
- hash(hashbuf, hashthis);
+ hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
free(hashthis);
convert_to_ascii(hashbuf, (unsigned char *)userh);
}
@@ -742,14 +743,13 @@ static CURLcode _Curl_auth_create_digest
unq(nonce-value) ":" unq(cnonce-value)
*/
- hashthis = (unsigned char *)
- aprintf("%s:%s:%s", digest->userhash ? userh : userp,
- digest->realm, passwdp);
+ hashthis = aprintf("%s:%s:%s", digest->userhash ? userh : userp,
+ digest->realm, passwdp);
if(!hashthis)
return CURLE_OUT_OF_MEMORY;
CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */
- hash(hashbuf, hashthis);
+ hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
free(hashthis);
convert_to_ascii(hashbuf, ha1);
@@ -762,7 +762,7 @@ static CURLcode _Curl_auth_create_digest
return CURLE_OUT_OF_MEMORY;
CURL_OUTPUT_DIGEST_CONV(data, tmp); /* Convert on non-ASCII machines */
- hash(hashbuf, (unsigned char *) tmp);
+ hash(hashbuf, (unsigned char *) tmp, strlen(tmp));
free(tmp);
convert_to_ascii(hashbuf, ha1);
}
@@ -780,18 +780,18 @@ static CURLcode _Curl_auth_create_digest
5.1.1 of RFC 2616)
*/
- hashthis = (unsigned char *) aprintf("%s:%s", request, uripath);
+ hashthis = aprintf("%s:%s", request, uripath);
if(digest->qop && strcasecompare(digest->qop, "auth-int")) {
/* We don't support auth-int for PUT or POST at the moment.
TODO: replace hash of empty string with entity-body for PUT/POST */
char hashed[65];
- unsigned char *hashthis2;
+ char *hashthis2;
- hash(hashbuf, (const unsigned char *)"");
+ hash(hashbuf, (const unsigned char *)"", 0);
convert_to_ascii(hashbuf, (unsigned char *)hashed);
- hashthis2 = (unsigned char *)aprintf("%s:%s", hashthis, hashed);
+ hashthis2 = aprintf("%s:%s", hashthis, hashed);
free(hashthis);
hashthis = hashthis2;
}
@@ -800,31 +800,23 @@ static CURLcode _Curl_auth_create_digest
return CURLE_OUT_OF_MEMORY;
CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */
- hash(hashbuf, hashthis);
+ hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
free(hashthis);
convert_to_ascii(hashbuf, ha2);
if(digest->qop) {
- hashthis = (unsigned char *) aprintf("%s:%s:%08x:%s:%s:%s",
- ha1,
- digest->nonce,
- digest->nc,
- digest->cnonce,
- digest->qop,
- ha2);
+ hashthis = aprintf("%s:%s:%08x:%s:%s:%s", ha1, digest->nonce, digest->nc,
+ digest->cnonce, digest->qop, ha2);
}
else {
- hashthis = (unsigned char *) aprintf("%s:%s:%s",
- ha1,
- digest->nonce,
- ha2);
+ hashthis = aprintf("%s:%s:%s", ha1, digest->nonce, ha2);
}
if(!hashthis)
return CURLE_OUT_OF_MEMORY;
CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */
- hash(hashbuf, hashthis);
+ hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
free(hashthis);
convert_to_ascii(hashbuf, request_digest);
diff -up curl-7.61.1/lib/vauth/ntlm.c.RHEL-32335 curl-7.61.1/lib/vauth/ntlm.c
--- curl-7.61.1/lib/vauth/ntlm.c.RHEL-32335 2024-04-10 09:51:15.114537483 +0200
+++ curl-7.61.1/lib/vauth/ntlm.c 2024-04-10 09:52:26.411962237 +0200
@@ -40,6 +40,7 @@
#include "curl_ntlm_core.h"
#include "curl_gethostname.h"
#include "curl_multibyte.h"
+#include "curl_md5.h"
#include "warnless.h"
#include "rand.h"
#include "vtls/vtls.h"
@@ -621,11 +622,10 @@ CURLcode Curl_auth_create_ntlm_type3_mes
memcpy(tmp, &ntlm->nonce[0], 8);
memcpy(tmp + 8, entropy, 8);
- result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
- if(!result)
- /* We shall only use the first 8 bytes of md5sum, but the des code in
- Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
- result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
+ Curl_md5it(md5sum, tmp, 16);
+ /* We shall only use the first 8 bytes of md5sum, but the des code in
+ Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
+ result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
if(result)
return result;
diff -up curl-7.61.1/tests/unit/unit1601.c.RHEL-32335 curl-7.61.1/tests/unit/unit1601.c
--- curl-7.61.1/tests/unit/unit1601.c.RHEL-32335 2024-04-10 10:20:19.347920127 +0200
+++ curl-7.61.1/tests/unit/unit1601.c 2024-04-10 10:21:53.606480641 +0200
@@ -36,18 +36,19 @@ static void unit_stop(void)
UNITTEST_START
#ifndef CURL_DISABLE_CRYPTO_AUTH
- unsigned char output[16];
+ const char string1[] = "1";
+ const char string2[] = "hello-you-fool";
+ unsigned char output[MD5_DIGEST_LEN];
unsigned char *testp = output;
- Curl_md5it(output, (const unsigned char *)"1");
-/* !checksrc! disable LONGLINE 2 */
- verify_memory(testp,
- "\xc4\xca\x42\x38\xa0\xb9\x23\x82\x0d\xcc\x50\x9a\x6f\x75\x84\x9b", 16);
+ Curl_md5it(output, (const unsigned char *) string1, strlen(string1));
+ verify_memory(testp, "\xc4\xca\x42\x38\xa0\xb9\x23\x82\x0d\xcc\x50\x9a\x6f"
+ "\x75\x84\x9b", MD5_DIGEST_LEN);
- Curl_md5it(output, (const unsigned char *)"hello-you-fool");
+ Curl_md5it(output, (const unsigned char *) string2, strlen(string2));
- verify_memory(testp,
- "\x88\x67\x0b\x6d\x5d\x74\x2f\xad\xa5\xcd\xf9\xb6\x82\x87\x5f\x22", 16);
+ verify_memory(testp, "\x88\x67\x0b\x6d\x5d\x74\x2f\xad\xa5\xcd\xf9\xb6\x82"
+ "\x87\x5f\x22", MD5_DIGEST_LEN);
#endif

View File

@ -0,0 +1,283 @@
From 17d1e27d309f16da960fd3b9933e6e2b1db22b17 Mon Sep 17 00:00:00 2001
From: Eric Wong <e@80x24.org>
Date: Sat, 10 Aug 2019 21:20:23 +0000
Subject: [PATCH] asyn-thread: issue CURL_POLL_REMOVE before closing socket
This avoids EBADF errors from EPOLL_CTL_DEL operations in the
ephiperfifo.c example. EBADF is dangerous in multi-threaded
applications where I rely on epoll_ctl to operate on the same
epoll description from different threads.
Follow-up to eb9a604f8d7db8
Bug: https://curl.haxx.se/mail/lib-2019-08/0026.html
Closes #4211
---
lib/asyn-thread.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 222e78d98..24da74885 100755
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -164,6 +164,7 @@ struct thread_sync_data {
duplicate */
int port;
#ifdef HAVE_SOCKETPAIR
+ struct connectdata *conn;
curl_socket_t sock_pair[2]; /* socket pair */
#endif
int sock_error;
@@ -201,11 +202,10 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
Curl_freeaddrinfo(tsd->res);
#ifdef HAVE_SOCKETPAIR
- /* close socket pair */
- if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
- sclose(tsd->sock_pair[0]);
- }
-
+ /*
+ * close one end of the socket pair (may be done in resolver thread);
+ * the other end (for reading) is always closed in the parent thread.
+ */
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
sclose(tsd->sock_pair[1]);
}
@@ -382,6 +382,10 @@ static void destroy_async_data(struct Curl_async *async)
if(async->os_specific) {
struct thread_data *td = (struct thread_data*) async->os_specific;
int done;
+#ifdef HAVE_SOCKETPAIR
+ curl_socket_t sock_rd = td->tsd.sock_pair[0];
+ struct connectdata *conn = td->tsd.conn;
+#endif
/*
* if the thread is still blocking in the resolve syscall, detach it and
@@ -403,6 +407,15 @@ static void destroy_async_data(struct Curl_async *async)
free(async->os_specific);
}
+#ifdef HAVE_SOCKETPAIR
+ /*
+ * ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
+ * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
+ */
+ if(conn)
+ Curl_multi_closed(conn->data, sock_rd);
+ sclose(sock_rd);
+#endif
}
async->os_specific = NULL;
@@ -644,6 +657,8 @@ int Curl_resolver_getsock(struct connectdata *conn,
if(td) {
/* return read fd to client for polling the DNS resolution status */
socks[0] = td->tsd.sock_pair[0];
+ DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn);
+ td->tsd.conn = conn;
ret_val = GETSOCK_READSOCK(0);
}
else {
--
2.49.0
From 041690aadb1357775ff06c5bf827a98585627c76 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 30 Jul 2019 10:29:54 +0200
Subject: [PATCH] asyn-thread: removed unused variable
Follow-up to eb9a604f. Mistake caused by me when I edited the commit
before push...
---
lib/asyn-thread.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index f17638e44..e323cbe20 100755
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -636,11 +636,10 @@ int Curl_resolver_getsock(struct connectdata *conn,
struct resdata *reslv = (struct resdata *)data->state.resolver;
#ifdef HAVE_SOCKETPAIR
struct thread_data *td = (struct thread_data*)conn->async.os_specific;
- int loop_idx;
#else
(void)socks;
- (void)numsocks;
#endif
+ (void)numsocks;
#ifdef HAVE_SOCKETPAIR
if(td) {
--
2.49.0
From 060fb84a5a07388f099c7a3422e281ac64d623a5 Mon Sep 17 00:00:00 2001
From: Xiang Xiao <xiaoxiang@xiaomi.com>
Date: Tue, 24 Dec 2019 21:47:37 +0800
Subject: [PATCH] lib: remove erroneous +x file permission on some c files
Modified by commit eb9a604 accidentally.
Closes https://github.com/curl/curl/pull/4756
---
lib/asyn-thread.c | 0
lib/multi.c | 0
2 files changed, 0 insertions(+), 0 deletions(-)
mode change 100755 => 100644 lib/asyn-thread.c
mode change 100755 => 100644 lib/multi.c
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
old mode 100755
new mode 100644
diff --git a/lib/multi.c b/lib/multi.c
old mode 100755
new mode 100644
--
2.49.0
From e34ec7de5964baa214555115f5061ed199d0f7b4 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 11 Sep 2019 23:11:58 +0200
Subject: [PATCH] asyn-thread: s/AF_LOCAL/AF_UNIX for Solaris
Reported-by: Dagobert Michelsen
Fixes #4328
Closes #4333
---
lib/asyn-thread.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 24da74885..fcbf1305e 100755
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -244,8 +244,8 @@ int init_thread_sync_data(struct thread_data * td,
Curl_mutex_init(tsd->mtx);
#ifdef HAVE_SOCKETPAIR
- /* create socket pair */
- if(socketpair(AF_LOCAL, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
+ /* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
tsd->sock_pair[0] = CURL_SOCKET_BAD;
tsd->sock_pair[1] = CURL_SOCKET_BAD;
goto err_exit;
--
2.49.0
From 9c76f694de1765152e0b349cd55baad5a501f55b Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 5 Oct 2019 15:41:09 +0200
Subject: [PATCH] asyn-thread: make use of Curl_socketpair() where available
---
lib/asyn-thread.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index fcbf1305e..8c552baa9 100755
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -163,7 +165,7 @@ struct thread_sync_data {
char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
int port;
-#ifdef HAVE_SOCKETPAIR
+#ifdef USE_SOCKETPAIR
struct connectdata *conn;
curl_socket_t sock_pair[2]; /* socket pair */
#endif
@@ -201,7 +203,7 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
if(tsd->res)
Curl_freeaddrinfo(tsd->res);
-#ifdef HAVE_SOCKETPAIR
+#ifdef USE_SOCKETPAIR
/*
* close one end of the socket pair (may be done in resolver thread);
* the other end (for reading) is always closed in the parent thread.
@@ -243,9 +245,9 @@ int init_thread_sync_data(struct thread_data * td,
Curl_mutex_init(tsd->mtx);
-#ifdef HAVE_SOCKETPAIR
+#ifdef USE_SOCKETPAIR
/* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */
- if(socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
+ if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
tsd->sock_pair[0] = CURL_SOCKET_BAD;
tsd->sock_pair[1] = CURL_SOCKET_BAD;
goto err_exit;
@@ -297,7 +299,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
struct thread_data *td = tsd->td;
char service[12];
int rc;
-#ifdef HAVE_SOCKETPAIR
+#ifdef USE_SOCKETPAIR
char buf[1];
#endif
@@ -322,11 +324,11 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
free(td);
}
else {
-#ifdef HAVE_SOCKETPAIR
+#ifdef USE_SOCKETPAIR
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
/* DNS has been resolved, signal client task */
buf[0] = 1;
- if(write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
+ if(swrite(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
/* update sock_erro to errno */
tsd->sock_error = SOCKERRNO;
}
@@ -382,7 +384,7 @@ static void destroy_async_data(struct Curl_async *async)
if(async->os_specific) {
struct thread_data *td = (struct thread_data*) async->os_specific;
int done;
-#ifdef HAVE_SOCKETPAIR
+#ifdef USE_SOCKETPAIR
curl_socket_t sock_rd = td->tsd.sock_pair[0];
struct connectdata *conn = td->tsd.conn;
#endif
@@ -407,7 +409,7 @@ static void destroy_async_data(struct Curl_async *async)
free(async->os_specific);
}
-#ifdef HAVE_SOCKETPAIR
+#ifdef USE_SOCKETPAIR
/*
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
@@ -649,14 +651,14 @@ int Curl_resolver_getsock(struct connectdata *conn,
timediff_t ms;
struct Curl_easy *data = conn->data;
struct resdata *reslv = (struct resdata *)data->state.resolver;
-#ifdef HAVE_SOCKETPAIR
+#ifdef USE_SOCKETPAIR
struct thread_data *td = (struct thread_data*)conn->async.os_specific;
#else
(void)socks;
#endif
(void)numsocks;
-#ifdef HAVE_SOCKETPAIR
+#ifdef USE_SOCKETPAIR
if(td) {
/* return read fd to client for polling the DNS resolution status */
socks[0] = td->tsd.sock_pair[0];
@@ -673,7 +675,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
else
milli = 200;
Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
-#ifdef HAVE_SOCKETPAIR
+#ifdef USE_SOCKETPAIR
}
#endif
--
2.49.0

View File

@ -0,0 +1,338 @@
From b1a049b4c024ea69ef571da8def3cc13889430f4 Mon Sep 17 00:00:00 2001
From: Jay Satiro <raysatiro@yahoo.com>
Date: Sun, 23 Feb 2020 18:37:09 -0500
Subject: [PATCH] libssh: Fix matching user-specified MD5 hex key
Prior to this change a match would never be successful because it
was mistakenly coded to compare binary data from libssh to a
user-specified hex string (ie CURLOPT_SSH_HOST_PUBLIC_KEY_MD5).
Reported-by: fds242@users.noreply.github.com
Fixes https://github.com/curl/curl/issues/4971
Closes https://github.com/curl/curl/pull/4974
(cherry picked from commit 09aa807240b9dcde78a919ff712316a1daf0655e)
---
lib/ssh-libssh.c | 20 ++++++++++++++++---
tests/FILEFORMAT | 1 +
tests/data/Makefile.inc | 1 +
tests/data/test664 | 44 +++++++++++++++++++++++++++++++++++++++++
tests/data/test665 | 44 +++++++++++++++++++++++++++++++++++++++++
tests/runtests.pl | 24 ++++++++++++++++++++++
tests/sshhelp.pm | 3 +++
tests/sshserver.pl | 31 +++++++++++++++++++++++++----
8 files changed, 161 insertions(+), 7 deletions(-)
create mode 100644 tests/data/test664
create mode 100644 tests/data/test665
diff --git a/lib/ssh-libssh.c b/lib/ssh-libssh.c
index 7d590891c..c203d6336 100644
--- a/lib/ssh-libssh.c
+++ b/lib/ssh-libssh.c
@@ -327,13 +327,27 @@ static int myssh_is_known(struct connectdata *conn)
return rc;
if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
+ int i;
+ char md5buffer[33];
+ const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
+
rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5,
&hash, &hlen);
- if(rc != SSH_OK)
+ if(rc != SSH_OK || hlen != 16) {
+ failf(data,
+ "Denied establishing ssh session: md5 fingerprint not available");
goto cleanup;
+ }
+
+ for(i = 0; i < 16; i++)
+ snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char)hash[i]);
+
+ infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
- if(hlen != strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) ||
- memcmp(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], hash, hlen)) {
+ if(!strcasecompare(md5buffer, pubkey_md5)) {
+ failf(data,
+ "Denied establishing ssh session: mismatch md5 fingerprint. "
+ "Remote %s is not equal to %s", md5buffer, pubkey_md5);
rc = SSH_ERROR;
goto cleanup;
}
diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT
index 135ded6c1..6b79093ab 100644
--- a/tests/FILEFORMAT
+++ b/tests/FILEFORMAT
@@ -368,6 +368,7 @@ Available substitute variables include:
%PWD - Current directory
%RTSP6PORT - IPv6 port number of the RTSP server
%RTSPPORT - Port number of the RTSP server
+%SSHSRVMD5 - MD5 of SSH server's public key
%SMTP6PORT - IPv6 port number of the SMTP server
%SMTPPORT - Port number of the SMTP server
%SOCKSPORT - Port number of the SOCKS4/5 server
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index e0457486b..923b58a63 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -84,6 +84,7 @@ test626 test627 test628 test629 test630 test631 test632 test633 test634 \
test635 test636 test637 test638 test639 test640 test641 test642 \
test643 test644 test645 test646 test647 test648 test649 test650 test651 \
test652 test653 test654 test655 test656 \
+test664 test665 \
\
test700 test701 test702 test703 test704 test705 test706 test707 test708 \
test709 test710 test711 test712 test713 test714 test715 \
diff --git a/tests/data/test664 b/tests/data/test664
new file mode 100644
index 000000000..cb73b248b
--- /dev/null
+++ b/tests/data/test664
@@ -0,0 +1,44 @@
+<testcase>
+<info>
+<keywords>
+SFTP
+server key check
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+test
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+sftp
+</server>
+ <name>
+SFTP correct host key
+ </name>
+ <command>
+--hostpubmd5 %SSHSRVMD5 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file664.txt
+</command>
+<file name="log/file664.txt">
+test
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+0
+</errorcode>
+<valgrind>
+disable
+</valgrind>
+</verify>
+</testcase>
diff --git a/tests/data/test665 b/tests/data/test665
new file mode 100644
index 000000000..830adb8f6
--- /dev/null
+++ b/tests/data/test665
@@ -0,0 +1,44 @@
+<testcase>
+<info>
+<keywords>
+SCP
+server key check
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+test
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+scp
+</server>
+ <name>
+SCP correct host key
+ </name>
+ <command>
+--hostpubmd5 %SSHSRVMD5 --key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file665.txt
+</command>
+<file name="log/file665.txt">
+test
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+0
+</errorcode>
+<valgrind>
+disable
+</valgrind>
+</verify>
+</testcase>
diff --git a/tests/runtests.pl b/tests/runtests.pl
index e12c1429a..4e2a19cf2 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -150,6 +150,8 @@ my $SMBPORT; # SMB server port
my $SMBSPORT; # SMBS server port
my $NEGTELNETPORT; # TELNET server port with negotiation
+my $SSHSRVMD5; # MD5 of ssh server public key
+
my $srcdir = $ENV{'srcdir'} || '.';
my $CURL="../src/curl".exe_ext(); # what curl executable to run on the tests
my $VCURL=$CURL; # what curl binary to use to verify the servers with
@@ -2181,6 +2183,18 @@ sub runsshserver {
return (0,0);
}
+ my $hstpubmd5f = "curl_host_rsa_key.pub_md5";
+ if(!open(PUBMD5FILE, "<", $hstpubmd5f) ||
+ (read(PUBMD5FILE, $SSHSRVMD5, 32) != 32) ||
+ !close(PUBMD5FILE) ||
+ ($SSHSRVMD5 !~ /^[a-f0-9]{32}$/i))
+ {
+ my $msg = "Fatal: $srvrname pubkey md5 missing : \"$hstpubmd5f\" : $!";
+ logmsg "$msg\n";
+ stopservers($verbose);
+ die $msg;
+ }
+
if($verbose) {
logmsg "RUN: $srvrname server is now running PID $pid2\n";
}
@@ -3205,6 +3219,16 @@ sub subVariables {
$$thing =~ s/%SRCDIR/$srcdir/g;
$$thing =~ s/%USER/$USER/g;
+ if($$thing =~ /%SSHSRVMD5/) {
+ if(!$SSHSRVMD5) {
+ my $msg = "Fatal: Missing SSH server pubkey MD5. Is server running?";
+ logmsg "$msg\n";
+ stopservers($verbose);
+ die $msg;
+ }
+ $$thing =~ s/%SSHSRVMD5/$SSHSRVMD5/g;
+ }
+
# The purpose of FTPTIME2 and FTPTIME3 is to provide times that can be
# used for time-out tests and that whould work on most hosts as these
# adjust for the startup/check time for this particular host. We needed
diff --git a/tests/sshhelp.pm b/tests/sshhelp.pm
index c5618a109..abdf9c458 100644
--- a/tests/sshhelp.pm
+++ b/tests/sshhelp.pm
@@ -50,6 +50,7 @@ use vars qw(
$sftpcmds
$hstprvkeyf
$hstpubkeyf
+ $hstpubmd5f
$cliprvkeyf
$clipubkeyf
@sftppath
@@ -82,6 +83,7 @@ use vars qw(
$sftpcmds
$hstprvkeyf
$hstpubkeyf
+ $hstpubmd5f
$cliprvkeyf
$clipubkeyf
display_sshdconfig
@@ -122,6 +124,7 @@ $sftpcmds = 'curl_sftp_cmds'; # sftp client commands batch file
$knownhosts = 'curl_client_knownhosts'; # ssh knownhosts file
$hstprvkeyf = 'curl_host_rsa_key'; # host private key file
$hstpubkeyf = 'curl_host_rsa_key.pub'; # host public key file
+$hstpubmd5f = 'curl_host_rsa_key.pub_md5'; # md5 hash of host public key
$cliprvkeyf = 'curl_client_key'; # client private key file
$clipubkeyf = 'curl_client_key.pub'; # client public key file
diff --git a/tests/sshserver.pl b/tests/sshserver.pl
index 9b3d122fd..cd92a62c5 100755
--- a/tests/sshserver.pl
+++ b/tests/sshserver.pl
@@ -28,6 +28,9 @@ use strict;
use warnings;
use Cwd;
use Cwd 'abs_path';
+use Digest::MD5;
+use Digest::MD5 'md5_hex';
+use MIME::Base64;
#***************************************************************************
# Variables and subs imported from sshhelp module
@@ -48,6 +51,7 @@ use sshhelp qw(
$sftpcmds
$hstprvkeyf
$hstpubkeyf
+ $hstpubmd5f
$cliprvkeyf
$clipubkeyf
display_sshdconfig
@@ -367,10 +371,11 @@ if((($sshid =~ /OpenSSH/) && ($sshvernum < 299)) ||
#
if((! -e $hstprvkeyf) || (! -s $hstprvkeyf) ||
(! -e $hstpubkeyf) || (! -s $hstpubkeyf) ||
+ (! -e $hstpubmd5f) || (! -s $hstpubmd5f) ||
(! -e $cliprvkeyf) || (! -s $cliprvkeyf) ||
(! -e $clipubkeyf) || (! -s $clipubkeyf)) {
# Make sure all files are gone so ssh-keygen doesn't complain
- unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf);
+ unlink($hstprvkeyf, $hstpubkeyf, $hstpubmd5f, $cliprvkeyf, $clipubkeyf);
logmsg 'generating host keys...' if($verbose);
if(system "\"$sshkeygen\" -q -t rsa -f $hstprvkeyf -C 'curl test server' -N ''") {
logmsg 'Could not generate host key';
@@ -381,6 +386,24 @@ if((! -e $hstprvkeyf) || (! -s $hstprvkeyf) ||
logmsg 'Could not generate client key';
exit 1;
}
+ # Make sure that permissions are restricted so openssh doesn't complain
+ system "chmod 600 $hstprvkeyf";
+ system "chmod 600 $cliprvkeyf";
+ # Save md5 hash of public host key
+ open(RSAKEYFILE, "<$hstpubkeyf");
+ my @rsahostkey = do { local $/ = ' '; <RSAKEYFILE> };
+ close(RSAKEYFILE);
+ if(!$rsahostkey[1]) {
+ logmsg 'Failed parsing base64 encoded RSA host key';
+ exit 1;
+ }
+ open(PUBMD5FILE, ">$hstpubmd5f");
+ print PUBMD5FILE md5_hex(decode_base64($rsahostkey[1]));
+ close(PUBMD5FILE);
+ if((! -e $hstpubmd5f) || (! -s $hstpubmd5f)) {
+ logmsg 'Failed writing md5 hash of RSA host key';
+ exit 1;
+ }
}
@@ -1073,8 +1096,8 @@ elsif($verbose && ($rc >> 8)) {
#***************************************************************************
# Clean up once the server has stopped
#
-unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf, $knownhosts);
-unlink($sshdconfig, $sshconfig, $sftpconfig);
-
+unlink($hstprvkeyf, $hstpubkeyf, $hstpubmd5f,
+ $cliprvkeyf, $clipubkeyf, $knownhosts,
+ $sshdconfig, $sshconfig, $sftpconfig);
exit 0;
--
2.47.1

View File

@ -0,0 +1,44 @@
From a1c1af1b82bf9427b2bd5ad949d24923f995909a Mon Sep 17 00:00:00 2001
From: Jacek Migacz <jmigacz@redhat.com>
Date: Wed, 9 Jul 2025 14:33:09 +0200
Subject: [PATCH] crypto: ensure crypto initialization works
---
lib/vtls/openssl.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 161e79e..7c41f54 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -3802,7 +3802,12 @@ static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */
(void) unused;
mdctx = EVP_MD_CTX_create();
- EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
+ if(!mdctx)
+ return CURLE_OUT_OF_MEMORY;
+ if(!EVP_DigestInit_ex(mdctx, EVP_md5(), NULL)) {
+ EVP_MD_CTX_destroy(mdctx);
+ return CURLE_FAILED_INIT;
+ }
EVP_DigestUpdate(mdctx, tmp, tmplen);
EVP_DigestFinal_ex(mdctx, md5sum, &len);
EVP_MD_CTX_destroy(mdctx);
@@ -3820,7 +3825,12 @@ static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
(void) unused;
mdctx = EVP_MD_CTX_create();
- EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
+ if(!mdctx)
+ return CURLE_OUT_OF_MEMORY;
+ if(!EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL)) {
+ EVP_MD_CTX_destroy(mdctx);
+ return CURLE_FAILED_INIT;
+ }
EVP_DigestUpdate(mdctx, tmp, tmplen);
EVP_DigestFinal_ex(mdctx, sha256sum, &len);
EVP_MD_CTX_destroy(mdctx);
--
2.50.0

View File

@ -0,0 +1,42 @@
From cbea2fd2c74feabeb6f13b3e3df243b225b3b3ab Mon Sep 17 00:00:00 2001
From: Johannes Schindelin <johannes.schindelin@gmx.de>
Date: Thu, 6 Dec 2018 17:26:13 +0100
Subject: [PATCH] NTLM: force the connection to HTTP/1.1
Since v7.62.0, cURL tries to use HTTP/2 whenever the server announces
the capability. However, NTLM authentication only works with HTTP/1.1,
and will likely remain in that boat (for details, see
https://docs.microsoft.com/en-us/iis/get-started/whats-new-in-iis-10/http2-on-iis#when-is-http2-not-supported).
When we just found out that we want to use NTLM, and when the current
connection runs in HTTP/2 mode, let's force the connection to be closed
and to be re-opened using HTTP/1.1.
Fixes https://github.com/curl/curl/issues/3341.
Closes #3345
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
lib/http.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/lib/http.c b/lib/http.c
index aed7aa80f..7be6f8b92 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -526,6 +526,12 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
pickhost = pickoneauth(&data->state.authhost, authmask);
if(!pickhost)
data->state.authproblem = TRUE;
+ if(data->state.authhost.picked == CURLAUTH_NTLM &&
+ conn->httpversion > 11) {
+ infof(data, "Forcing HTTP/1.1 for NTLM");
+ connclose(conn, "Force HTTP/1.1 connection");
+ conn->data->set.httpversion = CURL_HTTP_VERSION_1_1;
+ }
}
if(conn->bits.proxy_user_passwd &&
((data->req.httpcode == 407) ||
--
2.50.0

View File

@ -0,0 +1,29 @@
From c6ae07c6a541e0e96d0040afb62b45dd37711300 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 11 Aug 2025 20:23:05 +0200
Subject: [PATCH] cookie: don't treat the leading slash as trailing
If there is only a leading slash in the path, keep that. Also add an
assert to make sure the path is never blank.
Reported-by: Google Big Sleep
Closes #18266
---
lib/cookie.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/lib/cookie.c b/lib/cookie.c
index 914a4aca12ac..b72dd99bce9b 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -420,8 +420,9 @@ static char *sanitize_cookie_path(const char *cookie_path)
return new_path;
}
+ /* remove trailing slash when path is non-empty (len > 1) */
/* convert /hoge/ to /hoge */
- if(len && new_path[len - 1] == '/') {
+ if(len > 1 && new_path[len - 1] == '/') {
new_path[len - 1] = 0x0;
}

View File

@ -0,0 +1,988 @@
diff -Naur curl-7.61.1.orig/lib/http_aws_sigv4.c curl-7.61.1/lib/http_aws_sigv4.c
--- curl-7.61.1.orig/lib/http_aws_sigv4.c 1970-01-01 01:00:00.000000000 +0100
+++ curl-7.61.1/lib/http_aws_sigv4.c 2025-12-02 13:31:38.991776478 +0100
@@ -0,0 +1,511 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2021, 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.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+
+#define USE_AWS_SIGV4
+
+#include "urldata.h"
+#include "strcase.h"
+#include "strdup.h"
+#include "vauth/vauth.h"
+#include "vauth/digest.h"
+#include "http_aws_sigv4.h"
+#include "curl_sha256.h"
+#include "curl_hmac.h"
+#include "warnless.h"
+#include "transfer.h"
+
+#include "strcase.h"
+#include "parsedate.h"
+#include "sendf.h"
+
+#include <time.h>
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* SHA256 Init/Update/Final function pointers for HMAC */
+#if defined(USE_OPENSSL)
+#include <openssl/sha.h>
+#include <openssl/opensslv.h>
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
+#define USE_OPENSSL_SHA256
+#endif
+#endif
+
+#ifdef USE_OPENSSL_SHA256
+static void SHA256_Init_Wrapper(void *context)
+{
+ SHA256_Init((SHA256_CTX *)context);
+}
+
+static void SHA256_Update_Wrapper(void *context,
+ const unsigned char *data,
+ unsigned int len)
+{
+ SHA256_Update((SHA256_CTX *)context, data, len);
+}
+
+static void SHA256_Final_Wrapper(unsigned char *result, void *context)
+{
+ SHA256_Final(result, (SHA256_CTX *)context);
+}
+#else
+/* Use internal SHA256 implementation */
+typedef struct sha256_state SHA256_CTX;
+
+static void SHA256_Init_Wrapper(void *context);
+static int SHA256_Update_Wrapper_Internal(void *context,
+ const unsigned char *data,
+ unsigned int len);
+static int SHA256_Final_Wrapper_Internal(unsigned char *result,
+ void *context);
+
+static void SHA256_Update_Wrapper(void *context,
+ const unsigned char *data,
+ unsigned int len)
+{
+ SHA256_Update_Wrapper_Internal(context, data, len);
+}
+
+static void SHA256_Final_Wrapper(unsigned char *result, void *context)
+{
+ SHA256_Final_Wrapper_Internal(result, context);
+}
+
+/* Forward declarations for internal SHA256 functions */
+extern void SHA256_Init(SHA256_CTX *ctx);
+extern int SHA256_Update(SHA256_CTX *ctx, const unsigned char *data,
+ unsigned int len);
+extern int SHA256_Final(unsigned char *out, SHA256_CTX *ctx);
+
+static void SHA256_Init_Wrapper(void *context)
+{
+ SHA256_Init((SHA256_CTX *)context);
+}
+
+static int SHA256_Update_Wrapper_Internal(void *context,
+ const unsigned char *data,
+ unsigned int len)
+{
+ return SHA256_Update((SHA256_CTX *)context, data, len);
+}
+
+static int SHA256_Final_Wrapper_Internal(unsigned char *result,
+ void *context)
+{
+ return SHA256_Final(result, (SHA256_CTX *)context);
+}
+#endif
+
+/* HMAC-SHA256 parameters for curl 7.61.1 */
+static const HMAC_params Curl_HMAC_SHA256[] = {
+ {
+ CURLX_FUNCTION_CAST(HMAC_hinit_func, SHA256_Init_Wrapper),
+ CURLX_FUNCTION_CAST(HMAC_hupdate_func, SHA256_Update_Wrapper),
+ CURLX_FUNCTION_CAST(HMAC_hfinal_func, SHA256_Final_Wrapper),
+ sizeof(SHA256_CTX),
+ 64, /* Maximum key length (block size) */
+ 32 /* Result length (SHA256 produces 32 bytes) */
+ }
+};
+
+#define HMAC_SHA256(k, kl, d, dl, o) \
+ do { \
+ HMAC_context *hctx = Curl_HMAC_init(Curl_HMAC_SHA256, \
+ (unsigned char *)k, \
+ (unsigned int)kl); \
+ if(!hctx) { \
+ ret = CURLE_OUT_OF_MEMORY; \
+ goto fail; \
+ } \
+ Curl_HMAC_update(hctx, \
+ (unsigned char *)d, \
+ (unsigned int)dl); \
+ Curl_HMAC_final(hctx, o); \
+ } while(0)
+
+static void sha256_to_hex(char *dst, unsigned char *sha, size_t dst_l)
+{
+ int i;
+
+ DEBUGASSERT(dst_l >= 65);
+ for(i = 0; i < 32; ++i) {
+ curl_msnprintf(dst + (i * 2), dst_l - (i * 2), "%02x", sha[i]);
+ }
+}
+
+CURLcode Curl_output_aws_sigv4(struct connectdata *conn, bool proxy)
+{
+ CURLcode ret = CURLE_OUT_OF_MEMORY;
+ struct Curl_easy *data = conn->data;
+ size_t len;
+ const char *tmp0;
+ const char *tmp1;
+ char *provider0_low = NULL;
+ char *provider0_up = NULL;
+ char *provider1_low = NULL;
+ char *provider1_mid = NULL;
+ char *region = NULL;
+ char *service = NULL;
+ const char *hostname = conn->host.name;
+#ifdef DEBUGBUILD
+ char *force_timestamp;
+#endif
+ time_t clock;
+ struct tm tm;
+ char timestamp[17];
+ char date[9];
+ const char *content_type = Curl_checkheaders(conn, "Content-Type");
+ char *canonical_headers = NULL;
+ char *signed_headers = NULL;
+ Curl_HttpReq httpreq;
+ const char *method = NULL;
+ const char *post_data = data->set.postfields ? data->set.postfields : "";
+ unsigned char sha_hash[32];
+ char sha_hex[65];
+ char *canonical_request = NULL;
+ char *request_type = NULL;
+ char *credential_scope = NULL;
+ char *str_to_sign = NULL;
+ const char *user = data->state.aptr.user ? data->state.aptr.user : "";
+ const char *passwd = data->state.aptr.passwd ? data->state.aptr.passwd : "";
+ char *secret = NULL;
+ unsigned char tmp_sign0[32] = {0};
+ unsigned char tmp_sign1[32] = {0};
+ char *auth_headers = NULL;
+
+ DEBUGASSERT(!proxy);
+ (void)proxy;
+
+ if(Curl_checkheaders(conn, "Authorization")) {
+ /* Authorization already present, Bailing out */
+ return CURLE_OK;
+ }
+
+ /*
+ * Parameters parsing
+ * Google and Outscale use the same OSC or GOOG,
+ * but Amazon uses AWS and AMZ for header arguments.
+ * AWS is the default because most of non-amazon providers
+ * are still using aws:amz as a prefix.
+ */
+ tmp0 = data->set.str[STRING_AWS_SIGV4] ?
+ data->set.str[STRING_AWS_SIGV4] : "aws:amz";
+ tmp1 = strchr(tmp0, ':');
+ len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
+ if(len < 1) {
+ infof(data, "first provider can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ provider0_low = malloc(len + 1);
+ provider0_up = malloc(len + 1);
+ if(!provider0_low || !provider0_up) {
+ goto fail;
+ }
+ Curl_strntolower(provider0_low, tmp0, len);
+ provider0_low[len] = '\0';
+ Curl_strntoupper(provider0_up, tmp0, len);
+ provider0_up[len] = '\0';
+
+ if(tmp1) {
+ tmp0 = tmp1 + 1;
+ tmp1 = strchr(tmp0, ':');
+ len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
+ if(len < 1) {
+ infof(data, "second provider can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ provider1_low = malloc(len + 1);
+ provider1_mid = malloc(len + 1);
+ if(!provider1_low || !provider1_mid) {
+ goto fail;
+ }
+ Curl_strntolower(provider1_low, tmp0, len);
+ provider1_low[len] = '\0';
+ Curl_strntolower(provider1_mid, tmp0, len);
+ provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
+ provider1_mid[len] = '\0';
+
+ if(tmp1) {
+ tmp0 = tmp1 + 1;
+ tmp1 = strchr(tmp0, ':');
+ len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
+ if(len < 1) {
+ infof(data, "region can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ region = Curl_memdup(tmp0, len + 1);
+ if(!region) {
+ goto fail;
+ }
+ region[len] = '\0';
+
+ if(tmp1) {
+ tmp0 = tmp1 + 1;
+ service = strdup(tmp0);
+ if(!service) {
+ goto fail;
+ }
+ if(strlen(service) < 1) {
+ infof(data, "service can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ }
+ }
+ }
+ else {
+ provider1_low = Curl_memdup(provider0_low, len + 1);
+ provider1_mid = Curl_memdup(provider0_low, len + 1);
+ if(!provider1_low || !provider1_mid) {
+ goto fail;
+ }
+ provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
+ }
+
+ if(!service) {
+ tmp0 = hostname;
+ tmp1 = strchr(tmp0, '.');
+ len = tmp1 - tmp0;
+ if(!tmp1 || len < 1) {
+ infof(data, "service missing in parameters or hostname\n");
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ service = Curl_memdup(tmp0, len + 1);
+ if(!service) {
+ goto fail;
+ }
+ service[len] = '\0';
+
+ if(!region) {
+ tmp0 = tmp1 + 1;
+ tmp1 = strchr(tmp0, '.');
+ len = tmp1 - tmp0;
+ if(!tmp1 || len < 1) {
+ infof(data, "region missing in parameters or hostname\n");
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ region = Curl_memdup(tmp0, len + 1);
+ if(!region) {
+ goto fail;
+ }
+ region[len] = '\0';
+ }
+ }
+
+#ifdef DEBUGBUILD
+ force_timestamp = getenv("CURL_FORCETIME");
+ if(force_timestamp)
+ clock = 0;
+ else
+ time(&clock);
+#else
+ time(&clock);
+#endif
+ ret = Curl_gmtime(clock, &tm);
+ if(ret != CURLE_OK) {
+ goto fail;
+ }
+ if(!strftime(timestamp, sizeof(timestamp), "%Y%m%dT%H%M%SZ", &tm)) {
+ goto fail;
+ }
+ memcpy(date, timestamp, sizeof(date));
+ date[sizeof(date) - 1] = 0;
+
+ if(content_type) {
+ content_type = strchr(content_type, ':');
+ if(!content_type) {
+ ret = CURLE_FAILED_INIT;
+ goto fail;
+ }
+ content_type++;
+ /* Skip whitespace now */
+ while(*content_type == ' ' || *content_type == '\t')
+ ++content_type;
+
+ canonical_headers = curl_maprintf("content-type:%s\n"
+ "host:%s\n"
+ "x-%s-date:%s\n",
+ content_type,
+ hostname,
+ provider1_low, timestamp);
+ signed_headers = curl_maprintf("content-type;host;x-%s-date",
+ provider1_low);
+ }
+ else {
+ canonical_headers = curl_maprintf("host:%s\n"
+ "x-%s-date:%s\n",
+ hostname,
+ provider1_low, timestamp);
+ signed_headers = curl_maprintf("host;x-%s-date", provider1_low);
+ }
+
+ if(!canonical_headers || !signed_headers) {
+ goto fail;
+ }
+
+ Curl_sha256it(sha_hash,
+ (const unsigned char *) post_data, strlen(post_data));
+ sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
+
+ /* Determine HTTP method - curl 7.61.1 style */
+ httpreq = data->set.httpreq;
+ switch(httpreq) {
+ case HTTPREQ_GET:
+ method = "GET";
+ break;
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
+ method = "POST";
+ break;
+ case HTTPREQ_PUT:
+ method = "PUT";
+ break;
+ case HTTPREQ_HEAD:
+ method = "HEAD";
+ break;
+ case HTTPREQ_OPTIONS:
+ method = "OPTIONS";
+ break;
+ case HTTPREQ_CUSTOM:
+ method = data->set.customrequest;
+ break;
+ default:
+ method = "GET";
+ break;
+ }
+
+ canonical_request =
+ curl_maprintf("%s\n" /* HTTPRequestMethod */
+ "%s\n" /* CanonicalURI */
+ "%s\n" /* CanonicalQueryString */
+ "%s\n" /* CanonicalHeaders */
+ "%s\n" /* SignedHeaders */
+ "%s", /* HashedRequestPayload in hex */
+ method,
+ data->state.up.path,
+ data->state.up.query ? data->state.up.query : "",
+ canonical_headers,
+ signed_headers,
+ sha_hex);
+ if(!canonical_request) {
+ goto fail;
+ }
+
+ request_type = curl_maprintf("%s4_request", provider0_low);
+ if(!request_type) {
+ goto fail;
+ }
+
+ credential_scope = curl_maprintf("%s/%s/%s/%s",
+ date, region, service, request_type);
+ if(!credential_scope) {
+ goto fail;
+ }
+
+ Curl_sha256it(sha_hash, (unsigned char *) canonical_request,
+ strlen(canonical_request));
+ sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
+
+ /*
+ * Google allow to use rsa key instead of HMAC, so this code might change
+ * In the furure, but for now we support only HMAC version
+ */
+ str_to_sign = curl_maprintf("%s4-HMAC-SHA256\n" /* Algorithm */
+ "%s\n" /* RequestDateTime */
+ "%s\n" /* CredentialScope */
+ "%s", /* HashedCanonicalRequest in hex */
+ provider0_up,
+ timestamp,
+ credential_scope,
+ sha_hex);
+ if(!str_to_sign) {
+ goto fail;
+ }
+
+ secret = curl_maprintf("%s4%s", provider0_up, passwd);
+ if(!secret) {
+ goto fail;
+ }
+
+ HMAC_SHA256(secret, strlen(secret),
+ date, strlen(date), tmp_sign0);
+ HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
+ region, strlen(region), tmp_sign1);
+ HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
+ service, strlen(service), tmp_sign0);
+ HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
+ request_type, strlen(request_type), tmp_sign1);
+ HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
+ str_to_sign, strlen(str_to_sign), tmp_sign0);
+
+ sha256_to_hex(sha_hex, tmp_sign0, sizeof(sha_hex));
+
+ auth_headers = curl_maprintf("Authorization: %s4-HMAC-SHA256 "
+ "Credential=%s/%s, "
+ "SignedHeaders=%s, "
+ "Signature=%s\r\n"
+ "X-%s-Date: %s\r\n",
+ provider0_up,
+ user,
+ credential_scope,
+ signed_headers,
+ sha_hex,
+ provider1_mid,
+ timestamp);
+ if(!auth_headers) {
+ goto fail;
+ }
+
+ Curl_safefree(data->state.aptr.userpwd);
+ data->state.aptr.userpwd = auth_headers;
+ data->state.authhost.done = TRUE;
+ ret = CURLE_OK;
+
+fail:
+ free(provider0_low);
+ free(provider0_up);
+ free(provider1_low);
+ free(provider1_mid);
+ free(region);
+ free(service);
+ free(canonical_headers);
+ free(signed_headers);
+ free(canonical_request);
+ free(request_type);
+ free(credential_scope);
+ free(str_to_sign);
+ free(secret);
+ return ret;
+}
+
+#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) */
diff -Naur curl-7.61.1.orig/lib/http_aws_sigv4.h curl-7.61.1/lib/http_aws_sigv4.h
--- curl-7.61.1.orig/lib/http_aws_sigv4.h 1970-01-01 01:00:00.000000000 +0100
+++ curl-7.61.1/lib/http_aws_sigv4.h 2025-12-02 13:31:38.992776500 +0100
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_HTTP_AWS_SIGV4_H
+#define HEADER_CURL_HTTP_AWS_SIGV4_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2024, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * AWS SigV4 Support - Backport to RHEL 8
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_AWS_SIGV4
+
+/* AWS SigV4 authentication function */
+CURLcode Curl_output_aws_sigv4(struct connectdata *conn, bool proxy);
+
+#else
+
+#define Curl_output_aws_sigv4(x,y) CURLE_NOT_BUILT_IN
+
+#endif /* USE_AWS_SIGV4 */
+
+#endif /* HEADER_CURL_HTTP_AWS_SIGV4_H */
diff -Naur curl-7.61.1.orig/lib/Makefile.inc curl-7.61.1/lib/Makefile.inc
--- curl-7.61.1.orig/lib/Makefile.inc 2025-12-02 13:31:37.675747831 +0100
+++ curl-7.61.1/lib/Makefile.inc 2025-12-02 13:31:40.198802751 +0100
@@ -54,7 +54,7 @@
curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \
x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \
mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \
- urlapi.c
+ urlapi.c http_aws_sigv4.c
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
@@ -74,7 +74,8 @@
curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \
- curl_path.h curl_ctype.h curl_range.h psl.h urlapi-int.h
+ curl_path.h curl_ctype.h curl_range.h psl.h urlapi-int.h \
+ http_aws_sigv4.h
LIB_RCFILES = libcurl.rc
diff -Naur curl-7.61.1.orig/lib/openldap.c curl-7.61.1/lib/openldap.c
--- curl-7.61.1.orig/lib/openldap.c 2025-12-02 13:31:37.681747962 +0100
+++ curl-7.61.1/lib/openldap.c 2025-12-02 13:31:41.175824017 +0100
@@ -79,8 +79,8 @@
static CURLcode ldap_setup_connection(struct connectdata *conn);
static CURLcode ldap_do(struct connectdata *conn, bool *done);
static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool);
-static CURLcode ldap_connect(struct connectdata *conn, bool *done);
-static CURLcode ldap_connecting(struct connectdata *conn, bool *done);
+static CURLcode oldap_connect(struct connectdata *conn, bool *done);
+static CURLcode ooldap_connecting(struct connectdata *conn, bool *done);
static CURLcode ldap_disconnect(struct connectdata *conn, bool dead);
static Curl_recv ldap_recv;
@@ -95,8 +95,8 @@
ldap_do, /* do_it */
ldap_done, /* done */
ZERO_NULL, /* do_more */
- ldap_connect, /* connect_it */
- ldap_connecting, /* connecting */
+ oldap_connect, /* connect_it */
+ ooldap_connecting, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
@@ -121,8 +121,8 @@
ldap_do, /* do_it */
ldap_done, /* done */
ZERO_NULL, /* do_more */
- ldap_connect, /* connect_it */
- ldap_connecting, /* connecting */
+ oldap_connect, /* connect_it */
+ ooldap_connecting, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
@@ -206,7 +206,7 @@
static Sockbuf_IO ldapsb_tls;
#endif
-static CURLcode ldap_connect(struct connectdata *conn, bool *done)
+static CURLcode oldap_connect(struct connectdata *conn, bool *done)
{
ldapconninfo *li = conn->proto.generic;
struct Curl_easy *data = conn->data;
@@ -253,7 +253,7 @@
return CURLE_OK;
}
-static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
+static CURLcode ooldap_connecting(struct connectdata *conn, bool *done)
{
ldapconninfo *li = conn->proto.generic;
struct Curl_easy *data = conn->data;
diff -Naur curl-7.61.1.orig/lib/http.c curl-7.61.1/lib/http.c
--- curl-7.61.1.orig/lib/http.c 2025-12-05 12:00:00.000000000 +0100
+++ curl-7.61.1/lib/http.c 2025-12-05 12:30:00.000000000 +0100
@@ -60,6 +60,7 @@
#include "http_ntlm.h"
#include "curl_ntlm_wb.h"
#include "http_negotiate.h"
+#include "http_aws_sigv4.h"
#include "url.h"
#include "share.h"
#include "hostip.h"
@@ -362,6 +363,8 @@
pick->picked = CURLAUTH_NTLM_WB;
else if(avail & CURLAUTH_BASIC)
pick->picked = CURLAUTH_BASIC;
+ else if(avail & CURLAUTH_AWS_SIGV4)
+ pick->picked = CURLAUTH_AWS_SIGV4;
else {
pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
picked = FALSE;
@@ -682,6 +685,21 @@
functions work that way */
authstatus->done = TRUE;
}
+ if(authstatus->picked == CURLAUTH_AWS_SIGV4) {
+ /* AWS SigV4 */
+ if((!proxy && data->set.str[STRING_AWS_SIGV4] &&
+ !Curl_checkheaders(conn, "Authorization:"))) {
+ auth = "AWS_SIGV4";
+ result = Curl_output_aws_sigv4(conn, FALSE);
+ if(result)
+ return result;
+ }
+
+ /* NOTE: this function should set 'done' TRUE, as the other auth
+ functions work that way */
+ authstatus->done = TRUE;
+ }
+
if(auth) {
infof(data, "%s auth using %s with user '%s'\n",
diff -Naur curl-7.61.1.orig/include/curl/curl.h curl-7.61.1/include/curl/curl.h
--- curl-7.61.1.orig/include/curl/curl.h 2018-07-11 07:17:00.000000000 +0200
+++ curl-7.61.1/include/curl/curl.h 2025-12-10 14:00:00.000000000 +0100
@@ -710,6 +710,7 @@
#define CURLAUTH_NTLM (((unsigned long)1)<<3)
#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
+#define CURLAUTH_AWS_SIGV4 (((unsigned long)1)<<7)
#define CURLAUTH_BEARER (((unsigned long)1)<<6)
#define CURLAUTH_ONLY (((unsigned long)1)<<31)
#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
@@ -1856,6 +1857,9 @@
/* Disallow specifying username/login in URL. */
CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278),
+ /* AWS HTTP V4 Signature */
+ CINIT(AWS_SIGV4, STRINGPOINT, 279),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
--- curl-7.61.1.orig/lib/urldata.h 2018-07-11 07:17:00.000000000 +0200
+++ curl-7.61.1/lib/urldata.h 2025-12-09 00:00:00.000000000 +0100
@@ -1414,6 +1414,7 @@
STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth <password> */
#endif
STRING_BEARER, /* <bearer>, if used */
+ STRING_AWS_SIGV4, /* <aws-sigv4>, if used */
#ifdef USE_UNIX_SOCKETS
STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */
#endif
diff -Naur curl-7.61.1.orig/lib/http_aws_sigv4.c curl-7.61.1/lib/http_aws_sigv4.c
--- curl-7.61.1.orig/lib/http_aws_sigv4.c 2025-12-09 07:00:00.000000000 +0100
+++ curl-7.61.1/lib/http_aws_sigv4.c 2025-12-09 14:30:00.000000000 +0100
@@ -192,8 +192,8 @@
char *request_type = NULL;
char *credential_scope = NULL;
char *str_to_sign = NULL;
- const char *user = data->state.aptr.user ? data->state.aptr.user : "";
- const char *passwd = data->state.aptr.passwd ? data->state.aptr.passwd : "";
+ const char *user = conn->user ? conn->user : "";
+ const char *passwd = conn->passwd ? conn->passwd : "";
char *secret = NULL;
unsigned char tmp_sign0[32] = {0};
unsigned char tmp_sign1[32] = {0};
@@ -399,7 +399,7 @@
method = "OPTIONS";
break;
case HTTPREQ_CUSTOM:
- method = data->set.customrequest;
+ method = data->set.str[STRING_CUSTOMREQUEST];
break;
default:
method = "GET";
@@ -406,6 +406,16 @@
break;
}
+ /* Extract query string from path if present */
+ const char *query_str = NULL;
+ char *question_mark = strchr(data->state.path, '?');
+ if(question_mark) {
+ query_str = question_mark + 1;
+ }
+ else {
+ query_str = "";
+ }
+
canonical_request =
curl_maprintf("%s\n" /* HTTPRequestMethod */
"%s\n" /* CanonicalURI */
@@ -414,8 +424,8 @@
"%s\n" /* SignedHeaders */
"%s", /* HashedRequestPayload in hex */
method,
- data->state.up.path,
- data->state.up.query ? data->state.up.query : "",
+ data->state.path,
+ query_str,
canonical_headers,
signed_headers,
sha_hex);
@@ -488,8 +498,8 @@
goto fail;
}
- Curl_safefree(data->state.aptr.userpwd);
- data->state.aptr.userpwd = auth_headers;
+ Curl_safefree(conn->allocptr.userpwd);
+ conn->allocptr.userpwd = auth_headers;
data->state.authhost.done = TRUE;
ret = CURLE_OK;
@@ -509,3 +519,5 @@
free(secret);
return ret;
}
+
+#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) */
diff -Naur a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
--- a/docs/libcurl/symbols-in-versions 2018-09-04 22:48:37.000000000 +0200
+++ b/docs/libcurl/symbols-in-versions 2025-12-10 14:23:34.178991689 +0100
@@ -15,6 +15,7 @@
CURLAUTH_ANY 7.10.6
CURLAUTH_ANYSAFE 7.10.6
CURLAUTH_BASIC 7.10.6
+CURLAUTH_AWS_SIGV4 7.61.1
CURLAUTH_BEARER 7.61.0
CURLAUTH_DIGEST 7.10.6
CURLAUTH_DIGEST_IE 7.19.3
@@ -344,6 +345,7 @@
CURLOPT_ACCEPT_ENCODING 7.21.6
CURLOPT_ADDRESS_SCOPE 7.19.0
CURLOPT_APPEND 7.17.0
+CURLOPT_AWS_SIGV4 7.61.1
CURLOPT_AUTOREFERER 7.1
CURLOPT_BUFFERSIZE 7.10
CURLOPT_CAINFO 7.4.2
diff -Naur a/lib/setopt.c b/lib/setopt.c
--- a/lib/setopt.c 2025-12-02 13:31:37.682747984 +0100
+++ b/lib/setopt.c 2025-12-10 12:46:02.532544111 +0100
@@ -618,6 +618,20 @@
data->set.httpreq = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
break;
+
+ case CURLOPT_AWS_SIGV4:
+ /*
+ * String that is merged to some authentication
+ * parameters are used by the algorithm.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_AWS_SIGV4],
+ va_arg(param, char *));
+ /*
+ * Basic been set by default it need to be unset here
+ */
+ if(data->set.str[STRING_AWS_SIGV4])
+ data->set.httpauth = CURLAUTH_AWS_SIGV4;
+ break;
#endif /* CURL_DISABLE_HTTP */
case CURLOPT_MIMEPOST:
diff -Naur a/src/tool_cfgable.c b/src/tool_cfgable.c
--- a/src/tool_cfgable.c 2025-12-02 13:31:37.707011250 +0100
+++ b/src/tool_cfgable.c 2025-12-10 12:33:54.247212425 +0100
@@ -130,6 +130,7 @@
Curl_safefree(config->krblevel);
Curl_safefree(config->oauth_bearer);
+ Curl_safefree(config->aws_sigv4);
Curl_safefree(config->unix_socket_path);
Curl_safefree(config->writeout);
diff -Naur a/src/tool_cfgable.h b/src/tool_cfgable.h
--- a/src/tool_cfgable.h 2025-12-02 13:31:37.707011250 +0100
+++ b/src/tool_cfgable.h 2025-12-10 12:33:38.542315604 +0100
@@ -240,6 +240,7 @@
bool test_event_based;
#endif
char *oauth_bearer; /* OAuth 2.0 bearer token */
+ char *aws_sigv4; /* AWS Signature Version 4 */
bool nonpn; /* enable/disable TLS NPN extension */
bool noalpn; /* enable/disable TLS ALPN extension */
char *unix_socket_path; /* path to Unix domain socket */
diff -Naur a/src/tool_getparam.c b/src/tool_getparam.c
--- a/src/tool_getparam.c 2025-12-02 13:31:37.711748615 +0100
+++ b/src/tool_getparam.c 2025-12-10 12:36:24.374195746 +0100
@@ -79,6 +79,7 @@
{"*a", "random-file", ARG_FILENAME},
{"*b", "egd-file", ARG_STRING},
{"*B", "oauth2-bearer", ARG_STRING},
+ {"*V", "aws-sigv4", ARG_STRING},
{"*c", "connect-timeout", ARG_STRING},
{"*d", "ciphers", ARG_STRING},
{"*D", "dns-interface", ARG_STRING},
@@ -813,6 +814,10 @@
config->disable_eprt = toggle;
break;
case 'Z': /* --eprt */
+ case 'V': /* --aws-sigv4 */
+ GetStr(&config->aws_sigv4, nextarg);
+ config->authtype |= CURLAUTH_AWS_SIGV4;
+ break;
config->disable_eprt = (!toggle)?TRUE:FALSE;
break;
case '~': /* --xattr */
diff -Naur a/src/tool_help.c b/src/tool_help.c
--- a/src/tool_help.c 2025-12-02 13:31:37.709748572 +0100
+++ b/src/tool_help.c 2025-12-10 12:39:33.200888878 +0100
@@ -52,6 +52,8 @@
"Pick any authentication method"},
{"-a, --append",
"Append to target file when uploading"},
+ {" --aws-sigv4 <provider1[:provider2[:region[:service]]]>",
+ "Use AWS V4 signature authentication"},
{" --basic",
"Use HTTP Basic Authentication"},
{" --cacert <file>",
diff -Naur a/src/tool_operate.c b/src/tool_operate.c
--- a/src/tool_operate.c 2025-12-02 13:31:37.711748615 +0100
+++ b/src/tool_operate.c 2025-12-10 12:40:10.466140413 +0100
@@ -1136,6 +1136,8 @@
my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
config->proxy_key_type);
+ my_setopt_str(curl, CURLOPT_AWS_SIGV4,
+ config->aws_sigv4);
if(config->insecure_ok) {
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
diff -Naur a/docs/curl.1 b/docs/curl.1
--- a/docs/curl.1 2018-09-05 08:15:48.000000000 +0200
+++ b/docs/curl.1 2025-12-10 12:00:00.000000000 +0100
@@ -163,6 +163,12 @@
See also \fI--proxy-anyauth\fP and \fI--basic\fP and \fI--digest\fP.
.IP "-a, --append"
(FTP SFTP) When used in an upload, this makes curl append to the target file instead of
+.IP "--aws-sigv4 <service:region>"
+(HTTP) Use AWS Signature Version 4 authentication for the specified service and region.
+The service is the AWS service name (such as s3) and the region is the geographical
+AWS region (such as us-east-1). The credentials must be provided via \fI-u, --user\fP.
+
+If this option is used several times, the last one will be used.
overwriting it. If the remote file doesn't exist, it will be created. Note
that this flag is ignored by some SFTP servers (including OpenSSH).
.IP "--basic"
diff -Naur a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
--- a/docs/libcurl/curl_easy_setopt.3 2018-09-05 08:15:48.000000000 +0200
+++ b/docs/libcurl/curl_easy_setopt.3 2025-12-10 12:00:00.000000000 +0100
@@ -262,6 +262,8 @@
.IP CURLOPT_DISALLOW_USERNAME_IN_URL
Don't allow username in URL. See \fICURLOPT_DISALLOW_USERNAME_IN_URL(3)\fP
.SH HTTP OPTIONS
+.IP CURLOPT_AWS_SIGV4
+Set AWS Signature Version 4 authentication. See \fICURLOPT_AWS_SIGV4(3)\fP
.IP CURLOPT_AUTOREFERER
Automatically set Referer: header. See \fICURLOPT_AUTOREFERER(3)\fP
.IP CURLOPT_ACCEPT_ENCODING
diff -Naur a/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3 b/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3
--- a/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3 1970-01-01 00:00:00.000000000 +0000
+++ b/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3 2025-12-10 12:00:00.000000000 +0100
@@ -0,0 +1,78 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___\|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2018, 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.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_AWS_SIGV4 3 "December 10, 2025" "libcurl 7.61.1" "curl_easy_setopt options"
+
+.SH NAME
+CURLOPT_AWS_SIGV4 \- set AWS Signature Version 4 authentication
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_AWS_SIGV4, char *param);
+.SH DESCRIPTION
+Pass a char * that is the collection of service and region parameters that
+are used to authorize and sign requests.
+
+The format is:
+.B service:region
+where the
+.B service
+is the AWS service (for example,
+.B s3
+) and the
+.B region
+is the geographical AWS region (for example,
+.B us-east-1
+).
+
+When this option is set, the HTTP request will be signed using AWS Signature
+Version 4. The request is signed using the credentials provided in the
+\fICURLOPT_USERNAME(3)\fP and \fICURLOPT_PASSWORD(3)\fP options, which
+correspond to the AWS Access Key ID and Secret Access Key, respectively.
+
+The application does not have to keep the string around after setting this
+option.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+HTTP
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "https://s3.us-east-1.amazonaws.com/bucket/file");
+ curl_easy_setopt(curl, CURLOPT_AWS_SIGV4, "s3:us-east-1");
+ curl_easy_setopt(curl, CURLOPT_USERNAME, "AKIAIOSFODNN7EXAMPLE");
+ curl_easy_setopt(curl, CURLOPT_PASSWORD,
+ "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY");
+ curl_easy_perform(curl);
+}
+.SH AVAILABILITY
+Added in 7.61.1
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_HTTPAUTH "(3), "
+.BR CURLOPT_USERNAME "(3), "
+.BR CURLOPT_PASSWORD "(3), "

View File

@ -1,7 +1,7 @@
Summary: A utility for getting files from remote servers (FTP, HTTP, and others)
Name: curl
Version: 7.61.1
Release: 34%{?dist}
Release: 34%{?dist}.10
License: MIT
Source: https://curl.haxx.se/download/%{name}-%{version}.tar.xz
@ -175,6 +175,33 @@ Patch59: 0059-curl-7.61.1-CVE-2023-46218.patch
# lowercase headernames
Patch60: 0060-curl-7.61.1-lowercase-headernames.patch
# provide common cleanup method for push headers (CVE-2024-2398)
Patch61: 0061-curl-7.61.1-CVE-2024-2398.patch
# asyn-thread: create a socketpair to wait on
Patch62: 0062-curl-7.61.1-socketpair-to-wait-on.patch
# fix crash, when talking to a NTLM proxy in FIPS mode
Patch63: 0063-curl-7.61.1-native-md5.patch
# asyn-thread: issue CURL_POLL_REMOVE before closing socket
Patch64: 0064-curl-7.61.1-EBADF.patch
# libssh: Fix matching user-specified MD5 hex key
Patch65: 0065-md5-hex-key.patch
# crypto: ensure crypto initialization works
Patch66: 0066-crypto-initialization.patch
# NTLM: force the connection to HTTP/1.1
Patch67: 0067-curl-7.61.1-ntlm-force-http-1-1.patch
# cookie: don't treat the leading slash as trailing (CVE-2025-9086)
Patch68: 0068-curl-7.61.1-CVE-2025-9086.patch
# AWS Signature Version 4 authentication support
Patch69: 0069-curl-7.61.1-aws-sigv4.patch
# patch making libcurl multilib ready
Patch101: 0101-curl-7.32.0-multilib.patch
@ -335,79 +362,88 @@ be installed.
%setup -q
# upstream patches
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch -P 1 -p1
%patch -P 2 -p1
%patch -P 3 -p1
git init
git apply %{PATCH4}
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch14 -p1
%patch -P 5 -p1
%patch -P 6 -p1
%patch -P 7 -p1
%patch -P 8 -p1
%patch -P 9 -p1
%patch -P 10 -p1
%patch -P 11 -p1
%patch -P 14 -p1
# Fedora patches
%patch101 -p1
%patch102 -p1
%patch103 -p1
%patch104 -p1
%patch -P 101 -p1
%patch -P 102 -p1
%patch -P 103 -p1
%patch -P 104 -p1
# use different port range for 32bit and 64bit builds, thus make it possible
# to run both the builds in parallel on the same machine
%patch105 -p1
%patch -P 105 -p1
sed -e 's|%%HTTPPORT|%{?__isa_bits}90|g' -i tests/data/test1448
# upstream patches
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1
%patch34 -p1
%patch35 -p1
%patch36 -p1
%patch37 -p1
%patch -P 17 -p1
%patch -P 18 -p1
%patch -P 19 -p1
%patch -P 20 -p1
%patch -P 21 -p1
%patch -P 22 -p1
%patch -P 23 -p1
%patch -P 24 -p1
%patch -P 25 -p1
%patch -P 26 -p1
%patch -P 27 -p1
%patch -P 28 -p1
%patch -P 29 -p1
%patch -P 30 -p1
%patch -P 31 -p1
%patch -P 32 -p1
%patch -P 33 -p1
%patch -P 34 -p1
%patch -P 35 -p1
%patch -P 36 -p1
%patch -P 37 -p1
%patch38 -p1
%patch -P 38 -p1
sed -e 's|:8992/|:%{?__isa_bits}92/|g' -i tests/data/test97{3..6}
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch43 -p1
%patch44 -p1
%patch45 -p1
%patch46 -p1
%patch47 -p1
%patch48 -p1
%patch49 -p1
%patch50 -p1
%patch51 -p1
%patch -P 39 -p1
%patch -P 40 -p1
%patch -P 41 -p1
%patch -P 42 -p1
%patch -P 43 -p1
%patch -P 44 -p1
%patch -P 45 -p1
%patch -P 46 -p1
%patch -P 47 -p1
%patch -P 48 -p1
%patch -P 49 -p1
%patch -P 50 -p1
%patch -P 51 -p1
git apply %{PATCH52}
%patch53 -p1
%patch54 -p1
%patch55 -p1
%patch56 -p1
%patch57 -p1
%patch58 -p1
%patch59 -p1
%patch60 -p1
%patch -P 53 -p1
%patch -P 54 -p1
%patch -P 55 -p1
%patch -P 56 -p1
%patch -P 57 -p1
%patch -P 58 -p1
%patch -P 59 -p1
%patch -P 60 -p1
%patch -P 61 -p1
%patch -P 62 -p1
%patch -P 63 -p1
%patch -P 64 -p1
%patch -P 65 -p1
%patch -P 66 -p1
%patch -P 67 -p1
%patch -P 68 -p1
%patch -P 69 -p1
# make tests/*.py use Python 3
sed -e '1 s|^#!/.*python|#!%{__python3}|' -i tests/*.py
@ -570,6 +606,39 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la
%{_libdir}/libcurl.so.4.[0-9].[0-9].minimal
%changelog
* Wed Dec 03 2025 Jacek Migacz <jmigacz@redhat.com> - 7.61.1-34.el8_10.10
- AWS Signature Version 4 authentication support (RHEL-116183)
* Fri Oct 24 2025 Jacek Migacz <jmigacz@redhat.com> - 7.61.1-34.el8_10.9
- cookie: don't treat the leading slash as trailing (CVE-2025-9086)
Resolves: RHEL-121655
* Mon Jul 21 2025 Jacek Migacz <jmigacz@redhat.com> - 7.61.1-34.el8_10.8
- NTLM: force the connection to HTTP/1.1 (RHEL-73788)
* Wed Jul 09 2025 Jacek Migacz <jmigacz@redhat.com> - 7.61.1-34.el8_10.7
* crypto: ensure crypto initialization works (RHEL-102601)
* Thu May 29 2025 Carlos Santos <casantos@redhat.com> - 7.61.1-34.el8_10.6
- libssh: Fix matching user-specified MD5 hex key (RHEL-94574)
* Wed Jan 08 2025 Jacek Migacz <jmigacz@redhat.com> - 7.61.1-34.el8_10.5
- asyn-thread: fix EBADF regression (RHEL-85602)
* Wed Jan 08 2025 Jacek Migacz <jmigacz@redhat.com> - 7.61.1-34.el8_10.4
- make up incomplete patch for host name wildcard checking (RHEL-5680)
- asyn-thread: issue CURL_POLL_REMOVE before closing socket (RHEL-85602)
* Wed Oct 30 2024 Jacek Migacz <jmigacz@redhat.com> - 7.61.1-34.el8_10.3
- asyn-thread: create a socketpair to wait on (RHEL-34906)
- fix crash, when talking to a NTLM proxy in FIPS mode (RHEL-32641)
* Wed Aug 14 2024 Jacek Migacz <jmigacz@redhat.com> - 7.61.1-34.el8_10.2
- provide common cleanup method for push headers (CVE-2024-2398)
* Tue Jun 25 2024 Jacek Migacz <jmigacz@redhat.com> - 7.61.1-34.el8_10.1
- fix incorrect backport of bz2229800 (RHEL-44684)
* Tue Sep 19 2023 Jacek Migacz <jmigacz@redhat.com> - 7.61.1-34
- when keyboard-interactive auth fails, try password (#2229800)
- cap SFTP packet size sent (RHEL-5311)