--- PATCHES Wed Mar 19 22:33:37 2003 +++ PATCHES Thu Mar 20 21:38:55 2003 @@ -0,0 +1,3 @@ +patch-1.5.4.dw.confirm-crypt-hook.1 +patch-1.5.4.dw.multiple-crypt-hook.2 +patch-1.5.4.dw.crypt-autoselectkey.1 --- doc/manual.sgml.head Tue Mar 4 08:49:49 2003 +++ doc/manual.sgml.head Thu Mar 20 21:38:47 2003 @@ -1422,7 +1422,9 @@ or because, for some reasons, you need to override the key Mutt would normally use. The crypt-hook command provides a method by which you can specify the ID of the public key to be used when encrypting messages to -a certain recipient. +a certain recipient. You may use multiple pgp-hook's with the same +pattern; multiple matching pgp-hook's result in the use of multiple +keyids for recipient. The meaning of "key id" is to be taken broadly in this context: You can either put a numerical key ID here, an e-mail address, or even --- doc/muttrc.man.head.orig Sun Dec 22 20:50:22 2002 +++ doc/muttrc.man.head Sat Mar 22 23:43:27 2003 @@ -288,3 +288,6 @@ broadly: This can be a different e-mail address, a numerical key ID, -or even just an arbitrary search string. +or even just an arbitrary search string. You may use multiple +\fBpgp-hook\fPs with the same \fIpattern\fP; multiple matching +\fBpgp-hook\fPs result in the use of multiple \fIkey-id\fPs for +recipient. .TP --- hook.c Tue Jan 21 13:25:21 2003 +++ hook.c Thu Mar 20 21:38:47 2003 @@ -117,7 +117,11 @@ ptr->rx.not == not && !mutt_strcmp (pattern.data, ptr->rx.pattern)) { +#ifdef M_CRYPTHOOK + if (data & (M_FOLDERHOOK | M_SENDHOOK | M_MESSAGEHOOK | M_ACCOUNTHOOK | M_REPLYHOOK | M_CRYPTHOOK)) +#else if (data & (M_FOLDERHOOK | M_SENDHOOK | M_MESSAGEHOOK | M_ACCOUNTHOOK | M_REPLYHOOK)) +#endif { /* these hooks allow multiple commands with the same * pattern, so if we've already seen this pattern/command pair, just @@ -443,9 +447,25 @@ return _mutt_string_hook (chs, M_ICONVHOOK); } -char *mutt_crypt_hook (ADDRESS *adr) +LIST *mutt_crypt_hook (ADDRESS *adr) { - return _mutt_string_hook (adr->mailbox, M_CRYPTHOOK); + HOOK *hook; + LIST *key_list = NULL; + + if (!adr && !adr->mailbox) + return (NULL); + + for (hook = Hooks; hook; hook = hook->next) + { + if (!hook->command) + continue; + if (!(hook->type & M_CRYPTHOOK)) + continue; + + if ((regexec (hook->rx.rx, adr->mailbox, 0, NULL, 0) == 0) ^ hook->rx.not) + key_list = mutt_add_list (key_list, hook->command); + } + return (key_list); } #ifdef USE_SOCKET --- init.h Tue Mar 4 10:28:12 2003 +++ init.h Thu Mar 20 21:38:55 2003 @@ -1192,6 +1192,16 @@ ** when you are at the end of a message and invoke the \fInext-page\fP ** function. */ + + + { "pgp_autoselectkey", DT_SYN, R_NONE, UL "crypt_autoselectkey", 0 }, + { "crypt_autoselectkey", DT_BOOL, R_NONE, OPTCRYPTAUTOSELECT, 0 }, + /* + ** .pp + ** If set, then a list of keys is not presented for selection when only + ** one matching key is available. This may be useful in conjunction with + ** the \fIcrypt-hook\fP command. + */ { "pgp_autosign", DT_SYN, R_NONE, UL "crypt_autosign", 0 }, { "crypt_autosign", DT_BOOL, R_NONE, OPTCRYPTAUTOSIGN, 0 }, /* @@ -1216,6 +1226,15 @@ ** then OpenSSL is used instead to create S/MIME messages and ** settings can be overridden by use of the \fIsmime-menu\fP. ** (Crypto only) + */ + { "pgp_confirmhook", DT_SYN, R_NONE, UL "crypt_confirmhook", 1 }, + { "crypt_confirmhook", DT_BOOL, R_NONE, OPTCRYPTCONFIRMHOOK, 1 }, + /* + ** .pp + ** If set, then you will be prompted for confirmation of keys when using + ** the \fIcrypt-hook\fP command. If unset, no such confirmation prompt will + ** be presented. This is generally considered unsafe, especially where + ** typos are concerned. */ { "pgp_ignore_subkeys", DT_BOOL, R_NONE, OPTPGPIGNORESUB, 1}, /* --- mutt.h Tue Mar 4 08:49:48 2003 +++ mutt.h Thu Mar 20 21:38:55 2003 @@ -425,6 +425,7 @@ /* PGP options */ + OPTCRYPTAUTOSELECT, OPTCRYPTAUTOSIGN, OPTCRYPTAUTOENCRYPT, OPTCRYPTREPLYENCRYPT, @@ -434,6 +435,7 @@ OPTSMIMEISDEFAULT, OPTASKCERTLABEL, OPTSDEFAULTDECRYPTKEY, + OPTCRYPTCONFIRMHOOK, OPTPGPIGNORESUB, OPTPGPLONGIDS, OPTPGPAUTOTRAD, --- pgp.c Tue Feb 25 22:28:54 2003 +++ pgp.c Thu Mar 20 21:40:39 2003 @@ -1014,6 +1014,8 @@ char *keyID, *keylist = NULL, *t; size_t keylist_size = 0; size_t keylist_used = 0; + LIST *hook_list = NULL; + LIST *hook = NULL; ADDRESS *tmp = NULL, *addr = NULL; ADDRESS **last = &tmp; ADDRESS *p, *q; @@ -1047,70 +1049,97 @@ char buf[LONG_STRING]; q = p; - k_info = NULL; - if ((keyID = mutt_crypt_hook (p)) != NULL) + /* + * grab the list of matching hooks (matching on recipient address) + * process each entry singly so that auto key selection still works + */ + hook_list = mutt_crypt_hook (p); + hook = hook_list; + while (1) { int r; - snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox); - if ((r = mutt_yesorno (buf, M_YES)) == M_YES) + + k_info = NULL; + key = NULL; + + if (hook) { - if (is_numerical_keyid (keyID)) + keyID = (char *)hook->data; + snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox); + if (!option(OPTCRYPTCONFIRMHOOK) || (r = mutt_yesorno (buf, M_YES)) == M_YES) { - if (strncmp (keyID, "0x", 2) == 0) - keyID += 2; - goto bypass_selection; /* you don't see this. */ + if (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))) + { + if (fqdn) rfc822_qualify (addr, fqdn); + q = addr; + } + else + k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING); } - - /* check for e-mail address */ - if ((t = strchr (keyID, '@')) && - (addr = rfc822_parse_adrlist (NULL, keyID))) + else if (r == -1) { - if (fqdn) rfc822_qualify (addr, fqdn); - q = addr; + /* + * yes, this implies that if one key fails they all do + */ + FREE (&keylist); + rfc822_free_address (&tmp); + rfc822_free_address (&addr); + mutt_free_list (&hook_list); + return NULL; } - else - 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); - if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) - { - snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox); + if (k_info == NULL) + pgp_invoke_getkeys (q); - if ((key = pgp_ask_for_key (buf, q->mailbox, - KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) + if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) { - FREE (&keylist); - rfc822_free_address (&tmp); - rfc822_free_address (&addr); - return NULL; + snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox); + + if ((key = pgp_ask_for_key (buf, q->mailbox, + KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) + { + FREE (&keylist); + rfc822_free_address (&tmp); + rfc822_free_address (&addr); + mutt_free_list (&hook_list); + return NULL; + } } - } - else - key = k_info; + else + key = k_info; - keyID = pgp_keyid (key); + keyID = pgp_keyid (key); bypass_selection: - keylist_size += mutt_strlen (keyID) + 4; - safe_realloc ((void **)&keylist, keylist_size); - sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", /* __SPRINTF_CHECKED__ */ - keyID); - keylist_used = mutt_strlen (keylist); + keylist_size += mutt_strlen (keyID) + 4; + safe_realloc ((void **)&keylist, keylist_size); + sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", /* __SPRINTF_CHECKED__ */ + keyID); + keylist_used = mutt_strlen (keylist); + + pgp_free_key (&key); + rfc822_free_address (&addr); + + if (!hook_list) + break; + + hook = hook->next; + if (!hook) + break; - pgp_free_key (&key); - rfc822_free_address (&addr); + } + mutt_free_list (&hook_list); } rfc822_free_address (&tmp); --- pgpkey.c Tue Jan 21 13:25:21 2003 +++ pgpkey.c Thu Mar 20 21:38:32 2003 @@ -435,8 +435,13 @@ return rv; } + +#define pgp_trusted_id(uid) (!option(OPTPGPCHECKTRUST) \ + || (pgp_id_is_valid((uid)) \ + && pgp_id_is_strong((uid)))) + static pgp_key_t pgp_select_key (pgp_key_t keys, - ADDRESS * p, const char *s) + ADDRESS * p, const char *s) { int keymax; pgp_uid_t **KeyTable; @@ -450,6 +455,7 @@ pgp_uid_t *a; int (*f) (const void *, const void *); + int keymatch = 0; /* count matching keys */ int unusable = 0; keymax = 0; @@ -479,6 +485,7 @@ KeyTable[i++] = a; } + keymatch++; } if (!i && unusable) @@ -487,6 +494,21 @@ mutt_sleep (1); return NULL; } + else if (keymatch == 1 && option(OPTCRYPTAUTOSELECT)) + { + /* + * Only one matching key...see if there's an id with enough trust to auto-select + */ + kp = KeyTable[0]->parent; + for (a = kp->address; a; a = a->next) + { + if (pgp_trusted_id(a)) + { + safe_free ((void **) &KeyTable); + return (kp); + } + } + } switch (PgpSortKeys & SORT_MASK) { @@ -597,9 +619,7 @@ break; } - if (option (OPTPGPCHECKTRUST) && - (!pgp_id_is_valid (KeyTable[menu->current]) - || !pgp_id_is_strong (KeyTable[menu->current]))) + if (!pgp_trusted_id(KeyTable[menu->current])) { char *s = ""; char buff[LONG_STRING]; --- protos.h Thu Mar 6 22:24:46 2003 +++ protos.h Thu Mar 20 21:38:47 2003 @@ -129,7 +129,7 @@ char *mutt_get_body_charset (char *, size_t, BODY *); const char *mutt_get_name (ADDRESS *); char *mutt_get_parameter (const char *, PARAMETER *); -char *mutt_crypt_hook (ADDRESS *); +LIST *mutt_crypt_hook (ADDRESS *); char *mutt_make_date (char *, size_t); const char *mutt_make_version (void);