diff --git a/compose.c b/compose.c index 6dd2d307c..7232847ac 100644 --- a/compose.c +++ b/compose.c @@ -526,14 +526,29 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */ break; case OP_COMPOSE_EDIT_TO: menu->redraw = edit_address_list (HDR_TO, &msg->env->to); + if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) + { + crypt_opportunistic_encrypt (msg); + redraw_crypt_lines (msg); + } mutt_message_hook (NULL, msg, M_SEND2HOOK); break; case OP_COMPOSE_EDIT_BCC: menu->redraw = edit_address_list (HDR_BCC, &msg->env->bcc); + if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) + { + crypt_opportunistic_encrypt (msg); + redraw_crypt_lines (msg); + } mutt_message_hook (NULL, msg, M_SEND2HOOK); break; case OP_COMPOSE_EDIT_CC: menu->redraw = edit_address_list (HDR_CC, &msg->env->cc); + if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) + { + crypt_opportunistic_encrypt (msg); + redraw_crypt_lines (msg); + } mutt_message_hook (NULL, msg, M_SEND2HOOK); break; case OP_COMPOSE_EDIT_SUBJECT: @@ -593,6 +608,8 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */ mutt_error (_("Bad IDN in \"%s\": '%s'"), tag, err); FREE (&err); } + if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) + crypt_opportunistic_encrypt (msg); } else { diff --git a/crypt-gpgme.c b/crypt-gpgme.c index 8cbe7ff40..da9dc241c 100644 --- a/crypt-gpgme.c +++ b/crypt-gpgme.c @@ -3994,7 +3994,8 @@ static crypt_key_t *crypt_select_key (crypt_key_t *keys, } static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, - unsigned int app, int *forced_valid) + unsigned int app, int *forced_valid, + int auto_mode) { ADDRESS *r, *p; LIST *hints = NULL; @@ -4019,7 +4020,8 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, if (a && a->personal) hints = crypt_add_string_to_hints (hints, a->personal); - mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox); + if (! auto_mode ) + mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox); keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN) ); mutt_free_list (&hints); @@ -4094,7 +4096,14 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, if (matches) { - if (the_valid_key && !multi && !weak + if (auto_mode) + { + if (the_valid_key) + k = crypt_copy_key (the_valid_key); + else + k = NULL; + } + else if (the_valid_key && !multi && !weak && !(invalid && option (OPTPGPSHOWUNUSABLE))) { /* @@ -4122,7 +4131,7 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, } -static crypt_key_t *crypt_getkeybystr (char *p, short abilities, +static crypt_key_t *crypt_getkeybystr (const char *p, short abilities, unsigned int app, int *forced_valid) { LIST *hints = NULL; @@ -4244,45 +4253,25 @@ static crypt_key_t *crypt_ask_for_key (char *tag, } /* This routine attempts to find the keyids of the recipients of a - message. It returns NULL if any of the keys can not be found. */ -static char *find_keys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, - unsigned int app) + message. It returns NULL if any of the keys can not be found. + If auto_mode is true, only keys that can be determined without + prompting will be used. */ +static char *find_keys (ADDRESS *adrlist, unsigned int app, int auto_mode) { - char *keyID, *keylist = NULL, *t; + const char *keyID = NULL; + char *keylist = NULL, *t; size_t keylist_size = 0; size_t keylist_used = 0; - ADDRESS *tmp = NULL, *addr = NULL; - ADDRESS **last = &tmp; + ADDRESS *addr = NULL; ADDRESS *p, *q; - int i; - crypt_key_t *k_info, *key; + crypt_key_t *k_info; const char *fqdn = mutt_fqdn (1); #if 0 *r_application = APPLICATION_PGP|APPLICATION_SMIME; #endif - - for (i = 0; i < 3; i++) - { - switch (i) - { - case 0: p = to; break; - case 1: p = cc; break; - case 2: p = bcc; break; - default: abort (); - } - - *last = rfc822_cpy_adr (p, 0); - while (*last) - last = &((*last)->next); - } - - if (fqdn) - rfc822_qualify (tmp, fqdn); - - tmp = mutt_remove_duplicates (tmp); - - for (p = tmp; p ; p = p->next) + + for (p = adrlist; p ; p = p->next) { char buf[LONG_STRING]; int forced_valid = 0; @@ -4292,11 +4281,22 @@ static char *find_keys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, if ((keyID = mutt_crypt_hook (p)) != NULL) { - int r; - snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), - keyID, p->mailbox); - if ((r = mutt_yesorno (buf, M_YES)) == M_YES) + int r = M_NO; + if (! auto_mode) { + snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), + keyID, p->mailbox); + r = mutt_yesorno (buf, M_YES); + } + if (auto_mode || (r == M_YES)) + { + if (crypt_is_numerical_keyid (keyID)) + { + if (strncmp (keyID, "0x", 2) == 0) + keyID += 2; + goto bypass_selection; /* you don't see this. */ + } + /* check for e-mail address */ if ((t = strchr (keyID, '@')) && (addr = rfc822_parse_adrlist (NULL, keyID))) @@ -4305,7 +4305,7 @@ static char *find_keys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, rfc822_qualify (addr, fqdn); q = addr; } - else + else if (! auto_mode) { #if 0 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, @@ -4319,69 +4319,70 @@ static char *find_keys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, else if (r == -1) { FREE (&keylist); - rfc822_free_address (&tmp); rfc822_free_address (&addr); return NULL; } } - if (k_info == NULL - && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT, - app, &forced_valid)) == NULL) + if (k_info == NULL) + { + k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT, + app, &forced_valid, auto_mode); + } + + if ((k_info == NULL) && (! auto_mode)) { snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox); - if ((key = crypt_ask_for_key (buf, q->mailbox, - KEYFLAG_CANENCRYPT, + k_info = crypt_ask_for_key (buf, q->mailbox, + KEYFLAG_CANENCRYPT, #if 0 - *r_application, + *r_application, #else - app, + app, #endif - &forced_valid)) == NULL) - { - FREE (&keylist); - rfc822_free_address (&tmp); - rfc822_free_address (&addr); - return NULL; - } + &forced_valid); + } + + if (k_info == NULL) + { + FREE (&keylist); + rfc822_free_address (&addr); + return NULL; } - else - key = k_info; - { - const char *s = crypt_fpr (key); + + keyID = crypt_fpr (k_info); #if 0 - if (key->flags & KEYFLAG_ISX509) - *r_application &= ~APPLICATION_PGP; - if (!(key->flags & KEYFLAG_ISX509)) - *r_application &= ~APPLICATION_SMIME; + if (k_info->flags & KEYFLAG_ISX509) + *r_application &= ~APPLICATION_PGP; + if (!(k_info->flags & KEYFLAG_ISX509)) + *r_application &= ~APPLICATION_SMIME; #endif - keylist_size += mutt_strlen (s) + 4 + 1; - safe_realloc (&keylist, keylist_size); - sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */ - keylist_used ? " " : "", s, - forced_valid? "!":""); - } + bypass_selection: + keylist_size += mutt_strlen (keyID) + 4 + 1; + safe_realloc (&keylist, keylist_size); + sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */ + keylist_used ? " " : "", keyID, + forced_valid? "!":""); keylist_used = mutt_strlen (keylist); - crypt_free_key (&key); + crypt_free_key (&k_info); rfc822_free_address (&addr); } - rfc822_free_address (&tmp); return (keylist); } -char *pgp_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +char *pgp_gpgme_findkeys (ADDRESS *adrlist, int auto_mode) { - return find_keys (to, cc, bcc, APPLICATION_PGP); + return find_keys (adrlist, APPLICATION_PGP, auto_mode); } -char *smime_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +char *smime_gpgme_findkeys (ADDRESS *adrlist, int auto_mode) { - return find_keys (to, cc, bcc, APPLICATION_SMIME); + return find_keys (adrlist, APPLICATION_SMIME, auto_mode); } /* diff --git a/crypt-gpgme.h b/crypt-gpgme.h index 400d4a7f7..814c6654b 100644 --- a/crypt-gpgme.h +++ b/crypt-gpgme.h @@ -24,8 +24,8 @@ void pgp_gpgme_init (void); void smime_gpgme_init (void); -char *pgp_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc); -char *smime_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc); +char *pgp_gpgme_findkeys (ADDRESS *adrlist, int auto_mode); +char *smime_gpgme_findkeys (ADDRESS *adrlist, int auto_mode); BODY *pgp_gpgme_encrypt_message (BODY *a, char *keylist, int sign); BODY *smime_gpgme_build_smime_entity (BODY *a, char *keylist); diff --git a/crypt-mod-pgp-classic.c b/crypt-mod-pgp-classic.c index e414a147e..cd78f7aa9 100644 --- a/crypt-mod-pgp-classic.c +++ b/crypt-mod-pgp-classic.c @@ -46,9 +46,9 @@ static int crypt_mod_pgp_application_handler (BODY *m, STATE *s) return pgp_application_pgp_handler (m, s); } -static char *crypt_mod_pgp_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +static char *crypt_mod_pgp_findkeys (ADDRESS *adrlist, int auto_mode) { - return pgp_findKeys (to, cc, bcc); + return pgp_findKeys (adrlist, auto_mode); } static BODY *crypt_mod_pgp_sign_message (BODY *a) diff --git a/crypt-mod-pgp-gpgme.c b/crypt-mod-pgp-gpgme.c index 388056fd8..0481206b3 100644 --- a/crypt-mod-pgp-gpgme.c +++ b/crypt-mod-pgp-gpgme.c @@ -70,9 +70,9 @@ static void crypt_mod_pgp_invoke_import (const char *fname) pgp_gpgme_invoke_import (fname); } -static char *crypt_mod_pgp_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +static char *crypt_mod_pgp_findkeys (ADDRESS *adrlist, int auto_mode) { - return pgp_gpgme_findkeys (to, cc, bcc); + return pgp_gpgme_findkeys (adrlist, auto_mode); } static BODY *crypt_mod_pgp_sign_message (BODY *a) diff --git a/crypt-mod-smime-classic.c b/crypt-mod-smime-classic.c index bc0bb75ef..314fcab6c 100644 --- a/crypt-mod-smime-classic.c +++ b/crypt-mod-smime-classic.c @@ -46,9 +46,9 @@ static int crypt_mod_smime_application_handler (BODY *m, STATE *s) return smime_application_smime_handler (m, s); } -static char *crypt_mod_smime_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +static char *crypt_mod_smime_findkeys (ADDRESS *adrlist, int auto_mode) { - return smime_findKeys (to, cc, bcc); + return smime_findKeys (adrlist, auto_mode); } static BODY *crypt_mod_smime_sign_message (BODY *a) diff --git a/crypt-mod-smime-gpgme.c b/crypt-mod-smime-gpgme.c index 6e85b9803..3b761fca5 100644 --- a/crypt-mod-smime-gpgme.c +++ b/crypt-mod-smime-gpgme.c @@ -55,9 +55,9 @@ static int crypt_mod_smime_application_handler (BODY *m, STATE *s) return smime_gpgme_application_handler (m, s); } -static char *crypt_mod_smime_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +static char *crypt_mod_smime_findkeys (ADDRESS *adrlist, int auto_mode) { - return smime_gpgme_findkeys (to, cc, bcc); + return smime_gpgme_findkeys (adrlist, auto_mode); } static BODY *crypt_mod_smime_sign_message (BODY *a) diff --git a/crypt-mod.h b/crypt-mod.h index 1e284a0bd..6bf8e5a65 100644 --- a/crypt-mod.h +++ b/crypt-mod.h @@ -43,8 +43,7 @@ typedef int (*crypt_func_pgp_check_traditional_t) (FILE *fp, BODY *b, typedef BODY *(*crypt_func_pgp_traditional_encryptsign_t) (BODY *a, int flags, char *keylist); typedef BODY *(*crypt_func_pgp_make_key_attachment_t) (char *tempf); -typedef char *(*crypt_func_findkeys_t) (ADDRESS *to, - ADDRESS *cc, ADDRESS *bcc); +typedef char *(*crypt_func_findkeys_t) (ADDRESS *adrlist, int auto_mode); typedef BODY *(*crypt_func_sign_message_t) (BODY *a); typedef BODY *(*crypt_func_pgp_encrypt_message_t) (BODY *a, char *keylist, int sign); diff --git a/crypt.c b/crypt.c index d87e424dd..c004e5e3b 100644 --- a/crypt.c +++ b/crypt.c @@ -707,8 +707,11 @@ void crypt_extract_keys_from_messages (HEADER * h) -int crypt_get_keys (HEADER *msg, char **keylist) +int crypt_get_keys (HEADER *msg, char **keylist, int auto_mode) { + ADDRESS *adrlist = NULL, *last = NULL; + const char *fqdn = mutt_fqdn (1); + /* Do a quick check to make sure that we can find all of the encryption * keys if the user has requested this service. */ @@ -719,31 +722,71 @@ int crypt_get_keys (HEADER *msg, char **keylist) if ((WithCrypto & APPLICATION_PGP)) set_option (OPTPGPCHECKTRUST); + last = rfc822_append (&adrlist, msg->env->to, 0); + last = rfc822_append (last ? &last : &adrlist, msg->env->cc, 0); + rfc822_append (last ? &last : &adrlist, msg->env->bcc, 0); + + if (fqdn) + rfc822_qualify (adrlist, fqdn); + adrlist = mutt_remove_duplicates (adrlist); + *keylist = NULL; - if (msg->security & ENCRYPT) + if (auto_mode || (msg->security & ENCRYPT)) { if ((WithCrypto & APPLICATION_PGP) && (msg->security & APPLICATION_PGP)) { - if ((*keylist = crypt_pgp_findkeys (msg->env->to, msg->env->cc, - msg->env->bcc)) == NULL) + if ((*keylist = crypt_pgp_findkeys (adrlist, auto_mode)) == NULL) + { + rfc822_free_address (&adrlist); return (-1); + } unset_option (OPTPGPCHECKTRUST); } if ((WithCrypto & APPLICATION_SMIME) && (msg->security & APPLICATION_SMIME)) { - if ((*keylist = crypt_smime_findkeys (msg->env->to, msg->env->cc, - msg->env->bcc)) == NULL) + if ((*keylist = crypt_smime_findkeys (adrlist, auto_mode)) == NULL) + { + rfc822_free_address (&adrlist); return (-1); + } } } + + rfc822_free_address (&adrlist); return (0); } +/* + * Check if all recipients keys can be automatically determined. + * Enable encryption if they can, otherwise disable encryption. + */ + +void crypt_opportunistic_encrypt(HEADER *msg) +{ + char *pgpkeylist = NULL; + + /* crypt_autoencrypt should override crypt_opportunistic_encrypt */ + if (option (OPTCRYPTAUTOENCRYPT)) + return; + + crypt_get_keys (msg, &pgpkeylist, 1); + if (pgpkeylist != NULL ) + { + msg->security |= ENCRYPT; + FREE (&pgpkeylist); + } + else + { + msg->security &= ~ENCRYPT; + } +} + + static void crypt_fetch_signatures (BODY ***signatures, BODY *a, int *n) { @@ -900,3 +943,23 @@ int mutt_signed_handler (BODY *a, STATE *s) } +/* + * Used by pgp_findKeys and find_keys to check if a crypt-hook + * value is a key id. + */ + +short crypt_is_numerical_keyid (const char *s) +{ + /* or should we require the "0x"? */ + if (strncmp (s, "0x", 2) == 0) + s += 2; + if (strlen (s) % 8) + return 0; + while (*s) + if (strchr ("0123456789ABCDEFabcdef", *s++) == NULL) + return 0; + + return 1; +} + + diff --git a/cryptglue.c b/cryptglue.c index ab39f8325..252710de8 100644 --- a/cryptglue.c +++ b/cryptglue.c @@ -199,11 +199,13 @@ BODY *crypt_pgp_make_key_attachment (char *tempf) } /* This routine attempts to find the keyids of the recipients of a - message. It returns NULL if any of the keys can not be found. */ -char *crypt_pgp_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) + message. It returns NULL if any of the keys can not be found. + If auto_mode is true, only keys that can be determined without + prompting will be used. */ +char *crypt_pgp_findkeys (ADDRESS *adrlist, int auto_mode) { if (CRYPT_MOD_CALL_CHECK (PGP, findkeys)) - return (CRYPT_MOD_CALL (PGP, findkeys)) (to, cc, bcc); + return (CRYPT_MOD_CALL (PGP, findkeys)) (adrlist, auto_mode); return NULL; } @@ -333,11 +335,13 @@ int crypt_smime_verify_sender(HEADER *h) } /* This routine attempts to find the keyids of the recipients of a - message. It returns NULL if any of the keys can not be found. */ -char *crypt_smime_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) + message. It returns NULL if any of the keys can not be found. + If auto_mode is true, only keys that can be determined without + prompting will be used. */ +char *crypt_smime_findkeys (ADDRESS *adrlist, int auto_mode) { if (CRYPT_MOD_CALL_CHECK (SMIME, findkeys)) - return (CRYPT_MOD_CALL (SMIME, findkeys)) (to, cc, bcc); + return (CRYPT_MOD_CALL (SMIME, findkeys)) (adrlist, auto_mode); return NULL; } diff --git a/init.h b/init.h index 6d607f740..1d6aa11e2 100644 --- a/init.h +++ b/init.h @@ -492,6 +492,23 @@ struct option_t MuttVars[] = { ** $$crypt_replyencrypt, ** $$crypt_autosign, $$crypt_replysign and $$smime_is_default. */ + { "crypt_opportunistic_encrypt", DT_BOOL, R_NONE, OPTCRYPTOPPORTUNISTICENCRYPT, 0 }, + /* + ** .pp + ** Setting this variable will cause Mutt to automatically enable and + ** disable encryption, based on whether all message recipient keys + ** can be located by mutt. + ** .pp + ** When this option is enabled, mutt will determine the encryption + ** setting each time the TO, CC, and BCC lists are edited. If + ** $$edit_headers is set, mutt will also do so each time the message + ** is edited. If you wish to manually enable/disable encryption with + ** this option set, you should do so after editing the message and + ** recipients, to avoid mutt changing your setting. + ** .pp + ** \fBNote:\fP this option has no effect when $$crypt_autoencrypt is enabled. + ** (Crypto only) + */ { "pgp_replyencrypt", DT_SYN, R_NONE, UL "crypt_replyencrypt", 1 }, { "crypt_replyencrypt", DT_BOOL, R_NONE, OPTCRYPTREPLYENCRYPT, 1 }, /* diff --git a/mutt.h b/mutt.h index dba28c363..dfe3e1803 100644 --- a/mutt.h +++ b/mutt.h @@ -478,6 +478,7 @@ enum OPTCRYPTAUTOENCRYPT, OPTCRYPTAUTOPGP, OPTCRYPTAUTOSMIME, + OPTCRYPTOPPORTUNISTICENCRYPT, OPTCRYPTREPLYENCRYPT, OPTCRYPTREPLYSIGN, OPTCRYPTREPLYSIGNENCRYPTED, diff --git a/mutt_crypt.h b/mutt_crypt.h index c9fcd8932..049b5352f 100644 --- a/mutt_crypt.h +++ b/mutt_crypt.h @@ -140,8 +140,14 @@ void crypt_extract_keys_from_messages (HEADER *h); /* Do a quick check to make sure that we can find all of the encryption keys if the user has requested this service. - Return the list of keys in KEYLIST. */ -int crypt_get_keys (HEADER *msg, char **keylist); + Return the list of keys in KEYLIST. + If auto_mode is true, only keys that can be determined without + prompting will be used. */ +int crypt_get_keys (HEADER *msg, char **keylist, int auto_mode); + +/* Check if all recipients keys can be automatically determined. + * Enable encryption if they can, otherwise disable encryption. */ +void crypt_opportunistic_encrypt(HEADER *msg); /* Forget a passphrase and display a message. */ void crypt_forget_passphrase (void); @@ -153,6 +159,9 @@ int crypt_valid_passphrase (int); TEMPFILE. */ int crypt_write_signed(BODY *a, STATE *s, const char *tempf); +/* Check if a string contains a numerical key */ +short crypt_is_numerical_keyid (const char *s); + /*-- cryptglue.c --*/ @@ -196,8 +205,10 @@ void crypt_pgp_free_key (pgp_key_t *kpp); BODY *crypt_pgp_make_key_attachment (char *tempf); /* This routine attempts to find the keyids of the recipients of a - message. It returns NULL if any of the keys can not be found. */ -char *crypt_pgp_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc); + message. It returns NULL if any of the keys can not be found. + If auto_mode is true, only keys that can be determined without + prompting will be used. */ +char *crypt_pgp_findkeys (ADDRESS *adrlist, int auto_mode); /* Create a new body with a PGP signed message from A. */ BODY *crypt_pgp_sign_message (BODY *a); @@ -245,8 +256,10 @@ int crypt_smime_verify_sender(HEADER *h); char *crypt_smime_ask_for_key (char *prompt, char *mailbox, short public); /* This routine attempts to find the keyids of the recipients of a - message. It returns NULL if any of the keys can not be found. */ -char *crypt_smime_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc); + message. It returns NULL if any of the keys can not be found. + If auto_mode is true, only keys that can be determined without + prompting will be used. */ +char *crypt_smime_findkeys (ADDRESS *adrlist, int auto_mode); /* fixme: Needs documentation. */ BODY *crypt_smime_sign_message (BODY *a); diff --git a/pgp.c b/pgp.c index 506a078d1..594896fda 100644 --- a/pgp.c +++ b/pgp.c @@ -31,6 +31,7 @@ #endif #include "mutt.h" +#include "mutt_crypt.h" #include "mutt_curses.h" #include "pgp.h" #include "mime.h" @@ -1131,57 +1132,23 @@ BODY *pgp_sign_message (BODY *a) return (a); } -static short is_numerical_keyid (const char *s) -{ - /* or should we require the "0x"? */ - if (strncmp (s, "0x", 2) == 0) - s += 2; - if (strlen (s) % 8) - return 0; - while (*s) - if (strchr ("0123456789ABCDEFabcdef", *s++) == NULL) - return 0; - - return 1; -} - /* This routine attempts to find the keyids of the recipients of a message. * It returns NULL if any of the keys can not be found. + * If auto_mode is true, only keys that can be determined without + * prompting will be used. */ -char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +char *pgp_findKeys (ADDRESS *adrlist, int auto_mode) { char *keyID, *keylist = NULL; size_t keylist_size = 0; size_t keylist_used = 0; - ADDRESS *tmp = NULL, *addr = NULL; - ADDRESS **last = &tmp; + ADDRESS *addr = NULL; ADDRESS *p, *q; - int i; - pgp_key_t k_info = NULL, key = NULL; + pgp_key_t k_info = NULL; const char *fqdn = mutt_fqdn (1); - for (i = 0; i < 3; i++) - { - switch (i) - { - case 0: p = to; break; - case 1: p = cc; break; - case 2: p = bcc; break; - default: abort (); - } - - *last = rfc822_cpy_adr (p, 0); - while (*last) - last = &((*last)->next); - } - - if (fqdn) - rfc822_qualify (tmp, fqdn); - - tmp = mutt_remove_duplicates (tmp); - - for (p = tmp; p ; p = p->next) + for (p = adrlist; p ; p = p->next) { char buf[LONG_STRING]; @@ -1190,11 +1157,15 @@ char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) if ((keyID = mutt_crypt_hook (p)) != NULL) { - int r; - snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox); - if ((r = mutt_yesorno (buf, M_YES)) == M_YES) + int r = M_NO; + if (! auto_mode) { - if (is_numerical_keyid (keyID)) + snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox); + r = mutt_yesorno (buf, M_YES); + } + if (auto_mode || (r == M_YES)) + { + if (crypt_is_numerical_keyid (keyID)) { if (strncmp (keyID, "0x", 2) == 0) keyID += 2; @@ -1208,38 +1179,40 @@ char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) if (fqdn) rfc822_qualify (addr, fqdn); q = addr; } - else + else if (! auto_mode) + { k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING); + } } else if (r == -1) { FREE (&keylist); - rfc822_free_address (&tmp); rfc822_free_address (&addr); return NULL; } } if (k_info == NULL) + { pgp_invoke_getkeys (q); + k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING, auto_mode); + } - if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) + if ((k_info == NULL) && (! auto_mode)) { snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox); + k_info = pgp_ask_for_key (buf, q->mailbox, + KEYFLAG_CANENCRYPT, PGP_PUBRING); + } - if ((key = pgp_ask_for_key (buf, q->mailbox, - KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) - { - FREE (&keylist); - rfc822_free_address (&tmp); - rfc822_free_address (&addr); - return NULL; - } + if (k_info == NULL) + { + FREE (&keylist); + rfc822_free_address (&addr); + return NULL; } - else - key = k_info; - keyID = pgp_keyid (key); + keyID = pgp_keyid (k_info); bypass_selection: keylist_size += mutt_strlen (keyID) + 4; @@ -1248,11 +1221,10 @@ char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) keyID); keylist_used = mutt_strlen (keylist); - pgp_free_key (&key); + pgp_free_key (&k_info); rfc822_free_address (&addr); } - rfc822_free_address (&tmp); return (keylist); } diff --git a/pgp.h b/pgp.h index 2d98e14ed..738451b18 100644 --- a/pgp.h +++ b/pgp.h @@ -46,10 +46,10 @@ int pgp_decrypt_mime (FILE *, FILE **, BODY *, BODY **); /* pgp_key_t gpg_get_candidates (struct pgp_vinfo *, pgp_ring_t, LIST *); */ pgp_key_t pgp_ask_for_key (char *, char *, short, pgp_ring_t); pgp_key_t pgp_get_candidates (pgp_ring_t, LIST *); -pgp_key_t pgp_getkeybyaddr (ADDRESS *, short, pgp_ring_t); +pgp_key_t pgp_getkeybyaddr (ADDRESS *, short, pgp_ring_t, int); pgp_key_t pgp_getkeybystr (char *, short, pgp_ring_t); -char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc); +char *pgp_findKeys (ADDRESS *adrlist, int auto_mode); void pgp_forget_passphrase (void); int pgp_application_pgp_handler (BODY *, STATE *); diff --git a/pgpkey.c b/pgpkey.c index dad51b0ea..d3cdb26c9 100644 --- a/pgpkey.c +++ b/pgpkey.c @@ -812,7 +812,8 @@ static pgp_key_t *pgp_get_lastp (pgp_key_t p) return NULL; } -pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring) +pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring, + int auto_mode) { ADDRESS *r, *p; LIST *hints = NULL; @@ -831,7 +832,8 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring) if (a && a->personal) hints = pgp_add_string_to_hints (hints, a->personal); - mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox); + if (! auto_mode ) + mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox); keys = pgp_get_candidates (keyring, hints); mutt_free_list (&hints); @@ -895,7 +897,19 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring) if (matches) { - if (the_valid_key && !multi) + if (auto_mode) + { + if (the_valid_key) + { + pgp_remove_key (&matches, the_valid_key); + k = the_valid_key; + } + else + { + k = NULL; + } + } + else if (the_valid_key && !multi) { /* * There was precisely one strong match on a valid ID. @@ -903,7 +917,6 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring) * Proceed without asking the user. */ pgp_remove_key (&matches, the_valid_key); - pgp_free_key (&matches); k = the_valid_key; } else @@ -913,9 +926,10 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring) */ if ((k = pgp_select_key (matches, a, NULL))) pgp_remove_key (&matches, k); - pgp_free_key (&matches); } + pgp_free_key (&matches); + return k; } diff --git a/send.c b/send.c index 69919c9e2..5d1754fd1 100644 --- a/send.c +++ b/send.c @@ -1475,7 +1475,7 @@ ci_send_message (int flags, /* send mode */ msg->security |= INLINE; } - if (msg->security) + if (msg->security || option (OPTCRYPTOPPORTUNISTICENCRYPT)) { /* * When replying / forwarding, use the original message's @@ -1512,6 +1512,12 @@ ci_send_message (int flags, /* send mode */ } } + /* opportunistic encrypt relys on SMIME or PGP already being selected */ + if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) + { + crypt_opportunistic_encrypt(msg); + } + /* No permissible mechanisms found. Don't sign or encrypt. */ if (!(msg->security & (APPLICATION_SMIME|APPLICATION_PGP))) msg->security = 0; @@ -1646,7 +1652,7 @@ ci_send_message (int flags, /* send mode */ /* save the decrypted attachments */ clear_content = msg->content; - if ((crypt_get_keys (msg, &pgpkeylist) == -1) || + if ((crypt_get_keys (msg, &pgpkeylist, 0) == -1) || mutt_protect (msg, pgpkeylist) == -1) { msg->content = mutt_remove_multipart (msg->content); diff --git a/smime.c b/smime.c index 2691dc966..e4cb27558 100644 --- a/smime.c +++ b/smime.c @@ -729,47 +729,25 @@ void smime_getkeys (ENVELOPE *env) /* This routine attempts to find the keyids of the recipients of a message. * It returns NULL if any of the keys can not be found. + * If auto_mode is true, only keys that can be determined without + * prompting will be used. */ -char *smime_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +char *smime_findKeys (ADDRESS *adrlist, int auto_mode) { char *keyID, *keylist = NULL; size_t keylist_size = 0; size_t keylist_used = 0; - ADDRESS *tmp = NULL, *addr = NULL; - ADDRESS **last = &tmp; ADDRESS *p, *q; - int i; - const char *fqdn = mutt_fqdn (1); - - for (i = 0; i < 3; i++) - { - switch (i) - { - case 0: p = to; break; - case 1: p = cc; break; - case 2: p = bcc; break; - default: abort (); - } - - *last = rfc822_cpy_adr (p, 0); - while (*last) - last = &((*last)->next); - } - - if (fqdn) - rfc822_qualify (tmp, fqdn); - - tmp = mutt_remove_duplicates (tmp); - - for (p = tmp; p ; p = p->next) + for (p = adrlist; p ; p = p->next) { char buf[LONG_STRING]; q = p; - if ((keyID = smime_get_field_from_db (q->mailbox, NULL, 1, 1)) == NULL) + keyID = smime_get_field_from_db (q->mailbox, NULL, 1, 1); + if ((keyID == NULL) && (! auto_mode)) { snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), @@ -778,10 +756,9 @@ char *smime_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) } if(!keyID) { - mutt_message (_("No (valid) certificate found for %s."), q->mailbox); + if (! auto_mode) + mutt_message (_("No (valid) certificate found for %s."), q->mailbox); FREE (&keylist); - rfc822_free_address (&tmp); - rfc822_free_address (&addr); return NULL; } @@ -790,10 +767,7 @@ char *smime_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) sprintf (keylist + keylist_used, "%s\n", keyID); /* __SPRINTF_CHECKED__ */ keylist_used = mutt_strlen (keylist); - rfc822_free_address (&addr); - } - rfc822_free_address (&tmp); return (keylist); } diff --git a/smime.h b/smime.h index b2efe61f4..520d8f1d6 100644 --- a/smime.h +++ b/smime.h @@ -50,7 +50,7 @@ void smime_getkeys (ENVELOPE *); char* smime_ask_for_key (char *, char *, short); -char *smime_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc); +char *smime_findKeys (ADDRESS *adrlist, int auto_mode); void smime_invoke_import (char *, char *);