Change crypt_get_keys() to query autocrypt.
When oppenc_mode is set, we still query the original keyring
regardless, because the compose menu can still run oppenc even if
autocrypt is on.
Since mutt_autocrypt_ui_recommendation() checks each key as part of
making the recommendation, add a keylist parameter and use that
function.
Add gpgme changes to use the autocrypt context for encryption.
Postpone work:
* Change mutt_protect() to have a postpone parameter. Remove the
manual toggling of the SEC_SIGN bit outside the call when postponing.
* Since autocrypt doesn't set the SEC_SIGN bit, this allows us to turn off
signing inside mutt_protect() for both normal and autocrypt mode.
* Set the autocrypt postpone key in AutocryptDefaultKey.
Write autocrypt and gossip headers in outgoing emails.
Co-authored-by: Richard Russon <rich@flatcap.org>
return rv;
}
-enum AutocryptRec mutt_autocrypt_ui_recommendation(struct Email *hdr)
+/* Returns the recommendation. If the recommendataion is > NO and
+ * keylist is not NULL, keylist will be populated with the autocrypt
+ * keyids
+ */
+enum AutocryptRec mutt_autocrypt_ui_recommendation(struct Email *hdr, char **keylist)
{
enum AutocryptRec rv = AUTOCRYPT_REC_OFF;
struct AutocryptAccount *account = NULL;
struct AutocryptPeer *peer = NULL;
struct Address *recip = NULL;
int all_encrypt = 1, has_discourage = 0;
+ struct Buffer *keylist_buf = NULL;
+ const char *matching_key;
if (!C_Autocrypt || mutt_autocrypt_init(0) || !hdr)
return AUTOCRYPT_REC_OFF;
if (mutt_autocrypt_db_account_get(from, &account) <= 0)
goto cleanup;
+ keylist_buf = mutt_buffer_pool_get();
+ mutt_buffer_addstr(keylist_buf, account->keyid);
+
struct AddressList recips = TAILQ_HEAD_INITIALIZER(recips);
mutt_addrlist_copy(&recips, &hdr->env->to, false);
if (mutt_autocrypt_gpgme_is_valid_key(peer->keyid))
{
+ matching_key = peer->keyid;
+
if (!(peer->last_seen && peer->autocrypt_timestamp) ||
(peer->last_seen - peer->autocrypt_timestamp > 35 * 24 * 60 * 60))
{
}
else if (mutt_autocrypt_gpgme_is_valid_key(peer->gossip_keyid))
{
+ matching_key = peer->gossip_keyid;
+
has_discourage = 1;
all_encrypt = 0;
}
else
goto cleanup;
+ if (mutt_buffer_len(keylist_buf))
+ mutt_buffer_addch(keylist_buf, ' ');
+ mutt_buffer_addstr(keylist_buf, matching_key);
+
mutt_autocrypt_db_peer_free(&peer);
}
else
rv = AUTOCRYPT_REC_AVAILABLE;
+ if (keylist)
+ mutt_str_replace(keylist, mutt_b2s(keylist_buf));
+
+cleanup:
+ mutt_autocrypt_db_account_free(&account);
+ mutt_addrlist_clear(&recips);
+ mutt_autocrypt_db_peer_free(&peer);
+ mutt_buffer_pool_release(&keylist_buf);
+ return rv;
+}
+
+int mutt_autocrypt_set_sign_as_default_key(struct Email *hdr)
+{
+ int rv = -1;
+ struct AutocryptAccount *account = NULL;
+
+ if (!C_Autocrypt || mutt_autocrypt_init(0) || !hdr)
+ return -1;
+
+ struct Address *from = TAILQ_FIRST(&hdr->env->from);
+ if (!from || TAILQ_NEXT(from, entries))
+ return -1;
+
+ if (mutt_autocrypt_db_account_get(from, &account) <= 0)
+ goto cleanup;
+ if (!account->keyid)
+ goto cleanup;
+
+ mutt_str_replace(&AutocryptSignAs, account->keyid);
+ mutt_str_replace(&AutocryptDefaultKey, account->keyid);
+
+ rv = 0;
+
+cleanup:
+ mutt_autocrypt_db_account_free(&account);
+ return rv;
+}
+
+static void write_autocrypt_header_line(FILE *fp, const char *addr,
+ int prefer_encrypt, const char *keydata)
+{
+ int count = 0;
+
+ fprintf(fp, "addr=%s; ", addr);
+ if (prefer_encrypt)
+ fputs("prefer-encrypt=mutual; ", fp);
+ fputs("keydata=\n", fp);
+
+ while (*keydata)
+ {
+ count = 0;
+ fputs("\t", fp);
+ while (*keydata && count < 75)
+ {
+ fputc(*keydata, fp);
+ count++;
+ keydata++;
+ }
+ fputs("\n", fp);
+ }
+}
+
+int mutt_autocrypt_write_autocrypt_header(struct Envelope *env, FILE *fp)
+{
+ int rv = -1;
+ struct AutocryptAccount *account = NULL;
+
+ if (!C_Autocrypt || mutt_autocrypt_init(0) || !env)
+ return -1;
+
+ struct Address *from = TAILQ_FIRST(&env->from);
+ if (!from || TAILQ_NEXT(from, entries))
+ return -1;
+
+ if (mutt_autocrypt_db_account_get(from, &account) <= 0)
+ goto cleanup;
+ if (!account->keydata)
+ goto cleanup;
+
+ fputs("Autocrypt: ", fp);
+ write_autocrypt_header_line(fp, account->email_addr, account->prefer_encrypt,
+ account->keydata);
+
+ rv = 0;
+
cleanup:
mutt_autocrypt_db_account_free(&account);
+ return rv;
+}
+
+int mutt_autocrypt_write_gossip_headers(struct Envelope *env, FILE *fp)
+{
+ struct AutocryptHeader *gossip;
+
+ if (!C_Autocrypt || mutt_autocrypt_init(0) || !env)
+ return -1;
+
+ for (gossip = env->autocrypt_gossip; gossip; gossip = gossip->next)
+ {
+ fputs("Autocrypt-Gossip: ", fp);
+ write_autocrypt_header_line(fp, gossip->addr, 0, gossip->keydata);
+ }
+
+ return 0;
+}
+
+int mutt_autocrypt_generate_gossip_list(struct Email *hdr)
+{
+ int rv = -1;
+ struct AutocryptPeer *peer = NULL;
+ struct AutocryptAccount *account = NULL;
+ struct Address *recip = NULL;
+ struct AutocryptHeader *gossip;
+ const char *keydata, *addr;
+ struct Envelope *mime_headers;
+
+ if (!C_Autocrypt || mutt_autocrypt_init(0) || !hdr)
+ return -1;
+
+ mime_headers = hdr->content->mime_headers;
+ if (!mime_headers)
+ mime_headers = hdr->content->mime_headers = mutt_env_new();
+ mutt_free_autocrypthdr(&mime_headers->autocrypt_gossip);
+
+ struct AddressList recips = TAILQ_HEAD_INITIALIZER(recips);
+
+ mutt_addrlist_copy(&recips, &hdr->env->to, false);
+ mutt_addrlist_copy(&recips, &hdr->env->cc, false);
+
+ TAILQ_FOREACH(recip, &recips, entries)
+ {
+ /* At this point, we just accept missing keys and include what
+ * we can. */
+ if (mutt_autocrypt_db_peer_get(recip, &peer) <= 0)
+ continue;
+
+ keydata = NULL;
+ if (mutt_autocrypt_gpgme_is_valid_key(peer->keyid))
+ keydata = peer->keydata;
+ else if (mutt_autocrypt_gpgme_is_valid_key(peer->gossip_keyid))
+ keydata = peer->gossip_keydata;
+
+ if (keydata)
+ {
+ gossip = mutt_new_autocrypthdr();
+ gossip->addr = mutt_str_strdup(peer->email_addr);
+ gossip->keydata = mutt_str_strdup(keydata);
+ gossip->next = mime_headers->autocrypt_gossip;
+ mime_headers->autocrypt_gossip = gossip;
+ }
+
+ mutt_autocrypt_db_peer_free(&peer);
+ }
+
+ TAILQ_FOREACH(recip, &hdr->env->reply_to, entries)
+ {
+ addr = keydata = NULL;
+ if (mutt_autocrypt_db_account_get(recip, &account) > 0)
+ {
+ addr = account->email_addr;
+ keydata = account->keydata;
+ }
+ else if (mutt_autocrypt_db_peer_get(recip, &peer) > 0)
+ {
+ addr = peer->email_addr;
+ if (mutt_autocrypt_gpgme_is_valid_key(peer->keyid))
+ keydata = peer->keydata;
+ else if (mutt_autocrypt_gpgme_is_valid_key(peer->gossip_keyid))
+ keydata = peer->gossip_keydata;
+ }
+
+ if (keydata)
+ {
+ gossip = mutt_new_autocrypthdr();
+ gossip->addr = mutt_str_strdup(addr);
+ gossip->keydata = mutt_str_strdup(keydata);
+ gossip->next = mime_headers->autocrypt_gossip;
+ mime_headers->autocrypt_gossip = gossip;
+ }
+ mutt_autocrypt_db_account_free(&account);
+ mutt_autocrypt_db_peer_free(&peer);
+ }
+
mutt_addrlist_clear(&recips);
+ mutt_autocrypt_db_account_free(&account);
mutt_autocrypt_db_peer_free(&peer);
return rv;
}
void mutt_autocrypt_cleanup (void);
int mutt_autocrypt_process_autocrypt_header (struct Email *hdr, struct Envelope *env);
int mutt_autocrypt_process_gossip_header (struct Email *hdr, struct Envelope *env);
-enum AutocryptRec mutt_autocrypt_ui_recommendation (struct Email *hdr);
+enum AutocryptRec mutt_autocrypt_ui_recommendation (struct Email *hdr, char **keylist);
+int mutt_autocrypt_set_sign_as_default_key (struct Email *hdr);
+int mutt_autocrypt_write_autocrypt_header (struct Envelope *env, FILE *fp);
+int mutt_autocrypt_write_gossip_headers (struct Envelope *env, FILE *fp);
+int mutt_autocrypt_generate_gossip_list (struct Email *hdr);
#endif /* MUTT_AUTOCRYPT_AUTOCRYPT_H */
{
case 1:
e->security |= (SEC_AUTOCRYPT | SEC_AUTOCRYPT_OVERRIDE);
- e->security &= ~(SEC_ENCRYPT | SEC_SIGN | SEC_OPPENCRYPT);
+ e->security &= ~(SEC_ENCRYPT | SEC_SIGN | SEC_OPPENCRYPT | SEC_INLINE);
break;
case 2:
e->security &= ~SEC_AUTOCRYPT;
#ifdef USE_AUTOCRYPT
mutt_window_move(MuttIndexWindow, HDR_AUTOCRYPT, 0);
mutt_window_clrtoeol(MuttIndexWindow);
- SET_COLOR(MT_COLOR_COMPOSE_HEADER);
- printw("%*s", HeaderPadding[HDR_AUTOCRYPT], _(Prompts[HDR_AUTOCRYPT]));
- NORMAL_COLOR;
- if (C_Autocrypt && (e->security & SEC_AUTOCRYPT))
- {
- SET_COLOR(MT_COLOR_COMPOSE_SECURITY_ENCRYPT);
- addstr(_("Encrypt"));
- }
- else
+ if (C_Autocrypt)
{
- SET_COLOR(MT_COLOR_COMPOSE_SECURITY_NONE);
- addstr(_("Off"));
- }
+ SET_COLOR(MT_COLOR_COMPOSE_HEADER);
+ printw("%*s", HeaderPadding[HDR_AUTOCRYPT], _(Prompts[HDR_AUTOCRYPT]));
+ NORMAL_COLOR;
+ if (e->security & SEC_AUTOCRYPT)
+ {
+ SET_COLOR(MT_COLOR_COMPOSE_SECURITY_ENCRYPT);
+ addstr(_("Encrypt"));
+ }
+ else
+ {
+ SET_COLOR(MT_COLOR_COMPOSE_SECURITY_NONE);
+ addstr(_("Off"));
+ }
- SET_COLOR(MT_COLOR_COMPOSE_HEADER);
- mutt_window_mvprintw(MuttIndexWindow, HDR_AUTOCRYPT, 40, "%s", _("Recommendation: "));
- NORMAL_COLOR;
- printw("%s", _(AutocryptRecUiFlags[rd->autocrypt_rec]));
+ SET_COLOR(MT_COLOR_COMPOSE_HEADER);
+ mutt_window_mvprintw(MuttIndexWindow, HDR_AUTOCRYPT, 40, "%s", _("Recommendation: "));
+ NORMAL_COLOR;
+ printw("%s", _(AutocryptRecUiFlags[rd->autocrypt_rec]));
+ }
#endif
}
crypt_opportunistic_encrypt(e);
#ifdef USE_AUTOCRYPT
- rd->autocrypt_rec = mutt_autocrypt_ui_recommendation(e);
-
- /* Anything that enables SEC_ENCRYPT or SEC_SIGN, or turns on SMIME
- * overrides autocrypt, be it oppenc or the user having turned on
- * those flags manually. */
- if (e->security & (SEC_ENCRYPT | SEC_SIGN | APPLICATION_SMIME))
- e->security &= ~(SEC_AUTOCRYPT | SEC_AUTOCRYPT_OVERRIDE);
- else
+ if (C_Autocrypt)
{
- if (!(e->security & SEC_AUTOCRYPT_OVERRIDE))
+ rd->autocrypt_rec = mutt_autocrypt_ui_recommendation(e, NULL);
+
+ /* Anything that enables SEC_ENCRYPT or SEC_SIGN, or turns on SMIME
+ * overrides autocrypt, be it oppenc or the user having turned on
+ * those flags manually. */
+ if (e->security & (SEC_ENCRYPT | SEC_SIGN | APPLICATION_SMIME))
+ e->security &= ~(SEC_AUTOCRYPT | SEC_AUTOCRYPT_OVERRIDE);
+ else
{
- if (rd->autocrypt_rec == AUTOCRYPT_REC_YES)
- e->security |= SEC_AUTOCRYPT;
- else
- e->security &= ~SEC_AUTOCRYPT;
+ if (!(e->security & SEC_AUTOCRYPT_OVERRIDE))
+ {
+ if (rd->autocrypt_rec == AUTOCRYPT_REC_YES)
+ {
+ e->security |= SEC_AUTOCRYPT;
+ e->security &= ~SEC_INLINE;
+ }
+ else
+ e->security &= ~SEC_AUTOCRYPT;
+ }
}
}
- /* TODO:
- * - autocrypt menu for manually enabling/disabling (turns on override)
- * - deal with pgp and smime menu and their effects on security->SEC_AUTOCRYPT
- * when encryption or signing is enabled or if switch to smime mode
- */
#endif
redraw_crypt_lines(rd);
#endif
#ifdef USE_AUTOCRYPT
case OP_COMPOSE_AUTOCRYPT_MENU:
+ if (!C_Autocrypt)
+ break;
+
if ((WithCrypto & APPLICATION_SMIME) && (e->security & APPLICATION_SMIME))
{
if (e->security & (SEC_ENCRYPT | SEC_SIGN))
}
}
+#ifdef USE_AUTOCRYPT
+ /* This is a fail-safe to make sure the bit isn't somehow turned
+ * on. The user could have disabled the option after setting SEC_AUTOCRYPT,
+ * or perhaps resuming or replying to an autocrypt message.
+ */
+ if (!C_Autocrypt)
+ e->security &= ~SEC_AUTOCRYPT;
+#endif
+
mutt_menu_pop_current(menu);
mutt_menu_destroy(&menu);
WHERE char *C_AttachFormat; ///< Config: printf-like format string for the attachment menu
#ifdef USE_AUTOCRYPT
WHERE char *C_AutocryptDir;
+WHERE char *AutocryptSignAs; /* This is used in ncrypt/crypt_gpgme.c */
+WHERE char *AutocryptDefaultKey; /* Used for postponing messages */
#endif
WHERE char *C_ConfigCharset; ///< Config: Character set that the config files are in
WHERE char *C_CryptProtectedHeadersSubject; ///< Config: Use this as the subject for encrypted emails
#include "send.h"
#include "sendlib.h"
#include "state.h"
+#ifdef USE_AUTOCRYPT
+#include "autocrypt/autocrypt.h"
+#endif
struct Mailbox;
* @param keylist List of keys to encrypt to (space-separated)
* @retval 0 Success
* @retval -1 Error
+ *
+ * In postpone mode, signing is automatically disabled.
*/
-int mutt_protect(struct Email *e, char *keylist)
+int mutt_protect(struct Email *e, char *keylist, int postpone)
{
struct Body *pbody = NULL, *tmp_pbody = NULL;
struct Body *tmp_smime_pbody = NULL;
struct Body *tmp_pgp_pbody = NULL;
- int flags = (WithCrypto & APPLICATION_PGP) ? e->security : 0;
+ int security, sign, has_retainable_sig = 0;
if (!WithCrypto)
return -1;
- if (!(e->security & (SEC_ENCRYPT | SEC_SIGN)))
+ security = e->security;
+ sign = security & (SEC_AUTOCRYPT | SEC_SIGN);
+ if (postpone)
+ {
+ sign = 0;
+ security &= ~SEC_SIGN;
+ }
+
+ if (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) && !sign)
return 0;
- if ((e->security & SEC_SIGN) && !crypt_valid_passphrase(e->security))
+ if (sign && !(security & SEC_AUTOCRYPT) && !crypt_valid_passphrase(security))
return -1;
- if (((WithCrypto & APPLICATION_PGP) != 0) && ((e->security & PGP_INLINE) == PGP_INLINE))
+ if ((WithCrypto & APPLICATION_PGP) && !(security & SEC_AUTOCRYPT) &&
+ ((security & PGP_INLINE) == PGP_INLINE))
{
if ((e->content->type != TYPE_TEXT) ||
(mutt_str_strcasecmp(e->content->subtype, "plain") != 0))
mutt_endwin();
puts(_("Invoking PGP..."));
}
- pbody = crypt_pgp_traditional_encryptsign(e->content, flags, keylist);
+ pbody = crypt_pgp_traditional_encryptsign(e->content, security, keylist);
if (pbody)
{
e->content = pbody;
if (WithCrypto & APPLICATION_PGP)
tmp_pgp_pbody = e->content;
- if (C_CryptUsePka && (e->security & SEC_SIGN))
+ if (C_CryptUsePka && sign)
{
/* Set sender (necessary for e.g. PKA). */
const char *mailbox = NULL;
if (!mailbox && C_EnvelopeFromAddress)
mailbox = C_EnvelopeFromAddress->mailbox;
- if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
+ if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
crypt_smime_set_sender(mailbox);
- else if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
+ else if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
crypt_pgp_set_sender(mailbox);
if (free_from)
e->content->mime_headers = protected_headers;
}
- if (e->security & SEC_SIGN)
+ /* A note about e->content->mime_headers. If postpone or send
+ * fails, the mime_headers is cleared out before returning to the
+ * compose menu. So despite the "robustness" code above and in the
+ * gen_gossip_list function below, mime_headers will not be set when
+ * entering mutt_protect().
+ *
+ * This is important to note because the user could toggle
+ * $crypt_protected_headers_write or $autocrypt off back in the
+ * compose menu. We don't want mutt_write_rfc822_header() to write
+ * stale data from one option if the other is set.
+ */
+#ifdef USE_AUTOCRYPT
+ if (C_Autocrypt && !postpone && (security & SEC_AUTOCRYPT))
{
- if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
+ mutt_autocrypt_generate_gossip_list(e);
+ }
+#endif
+
+ if (sign)
+ {
+ if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
{
tmp_pbody = crypt_smime_sign_message(e->content);
if (!tmp_pbody)
tmp_smime_pbody = tmp_pbody;
}
- if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP) &&
- (!(flags & SEC_ENCRYPT) || C_PgpRetainableSigs))
+ if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP) &&
+ (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) || C_PgpRetainableSigs))
{
tmp_pbody = crypt_pgp_sign_message(e->content);
if (!tmp_pbody)
goto bail;
- flags &= ~SEC_SIGN;
+ has_retainable_sig = 1;
+ sign = 0;
pbody = tmp_pbody;
tmp_pgp_pbody = tmp_pbody;
}
- if ((WithCrypto != 0) && (e->security & APPLICATION_SMIME) && (e->security & APPLICATION_PGP))
+ if ((WithCrypto != 0) && (security & APPLICATION_SMIME) && (security & APPLICATION_PGP))
{
/* here comes the draft ;-) */
}
}
- if (e->security & SEC_ENCRYPT)
+ if (security & (SEC_ENCRYPT | SEC_AUTOCRYPT))
{
- if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
+ if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
{
tmp_pbody = crypt_smime_build_smime_entity(tmp_smime_pbody, keylist);
if (!tmp_pbody)
pbody = tmp_pbody;
}
- if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
+ if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
{
- pbody = crypt_pgp_encrypt_message(tmp_pgp_pbody, keylist, (flags & SEC_SIGN));
+ pbody = crypt_pgp_encrypt_message(e, tmp_pgp_pbody, keylist, sign);
if (!pbody)
{
/* did we perform a retainable signature? */
- if (flags != e->security)
+ if (has_retainable_sig)
{
/* remove the outer multipart layer */
tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
* signatures.
*/
- if (flags != e->security)
+ if (has_retainable_sig)
{
tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
mutt_body_free(&tmp_pgp_pbody->next);
/* Do a quick check to make sure that we can find all of the encryption
* keys if the user has requested this service. */
+ *keylist = NULL;
+
+#ifdef USE_AUTOCRYPT
+ if (!oppenc_mode && (e->security & SEC_AUTOCRYPT))
+ {
+ if (mutt_autocrypt_ui_recommendation(e, keylist) <= AUTOCRYPT_REC_NO)
+ return (-1);
+ return (0);
+ }
+#endif
+
if (WithCrypto & APPLICATION_PGP)
OptPgpCheckTrust = true;
mutt_addrlist_qualify(&addrlist, fqdn);
mutt_addrlist_dedupe(&addrlist);
- *keylist = NULL;
-
if (oppenc_mode || (e->security & SEC_ENCRYPT))
{
if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
gpgme_ctx_t ctx;
err = gpgme_new(&ctx);
+
+#ifdef USE_AUTOCRYPT
+ if (!err && OptAutocryptGpgme)
+ err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, NULL, C_AutocryptDir);
+#endif
+
if (err != 0)
{
mutt_error(_("error creating gpgme context: %s"), gpgme_strerror(err));
*/
static int set_signer(gpgme_ctx_t ctx, bool for_smime)
{
- char *signid = for_smime ? C_SmimeDefaultKey : C_PgpSignAs;
+ char *signid = NULL;
gpgme_error_t err;
gpgme_ctx_t listctx;
gpgme_key_t key, key2;
char *fpr = NULL, *fpr2 = NULL;
- if (!signid || !*signid)
+ if (for_smime)
+ signid = C_SmimeSignAs ? C_SmimeSignAs : C_SmimeDefaultKey;
+#ifdef USE_AUTOCRYPT
+ else if (OptAutocryptGpgme)
+ signid = AutocryptSignAs;
+#endif
+ else
+ signid = C_PgpSignAs ? C_PgpSignAs : C_PgpDefaultKey;
+
+ if (!signid)
return 0;
listctx = create_gpgme_context(for_smime);
#include "crypt_mod.h"
#include "curs_lib.h"
#include "ncrypt.h"
+#include "options.h"
+#ifdef USE_AUTOCRYPT
+#include "autocrypt/autocrypt.h"
+#endif
struct Address;
struct AddressList;
#endif
#ifdef CRYPT_BACKEND_GPGME
+#include "ncrypt/crypt_gpgme.h"
extern struct CryptModuleSpecs CryptModPgpGpgme;
extern struct CryptModuleSpecs CryptModSmimeGpgme;
#endif
/**
* crypt_pgp_encrypt_message - Wrapper for CryptModuleSpecs::pgp_encrypt_message()
*/
-struct Body *crypt_pgp_encrypt_message(struct Body *a, char *keylist, bool sign)
+struct Body *crypt_pgp_encrypt_message(struct Email *msg, struct Body *a,
+ char *keylist, int sign)
{
+#ifdef USE_AUTOCRYPT
+ struct Body *result;
+
+ if (msg->security & SEC_AUTOCRYPT)
+ {
+ if (mutt_autocrypt_set_sign_as_default_key(msg))
+ return NULL;
+
+ OptAutocryptGpgme = true;
+ result = pgp_gpgme_encrypt_message(a, keylist, sign);
+ OptAutocryptGpgme = false;
+
+ return result;
+ }
+#endif
+
if (CRYPT_MOD_CALL_CHECK(PGP, pgp_encrypt_message))
return CRYPT_MOD_CALL(PGP, pgp_encrypt_message)(a, keylist, sign);
struct Body;
struct State;
-struct Body *crypt_pgp_encrypt_message(struct Body *a, char *keylist, bool sign);
+struct Body *crypt_pgp_encrypt_message (struct Email *msg, struct Body *a, char *keylist, int sign);
char * crypt_pgp_find_keys(struct AddressList *al, bool oppenc_mode);
void crypt_pgp_invoke_import(const char *fname);
void crypt_pgp_set_sender(const char *sender);
SecurityFlags mutt_is_multipart_encrypted(struct Body *b);
SecurityFlags mutt_is_multipart_signed(struct Body *b);
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b);
-int mutt_protect(struct Email *e, char *keylist);
+int mutt_protect(struct Email *e, char *keylist, int);
int mutt_protected_headers_handler(struct Body *m, struct State *s);
bool mutt_should_hide_protected_subject(struct Email *e);
int mutt_signed_handler(struct Body *a, struct State *s);
/* pseudo options */
WHERE bool OptAttachMsg; /**< (pseudo) used by attach-message */
+WHERE bool OptAutocryptGpgme; /**< (pseudo) use Autocrypt context inside ncrypt/crypt_gpgme.c */
WHERE bool OptAuxSort; /**< (pseudo) using auxiliary sort function */
WHERE bool OptDontHandlePgpKeys; /**< (pseudo) used to extract PGP keys */
WHERE bool OptForceRefresh; /**< (pseudo) refresh even during macros */
flags |= SEC_OPPENCRYPT;
break;
+ case 'a':
+ case 'A':
+#ifdef USE_AUTOCRYPT
+ flags |= SEC_AUTOCRYPT;
+#endif
+ break;
+
+ case 'z':
+ case 'Z':
+#ifdef USE_AUTOCRYPT
+ flags |= SEC_AUTOCRYPT_OVERRIDE;
+#endif
+ break;
+
case 's':
case 'S':
flags |= SEC_SIGN;
#ifdef USE_IMAP
#include "imap/imap.h"
#endif
+#ifdef USE_AUTOCRYPT
+#include "autocrypt/autocrypt.h"
+#endif
/* These Config Variables are only used in send.c */
unsigned char C_AbortNoattach; ///< Config: Abort sending the email if attachments are missing
* Protected Headers. */
if (!C_FccBeforeSend)
{
- if ((WithCrypto != 0) && (e->security & (SEC_ENCRYPT | SEC_SIGN)) && C_FccClear)
+ if (WithCrypto && (e->security & (SEC_ENCRYPT | SEC_SIGN | SEC_AUTOCRYPT)) && C_FccClear)
{
e->content = clear_content;
- e->security &= ~(SEC_ENCRYPT | SEC_SIGN);
+ e->security &= ~(SEC_ENCRYPT | SEC_SIGN | SEC_AUTOCRYPT);
mutt_env_free(&e->content->mime_headers);
}
/* check to see if the user wants copies of all attachments */
if (e->content->type == TYPE_MULTIPART)
{
- if ((WithCrypto != 0) && (e->security & (SEC_ENCRYPT | SEC_SIGN)) &&
+ if ((WithCrypto != 0) && (e->security & (SEC_ENCRYPT | SEC_SIGN | SEC_AUTOCRYPT)) &&
((mutt_str_strcmp(e->content->subtype, "encrypted") == 0) ||
(mutt_str_strcmp(e->content->subtype, "signed") == 0)))
{
/* this means writing only the main part */
e->content = clear_content->parts;
- if (mutt_protect(e, pgpkeylist) == -1)
+ if (mutt_protect(e, pgpkeylist, 0) == -1)
{
/* we can't do much about it at this point, so
* fallback to saving the whole thing to fcc */
mutt_encode_descriptions(e_post->content, true);
- if ((WithCrypto != 0) && C_PostponeEncrypt && (e_post->security & SEC_ENCRYPT))
+ if (WithCrypto && C_PostponeEncrypt && (e_post->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)))
{
if (((WithCrypto & APPLICATION_PGP) != 0) && (e_post->security & APPLICATION_PGP))
encrypt_as = C_PgpDefaultKey;
if (!encrypt_as)
encrypt_as = C_PostponeEncryptAs;
- if (encrypt_as)
+#ifdef USE_AUTOCRYPT
+ if (e_post->security & SEC_AUTOCRYPT)
{
- bool is_signed = (e_post->security & SEC_SIGN);
- if (is_signed)
- e_post->security &= ~SEC_SIGN;
+ if (mutt_autocrypt_set_sign_as_default_key(e_post))
+ return -1;
+ encrypt_as = AutocryptDefaultKey;
+ }
+#endif
+ if (encrypt_as)
+ {
pgpkeylist = mutt_str_strdup(encrypt_as);
clear_content = e_post->content;
- if (mutt_protect(e_post, pgpkeylist) == -1)
+ if (mutt_protect(e_post, pgpkeylist, 1) == -1)
{
- if (is_signed)
- e_post->security |= SEC_SIGN;
FREE(&pgpkeylist);
e_post->content = mutt_remove_multipart(e_post->content);
decode_descriptions(e_post->content);
return -1;
}
- if (is_signed)
- e_post->security |= SEC_SIGN;
FREE(&pgpkeylist);
mutt_encode_descriptions(e_post->content, false);
if ((WithCrypto != 0) && (e_templ->security == 0) &&
!(flags & (SEND_BATCH | SEND_MAILX | SEND_POSTPONED | SEND_RESEND)))
{
- if (C_CryptAutosign)
- e_templ->security |= SEC_SIGN;
- if (C_CryptAutoencrypt)
- e_templ->security |= SEC_ENCRYPT;
- if (C_CryptReplyencrypt && e_cur && (e_cur->security & SEC_ENCRYPT))
- e_templ->security |= SEC_ENCRYPT;
- if (C_CryptReplysign && e_cur && (e_cur->security & SEC_SIGN))
- e_templ->security |= SEC_SIGN;
- if (C_CryptReplysignencrypted && e_cur && (e_cur->security & SEC_ENCRYPT))
- e_templ->security |= SEC_SIGN;
- if (((WithCrypto & APPLICATION_PGP) != 0) &&
- ((e_templ->security & (SEC_ENCRYPT | SEC_SIGN)) || C_CryptOpportunisticEncrypt))
- {
- if (C_PgpAutoinline)
- e_templ->security |= SEC_INLINE;
- if (C_PgpReplyinline && e_cur && (e_cur->security & SEC_INLINE))
- e_templ->security |= SEC_INLINE;
+ if (
+#ifdef USE_AUTOCRYPT
+ C_Autocrypt
+#else
+ 0
+#endif
+ && e_cur && (e_cur->security & SEC_AUTOCRYPT))
+ {
+ e_templ->security |= (SEC_AUTOCRYPT | SEC_AUTOCRYPT_OVERRIDE);
+ }
+ else
+ {
+ if (C_CryptAutosign)
+ e_templ->security |= SEC_SIGN;
+ if (C_CryptAutoencrypt)
+ e_templ->security |= SEC_ENCRYPT;
+ if (C_CryptReplyencrypt && e_cur && (e_cur->security & SEC_ENCRYPT))
+ e_templ->security |= SEC_ENCRYPT;
+ if (C_CryptReplysign && e_cur && (e_cur->security & SEC_SIGN))
+ e_templ->security |= SEC_SIGN;
+ if (C_CryptReplysignencrypted && e_cur && (e_cur->security & SEC_ENCRYPT))
+ e_templ->security |= SEC_SIGN;
+ if ((WithCrypto & APPLICATION_PGP) &&
+ ((e_templ->security & (SEC_ENCRYPT | SEC_SIGN)) || C_CryptOpportunisticEncrypt))
+ {
+ if (C_PgpAutoinline)
+ e_templ->security |= SEC_INLINE;
+ if (C_PgpReplyinline && e_cur && (e_cur->security & SEC_INLINE))
+ e_templ->security |= SEC_INLINE;
+ }
}
if (e_templ->security || C_CryptOpportunisticEncrypt)
/* If something has already enabled encryption, e.g. C_CryptAutoencrypt
* or C_CryptReplyencrypt, then don't enable opportunistic encrypt for
* the message. */
- if (!(e_templ->security & SEC_ENCRYPT))
+ if (!(e_templ->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)))
{
e_templ->security |= SEC_OPPENCRYPT;
crypt_opportunistic_encrypt(e_templ);
if (WithCrypto)
{
- if (e_templ->security & (SEC_ENCRYPT | SEC_SIGN))
+ if (e_templ->security & (SEC_ENCRYPT | SEC_SIGN | SEC_AUTOCRYPT))
{
/* save the decrypted attachments */
clear_content = e_templ->content;
if ((crypt_get_keys(e_templ, &pgpkeylist, 0) == -1) ||
- (mutt_protect(e_templ, pgpkeylist) == -1))
+ (mutt_protect(e_templ, pgpkeylist, 0) == -1))
{
e_templ->content = mutt_remove_multipart(e_templ->content);
{
if (!WithCrypto)
;
- else if ((e_templ->security & SEC_ENCRYPT) ||
+ else if ((e_templ->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) ||
((e_templ->security & SEC_SIGN) && (e_templ->content->type == TYPE_APPLICATION)))
{
mutt_body_free(&e_templ->content); /* destroy PGP data */
#else
#define EX_OK 0
#endif
+#ifdef USE_AUTOCRYPT
+#include "autocrypt/autocrypt.h"
+#endif
/* These Config Variables are only used in sendlib.c */
bool C_Allow8bit; ///< Config: Allow 8-bit messages, don't use quoted-printable or base64
if (a->encoding != ENC_7BIT)
fprintf(fp, "Content-Transfer-Encoding: %s\n", ENCODING(a->encoding));
- if (C_CryptProtectedHeadersWrite && a->mime_headers)
+ if ((C_CryptProtectedHeadersWrite
+#ifdef USE_AUTOCRYPT
+ || C_Autocrypt
+#endif
+ ) &&
+ a->mime_headers)
+ {
mutt_rfc822_write_header(fp, a->mime_headers, NULL, MUTT_WRITE_HEADER_MIME, false, false);
+ }
/* Do NOT add the terminator here!!! */
return ferror(fp) ? -1 : 0;
fputc('\n', fp);
}
+#ifdef USE_AUTOCRYPT
+ if (C_Autocrypt)
+ {
+ if (mode == MUTT_WRITE_HEADER_NORMAL)
+ mutt_autocrypt_write_autocrypt_header(env, fp);
+ if (mode == MUTT_WRITE_HEADER_MIME)
+ mutt_autocrypt_write_gossip_headers(env, fp);
+ }
+#endif
+
/* Add any user defined headers */
struct ListNode *tmp = NULL;
STAILQ_FOREACH(tmp, &env->userhdrs, entries)
}
if (e->security & SEC_INLINE)
fputc('I', msg->fp);
+#ifdef USE_AUTOCRYPT
+ if (e->security & SEC_AUTOCRYPT)
+ fputc('A', msg->fp);
+ if (e->security & SEC_AUTOCRYPT_OVERRIDE)
+ fputc('Z', msg->fp);
+#endif
fputc('\n', msg->fp);
}