aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--g10/getkey.c276
-rw-r--r--g10/gpg.c512
-rw-r--r--g10/keydb.h23
-rw-r--r--g10/pkclist.c7
-rw-r--r--g10/skclist.c7
6 files changed, 316 insertions, 512 deletions
diff --git a/NEWS b/NEWS
index c19c1cd12..2ee35e6c8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,9 @@
Noteworthy changes in version 2.1.11 (unreleased)
-------------------------------------------------
+ * gpg: Don't check for ambigious or non-matching key specification in
+ the config file or given to --encrypt-to. This feature will return
+ in 2.3.x.
Noteworthy changes in version 2.1.10 (2015-12-04)
-------------------------------------------------
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)
diff --git a/g10/gpg.c b/g10/gpg.c
index 71f44eddf..0e61238a3 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -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 )
{
diff --git a/g10/keydb.h b/g10/keydb.h
index 556b53726..66bfa57c0 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -485,6 +485,29 @@ int get_pubkey_fast ( PKT_public_key *pk, u32 *keyid );
using merge_selfsigs. */
KBNODE get_pubkeyblock( u32 *keyid );
+/* A list used by get_pubkeys to gather all of the matches. */
+struct pubkey
+{
+ struct pubkey *next;
+ /* The key to use (either the public key or the subkey). */
+ PKT_public_key *pk;
+ kbnode_t keyblock;
+};
+
+/* Free a single key. This does not remove key from any list! */
+void pubkey_free (struct pubkey *key);
+
+/* Free a list of public keys. */
+void pubkeys_free (struct pubkey *keys);
+
+/* Returns all keys that match the search specfication SEARCH_TERMS.
+ The returned keys should be freed using pubkeys_free. */
+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);
+
/* Find a public key identified by the name NAME.
If name appears to be a valid valid RFC822 mailbox (i.e., email
diff --git a/g10/pkclist.c b/g10/pkclist.c
index b6a213fe2..d7e78cb7c 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -914,6 +914,13 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
else
remusr = rcpts;
+ /* XXX: Change this function to use get_pubkeys instead of
+ get_pubkey_byname to detect ambiguous key specifications and warn
+ about duplicate keyblocks. For ambiguous key specifications on
+ the command line or provided interactively, prompt the user to
+ select the best key. If a key specification is ambiguous and we
+ are in batch mode, die. */
+
if (opt.encrypt_to_default_key)
{
static int warned;
diff --git a/g10/skclist.c b/g10/skclist.c
index 3d137b261..1eb0633fd 100644
--- a/g10/skclist.c
+++ b/g10/skclist.c
@@ -120,6 +120,13 @@ build_sk_list (ctrl_t ctrl,
gpg_error_t err;
SK_LIST sk_list = NULL;
+ /* XXX: Change this function to use get_pubkeys instead of
+ getkey_byname to detect ambiguous key specifications and warn
+ about duplicate keyblocks. For ambiguous key specifications on
+ the command line or provided interactively, prompt the user to
+ select the best key. If a key specification is ambiguous and we
+ are in batch mode, die. */
+
if (!locusr) /* No user ids given - use the default key. */
{
PKT_public_key *pk;