From 682eba024d42038e36fc7a8b6712c3f091655c8c Mon Sep 17 00:00:00 2001
From: Peridot Bot <rockyautomation@rockylinux.org>
Date: Wed, 1 Nov 2023 01:04:53 +0000
Subject: [PATCH] import curl-7.76.1-26.el9

---
 .curl.checksum                                |    1 +
 .curl.metadata                                |    2 +-
 SOURCES/0025-curl-7.76.1-CVE-2023-27533.patch |   59 +
 SOURCES/0026-curl-7.76.1-CVE-2023-27534.patch | 1060 +++++++++++++++++
 SOURCES/0027-curl-7.76.1-CVE-2023-27535.patch |  230 ++++
 SOURCES/0028-curl-7.76.1-CVE-2023-27536.patch |   54 +
 SOURCES/0029-curl-7.76.1-CVE-2023-27538.patch |   30 +
 SOURCES/0030-curl-7.76.1-CVE-2023-28322.patch |  420 +++++++
 SOURCES/0031-curl-7.76.1-CVE-2023-28321.patch |  304 +++++
 SPECS/curl.spec                               |   44 +-
 10 files changed, 2202 insertions(+), 2 deletions(-)
 create mode 100644 .curl.checksum
 create mode 100644 SOURCES/0025-curl-7.76.1-CVE-2023-27533.patch
 create mode 100644 SOURCES/0026-curl-7.76.1-CVE-2023-27534.patch
 create mode 100644 SOURCES/0027-curl-7.76.1-CVE-2023-27535.patch
 create mode 100644 SOURCES/0028-curl-7.76.1-CVE-2023-27536.patch
 create mode 100644 SOURCES/0029-curl-7.76.1-CVE-2023-27538.patch
 create mode 100644 SOURCES/0030-curl-7.76.1-CVE-2023-28322.patch
 create mode 100644 SOURCES/0031-curl-7.76.1-CVE-2023-28321.patch

diff --git a/.curl.checksum b/.curl.checksum
new file mode 100644
index 0000000..cc806fb
--- /dev/null
+++ b/.curl.checksum
@@ -0,0 +1 @@
+a50c2a09321bc05b955a258e4c74368344384576891dd5905cf0806d7ed98e34
diff --git a/.curl.metadata b/.curl.metadata
index c2a3f04..8ad7538 100644
--- a/.curl.metadata
+++ b/.curl.metadata
@@ -1 +1 @@
-d38ab79ef7a6d92df91ca8dfcf9a5eaf7e25b725 SOURCES/curl-7.76.1.tar.xz
+64bb5288c39f0840c07d077e30d9052e1cbb9fa6c2dc52523824cc859e679145 SOURCES/curl-7.76.1.tar.xz
diff --git a/SOURCES/0025-curl-7.76.1-CVE-2023-27533.patch b/SOURCES/0025-curl-7.76.1-CVE-2023-27533.patch
new file mode 100644
index 0000000..591c1cd
--- /dev/null
+++ b/SOURCES/0025-curl-7.76.1-CVE-2023-27533.patch
@@ -0,0 +1,59 @@
+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
+
diff --git a/SOURCES/0026-curl-7.76.1-CVE-2023-27534.patch b/SOURCES/0026-curl-7.76.1-CVE-2023-27534.patch
new file mode 100644
index 0000000..f9cff95
--- /dev/null
+++ b/SOURCES/0026-curl-7.76.1-CVE-2023-27534.patch
@@ -0,0 +1,1060 @@
+From 5085070dd92fe08f1de2c751fe54f52203ad3160 Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Sun, 16 Oct 2022 18:09:14 +0200
+Subject: [PATCH 1/4] curl_path: return error if given a NULL homedir
+
+Closes #9740
+
+Upstream-commit: 025bad1182ff87facbddd280dd07a0fc26b99f45
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ lib/curl_path.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/lib/curl_path.c b/lib/curl_path.c
+index 6100d77..35ea5b3 100644
+--- a/lib/curl_path.c
++++ b/lib/curl_path.c
+@@ -120,7 +120,8 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
+   bool relativePath = false;
+   static const char WHITESPACE[] = " \t\r\n";
+ 
+-  if(!*cp) {
++  DEBUGASSERT(homedir);
++  if(!*cp || !homedir) {
+     *cpp = NULL;
+     *path = NULL;
+     return CURLE_QUOTE_ERROR;
+-- 
+2.39.2
+
+
+From 69d0f1ba04c9c57d04f8e546e663ef9e9dba4542 Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Sun, 30 Oct 2022 17:38:16 +0100
+Subject: [PATCH 2/4] style: use space after comment start and before comment
+ end
+
+/* like this */
+
+/*not this*/
+
+checksrc is updated accordingly
+
+Closes #9828
+
+Upstream-commit: 52cc4a85fd7e5265ba8ff0f08adf4858f6773a11
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ docs/examples/ephiperfifo.c   |   4 +-
+ docs/examples/usercertinmem.c |   4 +-
+ include/curl/curl.h           |  10 +--
+ include/curl/typecheck-gcc.h  |   2 +-
+ lib/curl_path.c               |   4 -
+ lib/curl_rtmp.c               |  12 +--
+ lib/curl_setup.h              |   2 +-
+ lib/dict.c                    |   2 +-
+ lib/file.c                    |   2 +-
+ lib/ftp.c                     |   2 +-
+ lib/gopher.c                  |   2 +-
+ lib/http.c                    |   4 +-
+ lib/http_chunks.c             |   2 +-
+ lib/rtsp.c                    |   4 +-
+ lib/rtsp.h                    |   2 +-
+ lib/telnet.c                  |   2 +-
+ lib/urldata.h                 |   4 +-
+ lib/vauth/digest.c            |   4 +-
+ lib/vauth/krb5_sspi.c         |   2 +-
+ lib/vssh/libssh2.c            |   4 +-
+ lib/vtls/schannel.c           |   4 +-
+ lib/vtls/sectransp.c          |   2 -
+ src/tool_cfgable.h            |   5 +-
+ src/tool_getparam.c           |   4 +-
+ tests/libtest/lib1525.c       |   2 +-
+ tests/libtest/lib1526.c       |   2 +-
+ tests/libtest/lib1527.c       |   2 +-
+ tests/libtest/lib1528.c       |   2 +-
+ tests/libtest/lib1591.c       |   2 +-
+ tests/libtest/lib506.c        |   2 +-
+ tests/libtest/lib557.c        |   2 +-
+ tests/libtest/lib586.c        |   2 +-
+ tests/libtest/stub_gssapi.h   | 160 +++++++++++++++++-----------------
+ tests/server/tftp.h           |   2 +-
+ tests/server/util.c           |   2 +-
+ tests/unit/unit1300.c         |   4 +-
+ 36 files changed, 132 insertions(+), 141 deletions(-)
+
+diff --git a/docs/examples/ephiperfifo.c b/docs/examples/ephiperfifo.c
+index 11761b9..75336a4 100644
+--- a/docs/examples/ephiperfifo.c
++++ b/docs/examples/ephiperfifo.c
+@@ -164,7 +164,7 @@ static int multi_timer_cb(CURLM *multi, long timeout_ms, GlobalInfo *g)
+     memset(&its, 0, sizeof(struct itimerspec));
+   }
+ 
+-  timerfd_settime(g->tfd, /*flags=*/0, &its, NULL);
++  timerfd_settime(g->tfd, /* flags= */0, &its, NULL);
+   return 0;
+ }
+ 
+@@ -195,7 +195,7 @@ static void check_multi_info(GlobalInfo *g)
+   }
+ }
+ 
+-/* Called by libevent when we get action on a multi socket filedescriptor*/
++/* Called by libevent when we get action on a multi socket filedescriptor */
+ static void event_cb(GlobalInfo *g, int fd, int revents)
+ {
+   CURLMcode rc;
+diff --git a/docs/examples/usercertinmem.c b/docs/examples/usercertinmem.c
+index 35218bd..79d3aef 100644
+--- a/docs/examples/usercertinmem.c
++++ b/docs/examples/usercertinmem.c
+@@ -92,7 +92,7 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
+     "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"\
+     "-----END CERTIFICATE-----\n";
+ 
+-/*replace the XXX with the actual RSA key*/
++/* replace the XXX with the actual RSA key */
+   const char *mykey =
+     "-----BEGIN RSA PRIVATE KEY-----\n"\
+     "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
+@@ -190,7 +190,7 @@ int main(void)
+   curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
+ 
+   /* both VERIFYPEER and VERIFYHOST are set to 0 in this case because there is
+-     no CA certificate*/
++     no CA certificate */
+ 
+   curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 0L);
+   curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, 0L);
+diff --git a/include/curl/curl.h b/include/curl/curl.h
+index bed8068..680303b 100644
+--- a/include/curl/curl.h
++++ b/include/curl/curl.h
+@@ -371,7 +371,7 @@ typedef int (*curl_seek_callback)(void *instream,
+ #define CURL_READFUNC_PAUSE 0x10000001
+ 
+ /* Return code for when the trailing headers' callback has terminated
+-   without any errors*/
++   without any errors */
+ #define CURL_TRAILERFUNC_OK 0
+ /* Return code for when was an error in the trailing header's list and we
+   want to abort the request */
+@@ -453,7 +453,7 @@ typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
+ #define CURL_DID_MEMORY_FUNC_TYPEDEFS
+ #endif
+ 
+-/* the kind of data that is passed to information_callback*/
++/* the kind of data that is passed to information_callback */
+ typedef enum {
+   CURLINFO_TEXT = 0,
+   CURLINFO_HEADER_IN,    /* 1 */
+@@ -689,7 +689,7 @@ typedef enum {
+ #define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
+ #define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
+ 
+-#endif /*!CURL_NO_OLDIES*/
++#endif /* !CURL_NO_OLDIES */
+ 
+ /*
+  * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was
+@@ -834,7 +834,7 @@ enum curl_khstat {
+   CURLKHSTAT_DEFER,  /* do not accept it, but we can't answer right now so
+                         this causes a CURLE_DEFER error but otherwise the
+                         connection will be left intact etc */
+-  CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key*/
++  CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key */
+   CURLKHSTAT_LAST    /* not for use, only a marker for last-in-list */
+ };
+ 
+@@ -908,7 +908,7 @@ typedef enum {
+ #define CURLFTPSSL_ALL CURLUSESSL_ALL
+ #define CURLFTPSSL_LAST CURLUSESSL_LAST
+ #define curl_ftpssl curl_usessl
+-#endif /*!CURL_NO_OLDIES*/
++#endif /* !CURL_NO_OLDIES */
+ 
+ /* parameter for the CURLOPT_FTP_SSL_CCC option */
+ typedef enum {
+diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h
+index 34d0267..9e6fafd 100644
+--- a/include/curl/typecheck-gcc.h
++++ b/include/curl/typecheck-gcc.h
+@@ -429,7 +429,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
+   (CURLINFO_OFF_T < (info))
+ 
+ 
+-/* typecheck helpers -- check whether given expression has requested type*/
++/* typecheck helpers -- check whether given expression has requested type */
+ 
+ /* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros,
+  * otherwise define a new macro. Search for __builtin_types_compatible_p
+diff --git a/lib/curl_path.c b/lib/curl_path.c
+index 35ea5b3..649da7d 100644
+--- a/lib/curl_path.c
++++ b/lib/curl_path.c
+@@ -146,15 +146,12 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
+         break;
+       }
+       if(cp[i] == '\0') {  /* End of string */
+-        /*error("Unterminated quote");*/
+         goto fail;
+       }
+       if(cp[i] == '\\') {  /* Escaped characters */
+         i++;
+         if(cp[i] != '\'' && cp[i] != '\"' &&
+             cp[i] != '\\') {
+-          /*error("Bad escaped character '\\%c'",
+-              cp[i]);*/
+           goto fail;
+         }
+       }
+@@ -162,7 +159,6 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
+     }
+ 
+     if(j == 0) {
+-      /*error("Empty quotes");*/
+       goto fail;
+     }
+     *cpp = cp + i + strspn(cp + i, WHITESPACE);
+diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c
+index 2fa0267..8caba76 100644
+--- a/lib/curl_rtmp.c
++++ b/lib/curl_rtmp.c
+@@ -83,7 +83,7 @@ const struct Curl_handler Curl_handler_rtmp = {
+   PORT_RTMP,                            /* defport */
+   CURLPROTO_RTMP,                       /* protocol */
+   CURLPROTO_RTMP,                       /* family */
+-  PROTOPT_NONE                          /* flags*/
++  PROTOPT_NONE                          /* flags */
+ };
+ 
+ const struct Curl_handler Curl_handler_rtmpt = {
+@@ -106,7 +106,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
+   PORT_RTMPT,                           /* defport */
+   CURLPROTO_RTMPT,                      /* protocol */
+   CURLPROTO_RTMPT,                      /* family */
+-  PROTOPT_NONE                          /* flags*/
++  PROTOPT_NONE                          /* flags */
+ };
+ 
+ const struct Curl_handler Curl_handler_rtmpe = {
+@@ -129,7 +129,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
+   PORT_RTMP,                            /* defport */
+   CURLPROTO_RTMPE,                      /* protocol */
+   CURLPROTO_RTMPE,                      /* family */
+-  PROTOPT_NONE                          /* flags*/
++  PROTOPT_NONE                          /* flags */
+ };
+ 
+ const struct Curl_handler Curl_handler_rtmpte = {
+@@ -152,7 +152,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
+   PORT_RTMPT,                           /* defport */
+   CURLPROTO_RTMPTE,                     /* protocol */
+   CURLPROTO_RTMPTE,                     /* family */
+-  PROTOPT_NONE                          /* flags*/
++  PROTOPT_NONE                          /* flags */
+ };
+ 
+ const struct Curl_handler Curl_handler_rtmps = {
+@@ -175,7 +175,7 @@ const struct Curl_handler Curl_handler_rtmps = {
+   PORT_RTMPS,                           /* defport */
+   CURLPROTO_RTMPS,                      /* protocol */
+   CURLPROTO_RTMP,                       /* family */
+-  PROTOPT_NONE                          /* flags*/
++  PROTOPT_NONE                          /* flags */
+ };
+ 
+ const struct Curl_handler Curl_handler_rtmpts = {
+@@ -198,7 +198,7 @@ const struct Curl_handler Curl_handler_rtmpts = {
+   PORT_RTMPS,                           /* defport */
+   CURLPROTO_RTMPTS,                     /* protocol */
+   CURLPROTO_RTMPT,                      /* family */
+-  PROTOPT_NONE                          /* flags*/
++  PROTOPT_NONE                          /* flags */
+ };
+ 
+ static CURLcode rtmp_setup_connection(struct Curl_easy *data,
+diff --git a/lib/curl_setup.h b/lib/curl_setup.h
+index cf1c26a..1d81141 100644
+--- a/lib/curl_setup.h
++++ b/lib/curl_setup.h
+@@ -680,7 +680,7 @@ int netware_init(void);
+ #  define UNUSED_PARAM __attribute__((__unused__))
+ #  define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+ #else
+-#  define UNUSED_PARAM /*NOTHING*/
++#  define UNUSED_PARAM /* NOTHING */
+ #  define WARN_UNUSED_RESULT
+ #endif
+ 
+diff --git a/lib/dict.c b/lib/dict.c
+index 7b27f79..0ccfc0e 100644
+--- a/lib/dict.c
++++ b/lib/dict.c
+@@ -321,4 +321,4 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
+ 
+   return CURLE_OK;
+ }
+-#endif /*CURL_DISABLE_DICT*/
++#endif /* CURL_DISABLE_DICT */
+diff --git a/lib/file.c b/lib/file.c
+index 10d8f05..8b67c12 100644
+--- a/lib/file.c
++++ b/lib/file.c
+@@ -311,7 +311,7 @@ static CURLcode file_upload(struct Curl_easy *data)
+ 
+     nread = readcount;
+ 
+-    /*skip bytes before resume point*/
++    /* skip bytes before resume point */
+     if(data->state.resume_from) {
+       if((curl_off_t)nread <= data->state.resume_from) {
+         data->state.resume_from -= nread;
+diff --git a/lib/ftp.c b/lib/ftp.c
+index e920138..6043dea 100644
+--- a/lib/ftp.c
++++ b/lib/ftp.c
+@@ -1166,7 +1166,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
+     port++;
+   }
+ 
+-  /* maybe all ports were in use already*/
++  /* maybe all ports were in use already */
+   if(port > port_max) {
+     failf(data, "bind() failed, we ran out of ports!");
+     Curl_closesocket(data, conn, portsock);
+diff --git a/lib/gopher.c b/lib/gopher.c
+index f61232f..bdd6420 100644
+--- a/lib/gopher.c
++++ b/lib/gopher.c
+@@ -234,4 +234,4 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
+   Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
+   return CURLE_OK;
+ }
+-#endif /*CURL_DISABLE_GOPHER*/
++#endif /* CURL_DISABLE_GOPHER */
+diff --git a/lib/http.c b/lib/http.c
+index 28ef8dd..9a908fe 100644
+--- a/lib/http.c
++++ b/lib/http.c
+@@ -2081,7 +2081,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
+ {
+   const char *ptr;
+   if(!data->state.this_is_a_follow) {
+-    /* Free to avoid leaking memory on multiple requests*/
++    /* Free to avoid leaking memory on multiple requests */
+     free(data->state.first_host);
+ 
+     data->state.first_host = strdup(conn->host.name);
+@@ -2999,7 +2999,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
+         /* continue with HTTP/1.1 when explicitly requested */
+         break;
+       default:
+-        /* Check if user wants to use HTTP/2 with clear TCP*/
++        /* Check if user wants to use HTTP/2 with clear TCP */
+ #ifdef USE_NGHTTP2
+         if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+ #ifndef CURL_DISABLE_PROXY
+diff --git a/lib/http_chunks.c b/lib/http_chunks.c
+index beb9695..2c8b6c0 100644
+--- a/lib/http_chunks.c
++++ b/lib/http_chunks.c
+@@ -124,7 +124,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
+   *wrote = 0; /* nothing's written yet */
+ 
+   /* the original data is written to the client, but we go on with the
+-     chunk read process, to properly calculate the content length*/
++     chunk read process, to properly calculate the content length */
+   if(data->set.http_te_skip && !k->ignorebody) {
+     result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen);
+     if(result) {
+diff --git a/lib/rtsp.c b/lib/rtsp.c
+index cdd49dc..3391a8e 100644
+--- a/lib/rtsp.c
++++ b/lib/rtsp.c
+@@ -309,7 +309,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
+     break;
+   case RTSPREQ_RECEIVE:
+     p_request = "";
+-    /* Treat interleaved RTP as body*/
++    /* Treat interleaved RTP as body */
+     data->set.opt_no_body = FALSE;
+     break;
+   case RTSPREQ_LAST:
+@@ -645,7 +645,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
+       rtp_length = RTP_PKT_LENGTH(rtp);
+ 
+       if(rtp_dataleft < rtp_length + 4) {
+-        /* Need more - incomplete payload*/
++        /* Need more - incomplete payload */
+         *readmore = TRUE;
+         break;
+       }
+diff --git a/lib/rtsp.h b/lib/rtsp.h
+index 1e9cb7d..2776359 100644
+--- a/lib/rtsp.h
++++ b/lib/rtsp.h
+@@ -60,7 +60,7 @@ struct RTSP {
+    * HTTP functions can safely treat this as an HTTP struct, but RTSP aware
+    * functions can also index into the later elements.
+    */
+-  struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */
++  struct HTTP http_wrapper; /* wrap HTTP to do the heavy lifting */
+ 
+   long CSeq_sent; /* CSeq of this request */
+   long CSeq_recv; /* CSeq received */
+diff --git a/lib/telnet.c b/lib/telnet.c
+index 803d4c5..82fde7d 100644
+--- a/lib/telnet.c
++++ b/lib/telnet.c
+@@ -569,7 +569,7 @@ void rec_do(struct Curl_easy *data, int option)
+         sendsuboption(data, option);
+     }
+     else if(tn->subnegotiation[option] == CURL_YES) {
+-      /* send information to achieve this option*/
++      /* send information to achieve this option */
+       tn->us[option] = CURL_YES;
+       send_negotiation(data, CURL_WILL, option);
+       sendsuboption(data, option);
+diff --git a/lib/urldata.h b/lib/urldata.h
+index 52e4583..c9a52ab 100644
+--- a/lib/urldata.h
++++ b/lib/urldata.h
+@@ -243,7 +243,7 @@ struct ssl_connect_data {
+ 
+ struct ssl_primary_config {
+   long version;          /* what version the client wants to use */
+-  long version_max;      /* max supported version the client wants to use*/
++  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 */
+@@ -281,7 +281,7 @@ struct ssl_config_data {
+   char *key_passwd; /* plain text private key password */
+   BIT(certinfo);     /* gather lots of certificate info */
+   BIT(falsestart);
+-  BIT(enable_beast); /* allow this flaw for interoperability's sake*/
++  BIT(enable_beast); /* allow this flaw for interoperability's sake */
+   BIT(no_revoke);    /* disable SSL certificate revocation checks */
+   BIT(no_partialchain); /* don't accept partial certificate chains */
+   BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation
+diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c
+index 559852f..3fc4e50 100644
+--- a/lib/vauth/digest.c
++++ b/lib/vauth/digest.c
+@@ -139,7 +139,7 @@ bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
+ }
+ 
+ #if !defined(USE_WINDOWS_SSPI)
+-/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/
++/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string */
+ static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */
+                                      unsigned char *dest) /* 33 bytes */
+ {
+@@ -148,7 +148,7 @@ static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */
+     msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
+ }
+ 
+-/* Convert sha256 chunk to RFC7616 -suitable ascii string*/
++/* Convert sha256 chunk to RFC7616 -suitable ascii string */
+ static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */
+                                      unsigned char *dest) /* 65 bytes */
+ {
+diff --git a/lib/vauth/krb5_sspi.c b/lib/vauth/krb5_sspi.c
+index b2d1635..26bb794 100644
+--- a/lib/vauth/krb5_sspi.c
++++ b/lib/vauth/krb5_sspi.c
+@@ -530,4 +530,4 @@ void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5)
+   krb5->token_max = 0;
+ }
+ 
+-#endif /* USE_WINDOWS_SSPI && USE_KERBEROS5*/
++#endif /* USE_WINDOWS_SSPI && USE_KERBEROS5 */
+diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c
+index 0a468dd..e1c55b0 100644
+--- a/lib/vssh/libssh2.c
++++ b/lib/vssh/libssh2.c
+@@ -571,9 +571,9 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
+       /* remove old host+key that doesn't match */
+       if(host)
+         libssh2_knownhost_del(sshc->kh, host);
+-        /*FALLTHROUGH*/
++        /* FALLTHROUGH */
+     case CURLKHSTAT_FINE:
+-        /*FALLTHROUGH*/
++        /* FALLTHROUGH */
+     case CURLKHSTAT_FINE_ADD_TO_FILE:
+       /* proceed */
+       if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
+diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
+index a80eb50..61f4abf 100644
+--- a/lib/vtls/schannel.c
++++ b/lib/vtls/schannel.c
+@@ -195,7 +195,7 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct Curl_easy *data,
+   return CURLE_OK;
+ }
+ 
+-/*longest is 26, buffer is slightly bigger*/
++/* longest is 26, buffer is slightly bigger */
+ #define LONGEST_ALG_ID 32
+ #define CIPHEROPTION(X)                         \
+   if(strcmp(#X, tmp) == 0)                      \
+@@ -218,7 +218,7 @@ get_alg_id_by_name(char *name)
+   CIPHEROPTION(CALG_MAC);
+   CIPHEROPTION(CALG_RSA_SIGN);
+   CIPHEROPTION(CALG_DSS_SIGN);
+-/*ifdefs for the options that are defined conditionally in wincrypt.h*/
++/* ifdefs for the options that are defined conditionally in wincrypt.h */
+ #ifdef CALG_NO_SIGN
+   CIPHEROPTION(CALG_NO_SIGN);
+ #endif
+diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
+index f2d7835..febf51a 100644
+--- a/lib/vtls/sectransp.c
++++ b/lib/vtls/sectransp.c
+@@ -197,7 +197,6 @@ static OSStatus SocketRead(SSLConnectionRef connection,
+   size_t bytesToGo = *dataLength;
+   size_t initLen = bytesToGo;
+   UInt8 *currData = (UInt8 *)data;
+-  /*int sock = *(int *)connection;*/
+   struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
+   struct ssl_backend_data *backend = connssl->backend;
+   int sock = backend->ssl_sockfd;
+@@ -258,7 +257,6 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
+                             size_t *dataLength)  /* IN/OUT */
+ {
+   size_t bytesSent = 0;
+-  /*int sock = *(int *)connection;*/
+   struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
+   struct ssl_backend_data *backend = connssl->backend;
+   int sock = backend->ssl_sockfd;
+diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
+index 95c66d0..5046772 100644
+--- a/src/tool_cfgable.h
++++ b/src/tool_cfgable.h
+@@ -258,11 +258,8 @@ struct OperationConfig {
+   bool xattr;               /* store metadata in extended attributes */
+   long gssapi_delegation;
+   bool ssl_allow_beast;     /* allow this SSL vulnerability */
+-  bool proxy_ssl_allow_beast; /* allow this SSL vulnerability for proxy*/
+-
++  bool proxy_ssl_allow_beast; /* allow this SSL vulnerability for proxy */
+   bool ssl_no_revoke;       /* disable SSL certificate revocation checks */
+-  /*bool proxy_ssl_no_revoke; */
+-
+   bool ssl_revoke_best_effort; /* ignore SSL revocation offline/missing
+                                   revocation list errors */
+ 
+diff --git a/src/tool_getparam.c b/src/tool_getparam.c
+index f1393c3..51232ba 100644
+--- a/src/tool_getparam.c
++++ b/src/tool_getparam.c
+@@ -1064,7 +1064,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
+         /* This specifies the noproxy list */
+         GetStr(&config->noproxy, nextarg);
+         break;
+-       case '7': /* --socks5-gssapi-nec*/
++       case '7': /* --socks5-gssapi-nec */
+         config->socks5_gssapi_nec = toggle;
+         break;
+       case '8': /* --proxy1.0 */
+@@ -1230,7 +1230,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
+         config->httpversion = CURL_HTTP_VERSION_2_0;
+         break;
+       case '3': /* --http2-prior-knowledge */
+-        /* HTTP version 2.0 over clean TCP*/
++        /* HTTP version 2.0 over clean TCP */
+         config->httpversion = CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE;
+         break;
+       case '4': /* --http3 */
+diff --git a/tests/libtest/lib1525.c b/tests/libtest/lib1525.c
+index a2a4db2..912372f 100644
+--- a/tests/libtest/lib1525.c
++++ b/tests/libtest/lib1525.c
+@@ -48,7 +48,7 @@ int test(char *URL)
+ {
+   CURL *curl = NULL;
+   CURLcode res = CURLE_FAILED_INIT;
+-  /* http and proxy header list*/
++  /* http and proxy header list */
+   struct curl_slist *hhl = NULL;
+ 
+   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+diff --git a/tests/libtest/lib1526.c b/tests/libtest/lib1526.c
+index 37abc61..b287277 100644
+--- a/tests/libtest/lib1526.c
++++ b/tests/libtest/lib1526.c
+@@ -46,7 +46,7 @@ int test(char *URL)
+ {
+   CURL *curl = NULL;
+   CURLcode res = CURLE_FAILED_INIT;
+-  /* http and proxy header list*/
++  /* http and proxy header list */
+   struct curl_slist *hhl = NULL, *phl = NULL, *tmp = NULL;
+ 
+   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+diff --git a/tests/libtest/lib1527.c b/tests/libtest/lib1527.c
+index 9e0e452..2f7c91b 100644
+--- a/tests/libtest/lib1527.c
++++ b/tests/libtest/lib1527.c
+@@ -47,7 +47,7 @@ int test(char *URL)
+ {
+   CURL *curl = NULL;
+   CURLcode res = CURLE_FAILED_INIT;
+-  /* http header list*/
++  /* http header list */
+   struct curl_slist *hhl = NULL, *tmp = NULL;
+ 
+   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+diff --git a/tests/libtest/lib1528.c b/tests/libtest/lib1528.c
+index 98a332c..52dc0a0 100644
+--- a/tests/libtest/lib1528.c
++++ b/tests/libtest/lib1528.c
+@@ -28,7 +28,7 @@ int test(char *URL)
+ {
+   CURL *curl = NULL;
+   CURLcode res = CURLE_FAILED_INIT;
+-  /* http header list*/
++  /* http header list */
+   struct curl_slist *hhl = NULL;
+   struct curl_slist *phl = NULL;
+ 
+diff --git a/tests/libtest/lib1591.c b/tests/libtest/lib1591.c
+index 8349b1d..f7149cf 100644
+--- a/tests/libtest/lib1591.c
++++ b/tests/libtest/lib1591.c
+@@ -75,7 +75,7 @@ int test(char *URL)
+ {
+   CURL *curl = NULL;
+   CURLcode res = CURLE_FAILED_INIT;
+-  /* http and proxy header list*/
++  /* http and proxy header list */
+   struct curl_slist *hhl = NULL;
+ 
+   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+diff --git a/tests/libtest/lib506.c b/tests/libtest/lib506.c
+index 559e731..acea39a 100644
+--- a/tests/libtest/lib506.c
++++ b/tests/libtest/lib506.c
+@@ -347,7 +347,7 @@ int test(char *URL)
+   printf("-----------------\n");
+   curl_slist_free_all(cookies);
+ 
+-  /* try to free share, expect to fail because share is in use*/
++  /* try to free share, expect to fail because share is in use */
+   printf("try SHARE_CLEANUP...\n");
+   scode = curl_share_cleanup(share);
+   if(scode == CURLSHE_OK) {
+diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c
+index 00fbca3..4105a76 100644
+--- a/tests/libtest/lib557.c
++++ b/tests/libtest/lib557.c
+@@ -1494,7 +1494,7 @@ static int test_weird_arguments(void)
+                          "0123456789" /* 10 7 */
+                          "0123456789" /* 10 8 */
+                          "0123456789" /* 10 9 */
+-                         "0123456789" /* 10 10*/
++                         "0123456789" /* 10 10 */
+                          "0123456789" /* 10 11 */
+                          "01234567"   /* 8 */
+     );
+diff --git a/tests/libtest/lib586.c b/tests/libtest/lib586.c
+index da63e7c..8d7822d 100644
+--- a/tests/libtest/lib586.c
++++ b/tests/libtest/lib586.c
+@@ -215,7 +215,7 @@ int test(char *URL)
+   printf("PERFORM\n");
+   curl_easy_perform(curl);
+ 
+-  /* try to free share, expect to fail because share is in use*/
++  /* try to free share, expect to fail because share is in use */
+   printf("try SHARE_CLEANUP...\n");
+   scode = curl_share_cleanup(share);
+   if(scode == CURLSHE_OK) {
+diff --git a/tests/libtest/stub_gssapi.h b/tests/libtest/stub_gssapi.h
+index 5a89102..735630c 100644
+--- a/tests/libtest/stub_gssapi.h
++++ b/tests/libtest/stub_gssapi.h
+@@ -98,85 +98,85 @@ typedef struct gss_channel_bindings_struct {
+   gss_buffer_desc application_data;
+ } *gss_channel_bindings_t;
+ 
+-OM_uint32 gss_release_buffer(OM_uint32 * /*minor_status*/,
+-                             gss_buffer_t /*buffer*/);
+-
+-OM_uint32 gss_init_sec_context(OM_uint32 * /*minor_status*/,
+-            gss_const_cred_id_t /*initiator_cred_handle*/,
+-            gss_ctx_id_t * /*context_handle*/,
+-            gss_const_name_t /*target_name*/,
+-            const gss_OID /*mech_type*/,
+-            OM_uint32 /*req_flags*/,
+-            OM_uint32 /*time_req*/,
+-            const gss_channel_bindings_t /*input_chan_bindings*/,
+-            const gss_buffer_t /*input_token*/,
+-            gss_OID * /*actual_mech_type*/,
+-            gss_buffer_t /*output_token*/,
+-            OM_uint32 * /*ret_flags*/,
+-            OM_uint32 * /*time_rec*/);
+-
+-OM_uint32 gss_delete_sec_context(OM_uint32 * /*minor_status*/,
+-                                 gss_ctx_id_t * /*context_handle*/,
+-                                 gss_buffer_t /*output_token*/);
+-
+-OM_uint32 gss_inquire_context(OM_uint32 * /*minor_status*/,
+-                              gss_const_ctx_id_t /*context_handle*/,
+-                              gss_name_t * /*src_name*/,
+-                              gss_name_t * /*targ_name*/,
+-                              OM_uint32 * /*lifetime_rec*/,
+-                              gss_OID * /*mech_type*/,
+-                              OM_uint32 * /*ctx_flags*/,
+-                              int * /*locally_initiated*/,
+-                              int * /*open_context*/);
+-
+-OM_uint32 gss_wrap(OM_uint32 * /*minor_status*/,
+-                   gss_const_ctx_id_t /*context_handle*/,
+-                   int /*conf_req_flag*/,
+-                   gss_qop_t /*qop_req*/,
+-                   const gss_buffer_t /*input_message_buffer*/,
+-                   int * /*conf_state*/,
+-                   gss_buffer_t /*output_message_buffer*/);
+-
+-OM_uint32 gss_unwrap(OM_uint32 * /*minor_status*/,
+-                     gss_const_ctx_id_t /*context_handle*/,
+-                     const gss_buffer_t /*input_message_buffer*/,
+-                     gss_buffer_t /*output_message_buffer*/,
+-                     int * /*conf_state*/,
+-                     gss_qop_t * /*qop_state*/);
+-
+-OM_uint32 gss_seal(OM_uint32 * /*minor_status*/,
+-                   gss_ctx_id_t /*context_handle*/,
+-                   int /*conf_req_flag*/,
+-                   int /*qop_req*/,
+-                   gss_buffer_t /*input_message_buffer*/,
+-                   int * /*conf_state*/,
+-                   gss_buffer_t /*output_message_buffer*/);
+-
+-OM_uint32 gss_unseal(OM_uint32 * /*minor_status*/,
+-                     gss_ctx_id_t /*context_handle*/,
+-                     gss_buffer_t /*input_message_buffer*/,
+-                     gss_buffer_t /*output_message_buffer*/,
+-                     int * /*conf_state*/,
+-                     int * /*qop_state*/);
+-
+-OM_uint32 gss_import_name(OM_uint32 * /*minor_status*/,
+-                          const gss_buffer_t /*input_name_buffer*/,
+-                          const gss_OID /*input_name_type*/,
+-                          gss_name_t * /*output_name*/);
+-
+-OM_uint32 gss_release_name(OM_uint32 * /*minor_status*/,
+-                           gss_name_t * /*input_name*/);
+-
+-OM_uint32 gss_display_name(OM_uint32 * /*minor_status*/,
+-                           gss_const_name_t /*input_name*/,
+-                           gss_buffer_t /*output_name_buffer*/,
+-                           gss_OID * /*output_name_type*/);
+-
+-OM_uint32 gss_display_status(OM_uint32 * /*minor_status*/,
+-                             OM_uint32 /*status_value*/,
+-                             int /*status_type*/,
+-                             const gss_OID /*mech_type*/,
+-                             OM_uint32 * /*message_context*/,
+-                             gss_buffer_t /*status_string*/);
++OM_uint32 gss_release_buffer(OM_uint32 * /* minor_status */,
++                             gss_buffer_t /* buffer */);
++
++OM_uint32 gss_init_sec_context(OM_uint32 * /* minor_status */,
++            gss_const_cred_id_t /* initiator_cred_handle */,
++            gss_ctx_id_t * /* context_handle */,
++            gss_const_name_t /* target_name */,
++            const gss_OID /* mech_type */,
++            OM_uint32 /* req_flags */,
++            OM_uint32 /* time_req */,
++            const gss_channel_bindings_t /* input_chan_bindings */,
++            const gss_buffer_t /* input_token */,
++            gss_OID * /* actual_mech_type */,
++            gss_buffer_t /* output_token */,
++            OM_uint32 * /* ret_flags */,
++            OM_uint32 * /* time_rec */);
++
++OM_uint32 gss_delete_sec_context(OM_uint32 * /* minor_status */,
++                                 gss_ctx_id_t * /* context_handle */,
++                                 gss_buffer_t /* output_token */);
++
++OM_uint32 gss_inquire_context(OM_uint32 * /* minor_status */,
++                              gss_const_ctx_id_t /* context_handle */,
++                              gss_name_t * /* src_name */,
++                              gss_name_t * /* targ_name */,
++                              OM_uint32 * /* lifetime_rec */,
++                              gss_OID * /* mech_type */,
++                              OM_uint32 * /* ctx_flags */,
++                              int * /* locally_initiated */,
++                              int * /* open_context */);
++
++OM_uint32 gss_wrap(OM_uint32 * /* minor_status */,
++                   gss_const_ctx_id_t /* context_handle */,
++                   int /* conf_req_flag */,
++                   gss_qop_t /* qop_req */,
++                   const gss_buffer_t /* input_message_buffer */,
++                   int * /* conf_state */,
++                   gss_buffer_t /* output_message_buffer */);
++
++OM_uint32 gss_unwrap(OM_uint32 * /* minor_status */,
++                     gss_const_ctx_id_t /* context_handle */,
++                     const gss_buffer_t /* input_message_buffer */,
++                     gss_buffer_t /* output_message_buffer */,
++                     int * /* conf_state */,
++                     gss_qop_t * /* qop_state */);
++
++OM_uint32 gss_seal(OM_uint32 * /* minor_status */,
++                   gss_ctx_id_t /* context_handle n */,
++                   int /* conf_req_flag */,
++                   int /* qop_req */,
++                   gss_buffer_t /* input_message_buffer */,
++                   int * /* conf_state */,
++                   gss_buffer_t /* output_message_buffer */);
++
++OM_uint32 gss_unseal(OM_uint32 * /* minor_status */,
++                     gss_ctx_id_t /* context_handle */,
++                     gss_buffer_t /* input_message_buffer */,
++                     gss_buffer_t /* output_message_buffer */,
++                     int * /* conf_state */,
++                     int * /* qop_state */);
++
++OM_uint32 gss_import_name(OM_uint32 * /* minor_status */,
++                          const gss_buffer_t /* input_name_buffer */,
++                          const gss_OID /* input_name_type */,
++                          gss_name_t * /* output_name */);
++
++OM_uint32 gss_release_name(OM_uint32 * /* minor_status */,
++                           gss_name_t * /* input_name */);
++
++OM_uint32 gss_display_name(OM_uint32 * /* minor_status */,
++                           gss_const_name_t /* input_name */,
++                           gss_buffer_t /* output_name_buffer */,
++                           gss_OID * /* output_name_type */);
++
++OM_uint32 gss_display_status(OM_uint32 * /* minor_status */,
++                             OM_uint32 /* status_value */,
++                             int /* status_type */,
++                             const gss_OID /* mech_type */,
++                             OM_uint32 * /* message_context */,
++                             gss_buffer_t /* status_string */);
+ 
+ #endif /* HEADER_CURL_GSSAPI_STUBS_H */
+diff --git a/tests/server/tftp.h b/tests/server/tftp.h
+index 5699672..ab59575 100644
+--- a/tests/server/tftp.h
++++ b/tests/server/tftp.h
+@@ -32,7 +32,7 @@
+   ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7)))
+ #  define PACKED_STRUCT __attribute__((__packed__))
+ #else
+-#  define PACKED_STRUCT /*NOTHING*/
++#  define PACKED_STRUCT /* NOTHING */
+ #endif
+ 
+ /* Using a packed struct as binary in a program is begging for problems, but
+diff --git a/tests/server/util.c b/tests/server/util.c
+index c4f16e4..a0dec98 100644
+--- a/tests/server/util.c
++++ b/tests/server/util.c
+@@ -65,7 +65,7 @@
+     ((__W32API_MAJOR_VERSION == 3) && (__W32API_MINOR_VERSION < 6))
+ const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
+ #endif /* w32api < 3.6 */
+-#endif /* ENABLE_IPV6 && __MINGW32__*/
++#endif /* ENABLE_IPV6 && __MINGW32__ */
+ 
+ static struct timeval tvnow(void);
+ 
+diff --git a/tests/unit/unit1300.c b/tests/unit/unit1300.c
+index aba068a..936c77e 100644
+--- a/tests/unit/unit1300.c
++++ b/tests/unit/unit1300.c
+@@ -91,10 +91,10 @@ UNITTEST_START
+ 
+   fail_unless(Curl_llist_count(&llist) == 1,
+               "List size should be 1 after adding a new element");
+-  /*test that the list head data holds my unusedData */
++  /* test that the list head data holds my unusedData */
+   fail_unless(llist.head->ptr == &unusedData_case1,
+               "head ptr should be first entry");
+-  /*same goes for the list tail */
++  /* same goes for the list tail */
+   fail_unless(llist.tail == llist.head,
+               "tail and head should be the same");
+ 
+-- 
+2.39.2
+
+
+From ab44f4893b87cb3ef567be525a393bc174b031e7 Mon Sep 17 00:00:00 2001
+From: Eric Vigeant <evigeant@gmail.com>
+Date: Wed, 2 Nov 2022 11:47:09 -0400
+Subject: [PATCH 3/4] cur_path: do not add '/' if homedir ends with one
+
+When using SFTP and a path relative to the user home, do not add a
+trailing '/' to the user home dir if it already ends with one.
+
+Closes #9844
+
+Upstream-commit: 6c51adeb71da076c5c40a45e339e06bb4394a86b
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ lib/curl_path.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/lib/curl_path.c b/lib/curl_path.c
+index 649da7d..5be6637 100644
+--- a/lib/curl_path.c
++++ b/lib/curl_path.c
+@@ -69,10 +69,14 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
+       /* It is referenced to the home directory, so strip the
+          leading '/' */
+       memcpy(real_path, homedir, homelen);
+-      real_path[homelen] = '/';
+-      real_path[homelen + 1] = '\0';
++      /* Only add a trailing '/' if homedir does not end with one */
++      if(homelen == 0 || real_path[homelen - 1] != '/') {
++        real_path[homelen] = '/';
++        homelen++;
++        real_path[homelen] = '\0';
++      }
+       if(working_path_len > 3) {
+-        memcpy(real_path + homelen + 1, working_path + 3,
++        memcpy(real_path + homelen, working_path + 3,
+                1 + working_path_len -3);
+       }
+     }
+-- 
+2.39.2
+
+
+From a0b0e531267239c2beb4aeca15a0581a411d9c7b Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Thu, 9 Mar 2023 16:22:11 +0100
+Subject: [PATCH 4/4] curl_path: create the new path with dynbuf
+
+Closes #10729
+
+Upstream-commit: 4e2b52b5f7a3bf50a0f1494155717b02cc1df6d6
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ lib/curl_path.c | 75 +++++++++++++++++++++++--------------------------
+ 1 file changed, 35 insertions(+), 40 deletions(-)
+
+diff --git a/lib/curl_path.c b/lib/curl_path.c
+index 5be6637..b654aff 100644
+--- a/lib/curl_path.c
++++ b/lib/curl_path.c
+@@ -30,70 +30,65 @@
+ #include "escape.h"
+ #include "memdebug.h"
+ 
++#define MAX_SSHPATH_LEN 100000 /* arbitrary */
++
+ /* figure out the path to work with in this particular request */
+ CURLcode Curl_getworkingpath(struct Curl_easy *data,
+                              char *homedir,  /* when SFTP is used */
+                              char **path) /* returns the  allocated
+                                              real path to work with */
+ {
+-  char *real_path = NULL;
+   char *working_path;
+   size_t working_path_len;
++  struct dynbuf npath;
+   CURLcode result =
+     Curl_urldecode(data, data->state.up.path, 0, &working_path,
+                    &working_path_len, REJECT_ZERO);
+   if(result)
+     return result;
+ 
++  /* new path to switch to in case we need to */
++  Curl_dyn_init(&npath, MAX_SSHPATH_LEN);
++
+   /* Check for /~/, indicating relative to the user's home directory */
+-  if(data->conn->handler->protocol & CURLPROTO_SCP) {
+-    real_path = malloc(working_path_len + 1);
+-    if(real_path == NULL) {
++  if((data->conn->handler->protocol & CURLPROTO_SCP) &&
++     (working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) {
++    /* It is referenced to the home directory, so strip the leading '/~/' */
++    if(Curl_dyn_addn(&npath, &working_path[3], working_path_len - 3)) {
+       free(working_path);
+       return CURLE_OUT_OF_MEMORY;
+     }
+-    if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
+-      /* It is referenced to the home directory, so strip the leading '/~/' */
+-      memcpy(real_path, working_path + 3, working_path_len - 2);
+-    else
+-      memcpy(real_path, working_path, 1 + working_path_len);
+   }
+-  else if(data->conn->handler->protocol & CURLPROTO_SFTP) {
+-    if((working_path_len > 1) && (working_path[1] == '~')) {
+-      size_t homelen = strlen(homedir);
+-      real_path = malloc(homelen + working_path_len + 1);
+-      if(real_path == NULL) {
+-        free(working_path);
+-        return CURLE_OUT_OF_MEMORY;
+-      }
+-      /* It is referenced to the home directory, so strip the
+-         leading '/' */
+-      memcpy(real_path, homedir, homelen);
+-      /* Only add a trailing '/' if homedir does not end with one */
+-      if(homelen == 0 || real_path[homelen - 1] != '/') {
+-        real_path[homelen] = '/';
+-        homelen++;
+-        real_path[homelen] = '\0';
+-      }
+-      if(working_path_len > 3) {
+-        memcpy(real_path + homelen, working_path + 3,
+-               1 + working_path_len -3);
+-      }
++  else if((data->conn->handler->protocol & CURLPROTO_SFTP) &&
++          (working_path_len > 2) && !memcmp(working_path, "/~/", 3)) {
++    size_t len;
++    const char *p;
++    int copyfrom = 3;
++    if(Curl_dyn_add(&npath, homedir)) {
++      free(working_path);
++      return CURLE_OUT_OF_MEMORY;
+     }
+-    else {
+-      real_path = malloc(working_path_len + 1);
+-      if(real_path == NULL) {
+-        free(working_path);
+-        return CURLE_OUT_OF_MEMORY;
+-      }
+-      memcpy(real_path, working_path, 1 + working_path_len);
++    /* Copy a separating '/' if homedir does not end with one */
++    len = Curl_dyn_len(&npath);
++    p = Curl_dyn_ptr(&npath);
++    if(len && (p[len-1] != '/'))
++      copyfrom = 2;
++
++    if(Curl_dyn_addn(&npath,
++                     &working_path[copyfrom], working_path_len - copyfrom)) {
++      free(working_path);
++      return CURLE_OUT_OF_MEMORY;
+     }
+   }
+ 
+-  free(working_path);
++  if(Curl_dyn_len(&npath)) {
++    free(working_path);
+ 
+-  /* store the pointer for the caller to receive */
+-  *path = real_path;
++    /* store the pointer for the caller to receive */
++    *path = Curl_dyn_ptr(&npath);
++  }
++  else
++    *path = working_path;
+ 
+   return CURLE_OK;
+ }
+-- 
+2.39.2
+
diff --git a/SOURCES/0027-curl-7.76.1-CVE-2023-27535.patch b/SOURCES/0027-curl-7.76.1-CVE-2023-27535.patch
new file mode 100644
index 0000000..846a90c
--- /dev/null
+++ b/SOURCES/0027-curl-7.76.1-CVE-2023-27535.patch
@@ -0,0 +1,230 @@
+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
+
diff --git a/SOURCES/0028-curl-7.76.1-CVE-2023-27536.patch b/SOURCES/0028-curl-7.76.1-CVE-2023-27536.patch
new file mode 100644
index 0000000..7888e19
--- /dev/null
+++ b/SOURCES/0028-curl-7.76.1-CVE-2023-27536.patch
@@ -0,0 +1,54 @@
+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
+
diff --git a/SOURCES/0029-curl-7.76.1-CVE-2023-27538.patch b/SOURCES/0029-curl-7.76.1-CVE-2023-27538.patch
new file mode 100644
index 0000000..030b6bb
--- /dev/null
+++ b/SOURCES/0029-curl-7.76.1-CVE-2023-27538.patch
@@ -0,0 +1,30 @@
+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
+
diff --git a/SOURCES/0030-curl-7.76.1-CVE-2023-28322.patch b/SOURCES/0030-curl-7.76.1-CVE-2023-28322.patch
new file mode 100644
index 0000000..0aadf52
--- /dev/null
+++ b/SOURCES/0030-curl-7.76.1-CVE-2023-28322.patch
@@ -0,0 +1,420 @@
+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] == '/')
diff --git a/SOURCES/0031-curl-7.76.1-CVE-2023-28321.patch b/SOURCES/0031-curl-7.76.1-CVE-2023-28321.patch
new file mode 100644
index 0000000..b306e91
--- /dev/null
+++ b/SOURCES/0031-curl-7.76.1-CVE-2023-28321.patch
@@ -0,0 +1,304 @@
+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
diff --git a/SPECS/curl.spec b/SPECS/curl.spec
index f84d473..7d29f90 100644
--- a/SPECS/curl.spec
+++ b/SPECS/curl.spec
@@ -1,7 +1,7 @@
 Summary: A utility for getting files from remote servers (FTP, HTTP, and others)
 Name: curl
 Version: 7.76.1
-Release: 23%{?dist}
+Release: 26%{?dist}
 License: MIT
 Source: https://curl.se/download/%{name}-%{version}.tar.xz
 
@@ -74,6 +74,27 @@ Patch23:  0023-curl-7.76.1-CVE-2022-43552.patch
 # fix HTTP multi-header compression denial of service (CVE-2023-23916)
 Patch24:  0024-curl-7.76.1-CVE-2023-23916.patch
 
+# fix TELNET option IAC injection (CVE-2023-27533)
+Patch25:  0025-curl-7.76.1-CVE-2023-27533.patch
+
+# fix SFTP path ~ resolving discrepancy (CVE-2023-27534)
+Patch26:  0026-curl-7.76.1-CVE-2023-27534.patch
+
+# fix FTP too eager connection reuse (CVE-2023-27535)
+Patch27:  0027-curl-7.76.1-CVE-2023-27535.patch
+
+# fix GSS delegation too eager connection re-use (CVE-2023-27536)
+Patch28:  0028-curl-7.76.1-CVE-2023-27536.patch
+
+# fix SSH connection too eager reuse still (CVE-2023-27538)
+Patch29:  0029-curl-7.76.1-CVE-2023-27538.patch
+
+# unify the upload/method handling (CVE-2023-28322)
+Patch30:  0030-curl-7.76.1-CVE-2023-28322.patch
+
+# fix host name wildcard checking
+Patch31:  0031-curl-7.76.1-CVE-2023-28321.patch
+
 # patch making libcurl multilib ready
 Patch101: 0101-curl-7.32.0-multilib.patch
 
@@ -272,6 +293,13 @@ be installed.
 %patch22 -p1
 %patch23 -p1
 %patch24 -p1
+%patch25 -p1
+%patch26 -p1
+%patch27 -p1
+%patch28 -p1
+%patch29 -p1
+%patch30 -p1
+%patch31 -p1
 
 # Fedora patches
 %patch101 -p1
@@ -497,6 +525,20 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la
 %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal
 
 %changelog
+* Mon Jun 12 2023 Jacek Migacz <jmigacz@redhat.com> - 7.76.1-26
+- unify the upload/method handling (CVE-2023-28322)
+- fix host name wildcard checking (CVE-2023-28321)
+
+* Wed Apr 12 2023 Kamil Dudka <kdudka@redhat.com> - 7.76.1-25
+- adapt the fix of CVE-2023-27535 for RHEL 9 curl
+
+* Fri Mar 24 2023 Kamil Dudka <kdudka@redhat.com> - 7.76.1-24
+- fix SSH connection too eager reuse still (CVE-2023-27538)
+- fix GSS delegation too eager connection re-use (CVE-2023-27536)
+- fix FTP too eager connection reuse (CVE-2023-27535)
+- fix SFTP path ~ resolving discrepancy (CVE-2023-27534)
+- fix TELNET option IAC injection (CVE-2023-27533)
+
 * Wed Feb 15 2023 Kamil Dudka <kdudka@redhat.com> - 7.76.1-23
 - fix HTTP multi-header compression denial of service (CVE-2023-23916)
 
-- 
GitLab