1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

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>
This commit is contained in:
Werner Koch 2019-09-27 15:44:23 +02:00
commit 9698761933
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
61 changed files with 7194 additions and 507 deletions

View file

@ -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);
err = assuan_transact (ctx, "RESET",
NULL, NULL, NULL, NULL, NULL, NULL);
if (!err)
if (module_name_id == GNUPG_MODULE_NAME_AGENT)
err = assuan_transact (ctx, "RESET",
NULL, NULL, NULL, NULL, NULL, NULL);
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,6 +600,45 @@ 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_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. */
@ -566,119 +646,18 @@ 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,
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;
}
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);
#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);
}