Support DSA2.
authorWerner Koch <wk@gnupg.org>
Wed, 12 Dec 2007 10:28:30 +0000 (10:28 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 12 Dec 2007 10:28:30 +0000 (10:28 +0000)
Support Camellia for testing.
More audit stuff.

34 files changed:
ChangeLog
NEWS
TODO
common/ChangeLog
common/asshelp.c
common/audit.c
common/audit.h
configure.ac
doc/help.de.txt
doc/help.txt
g10/ChangeLog
g10/encode.c
g10/encr-data.c
g10/gpg.c
g10/import.c
g10/keyedit.c
g10/main.h
g10/mainproc.c
g10/misc.c
g10/parse-packet.c
g10/pubkey-enc.c
g10/sign.c
include/ChangeLog
include/cipher.h
scd/ChangeLog
scd/app-openpgp.c
sm/ChangeLog
sm/call-agent.c
sm/call-dirmngr.c
sm/certchain.c
sm/encrypt.c
sm/gpgsm.c
sm/gpgsm.h
sm/server.c

index 48f36a3..9613806 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2007-12-12  Werner Koch  <wk@g10code.com>
+
+       * configure.ac (USE_CAMELLIA): Define by new option --enable-camellia.
+
 2007-12-03  Werner Koch  <wk@g10code.com>
 
        * configure.ac: Add test gt_LC_MESSAGES..
diff --git a/NEWS b/NEWS
index 87ea82f..e6fe5a9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,14 @@ Noteworthy changes in version 2.0.8
  * The envvars XAUTHORITY and PINENTRY_USER_DATA are now passed to the
    pinentry.
 
+ * Allow encryption using Elgamal keys with the algorithm id 20.
+
+ * Fixed the auto creation of the key stub for smartcards.  
+
+ * Fixed a rare bug in decryption using the OpenPGP card.
+
+ * Creating DSA2 keys is now possible.
+
 
 Noteworthy changes in version 2.0.7 (2007-09-10)
 ------------------------------------------------
diff --git a/TODO b/TODO
index 7eebe44..630e832 100644 (file)
--- a/TODO
+++ b/TODO
@@ -91,7 +91,7 @@
 ** issue a NO_SECKEY xxxx if a -u key was not found.
 
 
-* When switching to libgcrypt 1.3
+* When switching to libgcrypt 1.4
 ** scd#encode_md_for_card, g10#encode_md_value, sm@do_encode_md
    Remove the extra test for a valid algorithm as libgcrypt will do it
    then in gcry_md_algo_info.
index a9e3932..b6b12f9 100644 (file)
@@ -1,3 +1,9 @@
+2007-12-11  Werner Koch  <wk@g10code.com>
+
+       * asshelp.c (send_pinentry_environment): Allow using of old
+       gpg-agents not capabale of the xauthority and pinentry_user_data
+       options.
+
 2007-12-04  Werner Koch  <wk@g10code.com>
 
        * Makefile.am (t_helpfile_LDADD, module_maint_tests): New.
index 5aa61c7..8274d88 100644 (file)
@@ -172,6 +172,8 @@ send_pinentry_environment (assuan_context_t ctx,
     {
       err = send_one_option (ctx, errsource, "xauthority", 
                              opt_xauthority ? opt_xauthority : dft_xauthority);
+      if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
+        err = 0;
       if (err)
         return err;
     }
@@ -183,6 +185,8 @@ send_pinentry_environment (assuan_context_t ctx,
       err = send_one_option (ctx, errsource, "pinentry-user-data", 
                              opt_pinentry_user_data ?
                              opt_pinentry_user_data : dft_pinentry_user_data);
+      if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
+        err = 0;
       if (err)
         return err;
     }
index 40cbb82..59f881c 100644 (file)
@@ -449,9 +449,9 @@ writeout_li (audit_ctx_t ctx, const char *oktext, const char *format, ...)
 
   if (ctx->use_html && format && oktext)
     {
-      if (!strcmp (oktext, "OK") || !strcmp (oktext, "Yes"))
+      if (!strcmp (oktext, "Yes"))
         color = "green";
-      else if (!strcmp (oktext, "FAIL") || !strcmp (oktext, "No"))
+      else if (!strcmp (oktext, "No"))
         color = "red";
     }
 
@@ -648,53 +648,165 @@ get_cert_subject (ksba_cert_t cert, int idx)
 }
 
 
+/* List the given certificiate.  If CERT is NULL, this is a NOP.  */
+static void
+list_cert (audit_ctx_t ctx, ksba_cert_t cert, int with_subj)
+{
+  char *name;
+  int idx;
+
+  name = get_cert_name (cert);
+  writeout_rem (ctx, "%s", name);
+  xfree (name);
+  if (with_subj)
+    {
+      enter_li (ctx);
+      for (idx=0; (name = get_cert_subject (cert, idx)); idx++)
+        {
+          writeout_rem (ctx, "%s", name);
+          xfree (name);
+        }
+      leave_li (ctx);
+    }
+}
+
+
 /* List the chain of certificates from STARTITEM up to STOPEVENT.  The
    certifcates are written out as comments.  */
 static void
 list_certchain (audit_ctx_t ctx, log_item_t startitem, audit_event_t stopevent)
 {
   log_item_t item;
-  char *name;
-  int idx;
 
   startitem = find_next_log_item (ctx, startitem, AUDIT_CHAIN_BEGIN,stopevent);
+  writeout_li (ctx, startitem? "Yes":"No", _("Certificate chain available"));
   if (!startitem)
-    {
-      writeout_li (ctx, gpg_strerror (GPG_ERR_MISSING_CERT)
-                   , _("Certificate chain"));
-      return; 
-    }
-  writeout_li (ctx, "OK", _("Certificate chain"));
+    return; 
+
   item = find_next_log_item (ctx, startitem, 
                              AUDIT_CHAIN_ROOTCERT, AUDIT_CHAIN_END);
   if (!item)
     writeout_rem (ctx, "%s", _("root certificate missing"));
   else
     {
-      name = get_cert_name (item->cert);
-      writeout_rem (ctx, "%s", name);
-      xfree (name);
+      list_cert (ctx, item->cert, 0);
     }
   item = startitem;
   while ( ((item = find_next_log_item (ctx, item, 
                                        AUDIT_CHAIN_CERT, AUDIT_CHAIN_END))))
     {
-      name = get_cert_name (item->cert);
-      writeout_rem (ctx, "%s", name);
-      xfree (name);
-      enter_li (ctx);
-      for (idx=0; (name = get_cert_subject (item->cert, idx)); idx++)
+      list_cert (ctx, item->cert, 1);
+    }
+}
+
+
+\f
+/* Process an encrypt operation's log.  */
+static void
+proc_type_encrypt (audit_ctx_t ctx)
+{
+  log_item_t loopitem, item;
+  int recp_no, idx;
+  char numbuf[35];
+  int algo;
+  char *name;
+
+  item = find_log_item (ctx, AUDIT_ENCRYPTION_DONE, 0);
+  writeout_li (ctx, item?"Yes":"No", "%s", _("Data encryption succeeded"));
+
+  enter_li (ctx);
+
+  item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
+  writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
+
+  item = find_log_item (ctx, AUDIT_SESSION_KEY, 0);
+  writeout_li (ctx, item? "Yes":"No", "%s", _("Session key created"));
+  if (item)
+    {
+      algo = gcry_cipher_map_name (item->string);
+      if (algo)
+        writeout_rem (ctx, _("algorithm: %s"), gcry_cipher_algo_name (algo));
+      else if (item->string && !strcmp (item->string, "1.2.840.113549.3.2"))
+        writeout_rem (ctx, _("unsupported algorithm: %s"), "RC2");
+      else if (item->string)
+        writeout_rem (ctx, _("unsupported algorithm: %s"), item->string);
+      else
+        writeout_rem (ctx, _("seems to be not encrypted"));
+    }
+
+  item = find_log_item (ctx, AUDIT_GOT_RECIPIENTS, 0);
+  snprintf (numbuf, sizeof numbuf, "%d", 
+            item && item->have_intvalue? item->intvalue : 0);
+  writeout_li (ctx, numbuf, "%s", _("Number of recipients"));
+
+  /* Loop over all recipients.  */
+  loopitem = NULL;
+  recp_no = 0;
+  while ((loopitem=find_next_log_item (ctx, loopitem, AUDIT_ENCRYPTED_TO, 0)))
+    {
+      recp_no++;
+      writeout_li (ctx, NULL, _("Recipient %d"), recp_no);
+      if (loopitem->cert)
         {
+          name = get_cert_name (loopitem->cert);
           writeout_rem (ctx, "%s", name);
           xfree (name);
+          enter_li (ctx);
+          for (idx=0; (name = get_cert_subject (loopitem->cert, idx)); idx++)
+            {
+              writeout_rem (ctx, "%s", name);
+              xfree (name);
+            }
+          leave_li (ctx);
         }
-      leave_li (ctx);
     }
+
+  leave_li (ctx);
+}
+
+
+\f
+/* Process a sign operation's log.  */
+static void
+proc_type_sign (audit_ctx_t ctx)
+{
+  log_item_t item;
+
+  item = NULL;
+  writeout_li (ctx, item?"Yes":"No", "%s", _("Data signing succeeded"));
+
+  enter_li (ctx);
+
+  item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
+  writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
+
+
+  leave_li (ctx);
 }
 
 
 \f
-/* Process a verification operation.  */
+/* Process a decrypt operation's log.  */
+static void
+proc_type_decrypt (audit_ctx_t ctx)
+{
+  log_item_t item;
+
+  item = NULL;
+  writeout_li (ctx, item?"Yes":"No", "%s", _("Data decryption succeeded"));
+
+  enter_li (ctx);
+
+  item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
+  writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
+
+
+  leave_li (ctx);
+}
+
+
+\f
+/* Process a verification operation's log.  */
 static void
 proc_type_verify (audit_ctx_t ctx)
 {
@@ -702,14 +814,13 @@ proc_type_verify (audit_ctx_t ctx)
   int signo, count, idx;
   char numbuf[35];
 
-  enter_li (ctx);
-  
-  writeout_li (ctx, "fixme", "%s", _("Signature verification"));
+  /* If there is at least one signature status we claim that the
+     verifciation succeeded.  This does not mean that the data has
+     verified okay.  */
+  item = find_log_item (ctx, AUDIT_SIG_STATUS, 0);
+  writeout_li (ctx, item?"Yes":"No", "%s", _("Data verification succeeded"));
   enter_li (ctx);
 
-  writeout_li (ctx, "fixme", "%s", _("Gpg-Agent ready"));
-  writeout_li (ctx, "fixme", "%s", _("Dirmngr ready"));
-
   item = find_log_item (ctx, AUDIT_GOT_DATA, AUDIT_NEW_SIG);
   writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
   if (!item)
@@ -721,19 +832,14 @@ proc_type_verify (audit_ctx_t ctx)
     goto leave;
 
   item = find_log_item (ctx, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG);
-  if (item)
-    writeout_li (ctx, "OK", "%s", _("Parsing signature"));
-  else 
+  writeout_li (ctx, item?"Yes":"No", "%s", _("Parsing signature succeeded"));
+  if (!item)
     {
       item = find_log_item (ctx, AUDIT_BAD_DATA_HASH_ALGO, AUDIT_NEW_SIG);
       if (item)
-        {
-          writeout_li (ctx,"FAIL", "%s",  _("Parsing signature"));
-          writeout_rem (ctx, _("Bad hash algorithm: %s"), 
-                        item->string? item->string:"?");
-        }
-      else
-        writeout_li (ctx, "FAIL", "%s", _("Parsing signature") );
+        writeout_rem (ctx, _("Bad hash algorithm: %s"), 
+                      item->string? item->string:"?");
+
       goto leave;
     }
 
@@ -761,19 +867,30 @@ proc_type_verify (audit_ctx_t ctx)
                                  AUDIT_CHAIN_STATUS, AUDIT_NEW_SIG);
       if (item && item->have_err)
         {
-          writeout_li (ctx, item->err? "FAIL":"OK", 
-                       _("Validation of certificate chain"));
+          writeout_li (ctx, item->err? "No":"Yes", 
+                       _("Certificate chain valid"));
           if (item->err)
             writeout_rem (ctx, "%s", gpg_strerror (item->err));
         }
       
       /* Show whether the root certificate is fine.  */
-      writeout_li (ctx, "No", "%s", _("Root certificate trustworthy"));
-      add_helptag (ctx, "gpgsm.root-cert-not-trusted");
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_ROOT_TRUSTED, AUDIT_CHAIN_STATUS);
+      if (item)
+        {
+          writeout_li (ctx, item->err?"No":"Yes", "%s",
+                       _("Root certificate trustworthy"));
+          if (item->err)
+            {
+              add_helptag (ctx, "gpgsm.root-cert-not-trusted");
+              writeout_rem (ctx, "%s", gpg_strerror (item->err));
+              list_cert (ctx, item->cert, 0);
+            }
+        }
 
       /* Show result of the CRL/OCSP check.  */
       writeout_li (ctx, "-", "%s", _("CRL/OCSP check of certificates"));
-      add_helptag (ctx, "gpgsm.ocsp-problem");
+ /*      add_helptag (ctx, "gpgsm.ocsp-problem"); */
 
 
       leave_li (ctx);
@@ -805,8 +922,6 @@ proc_type_verify (audit_ctx_t ctx)
         }
       leave_li (ctx);
     }
-
-  leave_li (ctx);
   leave_li (ctx);
 }
 
@@ -818,16 +933,24 @@ void
 audit_print_result (audit_ctx_t ctx, estream_t out, int use_html)
 {
   int idx;
-  int maxlen;
   size_t n;
+  log_item_t item;
   helptag_t helptag;
-
-  if (getenv ("use_html"))
-    use_html = 1;
-
+  const char *s;
+  int show_raw = 0;
+  
   if (!ctx)
     return;
 
+  /* We use an environment variable to include some debug info in the
+     log.  */
+  if ((s = getenv ("gnupg_debug_audit")))
+    {
+      show_raw = 1;
+      if (!strcmp (s, "html"))
+        use_html = 1;
+    }
+
   assert (!ctx->outstream);
   ctx->outstream = out;
   ctx->use_html = use_html;
@@ -843,51 +966,87 @@ audit_print_result (audit_ctx_t ctx, estream_t out, int use_html)
       goto leave;
     }
 
-  for (idx=0,maxlen=0; idx < DIM (eventstr_msgidx); idx++)
+  if (show_raw)
     {
-      n = strlen (eventstr_msgstr + eventstr_msgidx[idx]);    
-      if (n > maxlen)
-        maxlen = n;
-    }
+      int maxlen;
 
-  if (use_html)
-    es_fputs ("<pre>\n", out);
-  for (idx=0; idx < ctx->logused; idx++)
-    {
-      es_fprintf (out, "log: %-*s", 
-                  maxlen, event2str (ctx->log[idx].event));
-      if (ctx->log[idx].have_intvalue)
-        es_fprintf (out, " i=%d", ctx->log[idx].intvalue); 
-      if (ctx->log[idx].string)
+      for (idx=0,maxlen=0; idx < DIM (eventstr_msgidx); idx++)
         {
-          es_fputs (" s=`", out); 
-          writeout (ctx, ctx->log[idx].string); 
-          es_fputs ("'", out); 
+          n = strlen (eventstr_msgstr + eventstr_msgidx[idx]);    
+          if (n > maxlen)
+            maxlen = n;
         }
-      if (ctx->log[idx].cert)
-        es_fprintf (out, " has_cert"); 
-      if (ctx->log[idx].have_err)
+      
+      if (use_html)
+        es_fputs ("<pre>\n", out);
+      for (idx=0; idx < ctx->logused; idx++)
         {
-          es_fputs (" err=`", out);
-          writeout (ctx, gpg_strerror (ctx->log[idx].err)); 
-          es_fputs ("'", out);
+          es_fprintf (out, "log: %-*s", 
+                      maxlen, event2str (ctx->log[idx].event));
+          if (ctx->log[idx].have_intvalue)
+            es_fprintf (out, " i=%d", ctx->log[idx].intvalue); 
+          if (ctx->log[idx].string)
+            {
+              es_fputs (" s=`", out); 
+              writeout (ctx, ctx->log[idx].string); 
+              es_fputs ("'", out); 
+            }
+          if (ctx->log[idx].cert)
+            es_fprintf (out, " has_cert"); 
+          if (ctx->log[idx].have_err)
+            {
+              es_fputs (" err=`", out);
+              writeout (ctx, gpg_strerror (ctx->log[idx].err)); 
+              es_fputs ("'", out);
+            }
+          es_fputs ("\n", out);
         }
-      es_fputs ("\n", out);
+      if (use_html)
+        es_fputs ("</pre>\n", out);
+      else
+        es_fputs ("\n", out);
     }
-  if (use_html)
-    es_fputs ("</pre>\n", out);
-  else
-    es_fputs ("\n", out);
 
+  enter_li (ctx);
   switch (ctx->type)
     {
     case AUDIT_TYPE_NONE:
-      writeout_para (ctx, _("Audit of this operation is not supported."));
+      writeout_li (ctx, NULL, _("Unknown operation"));
+      break;
+    case AUDIT_TYPE_ENCRYPT:
+      proc_type_encrypt (ctx);
+      break;
+    case AUDIT_TYPE_SIGN:
+      proc_type_sign (ctx);
+      break;
+    case AUDIT_TYPE_DECRYPT:
+      proc_type_decrypt (ctx);
       break;
     case AUDIT_TYPE_VERIFY:
       proc_type_verify (ctx);
       break;
     }
+  item = find_log_item (ctx, AUDIT_AGENT_READY, 0);
+  if (item && item->have_err)
+    {
+      writeout_li (ctx, item->err? "No":"Yes", "%s", _("Gpg-Agent usable"));
+      if (item->err)
+        {
+          writeout_rem (ctx, "%s", gpg_strerror (item->err));
+          add_helptag (ctx, "gnupg.agent-problem");
+        }
+    }
+  item = find_log_item (ctx, AUDIT_DIRMNGR_READY, 0);
+  if (item && item->have_err)
+    {
+      writeout_li (ctx, item->err? "No":"Yes", "%s", _("Dirmngr usable"));
+      if (item->err)
+        {
+          writeout_rem (ctx, "%s", gpg_strerror (item->err));
+          add_helptag (ctx, "gnupg.dirmngr-problem");
+        }
+    }
+  leave_li (ctx);
 
 
   /* Show the help from the collected help tags.  */
index 514ef12..85c2ffc 100644 (file)
@@ -31,6 +31,9 @@ typedef struct audit_ctx_s *audit_ctx_t;
 typedef enum
   {
     AUDIT_TYPE_NONE  = 0,  /* No type set.  */
+    AUDIT_TYPE_ENCRYPT,    /* Data encryption.  */
+    AUDIT_TYPE_SIGN,       /* Signature creation.  */
+    AUDIT_TYPE_DECRYPT,    /* Data decryption.  */
     AUDIT_TYPE_VERIFY      /* Signature verification.  */
   }
 audit_type_t;
@@ -49,6 +52,16 @@ typedef enum
        now.  This indicates that all parameters are okay and we can
        start to process the actual data.  */
 
+    AUDIT_AGENT_READY,   /* err */
+    /* Indicates whether the gpg-agent is available.  For some
+       operations the agent is not required and thus no such event
+       will be logged.  */
+    
+    AUDIT_DIRMNGR_READY,   /* err */
+    /* Indicates whether the Dirmngr is available.  For some
+       operations the Dirmngr is not required and thus no such event
+       will be logged.  */
+
     AUDIT_GOT_DATA,
     /* Data to be processed has been seen.  */
 
@@ -122,6 +135,28 @@ typedef enum
     AUDIT_CHAIN_STATUS,  /* err */
     /* Tells the final status of the chain validation.  */
 
+    AUDIT_ROOT_TRUSTED,  /* cert, err */
+    /* Tells whether the root certificate is trusted.  This event is
+       emmited durcing chain validation.  */
+
+    AUDIT_GOT_RECIPIENTS,  /* int */
+    /* Records the number of recipients to be used for encryption.
+       This includes the recipients set by --encrypt-to but records 0
+       if no real recipient has been given.  */
+
+    AUDIT_SESSION_KEY,     /* string */
+    /* Mark the creation or availibility of the session key.  The
+       parameter is the algorithm ID.  */
+
+    AUDIT_ENCRYPTED_TO,   /* cert, err */
+    /* Records the certificate used for encryption and whether the
+       session key could be encrypted to it (err==0).  */
+
+    AUDIT_ENCRYPTION_DONE,
+    /* Encryption succeeded.  */
+
+    
+
 
     AUDIT_LAST_EVENT  /* Marker for parsing this list.  */
   }
index 13714da..9590544 100644 (file)
@@ -73,6 +73,7 @@ have_libusb=no
 use_bzip2=yes
 use_exec=yes
 disable_keyserver_path=no
+use_camellia=no
 
 
 GNUPG_BUILD_PROGRAM(gpg, yes)
@@ -172,6 +173,21 @@ AC_ARG_ENABLE(bzip2,
    use_bzip2=$enableval)
 AC_MSG_RESULT($use_bzip2)
 
+# Check whether testing support for Camellia has been requested
+AC_MSG_CHECKING([whether to enable the CAMELLIA cipher for gpg])
+AC_ARG_ENABLE(camellia,
+   AC_HELP_STRING([--enable-camellia],[enable the CAMELLIA cipher for gpg]),
+   use_camellia=$enableval)
+AC_MSG_RESULT($use_camellia)
+if test x"$use_camellia" = xyes ; then
+   AC_DEFINE(USE_CAMELLIA,1,[Define to include the CAMELLIA cipher into gpg])
+   AC_MSG_WARN([[
+***
+*** The Camellia cipher for gpg is for testing only and 
+*** is NOT for production use!
+***]])
+fi
+
 
 # Configure option to allow or disallow execution of external
 # programs, like a photo viewer.
@@ -1417,4 +1433,10 @@ echo "
                  gpg-check-pattern will not be build.
 "
 fi
+if test  x"$use_camellia" = xyes ; then
+  echo
+  echo "WARNING: The Camellia cipher for gpg is for testing only"
+  echo "         and is NOT for production use!"
+  echo
+fi
 
index 0518c38..4d8236e 100644 (file)
@@ -272,6 +272,6 @@ Eine Leerzeile beendet die Eingabe.
 
 
 # Local variables:
-# mode: fundamental
+# mode: default-generic
 # coding: utf-8
 # End:
index afaaa29..4b8ec62 100644 (file)
@@ -52,6 +52,44 @@ configured passphrase constraints.
 .
 
 
+.gnupg.agent-problem
+# There was a problem accessing or starting the agent.
+It was either not possible to connect to a running Gpg-Agent or a
+communication problem with a running agent occurred.  
+
+The system uses a background process, called Gpg-Agent, for processing
+private keys and to ask for passphrases.  The agent is usually started
+when the user logs in and runs as long the user is logged in. In case
+that no agent is available, the system tries to start one on the fly
+but that version of the agent is somewhat limited in functionality and
+thus may lead to little problems.
+
+You probably need to ask your administrator on how to solve the
+problem.  As a workaround you might try to log out and in to your
+session and see whether this helps.  If this helps please tell the
+administrator anyway because this indicates a bug in the software.
+.
+
+
+.gnupg.dirmngr-problem
+# There was a problen accessing the dirmngr.
+It was either not possible to connect to a running Dirmngr or a
+communication problem with a running Dirmngr occurred.  
+
+To lookup certificate revocation lists (CRLs), performing OCSP
+validation and to lookup keys through LDAP servers, the system uses an
+external service program named Dirmngr.  The Dirmngr is usually running
+as a system service (daemon) and does not need any attention by the
+user.  In case of problems the system might start its own copy of the
+Dirmngr on a per request base; this is a workaround and yields limited
+performance.
+
+If you encounter this problem, you should ask your system
+administrator how to proceed.  As an interim solution you may try to
+disable CRL checking in gpgsm's configuration.
+.
+
+
 .gpg.edit_ownertrust.value
 # The help identies prefixed with "gpg." used to be hard coded in gpg
 # but may now be overridden by help texts from this file.
@@ -312,6 +350,6 @@ your system administrator whether you should trust this certificate.
 
 
 # Local variables:
-# mode: fundamental
+# mode: default-generic
 # coding: utf-8
 # End:
index f6019a4..9e6602c 100644 (file)
@@ -1,6 +1,30 @@
+2007-12-12  Werner Koch  <wk@g10code.com>
+
+       * misc.c (map_cipher_openpgp_to_gcry): New.  Used to map Camellia
+       algorithms to Gcrypt.
+       (openpgp_cipher_test_algo): Call new map function.  Replace
+       all remaining calls to gcry_cipher_test_algo by a call to this.
+       (openpgp_cipher_algo_name): New.  Replace all remaining calls to
+       gcry_cipher_algo_name by a call to this.
+       (map_cipher_gcry_to_openpgp): New.
+       (string_to_cipher_algo): Use it.
+       * gpg.c (main): Print a warning if Camellia support is build in.
+       
+       * gpg.c (print_algo_names): New.  From the 1.4 branch by David.
+       (list_config): Use it here for the "ciphername" and "digestname"
+       config items so we can get a script-parseable list of the names.
+
+       * parse-packet.c (parse_onepass_sig): Sigclass is hex, so include
+       the 0x.
+
+       * sign.c (match_dsa_hash): Remove conditional builds dending on
+       USE_SHAxxx.  We don't need this becuase it can be expected that
+       libgcrypt provides it.  However we need to runtime test for SHA244
+       becuase that is only available with libgcrypt 2.4.
+
 2007-12-11  Werner Koch  <wk@g10code.com>
 
-       * mainproc.c (proc_pubkey_enc): Allo type 20 Elgamal key for
+       * mainproc.c (proc_pubkey_enc): Allow type 20 Elgamal key for
        decryption.
 
 2007-12-10  Werner Koch  <wk@g10code.com>
index ee2ce97..92aa9b2 100644 (file)
@@ -244,7 +244,7 @@ encode_simple( const char *filename, int mode, int use_seskey )
 
        if(opt.verbose)
          log_info(_("using cipher %s\n"),
-                  gcry_cipher_algo_name (cfx.dek->algo));
+                  openpgp_cipher_algo_name (cfx.dek->algo));
 
        cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
     }
@@ -558,7 +558,7 @@ encode_crypt( const char *filename, strlist_t remusr, int use_symkey )
                                opt.def_cipher_algo,NULL)!=opt.def_cipher_algo)
        log_info(_("WARNING: forcing symmetric cipher %s (%d)"
                   " violates recipient preferences\n"),
-                gcry_cipher_algo_name (opt.def_cipher_algo),
+                openpgp_cipher_algo_name (opt.def_cipher_algo),
                 opt.def_cipher_algo);
 
       cfx.dek->algo = opt.def_cipher_algo;
@@ -750,7 +750,7 @@ encrypt_filter( void *opaque, int control,
                                        NULL)!=opt.def_cipher_algo)
                log_info(_("forcing symmetric cipher %s (%d) "
                           "violates recipient preferences\n"),
-                        gcry_cipher_algo_name (opt.def_cipher_algo),
+                        openpgp_cipher_algo_name (opt.def_cipher_algo),
                         opt.def_cipher_algo);
 
              efx->cfx.dek->algo = opt.def_cipher_algo;
@@ -847,7 +847,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
                char *ustr = get_user_id_string_native (enc->keyid);
                log_info(_("%s/%s encrypted for: \"%s\"\n"),
                          gcry_pk_algo_name (enc->pubkey_algo),
-                         gcry_cipher_algo_name (dek->algo),
+                         openpgp_cipher_algo_name (dek->algo),
                          ustr );
                xfree(ustr);
            }
index a05ff46..56d787c 100644 (file)
@@ -88,8 +88,9 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
 
   if ( opt.verbose && !dek->algo_info_printed )
     {
-      if (!gcry_cipher_test_algo (dek->algo))
-        log_info (_("%s encrypted data\n"), gcry_cipher_algo_name (dek->algo));
+      if (!openpgp_cipher_test_algo (dek->algo))
+        log_info (_("%s encrypted data\n"), 
+                  openpgp_cipher_algo_name (dek->algo));
       else
         log_info (_("encrypted with unknown algorithm %d\n"), dek->algo );
       dek->algo_info_printed = 1;
index 38b5fad..75d44f6 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -791,7 +791,7 @@ my_strusage( int level )
       case 35:
        if( !ciphers )
            ciphers = build_list(_("Cipher: "), 'S', 
-                                 gcry_cipher_algo_name,
+                                 openpgp_cipher_algo_name,
                                  openpgp_cipher_test_algo );
        p = ciphers;
        break;
@@ -1384,6 +1384,24 @@ print_algo_numbers(int (*checker)(int))
 }
 
 
+static void
+print_algo_names(int (*checker)(int),const char *(*mapper)(int))
+{
+  int i,first=1;
+
+  for(i=0;i<=110;i++)
+    {
+      if(!checker(i))
+       {
+         if(first)
+           first=0;
+         else
+           printf(";");
+         printf("%s",mapper(i));
+       }
+    }
+}
+
 /* In the future, we can do all sorts of interesting configuration
    output here.  For now, just give "group" as the Enigmail folks need
    it, and pubkey, cipher, hash, and compress as they may be useful
@@ -1450,6 +1468,14 @@ list_config(char *items)
          any=1;
        }
 
+      if (show_all || !ascii_strcasecmp (name,"ciphername"))
+       {
+         printf ("cfg:ciphername:");
+         print_algo_names (openpgp_cipher_test_algo,openpgp_cipher_algo_name);
+         printf ("\n");
+         any = 1;
+       }
+
       if(show_all
         || ascii_strcasecmp(name,"digest")==0
         || ascii_strcasecmp(name,"hash")==0)
@@ -1460,6 +1486,16 @@ list_config(char *items)
          any=1;
        }
 
+      if (show_all
+          || !ascii_strcasecmp(name,"digestname")
+          || !ascii_strcasecmp(name,"hashname"))
+       {
+         printf ("cfg:digestname:");
+         print_algo_names (openpgp_md_test_algo, gcry_md_algo_name);
+         printf("\n");
+         any=1;
+       }
+      
       if(show_all || ascii_strcasecmp(name,"compress")==0)
        {
          printf("cfg:compress:");
@@ -2864,6 +2900,15 @@ main (int argc, char **argv )
         log_set_prefix (NULL, 1|2|4);
       }
 
+#ifdef USE_CAMELLIA    
+    /* We better also print a runtime warning if people build it with
+       support for Camellia (which is not yet defined by OpenPGP). */
+    log_info ("WARNING: This version has been built with support for the "
+              "Camellia cipher.\n");
+    log_info ("         It is for testing only and is NOT for production "
+              "use!\n");
+#endif
+
     if (opt.verbose > 2)
         log_info ("using character set `%s'\n", get_native_charset ());
 
@@ -3129,7 +3174,7 @@ main (int argc, char **argv )
        if(opt.def_cipher_algo
           && !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL))
          {
-           badalg = gcry_cipher_algo_name (opt.def_cipher_algo);
+           badalg = openpgp_cipher_algo_name (opt.def_cipher_algo);
            badtype = PREFTYPE_SYM;
          }
        else if(opt.def_digest_algo
index 66aa875..41198b6 100644 (file)
@@ -602,9 +602,9 @@ check_prefs(KBNODE keyblock)
                  if (openpgp_cipher_test_algo (prefs->value))
                    {
                      const char *algo = 
-                        (gcry_cipher_test_algo (prefs->value)
+                        (openpgp_cipher_test_algo (prefs->value)
                          ? num 
-                         : gcry_cipher_algo_name (prefs->value));
+                         : openpgp_cipher_algo_name (prefs->value));
                      if(!problem)
                        check_prefs_warning(pk);
                      log_info(_("         \"%s\": preference for cipher"
index 8efe824..c81594b 100644 (file)
@@ -2325,9 +2325,10 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose)
                     tty_printf (", ");
                 any = 1;
                 /* We don't want to display strings for experimental algos */
-                if (!gcry_cipher_test_algo (prefs[i].value)
+                if (!openpgp_cipher_test_algo (prefs[i].value)
                     && prefs[i].value < 100 )
-                    tty_printf ("%s", gcry_cipher_algo_name (prefs[i].value));
+                    tty_printf ("%s",
+                                openpgp_cipher_algo_name (prefs[i].value));
                 else
                     tty_printf ("[%d]", prefs[i].value);
                 if (prefs[i].value == CIPHER_ALGO_3DES )
@@ -2337,7 +2338,7 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose)
         if (!des_seen) {
             if (any)
                 tty_printf (", ");
-            tty_printf ("%s", gcry_cipher_algo_name (CIPHER_ALGO_3DES));
+            tty_printf ("%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
         }
         tty_printf ("\n     ");
        tty_printf (_("Digest: "));
index 9633870..bf3df64 100644 (file)
@@ -83,6 +83,7 @@ u16 checksum_mpi( gcry_mpi_t a );
 u32 buffer_to_u32( const byte *buffer );
 const byte *get_session_marker( size_t *rlen );
 int openpgp_cipher_test_algo( int algo );
+const char *openpgp_cipher_algo_name (int algo);
 int openpgp_pk_test_algo( int algo );
 int openpgp_pk_test_algo2 ( int algo, unsigned int use );
 int openpgp_pk_algo_usage ( int algo );
index 10d665b..3756e2f 100644 (file)
@@ -274,9 +274,9 @@ proc_symkey_enc( CTX c, PACKET *pkt )
     else if(!c->dek)
       {
         int algo = enc->cipher_algo;
-       const char *s = gcry_cipher_algo_name (algo);
+       const char *s = openpgp_cipher_algo_name (algo);
 
-       if (!gcry_cipher_test_algo (algo))
+       if (!openpgp_cipher_test_algo (algo))
          {
            if(!opt.quiet)
              {
@@ -524,8 +524,8 @@ proc_encrypted( CTX c, PACKET *pkt )
            algo = opt.def_cipher_algo;
            if ( algo )
              log_info (_("assuming %s encrypted data\n"),
-                        gcry_cipher_algo_name (algo));
-           else if ( gcry_cipher_test_algo (CIPHER_ALGO_IDEA) )
+                        openpgp_cipher_algo_name (algo));
+           else if ( openpgp_cipher_test_algo (CIPHER_ALGO_IDEA) )
              {
                algo = opt.def_cipher_algo;
                if (!algo)
@@ -533,7 +533,7 @@ proc_encrypted( CTX c, PACKET *pkt )
                idea_cipher_warn(1);
                log_info (_("IDEA cipher unavailable, "
                            "optimistically attempting to use %s instead\n"),
-                         gcry_cipher_algo_name (algo));
+                         openpgp_cipher_algo_name (algo));
              }
            else
              {
index 5f9af54..fa85e61 100644 (file)
@@ -301,7 +301,7 @@ print_cipher_algo_note( int algo )
        {
          warn=1;
          log_info (_("WARNING: using experimental cipher algorithm %s\n"),
-                    gcry_cipher_algo_name (algo));
+                    openpgp_cipher_algo_name (algo));
        }
     }
 }
@@ -324,6 +324,33 @@ print_digest_algo_note( int algo )
               gcry_md_algo_name (algo));
 }
 
+
+/* Map OpenPGP algo numbers to those used by Libgcrypt.  We need to do
+   this for algorithms we implemented in Libgcrypt after they become
+   part of OpenPGP.  */
+static int
+map_cipher_openpgp_to_gcry (int algo)
+{
+  switch (algo)
+    {
+    case CIPHER_ALGO_CAMELLIA128: return 310; 
+    case CIPHER_ALGO_CAMELLIA256: return 312; 
+    default: return algo;
+    }
+}
+
+/* The inverse fucntion of above.  */
+static int
+map_cipher_gcry_to_openpgp (int algo)
+{
+  switch (algo)
+    {
+    case 310: return CIPHER_ALGO_CAMELLIA128;
+    case 312: return CIPHER_ALGO_CAMELLIA256;
+    default: return algo;
+    }
+}
+
 /****************
  * Wrapper around the libgcrypt function with additonal checks on
  * the OpenPGP contraints for the algo ID.
@@ -331,12 +358,32 @@ print_digest_algo_note( int algo )
 int
 openpgp_cipher_test_algo( int algo )
 {
-  /* 5 and 6 are marked reserved by rfc2440bis.  */
+  /* (5 and 6 are marked reserved by rfc4880.)  */
   if ( algo < 0 || algo > 110 || algo == 5 || algo == 6 )
     return gpg_error (GPG_ERR_CIPHER_ALGO);
-  return gcry_cipher_test_algo (algo);
+
+  /* Camellia is not yet defined for OpenPGP thus only allow it if
+     requested.  */
+#ifndef USE_CAMELLIA
+  if (algo == CIPHER_ALGO_CAMELLIA128 
+       || algo == CIPHER_ALGO_CAMELLIA256)
+    return gpg_error (GPG_ERR_CIPHER_ALGO);
+#endif
+
+  return gcry_cipher_test_algo (map_cipher_openpgp_to_gcry (algo));
 }
 
+/* Map the OpenPGP cipher algorithm whose ID is contained in ALGORITHM to a
+   string representation of the algorithm name.  For unknown algorithm
+   IDs this function returns "?".  */
+const char *
+openpgp_cipher_algo_name (int algo) 
+{
+  return gcry_cipher_algo_name (map_cipher_openpgp_to_gcry (algo));
+}
+
+
+
 int
 openpgp_pk_test_algo( int algo )
 {
@@ -690,7 +737,7 @@ string_to_cipher_algo (const char *string)
 { 
   int val;
 
-  val = gcry_cipher_map_name (string);
+  val = map_cipher_gcry_to_openpgp (gcry_cipher_map_name (string));
   if (!val && string && (string[0]=='S' || string[0]=='s'))
     {
       char *endptr;
index b1b01e5..6b8e79e 100644 (file)
@@ -1588,8 +1588,10 @@ parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
     ops->keyid[1] = read_32(inp); pktlen -= 4;
     ops->last = iobuf_get_noeof(inp); pktlen--;
     if( list_mode )
-       fprintf (listfp, ":onepass_sig packet: keyid %08lX%08lX\n"
-              "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
+       fprintf (listfp,
+                 ":onepass_sig packet: keyid %08lX%08lX\n"
+                 "\tversion %d, sigclass 0x%02x, digest %d, pubkey %d, "
+                 "last=%d\n",
                (ulong)ops->keyid[0], (ulong)ops->keyid[1],
                version, ops->sig_class,
                ops->digest_algo, ops->pubkey_algo, ops->last );
index e0ae55f..b7e76a8 100644 (file)
@@ -282,7 +282,7 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
                && !opt.quiet
                && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ))
          log_info (_("WARNING: cipher algorithm %s not found in recipient"
-                      " preferences\n"), gcry_cipher_algo_name (dek->algo));
+                      " preferences\n"), openpgp_cipher_algo_name (dek->algo));
         if (!rc) {
             KBNODE k;
             
index 6bb30f0..022622b 100644 (file)
@@ -345,22 +345,24 @@ match_dsa_hash (unsigned int qbytes)
 {
   if (qbytes <= 20)
     return DIGEST_ALGO_SHA1;
-#ifdef USE_SHA256
-  if (qbytes <= 28)
+
+  /* SHA244 is only available with libgcrypt 1.4 - thus do a runtime
+     test.  */
+  if (qbytes <= 28 && !gcry_md_test_algo (DIGEST_ALGO_SHA224))
     return DIGEST_ALGO_SHA224;
+
   if (qbytes <= 32)
     return DIGEST_ALGO_SHA256;
-#endif
 
-#ifdef USE_SHA512
   if (qbytes <= 48)
     return DIGEST_ALGO_SHA384;
+
   if (qbytes <= 64)
     return DIGEST_ALGO_SHA512;
-#endif
+
   return DEFAULT_DIGEST_ALGO;
   /* DEFAULT_DIGEST_ALGO will certainly fail, but it's the best wrong
-     answer we have if the larger SHAs aren't there. */
+     answer we have if a digest larger than 512 bits is requested.  */
 }
 
 
@@ -1258,7 +1260,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
     algo = default_cipher_algo();
     if (!opt.quiet || !opt.batch)
         log_info (_("%s encryption will be used\n"),
-                  gcry_cipher_algo_name (algo) );
+                  openpgp_cipher_algo_name (algo) );
     cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, &canceled);
 
     if (!cfx.dek || !cfx.dek->keylen) {
index 344ae65..b4362be 100644 (file)
@@ -1,3 +1,7 @@
+2007-12-12  Werner Koch  <wk@g10code.com>
+
+       * cipher.h (CIPHER_ALGO_CAMELLIA128, CIPHER_ALGO_CAMELLIA256): New.
+
 2006-09-20  Werner Koch  <wk@g10code.com>
 
        * errors.h, http.h, memory.h, mpi.h, util.h, i18n.h: Removed.
index 9d2471a..52c4f27 100644 (file)
@@ -1,5 +1,6 @@
 /* cipher.h - Definitions for OpenPGP 
- * Copyright (C) 1998, 1999, 2000, 2001, 2006 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2006,
+ *               2007  Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -44,6 +45,9 @@
 #define CIPHER_ALGO_RIJNDAEL192  CIPHER_ALGO_AES192
 #define CIPHER_ALGO_RIJNDAEL256  CIPHER_ALGO_AES256
 #define CIPHER_ALGO_TWOFISH     /* 10 */  GCRY_CIPHER_TWOFISH  /* 256 bit */
+/* Note: Camellia ids don't match those used by libgcrypt. */
+#define CIPHER_ALGO_CAMELLIA128     11
+#define CIPHER_ALGO_CAMELLIA256     12
 #define CIPHER_ALGO_DUMMY          110    /* No encryption at all. */
 
 #define PUBKEY_ALGO_RSA          /*  1 */ GCRY_PK_RSA  
@@ -66,8 +70,8 @@
 #define DIGEST_ALGO_SHA256    /*  8 */ GCRY_MD_SHA256
 #define DIGEST_ALGO_SHA384    /*  9 */ GCRY_MD_SHA384
 #define DIGEST_ALGO_SHA512    /* 10 */ GCRY_MD_SHA512
-/* SHA224 is as of now only defined in the libgcrypt SVN; thus we
-   can't use that macro.  */
+/* SHA224 is only available in libgcrypt 1.4.0; thus we
+   can't use the GCRY macro here.  */
 #define DIGEST_ALGO_SHA224    /* 11 */ 11 /* GCRY_MD_SHA224 */
 
 #define COMPRESS_ALGO_NONE 0
index 166f308..51db189 100644 (file)
@@ -1,6 +1,6 @@
 2007-12-10  Werner Koch  <wk@g10code.com>
 
-       * app-openpgp.c (do_decipher): Take care of cryptograms shiorther
+       * app-openpgp.c (do_decipher): Take care of cryptograms shorter
        that 128 bytes.  Fixes bug#851.
 
 2007-11-14  Werner Koch  <wk@g10code.com>
index 5cfec04..e26a31e 100644 (file)
@@ -2461,7 +2461,7 @@ do_decipher (app_t app, const char *keyidstr,
 
       /* We might encounter a couple of leading zeroes in the
          cryptogram.  Due to internal use of MPIs thease leading
-         zeroes are stripped.  However the OpenPGp card expects
+         zeroes are stripped.  However the OpenPGP card expects
          exactly 128 bytes for the cryptogram (for a 1k key).  Thus we
          need to fix it up.  We do this for up to 16 leading zero
          bytes; a cryptogram with more than this is with a very high
index 5f03b86..49ed506 100644 (file)
@@ -1,3 +1,20 @@
+2007-12-11  Werner Koch  <wk@g10code.com>
+
+       * certchain.c (do_validate_chain): Log AUDIT_ROOT_TRUSTED.
+
+       * server.c (cmd_sign, cmd_decrypt, cmd_encrypt): Start audit log.
+       (cmd_recipient): Start audit session.
+
+       * gpgsm.c (main): Revamp creation of the audit log.
+
+       * gpgsm.h (struct server_control_s): Add AGENT_SEEN and DIRMNGR_SEEN.
+       * call-agent.c (start_agent): Record an audit event.
+       * call-dirmngr.c (start_dirmngr): Ditto. Add new arg CTRL and pass
+       it from all callers.
+       (prepare_dirmngr): New helper for start_dirmngr.
+
+       * encrypt.c (gpgsm_encrypt): Add calls to audit_log.
+
 2007-12-03  Werner Koch  <wk@g10code.com>
 
        * gpgsm.c (main): All gnupg_reopen_std.
index 3f4e11e..af35ac5 100644 (file)
@@ -1,5 +1,6 @@
 /* call-agent.c - divert operations to the agent
- *     Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2005,
+ *               2007 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -69,13 +70,14 @@ struct learn_parm_s
 static int
 start_agent (ctrl_t ctrl)
 {
-  if (agent_ctx)
-    return 0; /* fixme: We need a context for each thread or serialize
-                 the access to the agent (which is suitable given that
-                 the agent is not MT. */
-
+  int rc;
 
-  return start_new_gpg_agent (&agent_ctx,
+  if (agent_ctx)
+    rc = 0;      /* fixme: We need a context for each thread or
+                    serialize the access to the agent (which is
+                    suitable given that the agent is not MT. */
+  else
+    rc = start_new_gpg_agent (&agent_ctx,
                               GPG_ERR_SOURCE_DEFAULT,
                               opt.homedir,
                               opt.agent_program,
@@ -84,7 +86,13 @@ start_agent (ctrl_t ctrl)
                               opt.xauthority, opt.pinentry_user_data,
                               opt.verbose, DBG_ASSUAN,
                               gpgsm_status2, ctrl);
+  if (!ctrl->agent_seen)
+    {
+      ctrl->agent_seen = 1;
+      audit_log_ok (ctrl->audit, AUDIT_AGENT_READY, rc);
+    }
 
+  return rc;
 }
 
 
index a35e93c..a4b6fbc 100644 (file)
@@ -1,5 +1,5 @@
 /* call-dirmngr.c - communication with the dromngr 
- *     Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+ *     Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -134,13 +134,32 @@ get_membuf (struct membuf *mb, size_t *len)
 }
 
 
+/* This fucntion prepares the dirmngr for a new session.  The
+   audit-events option is used so that other dirmngr clients won't get
+   disturbed by such events.  */
+static void
+prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
+{
+  if (!ctrl->dirmngr_seen)
+    {
+      ctrl->dirmngr_seen = 1;
+      if (!err)
+        {
+          err = assuan_transact (ctx, "OPTION audit-events=1",
+                                 NULL, NULL, NULL, NULL, NULL, NULL);
+          if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
+            err = 0;  /* Allow the use of old dirmngr versions.  */
+        }
+      audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err);
+    }
+}
 
 
 \f
 /* Try to connect to the agent via socket or fork it off and work by
    pipes.  Handle the server's initial greeting */
 static int
-start_dirmngr (void)
+start_dirmngr (ctrl_t ctrl)
 {
   int rc;
   char *infostr, *p;
@@ -148,8 +167,11 @@ start_dirmngr (void)
   int try_default = 0;
 
   if (dirmngr_ctx)
-    return 0; /* fixme: We need a context for each thread or serialize
-                 the access to the dirmngr */
+    {
+      prepare_dirmngr (ctrl, dirmngr_ctx, 0);
+      return 0; /* fixme: We need a context for each thread or serialize
+                   the access to the dirmngr */
+    }
   /* Note: if you change this to multiple connections, you also need
      to take care of the implicit option sending caching. */
 
@@ -220,7 +242,7 @@ start_dirmngr (void)
               log_error (_("malformed DIRMNGR_INFO environment variable\n"));
               xfree (infostr);
               force_pipe_server = 1;
-              return start_dirmngr ();
+              return start_dirmngr (ctrl);
             }
           *p++ = 0;
           pid = atoi (p);
@@ -233,7 +255,7 @@ start_dirmngr (void)
                          prot);
               xfree (infostr);
               force_pipe_server = 1;
-              return start_dirmngr ();
+              return start_dirmngr (ctrl);
             }
         }
       else
@@ -251,11 +273,13 @@ start_dirmngr (void)
         {
           log_error (_("can't connect to the dirmngr - trying fall back\n"));
           force_pipe_server = 1;
-          return start_dirmngr ();
+          return start_dirmngr (ctrl);
         }
 #endif /*!HAVE_W32_SYSTEM*/
     }
 
+  prepare_dirmngr (ctrl, ctx, rc);
+
   if (rc)
     {
       log_error ("can't connect to the dirmngr: %s\n", gpg_strerror (rc));
@@ -424,7 +448,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
   struct isvalid_status_parm_s stparm;
 
 
-  rc = start_dirmngr ();
+  rc = start_dirmngr (ctrl);
   if (rc)
     return rc;
 
@@ -691,7 +715,7 @@ gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names,
   struct lookup_parm_s parm;
   size_t len;
 
-  rc = start_dirmngr ();
+  rc = start_dirmngr (ctrl);
   if (rc)
     return rc;
 
@@ -821,7 +845,7 @@ gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
   size_t len;
   struct run_command_parm_s parm;
 
-  rc = start_dirmngr ();
+  rc = start_dirmngr (ctrl);
   if (rc)
     return rc;
 
index f30c0c0..a21a38a 100644 (file)
@@ -1127,6 +1127,8 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
              associated with that specific root certificate.  */
           istrusted_rc = gpgsm_agent_istrusted (ctrl, subject_cert,
                                                 rootca_flags);
+          audit_log_cert (ctrl->audit, AUDIT_ROOT_TRUSTED,
+                          subject_cert, istrusted_rc);
           /* If the chain model extended attribute is used, make sure
              that our chain model flag is set. */
           if (has_validation_model_chain (subject_cert, listmode, listfp))
index 1e36e96..5f79be1 100644 (file)
@@ -1,5 +1,5 @@
 /* encrypt.c - Encrypt a message
- *     Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2003, 2004, 2007 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -318,9 +318,12 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
   int recpno;
   FILE *data_fp = NULL;
   certlist_t cl;
+  int count;
 
   memset (&encparm, 0, sizeof encparm);
 
+  audit_set_type (ctrl->audit, AUDIT_TYPE_ENCRYPT);
+
   /* Check that the certificate list is not empty and that at least
      one certificate is not flagged as encrypt_to; i.e. is a real
      recipient. */
@@ -331,10 +334,15 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
     {
       log_error(_("no valid recipients given\n"));
       gpgsm_status (ctrl, STATUS_NO_RECP, "0");
+      audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, 0);
       rc = gpg_error (GPG_ERR_NO_PUBKEY);
       goto leave;
     }
 
+  for (count = 0, cl = recplist; cl; cl = cl->next)
+    count++;
+  audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, count);
+
   kh = keydb_new (0);
   if (!kh)
     {
@@ -385,6 +393,8 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
       goto leave;
     }
 
+  audit_log (ctrl->audit, AUDIT_GOT_DATA);
+
   /* We are going to create enveloped data with uninterpreted data as
      inner content */
   err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
@@ -432,6 +442,8 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
       rc = out_of_core ();
       goto leave;
     }
+  
+  audit_log_s (ctrl->audit, AUDIT_SESSION_KEY, dek->algoid);
 
   /* Gather certificates of recipients, encrypt the session key for
      each and store them in the CMS object */
@@ -442,6 +454,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
       rc = encrypt_dek (dek, cl->cert, &encval);
       if (rc)
         {
+          audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, rc);
           log_error ("encryption failed for recipient no. %d: %s\n",
                      recpno, gpg_strerror (rc));
           goto leave;
@@ -450,6 +463,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
       err = ksba_cms_add_recipient (cms, cl->cert);
       if (err)
         {
+          audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
           log_error ("ksba_cms_add_recipient failed: %s\n",
                      gpg_strerror (err));
           rc = err;
@@ -459,6 +473,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
       
       err = ksba_cms_set_enc_val (cms, recpno, encval);
       xfree (encval);
+      audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
       if (err)
         {
           log_error ("ksba_cms_set_enc_val failed: %s\n",
@@ -466,7 +481,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
           rc = err;
           goto leave;
         }
-  }
+    }
 
   /* Main control loop for encryption. */
   recpno = 0;
@@ -496,6 +511,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
       log_error ("write failed: %s\n", gpg_strerror (rc));
       goto leave;
     }
+  audit_log (ctrl->audit, AUDIT_ENCRYPTION_DONE);
   log_info ("encrypted data created\n");
 
  leave:
index 10e3915..93474b3 100644 (file)
@@ -848,6 +848,7 @@ main ( int argc, char **argv)
   certlist_t signerlist = NULL;
   int do_not_setup_keys = 0;
   int recp_required = 0;
+  estream_t auditfp = NULL;
 
   /*mtrace();*/
 
@@ -1482,6 +1483,26 @@ main ( int argc, char **argv)
     keydb_add_resource (sl->d, 0, 0, NULL);
   FREE_STRLIST(nrings);
 
+
+  /* Prepare the audit log feature for certain commands.  */
+  if (auditlog)
+    {
+      switch (cmd)
+        {
+        case aEncr: 
+        case aSign:
+        case aDecrypt:
+        case aVerify:
+          audit_release (ctrl.audit);
+          ctrl.audit = audit_new ();
+          auditfp = open_es_fwrite (auditlog);
+          break;
+        default:
+          break;
+        }
+    }
+
+
   if (!do_not_setup_keys)
     {
       for (sl = locusr; sl ; sl = sl->next)
@@ -1528,6 +1549,7 @@ main ( int argc, char **argv)
   
   fname = argc? *argv : NULL;
   
+  /* Dispatch command.  */
   switch (cmd)
     {
     case aGPGConfList: 
@@ -1650,7 +1672,6 @@ main ( int argc, char **argv)
     case aVerify:
       {
         FILE *fp = NULL;
-        estream_t auditfp = NULL;
 
         set_binary (stdin);
         if (argc == 2 && opt.outfile)
@@ -1658,13 +1679,6 @@ main ( int argc, char **argv)
         else if (opt.outfile)
           fp = open_fwrite (opt.outfile);
 
-        if (auditlog)
-          {
-            audit_release (ctrl.audit);
-            ctrl.audit = audit_new ();
-            auditfp = open_es_fwrite (auditlog);
-          }
-
         if (!argc)
           gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */
         else if (argc == 1)
@@ -1674,16 +1688,8 @@ main ( int argc, char **argv)
         else
           wrong_args ("--verify [signature [detached_data]]");
 
-        if (auditlog)
-          {
-            audit_print_result (ctrl.audit, auditfp, 0);
-            audit_release (ctrl.audit);
-            ctrl.audit = NULL;
-          }
-
         if (fp && fp != stdout)
           fclose (fp);
-        es_fclose (auditfp);
       }
       break;
 
@@ -1846,6 +1852,15 @@ main ( int argc, char **argv)
         log_error ("invalid command (there is no implicit command)\n");
        break;
     }
+
+  /* Print the audit result if needed.  */
+  if (auditlog && auditfp)
+    {
+      audit_print_result (ctrl.audit, auditfp, 0);
+      audit_release (ctrl.audit);
+      ctrl.audit = NULL;
+      es_fclose (auditfp);
+    }
   
   /* cleanup */
   gpgsm_release_certlist (recplist);
index 8f9692a..5232ce4 100644 (file)
@@ -152,6 +152,10 @@ struct server_control_s
   struct server_local_s *server_local;
   
   audit_ctx_t audit;  /* NULL or a context for the audit subsystem.  */
+  int agent_seen;     /* Flag indicating that the gpg-agent has been
+                         accessed.  */
+  int dirmngr_seen;   /* Flag indicating that the dirmngr has been
+                         accessed.  */
   
   int with_colons;    /* Use column delimited output format */
   int with_chain;     /* Include the certifying certs in a listing */
index e61f9d6..b9fe2a2 100644 (file)
@@ -366,7 +366,14 @@ cmd_recipient (assuan_context_t ctx, char *line)
   ctrl_t ctrl = assuan_get_pointer (ctx);
   int rc;
 
-  rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist, 0);
+  if (!ctrl->audit)
+    rc = start_audit_session (ctrl);
+  else
+    rc = 0;
+
+  if (!rc)
+    rc = gpgsm_add_to_certlist (ctrl, line, 0,
+                                &ctrl->server_local->recplist, 0);
   if (rc)
     {
       gpg_err_code_t r = gpg_err_code (rc);
@@ -478,6 +485,8 @@ cmd_encrypt (assuan_context_t ctx, char *line)
                                            &ctrl->server_local->recplist, 1);
     }
   if (!rc)
+    rc = ctrl->audit? 0 : start_audit_session (ctrl);
+  if (!rc)
     rc = gpgsm_encrypt (assuan_get_pointer (ctx),
                         ctrl->server_local->recplist,
                         inp_fd, out_fp);
@@ -492,6 +501,7 @@ cmd_encrypt (assuan_context_t ctx, char *line)
   return rc;
 }
 
+
 /* DECRYPT
 
   This performs the decrypt operation after doing some check on the
@@ -517,7 +527,10 @@ cmd_decrypt (assuan_context_t ctx, char *line)
   out_fp = fdopen (dup(out_fd), "w");
   if (!out_fp)
     return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
-  rc = gpgsm_decrypt (ctrl, inp_fd, out_fp); 
+
+  rc = start_audit_session (ctrl);
+  if (!rc)
+    rc = gpgsm_decrypt (ctrl, inp_fd, out_fp); 
   fclose (out_fp);
 
   /* close and reset the fd */
@@ -600,8 +613,10 @@ cmd_sign (assuan_context_t ctx, char *line)
   if (!out_fp)
     return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
 
-  rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist,
-                   inp_fd, detached, out_fp);
+  rc = start_audit_session (ctrl);
+  if (!rc)
+    rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist,
+                     inp_fd, detached, out_fp);
   fclose (out_fp);
 
   /* close and reset the fd */