[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1053270: marked as done (bullseye-pu: package curl/7.74.0-1.3+deb11u9)



Your message dated Sat, 07 Oct 2023 12:41:28 +0100
with message-id <84bb5ff8312f749ebe536897993782bf35aa1977.camel@adam-barratt.org.uk>
and subject line Closing opu requests for updates included in 11.8
has caused the Debian Bug report #1053270,
regarding bullseye-pu: package curl/7.74.0-1.3+deb11u9
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
1053270: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1053270
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian.org@packages.debian.org
Usertags: pu
X-Debbugs-Cc: curl@packages.debian.org, charlesmelara@riseup.net
Control: affects -1 + src:curl

[ Reason ]
Vulnerabilities were discovered and reported to Curl upstream [1][2] with the
following CVE IDs:

- CVE-2023-28321
- CVE-2023-28322

The description of the CVE-2023-28321 is:

> An improper certificate validation vulnerability exists in curl
> <v8.1.0 in the way it supports matching of wildcard patterns when
> listed as "Subject Alternative Name" in TLS server certificates. curl
> can be built to use its own name matching function for TLS rather than
> one provided by a TLS library. This private wildcard matching function
> would match IDN (International Domain Name) hosts incorrectly and
> could as a result accept patterns that otherwise should mismatch. IDN
> hostnames are converted to puny code before used for certificate
> checks. Puny coded names always start with `xn--` and should not be
> allowed to pattern match, but the wildcard check in curl could still
> check for `x*`, which would match even though the IDN name most likely
> contained nothing even resembling an `x`.

And the description of the CVE-2023-28322 is:

> An information disclosure vulnerability exists in curl <v8.1.0 when
> doing HTTP(S) transfers, libcurl might erroneously use the read
> callback (`CURLOPT_READFUNCTION`) to ask for data to send, even when
> the `CURLOPT_POSTFIELDS` option has been set, if the same handle
> previously wasused to issue a `PUT` request which used that callback.
> This flaw may surprise the application and cause it to misbehave and
> either send off the wrong data or use memory after free or similar in
> the second transfer. The problem exists in the logic for a reused
> handle when it is (expected to be) changed from a PUT to a POST.

This proposed update is meant to fix those vulnerabilities.

[ Impact ]
As the vulnerabilities are present in bullseye's curl code, they can be
exploited by malicious actors.

[ Tests ]
Automatic tests were executed (from the curl test suite) during build
time. Everything passed after the changes were introduced.

I also conducted a test to see if the CVE-2023-28321 was fixed. In order
to do so, I've followed the report's reproduction steps [3] and tested in a
bullseye container. The default bullseye curl version is vulnerable, but
this new one is not. Unfortunately the PoC of CVE-2023-28322 was crafted
using a newer version of libcurl, so I wasn't able to validate the fix
of the backported patch.

Also, note the fix for CVE-2023-28321 comes from CentOS and is already
available there.

[ Risks ]
The changes for weren't big because the delta between bullseye's version and
current upstream are not that large (true for CVE-2023-28322). Though
they exist so I did a backport of the patch (obviously there is a
chance of introducing bugs here, but we are using the tests to spot it).

Also, the fix for CVE-2023-28321 is new code based on the fix applied in curl
8.1.0 done by a Red Hat engineer. So, new bugs could have been
introduced.

I reviewed this fix and samueloph reviewed everything (both fixes and
packaging).

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
Here is a list of the commits applied to this pu release:

commit a1190a634dcca9a85f8217c71b1073825885a16e
Author: Carlos Henrique Lima Melara <charlesmelara@riseup.net>
Date:   Sun Sep 10 15:29:53 2023 +0530

    Finalize changelog for 7.74.0-1.3+deb11u9 bullseye upload

commit 39155aa17df39693c2f21ef5dbb0ddf11568256f
Author: Carlos Henrique Lima Melara <charlesmelara@riseup.net>
Date:   Fri Sep 8 19:00:25 2023 +0530

    d/p/CVE-2023-28322.patch: backport patch

commit 156409a45db1c739edece8fd3b3d4d78d09c82ae
Author: Carlos Henrique Lima Melara <charlesmelara@riseup.net>
Date:   Sun Aug 13 11:01:11 2023 -0300

    Import 2 new patches fixing CVES

    One comes from upstream and another from CentOS.

    CVE-2023-28321
    CVE-2023-28322

[ Other info ]
Links:

[1] https://security-tracker.debian.org/tracker/CVE-2023-28321
[2] https://security-tracker.debian.org/tracker/CVE-2023-28322
[3] https://hackerone.com/reports/1950627

Cheers,
Charles
diff -Nru curl-7.74.0/debian/changelog curl-7.74.0/debian/changelog
--- curl-7.74.0/debian/changelog	2023-04-03 03:34:17.000000000 +0800
+++ curl-7.74.0/debian/changelog	2023-09-10 17:49:20.000000000 +0800
@@ -1,3 +1,14 @@
+curl (7.74.0-1.3+deb11u9) bullseye; urgency=medium
+
+  * Team upload.
+  * Import 2 new patches to fix CVES:
+    - CVE-2023-28321: IDN wildcard match may lead to Improper Cerificate
+      Validation.
+    - CVE-2023-28322: more POST-after-PUT confusion.
+  * debian/patches/CVE-2023-28322.patch: backport patch.
+
+ -- Carlos Henrique Lima Melara <charlesmelara@riseup.net>  Sun, 10 Sep 2023 15:19:20 +0530
+
 curl (7.74.0-1.3+deb11u8) bullseye; urgency=medium
 
   * Backport upstream patches to fix 5 CVEs:
diff -Nru curl-7.74.0/debian/patches/CVE-2023-28321.patch curl-7.74.0/debian/patches/CVE-2023-28321.patch
--- curl-7.74.0/debian/patches/CVE-2023-28321.patch	1970-01-01 07:30:00.000000000 +0730
+++ curl-7.74.0/debian/patches/CVE-2023-28321.patch	2023-09-10 17:49:20.000000000 +0800
@@ -0,0 +1,296 @@
+From bb4d7d8d9f2ce34d3dded9b96eaf800e38b92434 Mon Sep 17 00:00:00 2001
+From: Jacek Migacz <jmigacz@redhat.com>
+Date: Tue, 27 Jun 2023 19:42:23 +0200
+Subject: [PATCH] Resolves: CVE-2023-28321 - fix host name wildcard checking
+
+---
+ 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 -Nru curl-7.74.0/debian/patches/CVE-2023-28322.patch curl-7.74.0/debian/patches/CVE-2023-28322.patch
--- curl-7.74.0/debian/patches/CVE-2023-28322.patch	1970-01-01 07:30:00.000000000 +0730
+++ curl-7.74.0/debian/patches/CVE-2023-28322.patch	2023-09-10 17:49:20.000000000 +0800
@@ -0,0 +1,422 @@
+From 7815647d6582c0a4900be2e1de6c5e61272c496b 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.
+
+Closes #11017
+---
+ 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          | 4 ++--
+ 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, 35 insertions(+), 37 deletions(-)
+
+diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c
+index ba471a2..a91df76 100644
+--- a/lib/curl_rtmp.c
++++ b/lib/curl_rtmp.c
+@@ -219,7 +219,7 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
+   /* We have to know if it's a write before we send the
+    * connect request packet
+    */
+-  if(conn->data->set.upload)
++  if(conn->data->state.upload)
+     r->Link.protocol |= RTMP_FEATURE_WRITE;
+ 
+   /* For plain streams, use the buffer toggle trick to keep data flowing */
+@@ -251,7 +251,7 @@ static CURLcode rtmp_do(struct connectdata *conn, bool *done)
+   if(!RTMP_ConnectStream(r, 0))
+     return CURLE_FAILED_INIT;
+ 
+-  if(conn->data->set.upload) {
++  if(conn->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 a65eb77..9a13910 100644
+--- a/lib/file.c
++++ b/lib/file.c
+@@ -196,7 +196,7 @@ static CURLcode file_connect(struct connectdata *conn, 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(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
+     return CURLE_FILE_COULDNT_READ_FILE;
+@@ -378,7 +378,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
+ 
+   Curl_pgrsStartNow(data);
+ 
+-  if(data->set.upload)
++  if(data->state.upload)
+     return file_upload(conn);
+ 
+   file = conn->data->req.p.file;
+diff --git a/lib/ftp.c b/lib/ftp.c
+index 36a2a09..fe2636e 100644
+--- a/lib/ftp.c
++++ b/lib/ftp.c
+@@ -1361,7 +1361,7 @@ static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
+                                data->set.str[STRING_CUSTOMREQUEST]?
+                                data->set.str[STRING_CUSTOMREQUEST]:
+                                (data->set.ftp_list_only?"NLST":"LIST"));
+-      else if(data->set.upload)
++      else if(data->state.upload)
+         result = Curl_pp_sendf(&ftpc->pp, "PRET STOR %s",
+                                conn->proto.ftpc.file);
+       else
+@@ -3328,7 +3328,7 @@ static CURLcode ftp_done(struct connectdata *conn, 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 &&
+@@ -3598,7 +3598,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
+                            connected back to us */
+       }
+     }
+-    else if(data->set.upload) {
++    else if(data->state.upload) {
+       result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE);
+       if(result)
+         return result;
+@@ -4169,7 +4169,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
+     ftpc->file = NULL; /* instead of point to a zero byte,
+                             we make it a NULL pointer */
+ 
+-  if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) {
++  if(data->state.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_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 35ec7c5..1350125 100644
+--- a/lib/http.c
++++ b/lib/http.c
+@@ -2003,7 +2003,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
+   }
+ 
+   if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
+-     data->set.upload) {
++     data->state.upload) {
+     httpreq = HTTPREQ_PUT;
+   }
+ 
+@@ -2181,7 +2181,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
+     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 f3361cf..47d5b94 100644
+--- a/lib/imap.c
++++ b/lib/imap.c
+@@ -1476,11 +1476,11 @@ static CURLcode imap_done(struct connectdata *conn, 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(conn, IMAP_FETCH_FINAL);
+     else {
+       /* End the APPEND command first by sending an empty line */
+@@ -1546,7 +1546,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
+     selected = TRUE;
+ 
+   /* Start the first command in the DO phase */
+-  if(conn->data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
++  if(conn->data->state.upload || data->set.mimepost.kind != MIMEKIND_NONE)
+     /* APPEND can be executed directly */
+     result = imap_perform_append(conn);
+   else if(imap->custom && (selected || !imap->mailbox))
+diff --git a/lib/rtsp.c b/lib/rtsp.c
+index 151ff4a..89ad782 100644
+--- a/lib/rtsp.c
++++ b/lib/rtsp.c
+@@ -497,7 +497,7 @@ static CURLcode rtsp_do(struct connectdata *conn, 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;
+ 
+@@ -516,7 +516,7 @@ static CURLcode rtsp_do(struct connectdata *conn, 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 3c43cdb..90d2dac 100644
+--- a/lib/setopt.c
++++ b/lib/setopt.c
+@@ -297,8 +297,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 */
+@@ -626,7 +626,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:
+@@ -848,7 +847,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 0abed77..4584c91 100644
+--- a/lib/smb.c
++++ b/lib/smb.c
+@@ -516,7 +516,7 @@ static CURLcode smb_send_open(struct connectdata *conn)
+   byte_count = strlen(req->path);
+   msg.name_length = smb_swap16((unsigned short)byte_count);
+   msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL);
+-  if(conn->data->set.upload) {
++  if(conn->data->state.upload) {
+     msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE);
+     msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF);
+   }
+@@ -792,7 +792,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
+     smb_m = (const struct smb_nt_create_response*) msg;
+     req->fid = smb_swap16(smb_m->fid);
+     conn->data->req.offset = 0;
+-    if(conn->data->set.upload) {
++    if(conn->data->state.upload) {
+       conn->data->req.size = conn->data->state.infilesize;
+       Curl_pgrsSetUploadSize(conn->data, conn->data->req.size);
+       next_state = SMB_UPLOAD;
+diff --git a/lib/smtp.c b/lib/smtp.c
+index 51a2a56..ad3692b 100644
+--- a/lib/smtp.c
++++ b/lib/smtp.c
+@@ -1382,7 +1382,7 @@ static CURLcode smtp_done(struct connectdata *conn, 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.
+@@ -1475,7 +1475,7 @@ static CURLcode smtp_perform(struct connectdata *conn, 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(conn);
+   else
+diff --git a/lib/tftp.c b/lib/tftp.c
+index fba3f5e..b5b8bf5 100644
+--- a/lib/tftp.c
++++ b/lib/tftp.c
+@@ -391,7 +391,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;
+@@ -472,7 +472,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->conn->data->req.upload_fromhere =
+@@ -507,7 +507,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
+@@ -561,7 +561,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 fcc720d..fe8ffb4 100644
+--- a/lib/transfer.c
++++ b/lib/transfer.c
+@@ -1419,6 +1419,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);
+ }
+ 
+ /*
+@@ -1803,7 +1804,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");
+     }
+@@ -1842,7 +1842,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
+ 
+   /* 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 20664a6..b72da7c 100644
+--- a/lib/urldata.h
++++ b/lib/urldata.h
+@@ -1464,6 +1464,7 @@ struct UrlState {
+   BIT(stream_depends_e); /* set or don't set the Exclusive bit */
+   BIT(previouslypending); /* this transfer WAS in the multi->pending queue */
+   BIT(cookie_engine);
++  BIT(upload);         /* upload request */
+ };
+ 
+ 
+@@ -1824,7 +1825,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 e79d8e8..cb98a2f 100644
+--- a/lib/vssh/libssh.c
++++ b/lib/vssh/libssh.c
+@@ -1186,7 +1186,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
+     }
+ 
+     case SSH_SFTP_TRANS_INIT:
+-      if(data->set.upload)
++      if(data->state.upload)
+         state(conn, SSH_SFTP_UPLOAD_INIT);
+       else {
+         if(protop->path[strlen(protop->path)-1] == '/')
+@@ -1789,7 +1789,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, 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;
+@@ -1890,7 +1890,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
+         break;
+       }
+     case SSH_SCP_DONE:
+-      if(data->set.upload)
++      if(data->state.upload)
+         state(conn, SSH_SCP_SEND_EOF);
+       else
+         state(conn, SSH_SCP_CHANNEL_FREE);
+diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c
+index a69bcda..6fd853a 100644
+--- a/lib/vssh/libssh2.c
++++ b/lib/vssh/libssh2.c
+@@ -1844,7 +1844,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
+     }
+ 
+     case SSH_SFTP_TRANS_INIT:
+-      if(data->set.upload)
++      if(data->state.upload)
+         state(conn, SSH_SFTP_UPLOAD_INIT);
+       else {
+         if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
+@@ -2517,7 +2517,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, 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;
+@@ -2657,7 +2657,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
+     break;
+ 
+     case SSH_SCP_DONE:
+-      if(data->set.upload)
++      if(data->state.upload)
+         state(conn, SSH_SCP_SEND_EOF);
+       else
+         state(conn, SSH_SCP_CHANNEL_FREE);
+diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c
+index b0dfb20..97f464b 100644
+--- a/lib/vssh/wolfssh.c
++++ b/lib/vssh/wolfssh.c
+@@ -542,7 +542,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
+       }
+       break;
+     case SSH_SFTP_TRANS_INIT:
+-      if(data->set.upload)
++      if(data->state.upload)
+         state(conn, SSH_SFTP_UPLOAD_INIT);
+       else {
+         if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
diff -Nru curl-7.74.0/debian/patches/series curl-7.74.0/debian/patches/series
--- curl-7.74.0/debian/patches/series	2023-04-03 03:34:17.000000000 +0800
+++ curl-7.74.0/debian/patches/series	2023-09-10 17:49:20.000000000 +0800
@@ -38,6 +38,8 @@
 add_Curl_timestrcmp.patch
 CVE-2023-27535.patch
 CVE-2023-27536.patch
+CVE-2023-28321.patch
+CVE-2023-28322.patch
 
 # Always add CVE patches before these two patches
 90_gnutls.patch

--- End Message ---
--- Begin Message ---
Package: release.debian.org
Version: 11.8

Hi,

The updates referred to by each of these requests were included in
today's 11.8 bullseye point release.

Regards,

Adam

--- End Message ---

Reply to: