gpg: Fix typo.
[gnupg.git] / g10 / call-agent.c
index 7c30bdb..be8c33d 100644 (file)
 
 #include "gpg.h"
 #include <assuan.h>
-#include "util.h"
-#include "membuf.h"
+#include "../common/util.h"
+#include "../common/membuf.h"
 #include "options.h"
-#include "i18n.h"
-#include "asshelp.h"
-#include "sysutils.h"
+#include "../common/i18n.h"
+#include "../common/asshelp.h"
+#include "../common/sysutils.h"
 #include "call-agent.h"
-#include "status.h"
+#include "../common/status.h"
 #include "../common/shareddefs.h"
-#include "host2net.h"
+#include "../common/host2net.h"
 
 #define CONTROL_D ('D' - 'A' + 1)
 
@@ -160,7 +160,8 @@ default_inq_cb (void *opaque, const char *line)
           char buf[32];
 
           if (parm->keyinfo.keyid)
-            emit_status_need_passphrase (parm->keyinfo.keyid,
+            emit_status_need_passphrase (parm->ctrl,
+                                         parm->keyinfo.keyid,
                                          parm->keyinfo.mainkeyid,
                                          parm->keyinfo.pubkey_algo);
 
@@ -656,18 +657,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",
@@ -769,7 +758,7 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
 \f
 /* Call the agent to retrieve a data object.  This function returns
    the data in the same structure as used by the learn command.  It is
-   allowed to update such a structure using this commmand. */
+   allowed to update such a structure using this command. */
 int
 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
 {
@@ -1024,101 +1013,37 @@ agent_scd_genkey (int keyno, int force, u32 *createtime)
   status_sc_op_failure (rc);
   return rc;
 }
-
-
-
 \f
-/* Issue an SCD SERIALNO openpgp command and if SERIALNO is not NULL
-   ask the user to insert the requested card.  */
-gpg_error_t
-select_openpgp (const char *serialno)
+/* 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)
 {
-  gpg_error_t err;
-
-  /* Send the serialno command to initialize the connection.  Without
-     a given S/N we don't care about the data returned.  If the card
-     has already been initialized, this is a very fast command.  We
-     request the openpgp card because that is what we expect.
-
-     Note that an opt.limit_card_insert_tries of 1 means: No tries at
-     all whereas 0 means do not limit the number of tries.  Due to the
-     sue of a pinentry prompt with a cancel option we use it here in a
-     boolean sense.  */
-  if (!serialno || opt.limit_card_insert_tries == 1)
-    err = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
-                           NULL, NULL, NULL, NULL, NULL, NULL);
-  else
-    {
-      char *this_sn = NULL;
-      char *desc;
-      int ask;
-      char *want_sn;
-      char *p;
-
-      want_sn = xtrystrdup (serialno);
-      if (!want_sn)
-        return gpg_error_from_syserror ();
-      p = strchr (want_sn, '/');
-      if (p)
-        *p = 0;
+  int err;
+  char *serialno = NULL;
+  char line[ASSUAN_LINELENGTH];
 
-      do
-        {
-          ask = 0;
-          err = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
-                                 NULL, NULL, NULL, NULL,
-                                 get_serialno_cb, &this_sn);
-          if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
-            ask = 1;
-          else if (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED)
-            ask = 2;
-          else if (err)
-            ;
-          else if (this_sn)
-            {
-              if (strcmp (want_sn, this_sn))
-                ask = 2;
-            }
+  err = start_agent (NULL, 1);
+  if (err)
+    return err;
 
-          xfree (this_sn);
-          this_sn = NULL;
+  if (!demand)
+    strcpy (line, "SCD SERIALNO");
+  else
+    snprintf (line, DIM(line), "SCD SERIALNO --demand=%s", demand);
 
-          if (ask)
-            {
-              char *formatted = NULL;
-              char *ocodeset = i18n_switchto_utf8 ();
-
-              if (!strncmp (want_sn, "D27600012401", 12)
-                  && strlen (want_sn) == 32 )
-                formatted = xtryasprintf ("(%.4s) %.8s",
-                                          want_sn + 16, want_sn + 20);
-
-              err = 0;
-              desc = xtryasprintf
-                ("%s:\n\n"
-                 "  \"%s\"",
-                 ask == 1
-                 ? _("Please insert the card with serial number")
-                 : _("Please remove the current card and "
-                     "insert the one with serial number"),
-                 formatted? formatted : want_sn);
-              if (!desc)
-                err = gpg_error_from_syserror ();
-              xfree (formatted);
-              i18n_switchback (ocodeset);
-              if (!err)
-                err = gpg_agent_get_confirmation (desc);
-              xfree (desc);
-            }
-        }
-      while (ask && !err);
-      xfree (want_sn);
+  err = assuan_transact (agent_ctx, line,
+                         NULL, NULL, NULL, NULL,
+                         get_serialno_cb, &serialno);
+  if (err)
+    {
+      xfree (serialno);
+      return err;
     }
 
-  return err;
+  *r_serialno = serialno;
+  return 0;
 }
-
-
 \f
 /* Send a READCERT command to the SCdaemon. */
 int
@@ -1158,8 +1083,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