Package: release.debian.org
Control: affects -1 + src:fossil
X-Debbugs-Cc: fos...@packages.debian.org
User: release.debian....@packages.debian.org
Usertags: pu
Tags: bookworm
X-Debbugs-Cc: b...@beuc.net
Severity: normal
Hello Release Team,
[ Reason ]
This update fixes #1070069: serious issue in the fossil HTTP client,
related to the fix for CVE-2024-24795 for apache2 (2.4.59-1~deb12u1),
preventing it from cloning from a fixed Apache2 server (which now
strips the 'Content-Length' response header issued by the fossil CGI
server, to prevent a general case of response splitting).
This was fixed in DLA-3819-1 for fossil/buster.
https://lists.debian.org/debian-lts-announce/2024/05/msg00014.html
This superseeds #1070998 (full backport proposal), this is a targeted
fix.
[ Impact ]
The user can't use the fossil client to clone Fossil repositories
hosted with Apache2 (unless a specific server-side work-around was
applied in the Apache2 configuration), and otherwise can't cope with a
network configuration where the 'Content-Length' header is not
provided by the remote server/proxy stack.
[ Tests ]
No new test cases were introduced upstream. The embedded test suite
has errors, even in unstable, but with the patch it runs with the same
number of successes and errors, so no regression was spotted.
Later history of src/http.c was reviewed to spot possible regressions,
and follow-up fixes for 'Connection' headers is also included.
Manual testing was performed by reproducing the issue with an
Apache2+CGI+Fossil setup, with or without the configuration
work-around, and with or without enabling mod_http2 which triggers
different 'Connection' headers. In all cases cloning is now fixed.
[ Risks ]
The Fossil internal HTTP code seems a bit ad-hoc, but the upstream fix
is published for a year, and so is the buster DLA.
[ 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 stable
[X] the issue is verified as fixed in unstable (1:2.24-5)
[ Changes ]
Minimal backport of upstream changes, that make the HTTP client code a
bit more robust.
Typically the fossil client now can read data up to connection close
when the 'Content-Length' header is missing. Also fixes 'Connection'
header parsing to handle multiple values.
Unlike DLA-3819-1, no 'Break' header was introduced in debian/control,
as there's no particular conflict when fossil and apache2 are on the
same server. This is an issue with the fossil *client* and a remote
apache2.
[ Other info ]
A DLA is also planned for bullseye.
(#1071417 somehow didn't make it as a OSPU.)
diff -Nru fossil-2.21/debian/changelog fossil-2.21/debian/changelog
--- fossil-2.21/debian/changelog 2023-02-26 19:58:27.000000000 +0100
+++ fossil-2.21/debian/changelog 2025-05-04 11:12:18.000000000 +0200
@@ -1,3 +1,13 @@
+fossil (1:2.21-1+deb12u1) bookworm; urgency=medium
+
+ * Non-maintainer upload by the LTS Security Team.
+ * Fix issue in the fossil HTTP client, related to the fix for
+ CVE-2024-24795/apache2, preventing it from cloning from a fixed
+ Apache2 server (which now strips the Content-Length response header
+ issued by the fossil CGI server). (Closes: #1070069)
+
+ -- Sylvain Beucler <b...@debian.org> Sun, 04 May 2025 11:12:18 +0200
+
fossil (1:2.21-1) unstable; urgency=medium
* Add upstream/metadata
diff -Nru fossil-2.21/debian/patches/CVE-2024-24795-regression.patch
fossil-2.21/debian/patches/CVE-2024-24795-regression.patch
--- fossil-2.21/debian/patches/CVE-2024-24795-regression.patch 1970-01-01
01:00:00.000000000 +0100
+++ fossil-2.21/debian/patches/CVE-2024-24795-regression.patch 2025-05-04
11:12:18.000000000 +0200
@@ -0,0 +1,139 @@
+Origin: https://fossil-scm.org/home/info/a8e33fb161f45b65
+Origin: https://fossil-scm.org/home/info/71919ad1b542832c
+Origin: https://fossil-scm.org/home/info/f4ffefe708793b03
+Origin: https://fossil-scm.org/home/info/5f47bb59a7846aeb
+Reviewed-by: Sylvain Beucler <b...@debian.org>
+Last-Update: 2025-05-04
+
+Only backported parts relevant to the fossil HTTP client fix,
+discarded debugging improvements.
+
+Commit: a8e33fb161f45b65167f0dfe39b6fcbad21f5844ee469131fd8fa8fc09cd5e99
+Date: 2024-04-17 12:58:08
+Author: drh
+Comment: Fix the HTTP-reply parser so that it is able to deal with replies
that lack a Content-Length header field. This resolves the issue reported by
[forum:/forumpost/12ac403fd29cfc89|forum post 12ac403fd29cfc89]. Also in this
merge: (1) Add the --xverbose option to "fossil clone". (2) Improved error
messages when web servers misbehave. See also my misguided and incorrect
[https://bz.apache.org/bugzilla/show_bug.cgi?id=68905|Apache bug 68905].
Special thanks to Apache devs for setting me straight.
+Branch: trunk
+Tags: trunk
+Phase: *MERGE*
+
+Commit: 71919ad1b542832c615df0af08999c9624ade133f48d0f39448cf87d71fa1142
+Date: 2024-04-17 13:27:34
+Author: drh
+Comment: Only process HTTP replies that lack a Content-Length header if the
connection is set to be closed. Suggested by
[https://bz.apache.org/bugzilla/show_bug.cgi?id=68905].
+Branch: trunk
+Tags: trunk
+Phase:
+
+Commit: f4ffefe708793b036dc1d4a3c3806cdb24de73362df532779d1a80375a6347ad
+Date: 2024-04-17 14:02:19
+Author: drh
+Comment: Output a warning if a client sync or clone gets back a keep-alive
HTTP reply that lacks a content-length header.
+Branch: trunk
+Tags: trunk
+Phase:
+
+Commit: 5f47bb59a7846aeb3e073ffe24629bb87809b86358c7124d9b4596817c3599d5
+Date: 2024-04-21 16:20:19
+Author: drh
+Comment: Fix parsing of the argument to the "Connection:" header of HTTP
reply messages to deal with unusual arguments added by Apache mod_cgi. See
[forum:/forumpost/ca6fc85c80f4704f|forum thread ca6fc85c80f4704f].
+Branch: trunk
+Tags: trunk
+Phase: *MERGE*
+
+Index: fossil-2.21/src/http.c
+===================================================================
+--- fossil-2.21.orig/src/http.c
++++ fossil-2.21/src/http.c
+@@ -294,7 +294,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 */
+@@ -374,6 +373,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);
+@@ -412,17 +412,15 @@ 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++){}
+ iLength = atoi(&zLine[i]);
+ }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
+- char c;
+- for(i=11; fossil_isspace(zLine[i]); i++){}
+- c = zLine[i];
+- if( c=='c' || c=='C' ){
++ if( sqlite3_strlike("%close%", &zLine[11], 0)==0 ){
+ closeConnection = 1;
+- }else if( c=='k' || c=='K' ){
++ }else if( sqlite3_strlike("%keep-alive%", &zLine[11], 0)==0 ){
+ closeConnection = 0;
+ }
+ }else if( ( rc==301 || rc==302 || rc==307 || rc==308 ) &&
+@@ -485,7 +483,7 @@ int http_exchange(
+ }
+ }
+ }
+- if( iLength<0 ){
++ if( iHttpVersion<0 ){
+ fossil_warning("server did not reply");
+ goto write_err;
+ }
+@@ -498,13 +496,40 @@ 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 if( closeConnection ){
++ /* 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);
++ }
++ }else{
++ assert( iLength<0 && !closeConnection );
++ fossil_warning("\"content-length\" missing from %d keep-alive reply", rc);
+ }
+- blob_resize(pReply, iLength);
+ if( isError ){
+ char *z;
+ int i, j;
diff -Nru fossil-2.21/debian/patches/series fossil-2.21/debian/patches/series
--- fossil-2.21/debian/patches/series 2023-02-26 19:58:27.000000000 +0100
+++ fossil-2.21/debian/patches/series 2025-05-03 21:16:09.000000000 +0200
@@ -1 +1,2 @@
debian-changes
+CVE-2024-24795-regression.patch