--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock
Please unblock package postsrsd
[ Reason ]
Security fix for CVE-2021-35525.
[ Impact ]
Package is vulnerable to a potential DoS attack.
[ Tests ]
Tests from upstream backported, testsuite from upstream passes, manually tested
functionality.
[ Risks ]
Fix is a one-to-one backport from upstream, modulus formatting changes.
[ 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 testing
[ Other info ]
N/A
unblock postsrsd/1.10-2
diff -Nru postsrsd-1.10/debian/changelog postsrsd-1.10/debian/changelog
--- postsrsd-1.10/debian/changelog 2020-12-02 22:36:36.000000000 +0100
+++ postsrsd-1.10/debian/changelog 2021-07-14 21:21:11.000000000 +0200
@@ -1,4 +1,12 @@
-postsrsd (1.10-1) UNRELEASED; urgency=medium
+postsrsd (1.10-2) UNRELEASED; urgency=medium
+
+ * Fix CVE-2021-35525: potential DoS when Postfix sends certain long data
+ fields such as multiple concatenated email addresses. Fix backported from
+ upstream commit 077be98d8c8. (Closes: #990439)
+
+ -- Oxan van Leeuwen <o...@oxanvanleeuwen.nl> Wed, 14 Jul 2021 21:21:11 +0200
+
+postsrsd (1.10-1) unstable; urgency=medium
* New upstream release (Closes: #975633)
* Drop patches integrated upstream
diff -Nru
postsrsd-1.10/debian/patches/0002-SECURITY-Fix-DoS-on-overly-long-input-from-Postfix.patch
postsrsd-1.10/debian/patches/0002-SECURITY-Fix-DoS-on-overly-long-input-from-Postfix.patch
---
postsrsd-1.10/debian/patches/0002-SECURITY-Fix-DoS-on-overly-long-input-from-Postfix.patch
1970-01-01 01:00:00.000000000 +0100
+++
postsrsd-1.10/debian/patches/0002-SECURITY-Fix-DoS-on-overly-long-input-from-Postfix.patch
2021-07-14 21:21:11.000000000 +0200
@@ -0,0 +1,211 @@
+From: =?utf-8?q?Timo_R=C3=B6hling?= <t...@gaussglocke.de>
+Date: Sun, 21 Mar 2021 15:27:55 +0100
+Subject: SECURITY: Fix DoS on overly long input from Postfix
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+Thanks to Mateusz Jończyk who reported this issue and gave valuable
+feedback for its resolution.
+
+PostSRSd would hang on an overly long GET request, because the
+fread()/fwrite() logic in the subprocess would get confused by the
+remaining input line in its buffer.
+
+Theoretically, this error should never occur, as Postfix is supposed to
+send valid email addresses only, which are shorter than the buffer, even
+assuming every single character is percent-encoded. However, Postfix
+sometimes does seem to send malformed request with multiple concatenated
+email addresses. I'm not sure if there's a reliable way to trigger this
+condition by an external attacker, but it is a security bug in PostSRSd
+nevertheless.
+
+Fixes CVE-2021-35525.
+
+Origin:
https://github.com/roehling/postsrsd/commit/077be98d8c8a9847e4ae0c7dc09e7474cbe27db2
+Forwarded: not-needed
+Last-Update: 2021-07-14
+---
+ postsrsd.c | 52 ++++++++++++++++++++++++++++++-------------------
+ run_postsrsd_tests.bats | 40 +++++++++++++++++++++++++++++++++----
+ 2 files changed, 68 insertions(+), 24 deletions(-)
+
+diff --git a/postsrsd.c b/postsrsd.c
+index c009d8f..5ebf7f6 100644
+--- a/postsrsd.c
++++ b/postsrsd.c
+@@ -518,9 +518,9 @@ int main (int argc, char **argv)
+ fds[sc].events = POLLIN;
+ }
+ while(TRUE) {
+ int conn;
+- FILE *fp;
++ FILE *fp_read, *fp_write;
+ char linebuf[1024], *line;
+ char keybuf[1024], *key;
+
+ if (poll(fds, socket_count, 1000) < 0) {
+@@ -540,41 +540,53 @@ int main (int argc, char **argv)
+ int i;
+ // close listen sockets so that we don't stop the main daemon
process from restarting
+ for (i = 0; i < socket_count; ++i) close (sockets[i]);
+
+- fp = fdopen(conn, "r+");
+- if (fp == NULL) exit(EXIT_FAILURE);
+- fds[0].fd = conn;
+- fds[0].events = POLLIN;
+- if (poll(fds, 1, timeout * 1000) <= 0) return EXIT_FAILURE;
+- line = fgets(linebuf, sizeof(linebuf), fp);
+- while (line) {
+- fseek (fp, 0, SEEK_CUR); /* Workaround for Solaris */
++ /* create separate input/output streams */
++ fp_read = fdopen(conn, "r");
++ if (fp_read == NULL)
++ return EXIT_FAILURE;
++ fp_write = fdopen(dup(conn), "w");
++ if (fp_write == NULL) return EXIT_FAILURE;
++ errno = 0;
++ alarm(timeout);
++ if (errno != 0)
++ return EXIT_FAILURE;
++ while ((line = fgets(linebuf, sizeof(linebuf), fp_read))) {
+ char* token;
++ alarm(0);
++ if (strlen(line) >= sizeof(linebuf) - 1) {
++ fprintf(fp_write, "500 Invalid request\n");
++ fflush(fp_write);
++ return EXIT_FAILURE;
++ }
+ token = strtok(line, " \r\n");
+ if (token == NULL || strcmp(token, "get") != 0) {
+- fprintf (fp, "500 Invalid request\n");
+- fflush (fp);
++ fprintf (fp_write, "500 Invalid request\n");
++ fflush (fp_write);
+ return EXIT_FAILURE;
+ }
+ token = strtok(NULL, "\r\n");
+ if (!token) {
+- fprintf (fp, "500 Invalid request\n");
+- fflush (fp);
++ fprintf (fp_write, "500 Invalid request\n");
++ fflush (fp_write);
+ return EXIT_FAILURE;
+ }
+ key = url_decode(keybuf, sizeof(keybuf), token);
+ if (!key) {
+- fprintf (fp, "500 Invalid request\n");
+- fflush(fp);
++ fprintf (fp_write, "500 Invalid request\n");
++ fflush(fp_write);
+ return EXIT_FAILURE;
+ }
+- handler[sc](srs, fp, key, domain, excludes);
+- fflush (fp);
+- if (poll(fds, 1, timeout * 1000) <= 0) break;
+- line = fgets(linebuf, sizeof(linebuf), fp);
++ handler[sc](srs, fp_write, key, domain, excludes);
++ fflush (fp_write);
++ errno = 0;
++ alarm(timeout);
++ if (errno != 0)
++ return EXIT_FAILURE;
+ }
+- fclose (fp);
++ fclose (fp_write);
++ fclose (fp_read);
+ return EXIT_SUCCESS;
+ }
+ close (conn);
+ }
+diff --git a/run_postsrsd_tests.bats b/run_postsrsd_tests.bats
+index f4b04bb..3d52a50 100755
+--- a/run_postsrsd_tests.bats
++++ b/run_postsrsd_tests.bats
+@@ -2,9 +2,9 @@
+ # vim: filetype=bash:
+
+ if [ ! -x "$POSTSRSD" ]
+ then
+- for builddir in . build* obj*
++ for builddir in . build* obj* _build*
+ do
+ if [ -x "${builddir}/postsrsd" ]
+ then
+ POSTSRSD="${builddir}/postsrsd"
+@@ -14,9 +14,9 @@ then
+ fi
+ if [ ! -x "$POSTSRSD" ]
+ then
+ cat>&2 <<- EOF
+- cannot find postsrsd executable (looked in ., build*, obj*)
++ cannot find postsrsd executable (looked in ., build*, obj*, _build*)
+ please build the executable first, or set the POSTSRSD
+ environment variable if it is in a different location.
+
+ EOF
+@@ -25,14 +25,21 @@ fi
+
+ LANG=C.UTF-8
+
+
++fillchar()
++{
++ local count="$1"
++ local char="$2"
++ eval 'printf "'"$char"'%.0s" {1..'"$count"'}'
++}
++
+ start_postsrsd_at()
+ {
+ echo 'tops3cr3t' > "$BATS_TMPDIR/postsrsd.secret"
+ local faketime="$1"
+ shift
+- faketime "${faketime}" ${POSTSRSD} -D -f 10001 -r 10002 -p
"$BATS_TMPDIR/postsrsd.pid" -s "$BATS_TMPDIR/postsrsd.secret" -d example.com
"$@"
++ faketime "${faketime}" ${POSTSRSD} -D -t1 -f 10001 -r 10002 -p
"$BATS_TMPDIR/postsrsd.pid" -s "$BATS_TMPDIR/postsrsd.secret" -d example.com
"$@"
+ }
+
+ stop_postsrsd()
+ {
+@@ -158,9 +165,9 @@ teardown()
+ read<&9 line
+ [[ "$line" =~ ^"500 Domain excluded" ]]
+ }
+
+-@test "SRS invalid requests" {
++@test "Malformed or invalid requests" {
+ start_postsrsd_at "2020-01-01 00:01:00 UTC"
+ exec 9<>/dev/tcp/127.0.0.1/10001
+ echo>&9 "get"
+ read<&9 line
+@@ -172,5 +179,30 @@ teardown()
+ exec 9<>/dev/tcp/127.0.0.1/10001
+ echo>&9 "get encoding%er...@otherdomain.com"
+ read<&9 line
+ [[ "$line" =~ ^500 ]]
++ exec 9<>/dev/tcp/127.0.0.1/10001
++ # Try to overflow the input buffer
++ echo>&9 "get too_long@`fillchar 1024 a`.com"
++ read<&9 line
++ [[ "$line" =~ ^500 ]]
++}
++
++@test "Pipelining multiple requests" {
++ start_postsrsd_at "2020-01-01 00:01:00 UTC"
++ exec 9<>/dev/tcp/127.0.0.1/10001
++ # Send two requests at once and see if PostSRSd answers both
++ echo>&9 -e "get t...@domain1.com\nget t...@domain2.com"
++ read<&9 line
++ [[ "$line" =~ ^200 ]]
++ read<&9 line
++ [[ "$line" =~ ^200 ]]
++}
++
++@test "Session timeout" {
++ start_postsrsd_at "2020-01-01 00:01:00 UTC"
++ exec 9<>/dev/tcp/127.0.0.1/10001
++ # Wait until PostSRSd disconnects due to inactivity
++ sleep 2
++ echo >&9 "get t...@example.com"
++ ! read <&9 line
+ }
diff -Nru postsrsd-1.10/debian/patches/series
postsrsd-1.10/debian/patches/series
--- postsrsd-1.10/debian/patches/series 2020-12-02 22:36:36.000000000 +0100
+++ postsrsd-1.10/debian/patches/series 2021-07-14 21:21:11.000000000 +0200
@@ -1 +1,2 @@
0001-Run-as-postsrsd-user-by-default.patch
+0002-SECURITY-Fix-DoS-on-overly-long-input-from-Postfix.patch
--- End Message ---