From 9e834047519bbaffd54bc20590a4625e9622883e Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 2 Dec 2009 18:33:59 +0000 Subject: More stuff for the audit-log. --- common/ChangeLog | 8 +++ common/audit.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++------ common/audit.h | 45 ++++++++++-- 3 files changed, 239 insertions(+), 28 deletions(-) (limited to 'common') 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 + + * 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 * 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. */ -- cgit v1.2.3