1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-16 00:29:50 +02:00

Backported some stuff from trunk

This commit is contained in:
Werner Koch 2009-12-03 19:39:39 +00:00
parent 1356693b0d
commit ae7b03d427
13 changed files with 390 additions and 58 deletions

4
NEWS
View File

@ -1,12 +1,14 @@
Noteworthy changes in version 2.0.14 Noteworthy changes in version 2.0.14
------------------------------------------------- -------------------------------------------------
* The default for --inlucde-cert is now to include all certificates * The default for --include-cert is now to include all certificates
in the chain except for the root certificate. in the chain except for the root certificate.
* Numerical values may now be used as an alternative to the * Numerical values may now be used as an alternative to the
debug-level keywords. debug-level keywords.
* The GPGSM --audit-log feature is now more complete.
Noteworthy changes in version 2.0.13 (2009-09-04) Noteworthy changes in version 2.0.13 (2009-09-04)
------------------------------------------------- -------------------------------------------------

View File

@ -1,3 +1,12 @@
2009-12-03 Werner Koch <wk@g10code.com>
From trunk:
* 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-09-03 Werner Koch <wk@g10code.com> 2009-09-03 Werner Koch <wk@g10code.com>
Update from libestream: Update from libestream:

View File

@ -1,5 +1,5 @@
/* audit.c - GnuPG's audit subsystem /* 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. * This file is part of GnuPG.
* *
@ -42,7 +42,7 @@ struct log_item_s
{ {
audit_event_t event; /* The event. */ audit_event_t event; /* The event. */
gpg_error_t err; /* The logged error code. */ 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. */ char *string; /* A malloced string or NULL. */
ksba_cert_t cert; /* A certifciate or NULL. */ ksba_cert_t cert; /* A certifciate or NULL. */
int have_err:1; 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"); oktext = _("|audit-log-result|Not enabled");
else if (!strcmp (oktext, "error")) else if (!strcmp (oktext, "error"))
oktext = _("|audit-log-result|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 else
s = ""; s = "";
@ -806,16 +814,72 @@ proc_type_encrypt (audit_ctx_t ctx)
static void static void
proc_type_sign (audit_ctx_t ctx) 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")); writeout_li (ctx, item?"Yes":"No", "%s", _("Data signing succeeded"));
enter_li (ctx); enter_li (ctx);
item = find_log_item (ctx, AUDIT_GOT_DATA, 0); item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
writeout_li (ctx, item? "Yes":"No", "%s", _("Data available")); 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); leave_li (ctx);
} }
@ -826,16 +890,87 @@ proc_type_sign (audit_ctx_t ctx)
static void static void
proc_type_decrypt (audit_ctx_t ctx) 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; item = find_log_item (ctx, AUDIT_DECRYPTION_RESULT, 0);
writeout_li (ctx, item?"Yes":"No", "%s", _("Data decryption succeeded")); writeout_li (ctx, item && !item->err?"Yes":"No",
"%s", _("Data decryption succeeded"));
enter_li (ctx); enter_li (ctx);
item = find_log_item (ctx, AUDIT_GOT_DATA, 0); item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
writeout_li (ctx, item? "Yes":"No", "%s", _("Data available")); 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); leave_li (ctx);
} }
@ -847,11 +982,12 @@ static void
proc_type_verify (audit_ctx_t ctx) proc_type_verify (audit_ctx_t ctx)
{ {
log_item_t loopitem, item; log_item_t loopitem, item;
int signo, count, idx; int signo, count, idx, n_good, n_bad;
char numbuf[35]; char numbuf[35];
const char *result;
/* If there is at least one signature status we claim that the /* 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. */ verified okay. */
item = find_log_item (ctx, AUDIT_SIG_STATUS, 0); item = find_log_item (ctx, AUDIT_SIG_STATUS, 0);
writeout_li (ctx, item?"Yes":"No", "%s", _("Data verification succeeded")); writeout_li (ctx, item?"Yes":"No", "%s", _("Data verification succeeded"));
@ -867,17 +1003,41 @@ proc_type_verify (audit_ctx_t ctx)
if (!item) if (!item)
goto leave; goto leave;
item = find_log_item (ctx, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG); /* Print info about the used data hashing algorithms. */
writeout_li (ctx, item?"Yes":"No", "%s", _("Parsing signature succeeded")); for (idx=0, n_good=n_bad=0; idx < ctx->logused; idx++)
if (!item)
{ {
item = find_log_item (ctx, AUDIT_BAD_DATA_HASH_ALGO, AUDIT_NEW_SIG); item = ctx->log + idx;
if (item) if (item->event == AUDIT_NEW_SIG)
writeout_rem (ctx, _("Bad hash algorithm: %s"), break;
item->string? item->string:"?"); else if (item->event == AUDIT_DATA_HASH_ALGO)
n_good++;
goto leave; 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. */ /* Loop over all signatures. */
loopitem = find_log_item (ctx, AUDIT_NEW_SIG, 0); 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); AUDIT_SIG_NAME, AUDIT_NEW_SIG);
if (item) if (item)
writeout_rem (ctx, "%s", item->string); 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); enter_li (ctx);
/* List the certificate chain. */ /* 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 /* We use an environment variable to include some debug info in the
log. */ log. */
if ((s = getenv ("gnupg_debug_audit"))) if ((s = getenv ("gnupg_debug_audit")))
{ show_raw = 1;
show_raw = 1;
if (!strcmp (s, "html"))
use_html = 1;
}
assert (!ctx->outstream); assert (!ctx->outstream);
ctx->outstream = out; ctx->outstream = out;

View File

@ -62,6 +62,12 @@ typedef enum
operations the Dirmngr is not required and thus no such event operations the Dirmngr is not required and thus no such event
will be logged. */ will be logged. */
AUDIT_GPG_READY, /* err */
/* Indicates whether the Gpg engine is available. */
AUDIT_GPGSM_READY, /* err */
/* Indicates whether the Gpgsm engine is available. */
AUDIT_GOT_DATA, AUDIT_GOT_DATA,
/* Data to be processed has been seen. */ /* Data to be processed has been seen. */
@ -72,15 +78,27 @@ typedef enum
/* A certifciate only signature has been detected. */ /* A certifciate only signature has been detected. */
AUDIT_DATA_HASH_ALGO, /* int */ AUDIT_DATA_HASH_ALGO, /* int */
/* The hash algo given as argument is used for this signature. /* The hash algo given as argument is used for the data. This
This event will be repeated for all hash algorithms used with event will be repeated for all hash algorithms used with the
the data. */ 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 */ AUDIT_BAD_DATA_HASH_ALGO, /* string */
/* The hash algo as specified by the signature can't be used. /* The hash algo as specified by the signature can't be used.
STRING is the description of this algorithm which usually is an STRING is the description of this algorithm which usually is an
OID string. STRING may be NULL. */ 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 */ AUDIT_DATA_HASHING, /* ok_err */
/* Logs the result of the data hashing. */ /* Logs the result of the data hashing. */
@ -109,7 +127,7 @@ typedef enum
certificate used for verification. An example for STRING when certificate used for verification. An example for STRING when
using CMS is: "#1234/CN=Prostetnic Vogon Jeltz". */ 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 /* The signature status of the current signer. This is the last
audit information for one signature. STRING gives the status: audit information for one signature. STRING gives the status:
@ -121,6 +139,24 @@ typedef enum
"good" - good signature "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, AUDIT_VALIDATE_CHAIN,
/* Start the validation of a certificate chain. */ /* Start the validation of a certificate chain. */
@ -158,7 +194,12 @@ typedef enum
AUDIT_ENCRYPTION_DONE, AUDIT_ENCRYPTION_DONE,
/* Encryption succeeded. */ /* 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. */ AUDIT_LAST_EVENT /* Marker for parsing this list. */

View File

@ -3,6 +3,8 @@
* gpg.c (set_debug): Allow for numerical debug levels. Print * gpg.c (set_debug): Allow for numerical debug levels. Print
active debug flags. active debug flags.
* gpg.c (gpgconf_list): Add key "default_pubkey_algo".
2009-09-28 Werner Koch <wk@g10code.com> 2009-09-28 Werner Koch <wk@g10code.com>
* trustdb.c (get_validity_info): Take care of a NULL PK. Fixes * trustdb.c (get_validity_info): Take care of a NULL PK. Fixes

View File

@ -1613,6 +1613,11 @@ gpgconf_list (const char *configfile)
printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT); printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
printf ("group:%lu:\n", GC_OPT_FLAG_NONE); printf ("group:%lu:\n", GC_OPT_FLAG_NONE);
/* The next one is an info only item and should match what
keygen:ask_keysize actually implements. */
printf ("default_pubkey_algo:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT,
"RSA-2048");
xfree (configfile_esc); xfree (configfile_esc);
} }

View File

@ -1765,6 +1765,8 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
static unsigned static unsigned
ask_keysize (int algo, unsigned int primary_keysize) ask_keysize (int algo, unsigned int primary_keysize)
{ {
/* NOTE: If you change the default key size/algo, remember to change
it also in gpg.c:gpgconf_list. */
unsigned int nbits, min, def=2048, max=4096; unsigned int nbits, min, def=2048, max=4096;
int for_subkey = !!primary_keysize; int for_subkey = !!primary_keysize;
int autocomp = 0; int autocomp = 0;

View File

@ -1,3 +1,18 @@
2009-12-03 Werner Koch <wk@g10code.com>
From trunk:
* verify.c (gpgsm_verify): Add audit info on hash algorithms.
* sign.c (gpgsm_sign): Add audit log calls.
(hash_data): Return an error indicator.
* decrypt.c (gpgsm_decrypt): Add audit log calls.
* gpgsm.c: New option --html-audit-log.
* certreqgen.c (proc_parameters): Change fallback key length to
2048.
* gpgsm.c (main) <aGpgConfList>: Add key "default_pubkey_algo".
2009-12-03 Werner Koch <wk@g10code.com> 2009-12-03 Werner Koch <wk@g10code.com>
* gpgsm.c (set_debug): Allow for numerical debug levels. Print * gpgsm.c (set_debug): Allow for numerical debug levels. Print

View File

@ -61,7 +61,7 @@ The format of the native parameter file is follows:
This is a required parameter. For now the only supported This is a required parameter. For now the only supported
algorithm is "rsa". algorithm is "rsa".
Key-Length: <length-in-bits> Key-Length: <length-in-bits>
Length of the key in bits. Default is 1024. Length of the key in bits. Default is 2048.
Key-Grip: hexstring Key-Grip: hexstring
This is optional and used to generate a request for an already This is optional and used to generate a request for an already
existing key. Key-Length will be ignored when given, existing key. Key-Length will be ignored when given,
@ -83,7 +83,7 @@ Here is an example:
$ cat >foo <<EOF $ cat >foo <<EOF
%echo Generating a standard key %echo Generating a standard key
Key-Type: RSA Key-Type: RSA
Key-Length: 1024 Key-Length: 2048
Name-DN: CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE Name-DN: CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE
Name-Email: joe@foo.bar Name-Email: joe@foo.bar
# Do a commit here, so that we can later print "done" :-) # Do a commit here, so that we can later print "done" :-)
@ -477,7 +477,7 @@ proc_parameters (ctrl_t ctrl,
/* Check the keylength. */ /* Check the keylength. */
if (!get_parameter (para, pKEYLENGTH, 0)) if (!get_parameter (para, pKEYLENGTH, 0))
nbits = 1024; nbits = 2048;
else else
nbits = get_parameter_uint (para, pKEYLENGTH); nbits = get_parameter_uint (para, pKEYLENGTH);
if ((nbits < 1024 || nbits > 4096) && !cardkeyid) if ((nbits < 1024 || nbits > 4096) && !cardkeyid)

View File

@ -253,6 +253,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
memset (&dfparm, 0, sizeof dfparm); memset (&dfparm, 0, sizeof dfparm);
audit_set_type (ctrl->audit, AUDIT_TYPE_DECRYPT);
kh = keydb_new (0); kh = keydb_new (0);
if (!kh) if (!kh)
{ {
@ -296,6 +298,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
goto leave; goto leave;
} }
audit_log (ctrl->audit, AUDIT_SETUP_READY);
/* Parser loop. */ /* Parser loop. */
do do
{ {
@ -313,6 +317,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
const char *algoid; const char *algoid;
int any_key = 0; int any_key = 0;
audit_log (ctrl->audit, AUDIT_GOT_DATA);
algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/); algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
algo = gcry_cipher_map_name (algoid); algo = gcry_cipher_map_name (algoid);
mode = gcry_cipher_mode_from_oid (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); sprintf (numbuf, "%d", rc);
gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm", gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
numbuf, algoid?algoid:"?", NULL); 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 /* 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; goto leave;
} }
audit_log_i (ctrl->audit, AUDIT_DATA_CIPHER_ALGO, algo);
dfparm.algo = algo; dfparm.algo = algo;
dfparm.mode = mode; dfparm.mode = mode;
dfparm.blklen = gcry_cipher_get_algo_blklen (algo); 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); rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
if (rc == -1 && recp) if (rc == -1 && recp)
break; /* no more recipients */ break; /* no more recipients */
audit_log_i (ctrl->audit, AUDIT_NEW_RECP, recp);
if (rc) if (rc)
log_error ("recp %d - error getting info: %s\n", log_error ("recp %d - error getting info: %s\n",
recp, gpg_strerror (rc)); recp, gpg_strerror (rc));
@ -382,6 +392,13 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
gpgsm_dump_serial (serial); gpgsm_dump_serial (serial);
log_printf ("\n"); 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); keydb_search_reset (kh);
rc = keydb_search_issuer_sn (kh, issuer, serial); rc = keydb_search_issuer_sn (kh, issuer, serial);
if (rc) if (rc)
@ -415,6 +432,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
kidbuf, "0", "0", NULL); 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 /* Just in case there is a problem with the own
certificate we print this message - should never certificate we print this message - should never
@ -462,10 +481,41 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
decrypt_filter, decrypt_filter,
&dfparm); &dfparm);
} }
audit_log_ok (ctrl->audit, AUDIT_RECP_RESULT, rc);
} }
xfree (hexkeygrip); xfree (hexkeygrip);
xfree (desc); 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) if (!any_key)
{ {
rc = gpg_error (GPG_ERR_NO_SECKEY); 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.lastblock,
dfparm.blklen - npadding); dfparm.blklen - npadding);
if (rc) if (rc)
goto leave; goto leave;
for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++) 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: leave:
audit_log_ok (ctrl->audit, AUDIT_DECRYPTION_RESULT, rc);
if (rc) if (rc)
{ {
gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL); gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);

View File

@ -99,6 +99,7 @@ enum cmd_and_opt_values {
oLogFile, oLogFile,
oNoLogFile, oNoLogFile,
oAuditLog, oAuditLog,
oHtmlAuditLog,
oEnableSpecialFilenames, oEnableSpecialFilenames,
@ -286,6 +287,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oAuditLog, "audit-log", ARGPARSE_s_s (oAuditLog, "audit-log",
N_("|FILE|write an audit log to FILE")), 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 (oDryRun, "dry-run", N_("do not make any changes")),
ARGPARSE_s_n (oBatch, "batch", N_("batch mode: never ask")), ARGPARSE_s_n (oBatch, "batch", N_("batch mode: never ask")),
ARGPARSE_s_n (oAnswerYes, "yes", N_("assume yes on most questions")), ARGPARSE_s_n (oAnswerYes, "yes", N_("assume yes on most questions")),
@ -863,6 +865,7 @@ main ( int argc, char **argv)
int default_keyring = 1; int default_keyring = 1;
char *logfile = NULL; char *logfile = NULL;
char *auditlog = NULL; char *auditlog = NULL;
char *htmlauditlog = NULL;
int greeting = 0; int greeting = 0;
int nogreeting = 0; int nogreeting = 0;
int debug_wait = 0; int debug_wait = 0;
@ -878,6 +881,7 @@ main ( int argc, char **argv)
int do_not_setup_keys = 0; int do_not_setup_keys = 0;
int recp_required = 0; int recp_required = 0;
estream_t auditfp = NULL; estream_t auditfp = NULL;
estream_t htmlauditfp = NULL;
/*mtrace();*/ /*mtrace();*/
@ -1194,6 +1198,7 @@ main ( int argc, char **argv)
case oNoLogFile: logfile = NULL; break; case oNoLogFile: logfile = NULL; break;
case oAuditLog: auditlog = pargs.r.ret_str; break; case oAuditLog: auditlog = pargs.r.ret_str; break;
case oHtmlAuditLog: htmlauditlog = pargs.r.ret_str; break;
case oBatch: case oBatch:
opt.batch = 1; opt.batch = 1;
@ -1422,11 +1427,6 @@ main ( int argc, char **argv)
} }
# endif # 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) if (may_coredump && !opt.quiet)
log_info (_("WARNING: program may create a core file!\n")); log_info (_("WARNING: program may create a core file!\n"));
@ -1558,7 +1558,7 @@ main ( int argc, char **argv)
/* Prepare the audit log feature for certain commands. */ /* Prepare the audit log feature for certain commands. */
if (auditlog) if (auditlog || htmlauditlog)
{ {
switch (cmd) switch (cmd)
{ {
@ -1568,7 +1568,10 @@ main ( int argc, char **argv)
case aVerify: case aVerify:
audit_release (ctrl.audit); audit_release (ctrl.audit);
ctrl.audit = audit_new (); ctrl.audit = audit_new ();
auditfp = open_es_fwrite (auditlog); if (auditlog)
auditfp = open_es_fwrite (auditlog);
if (htmlauditlog)
htmlauditfp = open_es_fwrite (htmlauditlog);
break; break;
default: default:
break; break;
@ -1645,6 +1648,10 @@ main ( int argc, char **argv)
printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_DEFAULT); printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_DEFAULT);
printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE); printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE);
/* The next one is an info only item and should match what
proc_parameters actually implements. */
printf ("default_pubkey_algo:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT,
"RSA-2048");
} }
break; break;
case aGPGConfTest: case aGPGConfTest:
@ -1920,12 +1927,16 @@ main ( int argc, char **argv)
} }
/* Print the audit result if needed. */ /* 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); audit_release (ctrl.audit);
ctrl.audit = NULL; ctrl.audit = NULL;
es_fclose (auditfp); es_fclose (auditfp);
es_fclose (htmlauditfp);
} }
/* cleanup */ /* cleanup */

View File

@ -34,18 +34,20 @@
#include "i18n.h" #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) hash_data (int fd, gcry_md_hd_t md)
{ {
FILE *fp; FILE *fp;
char buffer[4096]; char buffer[4096];
int nread; int nread;
int rc = 0;
fp = fdopen ( dup (fd), "rb"); fp = fdopen ( dup (fd), "rb");
if (!fp) if (!fp)
{ {
log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
return; return -1;
} }
do do
@ -55,8 +57,12 @@ hash_data (int fd, gcry_md_hd_t md)
} }
while (nread); while (nread);
if (ferror (fp)) if (ferror (fp))
{
log_error ("read error on fd %d: %s\n", fd, strerror (errno)); log_error ("read error on fd %d: %s\n", fd, strerror (errno));
rc = -1;
}
fclose (fp); fclose (fp);
return rc;
} }
static int static int
@ -321,6 +327,8 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
certlist_t cl; certlist_t cl;
int release_signerlist = 0; int release_signerlist = 0;
audit_set_type (ctrl->audit, AUDIT_TYPE_SIGN);
kh = keydb_new (0); kh = keydb_new (0);
if (!kh) if (!kh)
{ {
@ -539,8 +547,11 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
goto leave; goto leave;
} }
gcry_md_enable (data_md, algo); 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) if (detached)
{ /* We hash the data right now so that we can store the message { /* We hash the data right now so that we can store the message
digest. ksba_cms_build() takes this as an flag that detached 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; unsigned char *digest;
size_t digest_len; 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++) for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
{ {
digest = gcry_md_read (data_md, cl->hash_algo); 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); rc = hash_and_copy_data (data_fd, data_md, writer);
if (rc) if (rc)
goto leave; goto leave;
audit_log (ctrl->audit, AUDIT_GOT_DATA);
for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
{ {
digest = gcry_md_read (data_md, cl->hash_algo); 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; unsigned char *sigval = NULL;
char *buf, *fpr; char *buf, *fpr;
audit_log_i (ctrl->audit, AUDIT_NEW_SIG, signer);
if (signer) if (signer)
gcry_md_reset (md); gcry_md_reset (md);
{ {
certlist_t cl_tmp; certlist_t cl_tmp;
for (cl_tmp=signerlist; cl_tmp; cl_tmp = cl_tmp->next) 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); 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); md, cl->hash_algo, &sigval);
if (rc) if (rc)
{ {
audit_log_cert (ctrl->audit, AUDIT_SIGNED_BY, cl->cert, rc);
gcry_md_close (md); gcry_md_close (md);
goto leave; goto leave;
} }
@ -693,6 +712,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
xfree (sigval); xfree (sigval);
if (err) if (err)
{ {
audit_log_cert (ctrl->audit, AUDIT_SIGNED_BY, cl->cert, err);
log_error ("failed to store the signature: %s\n", log_error ("failed to store the signature: %s\n",
gpg_strerror (err)); gpg_strerror (err));
rc = err; rc = err;
@ -708,28 +728,29 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
gcry_md_close (md); gcry_md_close (md);
goto leave; goto leave;
} }
rc = 0;
{ {
int pkalgo = gpgsm_get_key_algo_info (cl->cert, NULL); int pkalgo = gpgsm_get_key_algo_info (cl->cert, NULL);
rc = asprintf (&buf, "%c %d %d 00 %s %s", buf = xtryasprintf ("%c %d %d 00 %s %s",
detached? 'D':'S', detached? 'D':'S',
pkalgo, pkalgo,
cl->hash_algo, cl->hash_algo,
signed_at, signed_at,
fpr); fpr);
if (!buf)
rc = gpg_error_from_syserror ();
} }
xfree (fpr); xfree (fpr);
if (rc < 0) if (rc)
{ {
rc = gpg_error (GPG_ERR_ENOMEM);
gcry_md_close (md); gcry_md_close (md);
goto leave; goto leave;
} }
rc = 0;
gpgsm_status (ctrl, STATUS_SIG_CREATED, buf); 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); gcry_md_close (md);
} }
} }
while (stopreason != KSBA_SR_READY); while (stopreason != KSBA_SR_READY);
@ -741,6 +762,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
goto leave; goto leave;
} }
audit_log (ctrl->audit, AUDIT_SIGNING_DONE);
log_info ("signature created\n"); log_info ("signature created\n");

View 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", log_debug ("enabling extra hash algorithm %d\n",
opt.extra_digest_algo); opt.extra_digest_algo);
gcry_md_enable (data_md, 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) 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) else if (stopreason == KSBA_SR_END_DATA)
{ /* The data bas been hashed */ { /* The data bas been hashed */
audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING, 0);
} }
} }
while (stopreason != KSBA_SR_READY); 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"), log_printf (_(" using certificate ID 0x%08lX\n"),
gpgsm_get_short_fingerprint (cert, NULL)); gpgsm_get_short_fingerprint (cert, NULL));
audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
if (msgdigest) if (msgdigest)
{ /* Signed attributes are available. */ { /* 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; goto next_signer;
} }
audit_log_i (ctrl->audit, AUDIT_ATTR_HASH_ALGO, sigval_hash_algo);
rc = gcry_md_open (&md, sigval_hash_algo, 0); rc = gcry_md_open (&md, sigval_hash_algo, 0);
if (rc) if (rc)
{ {