auto_mode is used by crypt_opportunistic_encrypt to determine whether there are valid keys for all recipients of a message, without prompting the user.
The patch wraps around prompts, and makes getkeybyaddr methods return a valid key without prompting. crypt_getkeybyaddr() seems to be a bit different from pgp_getkeybyaddr(). In my testing, the gpgme method was NOT finding a single key in cases where the classic pgp method was. To make opportunistic_encrypt the most useful, I made both these methods return a key if they found ANY valid keys. The patch also enables a call to crypt_is_numerical_keyid() in find_keys(), so that crypt-hooks can actually be checked without prompting when gpgme is enabled. (The addition was patterned off of the pgp_findKeys() function). crypt-gpgme.c | 105 +++++++++++++++++++++++++++++++++++---------------------- pgp.c | 42 +++++++++++++--------- pgp.h | 2 +- pgpkey.c | 24 ++++++++++-- smime.c | 6 ++- 5 files changed, 114 insertions(+), 65 deletions(-)
# HG changeset patch # User Kevin McCarthy <ke...@8t8.us> # Date 1363403034 25200 # Branch HEAD # Node ID 1e48ca012c852879e46b94bd56d463e3db838831 # Parent 7082744ee06bb5388cb1de22147b20b210d06efc Implement auto_mode in the find_keys methods. auto_mode is used by crypt_opportunistic_encrypt to determine whether there are valid keys for all recipients of a message, without prompting the user. The patch wraps around prompts, and makes getkeybyaddr methods return a valid key without prompting. crypt_getkeybyaddr() seems to be a bit different from pgp_getkeybyaddr(). In my testing, the gpgme method was NOT finding a single key in cases where the classic pgp method was. To make opportunistic_encrypt the most useful, I made both these methods return a key if they found ANY valid keys. The patch also enables a call to crypt_is_numerical_keyid() in find_keys(), so that crypt-hooks can actually be checked without prompting when gpgme is enabled. (The addition was patterned off of the pgp_findKeys() function). diff --git a/crypt-gpgme.c b/crypt-gpgme.c --- a/crypt-gpgme.c +++ b/crypt-gpgme.c @@ -3954,17 +3954,18 @@ FREE (&key_table); set_option (OPTNEEDREDRAW); return k; } 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; int weak = 0; int invalid = 0; int multi = 0; int this_key_has_strong; @@ -3979,17 +3980,18 @@ *forced_valid = 0; if (a && a->mailbox) hints = crypt_add_string_to_hints (hints, a->mailbox); 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); if (!keys) return NULL; dprint (5, (debugfile, "crypt_getkeybyaddr: looking for %s <%s>.", @@ -4054,17 +4056,24 @@ the_valid_key = tmp; } } crypt_free_key (&keys); 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))) { /* * There was precisely one strong match on a valid ID, there * were no valid keys with weak matches, and we aren't * interested in seeing invalid keys. * * Proceed without asking the user. @@ -4082,17 +4091,17 @@ } else k = NULL; return k; } -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; crypt_key_t *keys; crypt_key_t *matches = NULL; crypt_key_t **matches_endp = &matches; crypt_key_t *k; @@ -4209,52 +4218,64 @@ } /* 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. */ 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 *addr = NULL; ADDRESS *p, *q; - 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 (p = adrlist; p ; p = p->next) { char buf[LONG_STRING]; int forced_valid = 0; q = p; k_info = NULL; 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))) { if (fqdn) rfc822_qualify (addr, fqdn); q = addr; } - else + else if (! auto_mode) { #if 0 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, *r_application, &forced_valid); #else k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, app, &forced_valid); #endif @@ -4263,58 +4284,62 @@ else if (r == -1) { FREE (&keylist); 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 (&addr); - return NULL; - } + &forced_valid); } - else - key = k_info; - - { - const char *s = crypt_fpr (key); + + if (k_info == NULL) + { + FREE (&keylist); + rfc822_free_address (&addr); + return NULL; + } + + + 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); } return (keylist); } char *pgp_gpgme_findkeys (ADDRESS *adrlist, int auto_mode) { return find_keys (adrlist, APPLICATION_PGP, auto_mode); diff --git a/pgp.c b/pgp.c --- a/pgp.c +++ b/pgp.c @@ -1139,86 +1139,94 @@ */ char *pgp_findKeys (ADDRESS *adrlist, int auto_mode) { char *keyID, *keylist = NULL; size_t keylist_size = 0; size_t keylist_used = 0; ADDRESS *addr = NULL; ADDRESS *p, *q; - pgp_key_t k_info = NULL, key = NULL; + pgp_key_t k_info = NULL; const char *fqdn = mutt_fqdn (1); for (p = adrlist; p ; p = p->next) { char buf[LONG_STRING]; q = p; k_info = NULL; 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 (strchr (keyID, '@') && (addr = rfc822_parse_adrlist (NULL, keyID))) { 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 (&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 (&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; safe_realloc (&keylist, keylist_size); sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", /* __SPRINTF_CHECKED__ */ keyID); keylist_used = mutt_strlen (keylist); - pgp_free_key (&key); + pgp_free_key (&k_info); rfc822_free_address (&addr); } return (keylist); } /* Warning: "a" is no longer freed in this routine, you need * to free it later. This is necessary for $fcc_attach. */ diff --git a/pgp.h b/pgp.h --- a/pgp.h +++ b/pgp.h @@ -41,17 +41,17 @@ int pgp_decrypt_mime (FILE *, FILE **, BODY *, BODY **); /* int pgp_string_matches_hint (const char *s, LIST * hints); */ /* 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 *adrlist, int auto_mode); void pgp_forget_passphrase (void); int pgp_application_pgp_handler (BODY *, STATE *); int pgp_encrypted_handler (BODY *, STATE *); void pgp_extract_keys_from_attachment_list (FILE * fp, int tag, BODY * top); diff --git a/pgpkey.c b/pgpkey.c --- a/pgpkey.c +++ b/pgpkey.c @@ -807,17 +807,18 @@ { for (; p; p = p->next) if (!p->next) return &p->next; 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; int multi = 0; int match; pgp_key_t keys, k, kn; @@ -826,17 +827,18 @@ pgp_key_t *last = &matches; pgp_uid_t *q; if (a && a->mailbox) hints = pgp_add_string_to_hints (hints, a->mailbox); 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); if (!keys) return NULL; dprint (5, (debugfile, "pgp_getkeybyaddr: looking for %s <%s>.", @@ -890,37 +892,49 @@ last = pgp_get_lastp (k); } } pgp_free_key (&keys); 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. * * Proceed without asking the user. */ pgp_remove_key (&matches, the_valid_key); - pgp_free_key (&matches); k = the_valid_key; } else { /* * Else: Ask the user. */ if ((k = pgp_select_key (matches, a, NULL))) pgp_remove_key (&matches, k); - pgp_free_key (&matches); } + pgp_free_key (&matches); + return k; } return NULL; } pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring) { diff --git a/smime.c b/smime.c --- a/smime.c +++ b/smime.c @@ -741,26 +741,28 @@ ADDRESS *p, *q; 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: "), q->mailbox); keyID = smime_ask_for_key(buf, q->mailbox, 1); } 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); return NULL; } keylist_size += mutt_strlen (keyID) + 2; safe_realloc (&keylist, keylist_size); sprintf (keylist + keylist_used, "%s\n", keyID); /* __SPRINTF_CHECKED__ */ keylist_used = mutt_strlen (keylist);