From 0611f548bcd3c772084d6c3111dc88a09a67f65a Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 6 Aug 2019 14:28:08 +0200 Subject: [PATCH] tools: New option --keyboxd for gpg-connect-agent. * configure.ac: New option --keyboxd-pgm. (KEYBOXD_NAME, KEYBOXD_DISP_NAME): New ac_defines. * common/util.h: Add substitutes for new error codes. (GNUPG_MODULE_NAME_KEYBOXD): New. * common/homedir.c (gnupg_module_name): Support GNUPG_MODULE_NAME_KEYBOXD. * common/asshelp.c (SECS_TO_WAIT_FOR_KEYBOXD): New. (wait_for_sock): Support keyboxd. (start_new_service): Ditto. (start_new_keyboxd): New. * tools/gpg-connect-agent.c: New options --keyboxd and --keyboxd-program. (start_agent): Implement new option. -- This change allows us to test the new keyboxd using our standard helper. It also provides the necessary code to start keyboxd on the fly. Signed-off-by: Werner Koch --- common/asshelp.c | 48 +++++++++++++++++++++++++++++++-------- common/asshelp.h | 10 ++++++++ common/homedir.c | 7 ++++++ common/util.h | 6 +++++ configure.ac | 13 +++++++++++ doc/tools.texi | 11 +++++++++ tools/gpg-connect-agent.c | 29 +++++++++++++++++++---- 7 files changed, 111 insertions(+), 13 deletions(-) diff --git a/common/asshelp.c b/common/asshelp.c index 84bc546e2..a5724fad5 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,14 @@ 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 +/* 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. */ 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, int verbose, assuan_context_t ctx, int *did_success_msg) { gpg_error_t err = 0; @@ -343,8 +342,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; @@ -357,8 +358,10 @@ wait_for_sock (int secs, int which, const char *sockname, { 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; } @@ -429,6 +432,14 @@ start_new_service (assuan_context_t *r_ctx, 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; + break; default: err = gpg_error (GPG_ERR_INV_ARG); assuan_release (ctx); @@ -520,7 +531,7 @@ start_new_service (assuan_context_t *r_ctx, printed_name, program? program : program_name, gpg_strerror (err)); else - err = wait_for_sock (seconds_to_wait, 0, + err = wait_for_sock (seconds_to_wait, module_name_id, sockname, verbose, ctx, &did_success_msg); } @@ -595,6 +606,25 @@ start_new_gpg_agent (assuan_context_t *r_ctx, } +/* 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_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) +{ + return start_new_service (r_ctx, GNUPG_MODULE_NAME_KEYBOXD, + errsource, keyboxd_program, + NULL, NULL, NULL, + 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. */ diff --git a/common/asshelp.h b/common/asshelp.h index a04a0775c..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 diff --git a/common/homedir.c b/common/homedir.c index 9c680a57f..4425d7811 100644 --- a/common/homedir.c +++ b/common/homedir.c @@ -1115,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/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); diff --git a/configure.ac b/configure.ac index df5ca1238..f18e7a26e 100644 --- a/configure.ac +++ b/configure.ac @@ -191,6 +191,14 @@ AM_CONDITIONAL(GNUPG_DIRMNGR_PGM, test -n "$GNUPG_DIRMNGR_PGM") show_gnupg_dirmngr_pgm="(default)" test -n "$GNUPG_DIRMNGR_PGM" && show_gnupg_dirmngr_pgm="$GNUPG_DIRMNGR_PGM" +AC_ARG_WITH(keyboxd-pgm, + [ --with-keyboxd-pgm=PATH Use PATH as the default for the keyboxd)], + GNUPG_KEYBOXD_PGM="$withval", GNUPG_KEYBOXD_PGM="" ) +AC_SUBST(GNUPG_KEYBOXD_PGM) +AM_CONDITIONAL(GNUPG_KEYBOXD_PGM, test -n "$GNUPG_KEYBOXD_PGM") +show_gnupg_keyboxd_pgm="(default)" +test -n "$GNUPG_KEYBOXD_PGM" && show_gnupg_keyboxd_pgm="$GNUPG_KEYBOXD_PGM" + AC_ARG_WITH(protect-tool-pgm, [ --with-protect-tool-pgm=PATH Use PATH as the default for the protect-tool)], GNUPG_PROTECT_TOOL_PGM="$withval", GNUPG_PROTECT_TOOL_PGM="" ) @@ -1870,6 +1878,10 @@ AC_DEFINE_UNQUOTED(DIRMNGR_NAME, "dirmngr", [The name of the dirmngr]) AC_DEFINE_UNQUOTED(DIRMNGR_DISP_NAME, "DirMngr", [The displayed name of dirmngr]) +AC_DEFINE_UNQUOTED(KEYBOXD_NAME, "keyboxd", [The name of the keyboxd]) +AC_DEFINE_UNQUOTED(KEYBOXD_DISP_NAME, "Keyboxd", + [The displayed name of keyboxd]) + AC_DEFINE_UNQUOTED(G13_NAME, "g13", [The name of the g13 tool]) AC_DEFINE_UNQUOTED(G13_DISP_NAME, "G13", [The displayed name of g13]) @@ -2090,6 +2102,7 @@ echo " Default agent: $show_gnupg_agent_pgm Default pinentry: $show_gnupg_pinentry_pgm Default scdaemon: $show_gnupg_scdaemon_pgm + Default keyboxd: $show_gnupg_keyboxd_pgm Default dirmngr: $show_gnupg_dirmngr_pgm Dirmngr auto start: $dirmngr_auto_start diff --git a/doc/tools.texi b/doc/tools.texi index 460030038..0893c65a5 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -1328,11 +1328,22 @@ Specify the directory manager (keyserver client) program to be started if none is running. This has only an effect if used together with the option @option{--dirmngr}. +@item --keyboxd-program @var{file} +@opindex keyboxd-program +Specify the keybox daemon program to be started if none is running. +This has only an effect if used together with the option +@option{--keyboxd}. + @item --dirmngr @opindex dirmngr Connect to a running directory manager (keyserver client) instead of to the gpg-agent. If a dirmngr is not running, start it. +@item --keyboxd +@opindex keyboxd +Connect to a running keybox daemon instead of +to the gpg-agent. If a keyboxd is not running, start it. + @item -S @itemx --raw-socket @var{name} @opindex raw-socket diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index 7eb7ffa3a..0a128b31a 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -60,12 +60,14 @@ enum cmd_and_opt_values oHomedir, oAgentProgram, oDirmngrProgram, + oKeyboxdProgram, oHex, oDecode, oNoExtConnect, oDirmngr, + oKeyboxd, oUIServer, - oNoAutostart, + oNoAutostart }; @@ -79,6 +81,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oHex, "hex", N_("print data out hex encoded")), ARGPARSE_s_n (oDecode,"decode", N_("decode received data lines")), ARGPARSE_s_n (oDirmngr,"dirmngr", N_("connect to the dirmngr")), + ARGPARSE_s_n (oKeyboxd,"keyboxd", N_("connect to the keyboxd")), ARGPARSE_s_n (oUIServer, "uiserver", "@"), ARGPARSE_s_s (oRawSocket, "raw-socket", N_("|NAME|connect to Assuan socket NAME")), @@ -97,6 +100,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_s (oHomedir, "homedir", "@" ), ARGPARSE_s_s (oAgentProgram, "agent-program", "@"), ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"), + ARGPARSE_s_s (oKeyboxdProgram, "keyboxd-program", "@"), ARGPARSE_end () }; @@ -109,11 +113,13 @@ struct int quiet; /* Be extra quiet. */ int autostart; /* Start the server if not running. */ const char *homedir; /* Configuration directory name */ - const char *agent_program; /* Value of --agent-program. */ + const char *agent_program; /* Value of --agent-program. */ const char *dirmngr_program; /* Value of --dirmngr-program. */ + const char *keyboxd_program; /* Value of --keyboxd-program. */ int hex; /* Print data lines in hex format. */ int decode; /* Decode received data lines. */ int use_dirmngr; /* Use the dirmngr and not gpg-agent. */ + int use_keyboxd; /* Use the keyboxd and not gpg-agent. */ int use_uiserver; /* Use the standard UI server. */ const char *raw_socket; /* Name of socket to connect in raw mode. */ const char *tcp_socket; /* Name of server to connect in tcp mode. */ @@ -1200,10 +1206,12 @@ main (int argc, char **argv) case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break; case oAgentProgram: opt.agent_program = pargs.r.ret_str; break; case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break; + case oKeyboxdProgram: opt.keyboxd_program = pargs.r.ret_str; break; case oNoAutostart: opt.autostart = 0; break; case oHex: opt.hex = 1; break; case oDecode: opt.decode = 1; break; case oDirmngr: opt.use_dirmngr = 1; break; + case oKeyboxd: opt.use_keyboxd = 1; break; case oUIServer: opt.use_uiserver = 1; break; case oRawSocket: opt.raw_socket = pargs.r.ret_str; break; case oTcpSocket: opt.tcp_socket = pargs.r.ret_str; break; @@ -1879,7 +1887,10 @@ main (int argc, char **argv) } if (opt.verbose) - log_info ("closing connection to agent\n"); + log_info ("closing connection to %s\n", + opt.use_dirmngr? "dirmngr" : + opt.use_keyboxd? "keyboxd" : + "agent"); /* XXX: We would like to release the context here, but libassuan nicely says good bye to the server, which results in a SIGPIPE if @@ -2224,6 +2235,13 @@ start_agent (void) opt.autostart, !opt.quiet, 0, NULL, NULL); + else if (opt.use_keyboxd) + err = start_new_keyboxd (&ctx, + GPG_ERR_SOURCE_DEFAULT, + opt.keyboxd_program, + opt.autostart, + !opt.quiet, 0, + NULL, NULL); else err = start_new_gpg_agent (&ctx, GPG_ERR_SOURCE_DEFAULT, @@ -2239,12 +2257,15 @@ start_agent (void) { if (!opt.autostart && (gpg_err_code (err) - == (opt.use_dirmngr? GPG_ERR_NO_DIRMNGR : GPG_ERR_NO_AGENT))) + == (opt.use_dirmngr? GPG_ERR_NO_DIRMNGR : + opt.use_keyboxd? GPG_ERR_NO_KEYBOXD : GPG_ERR_NO_AGENT))) { /* In the no-autostart case we don't make gpg-connect-agent fail on a missing server. */ log_info (opt.use_dirmngr? _("no dirmngr running in this session\n"): + opt.use_keyboxd? + _("no keybox daemon running in this session\n"): _("no gpg-agent running in this session\n")); exit (0); }