agent,g10: Remove redundant SERIALNO request.
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 16 Mar 2017 05:32:51 +0000 (14:32 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 16 Mar 2017 05:32:51 +0000 (14:32 +0900)
* agent/learncard.c (agent_handle_learn): Don't call
agent_card_serialno.  Get the serialno in status response.
* g10/call-agent.c (agent_scd_learn): Don't request "SCD SERIALNO".
(agent_scd_serialno): New.
(card_cardlist_cb, agent_scd_cardlist): New.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
agent/learncard.c
g10/call-agent.c
g10/call-agent.h

index cce9c3a..e0c882a 100644 (file)
@@ -302,11 +302,10 @@ int
 agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
 {
   int rc;
-
   struct kpinfo_cb_parm_s parm;
   struct certinfo_cb_parm_s cparm;
   struct sinfo_cb_parm_s sparm;
-  char *serialno = NULL;
+  const char *serialno = NULL;
   KEYPAIR_INFO item;
   SINFO sitem;
   unsigned char grip[20];
@@ -329,11 +328,6 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
   parm.ctrl = ctrl;
   cparm.ctrl = ctrl;
 
-  /* Check whether a card is present and get the serial number */
-  rc = agent_card_serialno (ctrl, &serialno, NULL);
-  if (rc)
-    goto leave;
-
   /* Now gather all the available info. */
   rc = agent_card_learn (ctrl, kpinfo_cb, &parm, certinfo_cb, &cparm,
                          sinfo_cb, &sparm);
@@ -345,17 +339,25 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
       goto leave;
     }
 
-  log_info ("card has S/N: %s\n", serialno);
-
   /* Pass on all the collected status information. */
   if (assuan_context)
     {
       for (sitem = sparm.info; sitem; sitem = sitem->next)
         {
+          if (!strcmp (sitem->keyword, "SERIALNO"))
+            serialno = sitem->data;
           assuan_write_status (assuan_context, sitem->keyword, sitem->data);
         }
     }
 
+  if (!serialno)
+    {
+      rc = GPG_ERR_NOT_FOUND;
+      goto leave;
+    }
+
+  log_info ("card has S/N: %s\n", serialno);
+
   /* Write out the certificates in a standard order. */
   for (i=0; certtype_list[i] != -1; i++)
     {
@@ -438,7 +440,6 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
 
 
  leave:
-  xfree (serialno);
   release_keypair_info (parm.info);
   release_certinfo (cparm.info);
   release_sinfo (sparm.info);
index 1606797..af06bf5 100644 (file)
@@ -656,18 +656,6 @@ agent_scd_learn (struct agent_card_info_s *info, int force)
   if (rc)
     return rc;
 
-  /* Send the serialno command to initialize the connection.  We don't
-     care about the data returned.  If the card has already been
-     initialized, this is a very fast command.  The main reason we
-     need to do this here is to handle a card removed case so that an
-     "l" command in --edit-card can be used to show ta newly inserted
-     card.  We request the openpgp card because that is what we
-     expect. */
-  rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
-                        NULL, NULL, NULL, NULL, NULL, NULL);
-  if (rc)
-    return rc;
-
   parm.ctx = agent_ctx;
   rc = assuan_transact (agent_ctx,
                         force ? "LEARN --sendinfo --force" : "LEARN --sendinfo",
@@ -1024,9 +1012,37 @@ agent_scd_genkey (int keyno, int force, u32 *createtime)
   status_sc_op_failure (rc);
   return rc;
 }
+\f
+/* Return the serial number of the card or an appropriate error.  The
+   serial number is returned as a hexstring. */
+int
+agent_scd_serialno (char **r_serialno, const char *demand)
+{
+  int err;
+  char *serialno = NULL;
+  char line[ASSUAN_LINELENGTH];
 
+  err = start_agent (NULL, 1);
+  if (err)
+    return err;
 
+  if (!demand)
+    strcpy (line, "SCD SERIALNO");
+  else
+    snprintf (line, DIM(line), "SCD SERIALNO --demand=%s", demand);
 
+  err = assuan_transact (agent_ctx, line,
+                         NULL, NULL, NULL, NULL,
+                         get_serialno_cb, &serialno);
+  if (err)
+    {
+      xfree (serialno);
+      return err;
+    }
+
+  *r_serialno = serialno;
+  return 0;
+}
 \f
 /* Send a READCERT command to the SCdaemon. */
 int
@@ -1066,8 +1082,72 @@ agent_scd_readcert (const char *certidstr,
 
   return 0;
 }
+\f
+struct card_cardlist_parm_s {
+  int error;
+  strlist_t list;
+};
+
 
+/* Callback function for agent_card_cardlist.  */
+static gpg_error_t
+card_cardlist_cb (void *opaque, const char *line)
+{
+  struct card_cardlist_parm_s *parm = opaque;
+  const char *keyword = line;
+  int keywordlen;
 
+  for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
+    ;
+  while (spacep (line))
+    line++;
+
+  if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
+    {
+      const char *s;
+      int n;
+
+      for (n=0,s=line; hexdigitp (s); s++, n++)
+        ;
+
+      if (!n || (n&1) || *s)
+        parm->error = gpg_error (GPG_ERR_ASS_PARAMETER);
+      else
+        add_to_strlist (&parm->list, line);
+    }
+
+  return 0;
+}
+
+/* Return cardlist.  */
+int
+agent_scd_cardlist (strlist_t *result)
+{
+  int err;
+  char line[ASSUAN_LINELENGTH];
+  struct card_cardlist_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  *result = NULL;
+  err = start_agent (NULL, 1);
+  if (err)
+    return err;
+
+  strcpy (line, "SCD GETINFO card_list");
+
+  err = assuan_transact (agent_ctx, line,
+                         NULL, NULL, NULL, NULL,
+                         card_cardlist_cb, &parm);
+  if (!err && parm.error)
+    err = parm.error;
+
+  if (!err)
+    *result = parm.list;
+  else
+    free_strlist (parm.list);
+
+  return 0;
+}
 \f
 /* Change the PIN of an OpenPGP card or reset the retry counter.
    CHVNO 1: Change the PIN
index e4fea57..a04fc73 100644 (file)
@@ -76,6 +76,12 @@ void agent_release_card_info (struct agent_card_info_s *info);
 /* Return card info. */
 int agent_scd_learn (struct agent_card_info_s *info, int force);
 
+/* Return list of cards.  */
+int agent_scd_cardlist (strlist_t *result);
+
+/* Return the serial number, possibly select by DEMAND.  */
+int agent_scd_serialno (char **r_serialno, const char *demand);
+
 /* Send an APDU to the card.  */
 gpg_error_t agent_scd_apdu (const char *hexapdu, unsigned int *r_sw);