summaryrefslogtreecommitdiffstats
path: root/common
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 /common
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 'common')
-rw-r--r--common/asshelp.c331
-rw-r--r--common/asshelp.h18
-rw-r--r--common/asshelp2.c56
-rw-r--r--common/homedir.c18
-rw-r--r--common/iobuf.c37
-rw-r--r--common/iobuf.h6
-rw-r--r--common/t-mbox-util.c6
-rw-r--r--common/userids.c14
-rw-r--r--common/util.h6
9 files changed, 312 insertions, 180 deletions
diff --git a/common/asshelp.c b/common/asshelp.c
index 88d18478d..83c378786 100644
--- a/common/asshelp.c
+++ b/common/asshelp.c
@@ -56,9 +56,11 @@
operation after we started them before giving up. */
#ifdef HAVE_W32CE_SYSTEM
# define SECS_TO_WAIT_FOR_AGENT 30
+# define SECS_TO_WAIT_FOR_KEYBOXD 30
# define SECS_TO_WAIT_FOR_DIRMNGR 30
#else
# define SECS_TO_WAIT_FOR_AGENT 5
+# define SECS_TO_WAIT_FOR_KEYBOXD 5
# define SECS_TO_WAIT_FOR_DIRMNGR 5
#endif
@@ -308,17 +310,15 @@ unlock_spawning (lock_spawn_t *lock, const char *name)
}
-/* Helper for start_new_gpg_agent and start_new_dirmngr.
- * Values for WHICH are:
- * 0 - Start gpg-agent
- * 1 - Start dirmngr
- * SECS give 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 which, const char *sockname,
+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;
@@ -343,8 +343,10 @@ wait_for_sock (int secs, int which, const char *sockname,
/* next_sleep_us); */
if (secsleft < lastalert)
{
- log_info (which == 1?
+ log_info (module_name_id == GNUPG_MODULE_NAME_DIRMNGR?
_("waiting for the dirmngr to come up ... (%ds)\n"):
+ module_name_id == GNUPG_MODULE_NAME_KEYBOXD?
+ _("waiting for the keyboxd to come up ... (%ds)\n"):
_("waiting for the agent to come up ... (%ds)\n"),
secsleft);
lastalert = secsleft;
@@ -352,13 +354,15 @@ wait_for_sock (int secs, int which, 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)
{
- log_info (which == 1?
+ log_info (module_name_id == GNUPG_MODULE_NAME_DIRMNGR?
_("connection to the dirmngr established\n"):
+ module_name_id == GNUPG_MODULE_NAME_KEYBOXD?
+ _("connection to the keyboxd established\n"):
_("connection to the agent established\n"));
*did_success_msg = 1;
}
@@ -372,25 +376,35 @@ wait_for_sock (int secs, int which, const char *sockname,
}
-/* Try to connect to the agent via socket or start it if it is not
- running and AUTOSTART is set. Handle the server's initial
- greeting. Returns a new assuan context at R_CTX or an error
- code. */
-gpg_error_t
-start_new_gpg_agent (assuan_context_t *r_ctx,
- gpg_err_source_t errsource,
- const char *agent_program,
- const char *opt_lc_ctype,
- const char *opt_lc_messages,
- session_env_t session_env,
- int autostart, int verbose, int debug,
- gpg_error_t (*status_cb)(ctrl_t, int, ...),
- ctrl_t status_cb_arg)
+/* Try to connect to a new service via socket or start it if it is not
+ * running and AUTOSTART is set. Handle the server's initial
+ * greeting. Returns a new assuan context at R_CTX or an error code.
+ * MODULE_NAME_ID is one of:
+ * GNUPG_MODULE_NAME_AGENT
+ * GNUPG_MODULE_NAME_DIRMNGR
+ */
+static gpg_error_t
+start_new_service (assuan_context_t *r_ctx,
+ int module_name_id,
+ gpg_err_source_t errsource,
+ const char *program_name,
+ const char *opt_lc_ctype,
+ const char *opt_lc_messages,
+ session_env_t session_env,
+ int autostart, int verbose, int debug,
+ gpg_error_t (*status_cb)(ctrl_t, int, ...),
+ ctrl_t status_cb_arg)
{
gpg_error_t err;
assuan_context_t ctx;
int did_success_msg = 0;
char *sockname;
+ const char *printed_name;
+ const char *lock_name;
+ 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;
@@ -402,15 +416,40 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
return err;
}
- sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
- if (!sockname)
+ switch (module_name_id)
{
- err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
+ case GNUPG_MODULE_NAME_AGENT:
+ sockname = make_filename (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
+ lock_name = "agent";
+ printed_name = "gpg-agent";
+ status_start_line = "starting_agent ? 0 0";
+ no_service_err = GPG_ERR_NO_AGENT;
+ seconds_to_wait = SECS_TO_WAIT_FOR_AGENT;
+ break;
+ case GNUPG_MODULE_NAME_DIRMNGR:
+ sockname = make_filename (gnupg_socketdir (), DIRMNGR_SOCK_NAME, NULL);
+ lock_name = "dirmngr";
+ printed_name = "dirmngr";
+ status_start_line = "starting_dirmngr ? 0 0";
+ no_service_err = GPG_ERR_NO_DIRMNGR;
+ seconds_to_wait = SECS_TO_WAIT_FOR_DIRMNGR;
+ break;
+ case GNUPG_MODULE_NAME_KEYBOXD:
+ sockname = make_filename (gnupg_socketdir (), KEYBOXD_SOCK_NAME, NULL);
+ lock_name = "keyboxd";
+ printed_name = "keyboxd";
+ 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);
assuan_release (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;
@@ -422,12 +461,12 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
int i;
/* With no success start a new server. */
- if (!agent_program || !*agent_program)
- agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT);
- else if ((s=strchr (agent_program, '|')) && s[1] == '-' && s[2]=='-')
+ if (!program_name || !*program_name)
+ program_name = gnupg_module_name (module_name_id);
+ else if ((s=strchr (program_name, '|')) && s[1] == '-' && s[2]=='-')
{
/* Hack to insert an additional option on the command line. */
- program = xtrystrdup (agent_program);
+ program = xtrystrdup (program_name);
if (!program)
{
gpg_error_t tmperr = gpg_err_make (errsource,
@@ -442,22 +481,21 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
}
if (verbose)
- log_info (_("no running gpg-agent - starting '%s'\n"),
- agent_program);
+ log_info (_("no running %s - starting '%s'\n"),
+ printed_name, program_name);
if (status_cb)
- status_cb (status_cb_arg, STATUS_PROGRESS,
- "starting_agent ? 0 0", NULL);
+ status_cb (status_cb_arg, STATUS_PROGRESS, status_start_line, NULL);
- /* We better pass an absolute home directory to the agent just
- in case gpg-agent does not convert the passed name to an
- absolute one (which it should do). */
+ /* We better pass an absolute home directory to the service just
+ * in case the service does not convert the passed name to an
+ * absolute one (which it should do). */
abs_homedir = make_absfilename_try (gnupg_homedir (), NULL);
if (!abs_homedir)
{
gpg_error_t tmperr = gpg_err_make (errsource,
gpg_err_code_from_syserror ());
- log_error ("error building filename: %s\n",gpg_strerror (tmperr));
+ log_error ("error building filename: %s\n", gpg_strerror (tmperr));
xfree (sockname);
assuan_release (ctx);
xfree (program);
@@ -468,8 +506,7 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
{
gpg_error_t tmperr = gpg_err_make (errsource,
gpg_err_code_from_syserror ());
- log_error ("error flushing pending output: %s\n",
- strerror (errno));
+ log_error ("error flushing pending output: %s\n", strerror (errno));
xfree (sockname);
assuan_release (ctx);
xfree (abs_homedir);
@@ -477,42 +514,42 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
return tmperr;
}
- /* If the agent has been configured for use with a standard
- socket, an environment variable is not required and thus
- we can safely start the agent here. */
i = 0;
argv[i++] = "--homedir";
argv[i++] = abs_homedir;
- argv[i++] = "--use-standard-socket";
+ if (module_name_id == GNUPG_MODULE_NAME_AGENT)
+ argv[i++] = "--use-standard-socket";
if (program_arg)
argv[i++] = program_arg;
argv[i++] = "--daemon";
argv[i++] = NULL;
- if (!(err = lock_spawning (&lock, gnupg_homedir (), "agent", verbose))
- && assuan_socket_connect (ctx, sockname, 0, 0))
+ if (!(err = lock_spawning (&lock, gnupg_homedir (), lock_name, verbose))
+ && assuan_socket_connect (ctx, sockname, 0, connect_flags))
{
#ifdef HAVE_W32_SYSTEM
- err = gnupg_spawn_process_detached (program? program : agent_program,
+ err = gnupg_spawn_process_detached (program? program : program_name,
argv, NULL);
-#else
+#else /*!W32*/
pid_t pid;
- err = gnupg_spawn_process_fd (program? program : agent_program,
+ err = gnupg_spawn_process_fd (program? program : program_name,
argv, -1, -1, -1, &pid);
if (!err)
- err = gnupg_wait_process (program? program : agent_program,
+ err = gnupg_wait_process (program? program : program_name,
pid, 1, NULL);
-#endif
+#endif /*!W32*/
if (err)
- log_error ("failed to start agent '%s': %s\n",
- agent_program, gpg_strerror (err));
+ log_error ("failed to start %s '%s': %s\n",
+ printed_name, program? program : program_name,
+ gpg_strerror (err));
else
- err = wait_for_sock (SECS_TO_WAIT_FOR_AGENT, 0,
- sockname, verbose, ctx, &did_success_msg);
+ err = wait_for_sock (seconds_to_wait, module_name_id,
+ sockname, connect_flags,
+ verbose, ctx, &did_success_msg);
}
- unlock_spawning (&lock, "agent");
+ unlock_spawning (&lock, lock_name);
xfree (abs_homedir);
xfree (program);
}
@@ -520,17 +557,21 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
if (err)
{
if (autostart || gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED)
- log_error ("can't connect to the agent: %s\n", gpg_strerror (err));
+ log_error ("can't connect to the %s: %s\n",
+ printed_name, gpg_strerror (err));
assuan_release (ctx);
- return gpg_err_make (errsource, GPG_ERR_NO_AGENT);
+ return gpg_err_make (errsource, no_service_err);
}
if (debug && !did_success_msg)
- log_debug ("connection to the agent established\n");
+ log_debug ("connection to the %s established\n", printed_name);
+
+ if (module_name_id == GNUPG_MODULE_NAME_AGENT)
+ err = assuan_transact (ctx, "RESET",
+ NULL, NULL, NULL, NULL, NULL, NULL);
- err = assuan_transact (ctx, "RESET",
- NULL, NULL, NULL, NULL, NULL, NULL);
- if (!err)
+ if (!err
+ && module_name_id == GNUPG_MODULE_NAME_AGENT)
{
err = send_pinentry_environment (ctx, errsource,
opt_lc_ctype, opt_lc_messages,
@@ -538,7 +579,7 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
if (gpg_err_code (err) == GPG_ERR_FORBIDDEN
&& gpg_err_source (err) == GPG_ERR_SOURCE_GPGAGENT)
{
- /* Check whether we are in restricted mode. */
+ /* Check whether the agent is in restricted mode. */
if (!assuan_transact (ctx, "GETINFO restricted",
NULL, NULL, NULL, NULL, NULL, NULL))
{
@@ -559,126 +600,64 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
}
+/* Try to connect tothe agent or start a new one. */
+gpg_error_t
+start_new_gpg_agent (assuan_context_t *r_ctx,
+ gpg_err_source_t errsource,
+ const char *agent_program,
+ const char *opt_lc_ctype,
+ const char *opt_lc_messages,
+ session_env_t session_env,
+ int autostart, int verbose, int debug,
+ gpg_error_t (*status_cb)(ctrl_t, int, ...),
+ ctrl_t status_cb_arg)
+{
+ return start_new_service (r_ctx, GNUPG_MODULE_NAME_AGENT,
+ errsource, agent_program,
+ opt_lc_ctype, opt_lc_messages, session_env,
+ autostart, verbose, debug,
+ status_cb, status_cb_arg);
+}
+
+
/* Try to connect to the dirmngr via a socket. On platforms
supporting it, start it up if needed and if AUTOSTART is true.
Returns a new assuan context at R_CTX or an error code. */
gpg_error_t
-start_new_dirmngr (assuan_context_t *r_ctx,
+start_new_keyboxd (assuan_context_t *r_ctx,
gpg_err_source_t errsource,
- const char *dirmngr_program,
- int autostart,
- int verbose, int debug,
+ const char *keyboxd_program,
+ int autostart, int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg)
{
- gpg_error_t err;
- assuan_context_t ctx;
- const char *sockname;
- int did_success_msg = 0;
-
- *r_ctx = NULL;
-
- err = assuan_new (&ctx);
- if (err)
- {
- log_error ("error allocating assuan context: %s\n", gpg_strerror (err));
- return err;
- }
-
- sockname = dirmngr_socket_name ();
- err = assuan_socket_connect (ctx, sockname, 0, 0);
-
-#ifdef USE_DIRMNGR_AUTO_START
- if (err && autostart)
- {
- lock_spawn_t lock;
- const char *argv[4];
- char *abs_homedir;
-
- /* No connection: Try start a new Dirmngr. */
- if (!dirmngr_program || !*dirmngr_program)
- dirmngr_program = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR);
-
- if (verbose)
- log_info (_("no running dirmngr - starting '%s'\n"),
- dirmngr_program);
-
- if (status_cb)
- status_cb (status_cb_arg, STATUS_PROGRESS,
- "starting_dirmngr ? 0 0", NULL);
-
- abs_homedir = make_absfilename (gnupg_homedir (), NULL);
- if (!abs_homedir)
- {
- gpg_error_t tmperr = gpg_err_make (errsource,
- gpg_err_code_from_syserror ());
- log_error ("error building filename: %s\n",gpg_strerror (tmperr));
- assuan_release (ctx);
- return tmperr;
- }
-
- if (fflush (NULL))
- {
- gpg_error_t tmperr = gpg_err_make (errsource,
- gpg_err_code_from_syserror ());
- log_error ("error flushing pending output: %s\n",
- strerror (errno));
- assuan_release (ctx);
- return tmperr;
- }
+ return start_new_service (r_ctx, GNUPG_MODULE_NAME_KEYBOXD,
+ errsource, keyboxd_program,
+ NULL, NULL, NULL,
+ autostart, verbose, debug,
+ status_cb, status_cb_arg);
+}
- argv[0] = "--daemon";
- /* Try starting the daemon. Versions of dirmngr < 2.1.15 do
- * this only if the home directory is given on the command line. */
- argv[1] = "--homedir";
- argv[2] = abs_homedir;
- argv[3] = NULL;
- if (!(err = lock_spawning (&lock, gnupg_homedir (), "dirmngr", verbose))
- && assuan_socket_connect (ctx, sockname, 0, 0))
- {
-#ifdef HAVE_W32_SYSTEM
- err = gnupg_spawn_process_detached (dirmngr_program, argv, NULL);
-#else
- pid_t pid;
-
- err = gnupg_spawn_process_fd (dirmngr_program, argv,
- -1, -1, -1, &pid);
- if (!err)
- err = gnupg_wait_process (dirmngr_program, pid, 1, NULL);
+/* Try to connect to the dirmngr via a socket. On platforms
+ supporting it, start it up if needed and if AUTOSTART is true.
+ Returns a new assuan context at R_CTX or an error code. */
+gpg_error_t
+start_new_dirmngr (assuan_context_t *r_ctx,
+ gpg_err_source_t errsource,
+ const char *dirmngr_program,
+ int autostart, int verbose, int debug,
+ gpg_error_t (*status_cb)(ctrl_t, int, ...),
+ ctrl_t status_cb_arg)
+{
+#ifndef USE_DIRMNGR_AUTO_START
+ autostart = 0;
#endif
- if (err)
- log_error ("failed to start the dirmngr '%s': %s\n",
- dirmngr_program, gpg_strerror (err));
- else
- err = wait_for_sock (SECS_TO_WAIT_FOR_DIRMNGR, 1,
- sockname, verbose, ctx, &did_success_msg);
- }
-
- unlock_spawning (&lock, "dirmngr");
- xfree (abs_homedir);
- }
-#else
- (void)dirmngr_program;
- (void)verbose;
- (void)status_cb;
- (void)status_cb_arg;
-#endif /*USE_DIRMNGR_AUTO_START*/
-
- if (err)
- {
- if (autostart || gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED)
- log_error ("connecting dirmngr at '%s' failed: %s\n",
- sockname, gpg_strerror (err));
- assuan_release (ctx);
- return gpg_err_make (errsource, GPG_ERR_NO_DIRMNGR);
- }
-
- if (debug && !did_success_msg)
- log_debug ("connection to the dirmngr established\n");
-
- *r_ctx = ctx;
- return 0;
+ return start_new_service (r_ctx, GNUPG_MODULE_NAME_DIRMNGR,
+ errsource, dirmngr_program,
+ NULL, NULL, NULL,
+ autostart, verbose, debug,
+ status_cb, status_cb_arg);
}
diff --git a/common/asshelp.h b/common/asshelp.h
index bf1bd1705..b2f4e538f 100644
--- a/common/asshelp.h
+++ b/common/asshelp.h
@@ -65,6 +65,16 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg);
+/* This function is used to connect to the keyboxd. If needed the
+ * keyboxd is started. */
+gpg_error_t
+start_new_keyboxd (assuan_context_t *r_ctx,
+ gpg_err_source_t errsource,
+ const char *keyboxd_program,
+ int autostart, int verbose, int debug,
+ gpg_error_t (*status_cb)(ctrl_t, int, ...),
+ ctrl_t status_cb_arg);
+
/* This function is used to connect to the dirmngr. On some platforms
the function is able starts a dirmngr process if needed. */
gpg_error_t
@@ -82,8 +92,16 @@ gpg_error_t get_assuan_server_version (assuan_context_t ctx,
/*-- asshelp2.c --*/
+void set_assuan_context_func (assuan_context_t (*func)(ctrl_t ctrl));
+
/* Helper function to print an assuan status line using a printf
format string. */
+
+gpg_error_t status_printf (ctrl_t ctrl, const char *keyword, const char *format,
+ ...) GPGRT_ATTR_PRINTF(3,4);
+gpg_error_t status_no_printf (ctrl_t ctrl, int no, const char *format,
+ ...) GPGRT_ATTR_PRINTF(3,4);
+
gpg_error_t print_assuan_status (assuan_context_t ctx,
const char *keyword,
const char *format,
diff --git a/common/asshelp2.c b/common/asshelp2.c
index 0a7c4549d..8410808e3 100644
--- a/common/asshelp2.c
+++ b/common/asshelp2.c
@@ -36,6 +36,24 @@
#include "util.h"
#include "asshelp.h"
+#include "status.h"
+
+
+/* A variable with a function to be used to return the current assuan
+ * context for a CTRL variable. This needs to be set using the
+ * set_assuan_ctx_func function. */
+static assuan_context_t (*the_assuan_ctx_func)(ctrl_t ctrl);
+
+
+/* Set FUNC to be used as a mapping fucntion from CTRL to an assuan
+ * context. Pass NULL for FUNC to disable the use of the assuan
+ * context in this module. */
+void
+set_assuan_context_func (assuan_context_t (*func)(ctrl_t ctrl))
+{
+ the_assuan_ctx_func = func;
+}
+
/* Helper function to print an assuan status line using a printf
format string. */
@@ -134,3 +152,41 @@ print_assuan_status_strings (assuan_context_t ctx, const char *keyword, ...)
va_end (arg_ptr);
return err;
}
+
+
+/* This function is similar to print_assuan_status but takes a CTRL
+ * arg instead of an assuan context as first argument. */
+gpg_error_t
+status_printf (ctrl_t ctrl, const char *keyword, const char *format, ...)
+{
+ gpg_error_t err;
+ va_list arg_ptr;
+ assuan_context_t ctx;
+
+ if (!ctrl || !the_assuan_ctx_func || !(ctx = the_assuan_ctx_func (ctrl)))
+ return 0;
+
+ va_start (arg_ptr, format);
+ err = vprint_assuan_status (ctx, keyword, format, arg_ptr);
+ va_end (arg_ptr);
+ return err;
+}
+
+
+/* Same as sytus_printf but takes a status number instead of a
+ * keyword. */
+gpg_error_t
+status_no_printf (ctrl_t ctrl, int no, const char *format, ...)
+{
+ gpg_error_t err;
+ va_list arg_ptr;
+ assuan_context_t ctx;
+
+ if (!ctrl || !the_assuan_ctx_func || !(ctx = the_assuan_ctx_func (ctrl)))
+ return 0;
+
+ va_start (arg_ptr, format);
+ err = vprint_assuan_status (ctx, get_status_string (no), format, arg_ptr);
+ va_end (arg_ptr);
+ return err;
+}
diff --git a/common/homedir.c b/common/homedir.c
index e9e75d01e..4425d7811 100644
--- a/common/homedir.c
+++ b/common/homedir.c
@@ -945,6 +945,17 @@ gnupg_cachedir (void)
}
+/* Return the standard socket name used by gpg-agent. */
+const char *
+gpg_agent_socket_name (void)
+{
+ static char *name;
+
+ if (!name)
+ name = make_filename (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
+ return name;
+}
+
/* Return the user socket name used by DirMngr. */
const char *
dirmngr_socket_name (void)
@@ -1104,6 +1115,13 @@ gnupg_module_name (int which)
X(bindir, "dirmngr", DIRMNGR_NAME);
#endif
+ case GNUPG_MODULE_NAME_KEYBOXD:
+#ifdef GNUPG_DEFAULT_KEYBOXD
+ return GNUPG_DEFAULT_KEYBOXD;
+#else
+ X(bindir, "keyboxd", KEYBOXD_NAME);
+#endif
+
case GNUPG_MODULE_NAME_PROTECT_TOOL:
#ifdef GNUPG_DEFAULT_PROTECT_TOOL
return GNUPG_DEFAULT_PROTECT_TOOL;
diff --git a/common/iobuf.c b/common/iobuf.c
index 05944255f..db5d062cd 100644
--- a/common/iobuf.c
+++ b/common/iobuf.c
@@ -106,6 +106,8 @@ typedef struct
int keep_open;
int no_cache;
int eof_seen;
+ int use_readlimit; /* Take care of the readlimit. */
+ size_t readlimit; /* Number of bytes left to read. */
int print_only_name; /* Flags indicating that fname is not a real file. */
char fname[1]; /* Name of the file. */
} file_es_filter_ctx_t;
@@ -635,6 +637,34 @@ file_es_filter (void *opaque, int control, iobuf_t chain, byte * buf,
rc = -1;
*ret_len = 0;
}
+ else if (a->use_readlimit)
+ {
+ nbytes = 0;
+ if (!a->readlimit)
+ { /* eof */
+ a->eof_seen = 1;
+ rc = -1;
+ }
+ else
+ {
+ if (size > a->readlimit)
+ size = a->readlimit;
+ rc = es_read (f, buf, size, &nbytes);
+ if (rc == -1)
+ { /* error */
+ rc = gpg_error_from_syserror ();
+ log_error ("%s: read error: %s\n", a->fname,strerror (errno));
+ }
+ else if (!nbytes)
+ { /* eof */
+ a->eof_seen = 1;
+ rc = -1;
+ }
+ else
+ a->readlimit -= nbytes;
+ }
+ *ret_len = nbytes;
+ }
else
{
nbytes = 0;
@@ -1412,7 +1442,8 @@ iobuf_fdopen_nc (int fd, const char *mode)
iobuf_t
-iobuf_esopen (estream_t estream, const char *mode, int keep_open)
+iobuf_esopen (estream_t estream, const char *mode, int keep_open,
+ size_t readlimit)
{
iobuf_t a;
file_es_filter_ctx_t *fcx;
@@ -1424,7 +1455,9 @@ iobuf_esopen (estream_t estream, const char *mode, int keep_open)
fcx->fp = estream;
fcx->print_only_name = 1;
fcx->keep_open = keep_open;
- sprintf (fcx->fname, "[fd %p]", estream);
+ fcx->readlimit = readlimit;
+ fcx->use_readlimit = !!readlimit;
+ snprintf (fcx->fname, 30, "[fd %p]", estream);
a->filter = file_es_filter;
a->filter_ov = fcx;
file_es_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
diff --git a/common/iobuf.h b/common/iobuf.h
index 16156383c..9c9650c61 100644
--- a/common/iobuf.h
+++ b/common/iobuf.h
@@ -328,8 +328,10 @@ iobuf_t iobuf_fdopen_nc (int fd, const char *mode);
letter 'w', creates an output filter. Otherwise, creates an input
filter. If KEEP_OPEN is TRUE, then the stream is not closed when
the filter is destroyed. Otherwise, the stream is closed when the
- filter is destroyed. */
-iobuf_t iobuf_esopen (estream_t estream, const char *mode, int keep_open);
+ filter is destroyed. If READLIMIT is not 0 this gives a limit on
+ the number of bytes to read from estream. */
+iobuf_t iobuf_esopen (estream_t estream, const char *mode, int keep_open,
+ size_t readlimit);
/* Create a filter using an existing socket. On Windows creates a
special socket filter. On non-Windows systems simply, this simply
diff --git a/common/t-mbox-util.c b/common/t-mbox-util.c
index ae717f96f..e777e03e2 100644
--- a/common/t-mbox-util.c
+++ b/common/t-mbox-util.c
@@ -77,6 +77,12 @@ run_mbox_test (void)
{ "<fo()o@example.org> ()", "fo()o@example.org" },
{ "fo()o@example.org", NULL},
{ "Mr. Foo <foo@example.org><bar@example.net>", "foo@example.org"},
+ { "Surname, Forename | company <foo@example.org>", "foo@example.org"},
+ /* The next one is for sure not RFC-822 correct but nevertheless
+ * the way gpg does it. We won't change it because the user-id
+ * is only rfc-822 alike and not compliant (think only of our
+ * utf-8 requirement). */
+ { "\"<foo@example.org>\" <foo@example.net>", "foo@example.org"},
{ NULL, NULL }
};
int idx;
diff --git a/common/userids.c b/common/userids.c
index 55bd85546..eb714a9af 100644
--- a/common/userids.c
+++ b/common/userids.c
@@ -65,6 +65,9 @@
* (note that you can't search for these characters). Compare
* is not case sensitive.
* - If the userid starts with a '&' a 40 hex digits keygrip is expected.
+ * - If the userid starts with a '^' followed by 40 hex digits it describes
+ * a Unique-Blob-ID (UBID) which is the hash of keyblob or certificate as
+ * stored in the database. This is used in the IPC of the keyboxd.
*/
gpg_error_t
@@ -251,6 +254,17 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
}
break;
+ case '^': /* UBID */
+ {
+ if (hex2bin (s+1, desc->u.ubid, 20) < 0)
+ {
+ rc = gpg_error (GPG_ERR_INV_USER_ID); /* Invalid. */
+ goto out;
+ }
+ mode = KEYDB_SEARCH_MODE_UBID;
+ }
+ break;
+
default:
if (s[0] == '0' && s[1] == 'x')
{
diff --git a/common/util.h b/common/util.h
index bd6cd1ff5..8f8a06a41 100644
--- a/common/util.h
+++ b/common/util.h
@@ -43,6 +43,10 @@
#define GPG_ERR_NO_AUTH 314
#define GPG_ERR_BAD_AUTH 315
#endif /*GPG_ERROR_VERSION_NUMBER*/
+#if GPG_ERROR_VERSION_NUMBER < 0x012500 /* 1.37 */
+#define GPG_ERR_NO_KEYBOXD 316
+#define GPG_ERR_KEYBOXD 317
+#endif /*GPG_ERROR_VERSION_NUMBER*/
/* Hash function used with libksba. */
#define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write)
@@ -243,6 +247,7 @@ const char *gnupg_libdir (void);
const char *gnupg_datadir (void);
const char *gnupg_localedir (void);
const char *gnupg_cachedir (void);
+const char *gpg_agent_socket_name (void);
const char *dirmngr_socket_name (void);
char *_gnupg_socketdir_internal (int skip_checks, unsigned *r_info);
@@ -261,6 +266,7 @@ char *_gnupg_socketdir_internal (int skip_checks, unsigned *r_info);
#define GNUPG_MODULE_NAME_GPGCONF 10
#define GNUPG_MODULE_NAME_DIRMNGR_LDAP 11
#define GNUPG_MODULE_NAME_GPGV 12
+#define GNUPG_MODULE_NAME_KEYBOXD 13
const char *gnupg_module_name (int which);
void gnupg_module_name_flush_some (void);
void gnupg_set_builddir (const char *newdir);