Fix a gpg2 problem with removed cards.

Allow runtime conf change for scdaemon.
New commands for scdaemon.
This commit is contained in:
Werner Koch 2009-02-27 14:36:59 +00:00
parent 618afc4231
commit ec4a3eb3c5
9 changed files with 143 additions and 16 deletions

4
NEWS
View File

@ -1,10 +1,12 @@
Noteworthy changes in version 2.0.11 (unreleased) 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. * 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 * The default cipher algorithm in GPGSM is now again 3DES. This is
due to interoperability problems with Outlook 2003 which still due to interoperability problems with Outlook 2003 which still
can't cope with AES. can't cope with AES.

View File

@ -1,3 +1,8 @@
2009-02-27 Werner Koch <wk@g10code.com>
* call-agent.c (agent_scd_pksign, agent_scd_pkdecrypt): First send
the SERIALNO command.
2009-02-24 Werner Koch <wk@g10code.com> 2009-02-24 Werner Koch <wk@g10code.com>
* pkglue.c (pk_verify): Return an error for improper DATA instead * pkglue.c (pk_verify): Return an error for improper DATA instead

View File

@ -698,6 +698,15 @@ agent_scd_pksign (const char *serialno, int hashalgo,
if (indatalen*2 + 50 > DIM(line)) if (indatalen*2 + 50 > DIM(line))
return gpg_error (GPG_ERR_GENERAL); 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 "); sprintf (line, "SCD SETDATA ");
p = line + strlen (line); p = line + strlen (line);
for (i=0; i < indatalen ; i++, p += 2 ) for (i=0; i < indatalen ; i++, p += 2 )
@ -754,6 +763,15 @@ agent_scd_pkdecrypt (const char *serialno,
if (indatalen*2 + 50 > DIM(line)) if (indatalen*2 + 50 > DIM(line))
return gpg_error (GPG_ERR_GENERAL); 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 "); sprintf (line, "SCD SETDATA ");
p = line + strlen (line); p = line + strlen (line);
for (i=0; i < indatalen ; i++, p += 2 ) for (i=0; i < indatalen ; i++, p += 2 )

View File

@ -1,3 +1,12 @@
2009-02-27 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com> 2009-02-25 Werner Koch <wk@g10code.com>
* apdu.c (apdu_get_status): Factor all code out to ... * apdu.c (apdu_get_status): Factor all code out to ...

View File

@ -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 check_application_conflict (ctrl_t ctrl, const char *name);
gpg_error_t select_application (ctrl_t ctrl, int slot, const char *name, gpg_error_t select_application (ctrl_t ctrl, int slot, const char *name,
app_t *r_app); app_t *r_app);
char *get_supported_applications (void);
void release_application (app_t app); void release_application (app_t app);
gpg_error_t app_munge_serialno (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); gpg_error_t app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp);

View File

@ -22,7 +22,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
# include <pth.h> #include <pth.h>
#include "scdaemon.h" #include "scdaemon.h"
#include "app-common.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; app->ref_count = 1;
log_debug ("USING application context (refcount=%u) (new)\n", app->ref_count);
lock_table[slot].app = app; lock_table[slot].app = app;
*r_app = app; *r_app = app;
unlock_reader (slot); 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. */ /* Deallocate the application. */
static void static void
deallocate_app (app_t app) deallocate_app (app_t app)

View File

@ -114,6 +114,11 @@ struct server_local_s
/* A disconnect command has been sent. */ /* A disconnect command has been sent. */
int disconnect_allowed; 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 deny_admin - Returns OK if admin commands are not allowed or
GPG_ERR_GENERAL if admin commands are allowed. 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 static int
@ -1628,6 +1636,15 @@ cmd_getinfo (assuan_context_t ctx, char *line)
} }
else if (!strcmp (line, "deny_admin")) else if (!strcmp (line, "deny_admin"))
rc = opt.allow_admin? gpg_error (GPG_ERR_GENERAL) : 0; 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 else
rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT"); rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
return rc; 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 }, { "RESTART", cmd_restart },
{ "DISCONNECT", cmd_disconnect }, { "DISCONNECT", cmd_disconnect },
{ "APDU", cmd_apdu }, { "APDU", cmd_apdu },
{ "KILLSCD", cmd_killscd },
{ NULL } { NULL }
}; };
int i, rc; int i, rc;
@ -1919,6 +1948,9 @@ scd_command_handler (ctrl_t ctrl, int fd)
/* Release the Assuan context. */ /* Release the Assuan context. */
assuan_deinit_server (ctx); assuan_deinit_server (ctx);
if (ctrl->server_local->stopme)
scd_exit (0);
/* If there are no more sessions return true. */ /* If there are no more sessions return true. */
return !session_list; return !session_list;
} }

View File

@ -1,3 +1,10 @@
2009-02-27 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com> 2009-01-20 Werner Koch <wk@g10code.com>
* gpgconf.c (main): Print more directories. * gpgconf.c (main): Print more directories.

View File

@ -104,7 +104,8 @@ gc_error (int status, int errnum, const char *fmt, ...)
/* Forward declaration. */ /* 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 /* 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
@ -181,7 +182,7 @@ static struct
{ "GPG Agent", "gpg-agent", GNUPG_MODULE_NAME_AGENT, { "GPG Agent", "gpg-agent", GNUPG_MODULE_NAME_AGENT,
gpg_agent_runtime_change, "gpgconf-gpg-agent.conf" }, gpg_agent_runtime_change, "gpgconf-gpg-agent.conf" },
{ "SCDaemon", "scdaemon", GNUPG_MODULE_NAME_SCDAEMON, { "SCDaemon", "scdaemon", GNUPG_MODULE_NAME_SCDAEMON,
NULL, "gpgconf-scdaemon.conf" }, scdaemon_runtime_change, "gpgconf-scdaemon.conf" },
{ "DirMngr", "dirmngr", GNUPG_MODULE_NAME_DIRMNGR, { "DirMngr", "dirmngr", GNUPG_MODULE_NAME_DIRMNGR,
NULL, "gpgconf-dirmngr.conf" }, NULL, "gpgconf-dirmngr.conf" },
{ "DirMngr LDAP Server List", NULL, 0, { "DirMngr LDAP Server List", NULL, 0,
@ -574,7 +575,7 @@ static gc_option_t gc_options_scdaemon[] =
{ "Monitor", { "Monitor",
GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
"gnupg", N_("Options controlling the diagnostic output") }, "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", "gnupg", "verbose",
GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
{ "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, { "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, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
"gnupg", "|FILE|read options from FILE", "gnupg", "|FILE|read options from FILE",
GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON }, 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", "gnupg", "|N|connect to reader at port N",
GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, 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", "gnupg", "|NAME|use NAME as ct-API driver",
GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, 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", "gnupg", "|NAME|use NAME as PC/SC driver",
GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, 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", "gnupg", "do not use the internal CCID driver",
GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, 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", "gnupg", "do not use a reader's keypad",
GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, 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", "gnupg", "|N|disconnect the card after N seconds of inactivity",
GC_ARG_TYPE_UINT32, GC_BACKEND_SCDAEMON }, GC_ARG_TYPE_UINT32, GC_BACKEND_SCDAEMON },
{ "Debug", { "Debug",
GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
"gnupg", N_("Options useful for debugging") }, "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", "gnupg", "|LEVEL|set the debugging level to LEVEL",
GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, 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"), "gnupg", N_("|FILE|write a log to FILE"),
GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON }, GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
{ "Security", { "Security",
GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
"gnupg", N_("Options controlling the security") }, "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", "gnupg", "deny the use of admin card commands",
GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
@ -994,7 +995,7 @@ struct error_line_s
/* Engine specific support. */ /* Engine specific support. */
void static void
gpg_agent_runtime_change (void) gpg_agent_runtime_change (void)
{ {
#ifndef HAVE_W32_SYSTEM #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 /* 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 switching the codeset to utf-8 because this is what we want to