* call-scd.c (inq_needpin): Skip leading spaces in of PIN
authorWerner Koch <wk@gnupg.org>
Tue, 24 May 2005 12:37:36 +0000 (12:37 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 24 May 2005 12:37:36 +0000 (12:37 +0000)
description.
* divert-scd.c (getpin_cb): Enhanced to cope with description
flags.
* query.c (agent_askpin): Add arg PROMPT_TEXT. Changed all
callers.

TODO
agent/ChangeLog
agent/agent.h
agent/call-scd.c
agent/command-ssh.c
agent/divert-scd.c
agent/findkey.c
agent/genkey.c
agent/query.c
scd/app-openpgp.c

diff --git a/TODO b/TODO
index fe10e9f..74763a7 100644 (file)
--- a/TODO
+++ b/TODO
@@ -96,11 +96,3 @@ might want to have an agent context for each service request
 
 
 
-* IMPORTANT:
-  Check that the PIN cache is cleared after failed card operations.
-  After receiving a HUP gpg-agent should set a flag to kill scdaemon
-  as soon as possible, w/o that scdaemon will continue running as a
-  zombie and gpg-agent won't be able to fire up a new one.
-  Implement an scd/agent option to wait for a card.
-
-
index 6c271c8..dcf0cdf 100644 (file)
@@ -1,3 +1,12 @@
+2005-05-24  Werner Koch  <wk@g10code.com>
+
+       * call-scd.c (inq_needpin): Skip leading spaces in of PIN
+       description.
+       * divert-scd.c (getpin_cb): Enhanced to cope with description
+       flags.
+       * query.c (agent_askpin): Add arg PROMPT_TEXT. Changed all
+       callers.
+
 2005-05-21  Werner Koch  <wk@g10code.com>
 
        * call-scd.c (start_scd): Don't test for an alive scdaemon here.
index 7e4f555..e416914 100644 (file)
@@ -179,7 +179,8 @@ int agent_key_available (const unsigned char *grip);
 /*-- query.c --*/
 void initialize_module_query (void);
 int agent_askpin (ctrl_t ctrl,
-                  const char *desc_text, const char *inital_errtext,
+                  const char *desc_text, const char *prompt_text,
+                  const char *inital_errtext,
                   struct pin_entry_info_s *pininfo);
 int agent_get_passphrase (ctrl_t ctrl, char **retpass,
                           const char *desc, const char *prompt,
index 617ef0d..78e28fe 100644 (file)
@@ -601,6 +601,8 @@ inq_needpin (void *opaque, const char *line)
       return ASSUAN_Inquire_Unknown;
     }
   line += 7;
+  while (*line == ' ')
+    line++;
 
   pinlen = 90;
   pin = gcry_malloc_secure (pinlen);
index 92a84c6..030cc70 100644 (file)
@@ -2369,7 +2369,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
     }
   pi->max_length = 100;
   pi->max_tries = 1;
-  err = agent_askpin (ctrl, description, NULL, pi);
+  err = agent_askpin (ctrl, description, NULL, NULL, pi);
   if (err)
     goto out;
 
index f460ffe..41a5dfc 100644 (file)
@@ -168,35 +168,113 @@ encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
    buf has been allocated by the caller and is of size MAXBUF which
    includes the terminating null.  The function should return an UTF-8
    string with the passphrase, the buffer may optionally be padded
-   with arbitrary characters */
+   with arbitrary characters.
+
+   INFO gets displayed as part of a generic string.  However if the
+   first character of INFO is a vertical bar all up to the next
+   verical bar are considered flags and only everything after the
+   second vertical bar gets displayed as the full prompt.
+
+   Flags:
+
+      'N' = New PIN, this requests a second prompt to repeat the the
+            PIN.  If the PIN is not correctly repeated it starts from
+            all over.
+      'A' = The PIN is an Admin PIN, SO-PIN, PUK or alike.
+
+   Example:
+
+     "|AN|Please enter the new security officer's PIN"
+     
+   The text "Please ..." will get displayed and the flags 'A' and 'N'
+   are considered.
+ */
 static int 
 getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
 {
   struct pin_entry_info_s *pi;
   int rc;
-  char *desc;
-  CTRL ctrl = opaque;
+  ctrl_t ctrl = opaque;
+  const char *ends, *s;
+  int any_flags = 0;
+  int newpin = 0;
+  const char *again_text = NULL;
+  const char *prompt = "PIN";
 
   if (maxbuf < 2)
     return gpg_error (GPG_ERR_INV_VALUE);
 
+  /* Parse the flags. */
+  if (info && *info =='|' && (ends=strchr (info+1, '|')))
+    {
+      for (s=info+1; s < ends; s++)
+        {
+          if (*s == 'A')
+            prompt = _("Admin PIN");
+          else if (*s == 'N')
+            newpin = 1;
+        }
+      info = ends+1;
+      any_flags = 1;
+    }
+  else if (info && *info == '|')
+    log_debug ("pin_cb called without proper PIN info hack\n");
+
 
   /* FIXME: keep PI and TRIES in OPAQUE.  Frankly this is a whole
      mess because we should call the card's verify function from the
      pinentry check pin CB. */
-  pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
+ again:
+  pi = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
+  if (!pi)
+    return gpg_error_from_errno (errno);
   pi->max_length = maxbuf-1;
   pi->min_digits = 0;  /* we want a real passphrase */
   pi->max_digits = 8;
   pi->max_tries = 3;
 
-  if ( asprintf (&desc, _("Please enter the PIN%s%s%s to unlock the card"), 
-                 info? " (`":"",
-                 info? info:"",
-                 info? "')":"") < 0)
-    desc = NULL;
-  rc = agent_askpin (ctrl, desc?desc:info, NULL, pi);
-  free (desc);
+  if (any_flags)
+    {
+      rc = agent_askpin (ctrl, info, prompt, again_text, pi);
+      again_text = NULL;
+      if (!rc && newpin)
+        {
+          struct pin_entry_info_s *pi2;
+          pi2 = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
+          if (!pi2)
+            {
+              rc = gpg_error_from_errno (errno);
+              xfree (pi);
+              return rc;
+            }
+          pi2->max_length = maxbuf-1;
+          pi2->min_digits = 0;
+          pi2->max_digits = 8;
+          pi2->max_tries = 1;
+          rc = agent_askpin (ctrl, _("Repeat this PIN"), prompt, NULL, pi2);
+          if (!rc && strcmp (pi->pin, pi2->pin))
+            {
+              again_text = N_("PIN not correctly repeated; try again");
+              xfree (pi2);
+              xfree (pi);
+              goto again;
+            }
+          xfree (pi2);
+        }
+    }
+  else
+    {
+      char *desc;
+      if ( asprintf (&desc,
+                     _("Please enter the PIN%s%s%s to unlock the card"), 
+                     info? " (`":"",
+                     info? info:"",
+                     info? "')":"") < 0)
+        desc = NULL;
+      rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi);
+      free (desc);
+    }
+
   if (!rc)
     {
       strncpy (buf, pi->pin, maxbuf-1);
index 0b5816b..999a5d6 100644 (file)
@@ -276,7 +276,7 @@ unprotect (CTRL ctrl, const char *desc_text,
   arg.unprotected_key = NULL;
   pi->check_cb_arg = &arg;
 
-  rc = agent_askpin (ctrl, desc_text, NULL, pi);
+  rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
   if (!rc)
     {
       assert (arg.unprotected_key);
index 17d85f7..e07518d 100644 (file)
@@ -120,11 +120,11 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
     pi2->check_cb_arg = pi->pin;
 
   next_try:
-    rc = agent_askpin (ctrl, text1, initial_errtext, pi);
+    rc = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
     initial_errtext = NULL;
     if (!rc)
       {
-        rc = agent_askpin (ctrl, text2, NULL, pi2);
+        rc = agent_askpin (ctrl, text2, NULL, NULL, pi2);
         if (rc == -1)
           { /* The re-entered one did not match and the user did not
                hit cancel. */
@@ -228,10 +228,10 @@ agent_protect_and_store (CTRL ctrl, gcry_sexp_t s_skey)
     pi2->check_cb_arg = pi->pin;
 
   next_try:
-    rc = agent_askpin (ctrl, text1, initial_errtext, pi);
+    rc = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
     if (!rc)
       {
-        rc = agent_askpin (ctrl, text2, NULL, pi2);
+        rc = agent_askpin (ctrl, text2, NULL, NULL, pi2);
         if (rc == -1)
           { /* The re-entered one did not match and the user did not
                hit cancel. */
index 622a266..d3b42a4 100644 (file)
@@ -288,8 +288,9 @@ all_digitsp( const char *s)
    number here and repeat it as long as we have invalid formed
    numbers. */
 int
-agent_askpin (CTRL ctrl,
-              const char *desc_text, const char *initial_errtext,
+agent_askpin (ctrl_t ctrl,
+              const char *desc_text, const char *prompt_text,
+              const char *initial_errtext,
               struct pin_entry_info_s *pininfo)
 {
   int rc;
@@ -310,7 +311,10 @@ agent_askpin (CTRL ctrl,
     desc_text = _("Please enter your passphrase, so that the secret key "
                   "can be unlocked for this session");
 
-  is_pin = desc_text && strstr (desc_text, "PIN");
+  if (prompt_text)
+    is_pin = !!strstr (prompt_text, "PIN");
+  else
+    is_pin = desc_text && strstr (desc_text, "PIN");
 
   rc = start_pinentry (ctrl);
   if (rc)
@@ -322,10 +326,10 @@ agent_askpin (CTRL ctrl,
   if (rc)
     return unlock_pinentry (map_assuan_err (rc));
 
-  rc = assuan_transact (entry_ctx,
-                        is_pin? "SETPROMPT PIN:"
-                              : "SETPROMPT Passphrase:",
-                        NULL, NULL, NULL, NULL, NULL, NULL);
+  snprintf (line, DIM(line)-1, "SETPROMPT %s",
+            prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
+  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));
 
index 91e208a..1448386 100644 (file)
@@ -1528,7 +1528,7 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr, int reset_mode,
 
 
 /* Check whether a key already exists.  KEYIDX is the index of the key
-   (0..2).  If FORCE is TRUE a diagnositivc will be printed but no
+   (0..2).  If FORCE is TRUE a diagnositic will be printed but no
    error returned if the key already exists. */
 static gpg_error_t
 does_key_exist (app_t app, int keyidx, int force)
@@ -2134,7 +2134,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
 
       {
         char *prompt;
-#define PROMPTSTRING  _("PIN [sigs done: %lu]")
+#define PROMPTSTRING  _("||Please enter the PIN%%0A[sigs done: %lu]")
 
         prompt = malloc (strlen (PROMPTSTRING) + 50);
         if (!prompt)