* gpg.sgml: Clarify new notation delete feature.
[gnupg.git] / g10 / cardglue.c
index 0e2da27..d850b56 100644 (file)
@@ -1,5 +1,5 @@
 /* cardglue.c - mainly dispatcher for card related functions.
- * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -29,7 +29,6 @@
 #include <errno.h>
 #include <stdarg.h>
 #include <assert.h>
-
 #include "options.h"
 #include "packet.h"
 #include "errors.h"
@@ -83,7 +82,7 @@ static assuan_error_t learn_status_cb (void *opaque, const char *line);
 #define ASSUAN_LINELENGTH 100
 
 static assuan_context_t 
-agent_open (int try)
+agent_open (int try, const char *orig_codeset)
 {
   return NULL;
 }
@@ -338,7 +337,7 @@ open_card_via_agent (int *scd_available)
   int rc;
 
   *scd_available = 0;
-  ctx = agent_open (1);
+  ctx = agent_open (1, NULL);
   if (!ctx)
     return NULL;
 
@@ -520,10 +519,24 @@ format_cacheid (const char *sn)
   return cacheid;
 }
 
+
+/* If RC is not 0, write an appropriate status message. */
+static void
+status_sc_op_failure (int rc)
+{
+  if (rc == G10ERR_CANCELED)
+    write_status_text (STATUS_SC_OP_FAILURE, "1");
+  else if (rc == G10ERR_BAD_PASS)
+    write_status_text (STATUS_SC_OP_FAILURE, "2");
+  else if (rc)
+    write_status (STATUS_SC_OP_FAILURE);
+}  
+
+
 /* Check that the serial number of the current card (as described by
    APP) matches SERIALNO.  If there is no match and we are not in
    batch mode, present a prompt to insert the desired card.  The
-   function return 0 is the present card is okay, -1 if the user
+   function returnd 0 if the present card is okay, -1 if the user
    selected to insert a new card or an error value.  Note that the
    card context will be closed in all cases except for 0 as return
    value and if it was possible to merely shutdown the reader. */
@@ -533,7 +546,7 @@ check_card_serialno (app_t app, const char *serialno)
   const char *s;
   int ask = 0;
   int n;
-  
+
   for (s = serialno, n=0; *s != '/' && hexdigitp (s); s++, n++)
     ;
   if (n != 32)
@@ -555,17 +568,20 @@ check_card_serialno (app_t app, const char *serialno)
         did_shutdown = 1;
       else
         card_close ();
-      tty_printf (_("Please remove the current card and "
-                    "insert the one with serial number:\n"
-                    "   %.*s\n"), 32, serialno);
+
+      if (!opt.batch)
+        tty_printf (_("Please remove the current card and "
+                      "insert the one with serial number:\n"
+                      "   %.*s\n"), 32, serialno);
 
       sprintf (buf, "1 %.32s", serialno);
       write_status_text (STATUS_CARDCTRL, buf);
 
-      if ( cpr_get_answer_okay_cancel ("cardctrl.change_card.okay",
-                          _("Hit return when ready "
-                            "or enter 'c' to cancel: "),
-                                       1) )
+      if ( !opt.batch
+           && cpr_get_answer_okay_cancel ("cardctrl.change_card.okay",
+                                          _("Hit return when ready "
+                                            "or enter 'c' to cancel: "),
+                                          1) )
         {
           card_close ();
           return -1;
@@ -880,8 +896,18 @@ pin_cb (void *opaque, const char *info, char **retstr)
 
  again:
   if (is_status_enabled())
-    write_status_text (STATUS_NEED_PASSPHRASE_PIN,
-                       isadmin? "OPENPGP 3" : "OPENPGP 1");
+    {
+      if (parm && parm->sn && *parm->sn)
+        {
+          char *buf = xmalloc ( 10 + strlen (parm->sn) + 1);
+          strcpy (stpcpy (buf, isadmin? "OPENPGP 3 ":"OPENPGP 1 "), parm->sn);
+          write_status_text (STATUS_NEED_PASSPHRASE_PIN, buf);
+          xfree (buf);
+        }
+      else  
+        write_status_text (STATUS_NEED_PASSPHRASE_PIN,
+                           isadmin? "OPENPGP 3" : "OPENPGP 1");
+    }
 
   value = ask_passphrase (info, again_text,
                           newpin && isadmin? "passphrase.adminpin.new.ask" :
@@ -898,7 +924,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
   cacheid = NULL;
   again_text = NULL;
   if (!value && canceled)
-    return -1;
+    return G10ERR_CANCELED;
   else if (!value)
     return G10ERR_GENERAL;
 
@@ -906,16 +932,17 @@ pin_cb (void *opaque, const char *info, char **retstr)
     {
       char *value2;
 
-      value2 = ask_passphrase (info, NULL, NULL,
+      value2 = ask_passphrase (info, NULL,
                                "passphrase.pin.repeat", 
                                _("Repeat this PIN: "),
-                              &canceled);
-      if (!value && canceled)
+                               NULL,
+                               &canceled);
+      if (!value2 && canceled)
         {
           xfree (value);
-          return -1;
+          return G10ERR_CANCELED;
         }
-      else if (!value)
+      else if (!value2)
         {
           xfree (value);
           return G10ERR_GENERAL;
@@ -940,10 +967,15 @@ pin_cb (void *opaque, const char *info, char **retstr)
 /* Send a SETATTR command to the SCdaemon. */
 int 
 agent_scd_setattr (const char *name,
-                   const unsigned char *value, size_t valuelen)
+                   const unsigned char *value, size_t valuelen,
+                   const char *serialno)
 {
   app_t app;
   int rc;
+  struct pincb_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialno;
 
   app = current_app? current_app : open_card ();
   if (!app)
@@ -981,11 +1013,10 @@ agent_scd_setattr (const char *name,
     }
   else
     {
-      rc = app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
+      rc = app->fnc.setattr (app, name, pin_cb, &parm, value, valuelen);
     }
 
-  if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+  status_sc_op_failure (rc);
   return rc;
 }
 
@@ -1003,11 +1034,17 @@ inq_writekey_parms (void *opaque, const char *keyword)
 
 /* Send a WRITEKEY command to the SCdaemon. */
 int 
-agent_scd_writekey (int keyno, const unsigned char *keydata, size_t keydatalen)
+agent_scd_writekey (int keyno, const char *serialno,
+                    const unsigned char *keydata, size_t keydatalen)
 {
   app_t app;
   int rc;
   char line[ASSUAN_LINELENGTH];
+  struct pincb_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialno;
+
   app = current_app? current_app : open_card ();
   if (!app)
     return gpg_error (GPG_ERR_CARD);
@@ -1032,12 +1069,11 @@ agent_scd_writekey (int keyno, const unsigned char *keydata, size_t keydatalen)
       snprintf (line, DIM(line)-1, "OPENPGP.%d", keyno);
       line[DIM(line)-1] = 0;
       rc = app->fnc.writekey (app, NULL, line, 0x0001,
-                              pin_cb, NULL,
+                              pin_cb, &parm,
                               keydata, keydatalen);
     }
 
-  if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+  status_sc_op_failure (rc);
   return rc;
 }
 
@@ -1097,12 +1133,17 @@ genkey_status_cb (void *opaque, const char *line)
 
 /* Send a GENKEY command to the SCdaemon. */
 int 
-agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
+agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
+                  const char *serialno)
 {
   app_t app;
   char line[ASSUAN_LINELENGTH];
   struct ctrl_ctx_s ctrl;
   int rc;
+  struct pincb_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialno;
 
   app = current_app? current_app : open_card ();
   if (!app)
@@ -1127,11 +1168,10 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
       ctrl.status_cb_arg = info;
       rc = app->fnc.genkey (app, &ctrl, line,
                             force? 1:0,
-                            pin_cb, NULL);
+                            pin_cb, &parm);
     }
 
-  if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+  status_sc_op_failure (rc);
   return rc;
 }
 
@@ -1213,7 +1253,7 @@ agent_scd_pksign (const char *serialno, int hashalgo,
 
   if (rc)
     {
-      write_status (STATUS_SC_OP_FAILURE);
+      status_sc_op_failure (rc);
       if (!app->assuan_ctx)
         agent_clear_pin_cache (serialno);
     }
@@ -1287,20 +1327,26 @@ agent_scd_pkdecrypt (const char *serialno,
 
   if (rc)
     {
-      write_status (STATUS_SC_OP_FAILURE);
+      status_sc_op_failure (rc);
       if (!app->assuan_ctx)
         agent_clear_pin_cache (serialno);
     }
   return rc;
 }
 
-/* Change the PIN of an OpenPGP card or reset the retry counter. */
+/* Change the PIN of an OpenPGP card or reset the retry
+   counter. SERIALNO may be NULL or a hex string finally passed to the
+   passphrase callback. */
 int 
-agent_scd_change_pin (int chvno)
+agent_scd_change_pin (int chvno, const char *serialno)
 {
   app_t app;
   int reset = 0;
   int rc;
+  struct pincb_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialno;
 
   reset = (chvno >= 100);
   chvno %= 100;
@@ -1326,11 +1372,10 @@ agent_scd_change_pin (int chvno)
 
       sprintf (chvnostr, "%d", chvno);
       rc = app->fnc.change_pin (app, NULL, chvnostr, reset,
-                                pin_cb, NULL);
+                                pin_cb, &parm);
     }
 
-  if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+  status_sc_op_failure (rc);
   return rc;
 }
 
@@ -1342,6 +1387,10 @@ agent_scd_checkpin (const char *serialnobuf)
 {
   app_t app;
   int rc;
+  struct pincb_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialnobuf;
 
   app = current_app? current_app : open_card ();
   if (!app)
@@ -1360,11 +1409,10 @@ agent_scd_checkpin (const char *serialnobuf)
     }
   else
     {
-      rc = app->fnc.check_pin (app, serialnobuf, pin_cb, NULL);
+      rc = app->fnc.check_pin (app, serialnobuf, pin_cb, &parm);
     }
 
-  if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+  status_sc_op_failure (rc);
   return rc;
 }