diff options
author | Neal H. Walfield <[email protected]> | 2015-08-31 09:14:21 +0000 |
---|---|---|
committer | Neal H. Walfield <[email protected]> | 2015-08-31 09:30:56 +0000 |
commit | 360b699e9b4b8f99bd790b3cd158cd6f0fd7c131 (patch) | |
tree | 3f8761ce469c6a0545678cb3318ba6e2f30c66b3 | |
parent | g10: Don't cache search results if the search didn't scan the whole DB. (diff) | |
download | gnupg-360b699e9b4b8f99bd790b3cd158cd6f0fd7c131.tar.gz gnupg-360b699e9b4b8f99bd790b3cd158cd6f0fd7c131.zip |
g10: Improve interface documentation of the keydb API.
* g10/keydb.c: Improve code comments and documentation of internal
interfaces. Improve documentation of public APIs and move that to...
* g10/keydb.h: ... this file.
--
Signed-off-by: Neal H. Walfield <[email protected]>.
Diffstat (limited to '')
-rw-r--r-- | g10/keydb.c | 105 | ||||
-rw-r--r-- | g10/keydb.h | 187 |
2 files changed, 223 insertions, 69 deletions
diff --git a/g10/keydb.c b/g10/keydb.c index eeefd2aa8..423205dbc 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -64,18 +64,37 @@ static void *primary_keyring=NULL; struct keydb_handle { + /* When we locked all of the resources in ACTIVE (using keyring_lock + / keybox_lock, as appropriate). */ int locked; + + /* The index into ACTIVE of the resources in which the last search + result was found. Initially -1. */ int found; + + /* Initially -1 (invalid). This is used to save a search result and + later restore it as the selected result. */ int saved_found; + + /* The number of skipped long blobs since the last search + (keydb_search_reset). */ unsigned long skipped_long_blobs; + + /* If set, this disables the use of the keyblock cache. */ int no_caching; /* Whether the next search will be from the beginning of the database (and thus consider all records). */ int is_reset; + /* The "file position." In our case, this is index of the current + resource in ACTIVE. */ int current; - int used; /* Number of items in ACTIVE. */ + + /* The number of resources in ACTIVE. */ + int used; + + /* Copy of ALL_RESOURCES when keydb_new is called. */ struct resource_item active[MAX_KEYDB_RESOURCES]; }; @@ -187,7 +206,7 @@ kid_not_found_insert (u32 *kid) } -/* Flush kid found cache. */ +/* Flush the kid not found cache. */ static void kid_not_found_flush (void) { @@ -229,7 +248,9 @@ keyblock_cache_clear (void) keyring/keybox already locked. This lock check does not work if the directory itself is not yet available. If IS_BOX is true the filename is expected to refer to a keybox. If FORCE_CREATE is true - the keyring or keybox will be created. */ + the keyring or keybox will be created. + + Return 0 if it is okay to access the specified file. */ static int maybe_create_keyring_or_box (char *filename, int is_box, int force_create) { @@ -392,10 +413,15 @@ maybe_create_keyring_or_box (char *filename, int is_box, int force_create) } -/* Helper for keydb_add_resource. Opens FILENAME to figures out the - resource type. Returns the resource type and a flag at R_NOTFOUND - indicating whether FILENAME could be opened at all. If the openpgp - flag is set in a keybox header, R_OPENPGP will be set to true. */ +/* Helper for keydb_add_resource. Opens FILENAME to figure out the + resource type. + + Returns the specified file's likely type. If the file does not + exist, returns KEYDB_RESOURCE_TYPE_NONE and sets *R_FOUND to 0. + Otherwise, tries to figure out the file's type. This is either + KEYDB_RESOURCE_TYPE_KEYBOX, KEYDB_RESOURCE_TYPE_KEYRING or + KEYDB_RESOURCE_TYPE_KEYNONE. If the file is a keybox and it has + the OpenPGP flag set, then R_OPENPGP is also set. */ static KeydbResourceType rt_from_file (const char *filename, int *r_found, int *r_openpgp) { @@ -436,17 +462,14 @@ rt_from_file (const char *filename, int *r_found, int *r_openpgp) } -/* - * Register a resource (keyring or aeybox). The first keyring or - * keybox which is added by this function is created if it does not - * exist. FLAGS are a combination of the KEYDB_RESOURCE_FLAG_ - * constants as defined in keydb.h. - */ gpg_error_t keydb_add_resource (const char *url, unsigned int flags) { + /* Whether we have successfully registered a resource. */ static int any_registered; + /* The file named by the URL (i.e., without the prototype). */ const char *resname = url; + char *filename = NULL; int create; int read_only = !!(flags&KEYDB_RESOURCE_FLAG_READONLY); @@ -459,11 +482,6 @@ keydb_add_resource (const char *url, unsigned int flags) /* Create the resource if it is the first registered one. */ create = (!read_only && !any_registered); - /* Do we have an URL? - * gnupg-ring:filename := this is a plain keyring. - * gnupg-kbx:filename := this is a keybox file. - * filename := See what is is, but create as plain keyring. - */ if (strlen (resname) > 11 && !strncmp( resname, "gnupg-ring:", 11) ) { rt = KEYDB_RESOURCE_TYPE_KEYRING; @@ -750,9 +768,6 @@ keydb_release (KEYDB_HANDLE hd) } -/* Set a flag on handle to not use cached results. This is required - for updating a keyring and for key listins. Fixme: Using a new - parameter for keydb_new might be a better solution. */ void keydb_disable_caching (KEYDB_HANDLE hd) { @@ -761,14 +776,6 @@ keydb_disable_caching (KEYDB_HANDLE hd) } -/* - * Return the name of the current resource. This is function first - * looks for the last found found, then for the current search - * position, and last returns the first available resource. The - * returned string is only valid as long as the handle exists. This - * function does only return NULL if no handle is specified, in all - * other error cases an empty string is returned. - */ const char * keydb_get_resource_name (KEYDB_HANDLE hd) { @@ -882,7 +889,6 @@ unlock_all (KEYDB_HANDLE hd) -/* Push the last found state if any. */ void keydb_push_found_state (KEYDB_HANDLE hd) { @@ -912,7 +918,6 @@ keydb_push_found_state (KEYDB_HANDLE hd) } -/* Pop the last found state. */ void keydb_pop_found_state (KEYDB_HANDLE hd) { @@ -1103,12 +1108,6 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no, } -/* - * Return the last found keyring. Caller must free it. - * The returned keyblock has the kbode flag bit 0 set for the node with - * the public key used to locate the keyblock or flag bit 1 set for - * the user ID node. - */ gpg_error_t keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb) { @@ -1279,9 +1278,6 @@ build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf, u32 **r_sigstatus) } -/* - * Update the current keyblock with the keyblock KB - */ gpg_error_t keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb) { @@ -1332,9 +1328,6 @@ keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb) } -/* - * Insert a new KB into one of the resources. - */ gpg_error_t keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb) { @@ -1396,9 +1389,6 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb) } -/* - * Delete the current keyblock. - */ gpg_error_t keydb_delete_keyblock (KEYDB_HANDLE hd) { @@ -1439,11 +1429,6 @@ keydb_delete_keyblock (KEYDB_HANDLE hd) -/* - * Locate the default writable key resource, so that the next - * operation (which is only relevant for inserts) will be done on this - * resource. - */ gpg_error_t keydb_locate_writable (KEYDB_HANDLE hd) { @@ -1496,9 +1481,6 @@ keydb_locate_writable (KEYDB_HANDLE hd) return gpg_error (GPG_ERR_NOT_FOUND); } -/* - * Rebuild the caches of all key resources. - */ void keydb_rebuild_caches (int noisy) { @@ -1528,7 +1510,6 @@ keydb_rebuild_caches (int noisy) } -/* Return the number of skipped blocks since the last search reset. */ unsigned long keydb_get_skipped_counter (KEYDB_HANDLE hd) { @@ -1536,9 +1517,6 @@ keydb_get_skipped_counter (KEYDB_HANDLE hd) } -/* - * Start the next search on this handle right at the beginning - */ gpg_error_t keydb_search_reset (KEYDB_HANDLE hd) { @@ -1626,18 +1604,13 @@ dump_search_desc (KEYDB_HANDLE hd, const char *text, } -/* - * Search through all keydb resources, starting at the current - * position, for a keyblock which contains one of the keys described - * in the DESC array. Returns GPG_ERR_NOT_FOUND if no matching - * keyring was found. - */ gpg_error_t keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc, size_t *descindex) { gpg_error_t rc; int was_reset = hd->is_reset; + /* If an entry is already in the cache, then don't add it again. */ int already_in_cache = 0; if (descindex) @@ -1732,8 +1705,6 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, } -/* Note that in contrast to using keydb_search in search first mode, - this function skips legacy keys. */ gpg_error_t keydb_search_first (KEYDB_HANDLE hd) { @@ -1753,8 +1724,6 @@ keydb_search_first (KEYDB_HANDLE hd) } -/* Note that in contrast to using keydb_search in search next mode, - this fucntion skips legacy keys. */ gpg_error_t keydb_search_next (KEYDB_HANDLE hd) { diff --git a/g10/keydb.h b/g10/keydb.h index 10864509c..a943ded88 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -1,6 +1,7 @@ /* keydb.h - Key database * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, * 2006, 2010 Free Software Foundation, Inc. + * Copyright (C) 2015 g10 Code GmbH * * This file is part of GnuPG. * @@ -132,28 +133,212 @@ union pref_hint #define KEYDB_RESOURCE_FLAG_READONLY 8 /* Open in read only mode. */ #define KEYDB_RESOURCE_FLAG_GPGVDEF 16 /* Default file for gpgv. */ +/* Register a resource (keyring or keybox). The first keyring or + keybox that is added using this function is created if it does not + already exist and the KEYDB_RESOURCE_FLAG_READONLY is not set. + + FLAGS are a combination of the KEYDB_RESOURCE_FLAG_* constants. + + URL must have the following form: + + gnupg-ring:filename = plain keyring + gnupg-kbx:filename = keybox file + filename = check file's type (create as a plain keyring) + + Note: on systems with drive letters (Windows) invalid URLs (i.e., + those with an unrecognized part before the ':' such as "c:\...") + will silently be treated as bare filenames. On other systems, such + URLs will cause this function to return GPG_ERR_GENERAL. + + If KEYDB_RESOURCE_FLAG_DEFAULT is set, the resource is a keyring + and the file ends in ".gpg", then this function also checks if a + file with the same name, but the extension ".kbx" exists, is a + keybox and the OpenPGP flag is set. If so, this function opens + that resource instead. + + If the file is not found, KEYDB_RESOURCE_FLAG_GPGVDEF is set and + the URL ends in ".kbx", then this function will try opening the + same URL, but with the extension ".gpg". If that file is a keybox + with the OpenPGP flag set or it is a keyring, then we use that + instead. + + If the file is not found, KEYDB_RESOURCE_FLAG_DEFAULT is set, the + file should be created and the file's extension is ".gpg" then we + replace the extension with ".kbx". + + + If the KEYDB_RESOURCE_FLAG_PRIMARY is set and the resource is a + keyring (not a keybox), then this resource is considered the + primary resource. This is used by keydb_locate_writable(). If + another primary keyring is set, then that keyring is considered the + primary. + + If KEYDB_RESOURCE_FLAG_READONLY is set and the resource is a + keyring (not a keybox), then the keyring is marked as read only and + operations just as keyring_insert_keyblock will return + GPG_ERR_ACCESS. */ gpg_error_t keydb_add_resource (const char *url, unsigned int flags); -void keydb_dump_stats (void); +/* Dump some statistics to the log. */ +void keydb_dump_stats (void); + +/* Create a new database handle. A database handle is similar to a + file handle: it contains a local file position. This is used when + searching: subsequent searches resume where the previous search + left off. To rewind the position, use keydb_search_reset(). */ KEYDB_HANDLE keydb_new (void); + +/* Free all resources owned by the database handle. */ void keydb_release (KEYDB_HANDLE hd); + +/* Set a flag on the handle to suppress use of cached results. This + is required for updating a keyring and for key listings. Fixme: + Using a new parameter for keydb_new might be a better solution. */ void keydb_disable_caching (KEYDB_HANDLE hd); + +/* Save the last found state and invalidate the current selection + (i.e., the entry selected by keydb_search() is invalidated and + something like keydb_get_keyblock() will return an error). This + does not change the file position. This makes it possible to do + something like: + + keydb_search (hd, ...); // Result 1. + keydb_push_found_state (hd); + keydb_search_reset (hd); + keydb_search (hd, ...); // Result 2. + keydb_pop_found_state (hd); + keydb_get_keyblock (hd, ...); // -> Result 1. + + Note: it is only possible to save a single save state at a time. + In other words, the the save stack only has room for a single + instance of the state. */ void keydb_push_found_state (KEYDB_HANDLE hd); + +/* Restore the previous save state. If the saved state is invalid, + this is equivalent to */ void keydb_pop_found_state (KEYDB_HANDLE hd); + +/* Return the file name of the resource in which the current search + result was found or, if there is no search result, the filename of + the current resource (i.e., the resource that the file position + points to). Note: the filename is not necessarily the URL used to + open it! + + This function only returns NULL if no handle is specified, in all + other error cases an empty string is returned. */ const char *keydb_get_resource_name (KEYDB_HANDLE hd); + +/* Return the keyblock last found by keydb_search() in *RET_KB. + + On success, the function returns 0 and the caller must free *RET_KB + using release_kbnode(). Otherwise, the function returns an error + code. + + The returned keyblock has the kbnode flag bit 0 set for the node + with the public key used to locate the keyblock or flag bit 1 set + for the user ID node. */ gpg_error_t keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb); + +/* Replace the currently selected keyblock (i.e., the last result + returned by keydb_search) with the key block in KB. + + This doesn't do anything if --dry-run was specified. + + Returns 0 on success. Otherwise, it returns an error code. */ gpg_error_t keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb); + +/* Insert a keyblock into one of the underlying keyrings or keyboxes. + + Be default, the keyring / keybox from which the last search result + came is used. If there was no previous search result (or + keydb_search_reset was called), then the keyring / keybox where the + next search would start is used (i.e., the current file position). + + Note: this doesn't do anything if --dry-run was specified. + + Returns 0 on success. Otherwise, it returns an error code. */ gpg_error_t keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb); + +/* Delete the currently selected keyblock. If you haven't done a + search yet on this database handle (or called keydb_search_reset), + then this will return an error. + + Returns 0 on success or an error code, if an error occurs. */ gpg_error_t keydb_delete_keyblock (KEYDB_HANDLE hd); + +/* A database may consists of multiple keyrings / key boxes. This + sets the "file position" to the start of the first keyring / key + box that is writable (i.e., doesn't have the read-only flag set). + + This first tries the primary keyring (the last keyring (not + keybox!) added using keydb_add_resource() and with + KEYDB_RESOURCE_FLAG_PRIMARY set). If that is not writable, then it + tries the keyrings / keyboxes in the order in which they were + added. */ gpg_error_t keydb_locate_writable (KEYDB_HANDLE hd); + +/* Rebuild the on-disk caches of all key resources. */ void keydb_rebuild_caches (int noisy); + +/* Return the number of skipped blocks (because they were to large to + read from a keybox) since the last search reset. */ unsigned long keydb_get_skipped_counter (KEYDB_HANDLE hd); + +/* Clears the current search result and resets the handle's position + so that the next search starts at the beginning of the database + (the start of the first resource). + + Returns 0 on success and an error code if an error occured. + (Currently, this function always returns 0 if HD is valid.) */ gpg_error_t keydb_search_reset (KEYDB_HANDLE hd); + +/* Search the database for keys matching the search description. + + DESC is an array of search terms with NDESC entries. The search + terms are or'd together. That is, the next entry in the DB that + matches any of the descriptions will be returned. + + Note: this function resumes searching where the last search left + off (i.e., at the current file position). If you want to search + from the start of the database, then you need to first call + keydb_search_reset(). + + If no key matches the search description, returns + GPG_ERR_NOT_FOUND. If there was a match, returns 0. If an error + occured, returns an error code. + + The returned key is considered to be selected and the raw data can, + for instance, be returned by calling keydb_get_keyblock(). */ gpg_error_t keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc, size_t *descindex); + +/* Return the first non-legacy key in the database. + + If you want the very first key in the database, you can directly + call keydb_search with the search description + KEYDB_SEARCH_MODE_FIRST. */ gpg_error_t keydb_search_first (KEYDB_HANDLE hd); + +/* Return the next key (not the next matching key!). + + Unlike calling keydb_search with KEYDB_SEARCH_MODE_NEXT, this + function silently skips legacy keys. */ gpg_error_t keydb_search_next (KEYDB_HANDLE hd); + +/* This is a convenience function for searching for keys with a long + key id. + + Note: this function resumes searching where the last search left + off. If you want to search the whole database, then you need to + first call keydb_search_reset(). */ gpg_error_t keydb_search_kid (KEYDB_HANDLE hd, u32 *kid); + +/* This is a convenience function for searching for keys with a long + (20 byte) fingerprint. This function ignores legacy keys. + + Note: this function resumes searching where the last search left + off. If you want to search the whole database, then you need to + first call keydb_search_reset(). */ gpg_error_t keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr); |