!23 [sync] PR-17: fix CVE-2024-39929
From: @openeuler-sync-bot Reviewed-by: @small_leek Signed-off-by: @small_leek
This commit is contained in:
commit
aa47563e2e
@ -0,0 +1,159 @@
|
||||
From 6ce5c70cff8989418e05d01fd2a57703007a6357 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Mon, 1 Jul 2024 19:35:12 +0100
|
||||
Subject: [PATCH] Fix MIME parsing of filenames specified using multiple
|
||||
parameters. Bug 3099
|
||||
|
||||
---
|
||||
doc/ChangeLog | 3 +++
|
||||
doc/spec.txt | 10 +++++-----
|
||||
src/mime.c | 51 +++++++++++++++++++++++++++++----------------------
|
||||
3 files changed, 37 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/doc/ChangeLog b/doc/ChangeLog
|
||||
index 3e6da91..095bdb4 100644
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -148,6 +148,9 @@ JH/32 Fix CHUNKING for a second message on a connection when the first was
|
||||
JH/33 Fis ${srs_encode ...} to handle an empty sender address, now returning
|
||||
an empty address. Previously the expansion returned an error.
|
||||
|
||||
+JH/34 Bug 3099: fix parsing of MIME filenames split over multiple paramemters.
|
||||
+ Previously the $mime_filename variable would have an incorrect value.
|
||||
+
|
||||
HS/01 Bug 2855: Handle a v4mapped sender address given us by a frontending
|
||||
proxy. Previously these were misparsed, leading to paniclog entries.
|
||||
|
||||
diff --git a/doc/spec.txt b/doc/spec.txt
|
||||
index ddadcaf..9128166 100644
|
||||
--- a/doc/spec.txt
|
||||
+++ b/doc/spec.txt
|
||||
@@ -32165,13 +32165,13 @@ The right hand side is expanded before use. After expansion, the value can be:
|
||||
the default path is then used.
|
||||
|
||||
The decode condition normally succeeds. It is only false for syntax errors or
|
||||
-unusual circumstances such as memory shortages. You can easily decode a file
|
||||
-with its original, proposed filename using
|
||||
+errors or unusual circumstances such as memory shortages.
|
||||
|
||||
-decode = $mime_filename
|
||||
+The variable &$mime_filename$& will have the suggested name for the file.
|
||||
+Note however that this might contain anything, and is very difficult
|
||||
+to safely use as all or even part of the filename.
|
||||
|
||||
-However, you should keep in mind that $mime_filename might contain anything. If
|
||||
-you place files outside of the default path, they are not automatically
|
||||
+If you place files outside of the default path, they are not
|
||||
unlinked.
|
||||
|
||||
For RFC822 attachments (these are messages attached to messages, with a
|
||||
diff --git a/src/mime.c b/src/mime.c
|
||||
index c192199..e7af413 100644
|
||||
--- a/src/mime.c
|
||||
+++ b/src/mime.c
|
||||
@@ -586,10 +586,10 @@ while(1)
|
||||
|
||||
while (*p)
|
||||
{
|
||||
- DEBUG(D_acl) debug_printf_indent("MIME: considering paramlist '%s'\n", p);
|
||||
+ DEBUG(D_acl)
|
||||
+ debug_printf_indent("MIME: considering paramlist '%s'\n", p);
|
||||
|
||||
- if ( !mime_filename
|
||||
- && strncmpic(CUS"content-disposition:", header, 20) == 0
|
||||
+ if ( strncmpic(CUS"content-disposition:", header, 20) == 0
|
||||
&& strncmpic(CUS"filename*", p, 9) == 0
|
||||
)
|
||||
{ /* RFC 2231 filename */
|
||||
@@ -603,11 +603,12 @@ while(1)
|
||||
|
||||
if (q && *q)
|
||||
{
|
||||
- uschar * temp_string, * err_msg;
|
||||
+ uschar * temp_string, * err_msg, * fname = q;
|
||||
int slen;
|
||||
|
||||
/* build up an un-decoded filename over successive
|
||||
filename*= parameters (for use when 2047 decode fails) */
|
||||
+/*XXX could grow a gstring here */
|
||||
|
||||
mime_fname_rfc2231 = string_sprintf("%#s%s",
|
||||
mime_fname_rfc2231, q);
|
||||
@@ -622,26 +623,32 @@ while(1)
|
||||
/* look for a ' in the "filename" */
|
||||
while(*s != '\'' && *s) s++; /* s is 1st ' or NUL */
|
||||
|
||||
- if ((size = s-q) > 0)
|
||||
- mime_filename_charset = string_copyn(q, size);
|
||||
+ if (*s) /* there was a ' */
|
||||
+ {
|
||||
+ if ((size = s-q) > 0)
|
||||
+ mime_filename_charset = string_copyn(q, size);
|
||||
|
||||
- if (*(p = s)) p++;
|
||||
- while(*p == '\'') p++; /* p is after 2nd ' */
|
||||
+ if (*(fname = s)) fname++;
|
||||
+ while(*fname == '\'') fname++; /* fname is after 2nd ' */
|
||||
+ }
|
||||
}
|
||||
- else
|
||||
- p = q;
|
||||
|
||||
- DEBUG(D_acl) debug_printf_indent("MIME: charset %s fname '%s'\n",
|
||||
- mime_filename_charset ? mime_filename_charset : US"<NULL>", p);
|
||||
+ DEBUG(D_acl)
|
||||
+ debug_printf_indent("MIME: charset %s fname '%s'\n",
|
||||
+ mime_filename_charset ? mime_filename_charset : US"<NULL>",
|
||||
+ fname);
|
||||
|
||||
- temp_string = rfc2231_to_2047(p, mime_filename_charset, &slen);
|
||||
- DEBUG(D_acl) debug_printf_indent("MIME: 2047-name %s\n", temp_string);
|
||||
+ temp_string = rfc2231_to_2047(fname, mime_filename_charset,
|
||||
+ &slen);
|
||||
+ DEBUG(D_acl)
|
||||
+ debug_printf_indent("MIME: 2047-name %s\n", temp_string);
|
||||
|
||||
temp_string = rfc2047_decode(temp_string, FALSE, NULL, ' ',
|
||||
- NULL, &err_msg);
|
||||
- DEBUG(D_acl) debug_printf_indent("MIME: plain-name %s\n", temp_string);
|
||||
+ NULL, &err_msg);
|
||||
+ DEBUG(D_acl)
|
||||
+ debug_printf_indent("MIME: plain-name %s\n", temp_string);
|
||||
|
||||
- if (!temp_string || (size = Ustrlen(temp_string)) == slen)
|
||||
+ if (!temp_string || (size = Ustrlen(temp_string)) == slen)
|
||||
decoding_failed = TRUE;
|
||||
else
|
||||
/* build up a decoded filename over successive
|
||||
@@ -650,9 +657,9 @@ while(1)
|
||||
mime_filename = mime_fname = mime_fname
|
||||
? string_sprintf("%s%s", mime_fname, temp_string)
|
||||
: temp_string;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ } /*!decoding_failed*/
|
||||
+ } /*q*/
|
||||
+ } /*2231 filename*/
|
||||
|
||||
else
|
||||
/* look for interesting parameters */
|
||||
@@ -681,7 +688,7 @@ while(1)
|
||||
|
||||
|
||||
/* There is something, but not one of our interesting parameters.
|
||||
- Advance past the next semicolon */
|
||||
+ Advance past the next semicolon */
|
||||
p = mime_next_semicolon(p);
|
||||
if (*p) p++;
|
||||
} /* param scan on line */
|
||||
@@ -799,5 +806,5 @@ return rc;
|
||||
|
||||
#endif /*WITH_CONTENT_SCAN*/
|
||||
|
||||
-/* vi: sw ai sw=2
|
||||
+/* vi: aw ai sw=2
|
||||
*/
|
||||
--
|
||||
2.33.0
|
||||
|
||||
266
backport-bug3099-MIME-support-RFC-2331-for-name.patch
Normal file
266
backport-bug3099-MIME-support-RFC-2331-for-name.patch
Normal file
@ -0,0 +1,266 @@
|
||||
From 1b3209b0577a9327ebb076f3b32b8a159c253f7b Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Tue, 2 Jul 2024 14:41:19 +0100
|
||||
Subject: [PATCH] MIME: support RFC 2331 for name=. Bug 3099
|
||||
|
||||
---
|
||||
doc/ChangeLog | 2 +
|
||||
src/mime.c | 188 ++++++++++++++++++++++++++------------------------
|
||||
2 files changed, 100 insertions(+), 90 deletions(-)
|
||||
|
||||
diff --git a/doc/ChangeLog b/doc/ChangeLog
|
||||
index 095bdb4..c1f0499 100644
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -150,6 +150,8 @@ JH/33 Fis ${srs_encode ...} to handle an empty sender address, now returning
|
||||
|
||||
JH/34 Bug 3099: fix parsing of MIME filenames split over multiple paramemters.
|
||||
Previously the $mime_filename variable would have an incorrect value.
|
||||
+ While in the code, extend coverage to name= which previously was only
|
||||
+ supported for single parameters, despite also filling in $mime_filename.
|
||||
|
||||
HS/01 Bug 2855: Handle a v4mapped sender address given us by a frontending
|
||||
proxy. Previously these were misparsed, leading to paniclog entries.
|
||||
diff --git a/src/mime.c b/src/mime.c
|
||||
index e7af413..f36823f 100644
|
||||
--- a/src/mime.c
|
||||
+++ b/src/mime.c
|
||||
@@ -29,10 +29,10 @@ static int mime_header_list_size = nelem(mime_header_list);
|
||||
|
||||
static mime_parameter mime_parameter_list[] = {
|
||||
/* name namelen value */
|
||||
- { US"name=", 5, &mime_filename },
|
||||
- { US"filename=", 9, &mime_filename },
|
||||
- { US"charset=", 8, &mime_charset },
|
||||
- { US"boundary=", 9, &mime_boundary }
|
||||
+ { US"name", 4, &mime_filename },
|
||||
+ { US"filename", 8, &mime_filename },
|
||||
+ { US"charset", 7, &mime_charset },
|
||||
+ { US"boundary", 8, &mime_boundary }
|
||||
};
|
||||
|
||||
|
||||
@@ -576,8 +576,8 @@ while(1)
|
||||
if (*(p = q)) p++; /* jump past the ; */
|
||||
|
||||
{
|
||||
- uschar * mime_fname = NULL;
|
||||
- uschar * mime_fname_rfc2231 = NULL;
|
||||
+ gstring * mime_fname = NULL;
|
||||
+ gstring * mime_fname_rfc2231 = NULL;
|
||||
uschar * mime_filename_charset = NULL;
|
||||
BOOL decoding_failed = FALSE;
|
||||
|
||||
@@ -589,90 +589,92 @@ while(1)
|
||||
DEBUG(D_acl)
|
||||
debug_printf_indent("MIME: considering paramlist '%s'\n", p);
|
||||
|
||||
- if ( strncmpic(CUS"content-disposition:", header, 20) == 0
|
||||
- && strncmpic(CUS"filename*", p, 9) == 0
|
||||
- )
|
||||
- { /* RFC 2231 filename */
|
||||
- uschar * q;
|
||||
-
|
||||
- /* find value of the filename */
|
||||
- p += 9;
|
||||
- while(*p != '=' && *p) p++;
|
||||
- if (*p) p++; /* p is filename or NUL */
|
||||
- q = mime_param_val(&p); /* p now trailing ; or NUL */
|
||||
-
|
||||
- if (q && *q)
|
||||
+ /* look for interesting parameters */
|
||||
+ for (mime_parameter * mp = mime_parameter_list;
|
||||
+ mp < mime_parameter_list + nelem(mime_parameter_list);
|
||||
+ mp++
|
||||
+ ) if (strncmpic(mp->name, p, mp->namelen) == 0)
|
||||
+ {
|
||||
+ p += mp->namelen;
|
||||
+ if (*p == '*') /* RFC 2231 */
|
||||
{
|
||||
- uschar * temp_string, * err_msg, * fname = q;
|
||||
- int slen;
|
||||
-
|
||||
- /* build up an un-decoded filename over successive
|
||||
- filename*= parameters (for use when 2047 decode fails) */
|
||||
-/*XXX could grow a gstring here */
|
||||
-
|
||||
- mime_fname_rfc2231 = string_sprintf("%#s%s",
|
||||
- mime_fname_rfc2231, q);
|
||||
-
|
||||
- if (!decoding_failed)
|
||||
+ while (isdigit(*++p)) ; /* ignore cont-cnt values */
|
||||
+ if (*p == '*') p++; /* step over sep chset mark */
|
||||
+ if (*p == '=')
|
||||
{
|
||||
- int size;
|
||||
- if (!mime_filename_charset)
|
||||
+ uschar * q;
|
||||
+ p++; /* step over = */
|
||||
+ q = mime_param_val(&p); /* p now trailing ; or NUL */
|
||||
+
|
||||
+ if (q && *q) /* q is the dequoted value */
|
||||
{
|
||||
- uschar * s = q;
|
||||
+ uschar * err_msg, * fname = q;
|
||||
+ int slen;
|
||||
|
||||
- /* look for a ' in the "filename" */
|
||||
- while(*s != '\'' && *s) s++; /* s is 1st ' or NUL */
|
||||
+ /* build up an un-decoded filename over successive
|
||||
+ filename*= parameters (for use when 2047 decode fails) */
|
||||
|
||||
- if (*s) /* there was a ' */
|
||||
+ mime_fname_rfc2231 = string_cat(mime_fname_rfc2231, q);
|
||||
+
|
||||
+ if (!decoding_failed)
|
||||
{
|
||||
- if ((size = s-q) > 0)
|
||||
- mime_filename_charset = string_copyn(q, size);
|
||||
-
|
||||
- if (*(fname = s)) fname++;
|
||||
- while(*fname == '\'') fname++; /* fname is after 2nd ' */
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- DEBUG(D_acl)
|
||||
- debug_printf_indent("MIME: charset %s fname '%s'\n",
|
||||
- mime_filename_charset ? mime_filename_charset : US"<NULL>",
|
||||
- fname);
|
||||
-
|
||||
- temp_string = rfc2231_to_2047(fname, mime_filename_charset,
|
||||
- &slen);
|
||||
- DEBUG(D_acl)
|
||||
- debug_printf_indent("MIME: 2047-name %s\n", temp_string);
|
||||
-
|
||||
- temp_string = rfc2047_decode(temp_string, FALSE, NULL, ' ',
|
||||
- NULL, &err_msg);
|
||||
- DEBUG(D_acl)
|
||||
- debug_printf_indent("MIME: plain-name %s\n", temp_string);
|
||||
-
|
||||
- if (!temp_string || (size = Ustrlen(temp_string)) == slen)
|
||||
- decoding_failed = TRUE;
|
||||
- else
|
||||
- /* build up a decoded filename over successive
|
||||
- filename*= parameters */
|
||||
-
|
||||
- mime_filename = mime_fname = mime_fname
|
||||
- ? string_sprintf("%s%s", mime_fname, temp_string)
|
||||
- : temp_string;
|
||||
- } /*!decoding_failed*/
|
||||
- } /*q*/
|
||||
- } /*2231 filename*/
|
||||
-
|
||||
- else
|
||||
- /* look for interesting parameters */
|
||||
- for (mime_parameter * mp = mime_parameter_list;
|
||||
- mp < mime_parameter_list + nelem(mime_parameter_list);
|
||||
- mp++
|
||||
- ) if (strncmpic(mp->name, p, mp->namelen) == 0)
|
||||
- {
|
||||
- uschar * q;
|
||||
- uschar * dummy_errstr;
|
||||
+ if (!mime_filename_charset)
|
||||
+ { /* try for RFC 2231 chset/lang */
|
||||
+ uschar * s = q;
|
||||
+
|
||||
+ /* look for a ' in the raw paramval */
|
||||
+ while(*s != '\'' && *s) s++; /* s is 1st ' or NUL */
|
||||
+
|
||||
+ if (*s) /* there was a ' */
|
||||
+ {
|
||||
+ int size;
|
||||
+ if ((size = s-q) > 0)
|
||||
+ mime_filename_charset = string_copyn(q, size);
|
||||
+
|
||||
+ if (*(fname = s)) fname++;
|
||||
+ while(*fname == '\'') fname++; /*fname is after 2nd '*/
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ DEBUG(D_acl)
|
||||
+ debug_printf_indent("MIME: charset %s fname '%s'\n",
|
||||
+ mime_filename_charset ? mime_filename_charset : US"<NULL>",
|
||||
+ fname);
|
||||
+
|
||||
+ fname = rfc2231_to_2047(fname, mime_filename_charset,
|
||||
+ &slen);
|
||||
+ DEBUG(D_acl)
|
||||
+ debug_printf_indent("MIME: 2047-name %s\n", fname);
|
||||
+
|
||||
+ fname = rfc2047_decode(fname, FALSE, NULL, ' ',
|
||||
+ NULL, &err_msg);
|
||||
+ DEBUG(D_acl) debug_printf_indent(
|
||||
+ "MIME: plain-name %s\n", fname);
|
||||
+
|
||||
+ if (!fname || Ustrlen(fname) == slen)
|
||||
+ decoding_failed = TRUE;
|
||||
+ else if (mp->value == &mime_filename)
|
||||
+ {
|
||||
+ /* build up a decoded filename over successive
|
||||
+ filename*= parameters */
|
||||
+
|
||||
+ mime_fname = string_cat(mime_fname, fname);
|
||||
+ mime_filename = string_from_gstring(mime_fname);
|
||||
+ }
|
||||
+ } /*!decoding_failed*/
|
||||
+ } /*q*/
|
||||
+
|
||||
+ if (*p) p++; /* p is past ; */
|
||||
+ goto param_done; /* done matching param names */
|
||||
+ } /*2231 param coding extension*/
|
||||
+ }
|
||||
+ else if (*p == '=')
|
||||
+ { /* non-2231 param */
|
||||
+ uschar * q, * dummy_errstr;
|
||||
|
||||
/* grab the value and copy to its expansion variable */
|
||||
- p += mp->namelen;
|
||||
+
|
||||
+ if (*p) p++; /* step over = */
|
||||
q = mime_param_val(&p); /* p now trailing ; or NUL */
|
||||
|
||||
*mp->value = q && *q
|
||||
@@ -683,26 +685,32 @@ while(1)
|
||||
"MIME: found %s parameter in %s header, value '%s'\n",
|
||||
mp->name, mh->name, *mp->value);
|
||||
|
||||
- break; /* done matching param names */
|
||||
+ if (*p) p++; /* p is past ; */
|
||||
+ goto param_done; /* done matching param names */
|
||||
}
|
||||
+ } /* interesting parameters */
|
||||
|
||||
+ /* There is something, but not one of our interesting parameters.
|
||||
+ Advance past the next semicolon */
|
||||
|
||||
- /* There is something, but not one of our interesting parameters.
|
||||
- Advance past the next semicolon */
|
||||
- p = mime_next_semicolon(p);
|
||||
- if (*p) p++;
|
||||
- } /* param scan on line */
|
||||
+ p = mime_next_semicolon(p);
|
||||
+ if (*p) p++;
|
||||
+ param_done:
|
||||
+ ; /* param scan on line */
|
||||
+ }
|
||||
|
||||
if (strncmpic(CUS"content-disposition:", header, 20) == 0)
|
||||
{
|
||||
- if (decoding_failed) mime_filename = mime_fname_rfc2231;
|
||||
+ if (decoding_failed)
|
||||
+ mime_filename = string_from_gstring(mime_fname_rfc2231);
|
||||
|
||||
DEBUG(D_acl) debug_printf_indent(
|
||||
"MIME: found %s parameter in %s header, value is '%s'\n",
|
||||
"filename", mh->name, mime_filename);
|
||||
}
|
||||
}
|
||||
- }
|
||||
+ break;
|
||||
+ } /* interesting headers */
|
||||
|
||||
/* set additional flag variables (easier access) */
|
||||
if ( mime_content_type
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
Summary: The exim mail transfer agent
|
||||
Name: exim
|
||||
Version: 4.96
|
||||
Release: 3
|
||||
Release: 4
|
||||
License: GPLv2+
|
||||
Url: https://www.exim.org/
|
||||
|
||||
@ -45,6 +45,9 @@ Patch4: exim-4.96-opendmarc-1.4-build-fix.patch
|
||||
Patch5: exim-4.96-build-fix.patch
|
||||
Patch6: CVE-2023-51766.patch
|
||||
Patch7: CVE-2022-3559.patch
|
||||
# CVE-2024-39929
|
||||
Patch8: backport-bug3099-Fix-MIME-parsing-of-filenames-specified-using-multiple-parameters.patch
|
||||
Patch9: backport-bug3099-MIME-support-RFC-2331-for-name.patch
|
||||
|
||||
Requires: /etc/pki/tls/certs /etc/pki/tls/private
|
||||
Requires: setup
|
||||
@ -484,6 +487,9 @@ fi
|
||||
%{_sysconfdir}/cron.daily/greylist-tidy.sh
|
||||
|
||||
%changelog
|
||||
* Thu Jul 11 2024 zhangxianting <zhangxianting@uniontech.com> - 4.96-4
|
||||
- fix CVE-2024-39929
|
||||
|
||||
* Thu Jul 11 2024 technology208 <technology@208suo.com> - 4.96-3
|
||||
- Fix CVE-2022-3559
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user