1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-06 23:17:47 +02:00

common: Remove code duplication for service starting.

* common/homedir.c (gpg_agent_socket_name): New.
* common/asshelp.c (start_new_service): New.  Based on
start_new_gpg_agent.
(start_new_gpg_agent): Divert to start_new_service.
(start_new_dirmngr): Ditto.
--

This prepares for adding yet another service starting function.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-08-05 09:49:09 +02:00
parent d8a84594ab
commit e22ebf3570
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 113 additions and 148 deletions

View File

@ -372,25 +372,34 @@ 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 /* 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 * running and AUTOSTART is set. Handle the server's initial
greeting. Returns a new assuan context at R_CTX or an error * greeting. Returns a new assuan context at R_CTX or an error code.
code. */ * MODULE_NAME_ID is one of:
gpg_error_t * GNUPG_MODULE_NAME_AGENT
start_new_gpg_agent (assuan_context_t *r_ctx, * GNUPG_MODULE_NAME_DIRMNGR
gpg_err_source_t errsource, */
const char *agent_program, static gpg_error_t
const char *opt_lc_ctype, start_new_service (assuan_context_t *r_ctx,
const char *opt_lc_messages, int module_name_id,
session_env_t session_env, gpg_err_source_t errsource,
int autostart, int verbose, int debug, const char *program_name,
gpg_error_t (*status_cb)(ctrl_t, int, ...), const char *opt_lc_ctype,
ctrl_t status_cb_arg) 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; gpg_error_t err;
assuan_context_t ctx; assuan_context_t ctx;
int did_success_msg = 0; int did_success_msg = 0;
char *sockname; char *sockname;
const char *printed_name;
const char *lock_name;
const char *status_start_line;
int no_service_err;
int seconds_to_wait;
const char *argv[6]; const char *argv[6];
*r_ctx = NULL; *r_ctx = NULL;
@ -402,10 +411,26 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
return err; return err;
} }
sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL); switch (module_name_id)
if (!sockname)
{ {
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;
default:
err = gpg_error (GPG_ERR_INV_ARG);
assuan_release (ctx); assuan_release (ctx);
return err; return err;
} }
@ -422,12 +447,12 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
int i; int i;
/* With no success start a new server. */ /* With no success start a new server. */
if (!agent_program || !*agent_program) if (!program_name || !*program_name)
agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT); program_name = gnupg_module_name (module_name_id);
else if ((s=strchr (agent_program, '|')) && s[1] == '-' && s[2]=='-') else if ((s=strchr (program_name, '|')) && s[1] == '-' && s[2]=='-')
{ {
/* Hack to insert an additional option on the command line. */ /* Hack to insert an additional option on the command line. */
program = xtrystrdup (agent_program); program = xtrystrdup (program_name);
if (!program) if (!program)
{ {
gpg_error_t tmperr = gpg_err_make (errsource, gpg_error_t tmperr = gpg_err_make (errsource,
@ -442,22 +467,21 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
} }
if (verbose) if (verbose)
log_info (_("no running gpg-agent - starting '%s'\n"), log_info (_("no running %s - starting '%s'\n"),
agent_program); printed_name, program_name);
if (status_cb) if (status_cb)
status_cb (status_cb_arg, STATUS_PROGRESS, status_cb (status_cb_arg, STATUS_PROGRESS, status_start_line, NULL);
"starting_agent ? 0 0", NULL);
/* We better pass an absolute home directory to the agent just /* We better pass an absolute home directory to the service just
in case gpg-agent does not convert the passed name to an * in case the service does not convert the passed name to an
absolute one (which it should do). */ * absolute one (which it should do). */
abs_homedir = make_absfilename_try (gnupg_homedir (), NULL); abs_homedir = make_absfilename_try (gnupg_homedir (), NULL);
if (!abs_homedir) if (!abs_homedir)
{ {
gpg_error_t tmperr = gpg_err_make (errsource, gpg_error_t tmperr = gpg_err_make (errsource,
gpg_err_code_from_syserror ()); 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); xfree (sockname);
assuan_release (ctx); assuan_release (ctx);
xfree (program); xfree (program);
@ -468,8 +492,7 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
{ {
gpg_error_t tmperr = gpg_err_make (errsource, gpg_error_t tmperr = gpg_err_make (errsource,
gpg_err_code_from_syserror ()); gpg_err_code_from_syserror ());
log_error ("error flushing pending output: %s\n", log_error ("error flushing pending output: %s\n", strerror (errno));
strerror (errno));
xfree (sockname); xfree (sockname);
assuan_release (ctx); assuan_release (ctx);
xfree (abs_homedir); xfree (abs_homedir);
@ -477,32 +500,31 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
return tmperr; 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; i = 0;
argv[i++] = "--homedir"; argv[i++] = "--homedir";
argv[i++] = abs_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) if (program_arg)
argv[i++] = program_arg; argv[i++] = program_arg;
argv[i++] = "--daemon"; argv[i++] = "--daemon";
argv[i++] = NULL; argv[i++] = NULL;
if (!(err = lock_spawning (&lock, gnupg_homedir (), "agent", verbose)) if (!(err = lock_spawning (&lock, gnupg_homedir (), lock_name, verbose))
&& assuan_socket_connect (ctx, sockname, 0, 0)) && assuan_socket_connect (ctx, sockname, 0, 0))
{ {
err = gnupg_spawn_process_detached (program? program : agent_program, err = gnupg_spawn_process_detached (program? program : program_name,
argv, NULL); argv, NULL);
if (err) if (err)
log_error ("failed to start agent '%s': %s\n", log_error ("failed to start %s '%s': %s\n",
agent_program, gpg_strerror (err)); printed_name, program? program : program_name,
gpg_strerror (err));
else else
err = wait_for_sock (SECS_TO_WAIT_FOR_AGENT, 0, err = wait_for_sock (seconds_to_wait, 0,
sockname, verbose, ctx, &did_success_msg); sockname, verbose, ctx, &did_success_msg);
} }
unlock_spawning (&lock, "agent"); unlock_spawning (&lock, lock_name);
xfree (abs_homedir); xfree (abs_homedir);
xfree (program); xfree (program);
} }
@ -510,17 +532,21 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
if (err) if (err)
{ {
if (autostart || gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED) 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); 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) if (debug && !did_success_msg)
log_debug ("connection to the agent established\n"); log_debug ("connection to the %s established\n", printed_name);
err = assuan_transact (ctx, "RESET", if (module_name_id == GNUPG_MODULE_NAME_AGENT)
NULL, NULL, NULL, NULL, NULL, NULL); err = assuan_transact (ctx, "RESET",
if (!err) NULL, NULL, NULL, NULL, NULL, NULL);
if (!err
&& module_name_id == GNUPG_MODULE_NAME_AGENT)
{ {
err = send_pinentry_environment (ctx, errsource, err = send_pinentry_environment (ctx, errsource,
opt_lc_ctype, opt_lc_messages, opt_lc_ctype, opt_lc_messages,
@ -528,7 +554,7 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
if (gpg_err_code (err) == GPG_ERR_FORBIDDEN if (gpg_err_code (err) == GPG_ERR_FORBIDDEN
&& gpg_err_source (err) == GPG_ERR_SOURCE_GPGAGENT) && 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", if (!assuan_transact (ctx, "GETINFO restricted",
NULL, NULL, NULL, NULL, NULL, NULL)) NULL, NULL, NULL, NULL, NULL, NULL))
{ {
@ -549,6 +575,26 @@ 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 /* Try to connect to the dirmngr via a socket. On platforms
supporting it, start it up if needed and if AUTOSTART is true. supporting it, start it up if needed and if AUTOSTART is true.
Returns a new assuan context at R_CTX or an error code. */ Returns a new assuan context at R_CTX or an error code. */
@ -556,110 +602,18 @@ gpg_error_t
start_new_dirmngr (assuan_context_t *r_ctx, start_new_dirmngr (assuan_context_t *r_ctx,
gpg_err_source_t errsource, gpg_err_source_t errsource,
const char *dirmngr_program, const char *dirmngr_program,
int autostart, int autostart, int verbose, int debug,
int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...), gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg) 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 #ifdef USE_DIRMNGR_AUTO_START
if (err && autostart) autostart = 0;
{ #endif
lock_spawn_t lock; return start_new_service (r_ctx, GNUPG_MODULE_NAME_DIRMNGR,
const char *argv[4]; errsource, dirmngr_program,
char *abs_homedir; NULL, NULL, NULL,
autostart, verbose, debug,
/* No connection: Try start a new Dirmngr. */ status_cb, status_cb_arg);
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;
}
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))
{
err = gnupg_spawn_process_detached (dirmngr_program, argv, NULL);
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;
} }

View File

@ -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. */ /* Return the user socket name used by DirMngr. */
const char * const char *
dirmngr_socket_name (void) dirmngr_socket_name (void)