[git] GnuPG - branch, master, updated. post-nuke-of-trailing-ws-163-gb22d62b

by Werner Koch cvs at cvs.gnupg.org
Thu Dec 15 16:14:21 CET 2011


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  b22d62bd1481dfe13d60a6d16b09b9297944f063 (commit)
       via  7737a2c269657189a583cde7f214f20871d264f8 (commit)
       via  792e137ec7997a0ff5c54ff970611238d28d4ba8 (commit)
       via  0bac31ee9f74a25d76b08c3e0355a338908f083a (commit)
       via  dcd64131c60efd0189aa05d5dbce6b93547b04e3 (commit)
      from  45cf9de341405a228e331bd3893cbcd6b72306be (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit b22d62bd1481dfe13d60a6d16b09b9297944f063
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Dec 15 14:47:04 2011 +0100

    scd: Add option --dump-atr to command APDU.
    
    * scd/atr.c: Rewrite.
    * scd/Makefile.am (scdaemon_SOURCES): Add atr.c and atr.h.
    * scd/command.c (cmd_apdu): Add option --dump-atr.

diff --git a/scd/Makefile.am b/scd/Makefile.am
index bdd457a..b42e53d 100644
--- a/scd/Makefile.am
+++ b/scd/Makefile.am
@@ -37,6 +37,7 @@ card_apps = app-openpgp.c app-nks.c app-dinsig.c app-p15.c app-geldkarte.c
 scdaemon_SOURCES = \
 	scdaemon.c scdaemon.h \
 	command.c \
+	atr.c atr.h \
 	apdu.c apdu.h \
 	ccid-driver.c ccid-driver.h \
 	iso7816.c iso7816.h \
diff --git a/scd/atr.c b/scd/atr.c
index 16f26fb..b8668a4 100644
--- a/scd/atr.c
+++ b/scd/atr.c
@@ -1,5 +1,5 @@
 /* atr.c - ISO 7816 ATR fucntions
- *	Copyright (C) 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2003, 2011 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -24,10 +24,9 @@
 #include <string.h>
 #include <assert.h>
 
-#include "scdaemon.h"
-#include "apdu.h"
+#include "../common/estream.h"
+#include "../common/logging.h"
 #include "atr.h"
-#include "dynload.h"
 
 static int const fi_table[16] = { 0, 372, 558, 744, 1116,1488, 1860, -1,
                                   -1, 512, 768, 1024, 1536, 2048, -1, -1 };
@@ -35,37 +34,42 @@ static int const di_table[16] = { -1, 1, 2, 4, 8, 16, -1, -1,
                                   0, -1, -2, -4, -8, -16, -32, -64};
 
 
-/* Dump the ATR of the card at SLOT in a human readable format to
-   stream FP.  */
-int
-atr_dump (int slot, FILE *fp)
+/* Dump the ATR in (BUFFER,BUFLEN) to a human readable format and
+   return that as a malloced buffer.  The caller must release this
+   buffer using es_free!  On error this function returns NULL and sets
+   ERRNO.  */
+char *
+atr_dump (const void *buffer, size_t buflen)
 {
-  unsigned char *atrbuffer, *atr;
-  size_t atrlen;
+  const unsigned char *atr = buffer;
+  size_t atrlen = buflen;
+  estream_t fp;
   int have_ta, have_tb, have_tc, have_td;
   int n_historical;
   int idx, val;
   unsigned char chksum;
+  char *result;
 
-  atr = atrbuffer = apdu_get_atr (slot, &atrlen);
-  if (!atr)
-    return gpg_error (GPG_ERR_GENERAL);
+  fp = es_fopenmem (0, "rwb");
+  if (!fp)
+    return NULL;
 
-  fprintf (fp, "Info on ATR of length %u at slot %d\n",
-           (unsigned int)atrlen, slot);
   if (!atrlen)
     {
-      fprintf (fp, "error: empty ATR\n");
+      es_fprintf (fp, "error: empty ATR\n");
       goto bailout;
     }
 
+  for (idx=0; idx < atrlen ; idx++)
+    es_fprintf (fp, "%s%02X", idx?" ":"", atr[idx]);
+  es_putc ('\n', fp);
 
   if (*atr == 0x3b)
-    fputs ("direct convention\n", fp);
+    es_fputs ("Direct convention\n", fp);
   else if (*atr == 0x3f)
-    fputs ("inverse convention\n", fp);
+    es_fputs ("Inverse convention\n", fp);
   else
-    fprintf (fp,"error: invalid TS character 0x%02x\n", *atr);
+    es_fprintf (fp,"error: invalid TS character 0x%02x\n", *atr);
   if (!--atrlen)
     goto bailout;
   atr++;
@@ -79,34 +83,34 @@ atr_dump (int slot, FILE *fp)
   have_tc = !!(*atr & 0x40);
   have_td = !!(*atr & 0x80);
   n_historical = (*atr & 0x0f);
-  fprintf (fp, "%d historical characters indicated\n", n_historical);
+  es_fprintf (fp, "%d historical characters indicated\n", n_historical);
 
   if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
-    fputs ("error: ATR shorter than indicated by format character\n", fp);
+    es_fputs ("error: ATR shorter than indicated by format character\n", fp);
   if (!--atrlen)
     goto bailout;
   atr++;
 
   if (have_ta)
     {
-      fputs ("TA1: F=", fp);
+      es_fputs ("TA1: F=", fp);
       val = fi_table[(*atr >> 4) & 0x0f];
       if (!val)
-        fputs ("internal clock", fp);
+        es_fputs ("internal clock", fp);
       else if (val == -1)
-        fputs ("RFU", fp);
+        es_fputs ("RFU", fp);
       else
-        fprintf (fp, "%d", val);
-      fputs (" D=", fp);
+        es_fprintf (fp, "%d", val);
+      es_fputs (" D=", fp);
       val = di_table[*atr & 0x0f];
       if (!val)
-        fputs ("[impossible value]\n", fp);
+        es_fputs ("[impossible value]\n", fp);
       else if (val == -1)
-        fputs ("RFU\n", fp);
+        es_fputs ("RFU\n", fp);
       else if (val < 0 )
-        fprintf (fp, "1/%d\n", val);
+        es_fprintf (fp, "1/%d\n", val);
       else
-        fprintf (fp, "%d\n", val);
+        es_fprintf (fp, "%d\n", val);
 
       if (!--atrlen)
         goto bailout;
@@ -115,8 +119,9 @@ atr_dump (int slot, FILE *fp)
 
   if (have_tb)
     {
-      fprintf (fp, "TB1: II=%d PI1=%d%s\n", (*atr >> 5) & 3, *atr & 0x1f,
-               (*atr & 0x80)? " [high bit not cleared]":"");
+      es_fprintf (fp, "TB1: II=%d PI1=%d%s\n",
+                  ((*atr >> 5) & 3), (*atr & 0x1f),
+                  (*atr & 0x80)? " [high bit not cleared]":"");
       if (!--atrlen)
         goto bailout;
       atr++;
@@ -125,9 +130,9 @@ atr_dump (int slot, FILE *fp)
   if (have_tc)
     {
       if (*atr == 255)
-        fputs ("TC1: guard time shortened to 1 etu\n", fp);
+        es_fputs ("TC1: guard time shortened to 1 etu\n", fp);
       else
-        fprintf (fp, "TC1: (extra guard time) N=%d\n", *atr);
+        es_fprintf (fp, "TC1: (extra guard time) N=%d\n", *atr);
 
       if (!--atrlen)
         goto bailout;
@@ -140,10 +145,11 @@ atr_dump (int slot, FILE *fp)
       have_tb = !!(*atr & 0x20);
       have_tc = !!(*atr & 0x40);
       have_td = !!(*atr & 0x80);
-      fprintf (fp, "TD1: protocol T%d supported\n", *atr & 0x0f);
+      es_fprintf (fp, "TD1: protocol T%d supported\n", (*atr & 0x0f));
 
       if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
-        fputs ("error: ATR shorter than indicated by format character\n", fp);
+        es_fputs ("error: ATR shorter than indicated by format character\n",
+                  fp);
 
       if (!--atrlen)
         goto bailout;
@@ -154,12 +160,12 @@ atr_dump (int slot, FILE *fp)
 
   if (have_ta)
     {
-      fprintf (fp, "TA2: (PTS) %stoggle, %splicit, T=%02X\n",
-               (*atr & 0x80)? "no-":"",
-               (*atr & 0x10)? "im": "ex",
-               (*atr & 0x0f));
+      es_fprintf (fp, "TA2: (PTS) %stoggle, %splicit, T=%02X\n",
+                  (*atr & 0x80)? "no-":"",
+                  (*atr & 0x10)? "im": "ex",
+                  (*atr & 0x0f));
       if ((*atr & 0x60))
-        fprintf (fp, "note: reserved bits are set (TA2=0x%02X)\n", *atr);
+        es_fprintf (fp, "note: reserved bits are set (TA2=0x%02X)\n", *atr);
       if (!--atrlen)
         goto bailout;
       atr++;
@@ -167,7 +173,7 @@ atr_dump (int slot, FILE *fp)
 
   if (have_tb)
     {
-      fprintf (fp, "TB2: PI2=%d\n", *atr);
+      es_fprintf (fp, "TB2: PI2=%d\n", *atr);
       if (!--atrlen)
         goto bailout;
       atr++;
@@ -175,7 +181,7 @@ atr_dump (int slot, FILE *fp)
 
   if (have_tc)
     {
-      fprintf (fp, "TC2: PWI=%d\n", *atr);
+      es_fprintf (fp, "TC2: PWI=%d\n", *atr);
       if (!--atrlen)
         goto bailout;
       atr++;
@@ -187,10 +193,11 @@ atr_dump (int slot, FILE *fp)
       have_tb = !!(*atr & 0x20);
       have_tc = !!(*atr & 0x40);
       have_td = !!(*atr & 0x80);
-      fprintf (fp, "TD2: protocol T%d supported\n", *atr & 0x0f);
+      es_fprintf (fp, "TD2: protocol T%d supported\n", *atr & 0x0f);
 
       if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
-        fputs ("error: ATR shorter than indicated by format character\n", fp);
+        es_fputs ("error: ATR shorter than indicated by format character\n",
+                  fp);
 
       if (!--atrlen)
         goto bailout;
@@ -203,7 +210,7 @@ atr_dump (int slot, FILE *fp)
     {
       if (have_ta)
         {
-          fprintf (fp, "TA%d: IFSC=%d\n", idx, *atr);
+          es_fprintf (fp, "TA%d: IFSC=%d\n", idx, *atr);
           if (!--atrlen)
             goto bailout;
           atr++;
@@ -211,7 +218,7 @@ atr_dump (int slot, FILE *fp)
 
       if (have_tb)
         {
-          fprintf (fp, "TB%d: BWI=%d CWI=%d\n",
+          es_fprintf (fp, "TB%d: BWI=%d CWI=%d\n",
                    idx, (*atr >> 4) & 0x0f, *atr & 0x0f);
           if (!--atrlen)
             goto bailout;
@@ -220,7 +227,7 @@ atr_dump (int slot, FILE *fp)
 
       if (have_tc)
         {
-          fprintf (fp, "TC%d: 0x%02X\n", idx, *atr);
+          es_fprintf (fp, "TC%d: 0x%02X\n", idx, *atr);
           if (!--atrlen)
             goto bailout;
           atr++;
@@ -232,11 +239,12 @@ atr_dump (int slot, FILE *fp)
           have_tb = !!(*atr & 0x20);
           have_tc = !!(*atr & 0x40);
           have_td = !!(*atr & 0x80);
-          fprintf (fp, "TD%d: protocol T%d supported\n", idx, *atr & 0x0f);
+          es_fprintf (fp, "TD%d: protocol T%d supported\n", idx, *atr & 0x0f);
 
           if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
-            fputs ("error: ATR shorter than indicated by format character\n",
-                   fp);
+            es_fputs ("error: "
+                      "ATR shorter than indicated by format character\n",
+                      fp);
 
           if (!--atrlen)
             goto bailout;
@@ -247,150 +255,36 @@ atr_dump (int slot, FILE *fp)
     }
 
   if (n_historical + 1 > atrlen)
-    fputs ("error: ATR shorter than required for historical bytes "
-           "and checksum\n", fp);
+    es_fputs ("error: ATR shorter than required for historical bytes "
+              "and checksum\n", fp);
 
   if (n_historical)
     {
-      fputs ("Historical:", fp);
+      es_fputs ("HCH:", fp);
       for (; n_historical && atrlen ; n_historical--, atrlen--, atr++)
-        fprintf (fp, " %02X", *atr);
-      putchar ('\n');
+        es_fprintf (fp, " %02X", *atr);
+      es_putc ('\n', fp);
     }
 
   if (!atrlen)
-    fputs ("error: checksum missing\n", fp);
+    es_fputs ("error: checksum missing\n", fp);
   else if (*atr == chksum)
-    fprintf (fp, "TCK: %02X (good)\n", *atr);
+    es_fprintf (fp, "TCK: %02X (good)\n", *atr);
   else
-    fprintf (fp, "TCK: %02X (bad; calculated %02X)\n", *atr, chksum);
+    es_fprintf (fp, "TCK: %02X (bad; computed %02X)\n", *atr, chksum);
 
   atrlen--;
   if (atrlen)
-    fprintf (fp, "error: %u bytes garbage at end of ATR\n",
-             (unsigned int)atrlen );
+    es_fprintf (fp, "error: %u bytes garbage at end of ATR\n",
+                (unsigned int)atrlen );
 
  bailout:
-  xfree (atrbuffer);
-
-  return 0;
-}
-
-
-/* Note: This code has not yet been tested!  It shall return -1 on
-   error or the number of historical bytes and store them at
-   HISTORICAL.  */
-int
-atr_get_historical (int slot, unsigned char historical[])
-{
-  int result = -1;
-  unsigned char *atrbuffer = NULL;
-  unsigned char *atr;
-  size_t atrlen;
-  int have_ta, have_tb, have_tc, have_td;
-  int n_historical;
-  int idx;
-  unsigned char chksum;
-
-  atr = atrbuffer = apdu_get_atr (slot, &atrlen);
-  if (!atr || atrlen < 2)
-    goto leave;
-  atrlen--;
-  atr++;
-
-  chksum = *atr;
-  for (idx=1; idx < atrlen-1; idx++)
-    chksum ^= atr[idx];
-
-  have_ta = !!(*atr & 0x10);
-  have_tb = !!(*atr & 0x20);
-  have_tc = !!(*atr & 0x40);
-  have_td = !!(*atr & 0x80);
-  n_historical = (*atr & 0x0f);
-
-  if (have_ta + have_tb + have_tc + have_td + n_historical >= atrlen)
-    goto leave; /* ATR shorter than indicated by format character.  */
-  atrlen--;
-  atr++;
-
-  if (have_ta + have_tb + have_tc >= atrlen)
-    goto leave;
-  atrlen -= have_ta + have_tb + have_tc;
-  atr    += have_ta + have_tb + have_tc;
-
-  if (have_td)
-    {
-      have_ta = !!(*atr & 0x10);
-      have_tb = !!(*atr & 0x20);
-      have_tc = !!(*atr & 0x40);
-      have_td = !!(*atr & 0x80);
-      if (have_ta + have_tb + have_tc + have_td + n_historical >= atrlen)
-        goto leave; /* ATR shorter than indicated by format character.  */
-      atrlen--;
-      atr++;
-    }
-  else
-    have_ta = have_tb = have_tc = have_td = 0;
-
-  if (have_ta + have_tb + have_tc >= atrlen)
-    goto leave;
-  atrlen -= have_ta + have_tb + have_tc;
-  atr    += have_ta + have_tb + have_tc;
-
-  if (have_td)
+  es_putc ('\0', fp); /* We want a string.  */
+  if (es_fclose_snatch (fp, (void**)&result, NULL))
     {
-      have_ta = !!(*atr & 0x10);
-      have_tb = !!(*atr & 0x20);
-      have_tc = !!(*atr & 0x40);
-      have_td = !!(*atr & 0x80);
-      if (have_ta + have_tb + have_tc + have_td + n_historical >= atrlen)
-        goto leave; /* ATR shorter than indicated by format character.  */
-      atrlen--;
-      atr++;
+      log_error ("oops: es_fclose_snatch failed: %s\n", strerror (errno));
+      return NULL;
     }
-  else
-    have_ta = have_tb = have_tc = have_td = 0;
-
-  for (idx = 3; have_ta || have_tb || have_tc || have_td; idx++)
-    {
-      if (have_ta + have_tb + have_tc >= atrlen)
-        goto leave;
-      atrlen -= have_ta + have_tb + have_tc;
-      atr    += have_ta + have_tb + have_tc;
-
-      if (have_td)
-        {
-          have_ta = !!(*atr & 0x10);
-          have_tb = !!(*atr & 0x20);
-          have_tc = !!(*atr & 0x40);
-          have_td = !!(*atr & 0x80);
-          if (have_ta + have_tb + have_tc + have_td + n_historical >= atrlen)
-            goto leave; /* ATR shorter than indicated by format character.  */
-          atrlen--;
-          atr++;
-        }
-      else
-        have_ta = have_tb = have_tc = have_td = 0;
-    }
-
-  if (n_historical >= atrlen)
-    goto leave; /* ATR shorter than required for historical bytes. */
-
-  if (n_historical)
-    {
-      for (idx=0; n_historical && atrlen; n_historical--, atrlen--, atr++)
-        historical[idx] = *atr;
-    }
-
-  if (!atrlen || *atr != chksum)
-    goto leave;
-
-  /* Don't care about garbage at the end of the ATR.  */
-
-  result = n_historical;
-
- leave:
-  xfree (atrbuffer);
 
   return result;
 }
diff --git a/scd/atr.h b/scd/atr.h
index 5f07522..b06a83a 100644
--- a/scd/atr.h
+++ b/scd/atr.h
@@ -20,7 +20,7 @@
 #ifndef ATR_H
 #define ATR_H
 
-int atr_dump (int slot, FILE *fp);
+char *atr_dump (const void *buffer, size_t buflen);
 
 
 
diff --git a/scd/command.c b/scd/command.c
index 0f57448..afd5ef2 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -35,11 +35,13 @@
 #include <ksba.h>
 #include "app-common.h"
 #include "apdu.h" /* Required for apdu_*_reader (). */
+#include "atr.h"
 #include "exechelp.h"
 #ifdef HAVE_LIBUSB
 #include "ccid-driver.h"
 #endif
 
+
 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
 #define MAXLEN_PIN 100
 
@@ -1795,7 +1797,7 @@ cmd_disconnect (assuan_context_t ctx, char *line)
 
 
 static const char hlp_apdu[] =
-  "APDU [--atr] [--more] [--exlen[=N]] [hexstring]\n"
+  "APDU [--[dump-]atr] [--more] [--exlen[=N]] [hexstring]\n"
   "\n"
   "Send an APDU to the current reader.  This command bypasses the high\n"
   "level functions and sends the data directly to the card.  HEXSTRING\n"
@@ -1826,7 +1828,10 @@ cmd_apdu (assuan_context_t ctx, char *line)
   size_t exlen;
   int slot;
 
-  with_atr = has_option (line, "--atr");
+  if (has_option (line, "--dump-atr"))
+    with_atr = 2;
+  else
+    with_atr = has_option (line, "--atr");
   handle_more = has_option (line, "--more");
 
   if ((s=has_option_name (line, "--exlen")))
@@ -1861,9 +1866,32 @@ cmd_apdu (assuan_context_t ctx, char *line)
           rc = gpg_error (GPG_ERR_INV_CARD);
           goto leave;
         }
-      bin2hex (atr, atrlen, hexbuf);
+      if (with_atr == 2)
+        {
+          char *string, *p, *pend;
+
+          string = atr_dump (atr, atrlen);
+          if (string)
+            {
+              for (rc=0, p=string; !rc && (pend = strchr (p, '\n')); p = pend+1)
+                {
+                  rc = assuan_send_data (ctx, p, pend - p + 1);
+                  if (!rc)
+                    rc = assuan_send_data (ctx, NULL, 0);
+                }
+              if (!rc && *p)
+                rc = assuan_send_data (ctx, p, strlen (p));
+              es_free (string);
+              if (rc)
+                goto leave;
+            }
+        }
+      else
+        {
+          bin2hex (atr, atrlen, hexbuf);
+          send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
+        }
       xfree (atr);
-      send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
     }
 
   apdu = hex_to_buffer (line, &apdulen);

commit 7737a2c269657189a583cde7f214f20871d264f8
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Dec 15 14:45:08 2011 +0100

    estream: New function es_fclose_snatch.
    
    * common/estream.c (cookie_ioctl_function_t): New type.
    (es_fclose_snatch): New function.
    (COOKIE_IOCTL_SNATCH_BUFFER): New constant.
    (struct estream_internal): Add field FUNC_IOCTL.
    (es_initialize): Clear FUNC_IOCTL.
    (es_func_mem_ioctl): New function.
    (es_fopenmem, es_fopenmem_init): Init FUNC_IOCTL.

diff --git a/common/estream.c b/common/estream.c
index c55c7f2..6b7bd8b 100644
--- a/common/estream.c
+++ b/common/estream.c
@@ -217,6 +217,17 @@ struct notify_list_s
 };
 typedef struct notify_list_s *notify_list_t;
 
+
+/* A private cookie function to implement an internal IOCTL
+   service.  */
+typedef int (*cookie_ioctl_function_t) (void *cookie, int cmd,
+					void *ptr, size_t *len);
+/* IOCTL commands for the private cookie function.  */
+#define COOKIE_IOCTL_SNATCH_BUFFER 1
+
+
+
+
 /* An internal stream object.  */
 struct estream_internal
 {
@@ -231,6 +242,7 @@ struct estream_internal
   es_cookie_read_function_t func_read;
   es_cookie_write_function_t func_write;
   es_cookie_seek_function_t func_seek;
+  cookie_ioctl_function_t func_ioctl;
   es_cookie_close_function_t func_close;
   int strategy;
   es_syshd_t syshd;              /* A copy of the sytem handle.  */
@@ -771,6 +783,33 @@ es_func_mem_seek (void *cookie, off_t *offset, int whence)
   return 0;
 }
 
+/* An IOCTL function for memory objects.  */
+static int
+es_func_mem_ioctl (void *cookie, int cmd, void *ptr, size_t *len)
+{
+  estream_cookie_mem_t mem_cookie = cookie;
+  int ret;
+
+  if (cmd == COOKIE_IOCTL_SNATCH_BUFFER)
+    {
+      /* Return the internal buffer of the stream to the caller and
+         invalidate it for the stream.  */
+      *(void**)ptr = mem_cookie->memory;
+      *len = mem_cookie->offset;
+      mem_cookie->memory = NULL;
+      mem_cookie->memory_size = 0;
+      mem_cookie->offset = 0;
+      ret = 0;
+    }
+  else
+    {
+      _set_errno (EINVAL);
+      ret = -1;
+    }
+
+  return ret;
+}
+
 
 /* Destroy function for memory objects.  */
 static int
@@ -1608,6 +1647,7 @@ es_initialize (estream_t stream,
   stream->intern->func_read = functions.func_read;
   stream->intern->func_write = functions.func_write;
   stream->intern->func_seek = functions.func_seek;
+  stream->intern->func_ioctl = NULL;
   stream->intern->func_close = functions.func_close;
   stream->intern->strategy = _IOFBF;
   stream->intern->syshd = *syshd;
@@ -2667,6 +2707,9 @@ es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
   if (es_create (&stream, cookie, &syshd, estream_functions_mem, modeflags, 0))
     (*estream_functions_mem.func_close) (cookie);
 
+  if (stream)
+    stream->intern->func_ioctl = es_func_mem_ioctl;
+
   return stream;
 }
 
@@ -2701,6 +2744,10 @@ es_fopenmem_init (size_t memlimit, const char *ES__RESTRICT mode,
           es_set_indicators (stream, 0, 0);
         }
     }
+
+  if (stream)
+    stream->intern->func_ioctl = es_func_mem_ioctl;
+
   return stream;
 }
 
@@ -3082,6 +3129,65 @@ es_fclose (estream_t stream)
 }
 
 
+/* This is a special version of es_fclose which can be used with
+   es_fopenmem to return the memory buffer.  This is feature is useful
+   to write to a memory buffer using estream.  Note that the function
+   does not close the stream if the stream does not support snatching
+   the buffer.  On error NULL is stored at R_BUFFER.  Note that if no
+   write operation has happened, NULL may also be stored at BUFFER on
+   success.  The caller needs to release the returned memory using
+   es_free.  */
+int
+es_fclose_snatch (estream_t stream, void **r_buffer, size_t *r_buflen)
+{
+  int err;
+
+  /* Note: There is no need to lock the stream in a close call.  The
+     object will be destroyed after the close and thus any other
+     contender for the lock would work on a closed stream.  */
+
+  if (r_buffer)
+    {
+      cookie_ioctl_function_t func_ioctl = stream->intern->func_ioctl;
+      size_t buflen;
+
+      *r_buffer = NULL;
+
+      if (!func_ioctl)
+        {
+          _set_errno (EOPNOTSUPP);
+          err = -1;
+          goto leave;
+        }
+
+      if (stream->flags.writing)
+        {
+          err = es_flush (stream);
+          if (err)
+            goto leave;
+          stream->flags.writing = 0;
+        }
+
+      err = func_ioctl (stream->intern->cookie, COOKIE_IOCTL_SNATCH_BUFFER,
+                        r_buffer, &buflen);
+      if (err)
+        goto leave;
+      if (r_buflen)
+        *r_buflen = buflen;
+    }
+
+  err = do_close (stream, 0);
+
+ leave:
+  if (err && r_buffer)
+    {
+      mem_free (*r_buffer);
+      *r_buffer = NULL;
+    }
+  return err;
+}
+
+
 /* Register or unregister a close notification function for STREAM.
    FNC is the function to call and FNC_VALUE the value passed as
    second argument.  To register the notification the value for MODE
diff --git a/common/estream.h b/common/estream.h
index 4966276..bbe5b62 100644
--- a/common/estream.h
+++ b/common/estream.h
@@ -1,5 +1,5 @@
 /* estream.h - Extended stream I/O Library
- * Copyright (C) 2004, 2005, 2006, 2007, 2010 g10 Code GmbH
+ * Copyright (C) 2004, 2005, 2006, 2007, 2010, 2011 g10 Code GmbH
  *
  * This file is part of Libestream.
  *
@@ -88,6 +88,7 @@
 #define es_freopen            _ESTREAM_PREFIX(es_freopen)
 #define es_fopencookie        _ESTREAM_PREFIX(es_fopencookie)
 #define es_fclose             _ESTREAM_PREFIX(es_fclose)
+#define es_fclose_snatch      _ESTREAM_PREFIX(es_fclose_snatch)
 #define es_onclose            _ESTREAM_PREFIX(es_onclose)
 #define es_fileno             _ESTREAM_PREFIX(es_fileno)
 #define es_fileno_unlocked    _ESTREAM_PREFIX(es_fileno_unlocked)
@@ -285,6 +286,7 @@ estream_t es_fopencookie (void *ES__RESTRICT cookie,
 			  const char *ES__RESTRICT mode,
 			  es_cookie_io_functions_t functions);
 int es_fclose (estream_t stream);
+int es_fclose_snatch (estream_t stream, void **r_buffer, size_t *r_buflen);
 int es_onclose (estream_t stream, int mode,
                 void (*fnc) (estream_t, void*), void *fnc_value);
 int es_fileno (estream_t stream);

commit 792e137ec7997a0ff5c54ff970611238d28d4ba8
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Dec 14 18:56:10 2011 +0100

    scd: Skip S/N reading for the "undefined" application.
    
    * scd/app.c (select_application): Skip serial number reading.

diff --git a/scd/app.c b/scd/app.c
index 63ef4fa..31e56fb 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -242,11 +242,14 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
   app_t app = NULL;
   unsigned char *result = NULL;
   size_t resultlen;
+  int want_undefined;
 
   (void)ctrl;
 
   *r_app = NULL;
 
+  want_undefined = (name && !strcmp (name, "undefined"));
+
   err = lock_reader (slot, ctrl);
   if (err)
     return err;
@@ -326,45 +329,49 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
   /* Fixme: We should now first check whether a card is at all
      present. */
 
-  /* Try to read the GDO file first to get a default serial number. */
-  err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
-  if (!err)
-    err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
-  if (!err)
-     err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
-  if (!err)
+  /* Try to read the GDO file first to get a default serial number.
+     We skip this if the undefined application has been requested. */
+  if (!want_undefined)
     {
-      size_t n;
-      const unsigned char *p;
-
-      p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
-      if (p)
-        resultlen -= (p-result);
-      if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
-        {
-          /* The object it does not fit into the buffer.  This is an
-             invalid encoding (or the buffer is too short.  However, I
-             have some test cards with such an invalid encoding and
-             therefore I use this ugly workaround to return something
-             I can further experiment with. */
-          log_info ("enabling BMI testcard workaround\n");
-          n--;
-        }
-
-      if (p && n <= resultlen)
+      err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
+      if (!err)
+        err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
+      if (!err)
+        err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
+      if (!err)
         {
-          /* The GDO file is pretty short, thus we simply reuse it for
-             storing the serial number. */
-          memmove (result, p, n);
-          app->serialno = result;
-          app->serialnolen = n;
-          err = app_munge_serialno (app);
-          if (err)
-            goto leave;
+          size_t n;
+          const unsigned char *p;
+
+          p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
+          if (p)
+            resultlen -= (p-result);
+          if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
+            {
+              /* The object it does not fit into the buffer.  This is an
+                 invalid encoding (or the buffer is too short.  However, I
+                 have some test cards with such an invalid encoding and
+                 therefore I use this ugly workaround to return something
+                 I can further experiment with. */
+              log_info ("enabling BMI testcard workaround\n");
+              n--;
+            }
+
+          if (p && n <= resultlen)
+            {
+              /* The GDO file is pretty short, thus we simply reuse it for
+                 storing the serial number. */
+              memmove (result, p, n);
+              app->serialno = result;
+              app->serialnolen = n;
+              err = app_munge_serialno (app);
+              if (err)
+                goto leave;
+            }
+          else
+            xfree (result);
+          result = NULL;
         }
-      else
-        xfree (result);
-      result = NULL;
     }
 
   /* For certain error codes, there is no need to try more.  */
@@ -373,7 +380,15 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
     goto leave;
 
   /* Figure out the application to use.  */
-  err = gpg_error (GPG_ERR_NOT_FOUND);
+  if (want_undefined)
+    {
+      /* We switch to the "undefined" application only if explicitly
+         requested.  */
+      app->apptype = "UNDEFINED";
+      err = 0;
+    }
+  else
+    err = gpg_error (GPG_ERR_NOT_FOUND);
 
   if (err && is_app_allowed ("openpgp")
           && (!name || !strcmp (name, "openpgp")))
@@ -387,14 +402,6 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
   if (err && is_app_allowed ("geldkarte")
       && (!name || !strcmp (name, "geldkarte")))
     err = app_select_geldkarte (app);
-  if (err && is_app_allowed ("undefined")
-      && (name && !strcmp (name, "undefined")))
-    {
-      /* We switch to the "undefined" application only if explicitly
-         requested.  */
-      app->apptype = "UNDEFINED";
-      err = 0;
-    }
   if (err && name)
     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
 

commit 0bac31ee9f74a25d76b08c3e0355a338908f083a
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Dec 14 18:48:47 2011 +0100

    scd: Add more status word values for documentation.

diff --git a/scd/apdu.c b/scd/apdu.c
index c37e8c4..5a51846 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -463,8 +463,11 @@ apdu_strerror (int rc)
     case SW_FILE_NOT_FOUND : return "file not found";
     case SW_RECORD_NOT_FOUND:return "record not found";
     case SW_REF_NOT_FOUND  : return "reference not found";
-    case SW_BAD_LC         : return "bad Lc";
-    case SW_BAD_P0_P1      : return "bad P0 or P1";
+    case SW_NOT_ENOUGH_MEMORY: return "not enough memory space in the file";
+    case SW_INCONSISTENT_LC: return "Lc inconsistent with TLV structure.";
+    case SW_INCORRECT_P0_P1: return "incorrect parameters P0,P1";
+    case SW_BAD_LC         : return "Lc inconsistent with P0,P1";
+    case SW_BAD_P0_P1      : return "bad P0,P1";
     case SW_INS_NOT_SUP    : return "instruction not supported";
     case SW_CLA_NOT_SUP    : return "class not supported";
     case SW_SUCCESS        : return "success";
diff --git a/scd/apdu.h b/scd/apdu.h
index f704256..7502546 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -41,6 +41,9 @@ enum {
   SW_NOT_SUPPORTED  = 0x6a81,
   SW_FILE_NOT_FOUND = 0x6a82,
   SW_RECORD_NOT_FOUND = 0x6a83,
+  SW_NOT_ENOUGH_MEMORY= 0x6a84, /* Not enough memory space in the file.  */
+  SW_INCONSISTENT_LC  = 0x6a85, /* Lc inconsistent with TLV structure.  */
+  SW_INCORRECT_P0_P1  = 0x6a86,
   SW_BAD_LC         = 0x6a87, /* Lc does not match command or p1/p2.  */
   SW_REF_NOT_FOUND  = 0x6a88,
   SW_BAD_P0_P1      = 0x6b00,

commit dcd64131c60efd0189aa05d5dbce6b93547b04e3
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Dec 14 17:00:50 2011 +0100

    scd: Add the "undefined" stub application.
    
    * scd/app.c (select_application): Implement the "undefined"
    application.

diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi
index 9184ce2..200fed8 100644
--- a/doc/scdaemon.texi
+++ b/doc/scdaemon.texi
@@ -181,6 +181,8 @@ write hashed data to files named @code{dbgmd-000*}
 trace Assuan protocol.  See also option @option{--debug-assuan-log-cats}.
 @item 11 (2048)
 trace APDU I/O to the card.  This may reveal sensitive data.
+ at item 12 (4096)
+trace some card reader related function calls.
 @end table
 
 @item --debug-all
@@ -327,6 +329,7 @@ stripping off the two leading dashes.
 * DINSIG Card::           The DINSIG card application
 * PKCS#15 Card::          The PKCS#15 card application
 * Geldkarte Card::        The Geldkarte application
+* Undefined Card::        The Undefined stub application
 @end menu
 
 @node OpenPGP Card
@@ -367,6 +370,14 @@ This is a simple application to display information of a German
 Geldkarte.  The Geldkarte is a small amount debit card application which
 comes with almost all German banking cards.
 
+ at node Undefined Card
+ at subsection The Undefined card application ``undefined''
+
+This is a stub application to allow the use of the APDU command even
+if no supported application is found on the card.  This application is
+not used automatically but must be explicitly requested using the
+SERIALNO command.
+
 
 @c *******************************************
 @c ***************            ****************
diff --git a/scd/app.c b/scd/app.c
index 6f0d756..63ef4fa 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -387,6 +387,14 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
   if (err && is_app_allowed ("geldkarte")
       && (!name || !strcmp (name, "geldkarte")))
     err = app_select_geldkarte (app);
+  if (err && is_app_allowed ("undefined")
+      && (name && !strcmp (name, "undefined")))
+    {
+      /* We switch to the "undefined" application only if explicitly
+         requested.  */
+      app->apptype = "UNDEFINED";
+      err = 0;
+    }
   if (err && name)
     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
 
@@ -422,6 +430,8 @@ get_supported_applications (void)
     "p15",
     "dinsig",
     "geldkarte",
+    /* Note: "undefined" is not listed here because it needs special
+       treatment by the client.  */
     NULL
   };
   int idx;

-----------------------------------------------------------------------

Summary of changes:
 common/estream.c  |  106 ++++++++++++++++++++++
 common/estream.h  |    4 +-
 doc/scdaemon.texi |   11 +++
 scd/Makefile.am   |    1 +
 scd/apdu.c        |    7 +-
 scd/apdu.h        |    3 +
 scd/app.c         |   91 +++++++++++--------
 scd/atr.c         |  252 +++++++++++++++-------------------------------------
 scd/atr.h         |    2 +-
 scd/command.c     |   36 +++++++-
 10 files changed, 289 insertions(+), 224 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list