kbnode_t *ret_keyblock, kbnode_t *ret_found_key);
static kbnode_t finish_lookup (kbnode_t keyblock,
unsigned int req_usage, int want_exact,
- unsigned int *r_flags);
+ int want_secret, unsigned int *r_flags);
static void print_status_key_considered (kbnode_t keyblock, unsigned int flags);
}
}
-/* Returns all keys that match the search specification 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! */
+/* Returns all keys that match the search specification 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.
+ *
+ * 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!
+ *
+ * Fixme: Currently, only PUBKEY_USAGE_ENC and PUBKEY_USAGE_SIG are
+ * implemented. */
gpg_error_t
get_pubkeys (ctrl_t ctrl,
char *search_terms, int use, int include_unusable, char *source,
pubkey_t *r_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. */
+ * 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;
-
+ char *use_str; /* USE transformed to a string. */
KEYDB_SEARCH_DESC desc;
-
GETKEY_CTX ctx;
pubkey_t results = NULL;
pubkey_t r;
-
int count;
-
char fingerprint[2 * MAX_FINGERPRINT_LEN + 1];
if (DBG_LOOKUP)
search_terms, gpg_strerror (err));
if (!opt.quiet && source)
log_info (_("(check argument of option '%s')\n"), source);
- goto out;
+ goto leave;
}
if (warn_possibly_ambiguous
count = 0;
do
{
- PKT_public_key *pk = xmalloc_clear (sizeof *pk);
+ PKT_public_key *pk;
KBNODE kb;
+
+ pk = xtrycalloc (1, sizeof *pk);
+ if (!pk)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
pk->req_usage = use;
if (! ctx)
else
err = getkey_next (ctrl, ctx, pk, &kb);
- if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
- /* No more results. */
+ if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) /* No more results. */
{
xfree (pk);
break;
}
- else if (err)
- /* An error (other than "not found"). */
+ else if (err) /* An error (other than "not found"). */
{
- log_error (_("error looking up: %s\n"),
- gpg_strerror (err));
+ log_error (_("error looking up: %s\n"), gpg_strerror (err));
xfree (pk);
break;
}
/* Another result! */
count ++;
- r = xmalloc_clear (sizeof (*r));
+ r = xtrycalloc (1, sizeof (*r));
+ if (!r)
+ {
+ err = gpg_error_from_syserror ();
+ xfree (pk);
+ goto leave;
+ }
r->pk = pk;
r->keyblock = kb;
r->next = results;
}
if (! results && gpg_err_code (err) == GPG_ERR_NOT_FOUND)
- /* No match. */
- {
+ { /* No match. */
if (DBG_LOOKUP)
log_debug ("%s: '%s' not found.\n", __func__, search_terms);
if (!opt.quiet && source)
log_info (_("(check argument of option '%s')\n"), source);
- goto out;
+ goto leave;
}
else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
- /* No more matches. */
- ;
+ ; /* No more matches. */
else if (err)
- /* Some other error. An error message was already printed
- out. Free RESULTS and continue. */
- goto out;
+ { /* Some other error. An error message was already printed out.
+ * Free RESULTS and continue. */
+ goto leave;
+ }
/* Check for duplicates. */
if (DBG_LOOKUP)
{
if (cmp_public_keys (r->keyblock->pkt->pkt.public_key,
r2->keyblock->pkt->pkt.public_key) != 0)
- /* Not a dup. */
- {
+ { /* Not a dup. */
prevp = &r2->next;
next = r2->next;
continue;
fingerprint, sizeof fingerprint));
}
- out:
+ leave:
if (err)
pubkeys_free (results);
else
/* More init stuff. */
if (!pk)
{
- pk = xmalloc_clear (sizeof *pk);
internal++;
+ pk = xtrycalloc (1, sizeof *pk);
+ if (!pk)
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
}
if (!rc)
{
/* Key found. */
- log_info (_("automatically retrieved '%s' via %s\n"),
- name, mechanism);
+ if (opt.verbose)
+ log_info (_("automatically retrieved '%s' via %s\n"),
+ name, mechanism);
break;
}
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY
/* Warning: node flag bits 0 and 1 should be preserved by
* merge_selfsigs. FIXME: Check whether this still holds. */
merge_selfsigs (ctrl, keyblock);
- found_key = finish_lookup (keyblock, pk->req_usage, 0, &infoflags);
+ found_key = finish_lookup (keyblock, pk->req_usage, 0, 0, &infoflags);
print_status_key_considered (keyblock, infoflags);
if (found_key)
pk_from_block (pk, keyblock, found_key);
*
* Like get_pubkey_byfprint, PK may be NULL. In that case, this
* function effectively just checks for the existence of the key. */
-int
+gpg_error_t
get_pubkey_byfprint_fast (PKT_public_key * pk,
const byte * fprint, size_t fprint_len)
{
- int rc = 0;
- KEYDB_HANDLE hd;
+ gpg_error_t err;
KBNODE keyblock;
+
+ err = get_keyblock_byfprint_fast (&keyblock, NULL, fprint, fprint_len, 0);
+ if (!err)
+ {
+ if (pk)
+ copy_public_key (pk, keyblock->pkt->pkt.public_key);
+ release_kbnode (keyblock);
+ }
+
+ return err;
+}
+
+
+/* This function is similar to get_pubkey_byfprint_fast but returns a
+ * keydb handle at R_HD and the keyblock at R_KEYBLOCK. R_KEYBLOCK or
+ * R_HD may be NULL. If LOCK is set the handle has been opend in
+ * locked mode and keydb_disable_caching () has been called. On error
+ * R_KEYBLOCK is set to NULL but R_HD must be released by the caller;
+ * it may have a value of NULL, though. This allows to do an insert
+ * operation on a locked keydb handle. */
+gpg_error_t
+get_keyblock_byfprint_fast (kbnode_t *r_keyblock, KEYDB_HANDLE *r_hd,
+ const byte *fprint, size_t fprint_len, int lock)
+{
+ gpg_error_t err;
+ KEYDB_HANDLE hd;
+ kbnode_t keyblock;
byte fprbuf[MAX_FINGERPRINT_LEN];
int i;
+ if (r_keyblock)
+ *r_keyblock = NULL;
+ if (r_hd)
+ *r_hd = NULL;
+
for (i = 0; i < MAX_FINGERPRINT_LEN && i < fprint_len; i++)
fprbuf[i] = fprint[i];
while (i < MAX_FINGERPRINT_LEN)
if (!hd)
return gpg_error_from_syserror ();
- rc = keydb_search_fpr (hd, fprbuf);
- if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
+ if (lock)
{
- keydb_release (hd);
- return GPG_ERR_NO_PUBKEY;
+ err = keydb_lock (hd);
+ if (err)
+ {
+ /* If locking did not work, we better don't return a handle
+ * at all - there was a reason that locking has been
+ * requested. */
+ keydb_release (hd);
+ return err;
+ }
+ keydb_disable_caching (hd);
}
- rc = keydb_get_keyblock (hd, &keyblock);
- keydb_release (hd);
- if (rc)
+
+ /* Fo all other errors we return the handle. */
+ if (r_hd)
+ *r_hd = hd;
+
+ err = keydb_search_fpr (hd, fprbuf);
+ if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
{
- log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc));
- return GPG_ERR_NO_PUBKEY;
+ if (!r_hd)
+ keydb_release (hd);
+ return gpg_error (GPG_ERR_NO_PUBKEY);
+ }
+ err = keydb_get_keyblock (hd, &keyblock);
+ if (err)
+ {
+ log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (err));
+ if (!r_hd)
+ keydb_release (hd);
+ return gpg_error (GPG_ERR_NO_PUBKEY);
}
log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
|| keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY);
- if (pk)
- copy_public_key (pk, keyblock->pkt->pkt.public_key);
- release_kbnode (keyblock);
/* Not caching key here since it won't have all of the fields
properly set. */
+ if (r_keyblock)
+ *r_keyblock = keyblock;
+ else
+ release_kbnode (keyblock);
+
+ if (!r_hd)
+ keydb_release (hd);
+
return 0;
}
+
const char *
parse_def_secret_key (ctrl_t ctrl)
{
*/
static kbnode_t
finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
- unsigned int *r_flags)
+ int want_secret, unsigned int *r_flags)
{
kbnode_t k;
continue;
}
+ if (want_secret && agent_probe_secret_key (NULL, pk))
+ {
+ if (DBG_LOOKUP)
+ log_debug ("\tno secret key\n");
+ continue;
+ }
+
if (DBG_LOOKUP)
log_debug ("\tsubkey might be fine\n");
/* In case a key has a timestamp of 0 set, we make sure
* merge_selfsigs. */
merge_selfsigs (ctrl, keyblock);
found_key = finish_lookup (keyblock, ctx->req_usage, ctx->exact,
- &infoflags);
+ want_secret, &infoflags);
print_status_key_considered (keyblock, infoflags);
if (found_key)
{
/* Returns false on error. */
int
-parse_auto_key_locate (char *options)
+parse_auto_key_locate (const char *options_arg)
{
char *tok;
+ char *options, *options_buf;
+ options = options_buf = xstrdup (options_arg);
while ((tok = optsep (&options)))
{
struct akl *akl, *check, *last = NULL;
else
{
free_akl (akl);
+ xfree (options_buf);
return 0;
}
}
}
+ xfree (options_buf);
return 1;
}