1 From 327f647a849c3974e7107b5386421b0058c15b29 Mon Sep 17 00:00:00 2001
2 From: Qualys Security Advisory <qsa@qualys.com>
3 Date: Sun, 21 Feb 2021 21:17:31 -0800
4 Subject: [PATCH 10/29] CVE-2020-28026: Line truncation and injection in
11 462 while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1
12 463 && big_buffer[len-1] != '\n'
14 465 { /* buffer not big enough for line; certs make this possible */
16 467 if (big_buffer_size >= BIG_BUFFER_SIZE*4) goto SPOOL_READ_ERROR;
17 468 buf = store_get_perm(big_buffer_size *= 2, FALSE);
18 469 memcpy(buf, big_buffer, --len);
20 The --len in memcpy() chops off a useful byte (we know for sure that
21 big_buffer[len-1] is not a '\n' because we entered the while loop).
23 src/spool_in.c | 48 +++++++++++++++++++++++++++++++---------------
24 1 file changed, 33 insertions(+), 15 deletions(-)
26 diff --git a/src/spool_in.c b/src/spool_in.c
27 index 2d349778c..dbbcf23ee 100644
30 @@ -307,6 +307,36 @@ dsn_ret = 0;
35 +fgets_big_buffer(FILE *fp)
40 +if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) return NULL;
42 +while ((len = Ustrlen(big_buffer)) == big_buffer_size-1
43 + && big_buffer[len-1] != '\n')
48 + if (big_buffer_size >= BIG_BUFFER_SIZE * 4) return NULL;
49 + newsize = big_buffer_size * 2;
50 + newbuffer = store_get_perm(newsize);
51 + memcpy(newbuffer, big_buffer, len);
53 + big_buffer = newbuffer;
54 + big_buffer_size = newsize;
55 + if (Ufgets(big_buffer + len, big_buffer_size - len, fp) == NULL) return NULL;
58 +if (len <= 0 || big_buffer[len-1] != '\n') return NULL;
65 /*************************************************
66 * Read spool header file *
67 @@ -450,21 +480,9 @@ p = big_buffer + 2;
71 - if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
72 + if (fgets_big_buffer(fp) == NULL) goto SPOOL_READ_ERROR;
73 if (big_buffer[0] != '-') break;
74 - while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1
75 - && big_buffer[len-1] != '\n'
77 - { /* buffer not big enough for line; certs make this possible */
79 - if (big_buffer_size >= BIG_BUFFER_SIZE*4) goto SPOOL_READ_ERROR;
80 - buf = store_get_perm(big_buffer_size *= 2);
81 - memcpy(buf, big_buffer, --len);
83 - if (Ufgets(big_buffer+len, big_buffer_size-len, fp) == NULL)
84 - goto SPOOL_READ_ERROR;
86 - big_buffer[len-1] = 0;
87 + big_buffer[Ustrlen(big_buffer)-1] = 0;
91 @@ -724,7 +742,7 @@ DEBUG(D_deliver)
92 buffer. It contains the count of recipients which follow on separate lines.
93 Apply an arbitrary sanity check.*/
95 -if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
96 +if (fgets_big_buffer(fp) == NULL) goto SPOOL_READ_ERROR;
97 if (sscanf(CS big_buffer, "%d", &rcount) != 1 || rcount > 16384)
98 goto SPOOL_FORMAT_ERROR;