The obuf can be overflowed in auth_cram.c, and possibly auth_gss.c.
Thanks to Jeriko One for the bug report.
goto bail;
}
- len = mutt_b64_decode(obuf, idata->buf + 2);
+ len = mutt_b64_decode(obuf, idata->buf + 2, sizeof(obuf));
if (len == -1)
{
mutt_debug(1, "Error decoding base64 response.\n");
goto bail;
}
- request_buf.length = mutt_b64_decode(buf2, idata->buf + 2);
+ request_buf.length = mutt_b64_decode(buf2, idata->buf + 2, sizeof(buf2));
request_buf.value = buf2;
sec_token = &request_buf;
mutt_debug(1, "#2 Error receiving server response.\n");
goto bail;
}
- request_buf.length = mutt_b64_decode(buf2, idata->buf + 2);
+ request_buf.length = mutt_b64_decode(buf2, idata->buf + 2, sizeof(buf2));
request_buf.value = buf2;
maj_stat = gss_unwrap(&min_stat, context, &request_buf, &send_token, &cflags, &quality);
/**
* mutt_b64_decode - Convert null-terminated base64 string to raw bytes
- * @param out Output buffer for the raw bytes
- * @param in Input buffer for the null-terminated base64-encoded string
+ * @param out Output buffer for the raw bytes
+ * @param in Input buffer for the null-terminated base64-encoded string
+ * @param olen Length of the output buffer
* @retval num Success, bytes written
* @retval -1 Error
*
* null-terminated. If the input buffer contains invalid base64 characters,
* this function returns -1.
*/
-int mutt_b64_decode(char *out, const char *in)
+int mutt_b64_decode(char *out, const char *in, size_t olen)
{
int len = 0;
unsigned char digit4;
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++;
}
#define base64val(c) Index64[(unsigned int) (c)]
size_t mutt_b64_encode(char *out, const char *cin, size_t len, size_t olen);
-int mutt_b64_decode(char *out, const char *in);
+int mutt_b64_decode(char *out, const char *in, size_t olen);
#endif /* _MUTT_BASE64_H */
}
else if (enc == ENCBASE64)
{
- char *out = mutt_mem_malloc(3 * len / 4 + 1);
- int dlen = mutt_b64_decode(out, it);
+ const int olen = 3 * len / 4 + 1;
+ char *out = mutt_mem_malloc(olen);
+ int dlen = mutt_b64_decode(out, it, olen);
if (dlen == -1)
{
FREE(&out);
void test_base64_decode(void)
{
char buffer[16];
- int len = mutt_b64_decode(buffer, encoded);
+ int len = mutt_b64_decode(buffer, encoded, sizeof(buffer));
if (!TEST_CHECK(len == sizeof(clear) - 1))
{
TEST_MSG("Expected: %zu", sizeof(clear) - 1);
/* Decoding a zero-length string should fail, too */
out1[0] = '\0';
- declen = mutt_b64_decode(out2, out1);
+ declen = mutt_b64_decode(out2, out1, sizeof(out2));
if (!TEST_CHECK(declen == -1))
{
TEST_MSG("Expected: %zu", -1);
TEST_MSG("Expected: %zu", exp);
TEST_MSG("Actual : %zu", enclen);
}
- declen = mutt_b64_decode(out2, out1);
+ declen = mutt_b64_decode(out2, out1, sizeof(out2));
if (!TEST_CHECK(declen == i))
{
TEST_MSG("Expected: %zu", i);