diff --git a/common/asshelp.c b/common/asshelp.c index 3fc28a156..e675fdad8 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -344,9 +344,10 @@ unlock_spawning (lock_spawn_t *lock, const char *name) } } -/* Try to connect to the agent via socket or fork it off and work by - pipes. Handle the server's initial greeting. Returns a new assuan - context at R_CTX or an error code. */ +/* 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, @@ -355,7 +356,7 @@ start_new_gpg_agent (assuan_context_t *r_ctx, const char *opt_lc_ctype, const char *opt_lc_messages, session_env_t session_env, - int verbose, int debug, + int autostart, int verbose, int debug, gpg_error_t (*status_cb)(ctrl_t, int, ...), ctrl_t status_cb_arg) { @@ -376,7 +377,7 @@ start_new_gpg_agent (assuan_context_t *r_ctx, sockname = make_absfilename (homedir, GPG_AGENT_SOCK_NAME, NULL); err = assuan_socket_connect (ctx, sockname, 0, 0); - if (err) + if (err && autostart) { char *abs_homedir; lock_spawn_t lock; @@ -491,7 +492,8 @@ start_new_gpg_agent (assuan_context_t *r_ctx, xfree (sockname); if (err) { - log_error ("can't connect to the agent: %s\n", gpg_strerror (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)); assuan_release (ctx); return gpg_err_make (errsource, GPG_ERR_NO_AGENT); } @@ -517,13 +519,14 @@ 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. Returns a new assuan context - at R_CTX or an error code. */ + 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 *homedir, const char *dirmngr_program, + int autostart, int verbose, int debug, gpg_error_t (*status_cb)(ctrl_t, int, ...), ctrl_t status_cb_arg) @@ -557,7 +560,7 @@ start_new_dirmngr (assuan_context_t *r_ctx, err = assuan_socket_connect (ctx, sockname, 0, 0); #ifdef USE_DIRMNGR_AUTO_START - if (err) + if (err && autostart) { lock_spawn_t lock; const char *argv[4]; @@ -670,8 +673,9 @@ start_new_dirmngr (assuan_context_t *r_ctx, if (err) { - log_error ("connecting dirmngr at '%s' failed: %s\n", - sockname, gpg_strerror (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); } diff --git a/common/asshelp.h b/common/asshelp.h index 08c3c8c0a..7b305856b 100644 --- a/common/asshelp.h +++ b/common/asshelp.h @@ -58,7 +58,7 @@ start_new_gpg_agent (assuan_context_t *r_ctx, const char *opt_lc_ctype, const char *opt_lc_messages, session_env_t session_env, - int verbose, int debug, + int autostart, int verbose, int debug, gpg_error_t (*status_cb)(ctrl_t, int, ...), ctrl_t status_cb_arg); @@ -69,7 +69,7 @@ start_new_dirmngr (assuan_context_t *r_ctx, gpg_err_source_t errsource, const char *homedir, const char *dirmngr_program, - int verbose, int debug, + int autostart, int verbose, int debug, gpg_error_t (*status_cb)(ctrl_t, int, ...), ctrl_t status_cb_arg); diff --git a/common/get-passphrase.c b/common/get-passphrase.c index 5b11eb169..53ce7d136 100644 --- a/common/get-passphrase.c +++ b/common/get-passphrase.c @@ -98,7 +98,7 @@ start_agent (void) agentargs.lc_ctype, agentargs.lc_messages, agentargs.session_env, - agentargs.verbosity, 0, NULL, NULL); + 1, agentargs.verbosity, 0, NULL, NULL); if (!err) { /* Tell the agent that we support Pinentry notifications. No diff --git a/g10/call-agent.c b/g10/call-agent.c index bacb9d5e0..74d8cec28 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -285,7 +285,7 @@ start_agent (ctrl_t ctrl, int for_card) opt.agent_program, opt.lc_ctype, opt.lc_messages, opt.session_env, - opt.verbose, DBG_ASSUAN, + 1, opt.verbose, DBG_ASSUAN, NULL, NULL); if (!rc) { diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c index 71f53240b..7150853e3 100644 --- a/g10/call-dirmngr.c +++ b/g10/call-dirmngr.c @@ -130,7 +130,7 @@ create_context (ctrl_t ctrl, assuan_context_t *r_ctx) GPG_ERR_SOURCE_DEFAULT, opt.homedir, opt.dirmngr_program, - opt.verbose, DBG_ASSUAN, + 1, opt.verbose, DBG_ASSUAN, NULL /*gpg_status2*/, ctrl); if (!err) { diff --git a/sm/call-agent.c b/sm/call-agent.c index f99caade4..59b1509b6 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -95,7 +95,7 @@ start_agent (ctrl_t ctrl) opt.agent_program, opt.lc_ctype, opt.lc_messages, opt.session_env, - opt.verbose, DBG_ASSUAN, + 1, opt.verbose, DBG_ASSUAN, gpgsm_status2, ctrl); if (!rc) diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 99a14c0e7..4dc8425d6 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -209,7 +209,7 @@ start_dirmngr_ext (ctrl_t ctrl, assuan_context_t *ctx_r) err = start_new_dirmngr (&ctx, GPG_ERR_SOURCE_DEFAULT, opt.homedir, opt.dirmngr_program, - opt.verbose, DBG_ASSUAN, + 1, opt.verbose, DBG_ASSUAN, gpgsm_status2, ctrl); prepare_dirmngr (ctrl, ctx, err); if (err) diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index 78dea2a4b..8e8ebcb71 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -63,7 +63,8 @@ enum cmd_and_opt_values oHex, oDecode, oNoExtConnect, - oDirmngr + oDirmngr, + oNoAutostart, }; @@ -89,6 +90,7 @@ static ARGPARSE_OPTS opts[] = { N_("|FILE|run commands from FILE on startup")), ARGPARSE_s_n (oSubst, "subst", N_("run /subst on startup")), + ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"), ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"), ARGPARSE_s_s (oHomedir, "homedir", "@" ), ARGPARSE_s_s (oAgentProgram, "agent-program", "@"), @@ -103,6 +105,7 @@ struct { int verbose; /* Verbosity level. */ 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 *dirmngr_program; /* Value of --dirmngr-program. */ @@ -1175,6 +1178,7 @@ main (int argc, char **argv) opt.homedir = default_homedir (); + opt.autostart = 1; opt.connect_flags = 1; /* Parse the command line. */ @@ -1191,6 +1195,7 @@ main (int argc, char **argv) case oHomedir: opt.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 oNoAutostart: opt.autostart = 0; break; case oHex: opt.hex = 1; break; case oDecode: opt.decode = 1; break; case oDirmngr: opt.use_dirmngr = 1; break; @@ -2195,6 +2200,7 @@ start_agent (void) GPG_ERR_SOURCE_DEFAULT, opt.homedir, opt.dirmngr_program, + opt.autostart, !opt.quiet, 0, NULL, NULL); else @@ -2204,14 +2210,30 @@ start_agent (void) opt.agent_program, NULL, NULL, session_env, + opt.autostart, !opt.quiet, 0, NULL, NULL); session_env_release (session_env); if (err) { - log_error (_("error sending standard options: %s\n"), gpg_strerror (err)); - exit (1); + if (!opt.autostart + && (gpg_err_code (err) + == opt.use_dirmngr? GPG_ERR_NO_DIRMNGR : 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"): + _("no gpg-agent running in this session\n")); + exit (0); + } + else + { + log_error (_("error sending standard options: %s\n"), + gpg_strerror (err)); + exit (1); + } } return ctx; diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index f9999bac6..77139bbae 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -107,6 +107,7 @@ gc_error (int status, int errnum, const char *fmt, ...) /* Forward declaration. */ static void gpg_agent_runtime_change (int killflag); static void scdaemon_runtime_change (int killflag); +static void dirmngr_runtime_change (int killflag); /* Backend configuration. Backends are used to decide how the default and current value of an option can be determined, and how the @@ -189,7 +190,7 @@ static struct { SCDAEMON_DISP_NAME, SCDAEMON_NAME, GNUPG_MODULE_NAME_SCDAEMON, scdaemon_runtime_change, GPGCONF_NAME"-" SCDAEMON_NAME ".conf" }, { DIRMNGR_DISP_NAME, DIRMNGR_NAME, GNUPG_MODULE_NAME_DIRMNGR, - NULL, GPGCONF_NAME "-" DIRMNGR_NAME ".conf" }, + dirmngr_runtime_change, GPGCONF_NAME "-" DIRMNGR_NAME ".conf" }, { DIRMNGR_DISP_NAME " LDAP Server List", NULL, 0, NULL, "ldapserverlist-file", "LDAP Server" }, { "Pinentry", "pinentry", GNUPG_MODULE_NAME_PINENTRY, @@ -1064,19 +1065,20 @@ gpg_agent_runtime_change (int killflag) { gpg_error_t err; const char *pgmname; - const char *argv[2]; + const char *argv[3]; pid_t pid; pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); - argv[0] = killflag? "KILLAGENT" : "RELOADAGENT"; - argv[1] = NULL; + argv[0] = "--no-autostart"; + argv[1] = killflag? "KILLAGENT" : "RELOADAGENT"; + argv[2] = NULL; err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid); if (!err) err = gnupg_wait_process (pgmname, pid, 1, NULL); if (err) - gc_error (0, 0, "error running '%s%s': %s", - pgmname, " reloadagent", gpg_strerror (err)); + gc_error (0, 0, "error running '%s %s': %s", + pgmname, argv[1], gpg_strerror (err)); gnupg_release_process (pid); } @@ -1086,7 +1088,7 @@ scdaemon_runtime_change (int killflag) { gpg_error_t err; const char *pgmname; - const char *argv[6]; + const char *argv[7]; pid_t pid; (void)killflag; /* For scdaemon kill and reload are synonyms. */ @@ -1098,18 +1100,43 @@ scdaemon_runtime_change (int killflag) pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); argv[0] = "-s"; - argv[1] = "GETINFO scd_running"; - argv[2] = "/if ${! $?}"; - argv[3] = "scd killscd"; - argv[4] = "/end"; - argv[5] = NULL; + argv[1] = "--no-autostart"; + argv[2] = "GETINFO scd_running"; + argv[3] = "/if ${! $?}"; + argv[4] = "scd killscd"; + argv[5] = "/end"; + argv[6] = NULL; err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid); if (!err) err = gnupg_wait_process (pgmname, pid, 1, NULL); if (err) - gc_error (0, 0, "error running '%s%s': %s", - pgmname, " scd killscd", gpg_strerror (err)); + gc_error (0, 0, "error running '%s %s': %s", + pgmname, argv[4], gpg_strerror (err)); + gnupg_release_process (pid); +} + + +static void +dirmngr_runtime_change (int killflag) +{ + gpg_error_t err; + const char *pgmname; + const char *argv[4]; + pid_t pid; + + pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); + argv[0] = "--no-autostart"; + argv[1] = "--dirmngr"; + argv[2] = killflag? "KILLDIRMNGR" : "RELOADDIRMNGR"; + argv[3] = NULL; + + err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid); + if (!err) + err = gnupg_wait_process (pgmname, pid, 1, NULL); + if (err) + gc_error (0, 0, "error running '%s %s': %s", + pgmname, argv[2], gpg_strerror (err)); gnupg_release_process (pid); }