Fix a gpg2 problem with removed cards.
authorWerner Koch <wk@gnupg.org>
Fri, 27 Feb 2009 14:36:59 +0000 (14:36 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 27 Feb 2009 14:36:59 +0000 (14:36 +0000)
Allow runtime conf change for scdaemon.
New commands for scdaemon.

NEWS
g10/ChangeLog
g10/call-agent.c
scd/ChangeLog
scd/app-common.h
scd/app.c
scd/command.c
tools/ChangeLog
tools/gpgconf-comp.c

diff --git a/NEWS b/NEWS
index 2a7f4e9..5e1cdb9 100644 (file)
--- 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.
index 91934e3..f081d82 100644 (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>
 
        * pkglue.c (pk_verify): Return an error for improper DATA instead
index 57d963d..572fa85 100644 (file)
@@ -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 )
index 2354443..1fd2de8 100644 (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>
 
        * apdu.c (apdu_get_status): Factor all code out to ...
index 5a45fa0..ad899a3 100644 (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 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);
index 4034fa6..d0b8328 100644 (file)
--- a/scd/app.c
+++ b/scd/app.c
@@ -22,7 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-# include <pth.h>
+#include <pth.h>
 
 #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)
index f3e374c..07a1e9b 100644 (file)
@@ -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);
+}
 
 
 \f
@@ -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;
 }
index 8c34741..dbe090f 100644 (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>
 
        * gpgconf.c (main): Print more directories.
index 6af8e90..66fe30d 100644 (file)
@@ -104,7 +104,8 @@ gc_error (int status, int errnum, const char *fmt, ...)
 
 \f
 /* 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
 
 \f
 /* 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));
+}
+
+
 \f
 /* 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