mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: First rough implementation of keyboxd access for key lookup.
* g10/Makefile.am: Add nPth flags. * g10/gpg.c: Include npth.h. (gpg_deinit_default_ctrl): Deinit call-keyboxd local data. (main): Init nPth. * g10/keydb-private.h (struct keydb_handle_s): Add field 'kbl' and remove the search result and the assuan context. * g10/call-keyboxd.c (struct keyboxd_local_s): Add more fields. (lock_datastream, unlock_datastream): New. (gpg_keyboxd_deinit_session_data): Adjust for changed data structures. (prepare_data_pipe): New. (open_context): Return kbl instead of an Assuan context. Init mutexes etc. (close_context): Merge into ... (keydb_release): here. Adjust for changed data structures. (datastream_thread): New. (keydb_get_keyblock): Implement datastream stuff. (keydb_search): Ditto. * common/asshelp.c (wait_for_sock): Add arg connect_flags. (start_new_service): Set FDPASSING flag for the keyboxd. -- This code as a lot of rough edges, in particular it relies on a well behaving keyboxd. We need to add code to shutdown the datastream reader thread in case of errors and to properly get it up again. We also need to make really sure that both threads run in lockstep so that the datastream thread is only active while we are sending a command to the keyboxd. We should also see whether we can depend nPth initialization on the --use-keyboxd option to avoid any problems with nPth. And we need to test on Windows. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
6c327b4dd6
commit
ce9906b008
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
/* Setup the pipe used for receiving data from the keyboxd. Store the
|
||||
* info on KBL. */
|
||||
static gpg_error_t
|
||||
open_context (ctrl_t ctrl, assuan_context_t *r_ctx)
|
||||
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_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 ();
|
||||
err = create_new_context (ctrl, &kbl->ctx);
|
||||
if (err)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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,13 +1032,50 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
|
||||
}
|
||||
|
||||
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->assuan_context, line,
|
||||
err = assuan_transact (hd->kbl->ctx, line,
|
||||
put_membuf_cb, &data,
|
||||
NULL, NULL,
|
||||
NULL, NULL);
|
||||
@ -830,8 +1092,8 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
14
g10/gpg.c
14
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)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user