mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +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:
parent
d8a84594ab
commit
e22ebf3570
228
common/asshelp.c
228
common/asshelp.c
@ -372,14 +372,18 @@ 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
|
||||||
|
*/
|
||||||
|
static gpg_error_t
|
||||||
|
start_new_service (assuan_context_t *r_ctx,
|
||||||
|
int module_name_id,
|
||||||
gpg_err_source_t errsource,
|
gpg_err_source_t errsource,
|
||||||
const char *agent_program,
|
const char *program_name,
|
||||||
const char *opt_lc_ctype,
|
const char *opt_lc_ctype,
|
||||||
const char *opt_lc_messages,
|
const char *opt_lc_messages,
|
||||||
session_env_t session_env,
|
session_env_t session_env,
|
||||||
@ -391,6 +395,11 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
|
|||||||
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,16 +467,15 @@ 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)
|
||||||
{
|
{
|
||||||
@ -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;
|
||||||
|
if (module_name_id == GNUPG_MODULE_NAME_AGENT)
|
||||||
argv[i++] = "--use-standard-socket";
|
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);
|
||||||
|
|
||||||
|
if (module_name_id == GNUPG_MODULE_NAME_AGENT)
|
||||||
err = assuan_transact (ctx, "RESET",
|
err = assuan_transact (ctx, "RESET",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (!err)
|
|
||||||
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user