diff options
author | Neal H. Walfield <[email protected]> | 2015-12-22 13:57:53 +0000 |
---|---|---|
committer | Neal H. Walfield <[email protected]> | 2015-12-22 14:03:56 +0000 |
commit | 7195b94345b0bb937477dc47fc5ec27fb108a099 (patch) | |
tree | a05f3847d97129fdd58eb67a3b892155158d4bd1 /g10/gpg.c | |
parent | gpg: Lazily evaluate --default-key. (diff) | |
download | gnupg-7195b94345b0bb937477dc47fc5ec27fb108a099.tar.gz gnupg-7195b94345b0bb937477dc47fc5ec27fb108a099.zip |
gpg: Don't check for ambiguous keys.
* g10/gpg.c (struct result): Move from here...
* g10/keydb.h (struct pubkey): ... to here. Update users.
* g10/gpg.c (check_user_ids): Move from here...
* g10/getkey.c (get_pubkeys): ... to here. Update users. Use
get_pubkey_byname to look up the keys (this also prunes invalid keys).
(pubkey_free): New function.
(pubkeys_free): New function.
* g10/gpg.c (main): Don't check for ambiguous key specifications.
--
Signed-off-by: Neal H. Walfield <[email protected]>
Regression-due-to: e8c53fc
This change not only moves the checks for ambiguous key specifications
from gpg.c to getkey.c, it also disables the checks. The old code was
too divorced from the actual key lookups and, as such, it reproduced
the logic. Unfortunately, the reproduction was a poor one: despite
fixing some inconsistencies (e.g., 10cca02), it still didn't deal with
group expansion or the auto key lookup functionality. Given the
amount of instability introduced by this change, we (Neal & Werner)
decided it is better to defer introducing this functionality until
2.3.
Diffstat (limited to '')
-rw-r--r-- | g10/gpg.c | 512 |
1 files changed, 0 insertions, 512 deletions
@@ -2101,506 +2101,6 @@ get_default_configname (void) return configname; } -struct result -{ - struct result *next; - kbnode_t keyblock; - int processed; -}; - -/* We show a warning when a key appears multiple times in the DB. */ -static strlist_t key_dups; - -static gpg_error_t -check_user_ids (strlist_t *sp, - int warn_possibly_ambiguous, - int error_if_not_found) -{ - strlist_t s = *sp; - strlist_t s2 = NULL; - strlist_t t; - - gpg_error_t rc = 0; - gpg_error_t err; - - KEYDB_HANDLE hd = NULL; - - char fingerprint_formatted[MAX_FORMATTED_FINGERPRINT_LEN + 1]; - - /* A quick check to avoid allocating a new strlist if we can skip - all keys. Handles also the case of !SP. See below for details. */ - for (t = s; t && (!(t->flags & PK_LIST_CONFIG) - && !(t->flags & PK_LIST_ENCRYPT_TO)); t = t->next) - ; - if (!t) - return 0; - - for (t = s; t; t = t->next) - { - const char *option_str; - int option; - - KEYDB_SEARCH_DESC desc; - struct result *results = NULL; - struct result *r; - - int count; - - /* We also potentially need a ! at the end. */ - char fingerprint[2 * MAX_FINGERPRINT_LEN + 1 + 1]; - char fingerprint2[2 * MAX_FINGERPRINT_LEN + 1]; - - KBNODE best_kb; - PKT_public_key *best_pk; - - /* Whether the key is for encryption or signing. */ - int encrypt = 1; - - /* If the key has been given on the command line and it has not - been given by one of the encrypt-to options, we skip the - checks. The reason is that the actual key selection code - does its own checks and provides proper status message to the - caller to detect the wrong keys. */ - if (!(t->flags & PK_LIST_CONFIG) && !(t->flags & PK_LIST_ENCRYPT_TO)) - { - add_to_strlist (&s2, t->d); - s2->flags = t->flags; - continue; - } - - option = t->flags >> PK_LIST_SHIFT; - switch (option) - { - case oDefaultKey: - option_str = "--default-key"; - encrypt = 0; - break; - case oLocalUser: - option_str = "--local-user"; - encrypt = 0; - break; - - case oEncryptTo: option_str = "--encrypt-to"; break; - case oHiddenEncryptTo: option_str = "--hidden-encrypt-to"; break; - case oEncryptToDefaultKey: option_str = "--encrypt-to-default-key"; break; - case oRecipient: option_str = "--recipient"; break; - case oHiddenRecipient: option_str = "--hidden-recipient"; break; - default: - log_bug ("Unsupport option: %d\n", (t->flags >> PK_LIST_SHIFT)); - } - - if (DBG_LOOKUP) - { - log_debug ("\n"); - log_debug ("%s: Checking %s=%s\n", __func__, option_str, t->d); - } - - err = classify_user_id (t->d, &desc, 1); - if (err) - { - if (! rc) - rc = err; - - log_error (_("key \"%s\" not found: %s\n"), - t->d, gpg_strerror (err)); - if (!opt.quiet) - log_info (_("(check argument of option '%s')\n"), option_str); - continue; - } - - if (warn_possibly_ambiguous - && ! (desc.mode == KEYDB_SEARCH_MODE_LONG_KID - || desc.mode == KEYDB_SEARCH_MODE_FPR16 - || desc.mode == KEYDB_SEARCH_MODE_FPR20 - || desc.mode == KEYDB_SEARCH_MODE_FPR)) - log_info (_("Warning: value '%s' for option '%s'" - " should be a long key ID or a fingerprint\n"), - t->d, option_str); - - if (! hd) - { - hd = keydb_new (); - if (!hd) - { - rc = gpg_error_from_syserror (); - break; - } - } - else - keydb_search_reset (hd); - - /* Gather all of the results. */ - count = 0; - while (1) - { - KBNODE kb; - - err = keydb_search (hd, &desc, 1, NULL); - if (gpg_err_code (err) == GPG_ERR_NOT_FOUND - || gpg_err_code (err) == GPG_ERR_EOF) - /* No more results. */ - break; - else if (err) - /* An error (other than "not found"). */ - { - log_error (_("error searching the keyring: %s\n"), - gpg_strerror (err)); - break; - } - - err = keydb_get_keyblock (hd, &kb); - if (err) - { - log_error (_("error reading keyblock: %s\n"), gpg_strerror (err)); - break; - } - - /* Another result! */ - count ++; - - r = xmalloc_clear (sizeof (*r)); - r->keyblock = kb; - r->next = results; - results = r; - } - - if (DBG_LOOKUP) - { - log_debug ("%s resulted in %d matches.\n", t->d, count); - for (r = results; r; r = r->next) - log_debug (" %s\n", - hexfingerprint (r->keyblock->pkt->pkt.public_key, - fingerprint, sizeof (fingerprint))); - } - - if (! results && (gpg_err_code (err) == GPG_ERR_NOT_FOUND - || gpg_err_code (err) == GPG_ERR_EOF)) - /* No match. */ - { - if (DBG_LOOKUP) - log_debug ("%s: '%s' not found.\n", __func__, t->d); - - if (error_if_not_found) - { - if (! rc) - rc = err; - - log_error (_("key \"%s\" not found\n"), t->d); - if (!opt.quiet) - log_info (_("(check argument of option '%s')\n"), option_str); - } - continue; - } - else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND - || gpg_err_code (err) == GPG_ERR_EOF) - /* No more matches. */ - ; - else if (err) - /* Some other error. An error message was already printed - out. Free RESULTS and continue. */ - { - if (! rc) - rc = err; - - while ((r = results)) - { - results = results->next; - release_kbnode (r->keyblock); - xfree (r); - } - - continue; - } - - /* Check for duplicates. */ - - if (DBG_LOOKUP) - log_debug ("%s: Checking results of %s='%s' for dups\n", - __func__, option_str, t->d); - while (1) - { - struct result **prevp; - struct result *next; - struct result *r2; - int dups = 0; - - /* After checking a result, we set R->PROCESSED. Find the - next unprocessed result. */ - for (r = results; r; r = r->next) - if (! r->processed) - break; - - if (! r) - /* There is nothing left to check. */ - break; - - hexfingerprint (r->keyblock->pkt->pkt.public_key, - fingerprint, sizeof fingerprint); - r->processed = 1; - - prevp = &results; - next = results; - while ((r2 = next)) - { - if (r2->processed) - { - prevp = &r2->next; - next = r2->next; - continue; - } - - hexfingerprint (r2->keyblock->pkt->pkt.public_key, - fingerprint2, sizeof fingerprint2); - - if (strcmp (fingerprint, fingerprint2) != 0) - /* Not a dup. */ - { - prevp = &r2->next; - next = r2->next; - continue; - } - - dups ++; - - /* Remove R2 from the list. */ - *prevp = r2->next; - release_kbnode (r2->keyblock); - next = r2->next; - xfree (r2); - } - - if (dups && ! strlist_find (key_dups, fingerprint)) - { - log_info (_("Warning: %s appears in the keyring %d times.\n"), - format_hexfingerprint (fingerprint, - fingerprint_formatted, - sizeof fingerprint_formatted), - 1 + dups); - add_to_strlist (&key_dups, fingerprint); - } - } - - if (DBG_LOOKUP) - { - log_debug ("After removing dups:\n"); - for (r = results, count = 0; r; r = r->next) - { - count ++; - log_debug (" %d: %s\n", - count, - hexfingerprint (r->keyblock->pkt->pkt.public_key, - fingerprint, sizeof fingerprint)); - } - } - - /* Now we find the best key. */ - assert (results); - /* Prune invalid keys. */ - { - int ambiguous = 0; - - if (DBG_LOOKUP) - log_debug ("Pruning bad keys.\n"); - - best_pk = NULL; - for (r = results; r; r = r->next) - { - KBNODE kb = r->keyblock; - PKT_public_key *pk = kb->pkt->pkt.public_key; - KBNODE n; - - /* Merge in the data from the self sigs so that things - like the revoked status are available. */ - merge_keys_and_selfsig (kb); - - if (/* Using disabled keys with --encrypt-to is allowed. */ - ! (option == oEncryptTo || option == oHiddenEncryptTo) - && pk_is_disabled (pk)) - { - if (DBG_LOOKUP) - log_debug (" Skipping disabled key: %s\n", - hexfingerprint (pk, fingerprint, - sizeof fingerprint)); - continue; - } - if (pk->flags.revoked) - { - if (DBG_LOOKUP) - log_debug (" Skipping revoked key: %s\n", - hexfingerprint (pk, fingerprint, - sizeof fingerprint)); - continue; - } - if (pk->has_expired) - { - if (DBG_LOOKUP) - log_debug (" Skipping expired key: %s\n", - hexfingerprint (pk, fingerprint, - sizeof fingerprint)); - continue; - } - - /* Check for the required encryption or signing - capability. */ - n = kb; - do - { - PKT_public_key *key = n->pkt->pkt.public_key; - - if ((/* Using disabled keys with --encrypt-to is allowed. */ - pk_is_disabled (key) - && ! (option == oEncryptTo - || option == oHiddenEncryptTo)) - || key->flags.revoked - || key->has_expired) - /* Invalid. */ - continue; - - if (encrypt && ! (key->pubkey_usage & PUBKEY_USAGE_ENC)) - continue; - if (! encrypt && ! (key->pubkey_usage & PUBKEY_USAGE_SIG)) - continue; - - /* Key passes basic tests. */ - break; - } - while ((n = find_next_kbnode (n, PKT_PUBLIC_SUBKEY))); - - if (! n) - { - if (DBG_LOOKUP) - log_debug (" Skipping %s, which does not have %s capability.\n", - hexfingerprint (r->keyblock->pkt->pkt.public_key, - fingerprint, sizeof fingerprint), - encrypt ? "encrypt" : "sign"); - continue; - } - else if (DBG_LOOKUP) - log_debug (" %s is valid and has %s capability.\n", - hexfingerprint (r->keyblock->pkt->pkt.public_key, - fingerprint, sizeof fingerprint), - encrypt ? "encrypt" : "sign"); - - - if (! best_pk) - { - best_pk = pk; - best_kb = kb; - continue; - } - - /* We have multiple candidates. Prefer the newer key. - - XXX: we should also consider key capabilities (if we - are encrypting to the key, does it have an encryption - capability?). - - XXX: if we are signing, then we should consider the - key that is actually available (e.g., if one is on a - smart card). */ - ambiguous = 1; - if (best_pk->timestamp < pk->timestamp) - best_pk = pk; - } - - if (! results) - { - if (encrypt) - log_error (_("%s: no matching keys are valid encryption keys"), - t->d); - else - log_error (_("%s: no matching keys are valid signing keys"), - t->d); - if (!opt.quiet) - log_info (_("(check argument of option '%s')\n"), option_str); - continue; - } - - if (ambiguous) - { - /* TRANSLATORS: The %s prints a key specification which - for example has been given at the command line. - Lines with fingerprints are printed after this - message. */ - log_error (_("key specification '%s' is ambiguous\n"), - t->d); - if (!opt.quiet) - log_info (_("(check argument of option '%s')\n"), - option_str); - - log_info (_("'%s' matches at least:\n"), t->d); - - for (r = results; r; r = r->next) - log_info (" %s\n", - format_hexfingerprint - (hexfingerprint (r->keyblock->pkt->pkt.public_key, - fingerprint, sizeof fingerprint), - fingerprint_formatted, - sizeof fingerprint_formatted)); - - if (! rc) - rc = GPG_ERR_AMBIGUOUS_NAME; - } - } - - if ((desc.mode == KEYDB_SEARCH_MODE_SHORT_KID - || desc.mode == KEYDB_SEARCH_MODE_LONG_KID - || desc.mode == KEYDB_SEARCH_MODE_FPR16 - || desc.mode == KEYDB_SEARCH_MODE_FPR20) - && strchr (t->d, '!')) - /* Exact search. In this case we want to set FINGERPRINT not - to the primary key, but the key (primary or sub) that - matched the search criteria. Note: there will always be - exactly one match. */ - { - kbnode_t n = best_kb; - PKT_public_key *match = NULL; - int i; - - do - { - if ((n->flag & 1)) - /* The matched node. */ - { - assert (! match); - match = n->pkt->pkt.public_key; - } - } - while ((n = find_next_kbnode (n, PKT_PUBLIC_SUBKEY))); - assert (match); - - hexfingerprint (match, fingerprint, sizeof fingerprint); - i = strlen (fingerprint); - fingerprint[i] = '!'; - fingerprint[i + 1] = '\0'; - } - else - hexfingerprint (best_pk, fingerprint, sizeof fingerprint); - - add_to_strlist (&s2, fingerprint); - s2->flags = s->flags; - - { - struct result *next = results; - while ((r = next)) - { - next = r->next; - release_kbnode (r->keyblock); - xfree (r); - } - } - } - - strlist_rev (&s2); - - keydb_release (hd); - - free_strlist (s); - *sp = s2; - return rc; -} - - int main (int argc, char **argv) { @@ -4280,18 +3780,6 @@ main (int argc, char **argv) break; } - { - rc = check_user_ids (&locusr, 1, 1); - if (rc) - g10_exit (1); - rc = check_user_ids (&remusr, 0, 1); - if (rc) - g10_exit (1); - rc = check_user_ids (&opt.def_secret_key, 1, 0); - if (rc) - g10_exit (1); - } - /* The command dispatcher. */ switch( cmd ) { |