Preparing an interim release
authorWerner Koch <wk@gnupg.org>
Mon, 28 Nov 2005 11:52:25 +0000 (11:52 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 28 Nov 2005 11:52:25 +0000 (11:52 +0000)
32 files changed:
ChangeLog
NEWS
TODO
agent/ChangeLog
agent/agent.h
agent/call-scd.c
agent/command.c
agent/divert-scd.c
agent/minip12.c
agent/query.c
agent/t-protect.c
am/cmacros.am
configure.ac
kbx/keybox-blob.c
po/POTFILES.in
po/de.po
scd/ChangeLog
scd/apdu.c
scd/apdu.h
scd/app-dinsig.c
scd/app-nks.c
scd/app-openpgp.c
scd/app-p15.c
scd/ccid-driver.c
scd/ccid-driver.h
scd/iso7816.c
scd/iso7816.h
scd/scdaemon.c
scd/scdaemon.h
tools/ChangeLog
tools/gpgconf-comp.c
tools/rfc822parse.c

index f63a035..46d66ed 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2005-11-28  Werner Koch  <wk@g10code.com>
+
+       * configure.ac: Append the revision to the version string.
+
+2005-11-13  Werner Koch  <wk@g10code.com>
+
+       * am/cmacros.am (-DGNUPG_SYSCONFDIR): Define it.
+
+2005-11-11  Werner Koch  <wk@g10code.com>
+
+       * configure.ac (NEED_KSBA_VERSION: Require 0.9.13.
+
+2005-09-12  Werner Koch  <wk@g10code.com>
+
+       Released 1.9.19.
+
 2005-08-01  Werner Koch  <wk@g10code.com>
 
        Released 1.9.18.
 2005-08-01  Werner Koch  <wk@g10code.com>
 
        Released 1.9.18.
diff --git a/NEWS b/NEWS
index 1e11487..edf2988 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+Noteworthy changes in version 1.9.20
+-------------------------------------------------
+
+ * [scdaemon] Support for keypads of some readers.  Tested only with
+   SPR532. New option --disable-keypad.
+
+
 Noteworthy changes in version 1.9.19 (2005-09-12)
 -------------------------------------------------
 
 Noteworthy changes in version 1.9.19 (2005-09-12)
 -------------------------------------------------
 
diff --git a/TODO b/TODO
index 32b7285..50f58ce 100644 (file)
--- a/TODO
+++ b/TODO
@@ -26,7 +26,6 @@ might want to have an agent context for each service request
 * sm/gpgsm.c
 ** Support --output for all commands
 ** mark all unimplemented commands and options.
 * sm/gpgsm.c
 ** Support --output for all commands
 ** mark all unimplemented commands and options.
-** Print a hint when MD2 is the cause for a problem.
 ** Implement --default-key
 ** support the anyPolicy semantic
 ** Check that we are really following the verification procedures in rfc3280.
 ** Implement --default-key
 ** support the anyPolicy semantic
 ** Check that we are really following the verification procedures in rfc3280.
index 9754840..1051787 100644 (file)
@@ -1,3 +1,20 @@
+2005-11-24  Werner Koch  <wk@g10code.com>
+
+       * minip12.c (p12_parse): Fixed for case that the key object comes
+       prior to the certificate.
+
+2005-10-19  Werner Koch  <wk@g10code.com>
+
+       * divert-scd.c (getpin_cb): Hack to use it for a keypad message.
+
+       * call-scd.c (inq_needpin): Reworked to support the new KEYPADINFO.
+
+       * query.c (start_pinentry): Keep track of the owner.
+       (popup_message_thread, agent_popup_message_start) 
+       (agent_popup_message_stop, agent_reset_query): New.
+       * command.c (start_command_handler): Make sure a popup window gets
+       closed.
+
 2005-10-08  Marcus Brinkmann  <marcus@g10code.de>
 
        * Makefile.am (gpg_protect_tool_LDADD): Add ../gl/libgnu.a.
 2005-10-08  Marcus Brinkmann  <marcus@g10code.de>
 
        * Makefile.am (gpg_protect_tool_LDADD): Add ../gl/libgnu.a.
index 7a646a8..0918395 100644 (file)
@@ -133,7 +133,7 @@ struct server_control_s
   int have_keygrip;
 
   int use_auth_call; /* Hack to send the PKAUTH command instead of the
   int have_keygrip;
 
   int use_auth_call; /* Hack to send the PKAUTH command instead of the
-                        PKSIGN command tro scdaemon.  */
+                        PKSIGN command to the scdaemon.  */
 };
 typedef struct server_control_s *CTRL;
 typedef struct server_control_s *ctrl_t;
 };
 typedef struct server_control_s *CTRL;
 typedef struct server_control_s *ctrl_t;
@@ -200,6 +200,7 @@ int agent_key_available (const unsigned char *grip);
 /*-- query.c --*/
 void initialize_module_query (void);
 void agent_query_dump_state (void);
 /*-- query.c --*/
 void initialize_module_query (void);
 void agent_query_dump_state (void);
+void agent_reset_query (ctrl_t ctrl);
 int agent_askpin (ctrl_t ctrl,
                   const char *desc_text, const char *prompt_text,
                   const char *inital_errtext,
 int agent_askpin (ctrl_t ctrl,
                   const char *desc_text, const char *prompt_text,
                   const char *inital_errtext,
@@ -209,6 +210,10 @@ int agent_get_passphrase (ctrl_t ctrl, char **retpass,
                           const char *errtext);
 int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok,
                            const char *cancel);
                           const char *errtext);
 int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok,
                            const char *cancel);
+int agent_popup_message_start (ctrl_t ctrl, const char *desc,
+                               const char *ok_btn, const char *cancel_btn);
+void agent_popup_message_stop (ctrl_t ctrl);
+
 
 /*-- cache.c --*/
 void agent_flush_cache (void);
 
 /*-- cache.c --*/
 void agent_flush_cache (void);
index 7a623fd..a883f27 100644 (file)
@@ -633,26 +633,43 @@ inq_needpin (void *opaque, const char *line)
   size_t pinlen;
   int rc;
 
   size_t pinlen;
   int rc;
 
-  if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7])))
+  if (!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7]))
     {
     {
-      log_error ("unsupported inquiry `%s'\n", line);
-      return ASSUAN_Inquire_Unknown;
-    }
-  line += 7;
-  while (*line == ' ')
-    line++;
+      line += 7;
+      while (*line == ' ')
+        line++;
+      
+      pinlen = 90;
+      pin = gcry_malloc_secure (pinlen);
+      if (!pin)
+        return ASSUAN_Out_Of_Core;
 
 
-  pinlen = 90;
-  pin = gcry_malloc_secure (pinlen);
-  if (!pin)
-    return ASSUAN_Out_Of_Core;
+      rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
+      if (rc)
+        rc = ASSUAN_Canceled;
+      if (!rc)
+        rc = assuan_send_data (parm->ctx, pin, pinlen);
+      xfree (pin);
+    }
+  else if (!strncmp (line, "KEYPADINFO", 10) && (line[10] == ' ' || !line[10]))
+    {
+      size_t code;
+      char *endp;
 
 
-  rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
-  if (rc)
-    rc = ASSUAN_Canceled;
-  if (!rc)
-    rc = assuan_send_data (parm->ctx, pin, pinlen);
-  xfree (pin);
+      code = strtoul (line+10, &endp, 10);
+      line = endp;
+      while (*line == ' ')
+        line++;
+      
+      rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, code);
+      if (rc)
+        rc = ASSUAN_Canceled;
+    }
+  else
+    {
+      log_error ("unsupported inquiry `%s'\n", line);
+      rc = ASSUAN_Inquire_Unknown;
+    }
 
   return rc;
 }
 
   return rc;
 }
index c39bcc6..daf9b86 100644 (file)
@@ -316,11 +316,11 @@ cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
    this command is not used a default text will be used.  Note, that
    this description implictly selects the label used for the entry
    box; if the string contains the string PIN (which in general will
    this command is not used a default text will be used.  Note, that
    this description implictly selects the label used for the entry
    box; if the string contains the string PIN (which in general will
-   not be translated), "PIN" is used, other wiese the translation of
+   not be translated), "PIN" is used, otherwise the translation of
    'passphrase" is used.  The description string should not contain
    blanks unless they are percent or '+' escaped.
 
    'passphrase" is used.  The description string should not contain
    blanks unless they are percent or '+' escaped.
 
-   The descrition is only valid for the next PKSIGN or PKDECRYPT
+   The description is only valid for the next PKSIGN or PKDECRYPT
    operation.
 */
 static int
    operation.
 */
 static int
@@ -399,7 +399,7 @@ cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
 /* PKSIGN <options>
 
    Perform the actual sign operation. Neither input nor output are
 /* PKSIGN <options>
 
    Perform the actual sign operation. Neither input nor output are
-   sensitive to eavesdropping */
+   sensitive to eavesdropping. */
 static int
 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
 {
 static int
 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
 {
@@ -1085,6 +1085,9 @@ start_command_handler (int listen_fd, int fd)
   /* Reset the SCD if needed. */
   agent_reset_scd (&ctrl);
 
   /* Reset the SCD if needed. */
   agent_reset_scd (&ctrl);
 
+  /* Reset the pinentry (in case of popup messages). */
+  agent_reset_query (&ctrl);
+
   assuan_deinit_server (ctx);
   if (ctrl.display)
     free (ctrl.display);
   assuan_deinit_server (ctx);
   if (ctrl.display)
     free (ctrl.display);
index 9d2fa44..926df26 100644 (file)
@@ -204,7 +204,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
   const char *again_text = NULL;
   const char *prompt = "PIN";
 
   const char *again_text = NULL;
   const char *prompt = "PIN";
 
-  if (maxbuf < 2)
+  if (buf && maxbuf < 2)
     return gpg_error (GPG_ERR_INV_VALUE);
 
   /* Parse the flags. */
     return gpg_error (GPG_ERR_INV_VALUE);
 
   /* Parse the flags. */
@@ -223,6 +223,23 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
   else if (info && *info == '|')
     log_debug ("pin_cb called without proper PIN info hack\n");
 
   else if (info && *info == '|')
     log_debug ("pin_cb called without proper PIN info hack\n");
 
+  /* If BUF has been passed as NULL, we are in keypad mode: The
+     callback opens the popup and immediatley returns. */
+  if (!buf)
+    {
+      if (maxbuf == 0) /* Close the pinentry. */
+        {
+          agent_popup_message_stop (ctrl);
+          rc = 0;
+        }
+      else if (maxbuf == 1)  /* Open the pinentry. */
+        {
+          rc = agent_popup_message_start (ctrl, info, NULL, NULL);
+        }
+      else
+        rc = gpg_error (GPG_ERR_INV_VALUE);
+      return rc;
+    }
 
   /* FIXME: keep PI and TRIES in OPAQUE.  Frankly this is a whole
      mess because we should call the card's verify function from the
 
   /* FIXME: keep PI and TRIES in OPAQUE.  Frankly this is a whole
      mess because we should call the card's verify function from the
index 91eef63..55f3946 100644 (file)
@@ -511,7 +511,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
       goto bailout;
     }
 
       goto bailout;
     }
 
-  /* Loop over all certificates inside the bab. */
+  /* Loop over all certificates inside the bag. */
   while (n)
     {
       int isbag = 0;
   while (n)
     {
       int isbag = 0;
@@ -860,6 +860,7 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
   size_t n = length;
   const char *where;
   int bagseqlength, len;
   size_t n = length;
   const char *where;
   int bagseqlength, len;
+  gcry_mpi_t *result = NULL;
 
   where = "pfx";
   if (parse_tag (&p, &n, &ti))
 
   where = "pfx";
   if (parse_tag (&p, &n, &ti))
@@ -936,10 +937,17 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
       else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data)
           && !memcmp (p, oid_data, DIM(oid_data)))
         {
       else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data)
           && !memcmp (p, oid_data, DIM(oid_data)))
         {
-          p += DIM(oid_data);
-          n -= DIM(oid_data);
-          len -= DIM(oid_data);
-          return parse_bag_data (p, n, (p-buffer), pw);
+          if (result)
+            log_info ("already got an data object, skipping next one\n");
+          else
+            {
+              p += DIM(oid_data);
+              n -= DIM(oid_data);
+              len -= DIM(oid_data);
+              result = parse_bag_data (p, n, (p-buffer), pw);
+              if (!result)
+                goto bailout;
+            }
         }
       else
         log_info ( "unknown bag type - skipped\n");
         }
       else
         log_info ( "unknown bag type - skipped\n");
@@ -950,9 +958,10 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
       n -= len;
     }
   
       n -= len;
     }
   
-  return NULL;
+  return result;
  bailout:
   log_error ("error at \"%s\", offset %u\n", where, (p - buffer));
  bailout:
   log_error ("error at \"%s\", offset %u\n", where, (p - buffer));
+  /* fixme: need to release RESULT. */
   return NULL;
 }
 
   return NULL;
 }
 
index b231f6f..a5a3d01 100644 (file)
 #include <assert.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #include <assert.h>
 #include <unistd.h>
 #include <sys/stat.h>
-#ifdef USE_GNU_PTH
-# include <pth.h>
+#ifndef HAVE_W32_SYSTEM
+#include <sys/wait.h>
 #endif
 #endif
+#include <pth.h>
 
 #include "agent.h"
 #include "i18n.h"
 
 #include "agent.h"
 #include "i18n.h"
    time. */
 #define LOCK_TIMEOUT  (1*60)
 
    time. */
 #define LOCK_TIMEOUT  (1*60)
 
+/* The assuan context of the current pinentry. */
+static assuan_context_t entry_ctx;
 
 
-static assuan_context_t entry_ctx = NULL;
-#ifdef USE_GNU_PTH
+/* The control variable of the connection owning the current pinentry.
+   This is only valid if ENTRY_CTX is not NULL.  Note, that we care
+   only about the value of the pointer and that it should never be
+   dereferenced.  */
+static ctrl_t entry_owner;
+
+/* A mutex used to serialize access to the pinentry. */
 static pth_mutex_t entry_lock;
 static pth_mutex_t entry_lock;
-#endif
 
 
-/* data to be passed to our callbacks */
-struct entry_parm_s {
+/* The thread ID of the popup working thread. */
+static pth_t  popup_tid;
+
+/* A flag used in communication between the popup working thread and
+   its stop function. */
+static int popup_finished;
+
+
+
+/* Data to be passed to our callbacks, */
+struct entry_parm_s
+{
   int lines;
   size_t size;
   unsigned char *buffer;
   int lines;
   size_t size;
   unsigned char *buffer;
@@ -67,17 +84,17 @@ struct entry_parm_s {
 /* This function must be called once to initialize this module.  This
    has to be done before a second thread is spawned.  We can't do the
    static initialization because Pth emulation code might not be able
 /* This function must be called once to initialize this module.  This
    has to be done before a second thread is spawned.  We can't do the
    static initialization because Pth emulation code might not be able
-   to do a static init; in particualr, it is not possible for W32. */
+   to do a static init; in particular, it is not possible for W32. */
 void
 initialize_module_query (void)
 {
 void
 initialize_module_query (void)
 {
-#ifdef USE_GNU_PTH
   static int initialized;
 
   if (!initialized)
   static int initialized;
 
   if (!initialized)
-    if (pth_mutex_init (&entry_lock))
-      initialized = 1;
-#endif /*USE_GNU_PTH*/
+    {
+      if (pth_mutex_init (&entry_lock))
+        initialized = 1;
+    }
 }
 
 
 }
 
 
@@ -102,8 +119,19 @@ agent_query_dump_state (void)
   log_info ("agent_query_dump_state: entry_lock=");
   dump_mutex_state (&entry_lock);
   log_printf ("\n");
   log_info ("agent_query_dump_state: entry_lock=");
   dump_mutex_state (&entry_lock);
   log_printf ("\n");
-  log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld\n",
-            entry_ctx, (long)assuan_get_pid (entry_ctx));
+  log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
+            entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid);
+}
+
+/* Called to make sure that a popup window owned by the current
+   connection gets closed. */
+void
+agent_reset_query (ctrl_t ctrl)
+{
+  if (entry_ctx && popup_tid && entry_owner == ctrl)
+    {
+      agent_popup_message_stop (ctrl);
+    }
 }
 
 
 }
 
 
@@ -117,14 +145,12 @@ unlock_pinentry (int rc)
   assuan_context_t ctx = entry_ctx;
 
   entry_ctx = NULL;
   assuan_context_t ctx = entry_ctx;
 
   entry_ctx = NULL;
-#ifdef USE_GNU_PTH
   if (!pth_mutex_release (&entry_lock))
     {
       log_error ("failed to release the entry lock\n");
       if (!rc)
         rc = gpg_error (GPG_ERR_INTERNAL);
     }
   if (!pth_mutex_release (&entry_lock))
     {
       log_error ("failed to release the entry lock\n");
       if (!rc)
         rc = gpg_error (GPG_ERR_INTERNAL);
     }
-#endif
   assuan_disconnect (ctx);
   return rc;
 }
   assuan_disconnect (ctx);
   return rc;
 }
@@ -145,7 +171,7 @@ atfork_cb (void *opaque, int where)
    pinentry - we will serialize _all_ pinentry calls.
  */
 static int
    pinentry - we will serialize _all_ pinentry calls.
  */
 static int
-start_pinentry (CTRL ctrl)
+start_pinentry (ctrl_t ctrl)
 {
   int rc;
   const char *pgmname;
 {
   int rc;
   const char *pgmname;
@@ -153,13 +179,10 @@ start_pinentry (CTRL ctrl)
   const char *argv[5];
   int no_close_list[3];
   int i;
   const char *argv[5];
   int no_close_list[3];
   int i;
+  pth_event_t evt;
 
 
-#ifdef USE_GNU_PTH
- {
-   pth_event_t evt;
-
-   evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
-   if (!pth_mutex_acquire (&entry_lock, 0, evt))
+  evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
+  if (!pth_mutex_acquire (&entry_lock, 0, evt))
     {
       if (pth_event_occurred (evt))
         rc = gpg_error (GPG_ERR_TIMEOUT);
     {
       if (pth_event_occurred (evt))
         rc = gpg_error (GPG_ERR_TIMEOUT);
@@ -170,9 +193,9 @@ start_pinentry (CTRL ctrl)
                  gpg_strerror (rc));
       return rc;
     }
                  gpg_strerror (rc));
       return rc;
     }
-   pth_event_free (evt, PTH_FREE_THIS);
- }
-#endif
+  pth_event_free (evt, PTH_FREE_THIS);
+
+  entry_owner = ctrl;
 
   if (entry_ctx)
     return 0; 
 
   if (entry_ctx)
     return 0; 
@@ -436,7 +459,7 @@ agent_askpin (ctrl_t ctrl,
    passphrase is returned in RETPASS as an hex encoded string to be
    freed by the caller */
 int 
    passphrase is returned in RETPASS as an hex encoded string to be
    freed by the caller */
 int 
-agent_get_passphrase (CTRL ctrl,
+agent_get_passphrase (ctrl_t ctrl,
                       char **retpass, const char *desc, const char *prompt,
                       const char *errtext)
 {
                       char **retpass, const char *desc, const char *prompt,
                       const char *errtext)
 {
@@ -517,11 +540,11 @@ agent_get_passphrase (CTRL ctrl,
 
 \f
 /* Pop up the PIN-entry, display the text and the prompt and ask the
 
 \f
 /* Pop up the PIN-entry, display the text and the prompt and ask the
-   user to confirm this.  We return 0 for success, ie. the used
+   user to confirm this.  We return 0 for success, ie. the user
    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
    other error. */
 int 
    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
    other error. */
 int 
-agent_get_confirmation (CTRL ctrl,
+agent_get_confirmation (ctrl_t ctrl,
                         const char *desc, const char *ok, const char *cancel)
 {
   int rc;
                         const char *desc, const char *ok, const char *cancel)
 {
   int rc;
@@ -562,4 +585,119 @@ agent_get_confirmation (CTRL ctrl,
 }
 
 
 }
 
 
+/* The thread running the popup message. */
+static void *
+popup_message_thread (void *arg)
+{
+  assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
+  popup_finished = 1;
+  return NULL;
+}
+
+
+/* Pop up a message window similar to the confirm one but keep it open
+   until agent_popup_message_stop has been called.  It is crucial for
+   the caller to make sure that the stop function gets called as soon
+   as the message is not anymore required becuase the message is
+   system modal and all other attempts to use the pinentry will fail
+   (after a timeout). */
+int 
+agent_popup_message_start (ctrl_t ctrl, const char *desc,
+                           const char *ok_btn, const char *cancel_btn)
+{
+  int rc;
+  char line[ASSUAN_LINELENGTH];
+  pth_attr_t tattr;
+
+  rc = start_pinentry (ctrl);
+  if (rc)
+    return rc;
+
+  if (desc)
+    snprintf (line, DIM(line)-1, "SETDESC %s", desc);
+  else
+    snprintf (line, DIM(line)-1, "RESET");
+  line[DIM(line)-1] = 0;
+  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+  if (rc)
+    return unlock_pinentry (map_assuan_err (rc));
+
+  if (ok_btn)
+    {
+      snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
+      line[DIM(line)-1] = 0;
+      rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
+      if (rc)
+        return unlock_pinentry (map_assuan_err (rc));
+    }
+  if (cancel_btn)
+    {
+      snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel_btn);
+      line[DIM(line)-1] = 0;
+      rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
+      if (rc)
+        return unlock_pinentry (map_assuan_err (rc));
+    }
+
+  tattr = pth_attr_new();
+  pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
+  pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
+  pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
+
+  popup_finished = 0;
+  popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
+  if (!popup_tid)
+    {
+      rc = gpg_error_from_errno (errno);
+      log_error ("error spawning popup message handler: %s\n",
+                 strerror (errno) );
+      pth_attr_destroy (tattr);
+      return unlock_pinentry (rc);
+    }
+  pth_attr_destroy (tattr);
+
+  return 0;
+}
+
+/* Close a popup window. */
+void
+agent_popup_message_stop (ctrl_t ctrl)
+{
+  int rc;
+  pid_t pid;
+
+  if (!popup_tid || !entry_ctx)
+    {
+      log_debug ("agent_popup_message_stop called with no active popup\n");
+      return; 
+    }
+
+  pid = assuan_get_pid (entry_ctx);
+  if (pid == (pid_t)(-1))
+    ; /* No pid available can't send a kill. */
+  else if (popup_finished)
+    ; /* Already finished and ready for joining. */
+  else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
+    { /* The daemon already died.  No need to send a kill.  However
+         because we already waited for the process, we need to tell
+         assuan that it should not wait again (done by
+         unlock_pinentry). */
+      if (rc == pid)
+        assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
+    }
+  else
+    kill (pid, SIGINT);
+
+  /* Now wait for the thread to terminate. */
+  rc = pth_join (popup_tid, NULL);
+  if (!rc)
+    log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
+               strerror (errno));
+  popup_tid = NULL;
+  entry_owner = NULL;
+
+  /* Now we can close the connection. */
+  unlock_pinentry (0);
+}
+
 
 
index 5187cf8..fee3c56 100644 (file)
@@ -173,7 +173,8 @@ test_agent_protect (void)
 
   for (i = 0; i < DIM (specs); i++)
     {
 
   for (i = 0; i < DIM (specs); i++)
     {
-      ret = agent_protect (specs[i].key, specs[i].passphrase,
+      ret = agent_protect ((const unsigned char*)specs[i].key,
+                           specs[i].passphrase,
                           &specs[i].result, &specs[i].resultlen);
       if (gpg_err_code (ret) != specs[i].ret_expected)
        {
                           &specs[i].result, &specs[i].resultlen);
       if (gpg_err_code (ret) != specs[i].ret_expected)
        {
index 0f7a09f..de68b6f 100644 (file)
@@ -25,7 +25,8 @@ if ! HAVE_DOSISH_SYSTEM
 AM_CPPFLAGS += -DGNUPG_BINDIR="\"$(bindir)\""            \
                -DGNUPG_LIBEXECDIR="\"$(libexecdir)\""    \
                -DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\""  \
 AM_CPPFLAGS += -DGNUPG_BINDIR="\"$(bindir)\""            \
                -DGNUPG_LIBEXECDIR="\"$(libexecdir)\""    \
                -DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\""  \
-               -DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\""
+               -DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\"" \
+               -DGNUPG_SYSCONFDIR="\"$(sysconfdir)/@PACKAGE@\""
 endif
 
 if GNUPG_AGENT_PGM
 endif
 
 if GNUPG_AGENT_PGM
index 30b1830..6ba6696 100644 (file)
 AC_PREREQ(2.52)
 min_automake_version="1.9.3"
 
 AC_PREREQ(2.52)
 min_automake_version="1.9.3"
 
-# Version number: Remember to change it immediately *after* a release.
-#                 Add a "-cvs" prefix for non-released code.
-AC_INIT(gnupg, 1.9.19, gnupg-devel@gnupg.org)
+# Remember to change the version number immediately *after* a release.
+# Uncomment the my_iscvs macro for non-released code.
+m4_define(my_version, [1.9.20])
+m4_define(my_iscvs, yes)
+AC_INIT([gnupg], my_version[]m4_ifdef([my_iscvs], [-cvs[]m4_translit(
+                 [$Revision$],[Ra-z $:])]), [gnupg-devel@gnupg.org])
 # Set development_version to yes if the minor number is odd or you
 # feel that the default check for a development version is not
 # sufficient.
 # Set development_version to yes if the minor number is odd or you
 # feel that the default check for a development version is not
 # sufficient.
@@ -36,7 +39,7 @@ NEED_LIBGCRYPT_VERSION=1.1.94
 
 NEED_LIBASSUAN_VERSION=0.6.10
 
 
 NEED_LIBASSUAN_VERSION=0.6.10
 
-NEED_KSBA_VERSION=0.9.12
+NEED_KSBA_VERSION=0.9.13
 
 
 PACKAGE=$PACKAGE_NAME
 
 
 PACKAGE=$PACKAGE_NAME
index 67c74b7..eacc001 100644 (file)
@@ -61,7 +61,7 @@ X.509 specific are noted like [X.509: xxx]
    u32 offset to the n-th key's keyID (a keyID is always 8 byte)
         or 0 if not known which is the case only for X509.
    u16 special key flags
    u32 offset to the n-th key's keyID (a keyID is always 8 byte)
         or 0 if not known which is the case only for X509.
    u16 special key flags
-        bit 0 =
+        bit 0 = qualified signature (not yet implemented}
    u16 reserved
  u16  size of serialnumber(may be zero) 
    n  u16 (see above) bytes of serial number
    u16 reserved
  u16  size of serialnumber(may be zero) 
    n  u16 (see above) bytes of serial number
index 8fff858..eb5711d 100644 (file)
@@ -17,6 +17,7 @@ kbx/kbxutil.c
 
 scd/scdaemon.c
 scd/app-openpgp.c
 
 scd/scdaemon.c
 scd/app-openpgp.c
+scd/app-nks.c
 
 sm/base64.c
 sm/call-agent.c
 
 sm/base64.c
 sm/call-agent.c
index 6b28544..2201c04 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -10,8 +10,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnupg2 1.9.18\n"
 "Report-Msgid-Bugs-To: translations@gnupg.org\n"
 msgstr ""
 "Project-Id-Version: gnupg2 1.9.18\n"
 "Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"POT-Creation-Date: 2005-11-23 13:00+0100\n"
-"PO-Revision-Date: 2005-11-23 13:02+0100\n"
+"POT-Creation-Date: 2005-11-28 12:14+0100\n"
+"PO-Revision-Date: 2005-11-28 12:16+0100\n"
 "Last-Translator: Werner Koch <wk@gnupg.org>\n"
 "Language-Team: de\n"
 "MIME-Version: 1.0\n"
 "Last-Translator: Werner Koch <wk@gnupg.org>\n"
 "Language-Team: de\n"
 "MIME-Version: 1.0\n"
@@ -766,6 +766,10 @@ msgstr ""
 msgid "can't access %s - invalid OpenPGP card?\n"
 msgstr "Zugriff auf %s nicht möglich - ungültige OpenPGP Karte?\n"
 
 msgid "can't access %s - invalid OpenPGP card?\n"
 msgstr "Zugriff auf %s nicht möglich - ungültige OpenPGP Karte?\n"
 
+#: scd/app-nks.c:344
+msgid "the NullPIN has not yet been changed\n"
+msgstr "Die Nullpin wurde noch nicht geändert\n"
+
 #: sm/base64.c:317
 #, c-format
 msgid "invalid radix64 character %02x skipped\n"
 #: sm/base64.c:317
 #, c-format
 msgid "invalid radix64 character %02x skipped\n"
@@ -1369,7 +1373,7 @@ msgstr "Signieren mit `%s' nicht möglich: %s\n"
 
 #: sm/gpgsm.c:1475
 msgid "this command has not yet been implemented\n"
 
 #: sm/gpgsm.c:1475
 msgid "this command has not yet been implemented\n"
-msgstr "Diee Kommando wurde noch nicht implementiert\n"
+msgstr "Dieses Kommando wurde noch nicht implementiert\n"
 
 #: sm/gpgsm.c:1705 sm/gpgsm.c:1742 sm/qualified.c:73
 #, c-format
 
 #: sm/gpgsm.c:1705 sm/gpgsm.c:1742 sm/qualified.c:73
 #, c-format
@@ -1548,10 +1552,10 @@ msgid ""
 msgstr ""
 "Sie sind dabei, eine Signatur mit dem Zertifikat:\n"
 "\"%s\"\n"
 msgstr ""
 "Sie sind dabei, eine Signatur mit dem Zertifikat:\n"
 "\"%s\"\n"
-"zu erzeugen.  Dies wird einen qualifizierte Signatur erzeugen, \n"
-"die gesetzlich einer handgeschriebene gleichgestellt ist.\n"
+"zu erzeugen.  Dies wird eine qualifizierte Signatur erzeugen, \n"
+"die gesetzlich einer handgeschriebenen gleichgestellt ist.\n"
 "\n"
 "\n"
-"%s%sSind Sie wirklich sicher, da Sie dies möchten?"
+"%s%sSind Sie wirklich sicher, daß Sie dies möchten?"
 
 #: sm/qualified.c:224
 msgid ""
 
 #: sm/qualified.c:224
 msgid ""
index ccea117..008d840 100644 (file)
@@ -1,8 +1,63 @@
+2005-11-23  Werner Koch  <wk@g10code.com>
+
+       * app-nks.c (verify_pin): Give a special error message for a Nullpin.
+
+2005-10-29  Werner Koch  <wk@g10code.com>
+
+       * ccid-driver.c (send_escape_cmd): New args RESULT, RESULTLEN and
+       RESULTMAX.  Changed all callers.
+       (ccid_transceive_escape): New.
+
+2005-10-27  Werner Koch  <wk@g10code.com>
+
+       * apdu.c [__CYGWIN__]: Make cygwin environment similar to _WIN32.
+       Suggested by John P. Clizbe.
+       * scdaemon.c [__CYGWIN__]: Set default PC/SC driver to winscard.dll.
+
+2005-10-19  Werner Koch  <wk@g10code.com>
+
+       * ccid-driver.h (CCID_DRIVER_ERR_NO_KEYPAD): New.
+       * apdu.h (SW_HOST_NO_KEYPAD): New.
+       * iso7816.h (struct iso7816_pininfo_s): New.
+       * iso7816.c (map_sw): Support new code.
+       (iso7816_check_keypad): New.
+       (iso7816_verify_kp, iso7816_change_reference_data_kp) 
+       (iso7816_reset_retry_counter_kp): New.  Extended versions of the
+       original functions.
+       * apdu.c (host_sw_string): Support new code. 
+       (reader_table_s): New field CHECK_KEYPAD.
+       (new_reader_slot, open_ct_reader, open_pcsc_reader) 
+       (open_ccid_reader, open_rapdu_reader): Initialize it.
+       (check_ccid_keypad): New.
+       (apdu_check_keypad): New.
+       (apdu_send_le): Factored all code out to ...
+       (send_le): .. new.  Takes an additional arg; changed all callers
+       of the orginal function to use this one with a NULL for the new
+       arg.
+       (apdu_send_simple_kp): New.
+       (ct_send_apdu, pcsc_send_apdu, my_rapdu_send_apdu) 
+       (send_apdu_ccid): New arg PININFO.
+       (send_apdu_ccid): Use the new arg.
+
+       * scdaemon.c: New option --disable-keypad.
+
 2005-10-08  Marcus Brinkmann  <marcus@g10code.de>
 
        * Makefile.am (scdaemon_LDADD): Add ../gl/libgnu.a after
        ../common/libcommon.a.
 
 2005-10-08  Marcus Brinkmann  <marcus@g10code.de>
 
        * Makefile.am (scdaemon_LDADD): Add ../gl/libgnu.a after
        ../common/libcommon.a.
 
+2005-09-20  Werner Koch  <wk@g10code.com>
+
+       * app-dinsig.c (verify_pin): Try ISO 9564 BCD encoding.
+
+       * iso7816.c (iso7816_select_application): Add arg FLAGS.  Changed
+       all callers to pass 0.
+       * app-openpgp.c (app_select_openpgp): But this one requires a
+       special flag.
+
+       * app-p15.c (app_select_p15): Don't use select application for the
+       BELPIC.
+
 2005-09-09  Werner Koch  <wk@g10code.com>
 
        * pcsc-wrapper.c (main): Removed bogus free.
 2005-09-09  Werner Koch  <wk@g10code.com>
 
        * pcsc-wrapper.c (main): Removed bogus free.
index 678ea12..f59d832 100644 (file)
 #include "ccid-driver.h"
 
 
 #include "ccid-driver.h"
 
 
-/* To to conflicting use of threading libraries we usually can't link
+/* Due to conflicting use of threading libraries we usually can't link
    against libpcsclite.   Instead we use a wrapper program.  */
 #ifdef USE_GNU_PTH
    against libpcsclite.   Instead we use a wrapper program.  */
 #ifdef USE_GNU_PTH
-#ifndef HAVE_W32_SYSTEM
+#if !defined(HAVE_W32_SYSTEM) && !defined(__CYGWIN__)
 #define NEED_PCSC_WRAPPER 1
 #endif
 #endif
 #define NEED_PCSC_WRAPPER 1
 #endif
 #endif
@@ -78,7 +78,7 @@
 #define MAX_READER 4 /* Number of readers we support concurrently. */
 
 
 #define MAX_READER 4 /* Number of readers we support concurrently. */
 
 
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
 #define DLSTDCALL __stdcall
 #else
 #define DLSTDCALL
 #define DLSTDCALL __stdcall
 #else
 #define DLSTDCALL
 #define MAX_OPEN_FDS 20
 #endif
 
 #define MAX_OPEN_FDS 20
 #endif
 
+/* Helper to pass patrameters related to keypad based operations. */
+struct pininfo_s
+{
+  int mode;
+  int minlen;
+  int maxlen;
+  int padlen;
+};
 
 /* A structure to collect information pertaining to one reader
    slot. */
 
 /* A structure to collect information pertaining to one reader
    slot. */
@@ -103,7 +111,8 @@ struct reader_table_s {
   int (*reset_reader)(int);
   int (*get_status_reader)(int, unsigned int *);
   int (*send_apdu_reader)(int,unsigned char *,size_t,
   int (*reset_reader)(int);
   int (*get_status_reader)(int, unsigned int *);
   int (*send_apdu_reader)(int,unsigned char *,size_t,
-                          unsigned char *, size_t *);
+                          unsigned char *, size_t *, struct pininfo_s *);
+  int (*check_keypad)(int, int, int, int, int, int);
   void (*dump_status_reader)(int);
 
   struct {
   void (*dump_status_reader)(int);
 
   struct {
@@ -320,6 +329,7 @@ new_reader_slot (void)
   reader_table[reader].reset_reader = NULL;
   reader_table[reader].get_status_reader = NULL;
   reader_table[reader].send_apdu_reader = NULL;
   reader_table[reader].reset_reader = NULL;
   reader_table[reader].get_status_reader = NULL;
   reader_table[reader].send_apdu_reader = NULL;
+  reader_table[reader].check_keypad = NULL;
   reader_table[reader].dump_status_reader = NULL;
 
   reader_table[reader].used = 1;
   reader_table[reader].dump_status_reader = NULL;
 
   reader_table[reader].used = 1;
@@ -372,6 +382,7 @@ host_sw_string (long err)
     case SW_HOST_GENERAL_ERROR: return "general error";
     case SW_HOST_NO_READER: return "no reader";
     case SW_HOST_ABORTED: return "aborted";
     case SW_HOST_GENERAL_ERROR: return "general error";
     case SW_HOST_NO_READER: return "no reader";
     case SW_HOST_ABORTED: return "aborted";
+    case SW_HOST_NO_KEYPAD: return "no keypad"; 
     default: return "unknown host status error";
     }
 }
     default: return "unknown host status error";
     }
 }
@@ -533,7 +544,7 @@ ct_get_status (int slot, unsigned int *status)
    set to BUFLEN.  Returns: CT API error code. */
 static int
 ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
    set to BUFLEN.  Returns: CT API error code. */
 static int
 ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
-              unsigned char *buffer, size_t *buflen)
+              unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo)
 {
   int rc;
   unsigned char dad[1], sad[1];
 {
   int rc;
   unsigned char dad[1], sad[1];
@@ -596,6 +607,7 @@ open_ct_reader (int port)
   reader_table[reader].reset_reader = reset_ct_reader;
   reader_table[reader].get_status_reader = ct_get_status;
   reader_table[reader].send_apdu_reader = ct_send_apdu;
   reader_table[reader].reset_reader = reset_ct_reader;
   reader_table[reader].get_status_reader = ct_get_status;
   reader_table[reader].send_apdu_reader = ct_send_apdu;
+  reader_table[reader].check_keypad = NULL;
   reader_table[reader].dump_status_reader = ct_dump_reader_status;
 
   dump_reader_status (reader);
   reader_table[reader].dump_status_reader = ct_dump_reader_status;
 
   dump_reader_status (reader);
@@ -1082,7 +1094,8 @@ pcsc_get_status (int slot, unsigned int *status)
    set to BUFLEN.  Returns: CT API error code. */
 static int
 pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
    set to BUFLEN.  Returns: CT API error code. */
 static int
 pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
-                unsigned char *buffer, size_t *buflen)
+                unsigned char *buffer, size_t *buflen, 
+                struct pininfo_s *pininfo)
 {
 #ifdef NEED_PCSC_WRAPPER
   long err;
 {
 #ifdef NEED_PCSC_WRAPPER
   long err;
@@ -1479,6 +1492,7 @@ open_pcsc_reader (const char *portstr)
   reader_table[slot].reset_reader = reset_pcsc_reader;
   reader_table[slot].get_status_reader = pcsc_get_status;
   reader_table[slot].send_apdu_reader = pcsc_send_apdu;
   reader_table[slot].reset_reader = reset_pcsc_reader;
   reader_table[slot].get_status_reader = pcsc_get_status;
   reader_table[slot].send_apdu_reader = pcsc_send_apdu;
+  reader_table[slot].check_keypad = NULL;
   reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
 
   /* Read the status so that IS_T0 will be set. */
   reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
 
   /* Read the status so that IS_T0 will be set. */
@@ -1625,6 +1639,7 @@ open_pcsc_reader (const char *portstr)
   reader_table[slot].reset_reader = reset_pcsc_reader;
   reader_table[slot].get_status_reader = pcsc_get_status;
   reader_table[slot].send_apdu_reader = pcsc_send_apdu;
   reader_table[slot].reset_reader = reset_pcsc_reader;
   reader_table[slot].get_status_reader = pcsc_get_status;
   reader_table[slot].send_apdu_reader = pcsc_send_apdu;
+  reader_table[slot].check_keypad = NULL;
   reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
 
 /*   log_debug ("state    from pcsc_status: 0x%lx\n", card_state); */
   reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
 
 /*   log_debug ("state    from pcsc_status: 0x%lx\n", card_state); */
@@ -1713,7 +1728,8 @@ get_status_ccid (int slot, unsigned int *status)
    set to BUFLEN.  Returns: Internal CCID driver error code. */
 static int
 send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
    set to BUFLEN.  Returns: Internal CCID driver error code. */
 static int
 send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
-                unsigned char *buffer, size_t *buflen)
+                unsigned char *buffer, size_t *buflen,
+                struct pininfo_s *pininfo)
 {
   long err;
   size_t maxbuflen;
 {
   long err;
   size_t maxbuflen;
@@ -1727,9 +1743,18 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
     log_printhex ("  APDU_data:", apdu, apdulen);
 
   maxbuflen = *buflen;
     log_printhex ("  APDU_data:", apdu, apdulen);
 
   maxbuflen = *buflen;
-  err = ccid_transceive (reader_table[slot].ccid.handle,
-                         apdu, apdulen,
-                         buffer, maxbuflen, buflen);
+  if (pininfo)
+    err = ccid_transceive_secure (reader_table[slot].ccid.handle,
+                                  apdu, apdulen,
+                                  pininfo->mode,
+                                  pininfo->minlen,
+                                  pininfo->maxlen,
+                                  pininfo->padlen,
+                                  buffer, maxbuflen, buflen);
+  else
+    err = ccid_transceive (reader_table[slot].ccid.handle,
+                           apdu, apdulen,
+                           buffer, maxbuflen, buflen);
   if (err)
     log_error ("ccid_transceive failed: (0x%lx)\n",
                err);
   if (err)
     log_error ("ccid_transceive failed: (0x%lx)\n",
                err);
@@ -1737,6 +1762,24 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
   return err;
 }
 
   return err;
 }
 
+
+/* Check whether the CCID reader supports the ISO command code COMMAND
+   on the keypad.  Return 0 on success.  For a description of the pin
+   parameters, see ccid-driver.c */
+static int
+check_ccid_keypad (int slot, int command, int pin_mode,
+                   int pinlen_min, int pinlen_max, int pin_padlen)
+{
+  unsigned char apdu[] = { 0, 0, 0, 0x81 };
+
+  apdu[1] = command;
+  return ccid_transceive_secure (reader_table[slot].ccid.handle,
+                                 apdu, sizeof apdu,
+                                 pin_mode, pinlen_min, pinlen_max, pin_padlen,
+                                 NULL, 0, NULL);
+}
+
+
 /* Open the reader and try to read an ATR.  */
 static int
 open_ccid_reader (const char *portstr)
 /* Open the reader and try to read an ATR.  */
 static int
 open_ccid_reader (const char *portstr)
@@ -1776,6 +1819,7 @@ open_ccid_reader (const char *portstr)
   reader_table[slot].reset_reader = reset_ccid_reader;
   reader_table[slot].get_status_reader = get_status_ccid;
   reader_table[slot].send_apdu_reader = send_apdu_ccid;
   reader_table[slot].reset_reader = reset_ccid_reader;
   reader_table[slot].get_status_reader = get_status_ccid;
   reader_table[slot].send_apdu_reader = send_apdu_ccid;
+  reader_table[slot].check_keypad = check_ccid_keypad;
   reader_table[slot].dump_status_reader = dump_ccid_reader_status;
 
   dump_reader_status (slot);
   reader_table[slot].dump_status_reader = dump_ccid_reader_status;
 
   dump_reader_status (slot);
@@ -1932,7 +1976,8 @@ my_rapdu_get_status (int slot, unsigned int *status)
    set to BUFLEN.  Returns: APDU error code. */
 static int
 my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
    set to BUFLEN.  Returns: APDU error code. */
 static int
 my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
-                    unsigned char *buffer, size_t *buflen)
+                    unsigned char *buffer, size_t *buflen,
+                    struct pininfo_s *pininfo)
 {
   int err;
   reader_table_t slotp;
 {
   int err;
   reader_table_t slotp;
@@ -2063,6 +2108,7 @@ open_rapdu_reader (int portno,
   reader_table[slot].reset_reader = reset_rapdu_reader;
   reader_table[slot].get_status_reader = my_rapdu_get_status;
   reader_table[slot].send_apdu_reader = my_rapdu_send_apdu;
   reader_table[slot].reset_reader = reset_rapdu_reader;
   reader_table[slot].get_status_reader = my_rapdu_get_status;
   reader_table[slot].send_apdu_reader = my_rapdu_send_apdu;
+  reader_table[slot].check_keypad = NULL;
   reader_table[slot].dump_status_reader = NULL;
 
   dump_reader_status (slot);
   reader_table[slot].dump_status_reader = NULL;
 
   dump_reader_status (slot);
@@ -2198,28 +2244,28 @@ apdu_open_reader (const char *portstr)
       pcsc_establish_context = dlsym (handle, "SCardEstablishContext");
       pcsc_release_context   = dlsym (handle, "SCardReleaseContext");
       pcsc_list_readers      = dlsym (handle, "SCardListReaders");
       pcsc_establish_context = dlsym (handle, "SCardEstablishContext");
       pcsc_release_context   = dlsym (handle, "SCardReleaseContext");
       pcsc_list_readers      = dlsym (handle, "SCardListReaders");
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
       if (!pcsc_list_readers)
         pcsc_list_readers    = dlsym (handle, "SCardListReadersA");
 #endif
       pcsc_get_status_change = dlsym (handle, "SCardGetStatusChange");
       if (!pcsc_list_readers)
         pcsc_list_readers    = dlsym (handle, "SCardListReadersA");
 #endif
       pcsc_get_status_change = dlsym (handle, "SCardGetStatusChange");
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
       if (!pcsc_get_status_change)
         pcsc_get_status_change = dlsym (handle, "SCardGetStatusChangeA");
 #endif
       pcsc_connect           = dlsym (handle, "SCardConnect");
       if (!pcsc_get_status_change)
         pcsc_get_status_change = dlsym (handle, "SCardGetStatusChangeA");
 #endif
       pcsc_connect           = dlsym (handle, "SCardConnect");
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
       if (!pcsc_connect)
         pcsc_connect         = dlsym (handle, "SCardConnectA");
 #endif
       pcsc_reconnect         = dlsym (handle, "SCardReconnect");
       if (!pcsc_connect)
         pcsc_connect         = dlsym (handle, "SCardConnectA");
 #endif
       pcsc_reconnect         = dlsym (handle, "SCardReconnect");
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
       if (!pcsc_reconnect)
         pcsc_reconnect       = dlsym (handle, "SCardReconnectA");
 #endif
       pcsc_disconnect        = dlsym (handle, "SCardDisconnect");
       pcsc_status            = dlsym (handle, "SCardStatus");
       if (!pcsc_reconnect)
         pcsc_reconnect       = dlsym (handle, "SCardReconnectA");
 #endif
       pcsc_disconnect        = dlsym (handle, "SCardDisconnect");
       pcsc_status            = dlsym (handle, "SCardStatus");
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
       if (!pcsc_status)
         pcsc_status          = dlsym (handle, "SCardStatusA");
 #endif
       if (!pcsc_status)
         pcsc_status          = dlsym (handle, "SCardStatusA");
 #endif
@@ -2492,11 +2538,30 @@ apdu_get_status (int slot, int hang,
 }
 
 
 }
 
 
+/* Check whether the reader supports the ISO command code COMMAND on
+   the keypad.  Return 0 on success.  For a description of the pin
+   parameters, see ccid-driver.c */
+int
+apdu_check_keypad (int slot, int command, int pin_mode,
+                   int pinlen_min, int pinlen_max, int pin_padlen)
+{
+  if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
+    return SW_HOST_NO_DRIVER;
+
+  if (reader_table[slot].check_keypad)
+    return reader_table[slot].check_keypad (slot, command,
+                                            pin_mode, pinlen_min, pinlen_max,
+                                            pin_padlen);
+  else
+    return SW_HOST_NOT_SUPPORTED;
+}
+
+
 /* Dispatcher for the actual send_apdu function. Note, that this
    function should be called in locked state. */
 static int
 send_apdu (int slot, unsigned char *apdu, size_t apdulen,
 /* Dispatcher for the actual send_apdu function. Note, that this
    function should be called in locked state. */
 static int
 send_apdu (int slot, unsigned char *apdu, size_t apdulen,
-           unsigned char *buffer, size_t *buflen)
+           unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo)
 {
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
 {
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
@@ -2504,24 +2569,20 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen,
   if (reader_table[slot].send_apdu_reader)
     return reader_table[slot].send_apdu_reader (slot,
                                                 apdu, apdulen,
   if (reader_table[slot].send_apdu_reader)
     return reader_table[slot].send_apdu_reader (slot,
                                                 apdu, apdulen,
-                                                buffer, buflen);
+                                                buffer, buflen, pininfo);
   else
     return SW_HOST_NOT_SUPPORTED;
 }
 
   else
     return SW_HOST_NOT_SUPPORTED;
 }
 
-/* Send an APDU to the card in SLOT.  The APDU is created from all
-   given parameters: CLASS, INS, P0, P1, LC, DATA, LE.  A value of -1
-   for LC won't sent this field and the data field; in this case DATA
-   must also be passed as NULL.  The return value is the status word
-   or -1 for an invalid SLOT or other non card related error.  If
-   RETBUF is not NULL, it will receive an allocated buffer with the
-   returned data.  The length of that data will be put into
-   *RETBUFLEN.  The caller is reponsible for releasing the buffer even
-   in case of errors.  */
-int
-apdu_send_le(int slot, int class, int ins, int p0, int p1,
-             int lc, const char *data, int le,
-             unsigned char **retbuf, size_t *retbuflen)
+
+/* Core APDU trabceiver function. Parameters are described at
+   apdu_send_le with the exception of PININFO which indicates keypad
+   related operations if not NULL. */
+static int
+send_le (int slot, int class, int ins, int p0, int p1,
+         int lc, const char *data, int le,
+         unsigned char **retbuf, size_t *retbuflen,
+         struct pininfo_s *pininfo)
 {
 #define RESULTLEN 256
   unsigned char result[RESULTLEN+10]; /* 10 extra in case of bugs in
 {
 #define RESULTLEN 256
   unsigned char result[RESULTLEN+10]; /* 10 extra in case of bugs in
@@ -2570,7 +2631,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1,
   /* As safeguard don't pass any garbage from the stack to the driver. */
   memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
   resultlen = RESULTLEN;
   /* As safeguard don't pass any garbage from the stack to the driver. */
   memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
   resultlen = RESULTLEN;
-  rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
+  rc = send_apdu (slot, apdu, apdulen, result, &resultlen, pininfo);
   if (rc || resultlen < 2)
     {
       log_error ("apdu_send_simple(%d) failed: %s\n",
   if (rc || resultlen < 2)
     {
       log_error ("apdu_send_simple(%d) failed: %s\n",
@@ -2638,7 +2699,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1,
           apdu[apdulen++] = len;
           memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
           resultlen = RESULTLEN;
           apdu[apdulen++] = len;
           memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
           resultlen = RESULTLEN;
-          rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
+          rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL);
           if (rc || resultlen < 2)
             {
               log_error ("apdu_send_simple(%d) for get response failed: %s\n",
           if (rc || resultlen < 2)
             {
               log_error ("apdu_send_simple(%d) for get response failed: %s\n",
@@ -2704,6 +2765,27 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1,
 }
 
 /* Send an APDU to the card in SLOT.  The APDU is created from all
 }
 
 /* Send an APDU to the card in SLOT.  The APDU is created from all
+   given parameters: CLASS, INS, P0, P1, LC, DATA, LE.  A value of -1
+   for LC won't sent this field and the data field; in this case DATA
+   must also be passed as NULL.  The return value is the status word
+   or -1 for an invalid SLOT or other non card related error.  If
+   RETBUF is not NULL, it will receive an allocated buffer with the
+   returned data.  The length of that data will be put into
+   *RETBUFLEN.  The caller is reponsible for releasing the buffer even
+   in case of errors.  */
+int
+apdu_send_le(int slot, int class, int ins, int p0, int p1,
+             int lc, const char *data, int le,
+             unsigned char **retbuf, size_t *retbuflen)
+{
+  return send_le (slot, class, ins, p0, p1,
+                  lc, data, le,
+                  retbuf, retbuflen,
+                  NULL);
+}
+
+
+/* Send an APDU to the card in SLOT.  The APDU is created from all
    given parameters: CLASS, INS, P0, P1, LC, DATA.  A value of -1 for
    LC won't sent this field and the data field; in this case DATA must
    also be passed as NULL. The return value is the status word or -1
    given parameters: CLASS, INS, P0, P1, LC, DATA.  A value of -1 for
    LC won't sent this field and the data field; in this case DATA must
    also be passed as NULL. The return value is the status word or -1
@@ -2716,8 +2798,8 @@ int
 apdu_send (int slot, int class, int ins, int p0, int p1,
            int lc, const char *data, unsigned char **retbuf, size_t *retbuflen)
 {
 apdu_send (int slot, int class, int ins, int p0, int p1,
            int lc, const char *data, unsigned char **retbuf, size_t *retbuflen)
 {
-  return apdu_send_le (slot, class, ins, p0, p1, lc, data, 256,
-                       retbuf, retbuflen);
+  return send_le (slot, class, ins, p0, p1, lc, data, 256,
+                  retbuf, retbuflen, NULL);
 }
 
 /* Send an APDU to the card in SLOT.  The APDU is created from all
 }
 
 /* Send an APDU to the card in SLOT.  The APDU is created from all
@@ -2730,7 +2812,25 @@ int
 apdu_send_simple (int slot, int class, int ins, int p0, int p1,
                   int lc, const char *data)
 {
 apdu_send_simple (int slot, int class, int ins, int p0, int p1,
                   int lc, const char *data)
 {
-  return apdu_send_le (slot, class, ins, p0, p1, lc, data, -1, NULL, NULL);
+  return send_le (slot, class, ins, p0, p1, lc, data, -1, NULL, NULL, NULL);
+}
+
+
+/* Same as apdu_send_simple but uses the keypad of the reader. */
+int
+apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1,
+                     int lc, const char *data,  
+                     int pin_mode,
+                     int pinlen_min, int pinlen_max, int pin_padlen)
+{
+  struct pininfo_s pininfo;
+
+  pininfo.mode = pin_mode;
+  pininfo.minlen = pinlen_min;
+  pininfo.maxlen = pinlen_max;
+  pininfo.padlen = pin_padlen;
+  return send_le (slot, class, ins, p0, p1, lc, data, -1,
+                  NULL, NULL, &pininfo);
 }
 
 
 }
 
 
@@ -2771,7 +2871,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen,
   class = apdulen? *apdu : 0;
 
   resultlen = RESULTLEN;
   class = apdulen? *apdu : 0;
 
   resultlen = RESULTLEN;
-  rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
+  rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL);
   if (rc || resultlen < 2)
     {
       log_error ("apdu_send_direct(%d) failed: %s\n",
   if (rc || resultlen < 2)
     {
       log_error ("apdu_send_direct(%d) failed: %s\n",
@@ -2825,7 +2925,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen,
           apdu[apdulen++] = len;
           memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
           resultlen = RESULTLEN;
           apdu[apdulen++] = len;
           memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
           resultlen = RESULTLEN;
-          rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
+          rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL);
           if (rc || resultlen < 2)
             {
               log_error ("apdu_send_direct(%d) for get response failed: %s\n",
           if (rc || resultlen < 2)
             {
               log_error ("apdu_send_direct(%d) for get response failed: %s\n",
index 45388fd..c3af825 100644 (file)
@@ -63,7 +63,8 @@ enum {
   SW_HOST_CARD_IO_ERROR = 0x1000a,
   SW_HOST_GENERAL_ERROR = 0x1000b,
   SW_HOST_NO_READER     = 0x1000c,
   SW_HOST_CARD_IO_ERROR = 0x1000a,
   SW_HOST_GENERAL_ERROR = 0x1000b,
   SW_HOST_NO_READER     = 0x1000c,
-  SW_HOST_ABORTED       = 0x1000d
+  SW_HOST_ABORTED       = 0x1000d,
+  SW_HOST_NO_KEYPAD     = 0x1000e
 };
 
 
 };
 
 
@@ -96,8 +97,14 @@ int apdu_activate (int slot);
 int apdu_reset (int slot);
 int apdu_get_status (int slot, int hang,
                      unsigned int *status, unsigned int *changed);
 int apdu_reset (int slot);
 int apdu_get_status (int slot, int hang,
                      unsigned int *status, unsigned int *changed);
+int apdu_check_keypad (int slot, int command, int pin_mode,
+                       int pinlen_min, int pinlen_max, int pin_padlen);
 int apdu_send_simple (int slot, int class, int ins, int p0, int p1,
                       int lc, const char *data);
 int apdu_send_simple (int slot, int class, int ins, int p0, int p1,
                       int lc, const char *data);
+int apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1,
+                         int lc, const char *data,  
+                         int pin_mode,
+                         int pinlen_min, int pinlen_max, int pin_padlen);
 int apdu_send (int slot, int class, int ins, int p0, int p1,
                int lc, const char *data,
                unsigned char **retbuf, size_t *retbuflen);
 int apdu_send (int slot, int class, int ins, int p0, int p1,
                int lc, const char *data,
                unsigned char **retbuf, size_t *retbuflen);
index 28b70c4..75cd12c 100644 (file)
@@ -1,5 +1,5 @@
 /* app-dinsig.c - The DINSIG (DIN V 66291-1) card application.
 /* app-dinsig.c - The DINSIG (DIN V 66291-1) card application.
- *     Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ *     Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  *
  * This file is part of GnuPG.
  *
@@ -280,10 +280,11 @@ verify_pin (app_t app,
 {
   if (!app->did_chv1 || app->force_chv1 ) 
     {
 {
   if (!app->did_chv1 || app->force_chv1 ) 
     {
+      const char *s;
       char *pinvalue;
       int rc;
 
       char *pinvalue;
       int rc;
 
-      rc = pincb (pincb_arg, "PIN", &pinvalue); 
+      rc = pincb (pincb_arg, "PIN", &pinvalue);
       if (rc)
         {
           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
       if (rc)
         {
           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
@@ -291,8 +292,16 @@ verify_pin (app_t app,
         }
 
       /* We require the PIN to be at least 6 and at max 8 bytes.
         }
 
       /* We require the PIN to be at least 6 and at max 8 bytes.
-         According to the specs, this should all be ASCII but we don't
-         check this. */
+         According to the specs, this should all be ASCII.  */
+      for (s=pinvalue; digitp (s); s++)
+        ;
+      if (*s)
+        {
+          log_error ("Non-numeric digits found in PIN\n");
+          xfree (pinvalue);
+          return gpg_error (GPG_ERR_BAD_PIN);
+        }
+
       if (strlen (pinvalue) < 6)
         {
           log_error ("PIN is too short; minimum length is 6\n");
       if (strlen (pinvalue) < 6)
         {
           log_error ("PIN is too short; minimum length is 6\n");
@@ -307,6 +316,28 @@ verify_pin (app_t app,
         }
 
       rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
         }
 
       rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
+      if (gpg_err_code (rc) == GPG_ERR_INV_VALUE)
+        {
+          /* We assume that ISO 9564-1 encoding is used and we failed
+             because the first nibble we passed was 3 and not 2.  DIN
+             says something about looking up such an encoding in the
+             SSD but I was not able to find any tag relevant to
+             this. */
+          char paddedpin[8];
+          int i, ndigits;
+
+          for (ndigits=0, s=pinvalue; *s; ndigits++, s++)
+            ;
+          i = 0;
+          paddedpin[i++] = 0x20 | (ndigits & 0x0f);
+          for (s=pinvalue; i < sizeof paddedpin && *s && s[1]; s = s+2 )
+            paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f));
+          if (i < sizeof paddedpin && *s)
+            paddedpin[i++] = (((*s - '0') << 4) | 0x0f);
+          while (i < sizeof paddedpin)
+              paddedpin[i++] = 0xff;
+          rc = iso7816_verify (app->slot, 0x81, paddedpin, sizeof paddedpin);
+        }
       if (rc)
         {
           log_error ("verify PIN failed\n");
       if (rc)
         {
           log_error ("verify PIN failed\n");
@@ -404,7 +435,7 @@ app_select_dinsig (APP app)
   int slot = app->slot;
   int rc;
   
   int slot = app->slot;
   int rc;
   
-  rc = iso7816_select_application (slot, aid, sizeof aid);
+  rc = iso7816_select_application (slot, aid, sizeof aid, 0);
   if (!rc)
     {
       app->apptype = "DINSIG";
   if (!rc)
     {
       app->apptype = "DINSIG";
index b6a3037..73ec8ea 100644 (file)
@@ -27,7 +27,7 @@
 #include <time.h>
 
 #include "scdaemon.h"
 #include <time.h>
 
 #include "scdaemon.h"
-
+#include "i18n.h"
 #include "iso7816.h"
 #include "app-common.h"
 #include "tlv.h"
 #include "iso7816.h"
 #include "app-common.h"
 #include "tlv.h"
@@ -320,7 +320,7 @@ verify_pin (app_t app,
           return rc;
         }
 
           return rc;
         }
 
-      /* The follwoing limits are due to TCOS but also defined in the
+      /* The following limits are due to TCOS but also defined in the
          NKS specs. */
       if (strlen (pinvalue) < 6)
         {
          NKS specs. */
       if (strlen (pinvalue) < 6)
         {
@@ -340,7 +340,10 @@ verify_pin (app_t app,
       rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue));
       if (rc)
         {
       rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue));
       if (rc)
         {
-          log_error ("verify PIN failed\n");
+          if ( gpg_error (rc) == GPG_ERR_USE_CONDITIONS )
+            log_error (_("the NullPIN has not yet been changed\n"));
+          else
+            log_error ("verify PIN failed\n");
           xfree (pinvalue);
           return rc;
         }
           xfree (pinvalue);
           return rc;
         }
@@ -492,7 +495,7 @@ app_select_nks (APP app)
   int slot = app->slot;
   int rc;
   
   int slot = app->slot;
   int rc;
   
-  rc = iso7816_select_application (slot, aid, sizeof aid);
+  rc = iso7816_select_application (slot, aid, sizeof aid, 0);
   if (!rc)
     {
       app->apptype = "NKS";
   if (!rc)
     {
       app->apptype = "NKS";
index 5625c72..3d04be0 100644 (file)
@@ -1284,6 +1284,11 @@ verify_chv2 (app_t app,
   if (!app->did_chv2) 
     {
       char *pinvalue;
   if (!app->did_chv2) 
     {
       char *pinvalue;
+      iso7816_pininfo_t pininfo;
+
+      memset (&pininfo, 0, sizeof pininfo);
+      pininfo.mode = 1;
+      pininfo.minlen = 6;
 
       rc = pincb (pincb_arg, "PIN", &pinvalue); 
       if (rc)
 
       rc = pincb (pincb_arg, "PIN", &pinvalue); 
       if (rc)
@@ -2455,7 +2460,9 @@ app_select_openpgp (app_t app)
   size_t buflen;
   void *relptr;
   
   size_t buflen;
   void *relptr;
   
-  rc = iso7816_select_application (slot, aid, sizeof aid);
+  /* Note that the card can't cope with P2=0xCO, thus we need to pass a
+     special flag value. */
+  rc = iso7816_select_application (slot, aid, sizeof aid, 0x0001);
   if (!rc)
     {
       unsigned int manufacturer;
   if (!rc)
     {
       unsigned int manufacturer;
index 739a9ef..8bb94cf 100644 (file)
@@ -3268,18 +3268,15 @@ app_select_p15 (app_t app)
   int direct = 0;
   int is_belpic = 0;
 
   int direct = 0;
   int is_belpic = 0;
 
-  rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid);
-  if (rc)
-    {
-      rc = iso7816_select_application (slot, pkcs15be_aid,sizeof pkcs15be_aid);
-      if (!rc)
-        is_belpic = 1;
-    }
+  rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid, 0);
   if (rc)
     { /* Not found: Try to locate it from 2F00.  We use direct path
          selection here because it seems that the Belgian eID card
          does only allow for that.  Many other cards supports this
   if (rc)
     { /* Not found: Try to locate it from 2F00.  We use direct path
          selection here because it seems that the Belgian eID card
          does only allow for that.  Many other cards supports this
-         selection method too. */
+         selection method too.  Note, that we don't use
+         select_application above for the Belgian card - the call
+         works but it seems that it did not switch to the correct DF.
+         Using the 2f02 just works. */
       unsigned short path[1] = { 0x2f00 };
 
       rc = iso7816_select_path (app->slot, path, 1, NULL, NULL);
       unsigned short path[1] = { 0x2f00 };
 
       rc = iso7816_select_path (app->slot, path, 1, NULL, NULL);
index f82d93b..fee7333 100644 (file)
@@ -1240,7 +1240,9 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
   if (CCID_COMMAND_FAILED (buffer))
     print_command_failed (buffer);
 
   if (CCID_COMMAND_FAILED (buffer))
     print_command_failed (buffer);
 
-  /* Check whether a card is at all available. */
+  /* Check whether a card is at all available.  Note: If you add new
+     error codes here, check whether they need to be ignored in
+     send_escape_cmd. */
   switch ((buffer[7] & 0x03))
     {
     case 0: /* no error */ break;
   switch ((buffer[7] & 0x03))
     {
     case 0: /* no error */ break;
@@ -1253,16 +1255,23 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
 
 
 /* Note that this function won't return the error codes NO_CARD or
 
 
 /* Note that this function won't return the error codes NO_CARD or
-   CARD_INACTIVE */
+   CARD_INACTIVE.  IF RESULT is not NULL, the result from the
+   operation will get returned in RESULT and its length in RESULTLEN.
+   If the response is larger than RESULTMAX, an error is returned and
+   the required buffer length returned in RESULTLEN.  */
 static int 
 send_escape_cmd (ccid_driver_t handle,
 static int 
 send_escape_cmd (ccid_driver_t handle,
-                 const unsigned char *data, size_t datalen)
+                 const unsigned char *data, size_t datalen,
+                 unsigned char *result, size_t resultmax, size_t *resultlen)
 {
   int i, rc;
   unsigned char msg[100];
   size_t msglen;
   unsigned char seqno;
 
 {
   int i, rc;
   unsigned char msg[100];
   size_t msglen;
   unsigned char seqno;
 
+  if (resultlen)
+    *resultlen = 0;
+
   if (datalen > sizeof msg - 10)
     return CCID_DRIVER_ERR_INV_VALUE; /* Escape data too large.  */
 
   if (datalen > sizeof msg - 10)
     return CCID_DRIVER_ERR_INV_VALUE; /* Escape data too large.  */
 
@@ -1285,11 +1294,42 @@ send_escape_cmd (ccid_driver_t handle,
     return rc;
   rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape,
                 seqno, 5000, 0);
     return rc;
   rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape,
                 seqno, 5000, 0);
-
+  if (result)
+    switch (rc)
+      {
+        /* We need to ignore certain errorcode here. */
+      case 0:
+      case CCID_DRIVER_ERR_CARD_INACTIVE:
+      case CCID_DRIVER_ERR_NO_CARD:
+        {
+          if (msglen > resultmax)
+            rc = CCID_DRIVER_ERR_INV_VALUE; /* Response too large. */
+          else
+            {
+              memcpy (result, msg, msglen);
+              *resultlen = msglen;
+            }
+          rc = 0;
+        }
+        break;
+      default:
+        break;
+      }
+  
   return rc;
 }
 
 
   return rc;
 }
 
 
+int
+ccid_transceive_escape (ccid_driver_t handle,
+                        const unsigned char *data, size_t datalen,
+                        unsigned char *resp, size_t maxresplen, size_t *nresp)
+{
+  return send_escape_cmd (handle, data, datalen, resp, maxresplen, nresp);
+}
+
+
+
 /* experimental */
 int
 ccid_poll (ccid_driver_t handle)
 /* experimental */
 int
 ccid_poll (ccid_driver_t handle)
@@ -1445,7 +1485,8 @@ ccid_get_atr (ccid_driver_t handle,
     {
       tried_iso = 1;
       /* Try switching to ISO mode. */
     {
       tried_iso = 1;
       /* Try switching to ISO mode. */
-      if (!send_escape_cmd (handle, (const unsigned char*)"\xF1\x01", 2))
+      if (!send_escape_cmd (handle, (const unsigned char*)"\xF1\x01", 2,
+                            NULL, 0, NULL))
         goto again;
     }
   else if (CCID_COMMAND_FAILED (msg))
         goto again;
     }
   else if (CCID_COMMAND_FAILED (msg))
@@ -1957,14 +1998,16 @@ ccid_transceive (ccid_driver_t handle,
 }
 
 
 }
 
 
-/* Send the CCID Secure command to the reader.  APDU_BUF should contain the APDU   template.  PIN_MODE defines now the pin gets formatted:
+/* Send the CCID Secure command to the reader.  APDU_BUF should
+   contain the APDU template.  PIN_MODE defines how the pin gets
+   formatted:
    
      1 := The PIN is ASCII encoded and of variable length.  The
           length of the PIN entered will be put into Lc by the reader.
           The APDU should me made up of 4 bytes without Lc.
 
    PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0
    
      1 := The PIN is ASCII encoded and of variable length.  The
           length of the PIN entered will be put into Lc by the reader.
           The APDU should me made up of 4 bytes without Lc.
 
    PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0
-   may be used t enable usbale defaults.  PIN_PADLEN should be 0
+   may be used t enable reasonable defaults.  PIN_PADLEN should be 0.
    
    When called with RESP and NRESP set to NULL, the function will
    merely check whether the reader supports the secure command for the
    
    When called with RESP and NRESP set to NULL, the function will
    merely check whether the reader supports the secure command for the
@@ -1996,7 +2039,7 @@ ccid_transceive_secure (ccid_driver_t handle,
   else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2))
     return CCID_DRIVER_ERR_NOT_SUPPORTED; /* Not yet by our code. */
   else
   else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2))
     return CCID_DRIVER_ERR_NOT_SUPPORTED; /* Not yet by our code. */
   else
-    return CCID_DRIVER_ERR_NOT_SUPPORTED;
+    return CCID_DRIVER_ERR_NO_KEYPAD;
     
   if (pin_mode != 1)
     return CCID_DRIVER_ERR_NOT_SUPPORTED;
     
   if (pin_mode != 1)
     return CCID_DRIVER_ERR_NOT_SUPPORTED;
@@ -2027,7 +2070,8 @@ ccid_transceive_secure (ccid_driver_t handle,
   if (handle->id_vendor == VENDOR_SCM)
     {
       DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n");
   if (handle->id_vendor == VENDOR_SCM)
     {
       DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n");
-      rc = send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3);
+      rc = send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3,
+                            NULL, 0, NULL);
       if (rc)
         return rc;
     }
       if (rc)
         return rc;
     }
@@ -2044,7 +2088,7 @@ ccid_transceive_secure (ccid_driver_t handle,
   if (handle->id_vendor == VENDOR_SCM)
     {
       /* For the SPR532 the next 2 bytes need to be zero.  We do this
   if (handle->id_vendor == VENDOR_SCM)
     {
       /* For the SPR532 the next 2 bytes need to be zero.  We do this
-         for all SCM product. Kudos to to Martin Paljak for this
+         for all SCM product. Kudos to Martin Paljak for this
          hint.  */
       msg[13] = msg[14] = 0;
     }
          hint.  */
       msg[13] = msg[14] = 0;
     }
index 1b9ac2f..6f65271 100644 (file)
@@ -58,7 +58,7 @@
 #ifndef CCID_DRIVER_H
 #define CCID_DRIVER_H
 
 #ifndef CCID_DRIVER_H
 #define CCID_DRIVER_H
 
-/* The CID driver returns the same error codes as the statsu words
+/* The CID driver returns the same error codes as the status words
    used by GnuPG's apdu.h.  For ease of maintenance they should always
    match.  */
 #define CCID_DRIVER_ERR_OUT_OF_CORE    0x10001 
    used by GnuPG's apdu.h.  For ease of maintenance they should always
    match.  */
 #define CCID_DRIVER_ERR_OUT_OF_CORE    0x10001 
@@ -74,6 +74,7 @@
 #define CCID_DRIVER_ERR_GENERAL_ERROR  0x1000b
 #define CCID_DRIVER_ERR_NO_READER      0x1000c
 #define CCID_DRIVER_ERR_ABORTED        0x1000d
 #define CCID_DRIVER_ERR_GENERAL_ERROR  0x1000b
 #define CCID_DRIVER_ERR_NO_READER      0x1000c
 #define CCID_DRIVER_ERR_ABORTED        0x1000d
+#define CCID_DRIVER_ERR_NO_KEYPAD      0x1000e
 
 struct ccid_driver_s;
 typedef struct ccid_driver_s *ccid_driver_t;
 
 struct ccid_driver_s;
 typedef struct ccid_driver_s *ccid_driver_t;
@@ -94,6 +95,10 @@ int ccid_transceive_secure (ccid_driver_t handle,
                      int pin_mode, 
                      int pinlen_min, int pinlen_max, int pin_padlen, 
                      unsigned char *resp, size_t maxresplen, size_t *nresp);
                      int pin_mode, 
                      int pinlen_min, int pinlen_max, int pin_padlen, 
                      unsigned char *resp, size_t maxresplen, size_t *nresp);
+int ccid_transceive_escape (ccid_driver_t handle,
+                            const unsigned char *data, size_t datalen,
+                            unsigned char *resp, size_t maxresplen,
+                            size_t *nresp);
 
 
 
 
 
 
index 5b98532..5c62e13 100644 (file)
@@ -47,9 +47,9 @@
 
 
 #define CMD_SELECT_FILE 0xA4
 
 
 #define CMD_SELECT_FILE 0xA4
-#define CMD_VERIFY      0x20
-#define CMD_CHANGE_REFERENCE_DATA 0x24
-#define CMD_RESET_RETRY_COUNTER   0x2C
+#define CMD_VERIFY                ISO7816_VERIFY
+#define CMD_CHANGE_REFERENCE_DATA ISO7816_CHANGE_REFERENCE_DATA
+#define CMD_RESET_RETRY_COUNTER   ISO7816_RESET_RETRY_COUNTER
 #define CMD_GET_DATA    0xCA
 #define CMD_PUT_DATA    0xDA
 #define CMD_MSE         0x22
 #define CMD_GET_DATA    0xCA
 #define CMD_PUT_DATA    0xDA
 #define CMD_MSE         0x22
@@ -95,6 +95,7 @@ map_sw (int sw)
     case SW_HOST_GENERAL_ERROR:  ec = GPG_ERR_GENERAL; break;
     case SW_HOST_NO_READER:      ec = GPG_ERR_ENODEV; break;
     case SW_HOST_ABORTED:        ec = GPG_ERR_CANCELED; break;
     case SW_HOST_GENERAL_ERROR:  ec = GPG_ERR_GENERAL; break;
     case SW_HOST_NO_READER:      ec = GPG_ERR_ENODEV; break;
     case SW_HOST_ABORTED:        ec = GPG_ERR_CANCELED; break;
+    case SW_HOST_NO_KEYPAD:      ec = GPG_ERR_NOT_SUPPORTED; break;
 
     default:
       if ((sw & 0x010000))
 
     default:
       if ((sw & 0x010000))
@@ -124,12 +125,15 @@ iso7816_map_sw (int sw)
    requested application ID.  The function can't be used to enumerate
    AIDs and won't return the AID on success.  The return value is 0
    for okay or a GPG error code.  Note that ISO error codes are
    requested application ID.  The function can't be used to enumerate
    AIDs and won't return the AID on success.  The return value is 0
    for okay or a GPG error code.  Note that ISO error codes are
-   internally mapped. */
+   internally mapped.  Bit 0 of FLAGS should be set if the card does
+   not understand P2=0xC0. */
 gpg_error_t
 gpg_error_t
-iso7816_select_application (int slot, const char *aid, size_t aidlen)
+iso7816_select_application (int slot, const char *aid, size_t aidlen,
+                            unsigned int flags)
 {
   int sw;
 {
   int sw;
-  sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, 0, aidlen, aid);
+  sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4,
+                         (flags&1)? 0 :0x0c, aidlen, aid);
   return map_sw (sw);
 }
 
   return map_sw (sw);
 }
 
@@ -221,27 +225,59 @@ iso7816_list_directory (int slot, int list_dirs,
 }
 
 
 }
 
 
+/* Check whether the reader supports the ISO command code COMMAND on
+   the keypad.  Returns 0 on success.  */
+gpg_error_t
+iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)
+{
+  int sw;
+
+  sw = apdu_check_keypad (slot, command, 
+                          pininfo->mode, pininfo->minlen, pininfo->maxlen,
+                          pininfo->padlen);
+  return map_sw (sw);
+}
+
 
 /* Perform a VERIFY command on SLOT using the card holder verification
 
 /* Perform a VERIFY command on SLOT using the card holder verification
-   vector CHVNO with a CHV of lenght CHVLEN.  Returns 0 on success. */
+   vector CHVNO with a CHV of lenght CHVLEN.  With PININFO non-NULL
+   the keypad of the reader will be used.  Returns 0 on success. */
 gpg_error_t
 gpg_error_t
-iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
+iso7816_verify_kp (int slot, int chvno, const char *chv, size_t chvlen,
+                   iso7816_pininfo_t *pininfo)
 {
   int sw;
 
 {
   int sw;
 
-  sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
+  if (pininfo && pininfo->mode)
+    sw = apdu_send_simple_kp (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv,
+                              pininfo->mode,
+                              pininfo->minlen,
+                              pininfo->maxlen,
+                              pininfo->padlen);
+  else
+    sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
   return map_sw (sw);
 }
 
   return map_sw (sw);
 }
 
+/* Perform a VERIFY command on SLOT using the card holder verification
+   vector CHVNO with a CHV of lenght CHVLEN.  Returns 0 on success. */
+gpg_error_t
+iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
+{
+  return iso7816_verify_kp (slot, chvno, chv, chvlen, NULL);
+}
+
 /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
    verification vector CHVNO.  If the OLDCHV is NULL (and OLDCHVLEN
    0), a "change reference data" is done, otherwise an "exchange
    reference data".  The new reference data is expected in NEWCHV of
 /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
    verification vector CHVNO.  If the OLDCHV is NULL (and OLDCHVLEN
    0), a "change reference data" is done, otherwise an "exchange
    reference data".  The new reference data is expected in NEWCHV of
-   length NEWCHVLEN.  */
+   length NEWCHVLEN.  With PININFO non-NULL the keypad of the reader
+   will be used.  */
 gpg_error_t
 gpg_error_t
-iso7816_change_reference_data (int slot, int chvno,
-                               const char *oldchv, size_t oldchvlen,
-                               const char *newchv, size_t newchvlen)
+iso7816_change_reference_data_kp (int slot, int chvno,
+                                  const char *oldchv, size_t oldchvlen,
+                                  const char *newchv, size_t newchvlen,
+                                  iso7816_pininfo_t *pininfo)
 {
   int sw;
   char *buf;
 {
   int sw;
   char *buf;
@@ -258,28 +294,69 @@ iso7816_change_reference_data (int slot, int chvno,
     memcpy (buf, oldchv, oldchvlen);
   memcpy (buf+oldchvlen, newchv, newchvlen);
 
     memcpy (buf, oldchv, oldchvlen);
   memcpy (buf+oldchvlen, newchv, newchvlen);
 
-  sw = apdu_send_simple (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
-                         oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf);
+  if (pininfo && pininfo->mode)
+    sw = apdu_send_simple_kp (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
+                           oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf,
+                           pininfo->mode,
+                           pininfo->minlen,
+                           pininfo->maxlen,
+                           pininfo->padlen);
+  else
+    sw = apdu_send_simple (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
+                           oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf);
   xfree (buf);
   return map_sw (sw);
 
 }
 
   xfree (buf);
   return map_sw (sw);
 
 }
 
+/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
+   verification vector CHVNO.  If the OLDCHV is NULL (and OLDCHVLEN
+   0), a "change reference data" is done, otherwise an "exchange
+   reference data".  The new reference data is expected in NEWCHV of
+   length NEWCHVLEN.  */
+gpg_error_t
+iso7816_change_reference_data (int slot, int chvno,
+                               const char *oldchv, size_t oldchvlen,
+                               const char *newchv, size_t newchvlen)
+{
+  return iso7816_change_reference_data_kp (slot, chvno, oldchv, oldchvlen,
+                                           newchv, newchvlen, NULL);
+}
+
+
 gpg_error_t
 gpg_error_t
-iso7816_reset_retry_counter (int slot, int chvno,
-                             const char *newchv, size_t newchvlen)
+iso7816_reset_retry_counter_kp (int slot, int chvno,
+                                const char *newchv, size_t newchvlen,
+                                iso7816_pininfo_t *pininfo)
 {
   int sw;
 
   if (!newchv || !newchvlen )
     return gpg_error (GPG_ERR_INV_VALUE);
 
 {
   int sw;
 
   if (!newchv || !newchvlen )
     return gpg_error (GPG_ERR_INV_VALUE);
 
-  sw = apdu_send_simple (slot, 0x00, CMD_RESET_RETRY_COUNTER,
-                         2, chvno, newchvlen, newchv);
+  if (pininfo && pininfo->mode)
+    sw = apdu_send_simple_kp (slot, 0x00, CMD_RESET_RETRY_COUNTER,
+                           2, chvno, newchvlen, newchv,
+                           pininfo->mode,
+                           pininfo->minlen,
+                           pininfo->maxlen,
+                           pininfo->padlen);
+  else
+    sw = apdu_send_simple (slot, 0x00, CMD_RESET_RETRY_COUNTER,
+                           2, chvno, newchvlen, newchv);
   return map_sw (sw);
 }
 
 
   return map_sw (sw);
 }
 
 
+gpg_error_t
+iso7816_reset_retry_counter (int slot, int chvno,
+                             const char *newchv, size_t newchvlen)
+{
+  return iso7816_reset_retry_counter_kp (slot, chvno, newchv, newchvlen, NULL);
+}
+
+
+
 /* Perform a GET DATA command requesting TAG and storing the result in
    a newly allocated buffer at the address passed by RESULT.  Return
    the length of this data at the address of RESULTLEN. */
 /* Perform a GET DATA command requesting TAG and storing the result in
    a newly allocated buffer at the address passed by RESULT.  Return
    the length of this data at the address of RESULTLEN. */
index 04c7ae6..8f79074 100644 (file)
 #include "cardglue.h"
 #endif
 
 #include "cardglue.h"
 #endif
 
+/* Command codes used by iso7816_check_keypad. */
+#define ISO7816_VERIFY                0x20
+#define ISO7816_CHANGE_REFERENCE_DATA 0x24
+#define ISO7816_RESET_RETRY_COUNTER   0x2C
+
+
+/* Information to be passed to keypad equipped readers.  See
+   ccid-driver.c for details. */
+struct iso7816_pininfo_s
+{
+  int mode;    /* A mode of 0 means: Do not use the keypad. */
+  int minlen;
+  int maxlen;
+  int padlen;
+  int padchar;
+};
+typedef struct iso7816_pininfo_s iso7816_pininfo_t;
+
+
 gpg_error_t iso7816_map_sw (int sw);
 
 gpg_error_t iso7816_select_application (int slot,
 gpg_error_t iso7816_map_sw (int sw);
 
 gpg_error_t iso7816_select_application (int slot,
-                                        const char *aid, size_t aidlen);
+                                        const char *aid, size_t aidlen,
+                                        unsigned int flags);
 gpg_error_t iso7816_select_file (int slot, int tag, int is_dir,
                                  unsigned char **result, size_t *resultlen);
 gpg_error_t iso7816_select_path (int slot,
 gpg_error_t iso7816_select_file (int slot, int tag, int is_dir,
                                  unsigned char **result, size_t *resultlen);
 gpg_error_t iso7816_select_path (int slot,
@@ -39,13 +59,26 @@ gpg_error_t iso7816_select_path (int slot,
                                  unsigned char **result, size_t *resultlen);
 gpg_error_t iso7816_list_directory (int slot, int list_dirs,
                                     unsigned char **result, size_t *resultlen);
                                  unsigned char **result, size_t *resultlen);
 gpg_error_t iso7816_list_directory (int slot, int list_dirs,
                                     unsigned char **result, size_t *resultlen);
+gpg_error_t iso7816_check_keypad (int slot, int command,
+                                  iso7816_pininfo_t *pininfo);
 gpg_error_t iso7816_verify (int slot,
                             int chvno, const char *chv, size_t chvlen);
 gpg_error_t iso7816_verify (int slot,
                             int chvno, const char *chv, size_t chvlen);
+gpg_error_t iso7816_verify_kp (int slot,
+                               int chvno, const char *chv, size_t chvlen,
+                               iso7816_pininfo_t *pininfo);
 gpg_error_t iso7816_change_reference_data (int slot, int chvno,
                                const char *oldchv, size_t oldchvlen,
                                const char *newchv, size_t newchvlen);
 gpg_error_t iso7816_change_reference_data (int slot, int chvno,
                                const char *oldchv, size_t oldchvlen,
                                const char *newchv, size_t newchvlen);
+gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno,
+                               const char *oldchv, size_t oldchvlen,
+                               const char *newchv, size_t newchvlen,
+                               iso7816_pininfo_t *pininfo);
 gpg_error_t iso7816_reset_retry_counter (int slot, int chvno,
                                          const char *newchv, size_t newchvlen);
 gpg_error_t iso7816_reset_retry_counter (int slot, int chvno,
                                          const char *newchv, size_t newchvlen);
+gpg_error_t iso7816_reset_retry_counter_kp (int slot, int chvno,
+                                            const char *newchv,
+                                            size_t newchvlen,
+                                            iso7816_pininfo_t *pininfo);
 gpg_error_t iso7816_get_data (int slot, int tag,
                               unsigned char **result, size_t *resultlen);
 gpg_error_t iso7816_put_data (int slot, int tag,
 gpg_error_t iso7816_get_data (int slot, int tag,
                               unsigned char **result, size_t *resultlen);
 gpg_error_t iso7816_put_data (int slot, int tag,
index c6995ab..56c0d76 100644 (file)
@@ -84,6 +84,7 @@ enum cmd_and_opt_values
   opcscDriver,
   oDisableCCID,
   oDisableOpenSC,
   opcscDriver,
   oDisableCCID,
   oDisableOpenSC,
+  oDisableKeypad,
   oAllowAdmin,
   oDenyAdmin,
   oDisableApplication,
   oAllowAdmin,
   oDenyAdmin,
   oDisableApplication,
@@ -126,6 +127,7 @@ static ARGPARSE_OPTS opts[] = {
                                     "@"
 #endif
                                          /* end --disable-ccid */},
                                     "@"
 #endif
                                          /* end --disable-ccid */},
+  { oDisableKeypad, "disable-keypad", 0, N_("do not use a reader's keypad")},
   { oAllowAdmin, "allow-admin", 0, N_("allow the use of admin card commands")},
   { oDenyAdmin,  "deny-admin",  0, "@" },  
   { oDisableApplication, "disable-application", 2, "@"},
   { oAllowAdmin, "allow-admin", 0, N_("allow the use of admin card commands")},
   { oDenyAdmin,  "deny-admin",  0, "@" },  
   { oDisableApplication, "disable-application", 2, "@"},
@@ -135,7 +137,7 @@ static ARGPARSE_OPTS opts[] = {
 
 
 /* The card dirver we use by default for PC/SC.  */
 
 
 /* The card dirver we use by default for PC/SC.  */
-#ifdef HAVE_W32_SYSTEM
+#if defined(HAVE_W32_SYSTEM) || defined(__CYGWIN__)
 #define DEFAULT_PCSC_DRIVER "winscard.dll"
 #else
 #define DEFAULT_PCSC_DRIVER "libpcsclite.so"
 #define DEFAULT_PCSC_DRIVER "winscard.dll"
 #else
 #define DEFAULT_PCSC_DRIVER "libpcsclite.so"
@@ -489,6 +491,8 @@ main (int argc, char **argv )
         case oDisableCCID: opt.disable_ccid = 1; break;
         case oDisableOpenSC: break;
 
         case oDisableCCID: opt.disable_ccid = 1; break;
         case oDisableOpenSC: break;
 
+        case oDisableKeypad: opt.disable_keypad = 1; break;
+
         case oAllowAdmin: opt.allow_admin = 1; break;
         case oDenyAdmin: opt.allow_admin = 0; break;
 
         case oAllowAdmin: opt.allow_admin = 1; break;
         case oDenyAdmin: opt.allow_admin = 0; break;
 
index 54566b6..abe9730 100644 (file)
 
 #define MAX_DIGEST_LEN 24 
 
 
 #define MAX_DIGEST_LEN 24 
 
-/* A large struct name "opt" to keep global flags */
+/* A large struct name "opt" to keep global flags. */
 struct {
 struct {
-  unsigned int debug; /* debug flags (DBG_foo_VALUE) */
-  int verbose;      /* verbosity level */
-  int quiet;        /* be as quiet as possible */
-  int dry_run;      /* don't change any persistent data */
-  int batch;        /* batch mode */
-  const char *homedir; /* configuration directory name */
+  unsigned int debug; /* Debug flags (DBG_foo_VALUE). */
+  int verbose;        /* Verbosity level. */
+  int quiet;          /* Be as quiet as possible. */
+  int dry_run;        /* Don't change any persistent data. */
+  int batch;          /* Batch mode. */
+  const char *homedir;      /* Configuration directory name. */
   const char *ctapi_driver; /* Library to access the ctAPI. */
   const char *pcsc_driver;  /* Library to access the PC/SC system. */
   const char *reader_port;  /* NULL or reder port to use. */
   int disable_ccid;    /* Disable the use of the internal CCID driver. */
   const char *ctapi_driver; /* Library to access the ctAPI. */
   const char *pcsc_driver;  /* Library to access the PC/SC system. */
   const char *reader_port;  /* NULL or reder port to use. */
   int disable_ccid;    /* Disable the use of the internal CCID driver. */
+  int disable_keypad;  /* Do not use a keypad. */
   int allow_admin;     /* Allow the use of admin commands for certain
                           cards. */
   int allow_admin;     /* Allow the use of admin commands for certain
                           cards. */
-  strlist_t disabled_applications;  /* card applications we do not
+  strlist_t disabled_applications;  /* Card applications we do not
                                        want to use. */
 } opt;
 
                                        want to use. */
 } opt;
 
index ba4f0ec..a57a0bc 100644 (file)
@@ -1,3 +1,11 @@
+2005-10-19  Werner Koch  <wk@g10code.com>
+
+       * gpgconf-comp.c (gc_options_scdaemon): New option --disable-keypad.
+
+2005-09-22  Werner Koch  <wk@g10code.com>
+
+       * rfc822parse.c (parse_field): Tread Content-Disposition special.
+
 2005-10-08  Marcus Brinkmann  <marcus@g10code.de>
 
        * Makefile.am (watchgnupg_LDADD): New variable.
 2005-10-08  Marcus Brinkmann  <marcus@g10code.de>
 
        * Makefile.am (watchgnupg_LDADD): New variable.
index e8d9ca2..4977075 100644 (file)
@@ -528,7 +528,9 @@ static gc_option_t gc_options_scdaemon[] =
    { "disable-ccid", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "gnupg", "do not use the internal CCID driver",
      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
    { "disable-ccid", GC_OPT_FLAG_NONE, 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_ADVANCED,
+     "gnupg", "do not use a reader's keypad",
+     GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
@@ -2447,7 +2449,8 @@ gc_component_change_options (int component, FILE *in)
                {
 #ifdef HAVE_W32_SYSTEM
                   /* FIXME: Won't work becuase W32 doesn't silently
                {
 #ifdef HAVE_W32_SYSTEM
                   /* FIXME: Won't work becuase W32 doesn't silently
-                     overwrite. */
+                     overwrite. Fix it by creating a backup copy and
+                     deliting the orginal file first. */
                   err = rename (src_pathname[i], dest_pathname[i]);
 #else /*!HAVE_W32_SYSTEM*/
                  /* This is a bit safer than rename() because we
                   err = rename (src_pathname[i], dest_pathname[i]);
 #else /*!HAVE_W32_SYSTEM*/
                  /* This is a bit safer than rename() because we
index 61377e7..df3b2e7 100644 (file)
@@ -766,6 +766,7 @@ parse_field (HDR_LINE hdr)
   } tspecial_header[] = {
     { "Content-Type", 12},
     { "Content-Transfer-Encoding", 25},
   } tspecial_header[] = {
     { "Content-Type", 12},
     { "Content-Transfer-Encoding", 25},
+    { "Content-Disposition", 19},
     { NULL, 0}
   };
   const char *delimiters;
     { NULL, 0}
   };
   const char *delimiters;