diff options
author | Kevin McCarthy <kevin@8t8.us> | 2015-07-26 14:48:53 -0700 |
---|---|---|
committer | Kevin McCarthy <kevin@8t8.us> | 2015-07-26 14:48:53 -0700 |
commit | 5360d1d5111a2aca89918335f930af39380059a9 (patch) | |
tree | 2249ed73b6f64f66fc2aaaafdd33881edc00b7a4 /pgp.c | |
parent | 9ffe468aefd72fbc2e44131b00cf4e83621708ca (diff) |
Handle malformed ms-exchange pgp-encrypted block. (closes #3742)
In certain circumstances, Exchange corrupts a multipart/encrypted block
into:
<multipart/mixed>
<text/plain>
<application/pgp-encrypted> [BASE64-encoded]
<application/octet-stream> [BASE64-encoded]
This patch pulls the full detection of valid/invalid multiparts
into mutt_body_handler(). It extracts a run_decode_and_handler()
function, which is reused by new intermediate handlers to decode
the application/octet-stream part before passing it directly to
crypt_pgp_encrypted_handler. These intermediate handlers then check
and set any GOODSIG flags back into the parent part.
This change may result in less error messages for invalid
multipart/encrypted parts. Instead, mutt will default to the
multipart_handler if it isn't fully "correct".
Viewing attachments uses crypt_pgp_decrypt_mime() which bypasses the
handler mechanism. Add decoding to the decrypt_mime() functions for pgp
and gpgme.
Thanks to Vincent Brillault for his analysis and initial patch.
Diffstat (limited to 'pgp.c')
-rw-r--r-- | pgp.c | 98 |
1 files changed, 64 insertions, 34 deletions
@@ -954,58 +954,88 @@ int pgp_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) char tempfile[_POSIX_PATH_MAX]; STATE s; BODY *p = b; - - if(!mutt_is_multipart_encrypted(b)) - return -1; + int need_decode = 0; + int saved_type; + LOFF_T saved_offset; + size_t saved_length; + FILE *decoded_fp = NULL; + int rv = 0; - if(!b->parts || !b->parts->next) + if (mutt_is_valid_multipart_pgp_encrypted (b)) + b = b->parts->next; + else if (mutt_is_malformed_multipart_pgp_encrypted (b)) + { + b = b->parts->next->next; + need_decode = 1; + } + else return -1; - - b = b->parts->next; - + memset (&s, 0, sizeof (s)); s.fpin = fpin; + + if (need_decode) + { + saved_type = b->type; + saved_offset = b->offset; + saved_length = b->length; + + mutt_mktemp (tempfile, sizeof (tempfile)); + if ((decoded_fp = safe_fopen (tempfile, "w+")) == NULL) + { + mutt_perror (tempfile); + return (-1); + } + unlink (tempfile); + + fseeko (s.fpin, b->offset, 0); + s.fpout = decoded_fp; + + mutt_decode_attachment (b, &s); + + fflush (decoded_fp); + b->length = ftello (decoded_fp); + b->offset = 0; + rewind (decoded_fp); + s.fpin = decoded_fp; + s.fpout = 0; + } + mutt_mktemp (tempfile, sizeof (tempfile)); if ((*fpout = safe_fopen (tempfile, "w+")) == NULL) { mutt_perror (tempfile); - return (-1); + rv = -1; + goto bail; } unlink (tempfile); - *cur = pgp_decrypt_part (b, &s, *fpout, p); - + if ((*cur = pgp_decrypt_part (b, &s, *fpout, p)) == NULL) + rv = -1; rewind (*fpout); - - if (!*cur) - return -1; - - return (0); + +bail: + if (need_decode) + { + b->type = saved_type; + b->length = saved_length; + b->offset = saved_offset; + safe_fclose (&decoded_fp); + } + + return rv; } +/* + * This handler is passed the application/octet-stream directly. + * The caller must propagate a->goodsig to its parent. + */ int pgp_encrypted_handler (BODY *a, STATE *s) { char tempfile[_POSIX_PATH_MAX]; FILE *fpout, *fpin; BODY *tattach; - BODY *p = a; int rc = 0; - - a = a->parts; - if (!a || a->type != TYPEAPPLICATION || !a->subtype || - ascii_strcasecmp ("pgp-encrypted", a->subtype) != 0 || - !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype || - ascii_strcasecmp ("octet-stream", a->next->subtype) != 0) - { - if (s->flags & M_DISPLAY) - state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"), s); - return -1; - } - - /* - * Move forward to the application/pgp-encrypted body. - */ - a = a->next; mutt_mktemp (tempfile, sizeof (tempfile)); if ((fpout = safe_fopen (tempfile, "w+")) == NULL) @@ -1017,7 +1047,7 @@ int pgp_encrypted_handler (BODY *a, STATE *s) if (s->flags & M_DISPLAY) crypt_current_time (s, "PGP"); - if ((tattach = pgp_decrypt_part (a, s, fpout, p)) != NULL) + if ((tattach = pgp_decrypt_part (a, s, fpout, a)) != NULL) { if (s->flags & M_DISPLAY) state_attach_puts (_("[-- The following data is PGP/MIME encrypted --]\n\n"), s); @@ -1035,7 +1065,7 @@ int pgp_encrypted_handler (BODY *a, STATE *s) */ if (mutt_is_multipart_signed (tattach) && !tattach->next) - p->goodsig |= tattach->goodsig; + a->goodsig |= tattach->goodsig; if (s->flags & M_DISPLAY) { |