summaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2019-09-09 14:34:09 +0200
committerWerner Koch <wk@gnupg.org>2019-09-09 15:01:47 +0200
commitaba82684fe14289cf62b4694bc398f3a274b4762 (patch)
treeb66c13bcb29f62f64c4aaa603d510b0fd65cb7cc /g10
parentkbx: Fix keyboxd search first. (diff)
downloadgnupg2-aba82684fe14289cf62b4694bc398f3a274b4762.tar.xz
gnupg2-aba82684fe14289cf62b4694bc398f3a274b4762.zip
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>
Diffstat (limited to 'g10')
-rw-r--r--g10/Makefile.am32
-rw-r--r--g10/call-keyboxd.c842
-rw-r--r--g10/delkey.c6
-rw-r--r--g10/export.c2
-rw-r--r--g10/getkey.c34
-rw-r--r--g10/gpg.c21
-rw-r--r--g10/gpg.h12
-rw-r--r--g10/gpgcompose.c4
-rw-r--r--g10/import.c15
-rw-r--r--g10/keydb-private.h176
-rw-r--r--g10/keydb.c240
-rw-r--r--g10/keydb.h71
-rw-r--r--g10/keyedit.c6
-rw-r--r--g10/keygen.c4
-rw-r--r--g10/keylist.c2
-rw-r--r--g10/keyserver.c2
-rw-r--r--g10/main.h2
-rw-r--r--g10/misc.c4
-rw-r--r--g10/options.h3
-rw-r--r--g10/photoid.c2
-rw-r--r--g10/revoke.c4
-rw-r--r--g10/sign.c12
-rw-r--r--g10/t-keydb-get-keyblock.c6
-rw-r--r--g10/t-keydb.c7
-rw-r--r--g10/tofu.c2
-rw-r--r--g10/trustdb.c2
26 files changed, 1221 insertions, 292 deletions
diff --git a/g10/Makefile.am b/g10/Makefile.am
index 884b4749b..1404014e9 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -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)
diff --git a/g10/call-keyboxd.c b/g10/call-keyboxd.c
new file mode 100644
index 000000000..f05a9e85f
--- /dev/null
+++ b/g10/call-keyboxd.c
@@ -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;
+}
diff --git a/g10/delkey.c b/g10/delkey.c
index b5ab47434..8a7144ace 100644
--- a/g10/delkey.c
+++ b/g10/delkey.c
@@ -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);
diff --git a/g10/export.c b/g10/export.c
index e8bf14cf5..15861cc0d 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -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 ();
diff --git a/g10/getkey.c b/g10/getkey.c
index 57617a0a9..2cc56cdbd 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -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);
diff --git a/g10/gpg.c b/g10/gpg.c
index 0bbe72394..145796cbc 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -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));
diff --git a/g10/gpg.h b/g10/gpg.h
index 28a77b6df..adb919d7d 100644
--- a/g10/gpg.h
+++ b/g10/gpg.h
@@ -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;
diff --git a/g10/gpgcompose.c b/g10/gpgcompose.c
index 7b7e1dc9a..43cecb90e 100644
--- a/g10/gpgcompose.c
+++ b/g10/gpgcompose.c
@@ -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)
diff --git a/g10/import.c b/g10/import.c
index c32dbf059..cab36e0b2 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -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);
}
diff --git a/g10/keydb-private.h b/g10/keydb-private.h
new file mode 100644
index 000000000..c5315b991
--- /dev/null
+++ b/g10/keydb-private.h
@@ -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*/
diff --git a/g10/keydb.c b/g10/keydb.c
index d3a2709bc..6ca239475 100644
--- a/g10/keydb.c
+++ b/g10/keydb.c
@@ -37,25 +37,10 @@
#include "keydb.h"
#include "../common/i18n.h"
-static int active_handles;
+#include "keydb-private.h" /* For struct keydb_handle_s */
-typedef enum
- {
- KEYDB_RESOURCE_TYPE_NONE = 0,
- KEYDB_RESOURCE_TYPE_KEYRING,
- KEYDB_RESOURCE_TYPE_KEYBOX
- } KeydbResourceType;
-#define MAX_KEYDB_RESOURCES 40
+static int active_handles;
-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
diff --git a/g10/keydb.h b/g10/keydb.h
index 6ad8dce4c..25304ed25 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -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. */
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 1bf5de9b2..9238d5d53 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -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)
{
diff --git a/g10/keygen.c b/g10/keygen.c
index d9037d29d..5aeda36ce 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -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
diff --git a/g10/keylist.c b/g10/keylist.c
index 1274775d2..5f5fe9d34 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -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
diff --git a/g10/keyserver.c b/g10/keyserver.c
index b07afb128..030bc9297 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -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 ();
diff --git a/g10/main.h b/g10/main.h
index f45b03909..981315a4a 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -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);
diff --git a/g10/misc.c b/g10/misc.c
index 0541d2b77..c2d5bbb8e 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -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));
diff --git a/g10/options.h b/g10/options.h
index 234929b15..bfa2cc31e 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -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
diff --git a/g10/photoid.c b/g10/photoid.c
index f9720d329..9bb4ab58f 100644
--- a/g10/photoid.c
+++ b/g10/photoid.c
@@ -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;
diff --git a/g10/revoke.c b/g10/revoke.c
index 0a93c31f9..0e39eca61 100644
--- a/g10/revoke.c
+++ b/g10/revoke.c
@@ -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 ();
diff --git a/g10/sign.c b/g10/sign.c
index d71580639..8c70b0a2e 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -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
diff --git a/g10/t-keydb-get-keyblock.c b/g10/t-keydb-get-keyblock.c
index 167a9bbee..90ce6e9a6 100644
--- a/g10/t-keydb-get-keyblock.c
+++ b/g10/t-keydb-get-keyblock.c
@@ -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);
}
diff --git a/g10/t-keydb.c b/g10/t-keydb.c
index 5eb8d0154..4c78dac48 100644
--- a/g10/t-keydb.c
+++ b/g10/t-keydb.c
@@ -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);
}
diff --git a/g10/tofu.c b/g10/tofu.c
index e78da15c1..2eda1ff30 100644
--- a/g10/tofu.c
+++ b/g10/tofu.c
@@ -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)
diff --git a/g10/trustdb.c b/g10/trustdb.c
index a230a6c03..352aecede 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -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 ();