More stuff for the audit-log.
authorWerner Koch <wk@gnupg.org>
Wed, 2 Dec 2009 18:33:59 +0000 (18:33 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 2 Dec 2009 18:33:59 +0000 (18:33 +0000)
NEWS
common/ChangeLog
common/audit.c
common/audit.h
g10/ChangeLog
g10/keyedit.c
sm/ChangeLog
sm/decrypt.c
sm/gpgsm.c
sm/sign.c
sm/verify.c

diff --git a/NEWS b/NEWS
index d9b0207..8001381 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,11 @@ Noteworthy changes in version 2.1 (under development)
  * Encrypted OpenPGP messages with trailing data (e.g. other OpenPGP
    packets) are now correctly parsed.
 
+ * The GPGSM --audit-log feature is now more complete.
+
+ * The G13 tool for disk encryption key management has been added.
+
+
 
 Noteworthy changes in version 2.0.13 (2009-09-04)
 -------------------------------------------------
index a519f38..6015768 100644 (file)
@@ -1,3 +1,11 @@
+2009-12-02  Werner Koch  <wk@g10code.com>
+
+       * audit.c (proc_type_decrypt, proc_type_sign): Implemented.
+       (proc_type_verify): Print hash algo infos.
+       * audit.h (AUDIT_DATA_CIPHER_ALGO, AUDIT_BAD_DATA_CIPHER_ALSO)
+       (AUDIT_NEW_RECP, AUDIT_DECRYPTION_RESULT, AUDIT_RECP_RESULT)
+       (AUDIT_ATTR_HASH_ALGO, AUDIT_SIGNED_BY, AUDIT_SIGNING_DONE):
+
 2009-11-05  Marcus Brinkmann  <marcus@g10code.de>
 
        * asshelp.c (start_new_gpg_agent): Update use of
index 436f0d2..02a0a2b 100644 (file)
@@ -1,5 +1,5 @@
 /* audit.c - GnuPG's audit subsystem
- *     Copyright (C) 2007 Free Software Foundation, Inc.
+ *     Copyright (C) 2007, 2009 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -42,7 +42,7 @@ struct log_item_s
 {
   audit_event_t event; /* The event.  */
   gpg_error_t err;     /* The logged error code.  */
-  int intvalue;        /* A logged interger value.  */
+  int intvalue;        /* A logged integer value.  */
   char *string;        /* A malloced string or NULL.  */
   ksba_cert_t cert;    /* A certifciate or NULL. */
   int have_err:1;
@@ -483,6 +483,14 @@ writeout_li (audit_ctx_t ctx, const char *oktext, const char *format, ...)
         oktext = _("|audit-log-result|Not enabled");
       else if (!strcmp (oktext, "error"))
         oktext = _("|audit-log-result|Error");
+      else if (!strcmp (oktext, "not-used"))
+        oktext = _("|audit-log-result|Not used");
+      else if (!strcmp (oktext, "okay"))
+        oktext = _("|audit-log-result|Okay");
+      else if (!strcmp (oktext, "skipped"))
+        oktext = _("|audit-log-result|Skipped");
+      else if (!strcmp (oktext, "some"))
+        oktext = _("|audit-log-result|Some");
       else
         s = "";
 
@@ -806,16 +814,72 @@ proc_type_encrypt (audit_ctx_t ctx)
 static void
 proc_type_sign (audit_ctx_t ctx)
 {
-  log_item_t item;
+  log_item_t item, loopitem;
+  int signer, idx;
+  const char *result;
+  ksba_cert_t cert;
+  char *name;
+  int lastalgo;
 
-  item = NULL;
+  item = find_log_item (ctx, AUDIT_SIGNING_DONE, 0);
   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"));
+  /* Write remarks with the data hash algorithms.  We use a very
+     simple scheme to avoid some duplicates.  */
+  loopitem = NULL; 
+  lastalgo = 0;
+  while ((loopitem = find_next_log_item
+          (ctx, loopitem, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG)))
+    {
+      if (loopitem->intvalue && loopitem->intvalue != lastalgo)
+        writeout_rem (ctx, _("data hash algorithm: %s"),
+                      gcry_md_algo_name (loopitem->intvalue));
+      lastalgo = loopitem->intvalue;
+    }
 
+  /* Loop over all signer.  */
+  loopitem = NULL;
+  signer = 0;
+  while ((loopitem=find_next_log_item (ctx, loopitem, AUDIT_NEW_SIG, 0)))
+    {
+      signer++;
+
+      item = find_next_log_item (ctx, loopitem, AUDIT_SIGNED_BY, AUDIT_NEW_SIG);
+      if (!item)
+        result = "error";
+      else if (!item->err)
+        result = "okay";
+      else if (gpg_err_code (item->err) == GPG_ERR_CANCELED)
+        result = "skipped";
+      else
+        result = gpg_strerror (item->err);
+      cert = item? item->cert : NULL;
+
+      writeout_li (ctx, result, _("Signer %d"), signer);
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_ATTR_HASH_ALGO, AUDIT_NEW_SIG);
+      if (item)
+        writeout_rem (ctx, _("attr hash algorithm: %s"),
+                      gcry_md_algo_name (item->intvalue));
+
+      if (cert)
+        {
+          name = get_cert_name (cert);
+          writeout_rem (ctx, "%s", name);
+          xfree (name);
+          enter_li (ctx);
+          for (idx=0; (name = get_cert_subject (cert, idx)); idx++)
+            {
+              writeout_rem (ctx, "%s", name);
+              xfree (name);
+            }
+          leave_li (ctx);
+        }
+    }
 
   leave_li (ctx);
 }
@@ -826,16 +890,87 @@ proc_type_sign (audit_ctx_t ctx)
 static void
 proc_type_decrypt (audit_ctx_t ctx)
 {
-  log_item_t item;
+  log_item_t loopitem, item;
+  int algo, recpno;
+  char *name;
+  char numbuf[35];
+  int idx;
 
-  item = NULL;
-  writeout_li (ctx, item?"Yes":"No", "%s", _("Data decryption succeeded"));
+  item = find_log_item (ctx, AUDIT_DECRYPTION_RESULT, 0);
+  writeout_li (ctx, item && !item->err?"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"));
 
+  item = find_log_item (ctx, AUDIT_DATA_CIPHER_ALGO, 0);
+  algo = item? item->intvalue : 0;
+  writeout_li (ctx, algo?"Yes":"No", "%s", _("Encryption algorithm supported"));
+  if (algo)
+    writeout_rem (ctx, _("algorithm: %s"), gcry_cipher_algo_name (algo));
+
+  item = find_log_item (ctx, AUDIT_BAD_DATA_CIPHER_ALGO, 0);
+  if (item && item->string)
+    {
+      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"));
+    }
+
+
+  for (recpno = 0, item = NULL;
+       (item = find_next_log_item (ctx, item, AUDIT_NEW_RECP, 0)); recpno++)
+    ;
+  snprintf (numbuf, sizeof numbuf, "%d", recpno);
+  writeout_li (ctx, numbuf, "%s", _("Number of recipients"));
+
+  /* Loop over all recipients.  */
+  loopitem = NULL;
+  while ((loopitem = find_next_log_item (ctx, loopitem, AUDIT_NEW_RECP, 0)))
+    {
+      const char *result;
+
+      recpno = loopitem->have_intvalue? loopitem->intvalue : -1;
+
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_RECP_RESULT, AUDIT_NEW_RECP);
+      if (!item)
+        result = "not-used";
+      else if (!item->err)
+        result = "okay";
+      else if (gpg_err_code (item->err) == GPG_ERR_CANCELED)
+        result = "skipped";
+      else
+        result = gpg_strerror (item->err);
+
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_RECP_NAME, AUDIT_NEW_RECP);
+      writeout_li (ctx, result, _("Recipient %d"), recpno);
+      if (item && item->string)
+        writeout_rem (ctx, "%s", item->string);
+
+      /* If we have a certificate write out more infos.  */
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_SAVE_CERT, AUDIT_NEW_RECP);
+      if (item && item->cert)
+        {
+          enter_li (ctx);
+          for (idx=0; (name = get_cert_subject (item->cert, idx)); idx++)
+            {
+              writeout_rem (ctx, "%s", name);
+              xfree (name);
+            }
+          leave_li (ctx);
+        }
+    }
 
   leave_li (ctx);
 }
@@ -847,11 +982,12 @@ static void
 proc_type_verify (audit_ctx_t ctx)
 {
   log_item_t loopitem, item;
-  int signo, count, idx;
+  int signo, count, idx, n_good, n_bad;
   char numbuf[35];
+  const char *result;
 
   /* If there is at least one signature status we claim that the
-     verifciation succeeded.  This does not mean that the data has
+     verification 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"));
@@ -867,17 +1003,41 @@ proc_type_verify (audit_ctx_t ctx)
   if (!item)
     goto leave;
 
-  item = find_log_item (ctx, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG);
-  writeout_li (ctx, item?"Yes":"No", "%s", _("Parsing signature succeeded"));
-  if (!item)
+  /* Print info about the used data hashing algorithms.  */
+  for (idx=0, n_good=n_bad=0; idx < ctx->logused; idx++)
     {
-      item = find_log_item (ctx, AUDIT_BAD_DATA_HASH_ALGO, AUDIT_NEW_SIG);
-      if (item)
-        writeout_rem (ctx, _("Bad hash algorithm: %s"), 
-                      item->string? item->string:"?");
-
-      goto leave;
+      item = ctx->log + idx;
+      if (item->event == AUDIT_NEW_SIG)
+        break;
+      else if (item->event == AUDIT_DATA_HASH_ALGO)
+        n_good++;
+      else if (item->event == AUDIT_BAD_DATA_HASH_ALGO)
+        n_bad++;
     }
+  item = find_log_item (ctx, AUDIT_DATA_HASHING, AUDIT_NEW_SIG);
+  if (!item || item->err || !n_good)
+    result = "No";
+  else if (n_good && !n_bad)
+    result = "Yes";
+  else
+    result = "Some";
+  writeout_li (ctx, result, "%s", _("Parsing data succeeded"));
+  if (n_good || n_bad)
+    {
+      for (idx=0; idx < ctx->logused; idx++)
+        {
+          item = ctx->log + idx;
+          if (item->event == AUDIT_NEW_SIG)
+            break;
+          else if (item->event == AUDIT_DATA_HASH_ALGO)
+            writeout_rem (ctx, _("data hash algorithm: %s"),
+                          gcry_md_algo_name (item->intvalue));
+          else if (item->event == AUDIT_BAD_DATA_HASH_ALGO)
+            writeout_rem (ctx, _("bad data hash algorithm: %s"), 
+                          item->string? item->string:"?");
+        }
+    }
+
 
   /* Loop over all signatures.  */
   loopitem = find_log_item (ctx, AUDIT_NEW_SIG, 0);
@@ -893,6 +1053,18 @@ proc_type_verify (audit_ctx_t ctx)
                                  AUDIT_SIG_NAME, AUDIT_NEW_SIG);
       if (item)
         writeout_rem (ctx, "%s", item->string);
+
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG);
+      if (item)
+        writeout_rem (ctx, _("data hash algorithm: %s"),
+                      gcry_md_algo_name (item->intvalue));
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_ATTR_HASH_ALGO, AUDIT_NEW_SIG);
+      if (item)
+        writeout_rem (ctx, _("attr hash algorithm: %s"),
+                      gcry_md_algo_name (item->intvalue));
+
       enter_li (ctx);
       
       /* List the certificate chain.  */
@@ -1006,11 +1178,7 @@ audit_print_result (audit_ctx_t ctx, estream_t out, int use_html)
   /* 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;
-    }
+    show_raw = 1;
 
   assert (!ctx->outstream);
   ctx->outstream = out;
index 5f5aff4..28d1edb 100644 (file)
@@ -81,15 +81,27 @@ typedef enum
     /* A certifciate only signature has been detected.  */
 
     AUDIT_DATA_HASH_ALGO,  /* int */
-    /* The hash algo given as argument is used for this signature.
-       This event will be repeated for all hash algorithms used with
-       the data.  */
+    /* The hash algo given as argument is used for the data.  This
+       event will be repeated for all hash algorithms used with the
+       data.  */
+
+    AUDIT_ATTR_HASH_ALGO,  /* int */
+    /* The hash algo given as argument is used to hash the message
+       digest and other signed attributes of this signature. */
+
+    AUDIT_DATA_CIPHER_ALGO,  /* int */
+    /* The cipher algo given as argument is used for this data.  */
 
     AUDIT_BAD_DATA_HASH_ALGO,  /* string */
     /* The hash algo as specified by the signature can't be used.
        STRING is the description of this algorithm which usually is an
        OID string.  STRING may be NULL. */
 
+    AUDIT_BAD_DATA_CIPHER_ALGO,  /* string */
+    /* The symmetric cipher algorithm is not supported.  STRING is the
+       description of this algorithm which usually is an OID string.
+       STRING may be NULL. */
+
     AUDIT_DATA_HASHING,    /* ok_err */
     /* Logs the result of the data hashing. */
 
@@ -118,7 +130,7 @@ typedef enum
        certificate used for verification.  An example for STRING when
        using CMS is: "#1234/CN=Prostetnic Vogon Jeltz".  */
 
-    AUDIT_SIG_STATUS,     /* string */
+    AUDIT_SIG_STATUS,      /* string */
     /* The signature status of the current signer.  This is the last
        audit information for one signature.  STRING gives the status:
 
@@ -130,6 +142,24 @@ typedef enum
          "good"        - good signature
     */
 
+    AUDIT_NEW_RECP,        /* int */
+    /* A new recipient has been seen during decryption.  The argument
+       is the recipient number as used internally by the program.  */
+    
+    AUDIT_RECP_NAME,       /* string */
+    /* The name of a recipient.  This is the name or other identification
+       data as known from the decryption and not the name from the
+       certificate used for decryption.  An example for STRING when
+       using CMS is: "#1234/CN=Prostetnic Vogon Jeltz".  */
+
+    AUDIT_RECP_RESULT,    /* ok_err */
+    /* The status of the session key decryption.  This is only written
+       for recipients tried. */
+
+    AUDIT_DECRYPTION_RESULT,    /* ok_err */
+    /* The status of the entire decryption.  The decryption was
+       successful if the error code is 0. */
+
     AUDIT_VALIDATE_CHAIN,
     /* Start the validation of a certificate chain. */
 
@@ -167,7 +197,12 @@ typedef enum
     AUDIT_ENCRYPTION_DONE,
     /* Encryption succeeded.  */
 
-    
+    AUDIT_SIGNED_BY,   /* cert, err */
+    /* Records the certificate used for signed and whether the signure
+       could be created (if err==0).  */
+
+    AUDIT_SIGNING_DONE,
+    /* Signing succeeded.  */
 
 
     AUDIT_LAST_EVENT  /* Marker for parsing this list.  */
index c8978f6..67a2eea 100644 (file)
@@ -1,3 +1,7 @@
+2009-11-27  Werner Koch  <wk@g10code.com>
+
+       * keyedit.c (cmds, keyedit_menu): New command "checkbkupkey".
+
 2009-11-25  Marcus Brinkmann  <marcus@g10code.de>
 
        * server.c (gpg_server): Use assuan_fd_t and assuan_fdopen on fds.
index bc79e8f..847e187 100644 (file)
@@ -1143,11 +1143,11 @@ change_passphrase( KBNODE keyblock )
        break;
       default:
        if( sk->protect.s2k.mode == 1001 ) {
-           tty_printf(_("Secret parts of primary key are not available.\n"));
+           tty_printf(_("Secret parts of key are not available.\n"));
            no_primary_secrets = 1;
        }
        else if( sk->protect.s2k.mode == 1002 ) {
-           tty_printf(_("Secret parts of primary key are stored on-card.\n"));
+           tty_printf(_("Secret parts of key are stored on-card.\n"));
            no_primary_secrets = 1;
        }
        else {
@@ -1365,8 +1365,8 @@ enum cmdids
     cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
     cmdEXPIRE, cmdBACKSIGN, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF,
     cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST,
-    cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCLEAN,
-    cmdMINIMIZE, cmdNOP
+    cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCHECKBKUPKEY,
+    cmdCLEAN, cmdMINIMIZE, cmdNOP
   };
 
 static struct
@@ -1423,6 +1423,8 @@ static struct
       N_("move a key to a smartcard")},
     { "bkuptocard", cmdBKUPTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, 
       N_("move a backup key to a smartcard")},
+    { "checkbkupkey", cmdCHECKBKUPKEY, KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, 
+      NULL},
 #endif /*ENABLE_CARD_SUPPORT*/
 
     { "delkey"  , cmdDELKEY    , KEYEDIT_NOT_SK,
@@ -1940,6 +1942,7 @@ keyedit_menu( const char *username, strlist_t locusr,
           break;
 
         case cmdBKUPTOCARD:
+        case cmdCHECKBKUPKEY:
          {
             /* Ask for a filename, check whether this is really a
                backup key as generated by the card generation, parse
@@ -1991,11 +1994,35 @@ keyedit_menu( const char *username, strlist_t locusr,
               }
             node = new_kbnode (pkt);
 
-            /* Store it.  */
-            if (card_store_subkey (node, 0))
+            if (cmd == cmdCHECKBKUPKEY)
               {
-                redisplay = 1;
-                sec_modified = 1;
+                PKT_secret_key *sk = node->pkt->pkt.secret_key;
+                switch (is_secret_key_protected (sk) )
+                  {
+                  case 0: /* Not protected. */
+                    tty_printf (_("This key is not protected.\n"));
+                    break;
+                  case -1:
+                    log_error (_("unknown key protection algorithm\n"));
+                    break;
+                  default:
+                    if (sk->protect.s2k.mode == 1001)
+                      tty_printf (_("Secret parts of key"
+                                    " are not available.\n"));
+                    if (sk->protect.s2k.mode == 1002)
+                      tty_printf (_("Secret parts of key"
+                                    " are stored on-card.\n"));
+                    else
+                      check_secret_key (sk, 0);
+                  }
+              }
+            else /* Store it.  */
+              {
+                if (card_store_subkey (node, 0))
+                  {
+                    redisplay = 1;
+                    sec_modified = 1;
+                  }
               }
             release_kbnode (node);
          }
index 80235db..1673163 100644 (file)
@@ -1,3 +1,16 @@
+2009-12-02  Werner Koch  <wk@g10code.com>
+
+       * verify.c (gpgsm_verify): Add audit info on hash algorithms.
+
+       * sign.c (gpgsm_sign): Add audit log calls.
+       (hash_data): Return an error indicator.
+
+2009-12-01  Werner Koch  <wk@g10code.com>
+
+       * decrypt.c (gpgsm_decrypt): Add audit log calls.
+
+       * gpgsm.c: New option --html-audit-log.
+
 2009-11-25  Marcus Brinkmann  <marcus@g10code.de>
 
        * server.c (gpgsm_server): Use assuan_fd_t and assuan_fdopen on
index 8fb9f2d..de02551 100644 (file)
@@ -253,6 +253,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
 
   memset (&dfparm, 0, sizeof dfparm);
 
+  audit_set_type (ctrl->audit, AUDIT_TYPE_DECRYPT);
+
   kh = keydb_new (0);
   if (!kh)
     {
@@ -296,6 +298,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
       goto leave;
     }
 
+  audit_log (ctrl->audit, AUDIT_SETUP_READY);
+
   /* Parser loop. */
   do 
     {
@@ -313,6 +317,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
           const char *algoid;
           int any_key = 0;
           
+          audit_log (ctrl->audit, AUDIT_GOT_DATA);
+
           algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
           algo = gcry_cipher_map_name (algoid);
           mode = gcry_cipher_mode_from_oid (algoid);
@@ -330,6 +336,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
                 sprintf (numbuf, "%d", rc);
                 gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
                                numbuf, algoid?algoid:"?", NULL);
+                audit_log_s (ctrl->audit, AUDIT_BAD_DATA_CIPHER_ALGO, algoid);
               }
 
               /* If it seems that this is not an encrypted message we
@@ -339,6 +346,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
 
               goto leave;
             }
+
+          audit_log_i (ctrl->audit, AUDIT_DATA_CIPHER_ALGO, algo);
           dfparm.algo = algo;
           dfparm.mode = mode;
           dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
@@ -369,6 +378,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
               rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
               if (rc == -1 && recp)
                 break; /* no more recipients */
+              audit_log_i (ctrl->audit, AUDIT_NEW_RECP, recp);
               if (rc)
                 log_error ("recp %d - error getting info: %s\n",
                            recp, gpg_strerror (rc));
@@ -382,6 +392,13 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
                   gpgsm_dump_serial (serial);
                   log_printf ("\n");
 
+                  if (ctrl->audit)
+                    {
+                      char *tmpstr = gpgsm_format_sn_issuer (serial, issuer);
+                      audit_log_s (ctrl->audit, AUDIT_RECP_NAME, tmpstr);
+                      xfree (tmpstr);
+                    }
+
                   keydb_search_reset (kh);
                   rc = keydb_search_issuer_sn (kh, issuer, serial);
                   if (rc)
@@ -415,6 +432,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
                                    kidbuf, "0", "0", NULL);
                   }
 
+                  /* Put the certificate into the audit log.  */
+                  audit_log_cert (ctrl->audit, AUDIT_SAVE_CERT, cert, 0);
 
                   /* Just in case there is a problem with the own
                      certificate we print this message - should never
@@ -462,10 +481,41 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
                                               decrypt_filter,
                                               &dfparm);
                     }
+                  audit_log_ok (ctrl->audit, AUDIT_RECP_RESULT, rc);
                 }
               xfree (hexkeygrip);
               xfree (desc);
             }
+
+          /* If we write an audit log add the unused recipients to the
+             log as well.  */
+          if (ctrl->audit && any_key)
+            {
+              for (;; recp++)
+                {
+                  char *issuer;
+                  ksba_sexp_t serial;
+                  int tmp_rc;
+
+                  tmp_rc = ksba_cms_get_issuer_serial (cms, recp,
+                                                       &issuer, &serial);
+                  if (tmp_rc == -1)
+                    break; /* no more recipients */
+                  audit_log_i (ctrl->audit, AUDIT_NEW_RECP, recp);
+                  if (tmp_rc)
+                    log_error ("recp %d - error getting info: %s\n",
+                               recp, gpg_strerror (rc));
+                  else
+                    {
+                      char *tmpstr = gpgsm_format_sn_issuer (serial, issuer);
+                      audit_log_s (ctrl->audit, AUDIT_RECP_NAME, tmpstr);
+                      xfree (tmpstr);
+                      xfree (issuer);
+                      xfree (serial);
+                    }
+                }
+            }
+
           if (!any_key)
             {
               rc = gpg_error (GPG_ERR_NO_SECKEY);
@@ -488,7 +538,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
                                       dfparm.lastblock, 
                                       dfparm.blklen - npadding);
               if (rc)
-                  goto leave;
+                goto leave;
 
               for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++)
                 {
@@ -515,6 +565,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
 
 
  leave:
+  audit_log_ok (ctrl->audit, AUDIT_DECRYPTION_RESULT, rc);
   if (rc)
     {
       gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);
index 2d262b7..6e7cd84 100644 (file)
@@ -99,6 +99,7 @@ enum cmd_and_opt_values {
   oLogFile,
   oNoLogFile,
   oAuditLog,
+  oHtmlAuditLog,
 
   oEnableSpecialFilenames,
 
@@ -286,6 +287,7 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_s (oAuditLog, "audit-log", 
                 N_("|FILE|write an audit log to FILE")),
+  ARGPARSE_s_s (oHtmlAuditLog, "html-audit-log", ""),
   ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
   ARGPARSE_s_n (oBatch, "batch", N_("batch mode: never ask")),
   ARGPARSE_s_n (oAnswerYes, "yes", N_("assume yes on most questions")),
@@ -851,6 +853,7 @@ main ( int argc, char **argv)
   int default_keyring = 1;
   char *logfile = NULL;
   char *auditlog = NULL;
+  char *htmlauditlog = NULL;
   int greeting = 0;
   int nogreeting = 0;
   int debug_wait = 0;
@@ -866,6 +869,7 @@ main ( int argc, char **argv)
   int do_not_setup_keys = 0;
   int recp_required = 0;
   estream_t auditfp = NULL;
+  estream_t htmlauditfp = NULL;
   struct assuan_malloc_hooks malloc_hooks;
 
   /*mtrace();*/
@@ -1182,6 +1186,7 @@ main ( int argc, char **argv)
         case oNoLogFile: logfile = NULL; break;          
 
         case oAuditLog: auditlog = pargs.r.ret_str; break;
+        case oHtmlAuditLog: htmlauditlog = pargs.r.ret_str; break;
 
         case oBatch: 
           opt.batch = 1;
@@ -1410,11 +1415,6 @@ main ( int argc, char **argv)
     }
 #  endif
 
-  if (auditlog)
-    log_info ("NOTE: The audit log feature (--audit-log) is "
-              "WORK IN PRORESS and not ready for use!\n");
-
-
   if (may_coredump && !opt.quiet)
     log_info (_("WARNING: program may create a core file!\n"));
 
@@ -1546,7 +1546,7 @@ main ( int argc, char **argv)
 
 
   /* Prepare the audit log feature for certain commands.  */
-  if (auditlog)
+  if (auditlog || htmlauditlog)
     {
       switch (cmd)
         {
@@ -1556,7 +1556,10 @@ main ( int argc, char **argv)
         case aVerify:
           audit_release (ctrl.audit);
           ctrl.audit = audit_new ();
-          auditfp = open_es_fwrite (auditlog);
+          if (auditlog)
+            auditfp = open_es_fwrite (auditlog);
+          if (htmlauditlog)
+            htmlauditfp = open_es_fwrite (htmlauditlog);
           break;
         default:
           break;
@@ -1914,12 +1917,16 @@ main ( int argc, char **argv)
     }
 
   /* Print the audit result if needed.  */
-  if (auditlog && auditfp)
+  if ((auditlog && auditfp) || (htmlauditlog && htmlauditfp))
     {
-      audit_print_result (ctrl.audit, auditfp, 0);
+      if (auditlog && auditfp)
+        audit_print_result (ctrl.audit, auditfp, 0);
+      if (htmlauditlog && htmlauditfp)
+        audit_print_result (ctrl.audit, htmlauditfp, 1);
       audit_release (ctrl.audit);
       ctrl.audit = NULL;
       es_fclose (auditfp);
+      es_fclose (htmlauditfp);
     }
   
   /* cleanup */
index 776a5a5..fd7c4ff 100644 (file)
--- a/sm/sign.c
+++ b/sm/sign.c
 #include "i18n.h"
 
 
-static void
+/* Hash the data and return if something was hashed.  Return -1 on error.  */
+static int
 hash_data (int fd, gcry_md_hd_t md)
 {
   FILE *fp;
   char buffer[4096];
   int nread;
+  int rc = 0;
 
   fp = fdopen ( dup (fd), "rb");
   if (!fp)
     {
       log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
-      return;
+      return -1;
     }
 
   do 
@@ -55,8 +57,12 @@ hash_data (int fd, gcry_md_hd_t md)
     }
   while (nread);
   if (ferror (fp))
+    {
       log_error ("read error on fd %d: %s\n", fd, strerror (errno));
+      rc = -1;
+    }
   fclose (fp);
+  return rc;
 }
 
 static int
@@ -321,6 +327,8 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
   certlist_t cl;
   int release_signerlist = 0;
 
+  audit_set_type (ctrl->audit, AUDIT_TYPE_SIGN);
+
   kh = keydb_new (0);
   if (!kh)
     {
@@ -539,8 +547,11 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
           goto leave;
         }
       gcry_md_enable (data_md, algo);
+      audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
     }
 
+  audit_log (ctrl->audit, AUDIT_SETUP_READY);
+
   if (detached)
     { /* We hash the data right now so that we can store the message
          digest.  ksba_cms_build() takes this as an flag that detached
@@ -548,7 +559,8 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
       unsigned char *digest;
       size_t digest_len;
 
-      hash_data (data_fd, data_md);
+      if (!hash_data (data_fd, data_md))
+        audit_log (ctrl->audit, AUDIT_GOT_DATA);
       for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
         {
           digest = gcry_md_read (data_md, cl->hash_algo);
@@ -623,6 +635,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
           rc = hash_and_copy_data (data_fd, data_md, writer);
           if (rc)
             goto leave;
+          audit_log (ctrl->audit, AUDIT_GOT_DATA);
           for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
             {
               digest = gcry_md_read (data_md, cl->hash_algo);
@@ -663,13 +676,18 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
               unsigned char *sigval = NULL;
               char *buf, *fpr;
 
+              audit_log_i (ctrl->audit, AUDIT_NEW_SIG, signer);
               if (signer)
                 gcry_md_reset (md);
               {
                 certlist_t cl_tmp;
 
                 for (cl_tmp=signerlist; cl_tmp; cl_tmp = cl_tmp->next)
-                  gcry_md_enable (md, cl_tmp->hash_algo);
+                  {
+                    gcry_md_enable (md, cl_tmp->hash_algo);
+                    audit_log_i (ctrl->audit, AUDIT_ATTR_HASH_ALGO, 
+                                 cl_tmp->hash_algo);
+                  }
               }
 
               rc = ksba_cms_hash_signed_attrs (cms, signer);
@@ -685,6 +703,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
                                                md, cl->hash_algo, &sigval);
               if (rc)
                 {
+                  audit_log_cert (ctrl->audit, AUDIT_SIGNED_BY, cl->cert, rc);
                   gcry_md_close (md);
                   goto leave;
                 }
@@ -693,6 +712,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
               xfree (sigval);
               if (err)
                 {
+                  audit_log_cert (ctrl->audit, AUDIT_SIGNED_BY, cl->cert, err);
                   log_error ("failed to store the signature: %s\n",
                              gpg_strerror (err));
                   rc = err;
@@ -708,28 +728,29 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
                   gcry_md_close (md);
                   goto leave;
                 }
+              rc = 0;
               {
                 int pkalgo = gpgsm_get_key_algo_info (cl->cert, NULL);
-                rc = asprintf (&buf, "%c %d %d 00 %s %s",
-                               detached? 'D':'S',
-                               pkalgo, 
-                               cl->hash_algo, 
-                               signed_at,
-                               fpr);
+                buf = xtryasprintf ("%c %d %d 00 %s %s",
+                                    detached? 'D':'S',
+                                    pkalgo, 
+                                    cl->hash_algo, 
+                                    signed_at,
+                                    fpr);
+                if (!buf)
+                  rc = gpg_error_from_syserror ();
               }
               xfree (fpr);
-              if (rc < 0)
+              if (rc)
                 {
-                  rc = gpg_error (GPG_ERR_ENOMEM);
                   gcry_md_close (md);
                   goto leave;
                 }
-              rc = 0;
               gpgsm_status (ctrl, STATUS_SIG_CREATED, buf);
-              free (buf); /* yes, we must use the regular free() here */
+              xfree (buf);
+              audit_log_cert (ctrl->audit, AUDIT_SIGNED_BY, cl->cert, 0);
             }
           gcry_md_close (md);
-
         }
     }
   while (stopreason != KSBA_SR_READY);   
@@ -741,6 +762,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
       goto leave;
     }
 
+  audit_log (ctrl->audit, AUDIT_SIGNING_DONE);
   log_info ("signature created\n");
 
 
index 77517c6..c8663e3 100644 (file)
@@ -216,6 +216,8 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
                 log_debug ("enabling extra hash algorithm %d\n", 
                            opt.extra_digest_algo);
               gcry_md_enable (data_md, opt.extra_digest_algo);
+              audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO,
+                           opt.extra_digest_algo);
             }
           if (is_detached)
             {
@@ -236,7 +238,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
         }
       else if (stopreason == KSBA_SR_END_DATA)
         { /* The data bas been hashed */
-
+          audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING, 0);
         }
     }
   while (stopreason != KSBA_SR_READY);   
@@ -452,6 +454,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
       log_printf (_(" using certificate ID 0x%08lX\n"),
                   gpgsm_get_short_fingerprint (cert, NULL));
 
+      audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
 
       if (msgdigest)
         { /* Signed attributes are available. */
@@ -484,6 +487,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
               goto next_signer; 
             }
             
+          audit_log_i (ctrl->audit, AUDIT_ATTR_HASH_ALGO, sigval_hash_algo);
           rc = gcry_md_open (&md, sigval_hash_algo, 0);
           if (rc)
             {