gpg: New option --use-keyboxd.

* g10/gpg.c (oUseKeyboxd,oKeyboxdProgram): New consts.
(opts): New options --use-keyboxd and --keyboxd-program.
(main): Implement them.
* g10/keydb.c: Move some defs out to ...
* g10/keydb-private.h: new file.
* g10/keydb.c: prefix function names with "internal" and move original
functions to ...
* g10/call-keyboxd.c: new file.  Divert to the internal fucntion if
--use-keyboxd is used.  Add a CTRL arg to most fucntions and change
all callers.
* g10/Makefile.am (common_source): Add new files.
(noinst_PROGRAMS): Do bot build gpgcompose.
--

Note that this is just the framework with only a basic implementation
of searching via keyboxd.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-09-09 14:34:09 +02:00
parent 5e00c1773d
commit aba82684fe
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
26 changed files with 1221 additions and 292 deletions

View File

@ -50,9 +50,9 @@ noinst_PROGRAMS = gpg
if !HAVE_W32CE_SYSTEM
noinst_PROGRAMS += gpgv
endif
if MAINTAINER_MODE
noinst_PROGRAMS += gpgcompose
endif
#if MAINTAINER_MODE
#noinst_PROGRAMS += gpgcompose
#endif
noinst_PROGRAMS += $(module_tests)
TESTS = $(module_tests)
TESTS_ENVIRONMENT = \
@ -99,7 +99,10 @@ common_source = \
filter.h \
free-packet.c \
getkey.c \
keydb.c keydb.h \
keydb.h \
keydb-private.h \
call-keyboxd.c \
keydb.c \
keyring.c keyring.h \
seskey.c \
kbnode.c \
@ -160,7 +163,7 @@ gpg_SOURCES = gpg.c \
keyedit.c keyedit.h \
$(gpg_sources)
gpgcompose_SOURCES = gpgcompose.c $(gpg_sources)
#gpgcompose_SOURCES = gpgcompose.c $(gpg_sources)
gpgv_SOURCES = gpgv.c \
$(common_source) \
verify.c
@ -179,29 +182,32 @@ gpg_LDADD = $(LDADD) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \
$(LIBICONV) $(resource_objs) $(extra_sys_libs)
gpg_LDFLAGS = $(extra_bin_ldflags)
gpgv_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
$(GPG_ERROR_LIBS) \
$(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
$(LIBICONV) $(resource_objs) $(extra_sys_libs)
gpgv_LDFLAGS = $(extra_bin_ldflags)
gpgcompose_LDADD = $(LDADD) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \
$(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
$(LIBICONV) $(resource_objs) $(extra_sys_libs)
gpgcompose_LDFLAGS = $(extra_bin_ldflags)
#gpgcompose_LDADD = $(LDADD) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \
# $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
# $(LIBICONV) $(resource_objs) $(extra_sys_libs)
#gpgcompose_LDFLAGS = $(extra_bin_ldflags)
t_common_ldadd =
module_tests = t-rmd160 t-keydb t-keydb-get-keyblock t-stutter
t_rmd160_SOURCES = t-rmd160.c rmd160.c
t_rmd160_LDADD = $(t_common_ldadd)
t_keydb_SOURCES = t-keydb.c test-stubs.c $(common_source)
t_keydb_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
t_keydb_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
$(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
$(LIBICONV) $(t_common_ldadd)
t_keydb_get_keyblock_SOURCES = t-keydb-get-keyblock.c test-stubs.c \
$(common_source)
t_keydb_get_keyblock_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
t_keydb_get_keyblock_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
$(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
$(LIBICONV) $(t_common_ldadd)
t_stutter_SOURCES = t-stutter.c test-stubs.c \
$(common_source)
t_stutter_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
t_stutter_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
$(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
$(LIBICONV) $(t_common_ldadd)

842
g10/call-keyboxd.c Normal file
View File

@ -0,0 +1,842 @@
/* call-keyboxd.c - Access to the keyboxd storage server
* Copyright (C) 2019 g10 Code GmbH
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
#include "gpg.h"
#include <assuan.h>
#include "../common/util.h"
#include "../common/membuf.h"
#include "options.h"
#include "../common/i18n.h"
#include "../common/asshelp.h"
#include "../common/status.h"
#include "keydb.h"
#include "keydb-private.h" /* For struct keydb_handle_s */
/* Data used to keep track of keybox daemon sessions. This allows us
* to use several sessions with the keyboxd and also to re-use already
* established sessions. Note that gpg.h defines the type
* keyboxd_local_t for this structure. */
struct keyboxd_local_s
{
/* Link to other keyboxd contexts which are used simultaneously. */
struct keyboxd_local_s *next;
/* The active Assuan context. */
assuan_context_t ctx;
/* This flag set while an operation is running on this context. */
unsigned int is_active : 1;
/* This flag is set to record that the standard per session init has
* been done. */
unsigned int per_session_init_done : 1;
};
/* Deinitialize all session resources pertaining to the keyboxd. */
void
gpg_keyboxd_deinit_session_data (ctrl_t ctrl)
{
keyboxd_local_t kbl;
while ((kbl = ctrl->keyboxd_local))
{
ctrl->keyboxd_local = kbl->next;
if (kbl->is_active)
log_error ("oops: trying to cleanup an active keyboxd context\n");
else
assuan_release (kbl->ctx);
xfree (kbl);
}
}
/* Print a warning if the server's version number is less than our
version number. Returns an error code on a connection problem. */
static gpg_error_t
warn_version_mismatch (assuan_context_t ctx, const char *servername)
{
gpg_error_t err;
char *serverversion;
const char *myversion = strusage (13);
err = get_assuan_server_version (ctx, 0, &serverversion);
if (err)
log_error (_("error getting version from '%s': %s\n"),
servername, gpg_strerror (err));
else if (compare_version_strings (serverversion, myversion) < 0)
{
char *warn;
warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"),
servername, serverversion, myversion);
if (!warn)
err = gpg_error_from_syserror ();
else
{
log_info (_("WARNING: %s\n"), warn);
if (!opt.quiet)
{
log_info (_("Note: Outdated servers may lack important"
" security fixes.\n"));
log_info (_("Note: Use the command \"%s\" to restart them.\n"),
"gpgconf --kill all");
}
write_status_strings (STATUS_WARNING, "server_version_mismatch 0",
" ", warn, NULL);
xfree (warn);
}
}
xfree (serverversion);
return err;
}
/* Connect to the keybox daemon and launch it if necessary. Handle
* the server's initial greeting and set global options. Returns a
* new assuan context or an error. */
static gpg_error_t
create_new_context (ctrl_t ctrl, assuan_context_t *r_ctx)
{
gpg_error_t err;
assuan_context_t ctx;
*r_ctx = NULL;
err = start_new_keyboxd (&ctx,
GPG_ERR_SOURCE_DEFAULT,
opt.keyboxd_program,
opt.autostart, opt.verbose, DBG_IPC,
NULL, ctrl);
if (!opt.autostart && gpg_err_code (err) == GPG_ERR_NO_KEYBOXD)
{
static int shown;
if (!shown)
{
shown = 1;
log_info (_("no keyboxd running in this session\n"));
}
}
else if (!err && !(err = warn_version_mismatch (ctx, KEYBOXD_NAME)))
{
/* Place to emit global options. */
}
if (err)
assuan_release (ctx);
else
*r_ctx = ctx;
return err;
}
/* Get a context for accessing keyboxd. If no context is available a
* new one is created and if necessary keyboxd is started. On success
* an assuan context is stored at R_CTX. This context may only be
* released by means of close_context. Note that NULL is stored at
* R_CTX on error. */
static gpg_error_t
open_context (ctrl_t ctrl, assuan_context_t *r_ctx)
{
gpg_error_t err;
keyboxd_local_t kbl;
*r_ctx = NULL;
for (;;)
{
for (kbl = ctrl->keyboxd_local; kbl && kbl->is_active; kbl = kbl->next)
;
if (kbl)
{
/* Found an inactive keyboxd session - return that. */
log_assert (!kbl->is_active);
/* But first do the per session init if not yet done. */
if (!kbl->per_session_init_done)
{
kbl->per_session_init_done = 1;
}
kbl->is_active = 1;
*r_ctx = kbl->ctx;
return 0;
}
/* None found. Create a new session and retry. */
kbl = xtrycalloc (1, sizeof *kbl);
if (!kbl)
return gpg_error_from_syserror ();
err = create_new_context (ctrl, &kbl->ctx);
if (err)
{
xfree (kbl);
return err;
}
/* Although we are not yet using nPth in gpg we better prepare
* to be nPth thread safe. Thus we add it to the list and
* retry; this is easier than to employ a lock. */
kbl->next = ctrl->keyboxd_local;
ctrl->keyboxd_local = kbl;
}
}
/* Close the assuan context CTX and return it to a pool of unused
* contexts. If CTX is NULL, the function does nothing. */
static void
close_context (ctrl_t ctrl, assuan_context_t ctx)
{
keyboxd_local_t kbl;
if (!ctx)
return;
for (kbl = ctrl->keyboxd_local; kbl; kbl = kbl->next)
{
if (kbl->ctx == ctx)
{
if (!kbl->is_active)
log_fatal ("closing inactive keyboxd context %p\n", ctx);
kbl->is_active = 0;
return;
}
}
log_fatal ("closing unknown keyboxd ctx %p\n", ctx);
}
/* 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(). This
* function returns NULL on error, sets ERRNO, and prints an error
* diagnostic. Depending on --use-keyboxd either the old internal
* keydb code is used (keydb.c) or, if set, the processing is diverted
* to the keyboxd. */
/* FIXME: We should change the interface to return a gpg_error_t. */
KEYDB_HANDLE
keydb_new (ctrl_t ctrl)
{
gpg_error_t err;
KEYDB_HANDLE hd;
if (DBG_CLOCK)
log_clock ("keydb_new");
hd = xtrycalloc (1, sizeof *hd);
if (!hd)
{
err = gpg_error_from_syserror ();
goto leave;
}
if (!opt.use_keyboxd)
{
err = internal_keydb_init (hd);
goto leave;
}
hd->use_keyboxd = 1;
hd->ctrl = ctrl;
hd->need_search_reset = 1;
err = open_context (ctrl, &hd->assuan_context);
if (err)
goto leave;
leave:
if (err)
{
int rc;
log_error (_("error opening key DB: %s\n"), gpg_strerror (err));
xfree (hd);
hd = NULL;
if (!(rc = gpg_err_code_to_errno (err)))
rc = gpg_err_code_to_errno (GPG_ERR_EIO);
gpg_err_set_errno (rc);
}
return hd;
}
/* Release a keydb handle. */
void
keydb_release (KEYDB_HANDLE hd)
{
if (!hd)
return;
if (!hd->use_keyboxd)
internal_keydb_deinit (hd);
else
{
close_context (hd->ctrl, hd->assuan_context);
}
xfree (hd);
}
/* Take a lock if we are not using the keyboxd. */
gpg_error_t
keydb_lock (KEYDB_HANDLE hd)
{
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if (!hd->use_keyboxd)
return internal_keydb_lock (hd);
return 0;
}
/* FIXME: This helper is duplicates code of partse_keyblock_image. */
static gpg_error_t
keydb_get_keyblock_do_parse (iobuf_t iobuf, int pk_no, int uid_no,
kbnode_t *r_keyblock)
{
gpg_error_t err;
struct parse_packet_ctx_s parsectx;
PACKET *pkt;
kbnode_t keyblock = NULL;
kbnode_t node, *tail;
int in_cert, save_mode;
int pk_count, uid_count;
*r_keyblock = NULL;
pkt = xtrymalloc (sizeof *pkt);
if (!pkt)
return gpg_error_from_syserror ();
init_packet (pkt);
init_parse_packet (&parsectx, iobuf);
save_mode = set_packet_list_mode (0);
in_cert = 0;
tail = NULL;
pk_count = uid_count = 0;
while ((err = parse_packet (&parsectx, pkt)) != -1)
{
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_PACKET)
{
free_packet (pkt, &parsectx);
init_packet (pkt);
continue;
}
if (err)
{
es_fflush (es_stdout);
log_error ("parse_keyblock_image: read error: %s\n",
gpg_strerror (err));
if (gpg_err_code (err) == GPG_ERR_INV_PACKET)
{
free_packet (pkt, &parsectx);
init_packet (pkt);
continue;
}
err = gpg_error (GPG_ERR_INV_KEYRING);
break;
}
/* Filter allowed packets. */
switch (pkt->pkttype)
{
case PKT_PUBLIC_KEY:
case PKT_PUBLIC_SUBKEY:
case PKT_SECRET_KEY:
case PKT_SECRET_SUBKEY:
case PKT_USER_ID:
case PKT_ATTRIBUTE:
case PKT_SIGNATURE:
case PKT_RING_TRUST:
break; /* Allowed per RFC. */
default:
log_info ("skipped packet of type %d in keybox\n", (int)pkt->pkttype);
free_packet(pkt, &parsectx);
init_packet(pkt);
continue;
}
/* Other sanity checks. */
if (!in_cert && pkt->pkttype != PKT_PUBLIC_KEY)
{
log_error ("parse_keyblock_image: first packet in a keybox blob "
"is not a public key packet\n");
err = gpg_error (GPG_ERR_INV_KEYRING);
break;
}
if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
|| pkt->pkttype == PKT_SECRET_KEY))
{
log_error ("parse_keyblock_image: "
"multiple keyblocks in a keybox blob\n");
err = gpg_error (GPG_ERR_INV_KEYRING);
break;
}
in_cert = 1;
node = new_kbnode (pkt);
switch (pkt->pkttype)
{
case PKT_PUBLIC_KEY:
case PKT_PUBLIC_SUBKEY:
case PKT_SECRET_KEY:
case PKT_SECRET_SUBKEY:
if (++pk_count == pk_no)
node->flag |= 1;
break;
case PKT_USER_ID:
if (++uid_count == uid_no)
node->flag |= 2;
break;
default:
break;
}
if (!keyblock)
keyblock = node;
else
*tail = node;
tail = &node->next;
pkt = xtrymalloc (sizeof *pkt);
if (!pkt)
{
err = gpg_error_from_syserror ();
break;
}
init_packet (pkt);
}
set_packet_list_mode (save_mode);
if (err == -1 && keyblock)
err = 0; /* Got the entire keyblock. */
if (err)
release_kbnode (keyblock);
else
{
*r_keyblock = keyblock;
}
free_packet (pkt, &parsectx);
deinit_parse_packet (&parsectx);
xfree (pkt);
return err;
}
/* 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_t *ret_kb)
{
gpg_error_t err;
int pk_no, uid_no;
*ret_kb = NULL;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if (DBG_CLOCK)
log_clock ("%s enter", __func__);
if (!hd->use_keyboxd)
{
err = internal_keydb_get_keyblock (hd, ret_kb);
goto leave;
}
if (!hd->search_result)
{
err = gpg_error (GPG_ERR_VALUE_NOT_FOUND);
goto leave;
}
pk_no = uid_no = 0; /*FIXME: Get this from the keyboxd. */
err = keydb_get_keyblock_do_parse (hd->search_result, pk_no, uid_no, ret_kb);
/* In contrast to the old code we close the iobuf here and thus this
* function may be called only once to get a keyblock. */
iobuf_close (hd->search_result);
hd->search_result = NULL;
leave:
if (DBG_CLOCK)
log_clock ("%s leave%s", __func__, err? " (failed)":"");
return err;
}
/* Update the keyblock KB (i.e., extract the fingerprint and find the
* corresponding keyblock in the keyring).
*
* This doesn't do anything if --dry-run was specified.
*
* Returns 0 on success. Otherwise, it returns an error code. Note:
* if there isn't a keyblock in the keyring corresponding to KB, then
* this function returns GPG_ERR_VALUE_NOT_FOUND.
*
* This function selects the matching record and modifies the current
* file position to point to the record just after the selected entry.
* Thus, if you do a subsequent search using HD, you should first do a
* keydb_search_reset. Further, if the selected record is important,
* you should use keydb_push_found_state and keydb_pop_found_state to
* save and restore it. */
gpg_error_t
keydb_update_keyblock (ctrl_t ctrl, KEYDB_HANDLE hd, kbnode_t kb)
{
gpg_error_t err;
log_assert (kb);
log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if (!hd->use_keyboxd)
{
err = internal_keydb_update_keyblock (ctrl, hd, kb);
goto leave;
}
err = GPG_ERR_NOT_IMPLEMENTED;
leave:
return err;
}
/* 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)
{
gpg_error_t err;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if (!hd->use_keyboxd)
{
err = internal_keydb_insert_keyblock (hd, kb);
goto leave;
}
err = GPG_ERR_NOT_IMPLEMENTED;
leave:
return err;
}
/* Delete the currently selected keyblock. If you haven't done a
* search yet on this database handle (or called keydb_search_reset),
* then this function returns an error.
*
* Returns 0 on success or an error code, if an error occured. */
gpg_error_t
keydb_delete_keyblock (KEYDB_HANDLE hd)
{
gpg_error_t err;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if (!hd->use_keyboxd)
{
err = internal_keydb_delete_keyblock (hd);
goto leave;
}
err = GPG_ERR_NOT_IMPLEMENTED;
leave:
return err;
}
/* Clears the current search result and resets the handle's position
* so that the next search starts at the beginning of the database.
*
* Returns 0 on success and an error code if an error occurred. */
gpg_error_t
keydb_search_reset (KEYDB_HANDLE hd)
{
gpg_error_t err;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if (DBG_CLOCK)
log_clock ("%s", __func__);
if (DBG_CACHE)
log_debug ("%s (hd=%p)", __func__, hd);
if (!hd->use_keyboxd)
{
err = internal_keydb_search_reset (hd);
goto leave;
}
/* All we need todo is to tell search that a reset is pending. Noet
* that keydb_new sets this flag as well. */
hd->need_search_reset = 1;
err = 0;
leave:
return err;
}
/* Search the database for keys matching the search description. If
* the DB contains any legacy keys, these are silently ignored.
*
* 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
* occurred, 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)
{
gpg_error_t err;
int i;
char line[ASSUAN_LINELENGTH];
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if (descindex)
*descindex = 0; /* Make sure it is always set on return. */
if (DBG_CLOCK)
log_clock ("%s enter", __func__);
if (DBG_LOOKUP)
{
log_debug ("%s: %zd search descriptions:\n", __func__, ndesc);
for (i = 0; i < ndesc; i ++)
{
char *t = keydb_search_desc_dump (&desc[i]);
log_debug ("%s %d: %s\n", __func__, i, t);
xfree (t);
}
}
if (!hd->use_keyboxd)
{
err = internal_keydb_search (hd, desc, ndesc, descindex);
goto leave;
}
if (hd->search_result)
{
iobuf_close (hd->search_result);
hd->search_result = NULL;
}
if (!hd->need_search_reset)
{
/* No reset requested thus continue the search. The keyboxd
* keeps the context of the search and thus the NEXT operates on
* the last search pattern. This is how we always used the
* keydb.c functions. In theory we were able to modify the
* search pattern between searches but that is not anymore
* supported by keyboxd and a cursory check does not show that
* we actually made used of that misfeature. */
snprintf (line, sizeof line, "NEXT");
goto do_search;
}
hd->need_search_reset = 0;
if (!ndesc)
{
err = gpg_error (GPG_ERR_INV_ARG);
goto leave;
}
/* FIXME: Implement --multi */
switch (desc->mode)
{
case KEYDB_SEARCH_MODE_EXACT:
snprintf (line, sizeof line, "SEARCH =%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_SUBSTR:
snprintf (line, sizeof line, "SEARCH *%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_MAIL:
snprintf (line, sizeof line, "SEARCH <%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_MAILSUB:
snprintf (line, sizeof line, "SEARCH @%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_MAILEND:
snprintf (line, sizeof line, "SEARCH .%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_WORDS:
snprintf (line, sizeof line, "SEARCH +%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_SHORT_KID:
snprintf (line, sizeof line, "SEARCH 0x%08lX",
(ulong)desc->u.kid[1]);
break;
case KEYDB_SEARCH_MODE_LONG_KID:
snprintf (line, sizeof line, "SEARCH 0x%08lX%08lX",
(ulong)desc->u.kid[0], (ulong)desc->u.kid[1]);
break;
case KEYDB_SEARCH_MODE_FPR:
{
unsigned char hexfpr[MAX_FINGERPRINT_LEN * 2 + 1];
log_assert (desc[0].fprlen <= MAX_FINGERPRINT_LEN);
bin2hex (desc[0].u.fpr, desc[0].fprlen, hexfpr);
snprintf (line, sizeof line, "SEARCH 0x%s", hexfpr);
}
break;
case KEYDB_SEARCH_MODE_ISSUER:
snprintf (line, sizeof line, "SEARCH #/%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_ISSUER_SN:
case KEYDB_SEARCH_MODE_SN:
snprintf (line, sizeof line, "SEARCH #%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_SUBJECT:
snprintf (line, sizeof line, "SEARCH /%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_KEYGRIP:
{
unsigned char hexgrip[KEYGRIP_LEN * 2 + 1];
bin2hex (desc[0].u.grip, KEYGRIP_LEN, hexgrip);
snprintf (line, sizeof line, "SEARCH &%s", hexgrip);
}
break;
case KEYDB_SEARCH_MODE_FIRST:
snprintf (line, sizeof line, "SEARCH");
break;
case KEYDB_SEARCH_MODE_NEXT:
log_debug ("%s: mode next - we should not get to here!\n", __func__);
snprintf (line, sizeof line, "NEXT");
break;
default:
err = gpg_error (GPG_ERR_INV_ARG);
goto leave;
}
do_search:
{
membuf_t data;
void *buffer;
size_t len;
init_membuf (&data, 8192);
err = assuan_transact (hd->assuan_context, line,
put_membuf_cb, &data,
NULL, NULL,
NULL, NULL);
if (err)
{
xfree (get_membuf (&data, &len));
goto leave;
}
buffer = get_membuf (&data, &len);
if (!buffer)
{
err = gpg_error_from_syserror ();
goto leave;
}
/* Fixme: Avoid double allocation. */
hd->search_result = iobuf_temp_with_content (buffer, len);
}
leave:
if (DBG_CLOCK)
log_clock ("%s leave (%sfound)", __func__, err? "not ":"");
return err;
}

View File

@ -65,7 +65,7 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
*r_sec_avail = 0;
hd = keydb_new ();
hd = keydb_new (ctrl);
if (!hd)
return gpg_error_from_syserror ();
@ -131,7 +131,7 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
if (!secret && !force)
{
if (have_secret_key_with_kid (keyid))
if (have_secret_key_with_kid (ctrl, keyid))
{
*r_sec_avail = 1;
err = gpg_error (GPG_ERR_EOF);
@ -141,7 +141,7 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
err = 0;
}
if (secret && !have_secret_key_with_kid (keyid))
if (secret && !have_secret_key_with_kid (ctrl, keyid))
{
err = gpg_error (GPG_ERR_NOT_FOUND);
log_error (_("key \"%s\" not found\n"), username);

View File

@ -1877,7 +1877,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
stats = &dummystats;
*any = 0;
init_packet (&pkt);
kdbhd = keydb_new ();
kdbhd = keydb_new (ctrl);
if (!kdbhd)
return gpg_error_from_syserror ();

View File

@ -403,7 +403,7 @@ get_pubkey (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid)
}
else
{
ctx.kr_handle = keydb_new ();
ctx.kr_handle = keydb_new (ctrl);
if (!ctx.kr_handle)
{
rc = gpg_error_from_syserror ();
@ -448,7 +448,7 @@ leave:
* 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)
get_pubkey_fast (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid)
{
int rc = 0;
KEYDB_HANDLE hd;
@ -476,7 +476,7 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
}
#endif
hd = keydb_new ();
hd = keydb_new (ctrl);
if (!hd)
return gpg_error_from_syserror ();
rc = keydb_search_kid (hd, keyid);
@ -550,7 +550,7 @@ get_pubkeyblock (ctrl_t ctrl, u32 * keyid)
memset (&ctx, 0, sizeof ctx);
/* No need to set exact here because we want the entire block. */
ctx.not_allocated = 1;
ctx.kr_handle = keydb_new ();
ctx.kr_handle = keydb_new (ctrl);
if (!ctx.kr_handle)
return NULL;
ctx.nitems = 1;
@ -592,7 +592,7 @@ get_seckey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid)
memset (&ctx, 0, sizeof ctx);
ctx.exact = 1; /* Use the key ID exactly as given. */
ctx.not_allocated = 1;
ctx.kr_handle = keydb_new ();
ctx.kr_handle = keydb_new (ctrl);
if (!ctx.kr_handle)
return gpg_error_from_syserror ();
ctx.nitems = 1;
@ -793,7 +793,7 @@ key_byname (ctrl_t ctrl, GETKEY_CTX *retctx, strlist_t namelist,
}
ctx->want_secret = want_secret;
ctx->kr_handle = keydb_new ();
ctx->kr_handle = keydb_new (ctrl);
if (!ctx->kr_handle)
{
rc = gpg_error_from_syserror ();
@ -1428,7 +1428,7 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
err = gpg_error_from_syserror ();
else
{
ctx->kr_handle = keydb_new ();
ctx->kr_handle = keydb_new (ctrl);
if (! ctx->kr_handle)
{
err = gpg_error_from_syserror ();
@ -1574,7 +1574,7 @@ get_pubkey_byfprint (ctrl_t ctrl, PKT_public_key *pk, kbnode_t *r_keyblock,
ctx.not_allocated = 1;
/* FIXME: We should get the handle from the cache like we do in
* get_pubkey. */
ctx.kr_handle = keydb_new ();
ctx.kr_handle = keydb_new (ctrl);
if (!ctx.kr_handle)
return gpg_error_from_syserror ();
@ -1612,13 +1612,14 @@ get_pubkey_byfprint (ctrl_t ctrl, PKT_public_key *pk, kbnode_t *r_keyblock,
* Like get_pubkey_byfprint, PK may be NULL. In that case, this
* function effectively just checks for the existence of the key. */
gpg_error_t
get_pubkey_byfprint_fast (PKT_public_key * pk,
get_pubkey_byfprint_fast (ctrl_t ctrl, PKT_public_key * pk,
const byte * fprint, size_t fprint_len)
{
gpg_error_t err;
KBNODE keyblock;
err = get_keyblock_byfprint_fast (&keyblock, NULL, fprint, fprint_len, 0);
err = get_keyblock_byfprint_fast (ctrl,
&keyblock, NULL, fprint, fprint_len, 0);
if (!err)
{
if (pk)
@ -1638,7 +1639,8 @@ get_pubkey_byfprint_fast (PKT_public_key * pk,
* 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,
get_keyblock_byfprint_fast (ctrl_t ctrl,
kbnode_t *r_keyblock, KEYDB_HANDLE *r_hd,
const byte *fprint, size_t fprint_len, int lock)
{
gpg_error_t err;
@ -1655,7 +1657,7 @@ get_keyblock_byfprint_fast (kbnode_t *r_keyblock, KEYDB_HANDLE *r_hd,
for (i = 0; i < MAX_FINGERPRINT_LEN && i < fprint_len; i++)
fprbuf[i] = fprint[i];
hd = keydb_new ();
hd = keydb_new (ctrl);
if (!hd)
return gpg_error_from_syserror ();
@ -1737,7 +1739,7 @@ parse_def_secret_key (ctrl_t ctrl)
if (! hd)
{
hd = keydb_new ();
hd = keydb_new (ctrl);
if (!hd)
return NULL;
}
@ -2712,7 +2714,7 @@ merge_selfsigs_main (ctrl_t ctrl, kbnode_t keyblock, int *r_revoked,
* reason to check that an ultimately trusted key is
* still valid - if it has been revoked the user
* should also remove the ultimate trust flag. */
if (get_pubkey_fast (ultimate_pk, sig->keyid) == 0
if (get_pubkey_fast (ctrl, ultimate_pk, sig->keyid) == 0
&& check_key_signature2 (ctrl,
keyblock, k, ultimate_pk,
NULL, NULL, NULL, NULL) == 0
@ -4078,7 +4080,7 @@ key_origin_string (int origin)
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)
have_secret_key_with_kid (ctrl_t ctrl, u32 *keyid)
{
gpg_error_t err;
KEYDB_HANDLE kdbhd;
@ -4087,7 +4089,7 @@ have_secret_key_with_kid (u32 *keyid)
kbnode_t node;
int result = 0;
kdbhd = keydb_new ();
kdbhd = keydb_new (ctrl);
if (!kdbhd)
return 0;
memset (&desc, 0, sizeof desc);

View File

@ -361,6 +361,7 @@ enum cmd_and_opt_values
oUseAgent,
oNoUseAgent,
oGpgAgentInfo,
oUseKeyboxd,
oMergeOnly,
oTryAllSecrets,
oTrustedKey,
@ -378,6 +379,7 @@ enum cmd_and_opt_values
oPersonalDigestPreferences,
oPersonalCompressPreferences,
oAgentProgram,
oKeyboxdProgram,
oDirmngrProgram,
oDisableDirmngr,
oDisplay,
@ -849,6 +851,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oPersonalCompressPreferences, "personal-compress-prefs", "@"),
ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
ARGPARSE_s_s (oKeyboxdProgram, "keyboxd-program", "@"),
ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"),
ARGPARSE_s_n (oDisableDirmngr, "disable-dirmngr", "@"),
ARGPARSE_s_s (oDisplay, "display", "@"),
@ -895,6 +898,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oNoAutoKeyLocate, "no-auto-key-locate", "@"),
ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
ARGPARSE_s_n (oNoSymkeyCache, "no-symkey-cache", "@"),
ARGPARSE_s_n (oUseKeyboxd, "use-keyboxd", "@"),
/* Dummy options with warnings. */
ARGPARSE_s_n (oUseAgent, "use-agent", "@"),
@ -2734,6 +2738,11 @@ main (int argc, char **argv)
case oGpgAgentInfo:
obsolete_option (configname, configlineno, "gpg-agent-info");
break;
case oUseKeyboxd:
opt.use_keyboxd = 1;
break;
case oReaderPort:
obsolete_scdaemon_option (configname, configlineno, "reader-port");
break;
@ -3491,6 +3500,7 @@ main (int argc, char **argv)
pers_compress_list=pargs.r.ret_str;
break;
case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
case oKeyboxdProgram: opt.keyboxd_program = pargs.r.ret_str; break;
case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
case oDisableDirmngr: opt.disable_dirmngr = 1; break;
case oWeakDigest:
@ -4105,8 +4115,10 @@ main (int argc, char **argv)
/* Add the keyrings, but not for some special commands. We always
* need to add the keyrings if we are running under SELinux, this
* is so that the rings are added to the list of secured files.
* We do not add any keyring if --no-keyring has been used. */
if (default_keyring >= 0
* We do not add any keyring if --no-keyring or --use-keyboxd has
* been used. */
if (!opt.use_keyboxd
&& default_keyring >= 0
&& (ALWAYS_ADD_KEYRINGS
|| (cmd != aDeArmor && cmd != aEnArmor && cmd != aGPGConfTest)))
{
@ -4118,9 +4130,8 @@ main (int argc, char **argv)
}
FREE_STRLIST(nrings);
/* In loopback mode, never ask for the password multiple times. */
if (opt.pinentry_mode == PINENTRY_MODE_LOOPBACK)
/* In loopback mode, never ask for the password multiple
times. */
{
opt.passphrase_repeat = 0;
}
@ -5064,7 +5075,7 @@ main (int argc, char **argv)
policy = parse_tofu_policy (argv[0]);
hd = keydb_new ();
hd = keydb_new (ctrl);
if (! hd)
{
write_status_failure ("tofu-driver", gpg_error(GPG_ERR_GENERAL));

View File

@ -60,16 +60,19 @@
/* Object used to keep state locally to server.c . */
struct server_local_s;
/* Object used to keep state locally to call-keyboxd.c . */
struct keyboxd_local_s;
typedef struct keyboxd_local_s *keyboxd_local_t;
/* Object used to keep state locally to call-dirmngr.c . */
struct dirmngr_local_s;
typedef struct dirmngr_local_s *dirmngr_local_t;
/* Object used to describe a keyblock node. */
typedef struct kbnode_struct *KBNODE; /* Deprecated use kbnode_t. */
typedef struct kbnode_struct *kbnode_t;
typedef struct kbnode_struct *KBNODE; /* Deprecated use kbnode_t. */typedef struct kbnode_struct *kbnode_t;
/* The handle for keydb operations. */
typedef struct keydb_handle *KEYDB_HANDLE;
typedef struct keydb_handle_s *KEYDB_HANDLE;
/* TOFU database meta object. */
struct tofu_dbs_s;
@ -96,6 +99,9 @@ struct server_control_s
/* Local data for call-dirmngr.c */
dirmngr_local_t dirmngr_local;
/* Local data for call-keyboxd.c */
keyboxd_local_t keyboxd_local;
/* Local data for tofu.c */
struct {
tofu_dbs_t dbs;

View File

@ -614,7 +614,7 @@ pk_search_terms (const char *option, int argc, char *argv[], void *cookie)
if (err)
log_fatal ("search terms '%s': %s\n", argv[0], gpg_strerror (err));
hd = keydb_new ();
hd = keydb_new (ctrl);
err = keydb_search (hd, &desc, 1, NULL);
if (err)
@ -810,7 +810,7 @@ sig_issuer (const char *option, int argc, char *argv[], void *cookie)
if (err)
log_fatal ("search terms '%s': %s\n", argv[0], gpg_strerror (err));
hd = keydb_new ();
hd = keydb_new (ctrl);
err = keydb_search (hd, &desc, 1, NULL);
if (err)

View File

@ -2022,7 +2022,7 @@ import_one_real (ctrl_t ctrl,
goto leave;
/* Do we have this key already in one of our pubrings ? */
err = get_keyblock_byfprint_fast (&keyblock_orig, &hd,
err = get_keyblock_byfprint_fast (ctrl, &keyblock_orig, &hd,
fpr2, fpr2len, 1/*locked*/);
if ((err
&& gpg_err_code (err) != GPG_ERR_NO_PUBKEY
@ -2310,13 +2310,13 @@ import_one_real (ctrl_t ctrl,
if (mod_key)
{
revocation_present (ctrl, keyblock_orig);
if (!from_sk && have_secret_key_with_kid (keyid))
if (!from_sk && have_secret_key_with_kid (ctrl, keyid))
check_prefs (ctrl, keyblock_orig);
}
else if (new_key)
{
revocation_present (ctrl, keyblock);
if (!from_sk && have_secret_key_with_kid (keyid))
if (!from_sk && have_secret_key_with_kid (ctrl, keyid))
check_prefs (ctrl, keyblock);
}
@ -3372,7 +3372,7 @@ import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options,
}
/* Read the original keyblock. */
hd = keydb_new ();
hd = keydb_new (ctrl);
if (!hd)
{
rc = gpg_error_from_syserror ();
@ -3768,7 +3768,8 @@ delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
else if (node->pkt->pkttype == PKT_SIGNATURE
&& !node->pkt->pkt.signature->flags.exportable
&& !(options&IMPORT_LOCAL_SIGS)
&& !have_secret_key_with_kid (node->pkt->pkt.signature->keyid))
&& !have_secret_key_with_kid (ctrl,
node->pkt->pkt.signature->keyid))
{
/* here we violate the rfc a bit by still allowing
* to import non-exportable signature when we have the
@ -4089,7 +4090,7 @@ revocation_present (ctrl_t ctrl, kbnode_t keyblock)
* itself? */
gpg_error_t err;
err = get_pubkey_byfprint_fast (NULL,
err = get_pubkey_byfprint_fast (ctrl, NULL,
sig->revkey[idx].fpr,
sig->revkey[idx].fprlen);
if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY
@ -4111,7 +4112,7 @@ revocation_present (ctrl_t ctrl, kbnode_t keyblock)
opt.keyserver, 0);
/* Do we have it now? */
err = get_pubkey_byfprint_fast (NULL,
err = get_pubkey_byfprint_fast (ctrl, NULL,
sig->revkey[idx].fpr,
sig->revkey[idx].fprlen);
}

176
g10/keydb-private.h Normal file
View File

@ -0,0 +1,176 @@
/* keydb-private.h - Common definitions for keydb.c and call-keyboxd.c
* Copyright (C) 2019 g10 Code GmbH
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef G10_KEYDB_PRIVATE_H
#define G10_KEYDB_PRIVATE_H
#include <assuan.h>
#include "../common/membuf.h"
/* Ugly forward declarations. */
struct keyring_handle;
typedef struct keyring_handle *KEYRING_HANDLE;
struct keybox_handle;
typedef struct keybox_handle *KEYBOX_HANDLE;
/* This is for keydb.c and only used in non-keyboxd mode. */
#define MAX_KEYDB_RESOURCES 40
/* This is for keydb.c and only used in non-keyboxd mode. */
typedef enum
{
KEYDB_RESOURCE_TYPE_NONE = 0,
KEYDB_RESOURCE_TYPE_KEYRING,
KEYDB_RESOURCE_TYPE_KEYBOX
} KeydbResourceType;
/* This is for keydb.c and only used in non-keyboxd mode. */
struct resource_item
{
KeydbResourceType type;
union {
KEYRING_HANDLE kr;
KEYBOX_HANDLE kb;
} u;
void *token;
};
/* This is a simple cache used to return the last result of a
* successful fingerprint search. This works only for keybox
* resources because (due to lack of a copy_keyblock function) we need
* to store an image of the keyblock which is fortunately instantly
* available for keyboxes. Only used in non-keyboxd mode. */
enum keyblock_cache_states {
KEYBLOCK_CACHE_EMPTY,
KEYBLOCK_CACHE_PREPARED,
KEYBLOCK_CACHE_FILLED
};
struct keyblock_cache {
enum keyblock_cache_states state;
byte fpr[MAX_FINGERPRINT_LEN];
byte fprlen;
iobuf_t iobuf; /* Image of the keyblock. */
int pk_no;
int uid_no;
/* Offset of the record in the keybox. */
int resource;
off_t offset;
};
/* The definition of the KEYDB_HANDLE as used internally by keydb.c and
* the newer call-keyboxd. */
struct keydb_handle_s
{
/* Flag set if this handles pertains to call-keyboxd.c. */
int use_keyboxd;
/* BEGIN USE_KEYBOXD */
/* (These fields are only valid if USE_KEYBOXD is set.) */
/* A shallow pointer with the CTRL used to create this handle. */
ctrl_t ctrl;
/* The context used to communicate with the keyboxd. */
assuan_context_t assuan_context;
/* I/O buffer with the last search result or NULL. */
iobuf_t search_result;
/* Flag indicating that a search reset is required. */
unsigned int need_search_reset : 1;
/* END USE_KEYBOXD */
/* BEGIN !USE_KEYBOXD */
/* (The remaining fields are only valid if USE_KEYBOXD is cleared.) */
/* When we locked all of the resources in ACTIVE (using keyring_lock
* / keybox_lock, as appropriate). */
int locked;
/* If this flag is set a lock will only be released by
* keydb_release. */
int keep_lock;
/* 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;
/* The number of resources in ACTIVE. */
int used;
/* Cache of the last found and parsed key block (only used for
keyboxes, not keyrings). */
struct keyblock_cache keyblock_cache;
/* Copy of ALL_RESOURCES when keydb_new is called. */
struct resource_item active[MAX_KEYDB_RESOURCES];
/* END !USE_KEYBOXD */
};
/*-- keydb.c --*/
/* These are the functions call-keyboxd diverts to if the keyboxd is
* not used. */
gpg_error_t internal_keydb_init (KEYDB_HANDLE hd);
void internal_keydb_deinit (KEYDB_HANDLE hd);
gpg_error_t internal_keydb_lock (KEYDB_HANDLE hd);
gpg_error_t internal_keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
gpg_error_t internal_keydb_update_keyblock (ctrl_t ctrl,
KEYDB_HANDLE hd, kbnode_t kb);
gpg_error_t internal_keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb);
gpg_error_t internal_keydb_delete_keyblock (KEYDB_HANDLE hd);
gpg_error_t internal_keydb_search_reset (KEYDB_HANDLE hd);
gpg_error_t internal_keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
size_t ndesc, size_t *descindex);
#endif /*G10_KEYDB_PRIVATE_H*/

View File

@ -37,25 +37,10 @@
#include "keydb.h"
#include "../common/i18n.h"
#include "keydb-private.h" /* For struct keydb_handle_s */
static int active_handles;
typedef enum
{
KEYDB_RESOURCE_TYPE_NONE = 0,
KEYDB_RESOURCE_TYPE_KEYRING,
KEYDB_RESOURCE_TYPE_KEYBOX
} KeydbResourceType;
#define MAX_KEYDB_RESOURCES 40
struct resource_item
{
KeydbResourceType type;
union {
KEYRING_HANDLE kr;
KEYBOX_HANDLE kb;
} u;
void *token;
};
static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
static int used_resources;
@ -67,74 +52,6 @@ static void *primary_keydb;
/* Whether we have successfully registered any resource. */
static int any_registered;
/* This is a simple cache used to return the last result of a
successful fingerprint search. This works only for keybox resources
because (due to lack of a copy_keyblock function) we need to store
an image of the keyblock which is fortunately instantly available
for keyboxes. */
enum keyblock_cache_states {
KEYBLOCK_CACHE_EMPTY,
KEYBLOCK_CACHE_PREPARED,
KEYBLOCK_CACHE_FILLED
};
struct keyblock_cache {
enum keyblock_cache_states state;
byte fpr[MAX_FINGERPRINT_LEN];
byte fprlen;
iobuf_t iobuf; /* Image of the keyblock. */
int pk_no;
int uid_no;
/* Offset of the record in the keybox. */
int resource;
off_t offset;
};
struct keydb_handle
{
/* When we locked all of the resources in ACTIVE (using keyring_lock
/ keybox_lock, as appropriate). */
int locked;
/* If this flag is set a lock will only be released by
* keydb_release. */
int keep_lock;
/* 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;
/* The number of resources in ACTIVE. */
int used;
/* Cache of the last found and parsed key block (only used for
keyboxes, not keyrings). */
struct keyblock_cache keyblock_cache;
/* Copy of ALL_RESOURCES when keydb_new is called. */
struct resource_item active[MAX_KEYDB_RESOURCES];
};
/* Looking up keys is expensive. To hide the cost, we cache whether
keys exist in the key database. Then, if we know a key does not
exist, we don't have to spend time looking it up. This
@ -273,7 +190,7 @@ kid_not_found_flush (void)
static void
keyblock_cache_clear (struct keydb_handle *hd)
keyblock_cache_clear (struct keydb_handle_s *hd)
{
hd->keyblock_cache.state = KEYBLOCK_CACHE_EMPTY;
iobuf_close (hd->keyblock_cache.iobuf);
@ -875,26 +792,17 @@ 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(). This
function returns NULL on error, sets ERRNO, and prints an error
diagnostic. */
KEYDB_HANDLE
keydb_new (void)
/* keydb_new diverts to here in non-keyboxd mode. HD is just the
* calloced structure with the handle type intialized. */
gpg_error_t
internal_keydb_init (KEYDB_HANDLE hd)
{
KEYDB_HANDLE hd;
gpg_error_t err = 0;
int i, j;
int die = 0;
int reterrno;
if (DBG_CLOCK)
log_clock ("keydb_new");
hd = xtrycalloc (1, sizeof *hd);
if (!hd)
goto leave;
log_assert (!hd->use_keyboxd);
hd->found = -1;
hd->saved_found = -1;
hd->is_reset = 1;
@ -936,28 +844,21 @@ keydb_new (void)
keydb_stats.handles++;
if (die)
{
keydb_release (hd);
gpg_err_set_errno (reterrno);
hd = NULL;
}
err = gpg_error_from_errno (reterrno);
leave:
if (!hd)
log_error (_("error opening key DB: %s\n"),
gpg_strerror (gpg_error_from_syserror()));
return hd;
return err;
}
/* Free all non-keyboxd resources owned by the database handle.
* keydb_release diverts to here. */
void
keydb_release (KEYDB_HANDLE hd)
internal_keydb_deinit (KEYDB_HANDLE hd)
{
int i;
if (!hd)
return;
log_assert (!hd->use_keyboxd);
log_assert (active_handles > 0);
active_handles--;
@ -979,19 +880,17 @@ keydb_release (KEYDB_HANDLE hd)
}
keyblock_cache_clear (hd);
xfree (hd);
}
/* Take a lock on the files immediately and not only during insert or
* update. This lock is released with keydb_release. */
gpg_error_t
keydb_lock (KEYDB_HANDLE hd)
internal_keydb_lock (KEYDB_HANDLE hd)
{
gpg_error_t err;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
log_assert (!hd->use_keyboxd);
err = lock_all (hd);
if (!err)
@ -1007,7 +906,7 @@ keydb_lock (KEYDB_HANDLE hd)
void
keydb_disable_caching (KEYDB_HANDLE hd)
{
if (hd)
if (hd && !hd->use_keyboxd)
hd->no_caching = 1;
}
@ -1029,6 +928,9 @@ keydb_get_resource_name (KEYDB_HANDLE hd)
if (!hd)
return NULL;
if (!hd->use_keyboxd)
return "[keyboxd]";
if ( hd->found >= 0 && hd->found < hd->used)
idx = hd->found;
else if ( hd->current >= 0 && hd->current < hd->used)
@ -1152,6 +1054,8 @@ unlock_all (KEYDB_HANDLE hd)
* Note: it is only possible to save a single save state at a time.
* In other words, the save stack only has room for a single
* instance of the state. */
/* FIXME(keyboxd): This function is used only at one place - see how
* we can avoid it. */
void
keydb_push_found_state (KEYDB_HANDLE hd)
{
@ -1183,6 +1087,8 @@ keydb_push_found_state (KEYDB_HANDLE hd)
/* Restore the previous save state. If the saved state is NULL or
invalid, this is a NOP. */
/* FIXME(keyboxd): This function is used only at one place - see how
* we can avoid it. */
void
keydb_pop_found_state (KEYDB_HANDLE hd)
{
@ -1347,6 +1253,7 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
/* Return the keyblock last found by keydb_search() in *RET_KB.
* keydb_get_keyblock divert to here in the non-keyboxd mode.
*
* On success, the function returns 0 and the caller must free *RET_KB
* using release_kbnode(). Otherwise, the function returns an error
@ -1356,17 +1263,11 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
* 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)
internal_keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
{
gpg_error_t err = 0;
*ret_kb = NULL;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if (DBG_CLOCK)
log_clock ("keydb_get_keybock enter");
log_assert (!hd->use_keyboxd);
if (hd->keyblock_cache.state == KEYBLOCK_CACHE_FILLED)
{
@ -1385,8 +1286,7 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
if (err)
keyblock_cache_clear (hd);
if (DBG_CLOCK)
log_clock (err? "keydb_get_keyblock leave (cached, failed)"
: "keydb_get_keyblock leave (cached)");
log_clock ("%s leave (cached mode)", __func__);
return err;
}
}
@ -1434,9 +1334,6 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
if (!err)
keydb_stats.get_keyblocks++;
if (DBG_CLOCK)
log_clock (err? "keydb_get_keyblock leave (failed)"
: "keydb_get_keyblock leave");
return err;
}
@ -1485,6 +1382,7 @@ build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf)
/* Update the keyblock KB (i.e., extract the fingerprint and find the
* corresponding keyblock in the keyring).
* keydb_update_keyblock diverts to here in the non-keyboxd mode.
*
* This doesn't do anything if --dry-run was specified.
*
@ -1499,20 +1397,16 @@ build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf)
* you should use keydb_push_found_state and keydb_pop_found_state to
* save and restore it. */
gpg_error_t
keydb_update_keyblock (ctrl_t ctrl, KEYDB_HANDLE hd, kbnode_t kb)
internal_keydb_update_keyblock (ctrl_t ctrl, KEYDB_HANDLE hd, kbnode_t kb)
{
gpg_error_t err;
PKT_public_key *pk;
KEYDB_SEARCH_DESC desc;
size_t len;
log_assert (kb);
log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
log_assert (!hd->use_keyboxd);
pk = kb->pkt->pkt.public_key;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
kid_not_found_flush ();
keyblock_cache_clear (hd);
@ -1575,6 +1469,7 @@ keydb_update_keyblock (ctrl_t ctrl, KEYDB_HANDLE hd, kbnode_t kb)
/* Insert a keyblock into one of the underlying keyrings or keyboxes.
* keydb_insert_keyblock diverts to here in the non-keyboxd mode.
*
* Be default, the keyring / keybox from which the last search result
* came is used. If there was no previous search result (or
@ -1585,13 +1480,12 @@ keydb_update_keyblock (ctrl_t ctrl, KEYDB_HANDLE hd, kbnode_t kb)
*
* Returns 0 on success. Otherwise, it returns an error code. */
gpg_error_t
keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
internal_keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
{
gpg_error_t err;
int idx;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
log_assert (!hd->use_keyboxd);
kid_not_found_flush ();
keyblock_cache_clear (hd);
@ -1650,12 +1544,11 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
*
* Returns 0 on success or an error code, if an error occurs. */
gpg_error_t
keydb_delete_keyblock (KEYDB_HANDLE hd)
internal_keydb_delete_keyblock (KEYDB_HANDLE hd)
{
gpg_error_t rc;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
log_assert (!hd->use_keyboxd);
kid_not_found_flush ();
keyblock_cache_clear (hd);
@ -1708,6 +1601,9 @@ keydb_locate_writable (KEYDB_HANDLE hd)
if (!hd)
return GPG_ERR_INV_ARG;
if (hd->use_keyboxd)
return 0; /* No need for this here. */
rc = keydb_search_reset (hd); /* this does reset hd->current */
if (rc)
return rc;
@ -1759,6 +1655,9 @@ keydb_rebuild_caches (ctrl_t ctrl, int noisy)
{
int i, rc;
if (opt.use_keyboxd)
return; /* No need for this here. */
for (i=0; i < used_resources; i++)
{
if (!keyring_is_writable (all_resources[i].token))
@ -1781,38 +1680,33 @@ keydb_rebuild_caches (ctrl_t ctrl, int noisy)
}
/* Return the number of skipped blocks (because they were to large to
/* Return the number of skipped blocks (because they were too large to
read from a keybox) since the last search reset. */
unsigned long
keydb_get_skipped_counter (KEYDB_HANDLE hd)
{
return hd ? hd->skipped_long_blobs : 0;
/*FIXME(keyboxd): Do we need this? */
return hd && !hd->use_keyboxd? hd->skipped_long_blobs : 0;
}
/* 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).
* keydb_search_reset diverts to here in the non-keyboxd mode.
*
* Returns 0 on success and an error code if an error occurred.
* (Currently, this function always returns 0 if HD is valid.) */
gpg_error_t
keydb_search_reset (KEYDB_HANDLE hd)
internal_keydb_search_reset (KEYDB_HANDLE hd)
{
gpg_error_t rc = 0;
int i;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
log_assert (!hd->use_keyboxd);
keyblock_cache_clear (hd);
if (DBG_CLOCK)
log_clock ("keydb_search_reset");
if (DBG_CACHE)
log_debug ("keydb_search: reset (hd=%p)", hd);
hd->skipped_long_blobs = 0;
hd->current = 0;
hd->found = -1;
@ -1840,6 +1734,7 @@ keydb_search_reset (KEYDB_HANDLE hd)
/* Search the database for keys matching the search description. If
* the DB contains any legacy keys, these are silently ignored.
* keydb_search diverts to here in the non-keyboxd mode.
*
* 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
@ -1857,21 +1752,16 @@ keydb_search_reset (KEYDB_HANDLE hd)
* 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)
internal_keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
size_t ndesc, size_t *descindex)
{
int i;
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;
int fprlen;
if (descindex)
*descindex = 0; /* Make sure it is always set on return. */
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
log_assert (!hd->use_keyboxd);
if (!any_registered)
{
@ -1879,26 +1769,11 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
return gpg_error (GPG_ERR_NOT_FOUND);
}
if (DBG_CLOCK)
log_clock ("keydb_search enter");
if (DBG_LOOKUP)
{
log_debug ("%s: %zd search descriptions:\n", __func__, ndesc);
for (i = 0; i < ndesc; i ++)
{
char *t = keydb_search_desc_dump (&desc[i]);
log_debug ("%s %d: %s\n", __func__, i, t);
xfree (t);
}
}
if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID
&& (already_in_cache = kid_not_found_p (desc[0].u.kid)) == 1 )
{
if (DBG_CLOCK)
log_clock ("keydb_search leave (not found, cached)");
log_clock ("%s leave (not found, cached)", __func__);
keydb_stats.notfound_cached++;
return gpg_error (GPG_ERR_NOT_FOUND);
}
@ -1926,7 +1801,7 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
{
/* (DESCINDEX is already set). */
if (DBG_CLOCK)
log_clock ("keydb_search leave (cached)");
log_clock ("%s leave (cached)", __func__);
hd->current = hd->keyblock_cache.resource;
/* HD->KEYBLOCK_CACHE.OFFSET is the last byte in the record.
@ -2016,9 +1891,6 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
&& !already_in_cache)
kid_not_found_insert (desc[0].u.kid);
if (DBG_CLOCK)
log_clock (rc? "keydb_search leave (not found)"
: "keydb_search leave (found)");
if (!rc)
keydb_stats.found++;
else

View File

@ -163,6 +163,38 @@ is_in_klist (struct key_item *k, PKT_signature *sig)
}
/*-- call-keyboxd.c --*/
/* Create a new database handle. Returns NULL on error, sets ERRNO,
* and prints an error diagnostic. */
KEYDB_HANDLE keydb_new (ctrl_t ctrl);
/* Release a keydb handle. */
void keydb_release (KEYDB_HANDLE hd);
/* Take a lock if we are not using the keyboxd. */
gpg_error_t keydb_lock (KEYDB_HANDLE hd);
/* Return the keyblock last found by keydb_search. */
gpg_error_t keydb_get_keyblock (KEYDB_HANDLE hd, kbnode_t *ret_kb);
/* Update the keyblock KB. */
gpg_error_t keydb_update_keyblock (ctrl_t ctrl, KEYDB_HANDLE hd, kbnode_t kb);
/* Insert a keyblock into one of the storage system. */
gpg_error_t keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb);
/* Delete the currently selected keyblock. */
gpg_error_t keydb_delete_keyblock (KEYDB_HANDLE hd);
/* Clears the current search result and resets the handle's position. */
gpg_error_t keydb_search_reset (KEYDB_HANDLE hd);
/* Search the database for keys matching the search description. */
gpg_error_t keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
size_t ndesc, size_t *descindex);
/*-- keydb.c --*/
@ -181,17 +213,6 @@ gpg_error_t keydb_add_resource (const char *url, unsigned int flags);
/* Dump some statistics to the log. */
void keydb_dump_stats (void);
/* Create a new database handle. Returns NULL on error, sets ERRNO,
and prints an error diagnostic. */
KEYDB_HANDLE keydb_new (void);
/* Free all resources owned by the database handle. */
void keydb_release (KEYDB_HANDLE hd);
/* Take a lock on the files immediately and not only during insert or
* update. This lock is released with keydb_release. */
gpg_error_t keydb_lock (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. */
@ -206,18 +227,6 @@ void keydb_pop_found_state (KEYDB_HANDLE hd);
/* Return the file name of the resource. */
const char *keydb_get_resource_name (KEYDB_HANDLE hd);
/* Return the keyblock last found by keydb_search. */
gpg_error_t keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
/* Update the keyblock KB. */
gpg_error_t keydb_update_keyblock (ctrl_t ctrl, KEYDB_HANDLE hd, kbnode_t kb);
/* Insert a keyblock into one of the underlying keyrings or keyboxes. */
gpg_error_t keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb);
/* Delete the currently selected keyblock. */
gpg_error_t keydb_delete_keyblock (KEYDB_HANDLE hd);
/* Find the first writable resource. */
gpg_error_t keydb_locate_writable (KEYDB_HANDLE hd);
@ -228,13 +237,6 @@ void keydb_rebuild_caches (ctrl_t ctrl, int noisy);
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. */
gpg_error_t keydb_search_reset (KEYDB_HANDLE hd);
/* Search the database for keys matching the search description. */
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. */
gpg_error_t keydb_search_first (KEYDB_HANDLE hd);
@ -323,7 +325,7 @@ int get_pubkey (ctrl_t ctrl, 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. */
int get_pubkey_fast (PKT_public_key *pk, u32 *keyid);
int get_pubkey_fast (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid);
/* Return the entire keyblock used to create SIG. This is a
* specialized version of get_pubkeyblock. */
@ -383,13 +385,14 @@ int get_pubkey_byfprint (ctrl_t ctrl, PKT_public_key *pk, kbnode_t *r_keyblock,
/* 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. */
gpg_error_t get_pubkey_byfprint_fast (PKT_public_key *pk,
gpg_error_t get_pubkey_byfprint_fast (ctrl_t ctrl, PKT_public_key *pk,
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. */
gpg_error_t get_keyblock_byfprint_fast (kbnode_t *r_keyblock,
gpg_error_t get_keyblock_byfprint_fast (ctrl_t ctrl,
kbnode_t *r_keyblock,
KEYDB_HANDLE *r_hd,
const byte *fprint, size_t fprint_len,
int lock);
@ -397,7 +400,7 @@ gpg_error_t get_keyblock_byfprint_fast (kbnode_t *r_keyblock,
/* Returns true if a secret key is available for the public key with
key id KEYID. */
int have_secret_key_with_kid (u32 *keyid);
int have_secret_key_with_kid (ctrl_t ctrl, u32 *keyid);
/* Parse the --default-key parameter. Returns the last key (in terms
of when the option is given) that is available. */

View File

@ -2289,7 +2289,7 @@ quick_find_keyblock (ctrl_t ctrl, const char *username,
*r_keyblock = NULL;
/* Search the key; we don't want the whole getkey stuff here. */
kdbhd = keydb_new ();
kdbhd = keydb_new (ctrl);
if (!kdbhd)
{
/* Note that keydb_new has already used log_error. */
@ -5761,7 +5761,7 @@ menu_revsig (ctrl_t ctrl, kbnode_t keyblock)
}
else if (!skip && node->pkt->pkttype == PKT_SIGNATURE
&& ((sig = node->pkt->pkt.signature),
have_secret_key_with_kid (sig->keyid)))
have_secret_key_with_kid (ctrl, sig->keyid)))
{
if ((sig->sig_class & ~3) == 0x10)
{
@ -5800,7 +5800,7 @@ menu_revsig (ctrl_t ctrl, kbnode_t keyblock)
}
else if (!skip && node->pkt->pkttype == PKT_SIGNATURE
&& ((sig = node->pkt->pkt.signature),
have_secret_key_with_kid (sig->keyid)))
have_secret_key_with_kid (ctrl, sig->keyid)))
{
if ((sig->sig_class & ~3) == 0x10)
{

View File

@ -4332,7 +4332,7 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid, const char *algostr,
desc.mode = KEYDB_SEARCH_MODE_EXACT;
desc.u.name = uid;
kdbhd = keydb_new ();
kdbhd = keydb_new (ctrl);
if (!kdbhd)
goto leave;
@ -5184,7 +5184,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
{
KEYDB_HANDLE pub_hd;
pub_hd = keydb_new ();
pub_hd = keydb_new (ctrl);
if (!pub_hd)
err = gpg_error_from_syserror ();
else

View File

@ -527,7 +527,7 @@ list_all (ctrl_t ctrl, int secret, int mark_secret)
if (opt.check_sigs)
listctx.check_sigs = 1;
hd = keydb_new ();
hd = keydb_new (ctrl);
if (!hd)
rc = gpg_error_from_syserror ();
else

View File

@ -1196,7 +1196,7 @@ keyidlist (ctrl_t ctrl, strlist_t users, KEYDB_SEARCH_DESC **klist,
*klist=xmalloc(sizeof(KEYDB_SEARCH_DESC)*num);
kdbhd = keydb_new ();
kdbhd = keydb_new (ctrl);
if (!kdbhd)
{
rc = gpg_error_from_syserror ();

View File

@ -157,7 +157,7 @@ struct expando_args
const byte *namehash;
};
char *pct_expando(const char *string,struct expando_args *args);
char *pct_expando (ctrl_t ctrl, const char *string,struct expando_args *args);
void deprecated_warning(const char *configname,unsigned int configlineno,
const char *option,const char *repl1,const char *repl2);
void deprecated_command (const char *name);

View File

@ -895,7 +895,7 @@ get_signature_count (PKT_public_key *pk)
/* Expand %-strings. Returns a string which must be xfreed. Returns
NULL if the string cannot be expanded (too large). */
char *
pct_expando(const char *string,struct expando_args *args)
pct_expando (ctrl_t ctrl, const char *string,struct expando_args *args)
{
const char *ch=string;
int idx=0,maxlen=0,done=0;
@ -1017,7 +1017,7 @@ pct_expando(const char *string,struct expando_args *args)
PKT_public_key *pk=
xmalloc_clear(sizeof(PKT_public_key));
if (!get_pubkey_fast (pk,args->pksk->main_keyid))
if (!get_pubkey_fast (ctrl, pk,args->pksk->main_keyid))
fingerprint_from_pk (pk, array, &len);
else
memset (array, 0, (len=MAX_FINGERPRINT_LEN));

View File

@ -126,6 +126,7 @@ struct
int completes_needed;
int max_cert_depth;
const char *agent_program;
const char *keyboxd_program;
const char *dirmngr_program;
int disable_dirmngr;
@ -284,6 +285,8 @@ struct
int only_sign_text_ids;
int no_symkey_cache; /* Disable the cache used for --symmetric. */
int use_keyboxd; /* Use the external keyboxd as storage backend. */
} opt;
/* CTRL is used to keep some global variables we currently can't

View File

@ -338,7 +338,7 @@ show_photos (ctrl_t ctrl, const struct user_attribute *attrs, int count,
#endif
/* make command grow */
command=pct_expando(opt.photo_viewer,&args);
command=pct_expando (ctrl, opt.photo_viewer,&args);
if(!command)
goto fail;

View File

@ -217,7 +217,7 @@ gen_desig_revoke (ctrl_t ctrl, const char *uname, strlist_t locusr)
afx = new_armor_context ();
kdbhd = keydb_new ();
kdbhd = keydb_new (ctrl);
if (!kdbhd)
{
rc = gpg_error_from_syserror ();
@ -641,7 +641,7 @@ gen_revoke (ctrl_t ctrl, const char *uname)
}
/* Search the userid; we don't want the whole getkey stuff here. */
kdbhd = keydb_new ();
kdbhd = keydb_new (ctrl);
if (!kdbhd)
{
rc = gpg_error_from_syserror ();

View File

@ -70,7 +70,7 @@ typedef struct pt_extra_hash_data_s *pt_extra_hash_data_t;
* a valid NAME=VALUE format.
*/
static void
mk_notation_policy_etc (PKT_signature *sig,
mk_notation_policy_etc (ctrl_t ctrl, PKT_signature *sig,
PKT_public_key *pk, PKT_public_key *pksk)
{
const char *string;
@ -97,7 +97,7 @@ mk_notation_policy_etc (PKT_signature *sig,
for (item = nd; item; item = item->next)
{
item->altvalue = pct_expando (item->value,&args);
item->altvalue = pct_expando (ctrl, item->value,&args);
if (!item->altvalue)
log_error (_("WARNING: unable to %%-expand notation "
"(too large). Using unexpanded.\n"));
@ -122,7 +122,7 @@ mk_notation_policy_etc (PKT_signature *sig,
{
string = pu->d;
p = pct_expando (string, &args);
p = pct_expando (ctrl, string, &args);
if (!p)
{
log_error(_("WARNING: unable to %%-expand policy URL "
@ -145,7 +145,7 @@ mk_notation_policy_etc (PKT_signature *sig,
{
string = pu->d;
p = pct_expando (string, &args);
p = pct_expando (ctrl, string, &args);
if (!p)
{
log_error (_("WARNING: unable to %%-expand preferred keyserver URL"
@ -834,7 +834,7 @@ write_signature_packets (ctrl_t ctrl,
BUG ();
build_sig_subpkt_from_sig (sig, pk);
mk_notation_policy_etc (sig, NULL, pk);
mk_notation_policy_etc (ctrl, sig, NULL, pk);
hash_sigversion_to_magic (md, sig, extrahash);
gcry_md_final (md);
@ -1660,7 +1660,7 @@ make_keysig_packet (ctrl_t ctrl,
sig->sig_class = sigclass;
build_sig_subpkt_from_sig (sig, pksk);
mk_notation_policy_etc (sig, pk, pksk);
mk_notation_policy_etc (ctrl, sig, pk, pksk);
/* Crucial that the call to mksubpkt comes LAST before the calls
* to finalize the sig as that makes it possible for the mksubpkt

View File

@ -21,9 +21,11 @@
#include "keydb.h"
static void
do_test (int argc, char *argv[])
{
ctrl_t ctrl;
char *fname;
int rc;
KEYDB_HANDLE hd1;
@ -33,6 +35,7 @@ do_test (int argc, char *argv[])
(void) argc;
(void) argv;
ctrl = xcalloc (1, sizeof *ctrl);
/* t-keydb-get-keyblock.gpg contains two keys: a modern key followed
by a legacy key. If we get the keyblock for the modern key, we
shouldn't get
@ -44,7 +47,7 @@ do_test (int argc, char *argv[])
if (rc)
ABORT ("Failed to open keyring.");
hd1 = keydb_new ();
hd1 = keydb_new (ctrl);
if (!hd1)
ABORT ("");
@ -62,4 +65,5 @@ do_test (int argc, char *argv[])
keydb_release (hd1);
release_kbnode (kb1);
xfree (ctrl);
}

View File

@ -25,6 +25,7 @@ static void
do_test (int argc, char *argv[])
{
int rc;
ctrl_t ctrl;
KEYDB_HANDLE hd1, hd2;
KEYDB_SEARCH_DESC desc1, desc2;
KBNODE kb1, kb2, p;
@ -35,16 +36,17 @@ do_test (int argc, char *argv[])
(void) argc;
(void) argv;
ctrl = xcalloc (1, sizeof *ctrl);
fname = prepend_srcdir ("t-keydb-keyring.kbx");
rc = keydb_add_resource (fname, 0);
test_free (fname);
if (rc)
ABORT ("Failed to open keyring.");
hd1 = keydb_new ();
hd1 = keydb_new (ctrl);
if (!hd1)
ABORT ("");
hd2 = keydb_new ();
hd2 = keydb_new (ctrl);
if (!hd2)
ABORT ("");
@ -101,4 +103,5 @@ do_test (int argc, char *argv[])
release_kbnode (kb2);
keydb_release (hd1);
keydb_release (hd2);
xfree (ctrl);
}

View File

@ -2131,7 +2131,7 @@ build_conflict_set (ctrl_t ctrl, tofu_dbs_t dbs,
/* If two keys have cross signatures, then they are controlled by
* the same person and thus are not in conflict. */
kb_all = xcalloc (sizeof (kb_all[0]), conflict_set_count);
hd = keydb_new ();
hd = keydb_new (ctrl);
for (i = 0, iter = conflict_set;
i < conflict_set_count;
i ++, iter = iter->next)

View File

@ -2015,7 +2015,7 @@ validate_keys (ctrl_t ctrl, int interactive)
trust. */
keydb_rebuild_caches (ctrl, 0);
kdb = keydb_new ();
kdb = keydb_new (ctrl);
if (!kdb)
return gpg_error_from_syserror ();