summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2009-12-02 19:33:59 +0100
committerWerner Koch <wk@gnupg.org>2009-12-02 19:33:59 +0100
commit9e834047519bbaffd54bc20590a4625e9622883e (patch)
treef8da97c151867fa9350ccfa058b8fcdae03a2183
parent2009-11-27 Marcus Brinkmann <marcus@g10code.de> (diff)
downloadgnupg2-9e834047519bbaffd54bc20590a4625e9622883e.tar.xz
gnupg2-9e834047519bbaffd54bc20590a4625e9622883e.zip
More stuff for the audit-log.
-rw-r--r--NEWS5
-rw-r--r--common/ChangeLog8
-rw-r--r--common/audit.c214
-rw-r--r--common/audit.h45
-rw-r--r--g10/ChangeLog4
-rw-r--r--g10/keyedit.c43
-rw-r--r--sm/ChangeLog13
-rw-r--r--sm/decrypt.c53
-rw-r--r--sm/gpgsm.c25
-rw-r--r--sm/sign.c52
-rw-r--r--sm/verify.c6
11 files changed, 406 insertions, 62 deletions
diff --git a/NEWS b/NEWS
index d9b0207cb..80013815d 100644
--- 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)
-------------------------------------------------
diff --git a/common/ChangeLog b/common/ChangeLog
index a519f3850..60157680d 100644
--- a/common/ChangeLog
+++ b/common/ChangeLog
@@ -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
diff --git a/common/audit.c b/common/audit.c
index 436f0d25d..02a0a2b22 100644
--- a/common/audit.c
+++ b/common/audit.c
@@ -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;
diff --git a/common/audit.h b/common/audit.h
index 5f5aff419..28d1edbd1 100644
--- a/common/audit.h
+++ b/common/audit.h
@@ -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. */
diff --git a/g10/ChangeLog b/g10/ChangeLog
index c8978f6d5..67a2eeafa 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -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.
diff --git a/g10/keyedit.c b/g10/keyedit.c
index bc79e8fa8..847e187ca 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -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);
}
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 80235db78..167316330 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -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
diff --git a/sm/decrypt.c b/sm/decrypt.c
index 8fb9f2dfd..de025516f 100644
--- a/sm/decrypt.c
+++ b/sm/decrypt.c
@@ -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);
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 2d262b707..6e7cd8406 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -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 */
diff --git a/sm/sign.c b/sm/sign.c
index 776a5a571..fd7c4ff2f 100644
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -34,18 +34,20 @@
#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");
diff --git a/sm/verify.c b/sm/verify.c
index 77517c61f..c8663e3e6 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -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)
{