aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <[email protected]>2015-09-16 12:01:48 +0000
committerNeal H. Walfield <[email protected]>2015-09-16 13:15:28 +0000
commitcab581c486e1987445092b1afdf2cba1f62d017d (patch)
tree2e6b05ce4cafca8db8497cd2f19d207a2ef9db3e
parentg10: Remove unused function have_any_secret_key. (diff)
downloadgnupg-cab581c486e1987445092b1afdf2cba1f62d017d.tar.gz
gnupg-cab581c486e1987445092b1afdf2cba1f62d017d.zip
g10: Improve documentation and comments for getkey.c.
* g10/getkey.c: Improve documentation and comments for most functions. Move documentation for public functions from here... * g10/keydb.h: ... to here. -- Signed-off-by: Neal H. Walfield <[email protected]>.
Diffstat (limited to '')
-rw-r--r--g10/getkey.c498
-rw-r--r--g10/keydb.h342
2 files changed, 661 insertions, 179 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index 68e8c1b04..039934420 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -49,12 +49,39 @@
struct getkey_ctx_s
{
+ /* Part of the search criteria: whether the search is an exact
+ search or not. A search that is exact requires that a key or
+ subkey meet all of the specified criteria. A search that is not
+ exact allows selecting a different key or subkey from the
+ keyblock that matched the critera. Further, an exact search
+ returns the key or subkey that matched whereas a non-exact search
+ typically returns the primary key. See finish_lookup for
+ details. */
int exact;
- int want_secret; /* The caller requested only secret keys. */
+
+ /* Part of the search criteria: Whether the caller only wants keys
+ with an available secret key. This is used by getkey_next to get
+ the next result with the same initial criteria. */
+ int want_secret;
+
+ /* Part of the search criteria: The type of the requested key. A
+ mask of PUBKEY_USAGE_SIG, PUBKEY_USAGE_ENC and PUBKEY_USAGE_CERT.
+ If non-zero, then for a key to match, it must implement one of
+ the required uses. */
int req_usage;
+
+ /* The database handle. */
KEYDB_HANDLE kr_handle;
+
+ /* Whether we should call xfree() on the context when the context is
+ released using getkey_end()). */
int not_allocated;
+
+ /* Part of the search criteria: The low-level search specification
+ as passed to keydb_search. */
int nitems;
+ /* This must be the last element in the structure. When we allocate
+ the structure, we allocate it so that ITEMS can hold NITEMS. */
KEYDB_SEARCH_DESC items[1];
};
@@ -124,6 +151,7 @@ print_stats ()
#endif
+/* For documentation see keydb.h. */
void
cache_public_key (PKT_public_key * pk)
{
@@ -207,7 +235,7 @@ user_id_not_found_utf8 (void)
/* Return the user ID from the given keyblock.
* We use the primary uid flag which has been set by the merge_selfsigs
- * function. The returned value is only valid as long as then given
+ * function. The returned value is only valid as long as the given
* keyblock is not changed. */
static const char *
get_primary_uid (KBNODE keyblock, size_t * uidlen)
@@ -311,6 +339,7 @@ cache_user_id (KBNODE keyblock)
}
+/* For documentation see keydb.h. */
void
getkey_disable_caches ()
{
@@ -347,9 +376,8 @@ pk_from_block (GETKEY_CTX ctx, PKT_public_key * pk, KBNODE keyblock,
copy_public_key (pk, a->pkt->pkt.public_key);
}
-/* Get a public key and store it into the allocated pk can be called
- * with PK set to NULL to just read it into some internal
- * structures. */
+
+/* For documentation see keydb.h. */
int
get_pubkey (PKT_public_key * pk, u32 * keyid)
{
@@ -366,6 +394,8 @@ get_pubkey (PKT_public_key * pk, u32 * keyid)
for (ce = pk_cache; ce; ce = ce->next)
{
if (ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1])
+ /* XXX: We don't check PK->REQ_USAGE here, but if we don't
+ read from the cache, we do check it! */
{
copy_public_key (pk, ce->pk);
return 0;
@@ -417,10 +447,7 @@ leave:
}
-/* Get a public key and store it into the allocated pk. This function
- differs from get_pubkey() in that it does not do a check of the key
- to avoid recursion. It should be used only in very certain cases.
- It will only retrieve primary keys. */
+/* For documentation see keydb.h. */
int
get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
{
@@ -485,6 +512,7 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
}
+/* For documentation see keydb.h. */
KBNODE
get_pubkeyblock (u32 * keyid)
{
@@ -507,13 +535,7 @@ get_pubkeyblock (u32 * keyid)
}
-
-
-/*
- * Get a public key and store it into PK. This functions check that a
- * corresponding secret key is available. With no secret key it does
- * not succeeed.
- */
+/* For documentation see keydb.h. */
gpg_error_t
get_seckey (PKT_public_key *pk, u32 *keyid)
{
@@ -546,6 +568,8 @@ get_seckey (PKT_public_key *pk, u32 *keyid)
}
+/* Skip unusable keys. A key is unusable if it is revoked, expired or
+ disabled or if the selected user id is revoked or expired. */
static int
skip_unusable (void *dummy, u32 * keyid, int uid_no)
{
@@ -601,13 +625,48 @@ leave:
}
-/* Try to get the pubkey by the userid. This function looks for the
- * first pubkey certificate which has the given name in a user_id. If
- * PK has the pubkey algo set, the function will only return a pubkey
- * with that algo. If NAMELIST is NULL, the first key is returned.
- * The caller should provide storage for the PK or pass NULL if it is
- * not needed. If RET_KB is not NULL the function stores the entire
- * keyblock at that address. */
+/* Search for keys matching some criteria.
+
+ If RETCTX is not NULL, then the constructed context is returned in
+ *RETCTX so that getpubkey_next can be used to get subsequent
+ results. In this case, getkey_end() must be used to free the
+ search context. If RETCTX is not NULL, then RET_KDBHD must be
+ NULL.
+
+ If NAMELIST is not NULL, then a search query is constructed using
+ classify_user_id on each of the strings in the list. (Recall: the
+ database does an OR of the terms, not an AND.) If NAMELIST is
+ NULL, then all results are returned.
+
+ If PK is not NULL, the public key of the first result is returned
+ in *PK. Note: PK->REQ_USAGE must be valid!!! If PK->REQ_USAGE is
+ set, it is used to filter the search results. See the
+ documentation for finish_lookup to understand exactly how this is
+ used. Note: The self-signed data has already been merged into the
+ public key using merge_selfsigs. Free *PK by calling
+ release_public_key_parts (or, if PK was allocated using xfree, you
+ can use free_public_key, which calls release_public_key_parts(PK)
+ and then xfree(PK)).
+
+ If WANT_SECRET is set, then only keys with an available secret key
+ (either locally or via key registered on a smartcard) are returned.
+
+ If INCLUDE_UNUSABLE is set, then unusable keys (see the
+ documentation for skip_unusable for an exact definition) are
+ skipped unless they are looked up by key id or by fingerprint.
+
+ If RET_KB is not NULL, the keyblock is returned in *RET_KB. This
+ should be freed using release_kbnode().
+
+ If RET_KDBHD is not NULL, then the new database handle used to
+ conduct the search is returned in *RET_KDBHD. This can be used to
+ get subsequent results using keydb_search_next. Note: in this
+ case, no advanced filtering is done for subsequent results (e.g.,
+ WANT_SECRET and PK->REQ_USAGE are not respected).
+
+ This function returns 0 on success. Otherwise, an error code is
+ returned. In particular, GPG_ERR_NO_PUBKEY or GPG_ERR_NO_SECKEY
+ (if want_secret is set) is returned if the key is not found. */
static int
key_byname (GETKEY_CTX *retctx, strlist_t namelist,
PKT_public_key *pk,
@@ -632,6 +691,7 @@ key_byname (GETKEY_CTX *retctx, strlist_t namelist,
*ret_kdbhd = NULL;
if (!namelist)
+ /* No search terms: iterate over the whole DB. */
{
ctx = xmalloc_clear (sizeof *ctx);
ctx->nitems = 1;
@@ -645,6 +705,9 @@ key_byname (GETKEY_CTX *retctx, strlist_t namelist,
for (n = 0, r = namelist; r; r = r->next)
n++;
+ /* CTX has space for a single search term at the end. Thus, we
+ need to allocate sizeof *CTX plus (n - 1) sizeof
+ CTX->ITEMS. */
ctx = xmalloc_clear (sizeof *ctx + (n - 1) * sizeof ctx->items);
ctx->nitems = n;
@@ -705,14 +768,7 @@ key_byname (GETKEY_CTX *retctx, strlist_t namelist,
}
-
-/* Find a public key from NAME and return the keyblock or the key. If
- ret_kdb is not NULL, the KEYDB handle used to locate this keyblock
- is returned and the caller is responsible for closing it. If a key
- was not found (or if local search has been disabled) and NAME is a
- valid RFC822 mailbox and --auto-key-locate has been enabled, we try
- to import the key via the online mechanisms defined by
- --auto-key-locate. */
+/* For documentation see keydb.h. */
int
get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
const char *name, KBNODE * ret_keyblock,
@@ -728,25 +784,38 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
if (retctx)
*retctx = NULL;
+ /* Does NAME appear to be a mailbox (mail address)? */
is_mbox = is_valid_mailbox (name);
- /* Check whether the default local search has been disabled.
- This is the case if either the "nodefault" or the "local" keyword
- are in the list of auto key locate mechanisms.
+ /* The auto-key-locate feature works as follows: there are a number
+ of methods to look up keys. By default, the local keyring is
+ tried first. Then, each method listed in the --auto-key-locate is
+ tried in the order it appears.
+
+ This can be changed as follows:
+
+ - if nodefault appears anywhere in the list of options, then
+ the local keyring is not tried first, or,
- ANYLOCALFIRST is set if the search order has the local method
- before any other or if "local" is used first by default. This
- makes sure that if a RETCTX is used it is only set if a local
- search has precedence over the other search methods and only then
- a followup call to get_pubkey_next shall succeed. */
+ - if local appears anywhere in the list of options, then the
+ local keyring is not tried first, but in the order in which
+ it was listed in the --auto-key-locate option.
+
+ Note: we only save the search context in RETCTX if the local
+ method is the first method tried (either explicitly or
+ implicitly). */
if (!no_akl)
+ /* auto-key-locate is enabled. */
{
+ /* nodefault is true if "nodefault" or "local" appear. */
for (akl = opt.auto_key_locate; akl; akl = akl->next)
if (akl->type == AKL_NODEFAULT || akl->type == AKL_LOCAL)
{
nodefault = 1;
break;
}
+ /* anylocalfirst is true if "local" appears before any other
+ search methods (except "nodefault"). */
for (akl = opt.auto_key_locate; akl; akl = akl->next)
if (akl->type != AKL_NODEFAULT)
{
@@ -757,14 +826,23 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
}
if (!nodefault)
+ /* "nodefault" didn't occur. Thus, "local" is implicitly the
+ first method to try. */
anylocalfirst = 1;
if (nodefault && is_mbox)
+ /* Either "nodefault" or "local" (explicitly) appeared in the auto
+ key locate list and NAME appears to be an email address. Don't
+ try the local keyring. */
{
- /* Nodefault but a mailbox - let the AKL locate the key. */
rc = GPG_ERR_NO_PUBKEY;
}
else
+ /* Either "nodefault" and "local" don't appear in the auto key
+ locate list (in which case we try the local keyring first) or
+ NAME does not appear to be an email address (in which case we
+ only try the local keyring). In this case, lookup NAME in the
+ local keyring. */
{
add_to_strlist (&namelist, name);
rc = key_byname (retctx, namelist, pk, 0,
@@ -774,6 +852,10 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
/* If the requested name resembles a valid mailbox and automatic
retrieval has been enabled, we try to import the key. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && !no_akl && is_mbox)
+ /* NAME wasn't present in the local keyring (or we didn't try the
+ local keyring). Since the auto key locate feature is enabled
+ and NAME appears to be an email address, try the auto locate
+ feature. */
{
for (akl = opt.auto_key_locate; akl; akl = akl->next)
{
@@ -885,6 +967,8 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
add_to_strlist (&namelist, fpr_string);
}
else if (!rc && !fpr && !did_key_byname)
+ /* The acquisition method said no failure occured, but it
+ didn't return a fingerprint. That's a failure. */
{
no_fingerprint = 1;
rc = GPG_ERR_NO_PUBKEY;
@@ -893,6 +977,10 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
fpr = NULL;
if (!rc && !did_key_byname)
+ /* There was no error and we didn't do a local lookup.
+ This means that we imported a key into the local
+ keyring. Try to read the imported key from the
+ keyring. */
{
if (retctx)
{
@@ -930,17 +1018,11 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
}
-/* Search for a key with the given fingerprint. The caller need to
- * prove an allocated public key object at PK. If R_KEYBLOCK is not
- * NULL the entire keyblock is stored there and the caller needs to
- * call release_kbnode() on it. Note that this function does an exact
- * search and thus the public key stored at PK may be a copy of a
- * subkey.
- *
- * FIXME:
- * We should replace this with the _byname function. This can be done
- * by creating a userID conforming to the unified fingerprint style.
- */
+/* For documentation see keydb.h.
+
+ FIXME: We should replace this with the _byname function. This can
+ be done by creating a userID conforming to the unified fingerprint
+ style. */
int
get_pubkey_byfprint (PKT_public_key *pk, kbnode_t *r_keyblock,
const byte * fprint, size_t fprint_len)
@@ -981,11 +1063,7 @@ get_pubkey_byfprint (PKT_public_key *pk, kbnode_t *r_keyblock,
}
-/* Get a public key and store it into the allocated pk. This function
- differs from get_pubkey_byfprint() in that it does not do a check
- of the key to avoid recursion. It should be used only in very
- certain cases. PK may be NULL to check just for the existance of
- the key. */
+/* For documentation see keydb.h. */
int
get_pubkey_byfprint_fast (PKT_public_key * pk,
const byte * fprint, size_t fprint_len)
@@ -1029,9 +1107,7 @@ get_pubkey_byfprint_fast (PKT_public_key * pk,
}
-/* Get a secret key by NAME and store it into PK. If NAME is NULL use
- * the default key. This functions checks that a corresponding secret
- * key is available. With no secret key it does not succeeed. */
+/* For documentation see keydb.h. */
gpg_error_t
get_seckey_default (PKT_public_key *pk)
{
@@ -1051,8 +1127,7 @@ get_seckey_default (PKT_public_key *pk)
return err;
}
-/* The new function to return a key.
- FIXME: Document it. */
+/* For documentation see keydb.h. */
gpg_error_t
getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk,
strlist_t names, int want_secret, kbnode_t *ret_keyblock)
@@ -1062,23 +1137,7 @@ getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk,
}
-/* Get a key by name and store it into PK if that is not NULL. If
- * RETCTX is not NULL return the search context which needs to be
- * released by the caller using getkey_end. If NAME is NULL use the
- * default key (see below). On success and if RET_KEYBLOCK is not
- * NULL the found keyblock is stored at this address. WANT_SECRET
- * passed as true requires that a secret key is available for the
- * selected key.
- *
- * If WANT_SECRET is true and NAME is NULL and a default key has been
- * defined that defined key is used. In all other cases the first
- * available key is used.
- *
- * FIXME: Explain what is up with unusable keys.
- *
- * FIXME: We also have the get_pubkey_byname function which has a
- * different semantic. Should be merged with this one.
- */
+/* For documentation see keydb.h. */
gpg_error_t
getkey_byname (getkey_ctx_t *retctx, PKT_public_key *pk,
const char *name, int want_secret, kbnode_t *ret_keyblock)
@@ -1106,7 +1165,7 @@ getkey_byname (getkey_ctx_t *retctx, PKT_public_key *pk,
}
-/* The new function to return the next key. */
+/* For documentation see keydb.h. */
gpg_error_t
getkey_next (getkey_ctx_t ctx, PKT_public_key *pk, kbnode_t *ret_keyblock)
{
@@ -1115,8 +1174,8 @@ getkey_next (getkey_ctx_t ctx, PKT_public_key *pk, kbnode_t *ret_keyblock)
/* We need to disable the caching so that for an exact key search we
won't get the result back from the cache and thus end up in an
- endless loop. Disabling this here is sufficient because although
- the result has been cached, if won't be used then. */
+ endless loop. The endless loop can occur, because the cache is
+ used without respecting the current file pointer! */
keydb_disable_caching (ctx->kr_handle);
rc = lookup (ctx, ret_keyblock, &found_key, ctx->want_secret);
@@ -1127,7 +1186,7 @@ getkey_next (getkey_ctx_t ctx, PKT_public_key *pk, kbnode_t *ret_keyblock)
}
-/* The new function to finish a key listing. */
+/* For documentation see keydb.h. */
void
getkey_end (getkey_ctx_t ctx)
{
@@ -1145,10 +1204,7 @@ getkey_end (getkey_ctx_t ctx)
************* Merging stuff ********************
************************************************/
-/* Set the mainkey_id fields for all keys in KEYBLOCK. This is
- usually done by merge_selfsigs but at some places we only need the
- main_kid but the the full merging. The function also guarantees
- that all pk->keyids are computed. */
+/* For documentation see keydb.h. */
void
setup_main_keyids (kbnode_t keyblock)
{
@@ -1177,7 +1233,7 @@ setup_main_keyids (kbnode_t keyblock)
}
-/* Merge all self-signatures with the keys. */
+/* For documentation see keydb.h. */
void
merge_keys_and_selfsig (KBNODE keyblock)
{
@@ -1252,7 +1308,7 @@ parse_key_usage (PKT_signature * sig)
/* Apply information from SIGNODE (which is the valid self-signature
* associated with that UID) to the UIDNODE:
- * - wether the UID has been revoked
+ * - weather the UID has been revoked
* - assumed creation date of the UID
* - temporary store the keyflags here
* - temporary store the key expiration time here
@@ -1377,7 +1433,33 @@ sig_to_revoke_info (PKT_signature * sig, struct revoke_info *rinfo)
}
-/* Note that R_REVOKED may be set to 0, 1 or 2. */
+/* Given a keyblock, parse the key block and extract various pieces of
+ information and save them with the primary key packet and the user
+ id packets. For instance, some information is stored in signature
+ packets. We find the latest such valid packet (since the user can
+ change that information) and copy its contents into the
+ PKT_public_key.
+
+ Note that R_REVOKED may be set to 0, 1 or 2.
+
+ This function fills in the following fields in the primary key's
+ keyblock:
+
+ main_keyid (computed)
+ revkey / numrevkeys (derived from self signed key data)
+ flags.valid (whether we have at least 1 self-sig)
+ flags.maybe_revoked (whether a designed revoked the key, but
+ we are missing the key to check the sig)
+ selfsigversion (highest version of any valid self-sig)
+ pubkey_usage (derived from most recent self-sig or most
+ recent user id)
+ has_expired (various sources)
+ expiredate (various sources)
+
+ See the documentation for fixup_uidnode for how the user id packets
+ are modified. In addition to that the primary user id's is_primary
+ field is set to 1 and the other user id's is_primary are set to
+ 0. */
static void
merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
struct revoke_info *rinfo)
@@ -1397,7 +1479,18 @@ merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
*r_revoked = 0;
memset (rinfo, 0, sizeof (*rinfo));
+ /* Section 11.1 of RFC 4880 determines the order of packets within a
+ message. There are three sections, which must occur in the
+ following order: the public key, the user ids and user attributes
+ and the subkeys. Within each section, each primary packet (e.g.,
+ a user id packet) is followed by one or more signature packets,
+ which modify that packet. */
+
+ /* According to Section 11.1 of RFC 4880, the public key must be the
+ first packet. */
if (keyblock->pkt->pkttype != PKT_PUBLIC_KEY)
+ /* parse_keyblock_image ensures that the first packet is the
+ public key. */
BUG ();
pk = keyblock->pkt->pkt.public_key;
keytimestamp = pk->timestamp;
@@ -1415,10 +1508,20 @@ merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
key_expire_seen = 1;
}
- /* First pass: Find the latest direct key self-signature. We assume
- * that the newest one overrides all others. */
+ /* First pass:
+
+ - Find the latest direct key self-signature. We assume that the
+ newest one overrides all others.
- /* In case this key was already merged. */
+ - Determine whether the key has been revoked.
+
+ - Gather all revocation keys (unlike other data, we don't just
+ take them from the latest self-signed packet).
+
+ - Determine max (sig[...]->version).
+ */
+
+ /* Reset this in case this key was already merged. */
xfree (pk->revkey);
pk->revkey = NULL;
pk->numrevkeys = 0;
@@ -1431,6 +1534,7 @@ merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
{
PKT_signature *sig = k->pkt->pkt.signature;
if (sig->keyid[0] == kid[0] && sig->keyid[1] == kid[1])
+ /* Self sig. */
{
if (check_key_signature (keyblock, k, NULL))
; /* Signature did not verify. */
@@ -1450,13 +1554,12 @@ merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
}
else if (IS_KEY_SIG (sig))
{
- /* Add any revocation keys onto the pk. This is
- particularly interesting since we normally only
- get data from the most recent 1F signature, but
- you need multiple 1F sigs to properly handle
- revocation keys (PGP does it this way, and a
- revocation key could be sensitive and hence in a
- different signature). */
+ /* Add the indicated revocations keys from all
+ signatures not just the latest. We do this
+ because you need multiple 1F sigs to properly
+ handle revocation keys (PGP does it this way, and
+ a revocation key could be sensitive and hence in
+ a different signature). */
if (sig->revkey)
{
int i;
@@ -1472,6 +1575,7 @@ merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
}
if (sig->timestamp >= sigdate)
+ /* This is the latest signature so far. */
{
if (sig->flags.expired)
; /* Signature has expired - ignore it. */
@@ -1490,7 +1594,6 @@ merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
}
/* Remove dupes from the revocation keys. */
-
if (pk->revkey)
{
int i, j, x, changed = 0;
@@ -1521,6 +1624,8 @@ merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
}
if (signode)
+ /* SIGNODE is the 1F signature packet with the latest creation
+ time. Extract some information from it. */
{
/* Some information from a direct key signature take precedence
* over the same information given in UID sigs. */
@@ -1588,6 +1693,8 @@ merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
if (k->pkt->pkttype == PKT_USER_ID)
{
if (uidnode && signode)
+ /* Apply the data from the most recent self-signed packet
+ to the preceding user id packet. */
{
fixup_uidnode (uidnode, signode, keytimestamp);
pk->flags.valid = 1;
@@ -1608,7 +1715,7 @@ merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
{
/* Note: we allow to invalidate cert revocations
* by a newer signature. An attacker can't use this
- * because a key should be revoced with a key revocation.
+ * because a key should be revoked with a key revocation.
* The reason why we have to allow for that is that at
* one time an email address may become invalid but later
* the same email address may become valid again (hired,
@@ -1664,7 +1771,7 @@ merge_selfsigs_main (KBNODE keyblock, int *r_revoked,
avoid infinite recursion in certain cases.
There is no reason to check that an ultimately
trusted key is still valid - if it has been
- revoked or the user should also renmove the
+ revoked the user should also remove the
ultimate trust flag. */
if (get_pubkey_fast (ultimate_pk, sig->keyid) == 0
&& check_key_signature2 (keyblock, k, ultimate_pk,
@@ -1885,6 +1992,25 @@ buf_to_sig (const byte * buf, size_t len)
return sig;
}
+/* Use the self-signed data to fill in various fields in subkeys.
+
+ KEYBLOCK is the whole keyblock. SUBNODE is the subkey to fill in.
+
+ Sets the following fields on the subkey:
+
+ main_keyid
+ flags.valid if the subkey has a valid self-sig binding
+ flags.revoked
+ flags.backsig
+ pubkey_usage
+ has_expired
+ expired_date
+
+ On this subkey's most revent valid self-signed packet, the
+ following field is set:
+
+ flags.chosen_selfsig
+ */
static void
merge_selfsigs_subkey (KBNODE keyblock, KBNODE subnode)
{
@@ -2070,18 +2196,11 @@ merge_selfsigs_subkey (KBNODE keyblock, KBNODE subnode)
}
-/*
- * Merge information from the self-signatures with the key, so that
- * we can later use them more easy.
- * The function works by first applying the self signatures to the
- * primary key and the to each subkey.
- * Here are the rules we use to decide which inormation from which
- * self-signature is used:
- * We check all self signatures or validity and ignore all invalid signatures.
- * All signatures are then ordered by their creation date ....
- * For the primary key:
- * FIXME the docs
- */
+/* Merge information from the self-signatures with the public key,
+ subkeys and user ids to make using them more easy.
+
+ See documentation for merge_selfsigs_main, merge_selfsigs_subkey
+ and fixup_uidnode for exactly which fields are updated. */
static void
merge_selfsigs (KBNODE keyblock)
{
@@ -2180,50 +2299,75 @@ merge_selfsigs (KBNODE keyblock)
-/* See whether the key fits our requirements and in case we do not
- * request the primary key, select a suitable subkey.
- *
- * Returns: True when a suitable key has been found.
- *
- * We have to distinguish four cases: FIXME!
- * 1. No usage and no primary key requested
- * Examples for this case are that we have a keyID to be used
- * for decrytion or verification.
- * 2. No usage but primary key requested
- * This is the case for all functions which work on an
- * entire keyblock, e.g. for editing or listing
- * 3. Usage and primary key requested
- * FXME
- * 4. Usage but no primary key requested
- * FIXME
- * FIXME: Tell what is going to happen here and something about the rationale
- * Note: We don't use this function if no specific usage is requested;
- * This way the getkey functions can be used for plain key listings.
- *
- * CTX ist the keyblock we are investigating, if FOUNDK is not NULL this
- * is the key we actually found by looking at the keyid or a fingerprint and
- * may either point to the primary or one of the subkeys. */
+/* See whether the key satisfies any additional requirements specified
+ in CTX. If so, return 1 and set CTX->FOUND_KEY to an appropriate
+ key or subkey. Otherwise, return 0 if there was no appropriate
+ key.
+
+ In case the primary key is not required, select a suitable subkey.
+ We need the primary key if PUBKEY_USAGE_CERT is set in
+ CTX->REQ_USAGE or we are in PGP6 or PGP7 mode and PUBKEY_USAGE_SIG
+ is set in CTX->REQ_USAGE.
+
+ If any of PUBKEY_USAGE_SIG, PUBKEY_USAGE_ENC and PUBKEY_USAGE_CERT
+ are set in CTX->REQ_USAGE, we filter by the key's function.
+ Concretely, if PUBKEY_USAGE_SIG and PUBKEY_USAGE_CERT are set, then
+ we only return a key if it is (at least) either a signing or a
+ certification key.
+
+ If CTX->REQ_USAGE is set, then we reject any keys that are not good
+ (i.e., valid, not revoked, not expired, etc.). This allows the
+ getkey functions to be used for plain key listings.
+
+ Sets the matched key's user id field (pk->user_id) to the user id
+ that matched the low-level search criteria or NULL.
+
+
+ This function needs to handle several different cases:
+
+ 1. No requested usage and no primary key requested
+ Examples for this case are that we have a keyID to be used
+ for decrytion or verification.
+ 2. No usage but primary key requested
+ This is the case for all functions which work on an
+ entire keyblock, e.g. for editing or listing
+ 3. Usage and primary key requested
+ FXME
+ 4. Usage but no primary key requested
+ FIXME
+
+ */
static KBNODE
finish_lookup (GETKEY_CTX ctx, KBNODE keyblock)
{
KBNODE k;
+
+ /* If CTX->EXACT is set, the key or subkey that actually matched the
+ low-level search criteria. */
KBNODE foundk = NULL;
+ /* The user id (if any) that matched the low-level search criteria. */
PKT_user_id *foundu = NULL;
+
#define USAGE_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC|PUBKEY_USAGE_CERT)
unsigned int req_usage = (ctx->req_usage & USAGE_MASK);
+
/* Request the primary if we're certifying another key, and also
if signing data while --pgp6 or --pgp7 is on since pgp 6 and 7
do not understand signatures made by a signing subkey. PGP 8
does. */
int req_prim = (ctx->req_usage & PUBKEY_USAGE_CERT) ||
((PGP6 || PGP7) && (ctx->req_usage & PUBKEY_USAGE_SIG));
+
+ u32 curtime = make_timestamp ();
+
u32 latest_date;
KBNODE latest_key;
- u32 curtime = make_timestamp ();
assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
if (ctx->exact)
+ /* Get the key or subkey that matched the low-level search
+ criteria. */
{
for (k = keyblock; k; k = k->next)
{
@@ -2237,6 +2381,7 @@ finish_lookup (GETKEY_CTX ctx, KBNODE keyblock)
}
}
+ /* Get the user id that matched that low-level search criteria. */
for (k = keyblock; k; k = k->next)
{
if ((k->flag & 2))
@@ -2420,9 +2565,22 @@ search_modes_are_fingerprint (getkey_ctx_t ctx)
}
-/* The main function to lookup a key. On success the found keyblock
- is stored at RET_KEYBLOCK and also in CTX. If WANT_SECRET is true
- a corresponding secret key is required. */
+/* A high-level function to lookup keys.
+
+ This function builds on top of the low-level keydb API. It first
+ searches the database using the description stored in CTX->ITEMS,
+ then it filters the results using CTX and, finally, if WANT_SECRET
+ is set, it ignores any keys for which no secret key is available.
+
+ Note: this function skips any legacy keys unless the search mode is
+ KEYDB_SEARCH_MODE_FIRST or KEYDB_SEARCH_MODE_NEXT or we are
+ searching by fingerprint.
+
+ Unlike the low-level search functions, this function also merges
+ all of the self-signed data into the keys, subkeys and user id
+ packets (see the merge_selfsigs for details).
+
+ On success the key's keyblock is stored at *RET_KEYBLOCK. */
static int
lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, kbnode_t *ret_found_key,
int want_secret)
@@ -2435,8 +2593,10 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, kbnode_t *ret_found_key,
for (;;)
{
rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems, NULL);
- /* Skip over all legacy keys but only if they are not requested
- by fingerprints.
+
+ /* Skip over all legacy keys unless we are iterating over all
+ keys in the DB or the key was requested by its fingerprint.
+
Fixme: The lower level keydb code should actually do that but
then it would be harder to report the number of skipped
legacy keys during import. */
@@ -2448,9 +2608,10 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, kbnode_t *ret_found_key,
if (rc)
break;
- /* If we are searching for the first key we have to make sure
- that the next iteration does not do an implicit reset.
- This can be triggered by an empty key ring. */
+ /* If we are iterating over the entire database, then we need to
+ change from KEYDB_SEARCH_MODE_FIRST, which does an implicit
+ reset, to KEYDB_SEARCH_MODE_NEXT, which gets the next
+ record. */
if (ctx->nitems && ctx->items->mode == KEYDB_SEARCH_MODE_FIRST)
ctx->items->mode = KEYDB_SEARCH_MODE_NEXT;
@@ -2482,11 +2643,11 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, kbnode_t *ret_found_key,
/* Release resources and continue search. */
release_kbnode (keyblock);
keyblock = NULL;
- /* We need to disable the caching so that for an exact key
- search we won't get the result back from the cache and thus
- end up in an endless loop. Disabling the cache here at this
- point is sufficient because even a cached result won't be
- used after a call to keydb_disable_caching. */
+ /* The keyblock cache ignores the current "file position".
+ Thus, if we request the next result and the cache matches
+ (and it will since it is what we just looked for), we'll get
+ the same entry back! We can avoid this infinite loop by
+ disabling the cache. */
keydb_disable_caching (ctx->kr_handle);
}
@@ -2520,18 +2681,7 @@ found:
}
-
-
-/*
- * Enumerate certain secret keys. Caller must use these procedure:
- * 1) create a void pointer and initialize it to NULL
- * 2) pass this void pointer by reference to this function
- * and provide space for the secret key (pass a buffer for sk)
- * 3) call this function as long as it does not return an error.
- * The error code GPG_ERR_EOF indicates the end of the listing.
- * 4) Always call this function a last time with SK set to NULL,
- * so that can free it's context.
- */
+/* For documentation see keydb.h. */
gpg_error_t
enum_secret_keys (void **context, PKT_public_key *sk)
{
@@ -2652,7 +2802,7 @@ get_user_id_string (u32 * keyid, int mode, size_t *r_len)
int pass = 0;
char *p;
- /* Try it two times; second pass reads from key resources. */
+ /* Try it two times; second pass reads from the database. */
do
{
for (r = user_id_db; r; r = r->next)
@@ -2741,8 +2891,11 @@ get_user_id_native (u32 * keyid)
}
-/* Return a user id from the caching by looking it up using the FPR
- which must be of size MAX_FINGERPRINT_LEN. */
+/* Return the user id for a key designated by its fingerprint, FPR,
+ which must be MAX_FINGERPRINT_LEN bytes in size. Note: the
+ returned string, which must be freed using xfree, may not be NUL
+ terminated. To determine the length of the string, you must use
+ *RN. */
char *
get_user_id_byfpr (const byte *fpr, size_t *rn)
{
@@ -2750,7 +2903,7 @@ get_user_id_byfpr (const byte *fpr, size_t *rn)
char *p;
int pass = 0;
- /* Try it two times; second pass reads from key resources. */
+ /* Try it two times; second pass reads from the database. */
do
{
for (r = user_id_db; r; r = r->next)
@@ -2778,6 +2931,9 @@ get_user_id_byfpr (const byte *fpr, size_t *rn)
return p;
}
+/* Like get_user_id_byfpr, but convert the string to the native
+ encoding. The returned string needs to be freed. Unlike
+ get_user_id_byfpr, the returned string is NUL terminated. */
char *
get_user_id_byfpr_native (const byte *fpr)
{
@@ -2790,6 +2946,7 @@ get_user_id_byfpr_native (const byte *fpr)
+/* For documentation see keydb.h. */
KEYDB_HANDLE
get_ctx_handle (GETKEY_CTX ctx)
{
@@ -2893,12 +3050,7 @@ parse_auto_key_locate (char *options)
}
-
-
-/* Return true if a secret key is available for the public key with
- * the given KEYID. This is just a fast check and does not tell us
- * whether the secret key is valid. It merely tells os whether there
- * is some secret key. */
+/* For documentation see keydb.h. */
int
have_secret_key_with_kid (u32 *keyid)
{
diff --git a/g10/keydb.h b/g10/keydb.h
index 67af5fbeb..680af1c61 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -70,7 +70,7 @@ enum resource_type {
/****************
- * A data structre to hold information about the external position
+ * A data structure to hold information about the external position
* of a keyblock.
*/
struct keyblock_pos_struct {
@@ -398,50 +398,380 @@ char *gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped);
/*-- getkey.c --*/
+
+/* Cache a copy of a public key in the public key cache. PK is not
+ cached if caching is disabled (via getkey_disable_caches), if
+ PK->FLAGS.DONT_CACHE is set, we don't know how to derive a key id
+ from the public key (e.g., unsupported algorithm), or a key with
+ the key id is already in the cache.
+
+ The public key packet is copied into the cache using
+ copy_public_key. Thus, any secret parts are not copied, for
+ instance.
+
+ This cache is filled by get_pubkey and is read by get_pubkey and
+ get_pubkey_fast. */
void cache_public_key( PKT_public_key *pk );
+
+/* Disable and drop the public key cache (which is filled by
+ cache_public_key and get_pubkey). Note: there is currently no way
+ to reenable this cache. */
void getkey_disable_caches(void);
+
+/* Return the public key with the key id KEYID and store it in *PK.
+ The resources in *PK should be released using
+ release_public_key_parts(). This function also stores a copy of
+ the public key in the user id cache (see cache_public_key).
+
+ If PK is NULL, this function just stores the public key in the
+ cache and returns the usual return code.
+
+ PK->REQ_USAGE (which is a mask of PUBKEY_USAGE_SIG,
+ PUBKEY_USAGE_ENC and PUBKEY_USAGE_CERT) is passed through to the
+ lookup function. If this is non-zero, only keys with the specified
+ usage will be returned. As such, it is essential that
+ PK->REQ_USAGE be correctly initialized!
+
+ Returns 0 on success, GPG_ERR_NO_PUBKEY if there is no public key
+ with the specified key id, or another error code if an error
+ occurs.
+
+ If the data was not read from the cache, then the self-signed data
+ has definately been merged into the public key using
+ merge_selfsigs. */
int get_pubkey( PKT_public_key *pk, u32 *keyid );
+
+/* Similar to get_pubkey, but it does not take PK->REQ_USAGE into
+ account nor does it merge in the self-signed data. This function
+ also only considers primary keys. It is intended to be used as a
+ quick check of the key to avoid recursion. It should only be used
+ in very certain cases. Like get_pubkey and unlike any of the other
+ lookup functions, this function also consults the user id cache
+ (see cache_public_key).
+
+ Return the public key in *PK. The resources in *PK should be
+ released using release_public_key_parts(). */
int get_pubkey_fast ( PKT_public_key *pk, u32 *keyid );
+
+/* Return the key block for the key with key id KEYID or NULL, if an
+ error occurs. Use release_kbnode() to release the key block.
+
+ The self-signed data has already been merged into the public key
+ using merge_selfsigs. */
KBNODE get_pubkeyblock( u32 *keyid );
+
+/* Find a public key identified by the name NAME.
+
+ If name appears to be a valid valid RFC822 mailbox (i.e., email
+ address) and auto key lookup is enabled (no_akl == 0), then the
+ specified auto key lookup methods (--auto-key-lookup) are used to
+ import the key into the local keyring. Otherwise, just the local
+ keyring is consulted.
+
+
+ If RETCTX is not NULL, then the constructed context is returned in
+ *RETCTX so that getpubkey_next can be used to get subsequent
+ results. In this case, getkey_end() must be used to free the
+ search context. If RETCTX is not NULL, then RET_KDBHD must be
+ NULL.
+
+ If PK is not NULL, the public key of the first result is returned
+ in *PK. Note: PK->REQ_USAGE must be valid!!! PK->REQ_USAGE is
+ passed through to the lookup function and is a mask of
+ PUBKEY_USAGE_SIG, PUBKEY_USAGE_ENC and PUBKEY_USAGE_CERT. If this
+ is non-zero, only keys with the specified usage will be returned.
+ Note: The self-signed data has already been merged into the public
+ key using merge_selfsigs. Free *PK by calling
+ release_public_key_parts (or, if PK was allocated using xfree, you
+ can use free_public_key, which calls release_public_key_parts(PK)
+ and then xfree(PK)).
+
+ NAME is a string, which is turned into a search query using
+ classify_user_id.
+
+ If RET_KEYBLOCK is not NULL, the keyblock is returned in
+ *RET_KEYBLOCK. This should be freed using release_kbnode().
+
+ If RET_KDBHD is not NULL, then the new database handle used to
+ conduct the search is returned in *RET_KDBHD. This can be used to
+ get subsequent results using keydb_search_next or to modify the
+ returned record. Note: in this case, no advanced filtering is done
+ for subsequent results (e.g., PK->REQ_USAGE is not respected).
+ Unlike RETCTX, this is always returned.
+
+ If INCLUDE_UNUSABLE is set, then unusable keys (see the
+ documentation for skip_unusable for an exact definition) are
+ skipped unless they are looked up by key id or by fingerprint.
+
+ If NO_AKL is set, then the auto key locate functionality is
+ disabled and only the local key ring is considered. Note: the
+ local key ring is consulted even if local is not in the
+ --auto-key-locate option list!
+
+ This function returns 0 on success. Otherwise, an error code is
+ returned. In particular, GPG_ERR_NO_PUBKEY or GPG_ERR_NO_SECKEY
+ (if want_secret is set) is returned if the key is not found. */
int get_pubkey_byname (ctrl_t ctrl,
- GETKEY_CTX *rx, PKT_public_key *pk, const char *name,
+ GETKEY_CTX *retctx, PKT_public_key *pk,
+ const char *name,
KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd,
int include_unusable, int no_akl );
+
+/* Return the public key with the key id KEYID and store it in *PK.
+ The resources should be released using release_public_key_parts().
+
+ Unlike other lookup functions, PK may not be NULL. PK->REQ_USAGE
+ is passed through to the lookup function and is a mask of
+ PUBKEY_USAGE_SIG, PUBKEY_USAGE_ENC and PUBKEY_USAGE_CERT. Thus, it
+ must be valid! If this is non-zero, only keys with the specified
+ usage will be returned.
+
+ Returns 0 on success. If a public key with the specified key id is
+ not found or a secret key is not available for that public key, an
+ error code is returned. Note: this function ignores legacy keys.
+ An error code is also return if an error occurs.
+
+ The self-signed data has already been merged into the public key
+ using merge_selfsigs. */
gpg_error_t get_seckey (PKT_public_key *pk, u32 *keyid);
+
+/* Lookup a key with the specified fingerprint.
+
+ If PK is not NULL, the public key of the first result is returned
+ in *PK. Note: this function does an exact search and thus the
+ returned public key may be a subkey rather than the primary key.
+ Note: The self-signed data has already been merged into the public
+ key using merge_selfsigs. Free *PK by calling
+ release_public_key_parts (or, if PK was allocated using xfree, you
+ can use free_public_key, which calls release_public_key_parts(PK)
+ and then xfree(PK)).
+
+ If PK->REQ_USAGE is set, it is used to filter the search results.
+ (Thus, if PK is not NULL, PK->REQ_USAGE must be valid!!!) See the
+ documentation for finish_lookup to understand exactly how this is
+ used.
+
+ If R_KEYBLOCK is not NULL, then the first result's keyblock is
+ returned in *R_KEYBLOCK. This should be freed using
+ release_kbnode().
+
+ FPRINT is a byte array whose contents is the fingerprint to use as
+ the search term. FPRINT_LEN specifies the length of the
+ fingerprint (in bytes). Currently, only 16 and 20-byte
+ fingerprints are supported. */
int get_pubkey_byfprint (PKT_public_key *pk, kbnode_t *r_keyblock,
const byte *fprint, size_t fprint_len);
+
+/* This function is similar to get_pubkey_byfprint, but it doesn't
+ merge the self-signed data into the public key and subkeys or into
+ the user ids. It also doesn't add the key to the user id cache.
+ Further, this function ignores PK->REQ_USAGE.
+
+ This function is intended to avoid recursion and, as such, should
+ only be used in very specific situations.
+
+ Like get_pubkey_byfprint, PK may be NULL. In that case, this
+ function effectively just checks for the existence of the key. */
int get_pubkey_byfprint_fast (PKT_public_key *pk,
const byte *fprint, size_t fprint_len);
/* Return whether a secret key is available for the public key with
- key id KEYID. Note: this is just a fast check and does not tell us
- whether the secret key is valid; this check merely indicates
- whether there is some secret key with the specified key id. */
+ key id KEYID. This function ignores legacy keys. Note: this is
+ just a fast check and does not tell us whether the secret key is
+ valid; this check merely indicates whether there is some secret key
+ with the specified key id. */
int have_secret_key_with_kid (u32 *keyid);
+/* Look up a secret key.
+
+ If PK is not NULL, the public key of the first result is returned
+ in *PK. Note: PK->REQ_USAGE must be valid!!! If PK->REQ_USAGE is
+ set, it is used to filter the search results. See the
+ documentation for finish_lookup to understand exactly how this is
+ used. Note: The self-signed data has already been merged into the
+ public key using merge_selfsigs. Free *PK by calling
+ release_public_key_parts (or, if PK was allocated using xfree, you
+ can use free_public_key, which calls release_public_key_parts(PK)
+ and then xfree(PK)).
+
+ If --default-key was set, then the specified key is looked up. (In
+ this case, the default key is returned even if it is considered
+ unusable. See the documentation for skip_unusable for exactly what
+ this means.)
+
+ Otherwise, this initiates a DB scan that returns all keys that are
+ usable (see previous paragraph for exactly what usable means) and
+ for which a secret key is available.
+
+ This function returns the first match. Additional results can be
+ returned using getkey_next. */
gpg_error_t get_seckey_default (PKT_public_key *pk);
+/* Search for keys matching some criteria.
+
+ If RETCTX is not NULL, then the constructed context is returned in
+ *RETCTX so that getpubkey_next can be used to get subsequent
+ results. In this case, getkey_end() must be used to free the
+ search context. If RETCTX is not NULL, then RET_KDBHD must be
+ NULL.
+
+ If PK is not NULL, the public key of the first result is returned
+ in *PK. Note: PK->REQ_USAGE must be valid!!! If PK->REQ_USAGE is
+ set, it is used to filter the search results. See the
+ documentation for finish_lookup to understand exactly how this is
+ used. Note: The self-signed data has already been merged into the
+ public key using merge_selfsigs. Free *PK by calling
+ release_public_key_parts (or, if PK was allocated using xfree, you
+ can use free_public_key, which calls release_public_key_parts(PK)
+ and then xfree(PK)).
+
+ If NAMES is not NULL, then a search query is constructed using
+ classify_user_id on each of the strings in the list. (Recall: the
+ database does an OR of the terms, not an AND.) If NAMES is
+ NULL, then all results are returned.
+
+ If WANT_SECRET is set, then only keys with an available secret key
+ (either locally or via key registered on a smartcard) are returned.
+
+ This function does not skip unusable keys (see the documentation
+ for skip_unusable for an exact definition).
+
+ If RET_KEYBLOCK is not NULL, the keyblock is returned in
+ *RET_KEYBLOCK. This should be freed using release_kbnode().
+
+ This function returns 0 on success. Otherwise, an error code is
+ returned. In particular, GPG_ERR_NO_PUBKEY or GPG_ERR_NO_SECKEY
+ (if want_secret is set) is returned if the key is not found. */
gpg_error_t getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk,
strlist_t names, int want_secret,
kbnode_t *ret_keyblock);
+
+/* Search for keys matching some criteria.
+
+ If RETCTX is not NULL, then the constructed context is returned in
+ *RETCTX so that getpubkey_next can be used to get subsequent
+ results. In this case, getkey_end() must be used to free the
+ search context. If RETCTX is not NULL, then RET_KDBHD must be
+ NULL.
+
+ If PK is not NULL, the public key of the first result is returned
+ in *PK. Note: PK->REQ_USAGE must be valid!!! If PK->REQ_USAGE is
+ set, it is used to filter the search results. See the
+ documentation for finish_lookup to understand exactly how this is
+ used. Note: The self-signed data has already been merged into the
+ public key using merge_selfsigs. Free *PK by calling
+ release_public_key_parts (or, if PK was allocated using xfree, you
+ can use free_public_key, which calls release_public_key_parts(PK)
+ and then xfree(PK)).
+
+ If NAME is not NULL, then a search query is constructed using
+ classify_user_id on the string. In this case, even unusable keys
+ (see the documentation for skip_unusable for an exact definition of
+ unusable) are returned. Otherwise, if --default-key was set, then
+ that key is returned (even if it is unusable). If neither of these
+ conditions holds, then the first usable key is returned.
+
+ If WANT_SECRET is set, then only keys with an available secret key
+ (either locally or via key registered on a smartcard) are returned.
+
+ This function does not skip unusable keys (see the documentation
+ for skip_unusable for an exact definition).
+
+ If RET_KEYBLOCK is not NULL, the keyblock is returned in
+ *RET_KEYBLOCK. This should be freed using release_kbnode().
+
+ This function returns 0 on success. Otherwise, an error code is
+ returned. In particular, GPG_ERR_NO_PUBKEY or GPG_ERR_NO_SECKEY
+ (if want_secret is set) is returned if the key is not found.
+
+ FIXME: We also have the get_pubkey_byname function which has a
+ different semantic. Should be merged with this one. */
gpg_error_t getkey_byname (getkey_ctx_t *retctx, PKT_public_key *pk,
const char *name, int want_secret,
kbnode_t *ret_keyblock);
+
+/* Return the next search result.
+
+ If PK is not NULL, the public key of the next result is returned in
+ *PK. Note: The self-signed data has already been merged into the
+ public key using merge_selfsigs. Free *PK by calling
+ release_public_key_parts (or, if PK was allocated using xfree, you
+ can use free_public_key, which calls release_public_key_parts(PK)
+ and then xfree(PK)).
+
+ The self-signed data has already been merged into the public key
+ using merge_selfsigs. */
gpg_error_t getkey_next (getkey_ctx_t ctx, PKT_public_key *pk,
kbnode_t *ret_keyblock);
+
+/* Release any resources used by a key listing content. This must be
+ called on the context returned by, e.g., getkey_byname. */
void getkey_end (getkey_ctx_t ctx);
+/* Return the database handle used by this context. The context still
+ owns the handle. */
+KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx);
+
+/* Enumerate some secret keys (specifically, those specified with
+ --default-key and --try-secret-key). Use the following procedure:
+
+ 1) Initialize a void pointer to NULL
+ 2) Pass a reference to this pointer to this function (content)
+ and provide space for the secret key (sk)
+ 3) Call this function as long as it does not return an error (or
+ until you are done). The error code GPG_ERR_EOF indicates the
+ end of the listing.
+ 4) Call this function a last time with SK set to NULL,
+ so that can free it's context.
+
+ In pseudo-code:
+
+ void *ctx = NULL;
+ PKT_public_key *sk = xmalloc_clear (sizeof (*sk));
+ gpg_error_t err;
+
+ while ((err = enum_secret_keys (&ctx, sk)))
+ {
+ // Process SK.
+
+ if (done)
+ break;
+
+ free_public_key (sk);
+ sk = xmalloc_clear (sizeof (*sk));
+ }
+
+ // Release any resources used by CTX.
+ enum_secret_keys (&ctx, NULL);
+ free_public_key (sk);
+
+ if (gpg_err_code (err) != GPG_ERR_EOF)
+ ; // An error occured.
+ */
gpg_error_t enum_secret_keys (void **context, PKT_public_key *pk);
+/* Set the mainkey_id fields for all keys in KEYBLOCK. This is
+ usually done by merge_selfsigs but at some places we only need the
+ main_kid not a full merge. The function also guarantees that all
+ pk->keyids are computed. */
void setup_main_keyids (kbnode_t keyblock);
+
+/* KEYBLOCK corresponds to a public key block. This function merges
+ much of the information from the self-signed data into the public
+ key, public subkey and user id data structures. If you use the
+ high-level search API (e.g., get_pubkey) for looking up key blocks,
+ then you don't need to call this function. This function is
+ useful, however, if you change the keyblock, e.g., by adding or
+ removing a self-signed data packet. */
void merge_keys_and_selfsig( KBNODE keyblock );
+
char*get_user_id_string_native( u32 *keyid );
char*get_long_user_id_string( u32 *keyid );
char*get_user_id( u32 *keyid, size_t *rn );
char*get_user_id_native( u32 *keyid );
char *get_user_id_byfpr (const byte *fpr, size_t *rn);
char *get_user_id_byfpr_native (const byte *fpr);
-KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx);
+
void release_akl(void);
int parse_auto_key_locate(char *options);