summaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2019-09-27 15:44:23 +0200
committerWerner Koch <wk@gnupg.org>2019-09-27 15:44:23 +0200
commit9698761933f7ade732178b45df2a8763e5801763 (patch)
tree5454a013e219a64dfd0feaf701285a65b7cfa431 /g10
parentbuild: Build gpg-pair-tool only when there is newer libgcrypt. (diff)
parentkbx: Fix error code return in keyboxd. (diff)
downloadgnupg2-9698761933f7ade732178b45df2a8763e5801763.tar.xz
gnupg2-9698761933f7ade732178b45df2a8763e5801763.zip
Merge branch 'switch-to-gpgk' into master
-- Resolved Conflicts: * common/asshelp.c: Keep the new code in master for spawing under Windows. * g10/Makefile.am: Keep all new file. * g10/photoid.c: Pass CTRL to pct_expando. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'g10')
-rw-r--r--g10/Makefile.am38
-rw-r--r--g10/call-keyboxd.c1112
-rw-r--r--g10/decrypt-data.c2
-rw-r--r--g10/delkey.c6
-rw-r--r--g10/export.c2
-rw-r--r--g10/getkey.c34
-rw-r--r--g10/gpg.c35
-rw-r--r--g10/gpg.h12
-rw-r--r--g10/gpgcompose.c4
-rw-r--r--g10/import.c17
-rw-r--r--g10/keydb-private.h171
-rw-r--r--g10/keydb.c252
-rw-r--r--g10/keydb.h74
-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/objcache.c4
-rw-r--r--g10/options.h3
-rw-r--r--g10/photoid.c4
-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
28 files changed, 1520 insertions, 303 deletions
diff --git a/g10/Makefile.am b/g10/Makefile.am
index ba297cfc9..2b92daf33 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -29,9 +29,9 @@ AM_CPPFLAGS =
include $(top_srcdir)/am/cmacros.am
AM_CFLAGS = $(SQLITE3_CFLAGS) $(LIBGCRYPT_CFLAGS) \
- $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS)
+ $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS) $(GPG_ERROR_CFLAGS)
-needed_libs = ../kbx/libkeybox.a $(libcommon)
+needed_libs = ../kbx/libkeybox.a $(libcommonpth)
# Because there are no program specific transform macros we need to
# work around that to allow installing gpg as gpg2.
@@ -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 = \
@@ -100,7 +100,10 @@ common_source = \
free-packet.c \
getkey.c \
expand-group.c \
- keydb.c keydb.h \
+ keydb.h \
+ keydb-private.h \
+ call-keyboxd.c \
+ keydb.c \
keyring.c keyring.h \
seskey.c \
kbnode.c \
@@ -161,7 +164,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
@@ -176,33 +179,36 @@ gpgv_SOURCES = gpgv.c \
LDADD = $(needed_libs) ../common/libgpgrl.a \
$(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS)
gpg_LDADD = $(LDADD) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \
- $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
$(LIBICONV) $(resource_objs) $(extra_sys_libs)
gpg_LDFLAGS = $(extra_bin_ldflags)
gpgv_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
- $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_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) $(NPTH_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) $(NPTH_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) $(NPTH_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..88ad07817
--- /dev/null
+++ b/g10/call-keyboxd.c
@@ -0,0 +1,1112 @@
+/* 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 <npth.h>
+
+#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/host2net.h"
+#include "../common/exechelp.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 object is used if fd-passing is used to convey the
+ * keyblocks. */
+ struct {
+ /* NULL or a stream used to receive data. */
+ estream_t fp;
+
+ /* Condition variable to sync the datastream with the command. */
+ npth_mutex_t mutex;
+ npth_cond_t cond;
+
+ /* The found keyblock or the parsing error. */
+ kbnode_t found_keyblock;
+ gpg_error_t found_err;
+ } datastream;
+
+ /* I/O buffer with the last search result or NULL. Used if
+ * D-lines are used to convey the keyblocks. */
+ iobuf_t search_result;
+
+ /* 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;
+
+ /* Flag indicating that a search reset is required. */
+ unsigned int need_search_reset : 1;
+};
+
+
+/* Local prototypes. */
+static void *datastream_thread (void *arg);
+
+
+
+
+static void
+lock_datastream (keyboxd_local_t kbl)
+{
+ int rc = npth_mutex_lock (&kbl->datastream.mutex);
+ if (rc)
+ log_fatal ("%s: failed to acquire mutex: %s\n", __func__,
+ gpg_strerror (gpg_error_from_errno (rc)));
+}
+
+
+static void
+unlock_datastream (keyboxd_local_t kbl)
+{
+ int rc = npth_mutex_unlock (&kbl->datastream.mutex);
+ if (rc)
+ log_fatal ("%s: failed to release mutex: %s\n", __func__,
+ gpg_strerror (gpg_error_from_errno (rc)));
+}
+
+
+/* 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
+ {
+ es_fclose (kbl->datastream.fp);
+ kbl->datastream.fp = NULL;
+ assuan_release (kbl->ctx);
+ kbl->ctx = NULL;
+ }
+ 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;
+}
+
+
+
+/* Setup the pipe used for receiving data from the keyboxd. Store the
+ * info on KBL. */
+static gpg_error_t
+prepare_data_pipe (keyboxd_local_t kbl)
+{
+ gpg_error_t err;
+ int rc;
+ int inpipe[2];
+ estream_t infp;
+ npth_t thread;
+ npth_attr_t tattr;
+
+ err = gnupg_create_inbound_pipe (inpipe, &infp, 0);
+ if (err)
+ {
+ log_error ("error creating inbound pipe: %s\n", gpg_strerror (err));
+ return err; /* That should not happen. */
+ }
+
+ err = assuan_sendfd (kbl->ctx, INT2FD (inpipe[1]));
+ if (err)
+ {
+ log_error ("sending sending fd %d to keyboxd: %s <%s>\n",
+ inpipe[1], gpg_strerror (err), gpg_strsource (err));
+ es_fclose (infp);
+ close (inpipe[1]);
+ return 0; /* Server may not support fd-passing. */
+ }
+
+ err = assuan_transact (kbl->ctx, "OUTPUT FD",
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ if (err)
+ {
+ log_info ("keyboxd does not accept our fd: %s <%s>\n",
+ gpg_strerror (err), gpg_strsource (err));
+ es_fclose (infp);
+ return 0;
+ }
+
+ kbl->datastream.fp = infp;
+ kbl->datastream.found_keyblock = NULL;
+ kbl->datastream.found_err = 0;
+
+ rc = npth_attr_init (&tattr);
+ if (rc)
+ {
+ err = gpg_error_from_errno (rc);
+ log_error ("error preparing thread for keyboxd: %s\n",gpg_strerror (err));
+ es_fclose (infp);
+ kbl->datastream.fp = NULL;
+ return err;
+ }
+ npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
+ rc = npth_create (&thread, &tattr, datastream_thread, kbl);
+ if (rc)
+ {
+ err = gpg_error_from_errno (rc);
+ log_error ("error spawning thread for keyboxd: %s\n", gpg_strerror (err));
+ npth_attr_destroy (&tattr);
+ es_fclose (infp);
+ kbl->datastream.fp = NULL;
+ return err;
+ }
+
+ return 0;
+}
+
+
+/* Get a context for accessing keyboxd. If no context is available a
+ * new one is created and if necessary keyboxd is started. R_KBL
+ * receives a pointer to the local context object. */
+static gpg_error_t
+open_context (ctrl_t ctrl, keyboxd_local_t *r_kbl)
+{
+ gpg_error_t err;
+ int rc;
+ keyboxd_local_t kbl;
+
+ *r_kbl = 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)
+ {
+ err = prepare_data_pipe (kbl);
+ if (err)
+ return err;
+ kbl->per_session_init_done = 1;
+ }
+
+ kbl->is_active = 1;
+ kbl->need_search_reset = 1;
+
+ *r_kbl = kbl;
+ return 0;
+ }
+
+ /* None found. Create a new session and retry. */
+ kbl = xtrycalloc (1, sizeof *kbl);
+ if (!kbl)
+ return gpg_error_from_syserror ();
+
+ rc = npth_mutex_init (&kbl->datastream.mutex, NULL);
+ if (rc)
+ {
+ err = gpg_error_from_errno (rc);
+ log_error ("error initializing mutex: %s\n", gpg_strerror (err));
+ xfree (kbl);
+ return err;
+ }
+ rc = npth_cond_init (&kbl->datastream.cond, NULL);
+ if (rc)
+ {
+ err = gpg_error_from_errno (rc);
+ log_error ("error initializing condition: %s\n", gpg_strerror (err));
+ npth_mutex_destroy (&kbl->datastream.mutex);
+ xfree (kbl);
+ return err;
+ }
+
+ err = create_new_context (ctrl, &kbl->ctx);
+ if (err)
+ {
+ npth_cond_destroy (&kbl->datastream.cond);
+ npth_mutex_destroy (&kbl->datastream.mutex);
+ xfree (kbl);
+ return err;
+ }
+
+ /* For thread-saftey 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;
+ }
+ /*NOTREACHED*/
+}
+
+
+
+/* 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;
+
+ err = open_context (ctrl, &hd->kbl);
+
+ 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)
+{
+ keyboxd_local_t kbl;
+
+ if (!hd)
+ return;
+
+ if (DBG_CLOCK)
+ log_clock ("keydb_release");
+ if (!hd->use_keyboxd)
+ internal_keydb_deinit (hd);
+ else
+ {
+ kbl = hd->kbl;
+ if (DBG_CLOCK)
+ log_clock ("close_context (found)");
+ if (!kbl->is_active)
+ log_fatal ("closing inactive keyboxd context %p\n", kbl);
+ kbl->is_active = 0;
+ hd->kbl = NULL;
+ hd->ctrl = NULL;
+ }
+ 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;
+}
+
+
+/* The thread used to read from the data stream. This is running as
+ * long as the connection and its datastream exists. */
+static void *
+datastream_thread (void *arg)
+{
+ keyboxd_local_t kbl = arg;
+ gpg_error_t err;
+ int rc;
+ unsigned char lenbuf[4];
+ size_t nread, datalen;
+ iobuf_t iobuf;
+ int pk_no, uid_no;
+ kbnode_t keyblock, tmpkeyblock;
+
+
+ log_debug ("Datastream_thread started\n");
+ while (kbl->datastream.fp)
+ {
+ /* log_debug ("Datastream_thread waiting ...\n"); */
+ if (es_read (kbl->datastream.fp, lenbuf, 4, &nread))
+ {
+ err = gpg_error_from_syserror ();
+ if (gpg_err_code (err) == GPG_ERR_EAGAIN)
+ continue;
+ log_error ("error reading data length from keyboxd: %s\n",
+ gpg_strerror (err));
+ gnupg_sleep (1);
+ continue;
+ }
+ if (nread != 4)
+ {
+ err = gpg_error (GPG_ERR_EIO);
+ log_error ("error reading data length from keyboxd: %s\n",
+ "short read");
+ continue;
+ }
+
+ datalen = buf32_to_size_t (lenbuf);
+ /* log_debug ("keyboxd announced %zu bytes\n", datalen); */
+
+ iobuf = iobuf_esopen (kbl->datastream.fp, "rb", 1, datalen);
+ pk_no = uid_no = 0; /* FIXME: Get this from the keyboxd. */
+ err = keydb_get_keyblock_do_parse (iobuf, pk_no, uid_no, &keyblock);
+ iobuf_close (iobuf);
+ if (!err)
+ {
+ /* log_debug ("parsing datastream succeeded\n"); */
+
+ /* Thread-safe assignment to the result var: */
+ tmpkeyblock = kbl->datastream.found_keyblock;
+ kbl->datastream.found_keyblock = keyblock;
+ release_kbnode (tmpkeyblock);
+ }
+ else
+ {
+ /* log_debug ("parsing datastream failed: %s <%s>\n", */
+ /* gpg_strerror (err), gpg_strsource (err)); */
+ tmpkeyblock = kbl->datastream.found_keyblock;
+ kbl->datastream.found_keyblock = NULL;
+ kbl->datastream.found_err = err;
+ release_kbnode (tmpkeyblock);
+ }
+
+ /* Tell the main thread. */
+ lock_datastream (kbl);
+ rc = npth_cond_signal (&kbl->datastream.cond);
+ if (rc)
+ {
+ err = gpg_error_from_errno (rc);
+ log_error ("%s: signaling condition failed: %s\n",
+ __func__, gpg_strerror (err));
+ }
+ unlock_datastream (kbl);
+ }
+ log_debug ("Datastream_thread finished\n");
+
+ return NULL;
+}
+
+
+/* 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->kbl->search_result)
+ {
+ pk_no = uid_no = 0; /*FIXME: Get this from the keyboxd. */
+ err = keydb_get_keyblock_do_parse (hd->kbl->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->kbl->search_result);
+ hd->kbl->search_result = NULL;
+ }
+ else if (hd->kbl->datastream.found_keyblock)
+ {
+ *ret_kb = hd->kbl->datastream.found_keyblock;
+ hd->kbl->datastream.found_keyblock = NULL;
+ err = 0;
+ }
+ else
+ {
+ err = gpg_error (GPG_ERR_VALUE_NOT_FOUND);
+ goto leave;
+ }
+
+ 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->kbl->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;
+ }
+
+ /* Clear the result objects. */
+ if (hd->kbl->search_result)
+ {
+ iobuf_close (hd->kbl->search_result);
+ hd->kbl->search_result = NULL;
+ }
+ if (hd->kbl->datastream.found_keyblock)
+ {
+ release_kbnode (hd->kbl->datastream.found_keyblock);
+ hd->kbl->datastream.found_keyblock = NULL;
+ }
+
+ /* Check whether this is a NEXT search. */
+ if (!hd->kbl->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->kbl->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_UBID:
+ {
+ unsigned char hexubid[20 * 2 + 1];
+ bin2hex (desc[0].u.grip, 20, hexubid);
+ snprintf (line, sizeof line, "SEARCH ^%s", hexubid);
+ }
+ 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:
+ if (hd->kbl->datastream.fp)
+ {
+ /* log_debug ("Sending command '%s'\n", line); */
+ err = assuan_transact (hd->kbl->ctx, line,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL);
+ if (err)
+ {
+ /* log_debug ("Finished command with error: %s\n", gpg_strerror (err)); */
+ /* Fixme: On unexpected errors we need a way to cancek the
+ * data stream. Probly it will be best to closeand reopen
+ * it. */
+ }
+ else
+ {
+ int rc;
+
+ /* log_debug ("Finished command .. telling data stream\n"); */
+ lock_datastream (hd->kbl);
+ if (!hd->kbl->datastream.found_keyblock)
+ {
+ /* log_debug ("%s: waiting on datastream_cond ...\n", __func__); */
+ rc = npth_cond_wait (&hd->kbl->datastream.cond,
+ &hd->kbl->datastream.mutex);
+ /* log_debug ("%s: waiting on datastream.cond done\n", __func__); */
+ if (rc)
+ {
+ err = gpg_error_from_errno (rc);
+ log_error ("%s: waiting on condition failed: %s\n",
+ __func__, gpg_strerror (err));
+ }
+ }
+ unlock_datastream (hd->kbl);
+ }
+ }
+ else /* Slower D-line version if fd-passing was not successful. */
+ {
+ membuf_t data;
+ void *buffer;
+ size_t len;
+
+ init_membuf (&data, 8192);
+ err = assuan_transact (hd->kbl->ctx, 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;
+ }
+
+ hd->kbl->search_result = iobuf_temp_with_content (buffer, len);
+ xfree (buffer);
+ }
+
+
+ leave:
+ if (DBG_CLOCK)
+ log_clock ("%s leave (%sfound)", __func__, err? "not ":"");
+ return err;
+}
diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c
index c73d5fb45..5fd458845 100644
--- a/g10/decrypt-data.c
+++ b/g10/decrypt-data.c
@@ -475,7 +475,7 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
rc = get_output_file ("", 0, ed->buf, &filename, &fp);
if (! rc)
{
- iobuf_t output = iobuf_esopen (fp, "w", 0);
+ iobuf_t output = iobuf_esopen (fp, "w", 0, 0);
armor_filter_context_t *afx = NULL;
if (opt.armor)
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 98ed3b0e6..3517be72c 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 2bf42a677..de5024198 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;
@@ -807,7 +807,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 ();
@@ -1448,7 +1448,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 ();
@@ -1594,7 +1594,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 ();
@@ -1632,13 +1632,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)
@@ -1658,7 +1659,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;
@@ -1675,7 +1677,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 ();
@@ -1757,7 +1759,7 @@ parse_def_secret_key (ctrl_t ctrl)
if (! hd)
{
- hd = keydb_new ();
+ hd = keydb_new (ctrl);
if (!hd)
return NULL;
}
@@ -2732,7 +2734,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
@@ -4117,7 +4119,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;
@@ -4126,7 +4128,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 6da36c2d4..b9b6de4e6 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -36,6 +36,7 @@
# endif
# include <windows.h>
#endif
+#include <npth.h>
#define INCLUDED_BY_MAIN_MODULE 1
#include "gpg.h"
@@ -361,6 +362,7 @@ enum cmd_and_opt_values
oUseAgent,
oNoUseAgent,
oGpgAgentInfo,
+ oUseKeyboxd,
oMergeOnly,
oTryAllSecrets,
oTrustedKey,
@@ -378,6 +380,7 @@ enum cmd_and_opt_values
oPersonalDigestPreferences,
oPersonalCompressPreferences,
oAgentProgram,
+ oKeyboxdProgram,
oDirmngrProgram,
oDisableDirmngr,
oDisplay,
@@ -850,6 +853,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", "@"),
@@ -896,6 +900,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", "@"),
/* Options which can be used in special circumstances. They are not
* published and we hope they are never required. */
@@ -983,6 +988,9 @@ static void add_keyserver_url( const char *string, int which );
static void emergency_cleanup (void);
static void read_sessionkey_from_fd (int fd);
+/* NPth wrapper function definitions. */
+ASSUAN_SYSTEM_NPTH_IMPL;
+
static char *
make_libversion (const char *libname, const char *(*getfnc)(const char*))
@@ -2250,6 +2258,7 @@ gpg_deinit_default_ctrl (ctrl_t ctrl)
gpg_dirmngr_deinit_session_data (ctrl);
keydb_release (ctrl->cached_getkey_kdb);
+ gpg_keyboxd_deinit_session_data (ctrl);
}
@@ -2742,6 +2751,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;
@@ -3499,6 +3513,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:
@@ -3738,6 +3753,11 @@ main (int argc, char **argv)
}
#endif
+ /* Init threading which is used by some helper functions. */
+ npth_init ();
+ assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);
+ gpgrt_set_syscall_clamp (npth_unprotect, npth_protect);
+
/* FIXME: We should use logging to a file only in server mode;
however we have not yet implemetyed that. Thus we try to get
away with --batch as indication for logging to file
@@ -3745,7 +3765,9 @@ main (int argc, char **argv)
if (logfile && opt.batch)
{
log_set_file (logfile);
- log_set_prefix (NULL, GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_TIME | GPGRT_LOG_WITH_PID);
+ log_set_prefix (NULL, (GPGRT_LOG_WITH_PREFIX
+ | GPGRT_LOG_WITH_TIME
+ | GPGRT_LOG_WITH_PID ));
}
if (opt.verbose > 2)
@@ -4120,8 +4142,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)))
{
@@ -4133,9 +4157,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;
}
@@ -5089,7 +5112,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 867a9de29..47014b948 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -550,7 +550,7 @@ import_keys_es_stream (ctrl_t ctrl, estream_t fp,
gpg_error_t err;
iobuf_t inp;
- inp = iobuf_esopen (fp, "rb", 1);
+ inp = iobuf_esopen (fp, "rb", 1, 0);
if (!inp)
{
err = gpg_error_from_syserror ();
@@ -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..efef82289
--- /dev/null
+++ b/g10/keydb-private.h
@@ -0,0 +1,171 @@
+/* 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;
+
+ /* Connection info which also keep the local state. (This is points
+ * into the CTRL->keybox_local list.) */
+ keyboxd_local_t kbl;
+
+ /* 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 92e5faae8..aeb62abfc 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);
@@ -448,7 +365,7 @@ maybe_create_keyring_or_box (char *filename, int is_box, int force_create)
rc = gpg_error_from_syserror ();
else
{
- rc = _keybox_write_header_blob (fp, 1);
+ rc = _keybox_write_header_blob (fp, NULL, 1);
fclose (fp);
}
if (rc)
@@ -539,6 +456,10 @@ keydb_search_desc_dump (struct keydb_search_desc *desc)
char b[MAX_FORMATTED_FINGERPRINT_LEN + 1];
char fpr[2 * MAX_FINGERPRINT_LEN + 1];
+#if MAX_FINGERPRINT_LEN < 20
+#error MAX_FINGERPRINT_LEN shorter than GRIP and UBID length/
+#endif
+
switch (desc->mode)
{
case KEYDB_SEARCH_MODE_EXACT:
@@ -578,7 +499,11 @@ keydb_search_desc_dump (struct keydb_search_desc *desc)
case KEYDB_SEARCH_MODE_SUBJECT:
return xasprintf ("SUBJECT: '%s'", desc->u.name);
case KEYDB_SEARCH_MODE_KEYGRIP:
- return xasprintf ("KEYGRIP: %s", desc->u.grip);
+ bin2hex (desc[0].u.grip, 20, fpr);
+ return xasprintf ("KEYGRIP: %s", fpr);
+ case KEYDB_SEARCH_MODE_UBID:
+ bin2hex (desc[0].u.ubid, 20, fpr);
+ return xasprintf ("UBID: %s", fpr);
case KEYDB_SEARCH_MODE_FIRST:
return xasprintf ("FIRST");
case KEYDB_SEARCH_MODE_NEXT:
@@ -888,26 +813,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;
@@ -949,28 +865,21 @@ keydb_new (void)
keydb_stats.handles++;
if (die)
- {
- keydb_release (hd);
- gpg_err_set_errno (reterrno);
- hd = NULL;
- }
-
- leave:
- if (!hd)
- log_error (_("error opening key DB: %s\n"),
- gpg_strerror (gpg_error_from_syserror()));
+ err = gpg_error_from_errno (reterrno);
- 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--;
@@ -992,19 +901,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)
@@ -1020,7 +927,7 @@ keydb_lock (KEYDB_HANDLE hd)
void
keydb_disable_caching (KEYDB_HANDLE hd)
{
- if (hd)
+ if (hd && !hd->use_keyboxd)
hd->no_caching = 1;
}
@@ -1042,6 +949,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)
@@ -1165,6 +1075,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)
{
@@ -1196,6 +1108,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)
{
@@ -1360,6 +1274,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
@@ -1369,17 +1284,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)
{
@@ -1398,8 +1307,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;
}
}
@@ -1447,9 +1355,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;
}
@@ -1498,6 +1403,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.
*
@@ -1512,20 +1418,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);
@@ -1588,6 +1490,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
@@ -1598,13 +1501,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);
@@ -1663,12 +1565,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);
@@ -1721,6 +1622,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;
@@ -1772,6 +1676,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))
@@ -1794,38 +1701,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;
@@ -1853,6 +1755,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
@@ -1870,21 +1773,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)
{
@@ -1892,26 +1790,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);
}
@@ -1939,7 +1822,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.
@@ -2029,9 +1912,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 6fbc432fd..f94b14659 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -169,6 +169,41 @@ is_in_klist (struct key_item *k, PKT_signature *sig)
}
+/*-- call-keyboxd.c --*/
+
+/* Release all open contexts to the keyboxd. */
+void gpg_keyboxd_deinit_session_data (ctrl_t ctrl);
+
+/* 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 --*/
@@ -187,17 +222,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. */
@@ -212,18 +236,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);
@@ -234,13 +246,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);
@@ -331,7 +336,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. */
@@ -391,13 +396,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);
@@ -405,7 +411,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 b66ae9548..2ac52d315 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 1e5722fb2..61682158e 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -4502,7 +4502,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;
@@ -5371,7 +5371,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 bbe66831c..dacc13788 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -524,7 +524,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 c63f61c30..c2e304f09 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -1195,7 +1195,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/objcache.c b/g10/objcache.c
index adb0717d7..a90b4d9d8 100644
--- a/g10/objcache.c
+++ b/g10/objcache.c
@@ -30,8 +30,8 @@
#include "options.h"
#include "objcache.h"
-/* Note that max value for uid_items is actually a the threshold when
- * we start to look for ietms which can be removed. */
+/* Note that max value for uid_items is actually the threshold when
+ * we start to look for items which can be removed. */
#define NO_OF_UID_ITEM_BUCKETS 107
#define MAX_UID_ITEMS_PER_BUCKET 20
diff --git a/g10/options.h b/g10/options.h
index 6285542b8..26c8439b6 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;
@@ -287,6 +288,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 477b641c6..f7ada2729 100644
--- a/g10/photoid.c
+++ b/g10/photoid.c
@@ -667,8 +667,8 @@ show_photos (ctrl_t ctrl, const struct user_attribute *attrs, int count,
int offset = attrs[i].len-len;
/* make command grow */
- command = pct_expando (opt.photo_viewer, &args);
- if (!command)
+ command = pct_expando (ctrl, opt.photo_viewer,&args);
+ if(!command)
goto fail;
name = xmalloc (1 + 16 + strlen(EXTSEP_S)
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 691c3d6d1..250c0cfeb 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;
@@ -99,7 +99,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"));
@@ -126,7 +126,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 "
@@ -149,7 +149,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"
@@ -838,7 +838,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);
@@ -1664,7 +1664,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 bd1dad8f5..64e6ec349 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -2017,7 +2017,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 ();