From ec4a3eb3c5b45321125a9b1fb2b8cd5ee20c52de Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 27 Feb 2009 14:36:59 +0000 Subject: [PATCH] Fix a gpg2 problem with removed cards. Allow runtime conf change for scdaemon. New commands for scdaemon. --- NEWS | 4 +++- g10/ChangeLog | 5 +++++ g10/call-agent.c | 18 +++++++++++++++++ scd/ChangeLog | 9 +++++++++ scd/app-common.h | 1 + scd/app.c | 35 ++++++++++++++++++++++++++++++-- scd/command.c | 32 +++++++++++++++++++++++++++++ tools/ChangeLog | 7 +++++++ tools/gpgconf-comp.c | 48 ++++++++++++++++++++++++++++++++------------ 9 files changed, 143 insertions(+), 16 deletions(-) diff --git a/NEWS b/NEWS index 2a7f4e9f2..5e1cdb98a 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,12 @@ Noteworthy changes in version 2.0.11 (unreleased) ------------------------------------------------- - * The SCDAEMON option --allow-admin is now used by default. + * Fixed a problem in SCDAEMON which caused unexpected card resets. * SCDAEMON is now aware of the Geldkarte. + * The SCDAEMON option --allow-admin is now used by default. + * The default cipher algorithm in GPGSM is now again 3DES. This is due to interoperability problems with Outlook 2003 which still can't cope with AES. diff --git a/g10/ChangeLog b/g10/ChangeLog index 91934e318..f081d82b5 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2009-02-27 Werner Koch + + * call-agent.c (agent_scd_pksign, agent_scd_pkdecrypt): First send + the SERIALNO command. + 2009-02-24 Werner Koch * pkglue.c (pk_verify): Return an error for improper DATA instead diff --git a/g10/call-agent.c b/g10/call-agent.c index 57d963dfd..572fa8513 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -698,6 +698,15 @@ agent_scd_pksign (const char *serialno, int hashalgo, if (indatalen*2 + 50 > DIM(line)) return gpg_error (GPG_ERR_GENERAL); + /* Send the serialno command to initialize the connection. We don't + care about the data returned. If the card has already been + initialized, this is a very fast command. We request the openpgp + card because that is waht we expect. */ + rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp", + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return rc; + sprintf (line, "SCD SETDATA "); p = line + strlen (line); for (i=0; i < indatalen ; i++, p += 2 ) @@ -754,6 +763,15 @@ agent_scd_pkdecrypt (const char *serialno, if (indatalen*2 + 50 > DIM(line)) return gpg_error (GPG_ERR_GENERAL); + /* Send the serialno command to initialize the connection. We don't + care about the data returned. If the card has already been + initialized, this is a very fast command. We request the openpgp + card because that is waht we expect. */ + rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp", + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return rc; + sprintf (line, "SCD SETDATA "); p = line + strlen (line); for (i=0; i < indatalen ; i++, p += 2 ) diff --git a/scd/ChangeLog b/scd/ChangeLog index 23544438c..1fd2de8c8 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,12 @@ +2009-02-27 Werner Koch + + * app.c (get_supported_applications): New. + * command.c (cmd_getinfo): New subcommand "app_list" + (cmd_killscd): New. + (register_commands): Register command KILLSCD. + (struct server_local_s): Add field STOPME. + (scd_command_handler): Act upon this. + 2009-02-25 Werner Koch * apdu.c (apdu_get_status): Factor all code out to ... diff --git a/scd/app-common.h b/scd/app-common.h index 5a45fa05b..ad899a3b6 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -141,6 +141,7 @@ void application_notify_card_reset (int slot); gpg_error_t check_application_conflict (ctrl_t ctrl, const char *name); gpg_error_t select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app); +char *get_supported_applications (void); void release_application (app_t app); gpg_error_t app_munge_serialno (app_t app); gpg_error_t app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); diff --git a/scd/app.c b/scd/app.c index 4034fa64c..d0b832843 100644 --- a/scd/app.c +++ b/scd/app.c @@ -22,7 +22,7 @@ #include #include #include -# include +#include #include "scdaemon.h" #include "app-common.h" @@ -373,7 +373,7 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) } app->ref_count = 1; - log_debug ("USING application context (refcount=%u) (new)\n", app->ref_count); + lock_table[slot].app = app; *r_app = app; unlock_reader (slot); @@ -381,6 +381,37 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) } +char * +get_supported_applications (void) +{ + const char *list[] = { + "openpgp", + "nks", + "p15", + "dinsig", + "geldkarte", + NULL + }; + int idx; + size_t nbytes; + char *buffer, *p; + + for (nbytes=1, idx=0; list[idx]; idx++) + nbytes += strlen (list[idx]) + 1 + 1; + + buffer = xtrymalloc (nbytes); + if (!buffer) + return NULL; + + for (p=buffer, idx=0; list[idx]; idx++) + if (is_app_allowed (list[idx])) + p = stpcpy (stpcpy (p, list[idx]), ":\n"); + *p = 0; + + return buffer; +} + + /* Deallocate the application. */ static void deallocate_app (app_t app) diff --git a/scd/command.c b/scd/command.c index f3e374c39..07a1e9b54 100644 --- a/scd/command.c +++ b/scd/command.c @@ -114,6 +114,11 @@ struct server_local_s /* A disconnect command has been sent. */ int disconnect_allowed; + + /* If set to true we will be terminate ourself at the end of the + this session. */ + int stopme; + }; @@ -1561,6 +1566,9 @@ cmd_unlock (assuan_context_t ctx, char *line) deny_admin - Returns OK if admin commands are not allowed or GPG_ERR_GENERAL if admin commands are allowed. + app_list - Return a list of supported applciations. One + application per line, fields delimited by colons, + first field is the name. */ static int @@ -1628,6 +1636,15 @@ cmd_getinfo (assuan_context_t ctx, char *line) } else if (!strcmp (line, "deny_admin")) rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0; + else if (!strcmp (line, "app_list")) + { + char *s = get_supported_applications (); + if (s) + rc = assuan_send_data (ctx, s, strlen (s)); + else + rc = 0; + xfree (s); + } else rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT"); return rc; @@ -1767,6 +1784,17 @@ cmd_apdu (assuan_context_t ctx, char *line) } +/* KILLSCD - Commit suicide. */ +static int +cmd_killscd (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + + (void)line; + + ctrl->server_local->stopme = 1; + return gpg_error (GPG_ERR_EOF); +} @@ -1802,6 +1830,7 @@ register_commands (assuan_context_t ctx) { "RESTART", cmd_restart }, { "DISCONNECT", cmd_disconnect }, { "APDU", cmd_apdu }, + { "KILLSCD", cmd_killscd }, { NULL } }; int i, rc; @@ -1919,6 +1948,9 @@ scd_command_handler (ctrl_t ctrl, int fd) /* Release the Assuan context. */ assuan_deinit_server (ctx); + if (ctrl->server_local->stopme) + scd_exit (0); + /* If there are no more sessions return true. */ return !session_list; } diff --git a/tools/ChangeLog b/tools/ChangeLog index 8c3474168..dbe090f0b 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,10 @@ +2009-02-27 Werner Koch + + * gpgconf-comp.c (gpg_agent_runtime_change): Declare static. + (scdaemon_runtime_change): New. + (gc_backend_scdaemon): Register new function. + (gc_options_scdaemon): Make most options runtime changable. + 2009-01-20 Werner Koch * gpgconf.c (main): Print more directories. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 6af8e9027..66fe30dcb 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -104,7 +104,8 @@ gc_error (int status, int errnum, const char *fmt, ...) /* Forward declaration. */ -void gpg_agent_runtime_change (void); +static void gpg_agent_runtime_change (void); +static void scdaemon_runtime_change (void); /* Backend configuration. Backends are used to decide how the default and current value of an option can be determined, and how the @@ -181,7 +182,7 @@ static struct { "GPG Agent", "gpg-agent", GNUPG_MODULE_NAME_AGENT, gpg_agent_runtime_change, "gpgconf-gpg-agent.conf" }, { "SCDaemon", "scdaemon", GNUPG_MODULE_NAME_SCDAEMON, - NULL, "gpgconf-scdaemon.conf" }, + scdaemon_runtime_change, "gpgconf-scdaemon.conf" }, { "DirMngr", "dirmngr", GNUPG_MODULE_NAME_DIRMNGR, NULL, "gpgconf-dirmngr.conf" }, { "DirMngr LDAP Server List", NULL, 0, @@ -574,7 +575,7 @@ static gc_option_t gc_options_scdaemon[] = { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the diagnostic output") }, - { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, + { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, @@ -590,39 +591,39 @@ static gc_option_t gc_options_scdaemon[] = { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON }, - { "reader-port", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + { "reader-port", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "|N|connect to reader at port N", GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, - { "ctapi-driver", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + { "ctapi-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|NAME|use NAME as ct-API driver", GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, - { "pcsc-driver", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + { "pcsc-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|NAME|use NAME as PC/SC driver", GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, - { "disable-ccid", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + { "disable-ccid", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", "do not use the internal CCID driver", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, - { "disable-keypad", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + { "disable-keypad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "do not use a reader's keypad", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, - { "card-timeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + { "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "|N|disconnect the card after N seconds of inactivity", GC_ARG_TYPE_UINT32, GC_BACKEND_SCDAEMON }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "gnupg", N_("Options useful for debugging") }, - { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, + { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, - { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + { "log-file", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", N_("|FILE|write a log to FILE"), GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON }, { "Security", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the security") }, - { "deny-admin", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + { "deny-admin", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "deny the use of admin card commands", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, @@ -994,7 +995,7 @@ struct error_line_s /* Engine specific support. */ -void +static void gpg_agent_runtime_change (void) { #ifndef HAVE_W32_SYSTEM @@ -1045,6 +1046,27 @@ gpg_agent_runtime_change (void) } +static void +scdaemon_runtime_change (void) +{ + gpg_error_t err; + const char *pgmname; + const char *argv[2]; + pid_t pid; + + pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); + argv[0] = "scd killscd"; + argv[1] = NULL; + + err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid); + if (!err) + err = gnupg_wait_process (pgmname, pid, NULL); + if (err) + gc_error (0, 0, "error running `%s%s': %s", + pgmname, " scd killscd", gpg_strerror (err)); +} + + /* More or less Robust version of dgettext. It has the side effect of switching the codeset to utf-8 because this is what we want to