Skip to content

Commit 6f163e0

Browse files
kevin8t8flatcap
authored andcommitted
Check outbuf length in mutt_to_base64()
The obuf can be overflowed in auth_cram.c, and possibly auth_gss.c. Thanks to Jeriko One for the bug report.
1 parent 5925aff commit 6f163e0

File tree

6 files changed

+20
-12
lines changed

6 files changed

+20
-12
lines changed

Diff for: imap/auth_cram.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ enum ImapAuthRes imap_auth_cram_md5(struct ImapData *idata, const char *method)
134134
goto bail;
135135
}
136136

137-
len = mutt_b64_decode(obuf, idata->buf + 2);
137+
len = mutt_b64_decode(obuf, idata->buf + 2, sizeof(obuf));
138138
if (len == -1)
139139
{
140140
mutt_debug(1, "Error decoding base64 response.\n");

Diff for: imap/auth_gss.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ enum ImapAuthRes imap_auth_gss(struct ImapData *idata, const char *method)
203203
goto bail;
204204
}
205205

206-
request_buf.length = mutt_b64_decode(buf2, idata->buf + 2);
206+
request_buf.length = mutt_b64_decode(buf2, idata->buf + 2, sizeof(buf2));
207207
request_buf.value = buf2;
208208
sec_token = &request_buf;
209209

@@ -238,7 +238,7 @@ enum ImapAuthRes imap_auth_gss(struct ImapData *idata, const char *method)
238238
mutt_debug(1, "#2 Error receiving server response.\n");
239239
goto bail;
240240
}
241-
request_buf.length = mutt_b64_decode(buf2, idata->buf + 2);
241+
request_buf.length = mutt_b64_decode(buf2, idata->buf + 2, sizeof(buf2));
242242
request_buf.value = buf2;
243243

244244
maj_stat = gss_unwrap(&min_stat, context, &request_buf, &send_token, &cflags, &quality);

Diff for: mutt/base64.c

+10-3
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,17 @@ size_t mutt_b64_encode(char *out, const char *cin, size_t len, size_t olen)
117117

118118
/**
119119
* mutt_b64_decode - Convert null-terminated base64 string to raw bytes
120-
* @param out Output buffer for the raw bytes
121-
* @param in Input buffer for the null-terminated base64-encoded string
120+
* @param out Output buffer for the raw bytes
121+
* @param in Input buffer for the null-terminated base64-encoded string
122+
* @param olen Length of the output buffer
122123
* @retval num Success, bytes written
123124
* @retval -1 Error
124125
*
125126
* This function performs base64 decoding. The resulting buffer is NOT
126127
* null-terminated. If the input buffer contains invalid base64 characters,
127128
* this function returns -1.
128129
*/
129-
int mutt_b64_decode(char *out, const char *in)
130+
int mutt_b64_decode(char *out, const char *in, size_t olen)
130131
{
131132
int len = 0;
132133
unsigned char digit4;
@@ -148,14 +149,20 @@ int mutt_b64_decode(char *out, const char *in)
148149
in += 4;
149150

150151
/* digits are already sanity-checked */
152+
if (len == olen)
153+
return len;
151154
*out++ = (base64val(digit1) << 2) | (base64val(digit2) >> 4);
152155
len++;
153156
if (digit3 != '=')
154157
{
158+
if (len == olen)
159+
return len;
155160
*out++ = ((base64val(digit2) << 4) & 0xf0) | (base64val(digit3) >> 2);
156161
len++;
157162
if (digit4 != '=')
158163
{
164+
if (len == olen)
165+
return len;
159166
*out++ = ((base64val(digit3) << 6) & 0xc0) | base64val(digit4);
160167
len++;
161168
}

Diff for: mutt/base64.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ extern const int Index64[];
2828
#define base64val(c) Index64[(unsigned int) (c)]
2929

3030
size_t mutt_b64_encode(char *out, const char *cin, size_t len, size_t olen);
31-
int mutt_b64_decode(char *out, const char *in);
31+
int mutt_b64_decode(char *out, const char *in, size_t olen);
3232

3333
#endif /* _MUTT_BASE64_H */

Diff for: mutt/rfc2047.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,9 @@ static char *rfc2047_decode_word(const char *s, size_t len, enum ContentEncoding
399399
}
400400
else if (enc == ENCBASE64)
401401
{
402-
char *out = mutt_mem_malloc(3 * len / 4 + 1);
403-
int dlen = mutt_b64_decode(out, it);
402+
const int olen = 3 * len / 4 + 1;
403+
char *out = mutt_mem_malloc(olen);
404+
int dlen = mutt_b64_decode(out, it, olen);
404405
if (dlen == -1)
405406
{
406407
FREE(&out);

Diff for: test/base64.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void test_base64_encode(void)
2727
void test_base64_decode(void)
2828
{
2929
char buffer[16];
30-
int len = mutt_b64_decode(buffer, encoded);
30+
int len = mutt_b64_decode(buffer, encoded, sizeof(buffer));
3131
if (!TEST_CHECK(len == sizeof(clear) - 1))
3232
{
3333
TEST_MSG("Expected: %zu", sizeof(clear) - 1);
@@ -59,7 +59,7 @@ void test_base64_lengths(void)
5959

6060
/* Decoding a zero-length string should fail, too */
6161
out1[0] = '\0';
62-
declen = mutt_b64_decode(out2, out1);
62+
declen = mutt_b64_decode(out2, out1, sizeof(out2));
6363
if (!TEST_CHECK(declen == -1))
6464
{
6565
TEST_MSG("Expected: %zu", -1);
@@ -76,7 +76,7 @@ void test_base64_lengths(void)
7676
TEST_MSG("Expected: %zu", exp);
7777
TEST_MSG("Actual : %zu", enclen);
7878
}
79-
declen = mutt_b64_decode(out2, out1);
79+
declen = mutt_b64_decode(out2, out1, sizeof(out2));
8080
if (!TEST_CHECK(declen == i))
8181
{
8282
TEST_MSG("Expected: %zu", i);

0 commit comments

Comments
 (0)