From: Kevin McCarthy Date: Fri, 26 Jul 2019 20:55:46 +0000 (-0700) Subject: Handle autocrypt message decryption. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2aec979b267efb2f82b5cb5f433948d3395932b8;p=mutt Handle autocrypt message decryption. Try autocrypt first for crypt_pgp_decrypt_mime() and pgp_gpgme_encrypted_handler(). Propagate the autocrypt bit if successful. This is used when replying to an autocrypt message, to force a reply using autocrypt. --- diff --git a/crypt-gpgme.c b/crypt-gpgme.c index 83f6ae6a..418bc180 100644 --- a/crypt-gpgme.c +++ b/crypt-gpgme.c @@ -1947,10 +1947,10 @@ static BODY *decrypt_part (BODY *a, STATE *s, FILE *fpout, int is_smime, int *r_is_signed) { struct stat info; - BODY *tattach; + BODY *tattach = NULL; int err = 0; - gpgme_ctx_t ctx; - gpgme_data_t ciphertext, plaintext; + gpgme_ctx_t ctx = NULL; + gpgme_data_t ciphertext = NULL, plaintext = NULL; int maybe_signed = 0; int anywarn = 0; int sig_stat = 0; @@ -1964,7 +1964,7 @@ restart: /* Make a data object from the body, create context etc. */ ciphertext = file_to_data_object (s->fpin, a->offset, a->length); if (!ciphertext) - return NULL; + goto cleanup; plaintext = create_gpgme_data (); /* Do the decryption or the verification in case of the S/MIME hack. */ @@ -1986,8 +1986,13 @@ restart: else err = gpgme_op_decrypt (ctx, ciphertext, plaintext); gpgme_data_release (ciphertext); + ciphertext = NULL; if (err) { + /* Abort right away and silently. Autocrypt will retry on the + * normal keyring. */ + if (option (OPTAUTOCRYPTGPGME)) + goto cleanup; if (is_smime && !maybe_signed && gpg_err_code (err) == GPG_ERR_NO_DATA) { @@ -2003,9 +2008,11 @@ restart: { maybe_signed = 1; gpgme_data_release (plaintext); + plaintext = NULL; /* We release the context because recent versions of gpgme+gpgsm * appear to end the session after an error */ gpgme_release (ctx); + ctx = NULL; goto restart; } } @@ -2019,9 +2026,7 @@ restart: gpgme_strerror (err)); state_attach_puts (buf, s); } - gpgme_data_release (plaintext); - gpgme_release (ctx); - return NULL; + goto cleanup; } mutt_need_hard_redraw (); @@ -2029,11 +2034,10 @@ restart: otherwise read_mime_header has a hard time parsing the message. */ if (data_object_to_stream (plaintext, fpout)) { - gpgme_data_release (plaintext); - gpgme_release (ctx); - return NULL; + goto cleanup; } gpgme_data_release (plaintext); + plaintext = NULL; a->is_signed_data = 0; if (sig_stat) @@ -2063,7 +2067,8 @@ restart: state_attach_puts (_("[-- End signature " "information --]\n\n"), s); } - gpgme_release (ctx); ctx = NULL; + gpgme_release (ctx); + ctx = NULL; fflush (fpout); rewind (fpout); @@ -2082,6 +2087,11 @@ restart: mutt_parse_part (fpout, tattach); } +cleanup: + gpgme_data_release (ciphertext); + gpgme_data_release (plaintext); + gpgme_release (ctx); + return tattach; } @@ -2158,10 +2168,16 @@ int pgp_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) unlink (tempfile); if ((*cur = decrypt_part (b, &s, *fpout, 0, &is_signed)) == NULL) + { rv = -1; - rewind (*fpout); - if (is_signed > 0) - first_part->goodsig = 1; + safe_fclose (fpout); + } + else + { + rewind (*fpout); + if (is_signed > 0) + first_part->goodsig = 1; + } bail: if (need_decode) @@ -3030,8 +3046,11 @@ int pgp_gpgme_encrypted_handler (BODY *a, STATE *s) } else { - mutt_error _("Could not decrypt PGP message"); - mutt_sleep (2); + if (!option (OPTAUTOCRYPTGPGME)) + { + mutt_error _("Could not decrypt PGP message"); + mutt_sleep (2); + } rc = -1; } diff --git a/crypt.c b/crypt.c index 84d8bd0e..1d5f9c5f 100644 --- a/crypt.c +++ b/crypt.c @@ -609,6 +609,10 @@ int crypt_query (BODY *m) if (t && m->goodsig) t |= GOODSIGN; +#ifdef USE_AUTOCRYPT + if (t && m->is_autocrypt) + t |= AUTOCRYPT; +#endif } if (m->type == TYPEMULTIPART || m->type == TYPEMESSAGE) diff --git a/cryptglue.c b/cryptglue.c index ce822173..b154e8dc 100644 --- a/cryptglue.c +++ b/cryptglue.c @@ -161,6 +161,19 @@ int crypt_pgp_valid_passphrase (void) /* Decrypt a PGP/MIME message. */ int crypt_pgp_decrypt_mime (FILE *a, FILE **b, BODY *c, BODY **d) { +#ifdef USE_AUTOCRYPT + int result; + + set_option (OPTAUTOCRYPTGPGME); + result = pgp_gpgme_decrypt_mime (a, b, c, d); + unset_option (OPTAUTOCRYPTGPGME); + if (result == 0) + { + c->is_autocrypt = 1; + return result; + } +#endif + if (CRYPT_MOD_CALL_CHECK (PGP, decrypt_mime)) return (CRYPT_MOD_CALL (PGP, decrypt_mime)) (a, b, c, d); @@ -179,6 +192,19 @@ int crypt_pgp_application_pgp_handler (BODY *m, STATE *s) /* MIME handler for an PGP/MIME encrypted message. */ int crypt_pgp_encrypted_handler (BODY *a, STATE *s) { +#ifdef USE_AUTOCRYPT + int result; + + set_option (OPTAUTOCRYPTGPGME); + result = pgp_gpgme_encrypted_handler (a, s); + unset_option (OPTAUTOCRYPTGPGME); + if (result == 0) + { + a->is_autocrypt = 1; + return result; + } +#endif + if (CRYPT_MOD_CALL_CHECK (PGP, encrypted_handler)) return (CRYPT_MOD_CALL (PGP, encrypted_handler)) (a, s); diff --git a/handler.c b/handler.c index 5c6397fc..990b3df6 100644 --- a/handler.c +++ b/handler.c @@ -1718,6 +1718,9 @@ static int valid_pgp_encrypted_handler (BODY *b, STATE *s) else rc = crypt_pgp_encrypted_handler (octetstream, s); b->goodsig |= octetstream->goodsig; +#ifdef USE_AUTOCRYPT + b->is_autocrypt |= octetstream->is_autocrypt; +#endif /* Relocate protected headers onto the multipart/encrypted part */ if (!rc && octetstream->mime_headers) @@ -1744,6 +1747,9 @@ static int malformed_pgp_encrypted_handler (BODY *b, STATE *s) /* exchange encodes the octet-stream, so re-run it through the decoder */ rc = run_decode_and_handler (octetstream, s, crypt_pgp_encrypted_handler, 0); b->goodsig |= octetstream->goodsig; +#ifdef USE_AUTOCRYPT + b->is_autocrypt |= octetstream->is_autocrypt; +#endif /* Relocate protected headers onto the multipart/encrypted part */ if (!rc && octetstream->mime_headers) diff --git a/mutt.h b/mutt.h index ba0df11e..9d02a1d2 100644 --- a/mutt.h +++ b/mutt.h @@ -812,6 +812,10 @@ typedef struct body unsigned int goodsig : 1; /* good cryptographic signature */ unsigned int warnsig : 1; /* maybe good signature */ unsigned int badsig : 1; /* bad cryptographic signature (needed to check encrypted s/mime-signatures) */ +#ifdef USE_AUTOCRYPT + unsigned int is_autocrypt : 1; /* used to flag autocrypt-decrypted messages + * for replying */ +#endif unsigned int collapsed : 1; /* used by recvattach */ unsigned int attach_qualifies : 1;