* passphrase.c (agent_get_passphrase): New args CUSTOM_PROMPT and
authorWerner Koch <wk@gnupg.org>
Thu, 9 Dec 2004 16:57:30 +0000 (16:57 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 9 Dec 2004 16:57:30 +0000 (16:57 +0000)
CUSTOM_DESCRIPTION.  Changed all callers.

* app-openpgp.c (do_getattr, do_learn_status, do_setattr): Support
the new private DOs.
(do_change_pin): Add a "N" prefix to the strings so that the
callback can act accordingly for a new PIN.  Unfortunately this
breaks existing translations but I see no wother way to overvome
this.

* cardglue.c (learn_status_cb): Ditto.
(agent_release_card_info): Ditto.
(struct pin_cb_info_s): Removed and changed all users.
(pin_cb): Reworked.

* card-util.c (card_status): Print them
(card_edit): New command PRIVATEDO.
(change_private_do): New.

g10/ChangeLog
g10/app-openpgp.c
g10/card-util.c
g10/cardglue.c
g10/cardglue.h
g10/passphrase.c

index e0d19d7..be759ba 100644 (file)
@@ -1,3 +1,24 @@
+2004-12-09  Werner Koch  <wk@g10code.com>
+
+       * passphrase.c (agent_get_passphrase): New args CUSTOM_PROMPT and
+       CUSTOM_DESCRIPTION.     Changed all callers.
+
+       * app-openpgp.c (do_getattr, do_learn_status, do_setattr): Support
+       the new private DOs.
+       (do_change_pin): Add a "N" prefix to the strings so that the
+       callback can act accordingly for a new PIN.  Unfortunately this
+       breaks existing translations but I see no wother way to overvome
+       this.
+
+       * cardglue.c (learn_status_cb): Ditto.
+       (agent_release_card_info): Ditto.
+       (struct pin_cb_info_s): Removed and changed all users.
+       (pin_cb): Reworked.
+
+       * card-util.c (card_status): Print them
+       (card_edit): New command PRIVATEDO.
+       (change_private_do): New.
+
 2004-12-09  David Shaw  <dshaw@jabberwocky.com>
 
        * keygen.c (ask_algo): Add a choose-your-own-capabilities option
index 163974c..24fe616 100644 (file)
@@ -81,6 +81,10 @@ static struct {
   { 0x00C6, 0, 0x6E, 1, 0, 0, 0, "CA Fingerprints" },
   { 0x007A, 1,    0, 1, 0, 0, 0, "Security Support Template" },
   { 0x0093, 0, 0x7A, 1, 1, 0, 0, "Digital Signature Counter" },
+  { 0x0101, 0,    0, 0, 0, 0, 0, "Private DO 1"},
+  { 0x0102, 0,    0, 0, 0, 0, 0, "Private DO 2"},
+  { 0x0103, 0,    0, 0, 0, 0, 0, "Private DO 3"},
+  { 0x0104, 0,    0, 0, 0, 0, 0, "Private DO 4"},
   { 0 }
 };
 
@@ -613,6 +617,10 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
     { "SERIALNO",     0x004F, -1 },
     { "AID",          0x004F },
     { "EXTCAP",       0x0000, -2 },
+    { "PRIVATE-DO-1", 0x0101 },
+    { "PRIVATE-DO-2", 0x0102 },
+    { "PRIVATE-DO-3", 0x0103 },
+    { "PRIVATE-DO-4", 0x0104 },
     { NULL, 0 }
   };
   int idx, i;
@@ -708,6 +716,15 @@ do_learn_status (app_t app, ctrl_t ctrl)
   do_getattr (app, ctrl, "CA-FPR");
   do_getattr (app, ctrl, "CHV-STATUS");
   do_getattr (app, ctrl, "SIG-COUNTER");
+  if (app->app_local->extcap.private_dos)
+    {
+      do_getattr (app, ctrl, "PRIVATE-DO-1");
+      do_getattr (app, ctrl, "PRIVATE-DO-2");
+      if (app->did_chv2)
+        do_getattr (app, ctrl, "PRIVATE-DO-3");
+      if (app->did_chv3)
+        do_getattr (app, ctrl, "PRIVATE-DO-4");
+    }
 
   return 0;
 }
@@ -867,17 +884,22 @@ do_setattr (app_t app, const char *name,
   static struct {
     const char *name;
     int tag;
+    int need_chv;
     int special;
   } table[] = {
-    { "DISP-NAME",    0x005B },
-    { "LOGIN-DATA",   0x005E, 2 },
-    { "DISP-LANG",    0x5F2D },
-    { "DISP-SEX",     0x5F35 },
-    { "PUBKEY-URL",   0x5F50 },
-    { "CHV-STATUS-1", 0x00C4, 1 },
-    { "CA-FPR-1",     0x00CA },
-    { "CA-FPR-2",     0x00CB },
-    { "CA-FPR-3",     0x00CC },
+    { "DISP-NAME",    0x005B, 3 },
+    { "LOGIN-DATA",   0x005E, 3, 2 },
+    { "DISP-LANG",    0x5F2D, 3 },
+    { "DISP-SEX",     0x5F35, 3 },
+    { "PUBKEY-URL",   0x5F50, 3 },
+    { "CHV-STATUS-1", 0x00C4, 3, 1 },
+    { "CA-FPR-1",     0x00CA, 3 },
+    { "CA-FPR-2",     0x00CB, 3 },
+    { "CA-FPR-3",     0x00CC, 3 },
+    { "PRIVATE-DO-1", 0x0101, 2 },
+    { "PRIVATE-DO-2", 0x0102, 3 },
+    { "PRIVATE-DO-3", 0x0103, 2 },
+    { "PRIVATE-DO-4", 0x0104, 3 },
     { NULL, 0 }
   };
 
@@ -887,7 +909,17 @@ do_setattr (app_t app, const char *name,
   if (!table[idx].name)
     return gpg_error (GPG_ERR_INV_NAME); 
 
-  rc = verify_chv3 (app, pincb, pincb_arg);
+  switch (table[idx].need_chv)
+    {
+    case 2:
+      rc = verify_chv2 (app, pincb, pincb_arg);
+      break;
+    case 3:
+      rc = verify_chv3 (app, pincb, pincb_arg);
+      break;
+    default:
+      rc = 0;
+    }
   if (rc)
     return rc;
 
@@ -956,10 +988,10 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr, int reset_mode,
   else
     app->did_chv1 = app->did_chv2 = 0;
 
-  /* Note to translators: Do not translate the "|A|" prefix but
+  /* Note to translators: Do not translate the "|*|" prefixes but
      keep it at the start of the string.  We need this elsewhere
      to get some infos on the string. */
-  rc = pincb (pincb_arg, chvno == 3? _("|A|New Admin PIN") : _("New PIN"), 
+  rc = pincb (pincb_arg, chvno == 3? _("|AN|New Admin PIN") : _("|N|New PIN"), 
               &pinvalue); 
   if (rc)
     {
index 066db0c..031d591 100644 (file)
@@ -377,6 +377,14 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
                    info.disp_sex == 2? _("female") : _("unspecified"));
       print_name (fp, "URL of public key : ", info.pubkey_url);
       print_name (fp, "Login data .......: ", info.login_data);
+      if (info.private_do[0])
+        print_name (fp, "Private DO 1 .....: ", info.private_do[0]);
+      if (info.private_do[1])
+        print_name (fp, "Private DO 2 .....: ", info.private_do[1]);
+      if (info.private_do[2])
+        print_name (fp, "Private DO 3 .....: ", info.private_do[2]);
+      if (info.private_do[3])
+        print_name (fp, "Private DO 4 .....: ", info.private_do[3]);
       if (info.cafpr1valid)
         {
           tty_fprintf (fp, "CA fingerprint %d .:", 1);
@@ -632,6 +640,75 @@ change_login (const char *args)
 }
 
 static int
+change_private_do (const char *args, int nr)
+{
+  char do_name[] = "PRIVATE-DO-X";
+  char *data;
+  int n;
+  int rc; 
+
+  assert (nr >= 1 && nr <= 4);
+  do_name[11] = '0' + nr;
+
+  if (args && (args = strchr (args, '<')))  /* Read it from a file */
+    {
+      FILE *fp;
+
+      /* Fixme: Factor this duplicated code out. */
+      for (args++; spacep (args); args++)
+        ;
+      fp = fopen (args, "rb");
+#if GNUPG_MAJOR_VERSION == 1
+      if (fp && is_secured_file (fileno (fp)))
+        {
+          fclose (fp);
+          fp = NULL;
+          errno = EPERM;
+        }
+#endif
+      if (!fp)
+        {
+          tty_printf (_("can't open `%s': %s\n"), args, strerror (errno));
+          return -1;
+        }
+          
+      data = xmalloc (254);
+      n = fread (data, 1, 254, fp);
+      fclose (fp);
+      if (n < 0)
+        {
+          tty_printf (_("error reading `%s': %s\n"), args, strerror (errno));
+          xfree (data);
+          return -1;
+        }
+    }
+  else
+    {
+      data = cpr_get ("cardedit.change_private_do",
+                      _("Private DO data: "));
+      if (!data)
+        return -1;
+      trim_spaces (data);
+      cpr_kill_prompt ();
+      n = strlen (data);
+    }
+
+  if (n > 254 )
+    {
+      tty_printf (_("Error: Private DO too long "
+                    "(limit is %d characters).\n"), 254);    
+      xfree (data);
+      return -1;
+    }
+
+  rc = agent_scd_setattr (do_name, data, n );
+  if (rc)
+    log_error ("error setting private DO: %s\n", gpg_strerror (rc));
+  xfree (data);
+  return rc;
+}
+
+static int
 change_lang (void)
 {
   char *data, *p;
@@ -1149,7 +1226,7 @@ card_edit (STRLIST commands)
     cmdNOP = 0,
     cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG,
     cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
-    cmdFORCESIG, cmdGENERATE, cmdPASSWD,
+    cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO,
     cmdINVCMD
   };
 
@@ -1180,6 +1257,8 @@ card_edit (STRLIST commands)
     { N_("generate"),
                   cmdGENERATE, 1, N_("generate new keys") },
     { N_("passwd"), cmdPASSWD, 0, N_("menu to change or unblock the PIN") },
+    /* Note, that we do not announce this command yet. */
+    { N_("privatedo"), cmdPRIVATEDO, 0, NULL },
     { NULL, cmdINVCMD, 0, NULL } 
   };
  
@@ -1335,6 +1414,14 @@ card_edit (STRLIST commands)
             change_cafpr (arg_number);
           break;
 
+        case cmdPRIVATEDO:
+          if ( arg_number < 1 || arg_number > 4 )
+            tty_printf ("usage: privatedo N\n"
+                        "       1 <= N <= 4\n");
+          else
+            change_private_do (arg_string, arg_number);
+          break;
+
         case cmdFORCESIG:
           toggle_forcesig ();
           break;
index 1b57b79..4899163 100644 (file)
@@ -49,12 +49,6 @@ struct ctrl_ctx_s {
 };
 
 
-struct pin_cb_info_s 
-{
-  int repeat;
-};
-
-
 static char *default_reader_port;
 static APP current_app;
 
@@ -233,6 +227,8 @@ app_get_serial_and_stamp (APP app, char **serial, time_t *stamp)
 void 
 agent_release_card_info (struct agent_card_info_s *info)
 {
+  int i;
+
   if (!info)
     return;
 
@@ -243,6 +239,11 @@ agent_release_card_info (struct agent_card_info_s *info)
   xfree (info->login_data); info->login_data = NULL;
   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
   info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
+  for (i=0; i < 4; i++)
+    {
+      xfree (info->private_do[i]);
+      info->private_do[i] = NULL;
+    }
 }
 
 
@@ -471,6 +472,7 @@ learn_status_cb (void *opaque, const char *line)
   int keywordlen;
   int i;
 
+/*   log_debug ("got status line `%s'\n", line); */
   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
     ;
   while (spacep (line))
@@ -570,7 +572,15 @@ learn_status_cb (void *opaque, const char *line)
       else if (no == 3)
         parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
     }
-
+  else if (keywordlen == 12 && !memcmp (keyword, "PRIVATE-DO-", 11)
+           && strchr ("1234", keyword[11]))
+    {
+      int no = keyword[11] - '1';
+      assert (no >= 0 && no <= 3);
+      xfree (parm->private_do[no]);
+      parm->private_do[no] = unescape_status_string (line);
+    }
   return 0;
 }
 
@@ -626,21 +636,28 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
 static int 
 pin_cb (void *opaque, const char *info, char **retstr)
 {
-  struct pin_cb_info_s *parm = opaque;
   char *value;
   int canceled;
   int isadmin = 0;
+  int newpin = 0;
   const char *again_text = NULL;
+  const char *ends, *s;
 
   *retstr = NULL;
   log_debug ("asking for PIN '%s'\n", info);
 
   /* We use a special prefix to check whether the Admin PIN has been
      requested. */
-  if (info && !strncmp (info, "|A|", 3))
+  if (info && *info =='|' && (ends=strchr (info+1, '|')))
     {
-      isadmin = 1;
-      info += 3;
+      for (s=info+1; s < ends; s++)
+        {
+          if (*s == 'A')
+            isadmin = 1;
+          else if (*s == 'N')
+            newpin = 1;
+        }
+      info = ends+1;
     }
 
  again:
@@ -649,8 +666,12 @@ pin_cb (void *opaque, const char *info, char **retstr)
                        isadmin? "OPENPGP 3" : "OPENPGP 1");
 
   value = ask_passphrase (info, again_text,
-                          isadmin? "passphrase.adminpin.ask"
-                                 : "passphrase.pin.ask", 
+                          newpin && isadmin? "passphrase.adminpin.new.ask" :
+                          newpin?  "passphrase.pin.new.ask" :
+                          isadmin? "passphrase.adminpin.ask" :
+                                   "passphrase.pin.ask", 
+                          newpin && isadmin? _("Enter New Admin PIN: ") :
+                          newpin?  _("Enter New PIN: ") :
                           isadmin? _("Enter Admin PIN: ")
                                  : _("Enter PIN: "),
                           &canceled);
@@ -660,7 +681,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
   else if (!value)
     return G10ERR_GENERAL;
 
-  if (parm->repeat)
+  if (newpin)
     {
       char *value2;
 
@@ -701,15 +722,12 @@ agent_scd_setattr (const char *name,
                    const unsigned char *value, size_t valuelen)
 {
   APP app;
-  struct pin_cb_info_s parm;
-
-  memset (&parm, 0, sizeof parm);
 
   app = current_app? current_app : open_card ();
   if (!app)
     return gpg_error (GPG_ERR_CARD);
 
-  return app->fnc.setattr (app, name, pin_cb, &parm, value, valuelen);
+  return app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
 }
 
 
@@ -772,9 +790,6 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
   APP app;
   char keynostr[20];
   struct ctrl_ctx_s ctrl;
-  struct pin_cb_info_s parm;
-
-  memset (&parm, 0, sizeof parm);
 
   app = current_app? current_app : open_card ();
   if (!app)
@@ -787,7 +802,7 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
 
   return app->fnc.genkey (app, &ctrl, keynostr,
                            force? 1:0,
-                           pin_cb, &parm);
+                           pin_cb, NULL);
 }
 
 /* Send a PKSIGN command to the SCdaemon. */
@@ -798,9 +813,6 @@ agent_scd_pksign (const char *serialno, int hashalgo,
 {
   APP app;
   int rc;
-  struct pin_cb_info_s parm;
-
-  memset (&parm, 0, sizeof parm);
 
   *r_buf = NULL;
   *r_buflen = 0;
@@ -817,7 +829,7 @@ agent_scd_pksign (const char *serialno, int hashalgo,
     return rc;
 
   return app->fnc.sign (app, serialno, hashalgo,
-                        pin_cb, &parm,
+                        pin_cb, NULL,
                         indata, indatalen,
                         r_buf, r_buflen);
 }
@@ -831,9 +843,6 @@ agent_scd_pkdecrypt (const char *serialno,
 {
   APP app;
   int rc;
-  struct pin_cb_info_s parm;
-
-  memset (&parm, 0, sizeof parm);
 
   *r_buf = NULL;
   *r_buflen = 0;
@@ -850,7 +859,7 @@ agent_scd_pkdecrypt (const char *serialno,
     return rc;
 
   return app->fnc.decipher (app, serialno, 
-                            pin_cb, &parm,
+                            pin_cb, NULL,
                             indata, indatalen,
                             r_buf, r_buflen);
 }
@@ -862,10 +871,6 @@ agent_scd_change_pin (int chvno)
   APP app;
   char chvnostr[20];
   int reset = 0;
-  struct pin_cb_info_s parm;
-
-  memset (&parm, 0, sizeof parm);
-  parm.repeat = 1;
 
   reset = (chvno >= 100);
   chvno %= 100;
@@ -876,7 +881,7 @@ agent_scd_change_pin (int chvno)
 
   sprintf (chvnostr, "%d", chvno);
   return app->fnc.change_pin (app, NULL, chvnostr, reset,
-                              pin_cb, &parm);
+                              pin_cb, NULL);
 }
 
 /* Perform a CHECKPIN operation.  SERIALNO should be the serial
@@ -886,15 +891,12 @@ int
 agent_scd_checkpin (const char *serialnobuf)
 {
   APP app;
-  struct pin_cb_info_s parm;
-
-  memset (&parm, 0, sizeof parm);
 
   app = current_app? current_app : open_card ();
   if (!app)
     return gpg_error (GPG_ERR_CARD);
 
-  return app->fnc.check_pin (app, serialnobuf, pin_cb, &parm);
+  return app->fnc.check_pin (app, serialnobuf, pin_cb, NULL);
 }
 
 
@@ -907,9 +909,6 @@ agent_openpgp_storekey (int keyno,
                         const unsigned char *e, size_t elen)
 {
   APP app;
-  struct pin_cb_info_s parm;
-
-  memset (&parm, 0, sizeof parm);
 
   app = current_app? current_app : open_card ();
   if (!app)
@@ -917,5 +916,5 @@ agent_openpgp_storekey (int keyno,
 
   return app_openpgp_storekey (app, keyno, template, template_len,
                                created_at, m, mlen, e, elen,
-                               pin_cb, &parm);
+                               pin_cb, NULL);
 }
index 812d44e..1160b32 100644 (file)
@@ -37,6 +37,7 @@ struct agent_card_info_s {
   int  disp_sex;     /* 0 = unspecified, 1 = male, 2 = female */
   char *pubkey_url;  /* malloced. */
   char *login_data;  /* malloced. */
+  char *private_do[4]; /* malloced. */
   char cafpr1valid;
   char cafpr2valid;
   char cafpr3valid;
index d63ba67..3b14918 100644 (file)
@@ -630,7 +630,8 @@ agent_close ( int fd )
  */
 static char *
 agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
-                       int *canceled)
+                       const char *custom_description,
+                       const char *custom_prompt, int *canceled)
 {
 #if defined(__riscos__)
   return NULL;
@@ -648,6 +649,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
   int prot;
   char *orig_codeset = NULL;
 
+  log_debug ("agent_get_passphrase tryagin='%s' prompt='%s'\n", tryagain_text, custom_prompt);
   if (canceled)
     *canceled = 0;
 
@@ -663,7 +665,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
     }
   
 #ifdef ENABLE_NLS
-  /* The Assuan agent protol requires us to trasnmit utf-8 strings */
+  /* The Assuan agent protol requires us to transmit utf-8 strings */
   orig_codeset = bind_textdomain_codeset (PACKAGE, NULL);
 #ifdef HAVE_LANGINFO_CODESET
   if (!orig_codeset)
@@ -680,7 +682,9 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
   if ( (fd = agent_open (&prot)) == -1 ) 
     goto failure;
 
-  if ( !mode && pk && keyid )
+  if (custom_description)
+    atext = native_to_utf8 (custom_description);
+  else if ( !mode && pk && keyid )
     { 
       char *uid;
       size_t uidlen;
@@ -818,9 +822,12 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
         tryagain_text = _(tryagain_text);
 
       /* We allocate 2 time the needed space for atext so that there
-         is nenough space for escaping */
+         is enough space for escaping */
       line = m_alloc (15 + 46 
-                      +  3*strlen (tryagain_text) + 3*strlen (atext) + 2);
+                      + 3*strlen (tryagain_text)
+                      + 3*strlen (atext)
+                      + 3*strlen (custom_prompt? custom_prompt:"")
+                      + 2);
       strcpy (line, "GET_PASSPHRASE ");
       p = line+15;
       if (!mode && have_fpr)
@@ -844,7 +851,28 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
             *p++ = *s;
         }
       *p++ = ' ';
-      *p++ = 'X'; /* Use the standard prompt */
+
+      /* The prompt.  */
+      if (custom_prompt)
+        {
+          char *tmp = native_to_utf8 (custom_prompt);
+          for (i=0, s=tmp; *s; s++)
+            {
+              if (*s < ' ' || *s == '+')
+                {
+                  sprintf (p, "%%%02X", *s);
+                  p += 3;
+                }
+              else if (*s == ' ')
+                *p++ = '+';
+              else
+                *p++ = *s;
+            }
+          xfree (tmp);
+        }
+      else
+        *p++ = 'X'; /* Use the standard prompt */
+
       *p++ = ' ';
       /* copy description */
       for (i=0, s= atext; *s; s++)
@@ -1047,7 +1075,7 @@ ask_passphrase (const char *description,
   if ( opt.use_agent ) 
     {
       pw = agent_get_passphrase (NULL, 0,
-                                 tryagain_text? tryagain_text :description,
+                                 tryagain_text, description, prompt,
                                  canceled );
       if (!pw)
         {
@@ -1188,9 +1216,9 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
        next_pw = NULL;
     }
     else if ( opt.use_agent ) {
-      /* Divert to teh gpg-agent. */
+      /* Divert to the gpg-agent. */
        pw = agent_get_passphrase ( keyid, mode == 2? 1: 0,
-                                    tryagain_text, canceled );
+                                    tryagain_text, NULL, NULL, canceled );
         if (!pw)
           {
             if (!opt.use_agent)
@@ -1198,7 +1226,8 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
             pw = m_strdup ("");
           }
         if( *pw && mode == 2 ) {
-           char *pw2 = agent_get_passphrase ( keyid, 2, NULL, canceled );
+          char *pw2 = agent_get_passphrase ( keyid, 2, NULL, NULL,
+                                               NULL, canceled );
             if (!pw2)
               {
                 if (!opt.use_agent)