aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/asshelp.c22
-rw-r--r--g10/Makefile.am14
-rw-r--r--g10/call-keyboxd.c420
-rw-r--r--g10/gpg.c14
-rw-r--r--g10/keydb-private.h11
-rw-r--r--g10/keydb.h3
6 files changed, 380 insertions, 104 deletions
diff --git a/common/asshelp.c b/common/asshelp.c
index a5724fad5..174933a83 100644
--- a/common/asshelp.c
+++ b/common/asshelp.c
@@ -310,14 +310,15 @@ unlock_spawning (lock_spawn_t *lock, const char *name)
}
-/* Helper to start a service.
- * SECS gives the number of seconds to wait. SOCKNAME is the name of
- * the socket to connect. VERBOSE is the usual verbose flag. CTX is
- * the assuan context. DID_SUCCESS_MSG will be set to 1 if a success
- * messages has been printed.
+/* Helper to start a service. SECS gives the number of seconds to
+ * wait. SOCKNAME is the name of the socket to connect. VERBOSE is
+ * the usual verbose flag. CTX is the assuan context. CONNECT_FLAGS
+ * are the assuan connect flags. DID_SUCCESS_MSG will be set to 1 if
+ * a success messages has been printed.
*/
static gpg_error_t
wait_for_sock (int secs, int module_name_id, const char *sockname,
+ unsigned int connect_flags,
int verbose, assuan_context_t ctx, int *did_success_msg)
{
gpg_error_t err = 0;
@@ -353,7 +354,7 @@ wait_for_sock (int secs, int module_name_id, const char *sockname,
}
gnupg_usleep (next_sleep_us);
elapsed_us += next_sleep_us;
- err = assuan_socket_connect (ctx, sockname, 0, 0);
+ err = assuan_socket_connect (ctx, sockname, 0, connect_flags);
if (!err)
{
if (verbose)
@@ -403,6 +404,7 @@ start_new_service (assuan_context_t *r_ctx,
const char *status_start_line;
int no_service_err;
int seconds_to_wait;
+ unsigned int connect_flags = 0;
const char *argv[6];
*r_ctx = NULL;
@@ -439,6 +441,7 @@ start_new_service (assuan_context_t *r_ctx,
status_start_line = "starting_keyboxd ? 0 0";
no_service_err = GPG_ERR_NO_KEYBOXD;
seconds_to_wait = SECS_TO_WAIT_FOR_KEYBOXD;
+ connect_flags |= ASSUAN_SOCKET_CONNECT_FDPASSING;
break;
default:
err = gpg_error (GPG_ERR_INV_ARG);
@@ -446,7 +449,7 @@ start_new_service (assuan_context_t *r_ctx,
return err;
}
- err = assuan_socket_connect (ctx, sockname, 0, 0);
+ err = assuan_socket_connect (ctx, sockname, 0, connect_flags);
if (err && autostart)
{
char *abs_homedir;
@@ -522,7 +525,7 @@ start_new_service (assuan_context_t *r_ctx,
argv[i++] = NULL;
if (!(err = lock_spawning (&lock, gnupg_homedir (), lock_name, verbose))
- && assuan_socket_connect (ctx, sockname, 0, 0))
+ && assuan_socket_connect (ctx, sockname, 0, connect_flags))
{
err = gnupg_spawn_process_detached (program? program : program_name,
argv, NULL);
@@ -532,7 +535,8 @@ start_new_service (assuan_context_t *r_ctx,
gpg_strerror (err));
else
err = wait_for_sock (seconds_to_wait, module_name_id,
- sockname, verbose, ctx, &did_success_msg);
+ sockname, connect_flags,
+ verbose, ctx, &did_success_msg);
}
unlock_spawning (&lock, lock_name);
diff --git a/g10/Makefile.am b/g10/Makefile.am
index 1404014e9..fd2cd21b9 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.
@@ -178,11 +178,11 @@ 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) \
- $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
$(LIBICONV) $(resource_objs) $(extra_sys_libs)
gpgv_LDFLAGS = $(extra_bin_ldflags)
@@ -197,17 +197,17 @@ 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) \
- $(LIBASSUAN_LIBS) $(GPG_ERROR_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) \
- $(LIBASSUAN_LIBS) $(GPG_ERROR_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) \
- $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
$(LIBICONV) $(t_common_ldadd)
diff --git a/g10/call-keyboxd.c b/g10/call-keyboxd.c
index f05a9e85f..97f84c03d 100644
--- a/g10/call-keyboxd.c
+++ b/g10/call-keyboxd.c
@@ -28,6 +28,7 @@
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
+#include <npth.h>
#include "gpg.h"
#include <assuan.h>
@@ -36,6 +37,8 @@
#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"
@@ -54,17 +57,63 @@ struct keyboxd_local_s
/* 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)
@@ -77,7 +126,12 @@ gpg_keyboxd_deinit_session_data (ctrl_t ctrl)
if (kbl->is_active)
log_error ("oops: trying to cleanup an active keyboxd context\n");
else
- assuan_release (kbl->ctx);
+ {
+ es_fclose (kbl->datastream.fp);
+ kbl->datastream.fp = NULL;
+ assuan_release (kbl->ctx);
+ kbl->ctx = NULL;
+ }
xfree (kbl);
}
}
@@ -165,18 +219,86 @@ create_new_context (ctrl_t ctrl, assuan_context_t *r_ctx)
}
+
+/* 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. 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. */
+ * 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, assuan_context_t *r_ctx)
+open_context (ctrl_t ctrl, keyboxd_local_t *r_kbl)
{
gpg_error_t err;
+ int rc;
keyboxd_local_t kbl;
- *r_ctx = NULL;
+ *r_kbl = NULL;
for (;;)
{
for (kbl = ctrl->keyboxd_local; kbl && kbl->is_active; kbl = kbl->next)
@@ -189,12 +311,16 @@ open_context (ctrl_t ctrl, assuan_context_t *r_ctx)
/* 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_ctx = kbl->ctx;
+ *r_kbl = kbl;
return 0;
}
@@ -202,43 +328,40 @@ open_context (ctrl_t ctrl, assuan_context_t *r_ctx)
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;
}
- /* 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. */
+ /* 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;
}
-}
-
-
-/* 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);
+ /*NOTREACHED*/
}
@@ -275,11 +398,8 @@ keydb_new (ctrl_t ctrl)
}
hd->use_keyboxd = 1;
hd->ctrl = ctrl;
- hd->need_search_reset = 1;
- err = open_context (ctrl, &hd->assuan_context);
- if (err)
- goto leave;
+ err = open_context (ctrl, &hd->kbl);
leave:
if (err)
@@ -300,14 +420,25 @@ keydb_new (ctrl_t ctrl)
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
{
- close_context (hd->ctrl, hd->assuan_context);
+ 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);
}
@@ -465,6 +596,86 @@ keydb_get_keyblock_do_parse (iobuf_t iobuf, int pk_no, int uid_no,
}
+/* 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
@@ -494,20 +705,28 @@ keydb_get_keyblock (KEYDB_HANDLE hd, kbnode_t *ret_kb)
goto leave;
}
- if (!hd->search_result)
+ 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;
}
- 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)":"");
@@ -636,7 +855,7 @@ keydb_search_reset (KEYDB_HANDLE hd)
/* 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;
+ hd->kbl->need_search_reset = 1;
err = 0;
leave:
@@ -697,14 +916,20 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
goto leave;
}
-
- if (hd->search_result)
+ /* Clear the result objects. */
+ if (hd->kbl->search_result)
{
- iobuf_close (hd->search_result);
- hd->search_result = NULL;
+ 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;
}
- if (!hd->need_search_reset)
+ /* 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
@@ -717,7 +942,7 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
goto do_search;
}
- hd->need_search_reset = 0;
+ hd->kbl->need_search_reset = 0;
if (!ndesc)
{
@@ -807,31 +1032,68 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
}
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;
- }
+ 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;
- buffer = get_membuf (&data, &len);
- if (!buffer)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
+ /* 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;
+ }
- /* Fixme: Avoid double allocation. */
- hd->search_result = iobuf_temp_with_content (buffer, len);
+ hd->kbl->search_result = iobuf_temp_with_content (buffer, len);
+ xfree (buffer);
}
diff --git a/g10/gpg.c b/g10/gpg.c
index 145796cbc..821d3959b 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"
@@ -979,6 +980,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*))
@@ -2246,6 +2250,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);
}
@@ -3736,6 +3741,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
@@ -3743,7 +3753,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)
diff --git a/g10/keydb-private.h b/g10/keydb-private.h
index c5315b991..efef82289 100644
--- a/g10/keydb-private.h
+++ b/g10/keydb-private.h
@@ -92,14 +92,9 @@ struct keydb_handle_s
/* 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;
+ /* Connection info which also keep the local state. (This is points
+ * into the CTRL->keybox_local list.) */
+ keyboxd_local_t kbl;
/* END USE_KEYBOXD */
diff --git a/g10/keydb.h b/g10/keydb.h
index 25304ed25..cc6f05956 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -165,6 +165,9 @@ 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);