From f5a8c2ef2cd2976bea83da0059916ac82fac2b1f Mon Sep 17 00:00:00 2001 From: Kevin McCarthy Date: Fri, 26 Jul 2019 13:55:46 -0700 Subject: [PATCH] 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. Co-authored-by: Richard Russon --- email/body.h | 4 ++++ handler.c | 3 +++ ncrypt/crypt.c | 4 ++++ ncrypt/crypt_gpgme.c | 45 ++++++++++++++++++++++++++++++-------------- ncrypt/cryptglue.c | 26 +++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 14 deletions(-) diff --git a/email/body.h b/email/body.h index 6dfb1b717..338251c9a 100644 --- a/email/body.h +++ b/email/body.h @@ -81,6 +81,10 @@ struct Body bool goodsig : 1; ///< Good cryptographic signature bool warnsig : 1; ///< Maybe good signature bool 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 bool collapsed : 1; ///< Used by recvattach bool attach_qualifies : 1; ///< This attachment should be counted diff --git a/handler.c b/handler.c index 1f6e01b07..d86f5a51f 100644 --- a/handler.c +++ b/handler.c @@ -1457,6 +1457,9 @@ static int malformed_pgp_encrypted_handler(struct Body *b, struct State *s) /* exchange encodes the octet-stream, so re-run it through the decoder */ int rc = run_decode_and_handler(octetstream, s, crypt_pgp_encrypted_handler, false); 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/ncrypt/crypt.c b/ncrypt/crypt.c index 9e367fc3d..40fa0472d 100644 --- a/ncrypt/crypt.c +++ b/ncrypt/crypt.c @@ -730,6 +730,10 @@ SecurityFlags crypt_query(struct Body *m) if (rc && m->goodsig) rc |= SEC_GOODSIGN; +#ifdef USE_AUTOCRYPT + if (rc && m->is_autocrypt) + rc |= SEC_AUTOCRYPT; +#endif } if ((m->type == TYPE_MULTIPART) || (m->type == TYPE_MESSAGE)) diff --git a/ncrypt/crypt_gpgme.c b/ncrypt/crypt_gpgme.c index aab9ea3f7..2c3d43a93 100644 --- a/ncrypt/crypt_gpgme.c +++ b/ncrypt/crypt_gpgme.c @@ -2155,8 +2155,8 @@ static struct Body *decrypt_part(struct Body *a, struct State *s, FILE *fp_out, struct stat info; struct 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; bool maybe_signed = false; bool anywarn = false; int sig_stat = 0; @@ -2172,7 +2172,7 @@ restart: /* Make a data object from the body, create context etc. */ ciphertext = file_to_data_object(s->fp_in, 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. */ @@ -2194,8 +2194,13 @@ restart: else err = gpgme_op_decrypt(ctx, ciphertext, plaintext); gpgme_data_release(ciphertext); + ciphertext = NULL; if (err != 0) { + /* Abort right away and silently. Autocrypt will retry on the + * normal keyring. */ + if (OptAutocryptGpgme) + goto cleanup; if (is_smime && !maybe_signed && (gpg_err_code(err) == GPG_ERR_NO_DATA)) { /* Check whether this might be a signed message despite what the mime @@ -2209,9 +2214,10 @@ restart: { maybe_signed = true; gpgme_data_release(plaintext); + plaintext = NULL; /* gpgsm ends the session after an error; restart it */ gpgme_release(ctx); - ctx = create_gpgme_context(is_smime); + ctx = NULL; goto restart; } } @@ -2224,9 +2230,7 @@ restart: _("[-- Error: decryption failed: %s --]\n\n"), gpgme_strerror(err)); state_attach_puts(buf, s); } - gpgme_data_release(plaintext); - gpgme_release(ctx); - return NULL; + goto cleanup; } redraw_if_needed(ctx); @@ -2234,11 +2238,10 @@ restart: * otherwise read_mime_header has a hard time parsing the message. */ if (data_object_to_stream(plaintext, fp_out)) { - gpgme_data_release(plaintext); - gpgme_release(ctx); - return NULL; + goto cleanup; } gpgme_data_release(plaintext); + plaintext = NULL; a->is_signed_data = false; if (sig_stat) @@ -2292,6 +2295,11 @@ restart: mutt_parse_part(fp_out, tattach); } +cleanup: + gpgme_data_release(ciphertext); + gpgme_data_release(plaintext); + gpgme_release(ctx); + return tattach; } @@ -2366,10 +2374,16 @@ int pgp_gpgme_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Bo *cur = decrypt_part(b, &s, *fp_out, false, &is_signed); if (!*cur) + { rc = -1; - rewind(*fp_out); - if (is_signed > 0) - first_part->goodsig = true; + mutt_file_fclose(fp_out); + } + else + { + rewind(*fp_out); + if (is_signed > 0) + first_part->goodsig = true; + } bail: if (need_decode) @@ -3225,7 +3239,10 @@ int pgp_gpgme_encrypted_handler(struct Body *a, struct State *s) } else { - mutt_error(_("Could not decrypt PGP message")); + if (!OptAutocryptGpgme) + { + mutt_error(_("Could not decrypt PGP message")); + } rc = -1; } diff --git a/ncrypt/cryptglue.c b/ncrypt/cryptglue.c index c7e63eb25..27f002de6 100644 --- a/ncrypt/cryptglue.c +++ b/ncrypt/cryptglue.c @@ -197,6 +197,19 @@ bool crypt_pgp_valid_passphrase(void) */ int crypt_pgp_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur) { +#ifdef USE_AUTOCRYPT + int result; + + OptAutocryptGpgme = true; + result = pgp_gpgme_decrypt_mime(fp_in, fp_out, b, cur); + OptAutocryptGpgme = false; + if (result == 0) + { + b->is_autocrypt = 1; + return result; + } +#endif + if (CRYPT_MOD_CALL_CHECK(PGP, decrypt_mime)) return CRYPT_MOD_CALL(PGP, decrypt_mime)(fp_in, fp_out, b, cur); @@ -223,6 +236,19 @@ int crypt_pgp_application_handler(struct Body *m, struct State *s) */ int crypt_pgp_encrypted_handler(struct Body *a, struct State *s) { +#ifdef USE_AUTOCRYPT + int result; + + OptAutocryptGpgme = true; + result = pgp_gpgme_encrypted_handler(a, s); + OptAutocryptGpgme = false; + 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); -- 2.40.0