Your message dated Sat, 31 Aug 2024 12:30:55 +0100
with message-id 
<27c418b1a49ffc566f1b9635359e59f6a742be26.ca...@adam-barratt.org.uk>
and subject line Closing bugs for 11.11
has caused the Debian Bug report #1071417,
regarding bullseye-pu: package fossil/2.15.2-1+deb11u1
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 ow...@bugs.debian.org
immediately.)


-- 
1071417: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1071417
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: bullseye
X-Debbugs-Cc: fos...@packages.debian.org
Control: affects -1 + src:fossil
User: release.debian....@packages.debian.org
Usertags: pu

this bug was opened by previous arrangement with maintainer.

[ Reason ]
fossil is affected by a regression due to a security update of apache
CVE-2024-24795. Backport was choosen
because upstream does not document all commit needed for fixing the regression.

[ Impact ]
Fossil is broken at least server part

[ Tests ]
Full upstream test suite

[ Risks ]
Broken fossil

[ 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 ]
Cherry picked and backport fix

[ Other info ]
None
diff -Nru fossil-2.15.2/debian/changelog fossil-2.15.2/debian/changelog
--- fossil-2.15.2/debian/changelog	2021-06-15 09:55:20.000000000 +0000
+++ fossil-2.15.2/debian/changelog	2024-05-14 21:29:39.000000000 +0000
@@ -1,3 +1,13 @@
+fossil (1:2.15.2-1+deb11u1) bullseye; urgency=medium
+
+  * Non maintainer fix with acknowlegment by maintainer.
+  * Cherry-pick fix f4ffefe708793b03 for CVE-2024-24795 and add
+    "Breaks: apache2 (<< 2.4.59-1~)" to stage fix; see
+    https://bz.apache.org/bugzilla/show_bug.cgi?id=68905
+    (closes: #1070069)
+
+ -- Bastien Roucari??s <ro...@debian.org>  Tue, 14 May 2024 21:29:39 +0000
+
 fossil (1:2.15.2-1) unstable; urgency=high
 
   * New upstream version, announcement (expurgated) says:
diff -Nru fossil-2.15.2/debian/control fossil-2.15.2/debian/control
--- fossil-2.15.2/debian/control	2021-04-07 08:12:51.000000000 +0000
+++ fossil-2.15.2/debian/control	2024-05-14 21:29:39.000000000 +0000
@@ -22,6 +22,7 @@
 Architecture: any
 Multi-Arch: foreign
 Depends: libtcl8.6 | libtcl, ${misc:Depends}, ${shlibs:Depends}
+Breaks: apache2 (<< 2.4.59-1~), apache2-bin (<< 2.4.59-1~)
 Suggests: gnupg | gnupg2
 Description: DSCM with built-in wiki, http interface and server, tickets database
  Fossil is an easy-to-use Distributed Source Control Management system
diff -Nru fossil-2.15.2/debian/patches/0002-Deal-with-the-missing-Content-Length-field.patch fossil-2.15.2/debian/patches/0002-Deal-with-the-missing-Content-Length-field.patch
--- fossil-2.15.2/debian/patches/0002-Deal-with-the-missing-Content-Length-field.patch	1970-01-01 00:00:00.000000000 +0000
+++ fossil-2.15.2/debian/patches/0002-Deal-with-the-missing-Content-Length-field.patch	2024-05-14 21:29:39.000000000 +0000
@@ -0,0 +1,361 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <ro...@debian.org>
+Date: Tue, 14 May 2024 21:23:16 +0000
+Subject: Deal with the missing Content-Length field
+
+fix regression of CVE-2024-24795
+
+bug: https://bz.apache.org/bugzilla/show_bug.cgi?id=68905
+origin: https://fossil-scm.org/home/vpatch?from=9c40ddbcd182f264&to=a8e33fb161f45b65
+---
+ src/cgi.c   | 43 ++++++++++++++++++++++++++++---------
+ src/clone.c | 14 +++++++++++-
+ src/http.c  | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------
+ src/main.c  | 14 ++++++++++--
+ src/xfer.c  |  1 +
+ 5 files changed, 121 insertions(+), 22 deletions(-)
+
+diff --git a/src/cgi.c b/src/cgi.c
+index d47575b..aade0fb 100644
+--- a/src/cgi.c
++++ b/src/cgi.c
+@@ -1034,7 +1034,7 @@ void cgi_trace(const char *z){
+ }
+ 
+ /* Forward declaration */
+-static NORETURN void malformed_request(const char *zMsg);
++static NORETURN void malformed_request(const char *zMsg, ...);
+ 
+ /*
+ ** Initialize the query parameter database.  Information is pulled from
+@@ -1080,6 +1080,7 @@ void cgi_init(void){
+   const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
+   const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
+   const char *zPathInfo = cgi_parameter("PATH_INFO",0);
++  const char *zContentLength = 0;
+ #ifdef _WIN32
+   const char *zServerSoftware = cgi_parameter("SERVER_SOFTWARE",0);
+ #endif
+@@ -1186,7 +1187,15 @@ void cgi_init(void){
+     g.zIpAddr = fossil_strdup(z);
+   }
+ 
+-  len = atoi(PD("CONTENT_LENGTH", "0"));
++  zContentLength = P("CONTENT_LENGTH");
++  if( zContentLength==0 ){
++    len = 0;
++    if( sqlite3_stricmp(PD("REQUEST_METHOD",""),"POST")==0 ){
++      malformed_request("missing CONTENT_LENGTH on a POST method");
++    }
++  }else{
++    len = atoi(zContentLength);
++  }
+   zType = P("CONTENT_TYPE");
+   zSemi = zType ? strchr(zType, ';') : 0;
+   if( zSemi ){
+@@ -1593,11 +1602,22 @@ void cgi_vprintf(const char *zFormat, va_list ap){
+ /*
+ ** Send a reply indicating that the HTTP request was malformed
+ */
+-static NORETURN void malformed_request(const char *zMsg){
+-  cgi_set_status(501, "Not Implemented");
+-  cgi_printf(
+-    "<html><body><p>Bad Request: %s</p></body></html>\n", zMsg
+-  );
++static NORETURN void malformed_request(const char *zMsg, ...){
++  va_list ap;
++  char *z;
++  va_start(ap, zMsg);
++  z = vmprintf(zMsg, ap);
++  va_end(ap);
++  cgi_set_status(400, "Bad Request");
++  zContentType = "text/plain";
++  if( g.zReqType==0 ) g.zReqType = "WWW";
++  if( g.zReqType[0]=='C' && PD("SERVER_SOFTWARE",0)!=0 ){
++    const char *zServer = PD("SERVER_SOFTWARE","");
++    cgi_printf("Bad CGI Request from \"%s\": %s\n",zServer,z);
++  }else{
++    cgi_printf("Bad %s Request: %s\n", g.zReqType, z);
++  }
++  fossil_free(z);
+   cgi_reply();
+   fossil_exit(0);
+ }
+@@ -1714,8 +1734,9 @@ void cgi_handle_http_request(const char *zIpAddr){
+   const char *zScheme = "http";
+   char zLine[2000];     /* A single line of input. */
+   g.fullHttpReply = 1;
++  g.zReqType = "HTTP";
+   if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
+-    malformed_request("missing HTTP header");
++    malformed_request("missing header");
+   }
+   blob_append(&g.httpHeader, zLine, -1);
+   cgi_trace(zLine);
+@@ -1725,13 +1746,14 @@ void cgi_handle_http_request(const char *zIpAddr){
+   }
+   if( fossil_strcmp(zToken,"GET")!=0 && fossil_strcmp(zToken,"POST")!=0
+       && fossil_strcmp(zToken,"HEAD")!=0 ){
+-    malformed_request("unsupported HTTP method");
++    malformed_request("unsupported HTTP method: \"%s\" - Fossil only supports"
++                      "GET, POST, and HEAD", zToken);
+   }
+   cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
+   cgi_setenv("REQUEST_METHOD",zToken);
+   zToken = extract_token(z, &z);
+   if( zToken==0 ){
+-    malformed_request("malformed URL in HTTP header");
++    malformed_request("malformed URI in the HTTP header");
+   }
+   cgi_setenv("REQUEST_URI", zToken);
+   cgi_setenv("SCRIPT_NAME", "");
+@@ -1840,6 +1862,7 @@ void cgi_handle_ssh_http_request(const char *zIpAddr){
+   }else{
+     fossil_panic("missing SSH IP address");
+   }
++  g.zReqType = "HTTP";
+   if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
+     malformed_request("missing HTTP header");
+   }
+diff --git a/src/clone.c b/src/clone.c
+index 38c2b69..05d5b00 100644
+--- a/src/clone.c
++++ b/src/clone.c
+@@ -137,6 +137,7 @@ void delete_private_content(void){
+ **    -u|--unversioned           Also sync unversioned content
+ **    -v|--verbose               Show more statistics in output
+ **    --workdir DIR              Also open a checkout in DIR
++**    --xverbose                 Extra debugging output
+ **
+ ** See also: [[init]], [[open]]
+ */
+@@ -162,6 +163,7 @@ void clone_cmd(void){
+     urlFlags |= URL_REMEMBER_PW;
+   }
+   if( find_option("verbose","v",0)!=0) syncFlags |= SYNC_VERBOSE;
++  if( find_option("xverbose",0,0)!=0) syncFlags |= SYNC_XVERBOSE;
+   if( find_option("unversioned","u",0)!=0 ) syncFlags |= SYNC_UNVERSIONED;
+   zHttpAuth = find_option("httpauth","B",1);
+   zDefaultUser = find_option("admin-user","A",1);
+@@ -262,7 +264,17 @@ void clone_cmd(void){
+     db_close(1);
+     if( nErr ){
+       file_delete(zRepo);
+-      fossil_fatal("server returned an error - clone aborted");
++      if( g.fHttpTrace ){
++        fossil_fatal(
++          "server returned an error - clone aborted\n\n%s",
++          http_last_trace_reply()
++        );
++      }else{
++        fossil_fatal(
++          "server returned an error - clone aborted\n"
++          "Rerun using --httptrace for more detail"
++        );
++      }
+     }
+     db_open_repository(zRepo);
+   }
+diff --git a/src/http.c b/src/http.c
+index 2bc4984..2d1f02a 100644
+--- a/src/http.c
++++ b/src/http.c
+@@ -49,6 +49,11 @@
+ /* Keep track of HTTP Basic Authorization failures */
+ static int fSeenHttpAuth = 0;
+ 
++/* The N value for most recent http-request-N.txt and http-reply-N.txt
++** trace files.
++*/
++static int traceCnt = 0;
++
+ /*
+ ** Construct the "login" card with the client credentials.
+ **
+@@ -208,6 +213,25 @@ char *prompt_for_httpauth_creds(void){
+   return zHttpAuth;
+ }
+ 
++/*
++** Return the complete text of the last HTTP reply as saved in the
++** http-reply-N.txt file.  This only works if run using --httptrace.
++** Without the --httptrace option, this routine returns a NULL pointer.
++** It still might return a NULL pointer if for some reason it cannot
++** find and open the last http-reply-N.txt file.
++*/
++char *http_last_trace_reply(void){
++  Blob x;
++  int n;
++  char *zFilename;
++  if( g.fHttpTrace==0 ) return 0;
++  zFilename = mprintf("http-reply-%d.txt", traceCnt);
++  n = blob_read_from_file(&x, zFilename, ExtFILE);
++  fossil_free(zFilename);
++  if( n<=0 ) return 0;
++  return blob_str(&x);
++}
++
+ /*
+ ** Sign the content in pSend, compress it, and send it to the server
+ ** via HTTP or HTTPS.  Get a reply, uncompress the reply, and store the reply
+@@ -230,7 +254,6 @@ int http_exchange(
+   Blob hdr;             /* The HTTP request header */
+   int closeConnection;  /* True to close the connection when done */
+   int iLength;          /* Expected length of the reply payload */
+-  int iRecvLen;         /* Received length of the reply payload */
+   int rc = 0;           /* Result code */
+   int iHttpVersion;     /* Which version of HTTP protocol server uses */
+   char *zLine;          /* A single line of the reply header */
+@@ -268,7 +291,6 @@ int http_exchange(
+   **      ./fossil test-http <http-request-1.txt
+   */
+   if( g.fHttpTrace ){
+-    static int traceCnt = 0;
+     char *zOutFile;
+     FILE *out;
+     traceCnt++;
+@@ -305,6 +327,7 @@ int http_exchange(
+   */
+   closeConnection = 1;
+   iLength = -1;
++  iHttpVersion = -1;
+   while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){
+     if( mHttpFlags & HTTP_VERBOSE ){
+       fossil_print("Read: [%s]\n", zLine);
+@@ -343,6 +366,7 @@ int http_exchange(
+         fossil_warning("server says: %s", &zLine[ii]);
+         goto write_err;
+       }
++      if( iHttpVersion<0 ) iHttpVersion = 1;
+       closeConnection = 0;
+     }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
+       for(i=15; fossil_isspace(zLine[i]); i++){}
+@@ -416,7 +440,12 @@ int http_exchange(
+       }
+     }
+   }
+-  if( iLength<0 ){
++  if( iHttpVersion<0 ){
++    /* We got nothing back from the server.  If using the ssh: protocol,
++    ** this might mean we need to add or remove the PATH=... argument
++    ** to the SSH command being sent.  If that is the case, retry the
++    ** request after adding or removing the PATH= argument.
++    */
+     fossil_warning("server did not reply");
+     goto write_err;
+   }
+@@ -429,13 +458,37 @@ int http_exchange(
+   ** Extract the reply payload that follows the header
+   */
+   blob_zero(pReply);
+-  blob_resize(pReply, iLength);
+-  iRecvLen = transport_receive(&g.url, blob_buffer(pReply), iLength);
+-  if( iRecvLen != iLength ){
+-    fossil_warning("response truncated: got %d bytes of %d", iRecvLen, iLength);
+-    goto write_err;
++  if( iLength==0 ){
++    /* No content to read */
++  }else if( iLength>0 ){
++    /* Read content of a known length */
++    int iRecvLen;         /* Received length of the reply payload */
++    blob_resize(pReply, iLength);
++    iRecvLen = transport_receive(&g.url, blob_buffer(pReply), iLength);
++    if( mHttpFlags & HTTP_VERBOSE ){
++      fossil_print("Reply received: %d of %d bytes\n", iRecvLen, iLength);
++    }
++    if( iRecvLen != iLength ){
++      fossil_warning("response truncated: got %d bytes of %d",
++                     iRecvLen, iLength);
++      goto write_err;
++    }
++  }else{
++    /* Read content until end-of-file */
++    int iRecvLen;         /* Received length of the reply payload */
++    unsigned int nReq = 1000;
++    unsigned int nPrior = 0;
++    do{
++      nReq *= 2;
++      blob_resize(pReply, nPrior+nReq);
++      iRecvLen = transport_receive(&g.url, &pReply->aData[nPrior], (int)nReq);
++      nPrior += iRecvLen;
++      pReply->nUsed = nPrior;
++    }while( iRecvLen==nReq && nReq<0x20000000 );
++    if( mHttpFlags & HTTP_VERBOSE ){
++      fossil_print("Reply received: %u bytes (w/o content-length)\n", nPrior);
++    }
+   }
+-  blob_resize(pReply, iLength);
+   if( isError ){
+     char *z;
+     int i, j;
+diff --git a/src/main.c b/src/main.c
+index 5f5e277..2effa14 100644
+--- a/src/main.c
++++ b/src/main.c
+@@ -216,7 +216,9 @@ struct Global {
+   const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
+   const char *zSSLIdentity;  /* Value of --ssl-identity option, filename of
+                              ** SSL client identity */
+-#if defined(_WIN32) && USE_SEE
++
++  const char *zReqType;      /* Type of request: "HTTP", "CGI", "SCGI" */
++#if USE_SEE
+   const char *zPidKey;    /* Saved value of the --usepidkey option.  Only
+                            * applicable when using SEE on Windows. */
+ #endif
+@@ -2218,6 +2220,7 @@ void cmd_cgi(void){
+   fossil_binary_mode(g.httpOut);
+   fossil_binary_mode(g.httpIn);
+   g.cgiOutput = 1;
++  g.zReqType = "CGI";
+   fossil_set_timeout(FOSSIL_DEFAULT_TIMEOUT);
+   /* Find the name of the CGI control file */
+   if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){
+@@ -2653,6 +2656,7 @@ void cmd_http(void){
+   g.fNoHttpCompress = find_option("nocompress",0,0)!=0;
+   g.zExtRoot = find_option("extroot",0,1);
+   g.zCkoutAlias = find_option("ckout-alias",0,1);
++  g.zReqType = "HTTP";
+   zInFile = find_option("in",0,1);
+   if( zInFile ){
+     backoffice_disable();
+@@ -2670,6 +2674,7 @@ void cmd_http(void){
+   }
+   zIpAddr = find_option("ipaddr",0,1);
+   useSCGI = find_option("scgi", 0, 0)!=0;
++  if( useSCGI ) g.zReqType = "SCGI";
+   zAltBase = find_option("baseurl", 0, 1);
+   if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay();
+   if( zAltBase ) set_base_url(zAltBase);
+@@ -2750,6 +2755,7 @@ void cmd_test_http(void){
+   fossil_binary_mode(g.httpIn);
+   g.zExtRoot = find_option("extroot",0,1);
+   find_server_repository(2, 0);
++  g.zReqType = "HTTP";
+   g.cgiOutput = 1;
+   g.fNoHttpCompress = 1;
+   g.fullHttpReply = 1;
+@@ -2930,7 +2936,11 @@ void cmd_webserver(void){
+   if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1;
+   zAltBase = find_option("baseurl", 0, 1);
+   fCreate = find_option("create",0,0)!=0;
+-  if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
++  g.zReqType = "HTTP";
++  if( find_option("scgi", 0, 0)!=0 ){
++    g.zReqType = "SCGI";
++    flags |= HTTP_SERVER_SCGI;
++  }
+   if( zAltBase ){
+     set_base_url(zAltBase);
+   }
+diff --git a/src/xfer.c b/src/xfer.c
+index f1e5399..7f9153d 100644
+--- a/src/xfer.c
++++ b/src/xfer.c
+@@ -1822,6 +1822,7 @@ static const char zBriefFormat[] =
+ #define SYNC_UV_DRYRUN      0x0400    /* Do not actually exchange files */
+ #define SYNC_IFABLE         0x0800    /* Inability to sync is not fatal */
+ #define SYNC_CKIN_LOCK      0x1000    /* Lock the current check-in */
++#define SYNC_XVERBOSE       0x20000    /* Extra verbose.  Network traffic */
+ #endif
+ 
+ /*
diff -Nru fossil-2.15.2/debian/patches/series fossil-2.15.2/debian/patches/series
--- fossil-2.15.2/debian/patches/series	2021-06-15 09:55:20.000000000 +0000
+++ fossil-2.15.2/debian/patches/series	2024-05-14 21:29:39.000000000 +0000
@@ -1 +1,2 @@
 debian-changes
+0002-Deal-with-the-missing-Content-Length-field.patch

Attachment: signature.asc
Description: This is a digitally signed message part.


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

Hi,

Each of these bugs relates to an update including in today's final
bullseye 11.11 point release.

Regards,

Adam

--- End Message ---

Reply via email to