aboutsummaryrefslogtreecommitdiffstats
path: root/g10/getkey.c
diff options
context:
space:
mode:
authorNeal H. Walfield <[email protected]>2015-12-22 13:57:53 +0000
committerNeal H. Walfield <[email protected]>2015-12-22 14:03:56 +0000
commit7195b94345b0bb937477dc47fc5ec27fb108a099 (patch)
treea05f3847d97129fdd58eb67a3b892155158d4bd1 /g10/getkey.c
parentgpg: Lazily evaluate --default-key. (diff)
downloadgnupg-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/getkey.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index ad0c207bf..45c3f512b 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -366,6 +366,282 @@ getkey_disable_caches ()
}
+void
+pubkey_free (struct pubkey *key)
+{
+ xfree (key->pk);
+ release_kbnode (key->keyblock);
+ xfree (key);
+}
+
+void
+pubkeys_free (struct pubkey *keys)
+{
+ while (keys)
+ {
+ struct pubkey *next = keys->next;
+ pubkey_free (keys);
+ keys = next;
+ }
+}
+
+/* Returns all keys that match the search specfication SEARCH_TERMS.
+
+ This function also checks for and warns about duplicate entries in
+ the keydb, which can occur if the user has configured multiple
+ keyrings or keyboxes or if a keyring or keybox was corrupted.
+
+ Note: SEARCH_TERMS will not be expanded (i.e., it may not be a
+ group).
+
+ USE is the operation for which the key is required. It must be
+ either PUBKEY_USAGE_ENC, PUBKEY_USAGE_SIG, PUBKEY_USAGE_CERT or
+ PUBKEY_USAGE_AUTH.
+
+ XXX: Currently, only PUBKEY_USAGE_ENC and PUBKEY_USAGE_SIG are
+ implemented.
+
+ INCLUDE_UNUSABLE indicates whether disabled keys are allowed.
+ (Recipients specified with --encrypt-to and --hidden-encrypt-to may
+ be disabled. It is possible to edit disabled keys.)
+
+ SOURCE is the context in which SEARCH_TERMS was specified, e.g.,
+ "--encrypt-to", etc. If this function is called interactively,
+ then this should be NULL.
+
+ If WARN_POSSIBLY_AMBIGUOUS is set, then emits a warning if the user
+ does not specify a long key id or a fingerprint.
+
+ The results are placed in *KEYS. *KEYS must be NULL! */
+gpg_error_t
+get_pubkeys (ctrl_t ctrl,
+ char *search_terms, int use, int include_unusable, char *source,
+ int warn_possibly_ambiguous,
+ struct pubkey **keys)
+{
+ /* We show a warning when a key appears multiple times in the DB.
+ This can happen for two reasons:
+
+ - The user has configured multiple keyrings or keyboxes.
+
+ - The keyring or keybox has been corrupted in some way, e.g., a
+ bug or a random process changing them.
+
+ For each duplicate, we only want to show the key once. Hence,
+ this list. */
+ static strlist_t key_dups;
+
+ /* USE transformed to a string. */
+ char *use_str;
+
+ gpg_error_t err;
+
+ KEYDB_SEARCH_DESC desc;
+
+ GETKEY_CTX ctx;
+ struct pubkey *results = NULL;
+ struct pubkey *r;
+
+ int count;
+
+ char fingerprint[2 * MAX_FINGERPRINT_LEN + 1];
+
+ if (DBG_LOOKUP)
+ {
+ log_debug ("\n");
+ log_debug ("%s: Checking %s=%s\n",
+ __func__, source ? source : "user input", search_terms);
+ }
+
+ if (*keys)
+ log_bug ("%s: KEYS should be NULL!\n", __func__);
+
+ switch (use)
+ {
+ case PUBKEY_USAGE_ENC: use_str = "encrypt"; break;
+ case PUBKEY_USAGE_SIG: use_str = "sign"; break;
+ case PUBKEY_USAGE_CERT: use_str = "cetify"; break;
+ case PUBKEY_USAGE_AUTH: use_str = "authentication"; break;
+ default: log_bug ("%s: Bad value for USE (%d)\n", __func__, use);
+ }
+
+ if (use == PUBKEY_USAGE_CERT || use == PUBKEY_USAGE_AUTH)
+ log_bug ("%s: use=%s is unimplemented.\n", __func__, use_str);
+
+ err = classify_user_id (search_terms, &desc, 1);
+ if (err)
+ {
+ log_info (_("key \"%s\" not found: %s\n"),
+ search_terms, gpg_strerror (err));
+ if (!opt.quiet && source)
+ log_info (_("(check argument of option '%s')\n"), source);
+ goto out;
+ }
+
+ 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: '%s' should be a long key ID or a fingerprint\n"),
+ search_terms);
+ if (!opt.quiet && source)
+ log_info (_("(check argument of option '%s')\n"), source);
+ }
+
+ /* Gather all of the results. */
+ ctx = NULL;
+ count = 0;
+ do
+ {
+ PKT_public_key *pk = xmalloc_clear (sizeof *pk);
+ KBNODE kb;
+ pk->req_usage = use;
+
+ if (! ctx)
+ err = get_pubkey_byname (ctrl, &ctx, pk, search_terms, &kb, NULL,
+ include_unusable, 1);
+ else
+ err = getkey_next (ctx, pk, &kb);
+
+ if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+ /* No more results. */
+ {
+ xfree (pk);
+ break;
+ }
+ else if (err)
+ /* An error (other than "not found"). */
+ {
+ log_error (_("error looking up: %s\n"),
+ gpg_strerror (err));
+ xfree (pk);
+ break;
+ }
+
+ /* Another result! */
+ count ++;
+
+ r = xmalloc_clear (sizeof (*r));
+ r->pk = pk;
+ r->keyblock = kb;
+ r->next = results;
+ results = r;
+ }
+ while (ctx);
+ getkey_end (ctx);
+
+ if (DBG_LOOKUP)
+ {
+ log_debug ("%s resulted in %d matches.\n", search_terms, 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)
+ /* No match. */
+ {
+ if (DBG_LOOKUP)
+ log_debug ("%s: '%s' not found.\n", __func__, search_terms);
+
+ log_info (_("key \"%s\" not found\n"), search_terms);
+ if (!opt.quiet && source)
+ log_info (_("(check argument of option '%s')\n"), source);
+
+ goto out;
+ }
+ else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+ /* No more matches. */
+ ;
+ else if (err)
+ /* Some other error. An error message was already printed
+ out. Free RESULTS and continue. */
+ goto out;
+
+ /* Check for duplicates. */
+ if (DBG_LOOKUP)
+ log_debug ("%s: Checking results of %s='%s' for dups\n",
+ __func__, source ? source : "user input", search_terms);
+ count = 0;
+ for (r = results; r; r = r->next)
+ {
+ struct pubkey **prevp;
+ struct pubkey *next;
+ struct pubkey *r2;
+ int dups = 0;
+
+ prevp = &r->next;
+ next = r->next;
+ while ((r2 = next))
+ {
+ if (cmp_public_keys (r->keyblock->pkt->pkt.public_key,
+ r2->keyblock->pkt->pkt.public_key) != 0)
+ /* Not a dup. */
+ {
+ prevp = &r2->next;
+ next = r2->next;
+ continue;
+ }
+
+ dups ++;
+ count ++;
+
+ /* Remove R2 from the list. */
+ *prevp = r2->next;
+ release_kbnode (r2->keyblock);
+ next = r2->next;
+ xfree (r2);
+ }
+
+ if (dups)
+ {
+ hexfingerprint (r->keyblock->pkt->pkt.public_key,
+ fingerprint, sizeof fingerprint);
+ if (! strlist_find (key_dups, fingerprint))
+ {
+ char fingerprint_formatted[MAX_FORMATTED_FINGERPRINT_LEN + 1];
+
+ 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 && count)
+ {
+ log_debug ("After removing %d dups:\n", count);
+ for (r = results, count = 0; r; r = r->next)
+ log_debug (" %d: %s\n",
+ count,
+ hexfingerprint (r->keyblock->pkt->pkt.public_key,
+ fingerprint, sizeof fingerprint));
+ }
+
+ out:
+ if (err)
+ {
+ while ((r = results))
+ {
+ results = results->next;
+ pubkey_free (r);
+ release_kbnode (r->keyblock);
+ xfree (r);
+ }
+ }
+ else
+ *keys = results;
+
+ return err;
+}
+
+
static void
pk_from_block (GETKEY_CTX ctx, PKT_public_key * pk, KBNODE keyblock,
KBNODE found_key)