From: Kevin McCarthy Date: Mon, 30 Mar 2015 22:45:52 +0000 (-0700) Subject: Implement oppenc_mode in the find_keys methods. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d062c47e7e8d43162564db9dabd0b4f770eadc22;p=neomutt 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 index 1aa96d4a3..78b4a967b 100644 --- a/crypt-gpgme.c +++ b/crypt-gpgme.c @@ -4052,21 +4052,25 @@ 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 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; @@ -4077,7 +4081,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 (! oppenc_mode ) + mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox); keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN) ); mutt_free_list (&hints); @@ -4103,6 +4108,7 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, 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); @@ -4111,25 +4117,29 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, 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); @@ -4137,14 +4147,20 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, { 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; } } @@ -4152,7 +4168,16 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, 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))) { /* @@ -4162,7 +4187,7 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, * * Proceed without asking the user. */ - k = crypt_copy_key (the_valid_key); + k = crypt_copy_key (the_strong_valid_key); } else { @@ -4171,6 +4196,7 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, */ k = crypt_select_key (matches, a, NULL, app, forced_valid); } + crypt_free_key (&matches); } else @@ -4180,7 +4206,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; @@ -4310,12 +4336,13 @@ static crypt_key_t *crypt_ask_for_key (char *tag, 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 @@ -4332,11 +4359,22 @@ static char *find_keys (ADDRESS *adrlist, unsigned int app, int oppenc_mode) 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))) @@ -4345,7 +4383,7 @@ static char *find_keys (ADDRESS *adrlist, unsigned int app, int oppenc_mode) rfc822_qualify (addr, fqdn); q = addr; } - else + else if (! oppenc_mode) { #if 0 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, @@ -4364,48 +4402,52 @@ static char *find_keys (ADDRESS *adrlist, unsigned int app, int oppenc_mode) } } - 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); + } + + 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); } return (keylist); diff --git a/pgp.c b/pgp.c index 5d022bed9..665fb3f24 100644 --- a/pgp.c +++ b/pgp.c @@ -1179,7 +1179,7 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode) 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); @@ -1192,9 +1192,13 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode) 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)) { @@ -1210,8 +1214,10 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode) 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) { @@ -1222,24 +1228,26 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode) } 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; @@ -1248,7 +1256,7 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode) keyID); keylist_used = mutt_strlen (keylist); - pgp_free_key (&key); + pgp_free_key (&k_info); rfc822_free_address (&addr); } diff --git a/pgp.h b/pgp.h index ab8740455..46a54846b 100644 --- a/pgp.h +++ b/pgp.h @@ -48,7 +48,7 @@ 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 *adrlist, int oppenc_mode); diff --git a/pgpkey.c b/pgpkey.c index b21620f6d..083e8c02e 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 oppenc_mode) { ADDRESS *r, *p; LIST *hints = NULL; @@ -821,7 +822,8 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring) 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; @@ -831,7 +833,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 (! oppenc_mode ) + mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox); keys = pgp_get_candidates (keyring, hints); mutt_free_list (&hints); @@ -870,14 +873,20 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring) 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); @@ -895,16 +904,30 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring) 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 { @@ -913,9 +936,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/smime.c b/smime.c index 000994597..b7e17cd5c 100644 --- a/smime.c +++ b/smime.c @@ -746,7 +746,8 @@ char *smime_findKeys (ADDRESS *adrlist, int oppenc_mode) 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: "), @@ -755,7 +756,8 @@ char *smime_findKeys (ADDRESS *adrlist, int oppenc_mode) } 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; }