* gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP.
authorWerner Koch <wk@gnupg.org>
Tue, 11 May 2004 19:11:53 +0000 (19:11 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 11 May 2004 19:11:53 +0000 (19:11 +0000)
(start_connection_thread): Hack to simulate a ticker.
* trustlist.c (agent_trustlist_housekeeping)
(agent_reload_trustlist): New.  Protected all global functions
here with a simple counter which is sufficient for Pth.

* fingerprint.c (gpgsm_get_key_algo_info): New.
* sign.c (gpgsm_sign): Don't assume RSA in the status line.
* keylist.c (list_cert_colon): Really print the algorithm and key
length.
(list_cert_raw, list_cert_std): Ditto.
(list_cert_colon): Reorganized to be able to tell whether a root
certificate is trusted.

agent/ChangeLog
agent/agent.h
agent/gpg-agent.c
agent/trustlist.c
sm/ChangeLog
sm/keylist.c

index cf4ae79..ae1dd88 100644 (file)
@@ -1,3 +1,11 @@
+2004-05-11  Werner Koch  <wk@gnupg.org>
+
+       * gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP.
+       (start_connection_thread): Hack to simulate a ticker.
+       * trustlist.c (agent_trustlist_housekeeping) 
+       (agent_reload_trustlist): New.  Protected all global functions
+       here with a simple counter which is sufficient for Pth.
+
 2004-05-03  Werner Koch  <wk@gnupg.org>
 
        * gpg-agent.c: Remove help texts for options lile --lc-ctype.
 2004-05-03  Werner Koch  <wk@gnupg.org>
 
        * gpg-agent.c: Remove help texts for options lile --lc-ctype.
index 99fdc05..6b7821e 100644 (file)
@@ -189,6 +189,8 @@ int agent_istrusted (const char *fpr);
 int agent_listtrusted (void *assuan_context);
 int agent_marktrusted (ctrl_t ctrl, const char *name,
                        const char *fpr, int flag);
 int agent_listtrusted (void *assuan_context);
 int agent_marktrusted (ctrl_t ctrl, const char *name,
                        const char *fpr, int flag);
+void agent_trustlist_housekeeping (void);
+void agent_reload_trustlist (void);
 
 
 /*-- divert-scd.c --*/
 
 
 /*-- divert-scd.c --*/
index ad6ef33..8d21dc4 100644 (file)
@@ -1083,6 +1083,7 @@ handle_signal (int signo)
                 "re-reading configuration and flushing cache\n");
       agent_flush_cache ();
       reread_configuration ();
                 "re-reading configuration and flushing cache\n");
       agent_flush_cache ();
       reread_configuration ();
+      agent_reload_trustlist ();
       break;
       
     case SIGUSR1:
       break;
       
     case SIGUSR1:
@@ -1129,6 +1130,12 @@ start_connection_thread (void *arg)
 
   if (opt.verbose)
     log_info ("handler for fd %d started\n", fd);
 
   if (opt.verbose)
     log_info ("handler for fd %d started\n", fd);
+
+  /* FIXME: Move this housekeeping into a ticker function.  Calling it
+     for each connection should work but won't work anymore if our
+     cleints start to keep connections. */
+  agent_trustlist_housekeeping ();
+
   start_command_handler (-1, fd);
   if (opt.verbose)
     log_info ("handler for fd %d terminated\n", fd);
   start_command_handler (-1, fd);
   if (opt.verbose)
     log_info ("handler for fd %d terminated\n", fd);
index 19de070..16b7dc3 100644 (file)
@@ -1,5 +1,5 @@
 /* trustlist.c - Maintain the list of trusted keys
 /* trustlist.c - Maintain the list of trusted keys
- *     Copyright (C) 2002 Free Software Foundation, Inc.
+ *     Copyright (C) 2002, 2004 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  *
  * This file is part of GnuPG.
  *
@@ -41,10 +41,13 @@ static const char headerblurb[] =
 "# with optional white spaces, followed by exactly 40 hex character,\n"
 "# optioanlly followed by a flag character which my either be 'P', 'S'\n"
 "# or '*'. Additional data delimited with by a white space is ignored.\n"
 "# with optional white spaces, followed by exactly 40 hex character,\n"
 "# optioanlly followed by a flag character which my either be 'P', 'S'\n"
 "# or '*'. Additional data delimited with by a white space is ignored.\n"
+"# NOTE: You should give the gpg-agent a HUP after editing this file.\n"
 "\n";
 
 
 static FILE *trustfp;
 "\n";
 
 
 static FILE *trustfp;
+static int   trustfp_used; /* Counter to track usage of TRUSTFP. */
+static int   reload_trustlist_pending;
 
 
 static int
 
 
 static int
@@ -164,7 +167,7 @@ read_list (char *key, int *keyflag)
   return 0;
 }
 
   return 0;
 }
 
-/* check whether the given fpr is in our trustdb.  We expect FPR to be
+/* Check whether the given fpr is in our trustdb.  We expect FPR to be
    an all uppercase hexstring of 40 characters. */
 int 
 agent_istrusted (const char *fpr)
    an all uppercase hexstring of 40 characters. */
 int 
 agent_istrusted (const char *fpr)
@@ -173,25 +176,31 @@ agent_istrusted (const char *fpr)
   static char key[41];
   int keyflag;
 
   static char key[41];
   int keyflag;
 
+  trustfp_used++;
   if (trustfp)
     rewind (trustfp);
   while (!(rc=read_list (key, &keyflag)))
     {
       if (!strcmp (key, fpr))
   if (trustfp)
     rewind (trustfp);
   while (!(rc=read_list (key, &keyflag)))
     {
       if (!strcmp (key, fpr))
-        return 0;
+        {
+          trustfp_used--;
+          return 0;
+        }
     }
   if (rc != -1)
     {
     }
   if (rc != -1)
     {
-      /* error in the trustdb - close it to give the user a chance for
+      /* Error in the trustdb - close it to give the user a chance for
          correction */
          correction */
-      fclose (trustfp);
+      if (trustfp)
+        fclose (trustfp);
       trustfp = NULL;
     }
       trustfp = NULL;
     }
+  trustfp_used--;
   return rc;
 }
 
 
   return rc;
 }
 
 
-/* write all trust entries to FP */
+/* Write all trust entries to FP. */
 int 
 agent_listtrusted (void *assuan_context)
 {
 int 
 agent_listtrusted (void *assuan_context)
 {
@@ -199,6 +208,7 @@ agent_listtrusted (void *assuan_context)
   static char key[51];
   int keyflag;
 
   static char key[51];
   int keyflag;
 
+  trustfp_used++;
   if (trustfp)
     rewind (trustfp);
   while (!(rc=read_list (key, &keyflag)))
   if (trustfp)
     rewind (trustfp);
   while (!(rc=read_list (key, &keyflag)))
@@ -213,11 +223,13 @@ agent_listtrusted (void *assuan_context)
     rc = 0;
   if (rc)
     {
     rc = 0;
   if (rc)
     {
-      /* error in the trustdb - close it to give the user a chance for
+      /* Error in the trustdb - close it to give the user a chance for
          correction */
          correction */
-      fclose (trustfp);
+      if (trustfp)
+        fclose (trustfp);
       trustfp = NULL;
     }
       trustfp = NULL;
     }
+  trustfp_used--;
   return rc;
 }
 
   return rc;
 }
 
@@ -252,7 +264,7 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
     }    
   xfree (fname);
 
     }    
   xfree (fname);
 
-
+  trustfp_used++;
   if (trustfp)
     rewind (trustfp);
   while (!(rc=read_list (key, &keyflag)))
   if (trustfp)
     rewind (trustfp);
   while (!(rc=read_list (key, &keyflag)))
@@ -260,14 +272,21 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
       if (!strcmp (key, fpr))
         return 0;
     }
       if (!strcmp (key, fpr))
         return 0;
     }
-  fclose (trustfp);
+  if (trustfp)
+    fclose (trustfp);
   trustfp = NULL;
   if (rc != -1)
   trustfp = NULL;
   if (rc != -1)
-    return rc;   /* error in the trustdb */
+    {
+      trustfp_used--;
+      return rc;   /* Error in the trustlist. */
+    }
 
   /* This feature must explicitly been enabled. */
   if (!opt.allow_mark_trusted)
 
   /* This feature must explicitly been enabled. */
   if (!opt.allow_mark_trusted)
-    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+    {
+      trustfp_used--;
+      return gpg_error (GPG_ERR_NOT_SUPPORTED);
+    }
 
   /* insert a new one */
   if (asprintf (&desc,
 
   /* insert a new one */
   if (asprintf (&desc,
@@ -275,42 +294,62 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
                 "  \"%s\"%%0A"
                 "has the fingerprint:%%0A"
                 "  %s", name, fpr) < 0 )
                 "  \"%s\"%%0A"
                 "has the fingerprint:%%0A"
                 "  %s", name, fpr) < 0 )
-    return out_of_core ();
+    {
+      trustfp_used--;
+      return out_of_core ();
+    }
   rc = agent_get_confirmation (ctrl, desc, "Correct", "No");
   free (desc);
   if (rc)
   rc = agent_get_confirmation (ctrl, desc, "Correct", "No");
   free (desc);
   if (rc)
-    return rc;
+    {
+      trustfp_used--;
+      return rc;
+    }
 
   if (asprintf (&desc,
                 "Do you ultimately trust%%0A"
                 "  \"%s\"%%0A"
                 "to correctly certify user certificates?",
                 name) < 0 )
 
   if (asprintf (&desc,
                 "Do you ultimately trust%%0A"
                 "  \"%s\"%%0A"
                 "to correctly certify user certificates?",
                 name) < 0 )
-    return out_of_core ();
+    {
+      trustfp_used--;
+      return out_of_core ();
+    }
   rc = agent_get_confirmation (ctrl, desc, "Yes", "No");
   free (desc);
   if (rc)
   rc = agent_get_confirmation (ctrl, desc, "Yes", "No");
   free (desc);
   if (rc)
-    return rc;
+    {
+      trustfp_used--;
+      return rc;
+    }
 
 
-  /* now check again to avoid duplicates.  Also open in append mode now */
+  /* Now check again to avoid duplicates.  Also open in append mode now. */
   rc = open_list (1);
   if (rc)
   rc = open_list (1);
   if (rc)
-    return rc;
+    {
+      trustfp_used--;
+      return rc;
+    }
   rewind (trustfp);
   while (!(rc=read_list (key, &keyflag)))
     {
       if (!strcmp (key, fpr))
   rewind (trustfp);
   while (!(rc=read_list (key, &keyflag)))
     {
       if (!strcmp (key, fpr))
-        return 0;
+        {
+          trustfp_used--;
+          return 0;
+        }
     }
   if (rc != -1)
     {
     }
   if (rc != -1)
     {
-      fclose (trustfp);
+      if (trustfp)
+        fclose (trustfp);
       trustfp = NULL;
       trustfp = NULL;
-      return rc;   /* error in the trustdb */
+      trustfp_used--;
+      return rc;   /* Error in the trustlist. */
     }
   rc = 0;
 
     }
   rc = 0;
 
-  /* append the key */
+  /* Append the key. */
   fflush (trustfp);
   fputs ("\n# ", trustfp);
   print_sanitized_string (trustfp, name, 0);
   fflush (trustfp);
   fputs ("\n# ", trustfp);
   print_sanitized_string (trustfp, name, 0);
@@ -322,5 +361,33 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
   if (fclose (trustfp))
     rc = gpg_error (gpg_err_code_from_errno (errno));
   trustfp = NULL;
   if (fclose (trustfp))
     rc = gpg_error (gpg_err_code_from_errno (errno));
   trustfp = NULL;
+  trustfp_used--;
   return rc;
 }
   return rc;
 }
+
+
+void
+agent_trustlist_housekeeping (void)
+{
+  if (reload_trustlist_pending && !trustfp_used)
+    {
+      if (trustfp)
+        {
+          fclose (trustfp);
+          trustfp = NULL;
+        }
+      reload_trustlist_pending = 0;
+    }
+}
+
+
+/* Not all editors are editing files in place, thus a changes
+   trustlist.txt won't be recognozed if we keep the file descriptor
+   open. This function may be used to explicitly close that file
+   descriptor, which will force a reopen in turn. */
+void
+agent_reload_trustlist (void)
+{
+  reload_trustlist_pending = 1;
+  agent_trustlist_housekeeping ();
+}
index a1997e2..eed350b 100644 (file)
@@ -9,6 +9,8 @@
        * keylist.c (list_cert_colon): Really print the algorithm and key
        length.
        (list_cert_raw, list_cert_std): Ditto.
        * keylist.c (list_cert_colon): Really print the algorithm and key
        length.
        (list_cert_raw, list_cert_std): Ditto.
+       (list_cert_colon): Reorganized to be able to tell whether a root
+       certificate is trusted.
 
        * gpgsm.c: New option --debug-allow-core-dump.
 
 
        * gpgsm.c: New option --debug-allow-core-dump.
 
index e9056b6..27c67de 100644 (file)
@@ -289,6 +289,7 @@ static void
 list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
                  FILE *fp, int have_secret)
 {
 list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
                  FILE *fp, int have_secret)
 {
+  int rc;
   int idx;
   char truststring[2];
   char *p;
   int idx;
   char truststring[2];
   char *p;
@@ -298,12 +299,39 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
   gpg_error_t valerr;
   int algo;
   unsigned int nbits;
   gpg_error_t valerr;
   int algo;
   unsigned int nbits;
+  const char *chain_id;
+  char *chain_id_buffer = NULL;
+  int is_root = 0;
 
   if (ctrl->with_validation)
     valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0);
   else
     valerr = 0;
 
 
   if (ctrl->with_validation)
     valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0);
   else
     valerr = 0;
 
+
+  /* We need to get the fingerprint and the chaining ID in advance. */
+  fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
+  {
+    ksba_cert_t next;
+
+    rc = gpgsm_walk_cert_chain (cert, &next);
+    if (!rc) /* We known the issuer's certificate. */
+      {
+        p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
+        chain_id_buffer = p;
+        chain_id = chain_id_buffer;
+        ksba_cert_release (next);
+      }
+    else if (rc == -1)  /* We have reached the root certificate. */
+      {
+        chain_id = fpr;
+        is_root = 1;
+      }
+    else
+      chain_id = NULL;
+  }
+
+
   fputs (have_secret? "crs:":"crt:", fp);
   truststring[0] = 0;
   truststring[1] = 0;
   fputs (have_secret? "crs:":"crt:", fp);
   truststring[0] = 0;
   truststring[1] = 0;
@@ -327,11 +355,23 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
           && *not_after && strcmp (current_time, not_after) > 0 )
         *truststring = 'e';
     }
           && *not_after && strcmp (current_time, not_after) > 0 )
         *truststring = 'e';
     }
+
+  /* Is we have no truststring yet (i.e. the certificate might be
+     good) and this is a root certificate, we ask the agent whether
+     this is a trusted root certificate. */
+  if (!*truststring && is_root)
+    {
+      rc = gpgsm_agent_istrusted (ctrl, cert);
+      if (!rc)
+        *truststring = 'u';  /* Yes, we trust this one (ultimately). */
+      else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
+        *truststring = 'n';  /* No, we do not trust this one. */
+      /* (in case of an error we can't tell anything.) */
+    }
   
   if (*truststring)
     fputs (truststring, fp);
 
   
   if (*truststring)
     fputs (truststring, fp);
 
-  fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
   algo = gpgsm_get_key_algo_info (cert, &nbits);
   fprintf (fp, ":%u:%d:%s:", nbits, algo, fpr+24);
 
   algo = gpgsm_get_key_algo_info (cert, &nbits);
   fprintf (fp, ":%u:%d:%s:", nbits, algo, fpr+24);
 
@@ -379,27 +419,12 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
   /* FPR record */
   fprintf (fp, "fpr:::::::::%s:::", fpr);
   /* Print chaining ID (field 13)*/
   /* FPR record */
   fprintf (fp, "fpr:::::::::%s:::", fpr);
   /* Print chaining ID (field 13)*/
-  {
-    ksba_cert_t next;
-    int rc;
-    
-    rc = gpgsm_walk_cert_chain (cert, &next);
-    if (!rc) /* We known the issuer's certificate. */
-      {
-        p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
-        fputs (p, fp);
-        xfree (p);
-        ksba_cert_release (next);
-      }
-    else if (rc == -1)  /* We reached the root certificate. */
-      {
-        fputs (fpr, fp);
-      }
-  }
+  if (chain_id)
+    fputs (chain_id, fp);
   putc (':', fp);
   putc ('\n', fp);
   putc (':', fp);
   putc ('\n', fp);
-  xfree (fpr); fpr = NULL;
-
+  xfree (fpr); fpr = NULL; chain_id = NULL;
+  xfree (chain_id_buffer); chain_id_buffer = NULL;
 
   if (opt.with_key_data)
     {
 
   if (opt.with_key_data)
     {