From: Kevin McCarthy Date: Fri, 13 Jul 2018 21:25:28 +0000 (-0700) Subject: Check outbuf length in mutt_from_base64() X-Git-Tag: mutt-1-10-1-rel~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3d9028fec8f4d08db2251096307c0bbbebce669a;p=mutt Check outbuf length in mutt_from_base64() The obuf can be overflowed in auth_cram.c, and possibly auth_gss.c. Thanks to Jeriko One for the bug report. --- diff --git a/base64.c b/base64.c index fd3ffb88..120d4baa 100644 --- a/base64.c +++ b/base64.c @@ -81,7 +81,7 @@ void mutt_to_base64 (unsigned char *out, const unsigned char *in, size_t len, /* Convert '\0'-terminated base 64 string to raw bytes. * Returns length of returned buffer, or -1 on error */ -int mutt_from_base64 (char *out, const char *in) +int mutt_from_base64 (char *out, const char *in, size_t olen) { int len = 0; register unsigned char digit1, digit2, digit3, digit4; @@ -103,14 +103,20 @@ int mutt_from_base64 (char *out, const char *in) in += 4; /* digits are already sanity-checked */ + if (len == olen) + return len; *out++ = (base64val(digit1) << 2) | (base64val(digit2) >> 4); len++; if (digit3 != '=') { + if (len == olen) + return len; *out++ = ((base64val(digit2) << 4) & 0xf0) | (base64val(digit3) >> 2); len++; if (digit4 != '=') { + if (len == olen) + return len; *out++ = ((base64val(digit3) << 6) & 0xc0) | base64val(digit4); len++; } diff --git a/imap/auth_cram.c b/imap/auth_cram.c index 9b6db9af..87617215 100644 --- a/imap/auth_cram.c +++ b/imap/auth_cram.c @@ -71,7 +71,7 @@ imap_auth_res_t imap_auth_cram_md5 (IMAP_DATA* idata, const char* method) goto bail; } - if ((len = mutt_from_base64 (obuf, idata->buf + 2)) == -1) + if ((len = mutt_from_base64 (obuf, idata->buf + 2, sizeof(obuf) - 1)) == -1) { dprint (1, (debugfile, "Error decoding base64 response.\n")); goto bail; diff --git a/imap/auth_gss.c b/imap/auth_gss.c index a08e7c20..e14f4aac 100644 --- a/imap/auth_gss.c +++ b/imap/auth_gss.c @@ -197,7 +197,7 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata, const char* method) goto bail; } - request_buf.length = mutt_from_base64 (buf2, idata->buf + 2); + request_buf.length = mutt_from_base64 (buf2, idata->buf + 2, sizeof(buf2)); request_buf.value = buf2; sec_token = &request_buf; @@ -233,7 +233,7 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata, const char* method) dprint (1, (debugfile, "Error receiving server response.\n")); goto bail; } - request_buf.length = mutt_from_base64 (buf2, idata->buf + 2); + request_buf.length = mutt_from_base64 (buf2, idata->buf + 2, sizeof(buf2)); request_buf.value = buf2; maj_stat = gss_unwrap (&min_stat, context, &request_buf, &send_token, diff --git a/protos.h b/protos.h index 8bcda67f..f933e925 100644 --- a/protos.h +++ b/protos.h @@ -397,7 +397,7 @@ ADDRESS *alias_reverse_lookup (ADDRESS *); /* base64.c */ void mutt_to_base64 (unsigned char*, const unsigned char*, size_t, size_t); -int mutt_from_base64 (char*, const char*); +int mutt_from_base64 (char*, const char*, size_t); /* utf8.c */ int mutt_wctoutf8 (char *s, unsigned int c, size_t buflen);