Lock scdaemon to CCID if once found.

This solves a problem where ccid was used, the card unplugged and then
scdaemon tries to find a new (plugged in) reader and thus will
eventually try PC/SC over and over again.

Also added an explicit --kill command to gpgconf.
This commit is contained in:
Werner Koch 2011-02-23 10:15:34 +01:00
parent 90dcc0c3ad
commit 7c03c8cc65
7 changed files with 239 additions and 143 deletions

View File

@ -301,10 +301,17 @@ is given, check that file instead.
@item --reload [@var{component}] @item --reload [@var{component}]
@opindex reload @opindex reload
Reload all or the given component. This is basically the sam as sending Reload all or the given component. This is basically the same as sending
a SIGHUP to the component. Components which don't support reloading are a SIGHUP to the component. Components which don't support reloading are
ignored. ignored.
@item --kill [@var{component}]
@opindex kill
Kill the given component. Components which support killing are
gpg-agent and scdaemon. Components which don't support reloading are
ignored. Note that as of now reload and kill have the same effect for
scdaemon.
@end table @end table
@ -1884,4 +1891,3 @@ gpg-zip --list-archive test1
@command{tar}(1), @command{tar}(1),
@end ifset @end ifset
@include see-also-note.texi @include see-also-note.texi

View File

@ -1,3 +1,7 @@
2011-02-23 Werner Koch <wk@g10code.com>
* apdu.c (apdu_open_reader): Lock in to CCID if used once.
2011-01-25 NIIBE Yutaka <gniibe@fsij.org>, 2011-01-25 NIIBE Yutaka <gniibe@fsij.org>,
Grant Olson <kgo@grant-olson.net> (wk) Grant Olson <kgo@grant-olson.net> (wk)

View File

@ -1,5 +1,6 @@
/* apdu.c - ISO 7816 APDU functions and low level I/O /* apdu.c - ISO 7816 APDU functions and low level I/O
* Copyright (C) 2003, 2004, 2008, 2009, 2010 Free Software Foundation, Inc. * Copyright (C) 2003, 2004, 2008, 2009, 2010,
* 2011 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -2355,12 +2356,25 @@ apdu_open_reader (const char *portstr, int *r_no_service)
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
if (!opt.disable_ccid) if (!opt.disable_ccid)
{ {
static int once_available;
int i; int i;
const char *s; const char *s;
slot = open_ccid_reader (portstr); slot = open_ccid_reader (portstr);
if (slot != -1) if (slot != -1)
return slot; /* got one */ {
once_available = 1;
return slot; /* got one */
}
/* If we ever loaded successfully loaded a CCID reader we never
want to fallback to another driver. This solves a problem
where ccid was used, the card unplugged and then scdaemon
tries to find a new reader and will eventually try PC/SC over
and over again. To reset this flag "gpgconf --kill scdaemon"
can be used. */
if (once_available)
return -1;
/* If a CCID reader specification has been given, the user does /* If a CCID reader specification has been given, the user does
not want a fallback to other drivers. */ not want a fallback to other drivers. */

View File

@ -1,3 +1,9 @@
2011-02-23 Werner Koch <wk@g10code.com>
* gpgconf.c: Add command --kill.
* gpgconf-comp.c (gc_component_kill): New.
(gpg_agent_runtime_change, scdaemon_runtime_change): Add kill flag.
2011-02-03 Werner Koch <wk@g10code.com> 2011-02-03 Werner Koch <wk@g10code.com>
* watchgnupg.c (print_version): Update copyright year. * watchgnupg.c (print_version): Update copyright year.
@ -1247,7 +1253,7 @@
Copyright 2003, 2004, 2005, 2006, 2007, 2008, Copyright 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010 Free Software Foundation, Inc. 2009, 2010, 2011 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without unlimited permission to copy and/or distribute it, with or without

View File

@ -1,5 +1,6 @@
/* gpgconf-comp.c - Configuration utility for GnuPG. /* gpgconf-comp.c - Configuration utility for GnuPG.
* Copyright (C) 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. * Copyright (C) 2004, 2007, 2008, 2009, 2010,
* 2011 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -104,8 +105,8 @@ gc_error (int status, int errnum, const char *fmt, ...)
/* Forward declaration. */ /* Forward declaration. */
static void gpg_agent_runtime_change (void); static void gpg_agent_runtime_change (int killflag);
static void scdaemon_runtime_change (void); static void scdaemon_runtime_change (int killflag);
/* Backend configuration. Backends are used to decide how the default /* Backend configuration. Backends are used to decide how the default
and current value of an option can be determined, and how the and current value of an option can be determined, and how the
@ -163,8 +164,9 @@ static struct
available. */ available. */
char module_name; char module_name;
/* The runtime change callback. */ /* The runtime change callback. If KILLFLAG is true the component
void (*runtime_change) (void); is killed and not just reloaded. */
void (*runtime_change) (int killflag);
/* The option name for the configuration filename of this backend. /* The option name for the configuration filename of this backend.
This must be an absolute filename. It can be an option from a This must be an absolute filename. It can be an option from a
@ -1047,7 +1049,7 @@ struct error_line_s
/* Engine specific support. */ /* Engine specific support. */
static void static void
gpg_agent_runtime_change (void) gpg_agent_runtime_change (int killflag)
{ {
gpg_error_t err; gpg_error_t err;
const char *pgmname; const char *pgmname;
@ -1055,7 +1057,7 @@ gpg_agent_runtime_change (void)
pid_t pid; pid_t pid;
pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
argv[0] = "reloadagent"; argv[0] = killflag? "KILLAGENT" : "RELOADAGENT";
argv[1] = NULL; argv[1] = NULL;
err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid); err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
@ -1069,13 +1071,15 @@ gpg_agent_runtime_change (void)
static void static void
scdaemon_runtime_change (void) scdaemon_runtime_change (int killflag)
{ {
gpg_error_t err; gpg_error_t err;
const char *pgmname; const char *pgmname;
const char *argv[6]; const char *argv[6];
pid_t pid; pid_t pid;
(void)killflag; /* For scdaemon kill and reload are synonyms. */
/* We use "GETINFO app_running" to see whether the agent is already /* We use "GETINFO app_running" to see whether the agent is already
running and kill it only in this case. This avoids an explicit running and kill it only in this case. This avoids an explicit
starting of the agent in case it is not yet running. There is starting of the agent in case it is not yet running. There is
@ -1099,6 +1103,35 @@ scdaemon_runtime_change (void)
} }
/* Unconditionally restart COMPONENT. */
void
gc_component_kill (int component)
{
int runtime[GC_BACKEND_NR];
gc_option_t *option;
gc_backend_t backend;
/* Set a flag for the backends to be reloaded. */
for (backend = 0; backend < GC_BACKEND_NR; backend++)
runtime[backend] = 0;
if (component >= 0)
{
assert (component < GC_COMPONENT_NR);
option = gc_component[component].options;
for (; option && option->name; option++)
runtime[option->backend] = 1;
}
/* Do the restart for the selected backends. */
for (backend = 0; backend < GC_BACKEND_NR; backend++)
{
if (runtime[backend] && gc_backend[backend].runtime_change)
(*gc_backend[backend].runtime_change) (1);
}
}
/* Unconditionally reload COMPONENT or all components if COMPONENT is -1. */ /* Unconditionally reload COMPONENT or all components if COMPONENT is -1. */
void void
gc_component_reload (int component) gc_component_reload (int component)
@ -1132,7 +1165,7 @@ gc_component_reload (int component)
for (backend = 0; backend < GC_BACKEND_NR; backend++) for (backend = 0; backend < GC_BACKEND_NR; backend++)
{ {
if (runtime[backend] && gc_backend[backend].runtime_change) if (runtime[backend] && gc_backend[backend].runtime_change)
(*gc_backend[backend].runtime_change) (); (*gc_backend[backend].runtime_change) (0);
} }
} }
@ -3195,7 +3228,7 @@ gc_component_change_options (int component, estream_t in, estream_t out)
for (backend = 0; backend < GC_BACKEND_NR; backend++) for (backend = 0; backend < GC_BACKEND_NR; backend++)
{ {
if (runtime[backend] && gc_backend[backend].runtime_change) if (runtime[backend] && gc_backend[backend].runtime_change)
(*gc_backend[backend].runtime_change) (); (*gc_backend[backend].runtime_change) (0);
} }
/* Move the per-process backup file into its place. */ /* Move the per-process backup file into its place. */
@ -3634,7 +3667,7 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
{ {
for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++) for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
if (runtime[backend_id] && gc_backend[backend_id].runtime_change) if (runtime[backend_id] && gc_backend[backend_id].runtime_change)
(*gc_backend[backend_id].runtime_change) (); (*gc_backend[backend_id].runtime_change) (0);
} }
} }

View File

@ -1,5 +1,5 @@
/* gpgconf.c - Configuration utility for GnuPG /* gpgconf.c - Configuration utility for GnuPG
* Copyright (C) 2003, 2007, 2009 Free Software Foundation, Inc. * Copyright (C) 2003, 2007, 2009, 2011 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -49,6 +49,7 @@ enum cmd_and_opt_values
aListConfig, aListConfig,
aCheckConfig, aCheckConfig,
aListDirs, aListDirs,
aKill,
aReload aReload
}; };
@ -72,6 +73,7 @@ static ARGPARSE_OPTS opts[] =
{ aCheckConfig, "check-config", 256, { aCheckConfig, "check-config", 256,
N_("check global configuration file") }, N_("check global configuration file") },
{ aReload, "reload", 256, N_("reload all or a given component")}, { aReload, "reload", 256, N_("reload all or a given component")},
{ aKill, "kill", 256, N_("kill a given component")},
{ 301, NULL, 0, N_("@\nOptions:\n ") }, { 301, NULL, 0, N_("@\nOptions:\n ") },
@ -180,6 +182,7 @@ main (int argc, char **argv)
case aListConfig: case aListConfig:
case aCheckConfig: case aCheckConfig:
case aReload: case aReload:
case aKill:
cmd = pargs.r_opt; cmd = pargs.r_opt;
break; break;
@ -240,6 +243,34 @@ main (int argc, char **argv)
} }
break; break;
case aKill:
if (!fname)
{
es_fputs (_("usage: gpgconf [options] "), es_stderr);
es_putc ('\n', es_stderr);
es_fputs (_("Need one component argument"), es_stderr);
es_putc ('\n', es_stderr);
exit (2);
}
else
{
/* Kill a given component. */
int idx;
idx = gc_component_find (fname);
if (idx < 0)
{
es_fputs (_("Component not found"), es_stderr);
es_putc ('\n', es_stderr);
exit (1);
}
else
{
gc_component_kill (idx);
}
}
break;
case aReload: case aReload:
if (!fname) if (!fname)
{ {
@ -344,4 +375,3 @@ main (int argc, char **argv)
return 0; return 0;
} }

View File

@ -44,6 +44,9 @@ char *gc_percent_escape (const char *src);
void gc_error (int status, int errnum, const char *fmt, ...); void gc_error (int status, int errnum, const char *fmt, ...);
/* Kill given component. */
void gc_component_kill (int component);
/* Reload given component. */ /* Reload given component. */
void gc_component_reload (int component); void gc_component_reload (int component);