Updated from latest NewPG project
authorWerner Koch <wk@gnupg.org>
Thu, 9 Jan 2003 12:59:25 +0000 (12:59 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 9 Jan 2003 12:59:25 +0000 (12:59 +0000)
28 files changed:
agent/ChangeLog
agent/agent.h
agent/cache.c
agent/command.c
agent/divert-scd.c
agent/findkey.c
agent/genkey.c
agent/gpg-agent.c
agent/pkdecrypt.c
agent/pksign.c
agent/protect-tool.c
agent/query.c
agent/simple-pwquery.c
agent/trustlist.c
common/ChangeLog
common/isascii.c [new file with mode: 0644]
common/putc_unlocked.c [new file with mode: 0644]
common/signal.c
kbx/ChangeLog
kbx/Makefile.am
kbx/keybox-search.c
sm/ChangeLog
sm/call-agent.c
sm/call-dirmngr.c
sm/certcheck.c
sm/gpgsm.c
sm/gpgsm.h
sm/verify.c

index c19193b..dc1bedf 100644 (file)
@@ -1,3 +1,76 @@
+2002-12-04  Werner Koch  <wk@gnupg.org>
+
+       * gpg-agent.c: New variable config_filename.
+       (parse_rereadable_options): New.
+       (main): Use it here.  Add setting of default values, set
+       config_filename.
+       (reread_configuration): Filled with actual code.
+
+2002-12-03  Werner Koch  <wk@gnupg.org>
+
+       * protect-tool.c (read_key): Don't run make_canonical on a NULL buffer.
+
+       * command.c (parse_hexstring): New.
+       (cmd_sethash): Use it.
+       (parse_keygrip): New.
+       (cmd_havekey, cmd_sigkey): Use it.
+       (cmd_passwd): New.
+       * genkey.c (agent_protect_and_store): New.
+       (store_key): Add arg FORCE.
+       (agent_genkey): Pass false to this force of store_key.
+
+2002-11-13  Werner Koch  <wk@gnupg.org>
+
+       * gpg-agent.c (main): Switch all messages to utf-8.
+
+       * simple-pwquery.c (agent_send_all_options): Use $GPG_TTY and
+       stdin with ttyname.
+
+       * cache.c (new_data): Uiih - /sizeof d/sizeof *d/.
+
+2002-11-10  Werner Koch  <wk@gnupg.org>
+
+       * command.c (option_handler): Fix keep_tty check.
+
+2002-11-06  Werner Koch  <wk@gnupg.org>
+
+       * gpg-agent.c (main): Make sure we have a default ttyname.
+       * command.c (option_handler): Check opt.keep_tty here
+       * query.c (start_pinentry): but not anymore here.
+
+2002-11-05  Werner Koch  <wk@gnupg.org>
+
+       * agent.h (opt,server_control_s): Move display and lc_ variables
+       to the control struct so that they are per connection.
+       * gpg-agent.c (agent_init_default_ctrl): New.
+       (main): Assign those command line options to new default_* variables.
+       Reset DISPLAY in server mode so that tehre is no implicit default.
+       * command.c (start_command_handler): Initialize and deinitialize
+       the control values.
+       (option_handler): Work on the ctrl values and not on the opt.
+       * query.c (start_pinentry): New argument CTRL to set the display
+       connection specific.  Changed all callers to pass this value.
+       (agent_askpin,agent_get_passphrase,agent_get_confirmation): Add
+       CTRL arg and pass it ot start_pinentry.
+       * command.c (cmd_get_passphrase): Pass CTRL argument.
+       * trustlist.c (agent_marktrusted):  Add CTRL argument  
+       * command.c (cmd_marktrusted): Pass CTRL argument
+       * divert-scd.c (ask_for_card):  Add CTRL arg. 
+       (divert_pksign,divert_pkdecrypt): Ditto.  Changed caller.
+       (getpin_cb): Use OPAQUE to pass the CTRL variable.  Changed both 
+       users.
+       * findkey.c (unprotect): Add CTRL arg.
+       (agent_key_from_file): Ditto.
+
+       * query.c (unlock_pinentry): Disconnect the pinentry so that we
+       start a new one for each request.  This is required to support
+       clients with different environments (e.g. X magic cookies).
+
+2002-09-05  Neal H. Walfield  <neal@cs.uml.edu>
+
+       * gpg-agent.c (main) [USE_GNU_PTH]: No need to call
+       assuan_set_io_func as assuan is smart.
+
 2002-09-25  Werner Koch  <wk@gnupg.org>
 
        * gpg-agent.c (handle_signal): Flush cache on SIGHUP.
index 24267b0..bd7b36a 100644 (file)
@@ -1,5 +1,5 @@
 /* agent.h - Global definitions for the agent
- *     Copyright (C) 2001 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2002 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -36,11 +36,6 @@ struct {
   int batch;        /* batch mode */
   const char *homedir; /* configuration directory name */
   const char *pinentry_program; 
-  char *display;
-  char *ttyname;
-  char *ttytype;
-  char *lc_ctype;
-  char *lc_messages;
   const char *scdaemon_program; 
   int no_grab;      /* don't let the pinentry grab the keyboard */
   unsigned long def_cache_ttl;
@@ -73,6 +68,11 @@ struct server_local_s;
 
 struct server_control_s {
   struct server_local_s *server_local;
+  char *display;
+  char *ttyname;
+  char *ttytype;
+  char *lc_ctype;
+  char *lc_messages;
   struct {
     int algo;
     unsigned char value[MAX_DIGEST_LEN];
@@ -107,6 +107,7 @@ enum {
 
 /*-- gpg-agent.c --*/
 void agent_exit (int rc); /* also implemented in other tools */
+void agent_init_default_ctrl (struct server_control_s *ctrl);
 
 /*-- command.c --*/
 void start_command_handler (int, int);
@@ -114,16 +115,17 @@ void start_command_handler (int, int);
 /*-- findkey.c --*/
 int agent_write_private_key (const unsigned char *grip,
                              const void *buffer, size_t length, int force);
-GCRY_SEXP agent_key_from_file (const unsigned char *grip,
+GCRY_SEXP agent_key_from_file (CTRL ctrl, const unsigned char *grip,
                                unsigned char **shadow_info, int ignore_cache);
 int agent_key_available (const unsigned char *grip);
 
 /*-- query.c --*/
-int agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo);
-int agent_get_passphrase (char **retpass,
+int agent_askpin (CTRL ctrl,
+                  const char *desc_text, struct pin_entry_info_s *pininfo);
+int agent_get_passphrase (CTRL ctrl, char **retpass,
                           const char *desc, const char *prompt,
                           const char *errtext);
-int agent_get_confirmation (const char *desc, const char *ok,
+int agent_get_confirmation (CTRL ctrl, const char *desc, const char *ok,
                            const char *cancel);
 
 /*-- cache.c --*/
@@ -143,6 +145,7 @@ int agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
 /*-- genkey.c --*/
 int agent_genkey (CTRL ctrl,
                   const char *keyparam, size_t keyparmlen, FILE *outfp);
+int agent_protect_and_store (CTRL ctrl, GCRY_SEXP s_skey);
 
 /*-- protect.c --*/
 int agent_protect (const unsigned char *plainkey, const char *passphrase,
@@ -160,13 +163,15 @@ int agent_get_shadow_info (const unsigned char *shadowkey,
 /*-- trustlist.c --*/
 int agent_istrusted (const char *fpr);
 int agent_listtrusted (void *assuan_context);
-int agent_marktrusted (const char *name, const char *fpr, int flag);
+int agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag);
 
 
 /*-- divert-scd.c --*/
-int divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
+int divert_pksign (CTRL ctrl, 
+                   const unsigned char *digest, size_t digestlen, int algo,
                    const unsigned char *shadow_info, unsigned char **r_sig);
-int divert_pkdecrypt (const unsigned char *cipher,
+int divert_pkdecrypt (CTRL ctrl,
+                      const unsigned char *cipher,
                       const unsigned char *shadow_info,
                       char **r_buf, size_t *r_len);
 
index 8f5bf9d..b6ab550 100644 (file)
@@ -67,7 +67,7 @@ new_data (const void *data, size_t length)
      secure storage provider*/
   total = length + 32 - (length % 32);
 
-  d = gcry_malloc_secure (sizeof d + total - 1);
+  d = gcry_malloc_secure (sizeof *d + total - 1);
   if (d)
     {
       d->totallen = total;
index 55ee8b8..3573c27 100644 (file)
@@ -77,6 +77,48 @@ has_option (const char *line, const char *name)
   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
 }
 
+/* Parse a hex string.  Return an Assuan error code or 0 on success and the
+   length of the parsed string in LEN. */
+static int
+parse_hexstring (ASSUAN_CONTEXT ctx, const char *string, size_t *len)
+{
+  const char *p;
+  size_t n;
+
+  /* parse the hash value */
+  for (p=string, n=0; hexdigitp (p); p++, n++)
+    ;
+  if (*p)
+    return set_error (Parameter_Error, "invalid hexstring");
+  if ((n&1))
+    return set_error (Parameter_Error, "odd number of digits");
+  *len = n;
+  return 0;
+}
+
+/* Parse the keygrip in STRING into the provided buffer BUF.  BUF must
+   provide space for 20 bytes. BUF is not changed if the fucntions
+   returns an error. */
+static int
+parse_keygrip (ASSUAN_CONTEXT ctx, const char *string, unsigned char *buf)
+{
+  int rc;
+  size_t n;
+  const unsigned char *p;
+
+  rc = parse_hexstring (ctx, string, &n);
+  if (rc)
+    return rc;
+  n /= 2;
+  if (n != 20)
+    return set_error (Parameter_Error, "invalid length of keygrip");
+
+  for (p=string, n=0; n < 20; p += 2, n++)
+    buf[n] = xtoi_2 (p);
+
+  return 0;
+}
+
 
 
 
@@ -136,6 +178,7 @@ cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
 static int
 cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
 {
+  CTRL ctrl = assuan_get_pointer (ctx);
   int rc, n, i;
   char *p;
   char fpr[41];
@@ -164,7 +207,7 @@ cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
   while (spacep (p))
     p++;
 
-  rc = agent_marktrusted (p, fpr, flag);
+  rc = agent_marktrusted (ctrl, p, fpr, flag);
   if (rc)
     log_error ("command marktrusted failed: %s\n", gnupg_strerror (rc));
   return map_to_assuan_status (rc);
@@ -179,23 +222,12 @@ cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
 static int
 cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
 {
-  int n;
-  char *p;
+  int rc;
   unsigned char buf[20];
 
-  /* parse the hash value */
-  for (p=line,n=0; hexdigitp (p); p++, n++)
-    ;
-  if (*p)
-    return set_error (Parameter_Error, "invalid hexstring");
-  if ((n&1))
-    return set_error (Parameter_Error, "odd number of digits");
-  n /= 2;
-  if (n != 20)
-    return set_error (Parameter_Error, "invalid length of keygrip");
-
-  for (p=line, n=0; n < 20; p += 2, n++)
-    buf[n] = xtoi_2 (p);
+  rc = parse_keygrip (ctx, line, buf);
+  if (rc)
+    return rc;
 
   if (agent_key_available (buf))
     return ASSUAN_No_Secret_Key;
@@ -211,29 +243,17 @@ cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
 static int
 cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
 {
-  int n;
-  char *p;
+  int rc;
   CTRL ctrl = assuan_get_pointer (ctx);
-  unsigned char *buf;
-
-  /* parse the hash value */
-  for (p=line,n=0; hexdigitp (p); p++, n++)
-    ;
-  if (*p)
-    return set_error (Parameter_Error, "invalid hexstring");
-  if ((n&1))
-    return set_error (Parameter_Error, "odd number of digits");
-  n /= 2;
-  if (n != 20)
-    return set_error (Parameter_Error, "invalid length of keygrip");
 
-  buf = ctrl->keygrip;
-  for (p=line, n=0; n < 20; p += 2, n++)
-    buf[n] = xtoi_2 (p);
+  rc = parse_keygrip (ctx, line, ctrl->keygrip);
+  if (rc)
+    return rc;
   ctrl->have_keygrip = 1;
   return 0;
 }
 
+
 /* SETHASH <algonumber> <hexstring> 
 
   The client can use this command to tell the server about the data
@@ -241,7 +261,8 @@ cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
 static int
 cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
 {
-  int n;
+  int rc;
+  size_t n;
   char *p;
   CTRL ctrl = assuan_get_pointer (ctx);
   unsigned char *buf;
@@ -257,12 +278,9 @@ cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
   ctrl->digest.algo = algo;
 
   /* parse the hash value */
-  for (p=line,n=0; hexdigitp (p); p++, n++)
-    ;
-  if (*p)
-    return set_error (Parameter_Error, "invalid hexstring");
-  if ((n&1))
-    return set_error (Parameter_Error, "odd number of digits");
+  rc = parse_hexstring (ctx, line, &n);
+  if (rc)
+    return rc;
   n /= 2;
   if (n != 16 && n != 20 && n != 24 && n != 32)
     return set_error (Parameter_Error, "unsupported length of hash");
@@ -386,6 +404,7 @@ plus_to_blank (char *s)
 static int
 cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
 {
+  CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
   const char *pw;
   char *response;
@@ -459,7 +478,7 @@ cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
       if (desc)
         plus_to_blank (desc);
 
-      rc = agent_get_passphrase (&response, desc, prompt, errtext);
+      rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
       if (!rc)
         {
           if (cacheid)
@@ -520,52 +539,92 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
 
 
 \f
+/* PASSWD <hexstring_with_keygrip>
+  
+   Change the passphrase/PID for the key identified by keygrip in LINE. */
+static int
+cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
+{
+  CTRL ctrl = assuan_get_pointer (ctx);
+  int rc;
+  unsigned char grip[20];
+  GCRY_SEXP s_skey = NULL;
+  unsigned char *shadow_info = NULL;
+
+  rc = parse_keygrip (ctx, line, grip);
+  if (rc)
+    return rc; /* we can't jump to leave because this is already an
+                  Assuan error code. */
+
+  s_skey = agent_key_from_file (ctrl, grip, &shadow_info, 1);
+  if (!s_skey && !shadow_info)
+    rc = seterr (No_Secret_Key);
+  else if (!s_skey)
+    {
+      log_error ("changing a smartcard PIN is not yet supported\n");
+      rc = seterr (Not_Implemented);
+    }
+  else
+    rc = agent_protect_and_store (ctrl, s_skey);
+
+  gcry_sexp_release (s_skey);
+  xfree (shadow_info);
+  if (rc)
+    log_error ("command passwd failed: %s\n", gnupg_strerror (rc));
+  return map_to_assuan_status (rc);
+}
+
+
+\f
 static int
 option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
 {
    CTRL ctrl = assuan_get_pointer (ctx);
 
-  /* FIXME: We should not change opt. here.  It is not a problem right
-     now but as soon as we are allowing concurrent connections we mess
-     things up */
   if (!strcmp (key, "display"))
     {
-      if (opt.display)
-        free (opt.display);
-      opt.display = strdup (value);
-      if (!opt.display)
+      if (ctrl->display)
+        free (ctrl->display);
+      ctrl->display = strdup (value);
+      if (!ctrl->display)
         return ASSUAN_Out_Of_Core;
     }
   else if (!strcmp (key, "ttyname"))
     {
-      if (opt.ttyname)
-        free (opt.ttyname);
-      opt.ttyname = strdup (value);
-      if (!opt.ttyname)
-        return ASSUAN_Out_Of_Core;
+      if (!opt.keep_tty)
+        {
+          if (ctrl->ttyname)
+            free (ctrl->ttyname);
+          ctrl->ttyname = strdup (value);
+          if (!ctrl->ttyname)
+            return ASSUAN_Out_Of_Core;
+        }
     }
   else if (!strcmp (key, "ttytype"))
     {
-      if (opt.ttytype)
-        free (opt.ttytype);
-      opt.ttytype = strdup (value);
-      if (!opt.ttytype)
-        return ASSUAN_Out_Of_Core;
+      if (!opt.keep_tty)
+        {
+          if (ctrl->ttytype)
+            free (ctrl->ttytype);
+          ctrl->ttytype = strdup (value);
+          if (!ctrl->ttytype)
+            return ASSUAN_Out_Of_Core;
+        }
     }
   else if (!strcmp (key, "lc-ctype"))
     {
-      if (opt.lc_ctype)
-        free (opt.lc_ctype);
-      opt.lc_ctype = strdup (value);
-      if (!opt.lc_ctype)
+      if (ctrl->lc_ctype)
+        free (ctrl->lc_ctype);
+      ctrl->lc_ctype = strdup (value);
+      if (!ctrl->lc_ctype)
         return ASSUAN_Out_Of_Core;
     }
   else if (!strcmp (key, "lc-messages"))
     {
-      if (opt.lc_messages)
-        free (opt.lc_messages);
-      opt.lc_messages = strdup (value);
-      if (!opt.lc_messages)
+      if (ctrl->lc_messages)
+        free (ctrl->lc_messages);
+      ctrl->lc_messages = strdup (value);
+      if (!ctrl->lc_messages)
         return ASSUAN_Out_Of_Core;
     }
   else if (!strcmp (key, "use-cache-for-signing"))
@@ -599,6 +658,7 @@ register_commands (ASSUAN_CONTEXT ctx)
     { "LISTTRUSTED",  0,  cmd_listtrusted },
     { "MARKTRUSTED",  0,  cmd_marktrusted },
     { "LEARN",        0,  cmd_learn },
+    { "PASSWD",       0,  cmd_passwd },
     { "",     ASSUAN_CMD_INPUT, NULL }, 
     { "",     ASSUAN_CMD_OUTPUT, NULL }, 
     { NULL }
@@ -630,6 +690,7 @@ start_command_handler (int listen_fd, int fd)
   struct server_control_s ctrl;
 
   memset (&ctrl, 0, sizeof ctrl);
+  agent_init_default_ctrl (&ctrl);
   
   if (listen_fd == -1 && fd == -1)
     {
@@ -693,5 +754,15 @@ start_command_handler (int listen_fd, int fd)
 
 
   assuan_deinit_server (ctx);
+  if (ctrl.display)
+    free (ctrl.display);
+  if (ctrl.ttyname)
+    free (ctrl.ttyname);
+  if (ctrl.ttytype)
+    free (ctrl.ttytype);
+  if (ctrl.lc_ctype)
+    free (ctrl.lc_ctype);
+  if (ctrl.lc_messages)
+    free (ctrl.lc_messages);
 }
 
index 40b6bcf..38f8173 100644 (file)
@@ -34,7 +34,7 @@
 
 
 static int
-ask_for_card (const unsigned char *shadow_info, char **r_kid)
+ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid)
 {
   int rc, i;
   const unsigned char *s;
@@ -119,7 +119,7 @@ ask_for_card (const unsigned char *shadow_info, char **r_kid)
             }
           else
             {
-              rc = agent_get_confirmation (desc, NULL, NULL);
+              rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
               free (desc);
             }
         }
@@ -174,8 +174,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
   struct pin_entry_info_s *pi;
   int rc;
   char *desc;
-
-  assert (!opaque);
+  CTRL ctrl = opaque;
 
   if (maxbuf < 2)
     return GNUPG_Invalid_Value;
@@ -195,7 +194,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
                  info? info:"",
                  info? "')":"") < 0)
     desc = NULL;
-  rc = agent_askpin (desc?desc:info, pi);
+  rc = agent_askpin (ctrl, desc?desc:info, pi);
   free (desc);
   if (!rc)
     {
@@ -210,7 +209,8 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
 
 
 int
-divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
+divert_pksign (CTRL ctrl, 
+               const unsigned char *digest, size_t digestlen, int algo,
                const unsigned char *shadow_info, unsigned char **r_sig)
 {
   int rc;
@@ -220,7 +220,7 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
   unsigned char *data;
   size_t ndata;
 
-  rc = ask_for_card (shadow_info, &kid);
+  rc = ask_for_card (ctrl, shadow_info, &kid);
   if (rc)
     return rc;
 
@@ -229,7 +229,7 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
   if (rc)
     return rc;
 
-  rc = agent_card_pksign (kid, getpin_cb, NULL,
+  rc = agent_card_pksign (kid, getpin_cb, ctrl,
                           data, ndata, &sigval, &siglen);
   if (!rc)
     *r_sig = sigval;
@@ -244,7 +244,8 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
    key identified by SHADOW_INFO and return the plaintext in an
    allocated buffer in R_BUF.  */
 int  
-divert_pkdecrypt (const unsigned char *cipher,
+divert_pkdecrypt (CTRL ctrl,
+                  const unsigned char *cipher,
                   const unsigned char *shadow_info,
                   char **r_buf, size_t *r_len)
 {
@@ -288,11 +289,11 @@ divert_pkdecrypt (const unsigned char *cipher,
   ciphertext = s;
   ciphertextlen = n;
 
-  rc = ask_for_card (shadow_info, &kid);
+  rc = ask_for_card (ctrl, shadow_info, &kid);
   if (rc)
     return rc;
 
-  rc = agent_card_pkdecrypt (kid, getpin_cb, NULL,
+  rc = agent_card_pkdecrypt (kid, getpin_cb, ctrl,
                              ciphertext, ciphertextlen,
                              &plaintext, &plaintextlen);
   if (!rc)
index 8ec230f..96a1f36 100644 (file)
@@ -131,9 +131,10 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
 
 /* Unprotect the canconical encoded S-expression key in KEYBUF.  GRIP
    should be the hex encoded keygrip of that key to be used with the
-   cahing mechanism. */
+   caching mechanism. */
 static int
-unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
+unprotect (CTRL ctrl,
+           unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
 {
   struct pin_entry_info_s *pi;
   struct try_unprotect_arg_s arg;
@@ -176,7 +177,7 @@ unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
   arg.unprotected_key = NULL;
   pi->check_cb_arg = &arg;
 
-  rc = agent_askpin (NULL, pi);
+  rc = agent_askpin (ctrl, NULL, pi);
   if (!rc)
     {
       assert (arg.unprotected_key);
@@ -197,7 +198,8 @@ unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
    With IGNORE_CACHE passed as true the passphrase is not taken from
    the cache.*/
 GCRY_SEXP
-agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info,
+agent_key_from_file (CTRL ctrl,
+                     const unsigned char *grip, unsigned char **shadow_info,
                      int ignore_cache)
 {
   int i, rc;
@@ -271,7 +273,7 @@ agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info,
     case PRIVATE_KEY_CLEAR:
       break; /* no unprotection needed */
     case PRIVATE_KEY_PROTECTED:
-      rc = unprotect (&buf, grip, ignore_cache);
+      rc = unprotect (ctrl, &buf, grip, ignore_cache);
       if (rc)
         log_error ("failed to unprotect the secret key: %s\n",
                    gnupg_strerror (rc));
index dccac94..6def5cd 100644 (file)
@@ -30,7 +30,7 @@
 #include "i18n.h"
 
 static int
-store_key (GCRY_SEXP private, const char *passphrase)
+store_key (GCRY_SEXP private, const char *passphrase, int force)
 {
   int rc;
   char *buf;
@@ -65,13 +65,13 @@ store_key (GCRY_SEXP private, const char *passphrase)
       buf = p;
     }
 
-  rc = agent_write_private_key (grip, buf, len, 0);
+  rc = agent_write_private_key (grip, buf, len, force);
   xfree (buf);
   return rc;
 }
 
 /* Callback function to compare the first entered PIN with the one
-   currently beeing entered. */
+   currently being entered. */
 static int
 reenter_compare_cb (struct pin_entry_info_s *pi)
 {
@@ -119,9 +119,9 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
     pi2->check_cb = reenter_compare_cb;
     pi2->check_cb_arg = pi->pin;
 
-    rc = agent_askpin (text1, pi);
+    rc = agent_askpin (ctrl, text1, pi);
     if (!rc)
-      rc = agent_askpin (text2, pi2);
+      rc = agent_askpin (ctrl, text2, pi2);
     if (rc)
       return rc;
     if (!*pi->pin)
@@ -162,7 +162,7 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
   
   /* store the secret key */
   log_debug ("storing private key\n");
-  rc = store_key (s_private, pi? pi->pin:NULL);
+  rc = store_key (s_private, pi? pi->pin:NULL, 0);
   xfree (pi); pi = NULL;
   gcry_sexp_release (s_private);
   if (rc)
@@ -198,3 +198,41 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
   return 0;
 }
 
+
+\f
+/* Apply a new passpahrse to the key S_SKEY and store it. */
+int
+agent_protect_and_store (CTRL ctrl, GCRY_SEXP s_skey) 
+{
+  struct pin_entry_info_s *pi, *pi2;
+  int rc;
+
+  {
+    const char *text1 = _("Please enter the new passphrase");
+    const char *text2 = _("Please re-enter this passphrase");
+
+    pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
+    pi2 = pi + (sizeof *pi + 100);
+    pi->max_length = 100;
+    pi->max_tries = 3;
+    pi2->max_length = 100;
+    pi2->max_tries = 3;
+    pi2->check_cb = reenter_compare_cb;
+    pi2->check_cb_arg = pi->pin;
+
+    rc = agent_askpin (ctrl, text1, pi);
+    if (!rc)
+      rc = agent_askpin (ctrl, text2, pi2);
+    if (rc)
+      return rc;
+    if (!*pi->pin)
+      {
+        xfree (pi);
+        pi = NULL; /* User does not want a passphrase. */
+      }
+  }
+
+  rc = store_key (s_skey, pi? pi->pin:NULL, 1);
+  xfree (pi);
+  return 0;
+}
index 3c823e5..780dfad 100644 (file)
@@ -137,6 +137,18 @@ static int maybe_setuid = 1;
 /* Name of the communication socket */
 static char socket_name[128];
 
+/* Default values for options passed to the pinentry. */
+static char *default_display;
+static char *default_ttyname;
+static char *default_ttytype;
+static char *default_lc_ctype;
+static char *default_lc_messages;
+
+/* Name of a config file, which will be reread on a HUP if it is not NULL. */
+static char *config_filename;
+
+
+/* Local prototypes. */
 static void create_directories (void);
 #ifdef USE_GNU_PTH
 static void handle_connections (int listen_fd);
@@ -248,6 +260,51 @@ cleanup_sh (int sig)
   raise( sig );
 }
 
+
+/* Handle options which are allowed to be reset after program start.
+   Return true when the current option in PARGS could be handled and
+   false if not.  As a special feature, passing a value of NULL for
+   PARGS, resets the options to the default. */
+static int
+parse_rereadable_options (ARGPARSE_ARGS *pargs)
+{
+  if (!pargs)
+    { /* reset mode */
+      opt.quiet = 0;
+      opt.verbose = 0;
+      opt.debug = 0;
+      opt.no_grab = 0;
+      opt.pinentry_program = NULL;
+      opt.scdaemon_program = NULL;
+      opt.def_cache_ttl = 10*60; /* default to 10 minutes */
+      opt.ignore_cache_for_signing = 0;
+      return 1;
+    }
+
+  switch (pargs->r_opt)
+    {
+    case oQuiet: opt.quiet = 1; break;
+    case oVerbose: opt.verbose++; break;
+
+    case oDebug: opt.debug |= pargs->r.ret_ulong; break;
+    case oDebugAll: opt.debug = ~0; break;
+
+    case oNoGrab: opt.no_grab = 1; break;
+      
+    case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
+    case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
+
+    case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break;
+      
+    case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
+
+    default:
+      return 0; /* not handled */
+    }
+  return 1; /* handled */
+}
+
+
 int
 main (int argc, char **argv )
 {
@@ -288,15 +345,14 @@ main (int argc, char **argv )
     }
 
   assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
-#ifdef USE_GNU_PTH
-  assuan_set_io_func (pth_read, pth_write);
-#endif
 
   gcry_set_log_handler (my_gcry_logger, NULL);
   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
 
   may_coredump = disable_core_dumps ();
 
+  parse_rereadable_options (NULL); /* Reset them to default values. */
+
   shell = getenv ("SHELL");
   if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
     csh_style = 1;
@@ -304,7 +360,6 @@ main (int argc, char **argv )
   opt.homedir = getenv("GNUPGHOME");
   if (!opt.homedir || !*opt.homedir)
     opt.homedir = GNUPG_DEFAULT_HOMEDIR;
-  opt.def_cache_ttl = 10*60; /* default to 10 minutes */
 
 
   /* check whether we have a config file on the commandline */
@@ -375,14 +430,12 @@ main (int argc, char **argv )
 
   while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) )
     {
+      if (parse_rereadable_options (&pargs))
+        continue; /* Already handled */
       switch (pargs.r_opt)
         {
-        case oQuiet: opt.quiet = 1; break;
-        case oVerbose: opt.verbose++; break;
         case oBatch: opt.batch=1; break;
 
-        case oDebug: opt.debug |= pargs.r.ret_ulong; break;
-        case oDebugAll: opt.debug = ~0; break;
         case oDebugWait: debug_wait = pargs.r.ret_int; break;
 
         case oOptions:
@@ -399,7 +452,6 @@ main (int argc, char **argv )
         case oNoOptions: break; /* no-options */
         case oHomedir: opt.homedir = pargs.r.ret_str; break;
         case oNoDetach: nodetach = 1; break;
-        case oNoGrab: opt.no_grab = 1; break;
         case oLogFile: logfile = pargs.r.ret_str; break;
         case oCsh: csh_style = 1; break;
         case oSh: csh_style = 0; break;
@@ -407,16 +459,12 @@ main (int argc, char **argv )
         case oDaemon: is_daemon = 1; break;
         case oDisablePth: disable_pth = 1; break;
 
-        case oPinentryProgram: opt.pinentry_program = pargs.r.ret_str; break;
-        case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
-        case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
-        case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
-        case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
-        case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
-        case oScdaemonProgram: opt.scdaemon_program = pargs.r.ret_str; break;
-        case oDefCacheTTL: opt.def_cache_ttl = pargs.r.ret_ulong; break;
+        case oDisplay: default_display = xstrdup (pargs.r.ret_str); break;
+        case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break;
+        case oTTYtype: default_ttytype = xstrdup (pargs.r.ret_str); break;
+        case oLCctype: default_lc_ctype = xstrdup (pargs.r.ret_str); break;
+        case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str); break;
 
-        case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
         case oKeepTTY: opt.keep_tty = 1; break;
         case oKeepDISPLAY: opt.keep_display = 1; break;
 
@@ -427,7 +475,8 @@ main (int argc, char **argv )
     {
       fclose( configfp );
       configfp = NULL;
-      xfree(configname);
+      /* Keep a copy of the name so that it can be read on SIGHUP. */
+      config_filename = configname;
       configname = NULL;
       goto next_pass;
     }
@@ -465,7 +514,22 @@ main (int argc, char **argv )
       sleep (debug_wait);
       log_debug ("... okay\n");
     }
+
+  if (!pipe_server && !is_daemon)
+    log_info (_("please use the option `--daemon'"
+                " to run the program in the background\n"));
   
+#ifdef ENABLE_NLS
+  /* gpg-agent usdually does not ooutput any messages becuase it runs
+     in the background.  For log files it is acceptable to have
+     messages always encoded in utf-8.  We switch here to utf-8, so
+     that commands like --help still give native messages.  It is far
+     easier to swicthnonly once instead of for every message and it
+     actually helps when more then one thread is active (avoids
+     required an extra copy step). */
+    bind_textdomain_codeset (PACKAGE, "UTF-8");
+#endif
+
   /* now start with logging to a file if this is desired */
   if (logfile)
     {
@@ -473,16 +537,18 @@ main (int argc, char **argv )
       log_set_prefix (NULL, 1|2|4);
     }
 
+  /* Make sure that we have a default ttyname. */
+  if (!default_ttyname && ttyname (1))
+    default_ttyname = xstrdup (ttyname (1));
+  if (!default_ttytype && getenv ("TERM"))
+    default_ttytype = xstrdup (getenv ("TERM"));
 
   if (pipe_server)
     { /* this is the simple pipe based server */
       start_command_handler (-1, -1);
     }
   else if (!is_daemon)
-    {
-      log_info (_("please use the option `--daemon'"
-                  " to run the program in the background\n"));
-    }
+    ;
   else
     { /* regular server mode */
       int fd;
@@ -491,6 +557,13 @@ main (int argc, char **argv )
       struct sockaddr_un serv_addr;
       char *p;
 
+      /* Remove the DISPLAY variable so that a pinentry does not
+         default to a specific display.  There is still a default
+         display when gpg-agent weas started using --display or a
+         client requested this using an OPTION command. */
+      if (!opt.keep_display)
+        unsetenv ("DISPLAY");
+
       *socket_name = 0;
       snprintf (socket_name, DIM(socket_name)-1,
                 "/tmp/gpg-XXXXXX/S.gpg-agent");
@@ -702,10 +775,76 @@ agent_exit (int rc)
 }
 
 
+void
+agent_init_default_ctrl (struct server_control_s *ctrl)
+{
+  /* Note we ignore malloc errors because we can't do much about it
+     and the request will fail anyway shortly after this
+     initialization. */
+  if (ctrl->display)
+    free (ctrl->display);
+  ctrl->display = default_display? strdup (default_display) : NULL;
+
+  if (ctrl->ttyname)
+    free (ctrl->ttyname);
+  ctrl->ttyname = default_ttyname? strdup (default_ttyname) : NULL;
+
+  if (ctrl->ttytype)
+    free (ctrl->ttytype);
+  ctrl->ttytype = default_ttytype? strdup (default_ttytype) : NULL;
+
+  if (ctrl->lc_ctype)
+    free (ctrl->lc_ctype);
+  ctrl->lc_ctype = default_lc_ctype? strdup (default_lc_ctype) : NULL;
+
+  if (ctrl->lc_messages)
+    free (ctrl->lc_messages);
+  ctrl->lc_messages = default_lc_messages? strdup (default_lc_messages) : NULL;
+}
+
+
+/* Reread parts of the configuration.  Note, that this function is
+   obviously not thread-safe and should only be called from the PTH
+   signal handler. 
+
+   Fixme: Due to the way the argument parsing works, we create a
+   memory leak here for all string type arguments.  There is currently
+   no clean way to tell whether the memory for the argument has been
+   allocated or points into the process' original arguments.  Unless
+   we have a mechanism to tell this, we need to live on with this. */
 static void
 reread_configuration (void)
 {
-  /* FIXME: Move parts of the option parsing to here. */
+  ARGPARSE_ARGS pargs;
+  FILE *fp;
+  unsigned int configlineno = 0;
+  int dummy;
+
+  if (!config_filename)
+    return; /* No config file. */
+
+  fp = fopen (config_filename, "r");
+  if (!fp)
+    {
+      log_error (_("option file `%s': %s\n"),
+                 config_filename, strerror(errno) );
+      return;
+    }
+
+  parse_rereadable_options (NULL); /* Start from the default values. */
+
+  memset (&pargs, 0, sizeof pargs);
+  dummy = 0;
+  pargs.argc = &dummy;
+  pargs.flags = 1;  /* do not remove the args */
+  while (optfile_parse (fp, config_filename, &configlineno, &pargs, opts) )
+    {
+      if (pargs.r_opt < -1)
+        pargs.err = 1; /* Print a warning. */
+      else /* Try to parse this option - ignore unchangeable ones. */
+        parse_rereadable_options (&pargs);
+    }
+  fclose (fp);
 }
 
 
index 6add3d4..094736c 100644 (file)
@@ -64,7 +64,7 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
       log_printhex ("keygrip:", ctrl->keygrip, 20);
       log_printhex ("cipher: ", ciphertext, ciphertextlen);
     }
-  s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, 0);
+  s_skey = agent_key_from_file (ctrl, ctrl->keygrip, &shadow_info, 0);
   if (!s_skey && !shadow_info)
     {
       log_error ("failed to read the secret key\n");
@@ -81,7 +81,7 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
           goto leave;
         }
 
-      rc = divert_pkdecrypt (ciphertext, shadow_info, &buf, &len );
+      rc = divert_pkdecrypt (ctrl, ciphertext, shadow_info, &buf, &len );
       if (rc)
         {
           log_error ("smartcard decryption failed: %s\n", gnupg_strerror (rc));
index 2acc63d..1d84d48 100644 (file)
@@ -1,5 +1,5 @@
 /* pksign.c - public key signing (well, acually using a secret key)
- *     Copyright (C) 2001 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2002 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -98,7 +98,8 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache)
   if (!ctrl->have_keygrip)
     return seterr (No_Secret_Key);
 
-  s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, ignore_cache);
+  s_skey = agent_key_from_file (ctrl,
+                                ctrl->keygrip, &shadow_info, ignore_cache);
   if (!s_skey && !shadow_info)
     {
       log_error ("failed to read the secret key\n");
@@ -110,7 +111,8 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache)
     { /* divert operation to the smartcard */
       unsigned char *sigbuf;
 
-      rc = divert_pksign (ctrl->digest.value, 
+      rc = divert_pksign (ctrl, 
+                          ctrl->digest.value, 
                           ctrl->digest.valuelen,
                           ctrl->digest.algo,
                           shadow_info, &sigbuf);
index 1d706ea..d501abd 100644 (file)
@@ -275,6 +275,8 @@ read_key (const char *fname)
   unsigned char *key;
   
   buf = read_file (fname, &buflen);
+  if (!buf)
+    return NULL;
   key = make_canonical (fname, buf, buflen);
   xfree (buf);
   return key;
index ee18a14..a20e4fe 100644 (file)
@@ -1,5 +1,5 @@
 /* query.c - fork of the pinentry to query stuff from the user
- *     Copyright (C) 2001 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2002 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -56,9 +56,15 @@ struct entry_parm_s {
 
 
 \f
+/* Unlock the pinentry so that another thread can start one and
+   disconnect that pinentry - we do this after the unlock so that a
+   stalled pinentry does not block other threads.  Fixme: We should
+   have a timeout in Assuan for the disconnetc operation. */
 static int 
 unlock_pinentry (int rc)
 {
+  ASSUAN_CONTEXT ctx = entry_ctx;
+
 #ifdef USE_GNU_PTH
   if (!pth_mutex_release (&entry_lock))
     {
@@ -67,6 +73,8 @@ unlock_pinentry (int rc)
         rc = GNUPG_Internal_Error;
     }
 #endif
+  entry_ctx = NULL;
+  assuan_disconnect (ctx);
   return rc;
 }
 
@@ -75,7 +83,7 @@ unlock_pinentry (int rc)
    pinentry - we will serialize _all_ pinentry calls.
  */
 static int
-start_pinentry (void)
+start_pinentry (CTRL ctrl)
 {
   int rc;
   const char *pgmname;
@@ -96,7 +104,7 @@ start_pinentry (void)
     return 0; 
 
   if (opt.verbose)
-    log_info ("no running PIN Entry - starting it\n");
+    log_info ("starting a new PIN Entry\n");
       
   if (fflush (NULL))
     {
@@ -111,12 +119,11 @@ start_pinentry (void)
   else
     pgmname++;
 
-  /* FIXME: We must do this thread specific */
   argv[0] = pgmname;
-  if (opt.display && !opt.keep_display)
+  if (ctrl->display && !opt.keep_display)
     {
       argv[1] = "--display";
-      argv[2] = opt.display;
+      argv[2] = ctrl->display;
       argv[3] = NULL;
     }
   else
@@ -150,10 +157,10 @@ start_pinentry (void)
                         NULL, NULL, NULL, NULL, NULL, NULL);
   if (rc)
     return unlock_pinentry (map_assuan_err (rc));
-  if (opt.ttyname && !opt.keep_tty)
+  if (ctrl->ttyname)
     {
       char *optstr;
-      if (asprintf (&optstr, "OPTION ttyname=%s", opt.ttyname) < 0 )
+      if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
        return unlock_pinentry (GNUPG_Out_Of_Core);
       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
                            NULL);
@@ -161,30 +168,30 @@ start_pinentry (void)
       if (rc)
        return unlock_pinentry (map_assuan_err (rc));
     }
-  if (opt.ttytype && !opt.keep_tty)
+  if (ctrl->ttytype)
     {
       char *optstr;
-      if (asprintf (&optstr, "OPTION ttytype=%s", opt.ttytype) < 0 )
+      if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
        return unlock_pinentry (GNUPG_Out_Of_Core);
       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
                            NULL);
       if (rc)
        return unlock_pinentry (map_assuan_err (rc));
     }
-  if (opt.lc_ctype)
+  if (ctrl->lc_ctype)
     {
       char *optstr;
-      if (asprintf (&optstr, "OPTION lc-ctype=%s", opt.lc_ctype) < 0 )
+      if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
        return unlock_pinentry (GNUPG_Out_Of_Core);
       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
                            NULL);
       if (rc)
        return unlock_pinentry (map_assuan_err (rc));
     }
-  if (opt.lc_messages)
+  if (ctrl->lc_messages)
     {
       char *optstr;
-      if (asprintf (&optstr, "OPTION lc-messages=%s", opt.lc_messages) < 0 )
+      if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
        return unlock_pinentry (GNUPG_Out_Of_Core);
       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
                            NULL);
@@ -230,7 +237,8 @@ all_digitsp( const char *s)
    number here and repeat it as long as we have invalid formed
    numbers. */
 int
-agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
+agent_askpin (CTRL ctrl,
+              const char *desc_text, struct pin_entry_info_s *pininfo)
 {
   int rc;
   char line[ASSUAN_LINELENGTH];
@@ -252,7 +260,7 @@ agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
 
   is_pin = desc_text && strstr (desc_text, "PIN");
 
-  rc = start_pinentry ();
+  rc = start_pinentry (ctrl);
   if (rc)
     return rc;
 
@@ -335,7 +343,8 @@ agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
    passphrase is returned in RETPASS as an hex encoded string to be
    freed by the caller */
 int 
-agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
+agent_get_passphrase (CTRL ctrl,
+                      char **retpass, const char *desc, const char *prompt,
                       const char *errtext)
 {
 
@@ -349,7 +358,7 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
   if (opt.batch)
     return GNUPG_Bad_Passphrase; 
 
-  rc = start_pinentry ();
+  rc = start_pinentry (ctrl);
   if (rc)
     return rc;
 
@@ -417,12 +426,13 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
    confirmed it, GNUPG_Not_Confirmed for what the text says or an
    other error. */
 int 
-agent_get_confirmation (const char *desc, const char *ok, const char *cancel)
+agent_get_confirmation (CTRL ctrl,
+                        const char *desc, const char *ok, const char *cancel)
 {
   int rc;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_pinentry ();
+  rc = start_pinentry (ctrl);
   if (rc)
     return rc;
 
index 5bb08af..afdc4e2 100644 (file)
@@ -177,9 +177,10 @@ agent_send_all_options (int fd)
         return rc;
     }
 
-  if (ttyname (1))
-    dft_ttyname = ttyname (1);
-  if (dft_ttyname)
+  dft_ttyname = getenv ("GPG_TTY");
+  if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
+    dft_ttyname = ttyname (0);
+  if (dft_ttyname && *dft_ttyname)
     {
       if ((rc=agent_send_option (fd, "ttyname", dft_ttyname)))
         return rc;
index b6545f7..9fc4623 100644 (file)
@@ -228,7 +228,7 @@ agent_listtrusted (void *assuan_context)
    whether this is actual wants he want to do.
 */
 int 
-agent_marktrusted (const char *name, const char *fpr, int flag)
+agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
 {
   int rc;
   static char key[41];
@@ -254,7 +254,7 @@ agent_marktrusted (const char *name, const char *fpr, int flag)
                 "has the fingerprint:%%0A"
                 "  %s", name, fpr) < 0 )
     return GNUPG_Out_Of_Core;
-  rc = agent_get_confirmation (desc, "Correct", "No");
+  rc = agent_get_confirmation (ctrl, desc, "Correct", "No");
   free (desc);
   if (rc)
     return rc;
@@ -265,7 +265,7 @@ agent_marktrusted (const char *name, const char *fpr, int flag)
                 "to correctly certify user certificates?",
                 name) < 0 )
     return GNUPG_Out_Of_Core;
-  rc = agent_get_confirmation (desc, "Yes", "No");
+  rc = agent_get_confirmation (ctrl, desc, "Yes", "No");
   free (desc);
   if (rc)
     return rc;
index ff88665..e202658 100644 (file)
@@ -1,3 +1,14 @@
+2002-10-31  Neal H. Walfield  <neal@g10code.de>
+
+       * isascii.c: New file.
+       * putc_unlocked.c: Likewise.
+
+2002-10-28  Neal H. Walfield  <neal@g10code.de>
+
+       * signal.c (caught_fatal_sig): Remove superfluous zero
+       initializer.
+       (caught_sigusr1): Likewise.
+
 2002-09-04  Neal H. Walfield  <neal@g10code.de>
 
        * vasprintf.c (vasprintf) [va_copy]: Use va_copy.
diff --git a/common/isascii.c b/common/isascii.c
new file mode 100644 (file)
index 0000000..565c716
--- /dev/null
@@ -0,0 +1,29 @@
+/* isascii.c - Replacement for isascii.
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+int
+isascii (int c)
+{
+  return (((c) & ~0x7f) == 0);
+}
diff --git a/common/putc_unlocked.c b/common/putc_unlocked.c
new file mode 100644 (file)
index 0000000..02c6461
--- /dev/null
@@ -0,0 +1,31 @@
+/* putc_unlocked.c - Replacement for putc_unlocked.
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+int
+putc_unlocked (int c, FILE *stream)
+{
+  return putc (c, stream);
+}
index b150fa9..dc026c1 100644 (file)
@@ -30,8 +30,8 @@
 #include "util.h"
 
 
-static volatile int caught_fatal_sig = 0;
-static volatile int caught_sigusr1 = 0;
+static volatile int caught_fatal_sig;
+static volatile int caught_sigusr1;
 static void (*cleanup_fnc)(void);
 
 
index 351ec5d..14c225f 100644 (file)
@@ -1,3 +1,12 @@
+2002-11-14  Werner Koch  <wk@gnupg.org>
+
+       * keybox-search.c (blob_cmp_name) <compare all names>: Fixed
+       length compare; there is no 0 stored since nearly a year.  
+
+2002-10-31  Neal H. Walfield  <neal@g10code.de>
+
+       * Makefile.am (AM_CPPFLAGS): Fix ytpo.
+
 2002-08-10  Werner Koch  <wk@gnupg.org>
 
        * keybox-search.c (blob_cmp_fpr_part): New.
@@ -16,7 +25,7 @@
 2002-06-19  Werner Koch  <wk@gnupg.org>
 
        * keybox-init.c (keybox_set_ephemeral): New.
-       * keybox-blob.c (create_blob_header): Store epheermal flag.
+       * keybox-blob.c (create_blob_header): Store ephemeral flag.
        (_keybox_create_x509_blob): Pass epheermal flag on.
        * keybox-update.c (keybox_insert_cert): Ditto.
        * keybox-search.c (blob_get_blob_flags): New.
index 4e71703..78d5df2 100644 (file)
@@ -1,5 +1,5 @@
 # Keybox Makefile 
-# Copyright (C) 2001 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
 #
 # This file is part of GnuPG.
 #
@@ -23,7 +23,7 @@ localedir = $(datadir)/locale
 INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\"
 
 EXTRA_DIST = mkerrors
-AM_CPPFLAGS =   $(KSBA_CFLAGS) $(LIBGCRYPT_CLFAGS)
+AM_CPPFLAGS =   $(KSBA_CFLAGS) $(LIBGCRYPT_CFLAGS)
 BUILT_SOURCES = keybox-errors.c
 
 noinst_LIBRARIES = libkeybox.a
index 126364f..a96b0c2 100644 (file)
@@ -234,9 +234,8 @@ blob_cmp_name (KEYBOXBLOB blob, int idx,
           len = get32 (buffer+mypos+4);
           if (off+len > length)
             return 0; /* error: better stop here out of bounds */
-          if (len < 2)
-            continue; /* empty name or 0 not stored */
-          len--;
+          if (len < 1)
+            continue; /* empty name */
           if (substr)
             {
               if (ascii_memcasemem (buffer+off, len, name, namelen))
index 8e11e0d..0a91507 100644 (file)
@@ -1,3 +1,35 @@
+2002-12-03  Werner Koch  <wk@gnupg.org>
+
+       * call-agent.c (gpgsm_agent_passwd): New.
+       * gpgsm.c (main): New command --passwd and --call-protect-tool
+       (run_protect_tool): New.
+
+2002-11-25  Werner Koch  <wk@gnupg.org>
+
+       * verify.c (gpgsm_verify): Handle content-type attribute. 
+
+2002-11-13  Werner Koch  <wk@gnupg.org>
+
+       * call-agent.c (start_agent): Try to use $GPG_TTY instead of
+       ttyname.  Changed ttyname to test stdin becuase it can be assumed
+       that output redirection is more common that input redirection.
+
+2002-11-12  Werner Koch  <wk@gnupg.org>
+
+       * gpgsm.c: New command --call-dirmngr. 
+       * call-dirmngr.c (gpgsm_dirmngr_run_command)
+       (run_command_inq_cb,run_command_cb)
+       (run_command_status_cb): New.
+
+2002-11-11  Werner Koch  <wk@gnupg.org>
+
+       * certcheck.c (gpgsm_check_cms_signature): Don't double free
+       s_sig but free s_pkey at leave.
+
+2002-11-10  Werner Koch  <wk@gnupg.org>
+
+       * gpgsm.c: Removed duplicate --list-secret-key entry.
+
 2002-09-19  Werner Koch  <wk@gnupg.org>
 
        * certcheck.c (gpgsm_check_cert_sig): Add cert hash debugging.
index 6cb2fb5..d518b2b 100644 (file)
@@ -248,8 +248,12 @@ start_agent (void)
       if (rc)
        return map_assuan_err (rc);
     }
-  if (!opt.ttyname && ttyname (1))
-    dft_ttyname = ttyname (1);
+  if (!opt.ttyname)
+    {
+      dft_ttyname = getenv ("GPG_TTY");
+      if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
+        dft_ttyname = ttyname (0);
+    }
   if (opt.ttyname || dft_ttyname)
     {
       char *optstr;
@@ -749,3 +753,25 @@ gpgsm_agent_learn ()
   return learn_parm.error;
 }
 
+\f
+/* Ask the agent to change the passphrase of the key identified by HEXKEYGRIP. */
+int
+gpgsm_agent_passwd (const char *hexkeygrip)
+{
+  int rc;
+  char line[ASSUAN_LINELENGTH];
+
+  rc = start_agent ();
+  if (rc)
+    return rc;
+
+  if (!hexkeygrip || strlen (hexkeygrip) != 40)
+    return GNUPG_Invalid_Value;
+
+  snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
+  line[DIM(line)-1] = 0;
+
+  rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+  return map_assuan_err (rc);
+}
+
index a1d94e2..6c1156a 100644 (file)
@@ -26,6 +26,7 @@
 #include <unistd.h> 
 #include <time.h>
 #include <assert.h>
+#include <ctype.h>
 
 #include <gcrypt.h>
 
@@ -59,7 +60,9 @@ struct lookup_parm_s {
   int error;
 };
 
-
+struct run_command_parm_s {
+  ASSUAN_CONTEXT ctx;
+};
 
 
 /* A simple implementation of a dynamic buffer.  Use init_membuf() to
@@ -452,7 +455,7 @@ lookup_status_cb (void *opaque, const char *line)
 }
 
 
-/* Run the Directroy Managers lookup command using the apptern
+/* Run the Directroy Managers lookup command using the pattern
    compiled from the strings given in NAMES.  The caller must provide
    the callback CB which will be passed cert by cert.  Note that CTRL
    is optional. */
@@ -493,3 +496,136 @@ gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
 }
 
 
+\f
+/* Run Command helpers*/
+
+/* Fairly simple callback to write all output of dirmngr to stdout. */
+static AssuanError
+run_command_cb (void *opaque, const void *buffer, size_t length)
+{
+  if (buffer)
+    {
+      if ( fwrite (buffer, length, 1, stdout) != 1 )
+        log_error ("error writing to stdout: %s\n", strerror (errno));
+    }
+  return 0;
+}
+
+/* Handle inquiries from the dirmngr COMMAND. */
+static AssuanError
+run_command_inq_cb (void *opaque, const char *line)
+{
+  struct run_command_parm_s *parm = opaque;
+  AssuanError rc = 0;
+
+  if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
+    { /* send the given certificate */
+      int err;
+      KsbaCert cert;
+      const unsigned char *der;
+      size_t derlen;
+
+      line += 8;
+      if (!*line)
+        return ASSUAN_Inquire_Error;
+
+      err = gpgsm_find_cert (line, &cert);
+      if (err)
+        {
+          log_error ("certificate not found: %s\n", gnupg_strerror (err));
+          rc = ASSUAN_Inquire_Error;
+        }
+      else
+        {
+          der = ksba_cert_get_image (cert, &derlen);
+          if (!der)
+            rc = ASSUAN_Inquire_Error;
+          else
+            rc = assuan_send_data (parm->ctx, der, derlen);
+          ksba_cert_release (cert);
+        }
+    }
+  else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) )
+    { /* Simply show the message given in the argument. */
+      line += 9;
+      log_info ("dirmngr: %s\n", line);
+    }
+  else
+    {
+      log_error ("unsupported inquiry `%s'\n", line);
+      rc = ASSUAN_Inquire_Unknown;
+    }
+
+  return rc; 
+}
+
+static AssuanError
+run_command_status_cb (void *opaque, const char *line)
+{
+  if (opt.verbose)
+    {
+      log_info ("dirmngr status: %s\n", line);
+    }
+  return 0;
+}
+
+
+
+/* Pass COMMAND to dirmngr and print all output generated by Dirmngr
+   to stdout.  A couple of inquiries are defined (see above).  ARGC
+   arguments in ARGV are given to the Dirmngr.  Spaces, plus and
+   percent characters within the argument strings are percent escaped
+   so that blanks can act as delimiters. */
+int
+gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
+                           int argc, char **argv)
+{ 
+  int rc;
+  int i;
+  const char *s;
+  char *line, *p;
+  size_t len;
+  struct run_command_parm_s parm;
+
+  rc = start_dirmngr ();
+  if (rc)
+    return rc;
+
+  parm.ctx = dirmngr_ctx;
+
+  len = strlen (command) + 1;
+  for (i=0; i < argc; i++)
+    len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
+  line = xtrymalloc (len);
+  if (!line)
+    return GNUPG_Out_Of_Core;
+
+  p = stpcpy (line, command);
+  for (i=0; i < argc; i++)
+    {
+      *p++ = ' ';
+      for (s=argv[i]; *s; s++)
+        {
+          if (!isascii (*s))
+            *p++ = *s;
+          else if (*s == ' ')
+            *p++ = '+';
+          else if (!isprint (*s) || *s == '+')
+            {
+              sprintf (p, "%%%02X", *s);
+              p += 3;
+            }
+          else
+            *p++ = *s;
+        }
+    }
+  *p = 0;
+
+  rc = assuan_transact (dirmngr_ctx, line,
+                        run_command_cb, NULL,
+                        run_command_inq_cb, &parm,
+                        run_command_status_cb, NULL);
+  xfree (line);
+  log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
+  return map_assuan_err (rc);
+}
index 37d2b00..1f9054b 100644 (file)
@@ -266,13 +266,12 @@ gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval,
     BUG ();
   gcry_mpi_release (frame);
   
-  
   rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
   if (DBG_CRYPTO)
       log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc));
   gcry_sexp_release (s_sig);
   gcry_sexp_release (s_hash);
-  gcry_sexp_release (s_sig);
+  gcry_sexp_release (s_pkey);
   return map_gcry_err (rc);
 }
 
index bfcdeb7..1583787 100644 (file)
@@ -77,6 +77,9 @@ enum cmd_and_opt_values {
   aCheckKeys, /* nyi */
   aServer,                        
   aLearnCard,
+  aCallDirmngr,
+  aCallProtectTool,
+  aPasswd,
 
   oOptions,
   oDebug,
@@ -139,7 +142,6 @@ enum cmd_and_opt_values {
   oCipherAlgo,
   oDigestAlgo,
   oCompressAlgo,
-  oPasswdFD,
   oCommandFD,
   oNoVerbose,
   oTrustDBName,
@@ -219,7 +221,6 @@ static ARGPARSE_OPTS opts[] = {
     { aListSigs,   "list-sigs", 256, N_("list certificate chain")}, 
     { aListSigs,   "check-sigs",256, "@"},
     { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
-    { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
     { aKeygen,    "gen-key",  256, N_("generate a new key pair")},
     { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
     { aSendKeys, "send-keys"     , 256, N_("export keys to a key server") },
@@ -228,7 +229,10 @@ static ARGPARSE_OPTS opts[] = {
     { aExport, "export",      256     , N_("export certificates")},
     { aLearnCard, "learn-card", 256 ,N_("register a smartcard")},
     { aServer, "server",      256, N_("run in server mode")},
-    { oLogFile, "log-file"   ,2, N_("use a log file for the server")},
+    { aCallDirmngr, "call-dirmngr", 256, N_("pass a command to the dirmngr")},
+    { aCallProtectTool, "call-protect-tool", 256,
+                                   N_("invoke gpg-protect-tool")},
+    { aPasswd, "passwd",      256, N_("change a passphrase")},
 
     { 301, NULL, 0, N_("@\nOptions:\n ") },
 
@@ -283,6 +287,7 @@ static ARGPARSE_OPTS opts[] = {
     { oVerbose, "verbose",   0, N_("verbose") },
     { oQuiet,  "quiet",   0, N_("be somewhat more quiet") },
     { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") },
+    { oLogFile, "log-file"   ,2, N_("use a log file for the server")},
 #if 0
     { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") },
     { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") },
@@ -406,6 +411,7 @@ static void emergency_cleanup (void);
 static int check_special_filename (const char *fname);
 static int open_read (const char *filename);
 static FILE *open_fwrite (const char *filename);
+static void run_protect_tool (int argc, char **argv);
 
 
 static int
@@ -589,6 +595,7 @@ main ( int argc, char **argv)
   char *configname = NULL;
   unsigned configlineno;
   int parse_debug = 0;
+  int no_more_options = 0;
   int default_config =1;
   int default_keyring = 1;
   char *logfile = NULL;
@@ -666,6 +673,9 @@ main ( int argc, char **argv)
         default_config = 0; /* --no-options */
       else if (pargs.r_opt == oHomedir)
         opt.homedir = pargs.r.ret_str;
+      else if (pargs.r_opt == aCallProtectTool)
+        break; /* This break makes sure that --version and --help are
+                  passed to the protect-tool. */
     }
   
   
@@ -724,7 +734,8 @@ main ( int argc, char **argv)
     default_config = 0;
   }
 
-  while (optfile_parse (configfp, configname, &configlineno, &pargs, opts))
+  while (!no_more_options 
+         && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
     {
       switch (pargs.r_opt)
         {
@@ -732,7 +743,17 @@ main ( int argc, char **argv)
           opt.batch = 1;
           set_cmd (&cmd, aServer);
           break;
+        case aCallDirmngr:
+          opt.batch = 1;
+          set_cmd (&cmd, aCallDirmngr);
+          break;
 
+        case aCallProtectTool:
+          opt.batch = 1;
+          set_cmd (&cmd, aCallProtectTool);
+          no_more_options = 1; /* Stop parsing. */
+          break;
+        
         case aCheckKeys: set_cmd (&cmd, aCheckKeys); break;
         case aImport: set_cmd (&cmd, aImport); break;
         case aSendKeys: set_cmd (&cmd, aSendKeys); break;
@@ -744,6 +765,8 @@ main ( int argc, char **argv)
         case aListSigs: set_cmd (&cmd, aListSigs); break;
 
         case aLearnCard: set_cmd (&cmd, aLearnCard); break;
+          
+        case aPasswd: set_cmd (&cmd, aPasswd); break;
 
         case aDeleteKey:
           set_cmd (&cmd, aDeleteKey);
@@ -1128,6 +1151,18 @@ main ( int argc, char **argv)
       gpgsm_server ();
       break;
 
+    case aCallDirmngr:
+      if (!argc)
+        wrong_args (_("--call-dirmngr <command> {args}"));
+      else
+        if (gpgsm_dirmngr_run_command (&ctrl, *argv, argc-1, argv+1))
+          gpgsm_exit (1);
+      break;
+
+    case aCallProtectTool:
+      run_protect_tool (argc, argv);
+      break;
+
     case aEncr: /* encrypt the given file */
       if (!argc)
         gpgsm_encrypt (&ctrl, recplist, 0, stdout); /* from stdin */
@@ -1258,6 +1293,28 @@ main ( int argc, char **argv)
         }
       break;
 
+    case aPasswd:
+      if (argc != 1)
+        wrong_args ("--passwd <key-Id>");
+      else
+        {
+          int rc;
+          KsbaCert cert = NULL;
+          char *grip = NULL;
+
+          rc = gpgsm_find_cert (*argv, &cert);
+          if (rc)
+            ;
+          else if (!(grip = gpgsm_get_keygrip_hexstring (cert)))
+            rc = GNUPG_Bug;
+          else 
+            rc = gpgsm_agent_passwd (grip);
+          if (rc)
+            log_error ("error changing passphrase: %s\n", gnupg_strerror (rc));
+          xfree (grip);
+          ksba_cert_release (cert);
+        }
+      break;
 
     default:
         log_error ("invalid command (there is no implicit command)\n");
@@ -1386,3 +1443,24 @@ open_fwrite (const char *filename)
     }
   return fp;
 }
+
+
+static void
+run_protect_tool (int argc, char **argv)
+{
+  char *pgm = GNUPG_PROTECT_TOOL;
+  char **av;
+  int i;
+
+  av = xcalloc (argc+2, sizeof *av);
+  av[0] = strrchr (pgm, '/');
+  if (!av[0])
+    av[0] = pgm;
+  for (i=1; argc; i++, argc--, argv++)
+    av[i] = *argv;
+  av[i] = NULL;
+  execv (pgm, av); 
+  log_error ("error executing `%s': %s\n", pgm, strerror (errno));
+  gpgsm_exit (2);
+}
+
index 5059020..dd91e37 100644 (file)
@@ -248,11 +248,14 @@ int gpgsm_agent_istrusted (KsbaCert cert);
 int gpgsm_agent_havekey (const char *hexkeygrip);
 int gpgsm_agent_marktrusted (KsbaCert cert);
 int gpgsm_agent_learn (void);
+int gpgsm_agent_passwd (const char *hexkeygrip);
 
 /*-- call-dirmngr.c --*/
 int gpgsm_dirmngr_isvalid (KsbaCert cert);
 int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
                           void (*cb)(void*, KsbaCert), void *cb_value);
+int gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
+                               int argc, char **argv);
 
 
 
index df7c8bf..3461d68 100644 (file)
@@ -257,6 +257,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
       KsbaSexp serial;
       char *msgdigest = NULL;
       size_t msgdigestlen;
+      char *ctattr;
 
       err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
       if (!signer && err == KSBA_No_Data && data_fd == -1 && is_detached)
@@ -313,6 +314,35 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
       else /* real error */
         break;
 
+      err = ksba_cms_get_sigattr_oids (cms, signer,
+                                       "1.2.840.113549.1.9.3",&ctattr);
+      if (!err) 
+        {
+          const char *s;
+
+          if (DBG_X509)
+            log_debug ("signer %d - content-type attribute: %s", signer, ctattr);
+          s = ksba_cms_get_content_oid (cms, 1);
+          if (!s || strcmp (ctattr, s))
+            {
+              log_error ("content-type attribute does not match "
+                         "actual content-type\n");
+              ksba_free (ctattr);
+              ctattr = NULL;
+              goto next_signer;
+            }
+          ksba_free (ctattr);
+          ctattr = NULL;
+        }
+      else if (err != -1)
+        {
+          log_error ("error getting content-type attribute: %s\n",
+                     ksba_strerror (err));
+          goto next_signer;
+        }
+      err = 0;
+
+
       sigval = ksba_cms_get_sig_val (cms, signer);
       if (!sigval)
         {