Implement oppenc_mode in the find_keys methods. oppenc_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 address-matching key without prompting. The patch also fixes a small problem with gpgme's getkeybyaddr. When determining if there were multiple strong matches, it was comparing the crypt_key_t instead of its kobj member (gpgme_key_t). 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). -Kevin
# HG changeset patch # User Kevin McCarthy <[email protected]> # Date 1423248571 28800 # Fri Feb 06 10:49:31 2015 -0800 # Node ID f6dc07414374fee69baaff7f0508dcbc0a444ee0 # Parent 5475ea594ba7451a6cc23ce70d6b8ccd37eb0cda Implement oppenc_mode in the find_keys methods. oppenc_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 address-matching key without prompting. The patch also fixes a small problem with gpgme's getkeybyaddr. When determining if there were multiple strong matches, it was comparing the crypt_key_t instead of its kobj member (gpgme_key_t). 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 @@ -4064,42 +4064,47 @@ 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 oppenc_mode) { ADDRESS *r, *p; LIST *hints = NULL; int weak = 0; int invalid = 0; + int addr_match = 0; int multi = 0; int this_key_has_strong; + int this_key_has_addr_match; int this_key_has_weak; int this_key_has_invalid; int match; crypt_key_t *keys, *k; - crypt_key_t *the_valid_key = NULL; + crypt_key_t *the_strong_valid_key = NULL; + crypt_key_t *a_valid_addrmatch_key = NULL; crypt_key_t *matches = NULL; crypt_key_t **matches_endp = &matches; *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 (! oppenc_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>.", @@ -4115,94 +4120,115 @@ dprint (5, (debugfile, " insufficient abilities: Has %x, want %x\n", k->flags, abilities)); continue; } this_key_has_weak = 0; /* weak but valid match */ this_key_has_invalid = 0; /* invalid match */ this_key_has_strong = 0; /* strong and valid match */ + this_key_has_addr_match = 0; match = 0; /* any match */ r = rfc822_parse_adrlist (NULL, k->uid); for (p = r; p; p = p->next) { int validity = crypt_id_matches_addr (a, p, k); if (validity & CRYPT_KV_MATCH) /* something matches */ + { match = 1; - /* is this key a strong candidate? */ - if ((validity & CRYPT_KV_VALID) - && (validity & CRYPT_KV_STRONGID) - && (validity & CRYPT_KV_ADDR)) + if (validity & CRYPT_KV_VALID) { - if (the_valid_key && the_valid_key != k) - multi = 1; - the_valid_key = k; - this_key_has_strong = 1; + if (validity & CRYPT_KV_ADDR) + { + if (validity & CRYPT_KV_STRONGID) + { + if (the_strong_valid_key + && the_strong_valid_key->kobj != k->kobj) + multi = 1; + this_key_has_strong = 1; + } + else + this_key_has_addr_match = 1; + } + else + this_key_has_weak = 1; } - else if ((validity & CRYPT_KV_MATCH) - && !(validity & CRYPT_KV_VALID)) - this_key_has_invalid = 1; - else if ((validity & CRYPT_KV_MATCH) - && (!(validity & CRYPT_KV_STRONGID) - || !(validity & CRYPT_KV_ADDR))) - this_key_has_weak = 1; + else + this_key_has_invalid = 1; + } } rfc822_free_address (&r); if (match) { crypt_key_t *tmp; - if (!this_key_has_strong && this_key_has_invalid) - invalid = 1; - if (!this_key_has_strong && this_key_has_weak) - weak = 1; - *matches_endp = tmp = crypt_copy_key (k); matches_endp = &tmp->next; - the_valid_key = tmp; + + if (this_key_has_strong) + the_strong_valid_key = tmp; + else if (this_key_has_addr_match) + { + addr_match = 1; + a_valid_addrmatch_key = tmp; + } + else if (this_key_has_invalid) + invalid = 1; + else if (this_key_has_weak) + weak = 1; } } crypt_free_key (&keys); if (matches) { - if (the_valid_key && !multi && !weak + if (oppenc_mode) + { + if (the_strong_valid_key) + k = crypt_copy_key (the_strong_valid_key); + else if (a_valid_addrmatch_key) + k = crypt_copy_key (a_valid_addrmatch_key); + else + k = NULL; + } + else if (the_strong_valid_key && !multi && !weak && !addr_match && !(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. */ - k = crypt_copy_key (the_valid_key); + k = crypt_copy_key (the_strong_valid_key); } else { /* * Else: Ask the user. */ k = crypt_select_key (matches, a, NULL, app, forced_valid); } + crypt_free_key (&matches); } 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; const char *ps, *pl; @@ -4329,52 +4355,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 oppenc_mode is true, only keys that can be determined without prompting will be used. */ static char *find_keys (ADDRESS *adrlist, unsigned int app, int oppenc_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 (! oppenc_mode) { + snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), + keyID, p->mailbox); + r = mutt_yesorno (buf, M_YES); + } + if (oppenc_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 (! oppenc_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 @@ -4383,58 +4421,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, oppenc_mode); + } + + if ((k_info == NULL) && (! oppenc_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 oppenc_mode) { return find_keys (adrlist, APPLICATION_PGP, oppenc_mode); diff --git a/pgp.c b/pgp.c --- a/pgp.c +++ b/pgp.c @@ -1162,86 +1162,94 @@ */ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_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 (! oppenc_mode) + { + snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox); + r = mutt_yesorno (buf, M_YES); + } + if (oppenc_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 (! oppenc_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, oppenc_mode); + } - if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) + if ((k_info == NULL) && (! oppenc_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 @@ -43,17 +43,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 oppenc_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,36 +807,39 @@ { 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 oppenc_mode) { ADDRESS *r, *p; LIST *hints = NULL; int multi = 0; int match; pgp_key_t keys, k, kn; - pgp_key_t the_valid_key = NULL; + pgp_key_t the_strong_valid_key = NULL; + pgp_key_t a_valid_addrmatch_key = NULL; pgp_key_t matches = NULL; 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 (! oppenc_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>.", @@ -865,24 +868,30 @@ for (p = r; p; p = p->next) { int validity = pgp_id_matches_addr (a, p, q); if (validity & PGP_KV_MATCH) /* something matches */ match = 1; - /* is this key a strong candidate? */ - if ((validity & PGP_KV_VALID) && (validity & PGP_KV_STRONGID) - && (validity & PGP_KV_ADDR)) - { - if (the_valid_key && the_valid_key != k) - multi = 1; - the_valid_key = k; - } + if ((validity & PGP_KV_VALID) + && (validity & PGP_KV_ADDR)) + { + if (validity & PGP_KV_STRONGID) + { + if (the_strong_valid_key && the_strong_valid_key != k) + multi = 1; + the_strong_valid_key = k; + } + else + { + a_valid_addrmatch_key = k; + } + } } rfc822_free_address (&r); } if (match) { *last = pgp_principal_key (k); @@ -890,37 +899,52 @@ last = pgp_get_lastp (k); } } pgp_free_key (&keys); if (matches) { - if (the_valid_key && !multi) + if (oppenc_mode) + { + if (the_strong_valid_key) + { + pgp_remove_key (&matches, the_strong_valid_key); + k = the_strong_valid_key; + } + else if (a_valid_addrmatch_key) + { + pgp_remove_key (&matches, a_valid_addrmatch_key); + k = a_valid_addrmatch_key; + } + else + k = NULL; + } + else if (the_strong_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; + pgp_remove_key (&matches, the_strong_valid_key); + k = the_strong_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, !oppenc_mode); + if ((keyID == NULL) && (! oppenc_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 (! oppenc_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);
signature.asc
Description: PGP signature
