1 /* audit.c - GnuPG's audit subsystem
2 * Copyright (C) 2007, 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <https://www.gnu.org/licenses/>.
29 #include "audit-events.h"
31 /* A list to maintain a list of helptags. */
34 struct helptag_s *next;
37 typedef struct helptag_s *helptag_t;
43 audit_event_t event; /* The event. */
44 gpg_error_t err; /* The logged error code. */
45 int intvalue; /* A logged integer value. */
46 char *string; /* A malloced string or NULL. */
47 ksba_cert_t cert; /* A certifciate or NULL. */
51 typedef struct log_item_s *log_item_t;
55 /* The main audit object. */
58 const char *failure; /* If set a description of the internal failure. */
61 log_item_t log; /* The table with the log entries. */
62 size_t logsize; /* The allocated size for LOG. */
63 size_t logused; /* The used size of LOG. */
65 estream_t outstream; /* The current output stream. */
66 int use_html; /* The output shall be HTML formatted. */
67 int indentlevel; /* Current level of indentation. */
68 helptag_t helptags; /* List of help keys. */
74 static void writeout_para (audit_ctx_t ctx,
75 const char *format, ...) GPGRT_ATTR_PRINTF(2,3);
76 static void writeout_li (audit_ctx_t ctx, const char *oktext,
77 const char *format, ...) GPGRT_ATTR_PRINTF(3,4);
78 static void writeout_rem (audit_ctx_t ctx,
79 const char *format, ...) GPGRT_ATTR_PRINTF(2,3);
82 /* Add NAME to the list of help tags. NAME needs to be a const string
83 an this function merly stores this pointer. */
85 add_helptag (audit_ctx_t ctx, const char *name)
89 for (item=ctx->helptags; item; item = item->next)
90 if (!strcmp (item->name, name))
91 return; /* Already in the list. */
92 item = xtrycalloc (1, sizeof *item);
94 return; /* Don't care about memory problems. */
96 item->next = ctx->helptags;
101 /* Remove all help tags from the context. */
103 clear_helptags (audit_ctx_t ctx)
105 while (ctx->helptags)
107 helptag_t tmp = ctx->helptags->next;
108 xfree (ctx->helptags);
116 event2str (audit_event_t event)
118 /* We need the cast so that compiler does not complain about an
119 always true comparison (>= 0) for an unsigned value. */
120 int idx = eventstr_msgidxof ((int)event);
122 return "Unknown event";
124 return eventstr_msgstr + eventstr_msgidx[idx];
129 /* Create a new audit context. In case of an error NULL is returned
130 and errno set appropriately. */
136 ctx = xtrycalloc (1, sizeof *ctx);
142 /* Release an audit context. Passing NULL for CTX is allowed and does
145 audit_release (audit_ctx_t ctx)
152 for (idx=0; idx < ctx->logused; idx++)
154 if (ctx->log[idx].string)
155 xfree (ctx->log[idx].string);
156 if (ctx->log[idx].cert)
157 ksba_cert_release (ctx->log[idx].cert);
161 clear_helptags (ctx);
166 /* Set the type for the audit operation. If CTX is NULL, this is a
169 audit_set_type (audit_ctx_t ctx, audit_type_t type)
171 if (!ctx || ctx->failure)
172 return; /* Audit not enabled or an internal error has occurred. */
174 if (ctx->type && ctx->type != type)
176 ctx->failure = "conflict in type initialization";
183 /* Create a new log item and put it into the table. Return that log
184 item on success; return NULL on memory failure and mark that in
187 create_log_item (audit_ctx_t ctx)
189 log_item_t item, table;
195 table = xtrymalloc (size * sizeof *table);
198 ctx->failure = "Out of memory in create_log_item";
206 else if (ctx->logused >= ctx->logsize)
208 size = ctx->logsize + 10;
209 table = xtryrealloc (ctx->log, size * sizeof *table);
212 ctx->failure = "Out of memory while reallocating in create_log_item";
217 item = ctx->log + ctx->logused++;
220 item = ctx->log + ctx->logused++;
222 item->event = AUDIT_NULL_EVENT;
226 item->have_intvalue = 0;
234 /* Add a new event to the audit log. If CTX is NULL, this function
237 audit_log (audit_ctx_t ctx, audit_event_t event)
241 if (!ctx || ctx->failure)
242 return; /* Audit not enabled or an internal error has occurred. */
245 ctx->failure = "Invalid event passed to audit_log";
248 if (!(item = create_log_item (ctx)))
253 /* Add a new event to the audit log. If CTX is NULL, this function
254 does nothing. This version also adds the result of the operation
257 audit_log_ok (audit_ctx_t ctx, audit_event_t event, gpg_error_t err)
261 if (!ctx || ctx->failure)
262 return; /* Audit not enabled or an internal error has occurred. */
265 ctx->failure = "Invalid event passed to audit_log_ok";
268 if (!(item = create_log_item (ctx)))
276 /* Add a new event to the audit log. If CTX is NULL, this function
277 does nothing. This version also add the integer VALUE to the log. */
279 audit_log_i (audit_ctx_t ctx, audit_event_t event, int value)
283 if (!ctx || ctx->failure)
284 return; /* Audit not enabled or an internal error has occurred. */
287 ctx->failure = "Invalid event passed to audit_log_i";
290 if (!(item = create_log_item (ctx)))
293 item->intvalue = value;
294 item->have_intvalue = 1;
298 /* Add a new event to the audit log. If CTX is NULL, this function
299 does nothing. This version also add the integer VALUE to the log. */
301 audit_log_s (audit_ctx_t ctx, audit_event_t event, const char *value)
306 if (!ctx || ctx->failure)
307 return; /* Audit not enabled or an internal error has occurred. */
310 ctx->failure = "Invalid event passed to audit_log_s";
313 tmp = xtrystrdup (value? value : "");
316 ctx->failure = "Out of memory in audit_event";
319 if (!(item = create_log_item (ctx)))
328 /* Add a new event to the audit log. If CTX is NULL, this function
329 does nothing. This version also adds the certificate CERT and the
330 result of an operation to the log. */
332 audit_log_cert (audit_ctx_t ctx, audit_event_t event,
333 ksba_cert_t cert, gpg_error_t err)
337 if (!ctx || ctx->failure)
338 return; /* Audit not enabled or an internal error has occurred. */
341 ctx->failure = "Invalid event passed to audit_log_cert";
344 if (!(item = create_log_item (ctx)))
351 ksba_cert_ref (cert);
357 /* Write TEXT to the outstream. */
359 writeout (audit_ctx_t ctx, const char *text)
363 for (; *text; text++)
366 es_fputs ("<", ctx->outstream);
367 else if (*text == '&')
368 es_fputs ("&", ctx->outstream);
370 es_putc (*text, ctx->outstream);
374 es_fputs (text, ctx->outstream);
378 /* Write TEXT to the outstream using a variable argument list. */
380 writeout_v (audit_ctx_t ctx, const char *format, va_list arg_ptr)
384 gpgrt_vasprintf (&buf, format, arg_ptr);
391 writeout (ctx, "[!!Out of core!!]");
395 /* Write TEXT as a paragraph. */
397 writeout_para (audit_ctx_t ctx, const char *format, ...)
402 es_fputs ("<p>", ctx->outstream);
403 va_start (arg_ptr, format) ;
404 writeout_v (ctx, format, arg_ptr);
407 es_fputs ("</p>\n", ctx->outstream);
409 es_fputc ('\n', ctx->outstream);
414 enter_li (audit_ctx_t ctx)
418 if (!ctx->indentlevel)
420 es_fputs ("<table border=\"0\">\n"
422 " <col width=\"80%\" />\n"
423 " <col width=\"20%\" />\n"
433 leave_li (audit_ctx_t ctx)
438 if (!ctx->indentlevel)
439 es_fputs ("</table>\n", ctx->outstream);
444 /* Write TEXT as a list element. If OKTEXT is not NULL, append it to
447 writeout_li (audit_ctx_t ctx, const char *oktext, const char *format, ...)
450 const char *color = NULL;
452 if (ctx->use_html && format && oktext)
454 if (!strcmp (oktext, "Yes")
455 || !strcmp (oktext, "good") )
457 else if (!strcmp (oktext, "No")
458 || !strcmp (oktext, "bad") )
462 if (format && oktext)
464 const char *s = NULL;
466 if (!strcmp (oktext, "Yes"))
468 else if (!strcmp (oktext, "No"))
470 else if (!strcmp (oktext, "good"))
472 /* TRANSLATORS: Copy the prefix between the vertical bars
473 verbatim. It will not be printed. */
474 oktext = _("|audit-log-result|Good");
476 else if (!strcmp (oktext, "bad"))
477 oktext = _("|audit-log-result|Bad");
478 else if (!strcmp (oktext, "unsupported"))
479 oktext = _("|audit-log-result|Not supported");
480 else if (!strcmp (oktext, "no-cert"))
481 oktext = _("|audit-log-result|No certificate");
482 else if (!strcmp (oktext, "disabled"))
483 oktext = _("|audit-log-result|Not enabled");
484 else if (!strcmp (oktext, "error"))
485 oktext = _("|audit-log-result|Error");
486 else if (!strcmp (oktext, "not-used"))
487 oktext = _("|audit-log-result|Not used");
488 else if (!strcmp (oktext, "okay"))
489 oktext = _("|audit-log-result|Okay");
490 else if (!strcmp (oktext, "skipped"))
491 oktext = _("|audit-log-result|Skipped");
492 else if (!strcmp (oktext, "some"))
493 oktext = _("|audit-log-result|Some");
497 /* If we have set a prefix, skip it. */
498 if (!s && *oktext == '|' && (s=strchr (oktext+1,'|')))
506 es_fputs (" <tr><td><table><tr><td>", ctx->outstream);
508 es_fprintf (ctx->outstream, "<font color=\"%s\">*</font>", color);
510 es_fputs ("*", ctx->outstream);
511 for (i=1; i < ctx->indentlevel; i++)
512 es_fputs (" ", ctx->outstream);
513 es_fputs ("</td><td>", ctx->outstream);
516 es_fprintf (ctx->outstream, "* %*s", (ctx->indentlevel-1)*2, "");
519 va_start (arg_ptr, format) ;
520 writeout_v (ctx, format, arg_ptr);
524 es_fputs ("</td></tr></table>", ctx->outstream);
525 if (format && oktext)
529 es_fputs ("</td><td>", ctx->outstream);
531 es_fprintf (ctx->outstream, "<font color=\"%s\">", color);
534 writeout (ctx, ": ");
535 writeout (ctx, oktext);
537 es_fputs ("</font>", ctx->outstream);
541 es_fputs ("</td></tr>\n", ctx->outstream);
543 es_fputc ('\n', ctx->outstream);
547 /* Write a remark line. */
549 writeout_rem (audit_ctx_t ctx, const char *format, ...)
557 es_fputs (" <tr><td><table><tr><td>*", ctx->outstream);
558 for (i=1; i < ctx->indentlevel; i++)
559 es_fputs (" ", ctx->outstream);
560 es_fputs (" </td><td> (", ctx->outstream);
564 es_fprintf (ctx->outstream, "* %*s (", (ctx->indentlevel-1)*2, "");
567 va_start (arg_ptr, format) ;
568 writeout_v (ctx, format, arg_ptr);
572 es_fputs (")</td></tr></table></td></tr>\n", ctx->outstream);
574 es_fputs (")\n", ctx->outstream);
578 /* Return the first log item for EVENT. If STOPEVENT is not 0 never
579 look behind that event in the log. If STARTITEM is not NULL start
580 search _after_that item. */
582 find_next_log_item (audit_ctx_t ctx, log_item_t startitem,
583 audit_event_t event, audit_event_t stopevent)
587 for (idx=0; idx < ctx->logused; idx++)
591 if (ctx->log + idx == startitem)
594 else if (stopevent && ctx->log[idx].event == stopevent)
596 else if (ctx->log[idx].event == event)
597 return ctx->log + idx;
604 find_log_item (audit_ctx_t ctx, audit_event_t event, audit_event_t stopevent)
606 return find_next_log_item (ctx, NULL, event, stopevent);
610 /* Helper to a format a serial number. */
612 format_serial (ksba_const_sexp_t sn)
614 const char *p = (const char *)sn;
621 BUG (); /* Not a valid S-expression. */
622 n = strtoul (p+1, &endp, 10);
625 BUG (); /* Not a valid S-expression. */
626 return bin2hex (p+1, n, NULL);
630 /* Return a malloced string with the serial number and the issuer DN
631 of the certificate. */
633 get_cert_name (ksba_cert_t cert)
640 return xtrystrdup ("[no certificate]");
642 issuer = ksba_cert_get_issuer (cert, 0);
643 sn = ksba_cert_get_serial (cert);
646 p = format_serial (sn);
648 result = xtrystrdup ("[invalid S/N]");
651 result = xtrymalloc (strlen (p) + strlen (issuer) + 2 + 1);
655 strcpy (stpcpy (stpcpy (result+1, p),"/"), issuer);
661 result = xtrystrdup ("[missing S/N or issuer]");
667 /* Return a malloced string with the serial number and the issuer DN
668 of the certificate. */
670 get_cert_subject (ksba_cert_t cert, int idx)
676 return xtrystrdup ("[no certificate]");
678 subject = ksba_cert_get_subject (cert, idx);
681 result = xtrymalloc (strlen (subject) + 1 + 1);
685 strcpy (result+1, subject);
695 /* List the given certificiate. If CERT is NULL, this is a NOP. */
697 list_cert (audit_ctx_t ctx, ksba_cert_t cert, int with_subj)
702 name = get_cert_name (cert);
703 writeout_rem (ctx, "%s", name);
708 for (idx=0; (name = get_cert_subject (cert, idx)); idx++)
710 writeout_rem (ctx, "%s", name);
718 /* List the chain of certificates from STARTITEM up to STOPEVENT. The
719 certifcates are written out as comments. */
721 list_certchain (audit_ctx_t ctx, log_item_t startitem, audit_event_t stopevent)
725 startitem = find_next_log_item (ctx, startitem, AUDIT_CHAIN_BEGIN,stopevent);
726 writeout_li (ctx, startitem? "Yes":"No", _("Certificate chain available"));
730 item = find_next_log_item (ctx, startitem,
731 AUDIT_CHAIN_ROOTCERT, AUDIT_CHAIN_END);
733 writeout_rem (ctx, "%s", _("root certificate missing"));
736 list_cert (ctx, item->cert, 0);
739 while ( ((item = find_next_log_item (ctx, item,
740 AUDIT_CHAIN_CERT, AUDIT_CHAIN_END))))
742 list_cert (ctx, item->cert, 1);
748 /* Process an encrypt operation's log. */
750 proc_type_encrypt (audit_ctx_t ctx)
752 log_item_t loopitem, item;
758 item = find_log_item (ctx, AUDIT_ENCRYPTION_DONE, 0);
759 writeout_li (ctx, item?"Yes":"No", "%s", _("Data encryption succeeded"));
763 item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
764 writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
766 item = find_log_item (ctx, AUDIT_SESSION_KEY, 0);
767 writeout_li (ctx, item? "Yes":"No", "%s", _("Session key created"));
770 algo = gcry_cipher_map_name (item->string);
772 writeout_rem (ctx, _("algorithm: %s"), gnupg_cipher_algo_name (algo));
773 else if (item->string && !strcmp (item->string, "1.2.840.113549.3.2"))
774 writeout_rem (ctx, _("unsupported algorithm: %s"), "RC2");
775 else if (item->string)
776 writeout_rem (ctx, _("unsupported algorithm: %s"), item->string);
778 writeout_rem (ctx, _("seems to be not encrypted"));
781 item = find_log_item (ctx, AUDIT_GOT_RECIPIENTS, 0);
782 snprintf (numbuf, sizeof numbuf, "%d",
783 item && item->have_intvalue? item->intvalue : 0);
784 writeout_li (ctx, numbuf, "%s", _("Number of recipients"));
786 /* Loop over all recipients. */
789 while ((loopitem=find_next_log_item (ctx, loopitem, AUDIT_ENCRYPTED_TO, 0)))
792 writeout_li (ctx, NULL, _("Recipient %d"), recp_no);
795 name = get_cert_name (loopitem->cert);
796 writeout_rem (ctx, "%s", name);
799 for (idx=0; (name = get_cert_subject (loopitem->cert, idx)); idx++)
801 writeout_rem (ctx, "%s", name);
813 /* Process a sign operation's log. */
815 proc_type_sign (audit_ctx_t ctx)
817 log_item_t item, loopitem;
824 item = find_log_item (ctx, AUDIT_SIGNING_DONE, 0);
825 writeout_li (ctx, item?"Yes":"No", "%s", _("Data signing succeeded"));
829 item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
830 writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
831 /* Write remarks with the data hash algorithms. We use a very
832 simple scheme to avoid some duplicates. */
835 while ((loopitem = find_next_log_item
836 (ctx, loopitem, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG)))
838 if (loopitem->intvalue && loopitem->intvalue != lastalgo)
839 writeout_rem (ctx, _("data hash algorithm: %s"),
840 gcry_md_algo_name (loopitem->intvalue));
841 lastalgo = loopitem->intvalue;
844 /* Loop over all signer. */
847 while ((loopitem=find_next_log_item (ctx, loopitem, AUDIT_NEW_SIG, 0)))
851 item = find_next_log_item (ctx, loopitem, AUDIT_SIGNED_BY, AUDIT_NEW_SIG);
856 else if (gpg_err_code (item->err) == GPG_ERR_CANCELED)
859 result = gpg_strerror (item->err);
860 cert = item? item->cert : NULL;
862 writeout_li (ctx, result, _("Signer %d"), signer);
863 item = find_next_log_item (ctx, loopitem,
864 AUDIT_ATTR_HASH_ALGO, AUDIT_NEW_SIG);
866 writeout_rem (ctx, _("attr hash algorithm: %s"),
867 gcry_md_algo_name (item->intvalue));
871 name = get_cert_name (cert);
872 writeout_rem (ctx, "%s", name);
875 for (idx=0; (name = get_cert_subject (cert, idx)); idx++)
877 writeout_rem (ctx, "%s", name);
889 /* Process a decrypt operation's log. */
891 proc_type_decrypt (audit_ctx_t ctx)
893 log_item_t loopitem, item;
899 item = find_log_item (ctx, AUDIT_DECRYPTION_RESULT, 0);
900 writeout_li (ctx, item && !item->err?"Yes":"No",
901 "%s", _("Data decryption succeeded"));
905 item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
906 writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
908 item = find_log_item (ctx, AUDIT_DATA_CIPHER_ALGO, 0);
909 algo = item? item->intvalue : 0;
910 writeout_li (ctx, algo?"Yes":"No", "%s", _("Encryption algorithm supported"));
912 writeout_rem (ctx, _("algorithm: %s"), gnupg_cipher_algo_name (algo));
914 item = find_log_item (ctx, AUDIT_BAD_DATA_CIPHER_ALGO, 0);
915 if (item && item->string)
917 algo = gcry_cipher_map_name (item->string);
919 writeout_rem (ctx, _("algorithm: %s"), gnupg_cipher_algo_name (algo));
920 else if (item->string && !strcmp (item->string, "1.2.840.113549.3.2"))
921 writeout_rem (ctx, _("unsupported algorithm: %s"), "RC2");
922 else if (item->string)
923 writeout_rem (ctx, _("unsupported algorithm: %s"), item->string);
925 writeout_rem (ctx, _("seems to be not encrypted"));
929 for (recpno = 0, item = NULL;
930 (item = find_next_log_item (ctx, item, AUDIT_NEW_RECP, 0)); recpno++)
932 snprintf (numbuf, sizeof numbuf, "%d", recpno);
933 writeout_li (ctx, numbuf, "%s", _("Number of recipients"));
935 /* Loop over all recipients. */
937 while ((loopitem = find_next_log_item (ctx, loopitem, AUDIT_NEW_RECP, 0)))
941 recpno = loopitem->have_intvalue? loopitem->intvalue : -1;
943 item = find_next_log_item (ctx, loopitem,
944 AUDIT_RECP_RESULT, AUDIT_NEW_RECP);
949 else if (gpg_err_code (item->err) == GPG_ERR_CANCELED)
952 result = gpg_strerror (item->err);
954 item = find_next_log_item (ctx, loopitem,
955 AUDIT_RECP_NAME, AUDIT_NEW_RECP);
956 writeout_li (ctx, result, _("Recipient %d"), recpno);
957 if (item && item->string)
958 writeout_rem (ctx, "%s", item->string);
960 /* If we have a certificate write out more infos. */
961 item = find_next_log_item (ctx, loopitem,
962 AUDIT_SAVE_CERT, AUDIT_NEW_RECP);
963 if (item && item->cert)
966 for (idx=0; (name = get_cert_subject (item->cert, idx)); idx++)
968 writeout_rem (ctx, "%s", name);
980 /* Process a verification operation's log. */
982 proc_type_verify (audit_ctx_t ctx)
984 log_item_t loopitem, item;
985 int signo, count, idx, n_good, n_bad;
989 /* If there is at least one signature status we claim that the
990 verification succeeded. This does not mean that the data has
992 item = find_log_item (ctx, AUDIT_SIG_STATUS, 0);
993 writeout_li (ctx, item?"Yes":"No", "%s", _("Data verification succeeded"));
996 item = find_log_item (ctx, AUDIT_GOT_DATA, AUDIT_NEW_SIG);
997 writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
1001 item = find_log_item (ctx, AUDIT_NEW_SIG, 0);
1002 writeout_li (ctx, item? "Yes":"No", "%s", _("Signature available"));
1006 /* Print info about the used data hashing algorithms. */
1007 for (idx=0, n_good=n_bad=0; idx < ctx->logused; idx++)
1009 item = ctx->log + idx;
1010 if (item->event == AUDIT_NEW_SIG)
1012 else if (item->event == AUDIT_DATA_HASH_ALGO)
1014 else if (item->event == AUDIT_BAD_DATA_HASH_ALGO)
1017 item = find_log_item (ctx, AUDIT_DATA_HASHING, AUDIT_NEW_SIG);
1018 if (!item || item->err || !n_good)
1020 else if (n_good && !n_bad)
1024 writeout_li (ctx, result, "%s", _("Parsing data succeeded"));
1025 if (n_good || n_bad)
1027 for (idx=0; idx < ctx->logused; idx++)
1029 item = ctx->log + idx;
1030 if (item->event == AUDIT_NEW_SIG)
1032 else if (item->event == AUDIT_DATA_HASH_ALGO)
1033 writeout_rem (ctx, _("data hash algorithm: %s"),
1034 gcry_md_algo_name (item->intvalue));
1035 else if (item->event == AUDIT_BAD_DATA_HASH_ALGO)
1036 writeout_rem (ctx, _("bad data hash algorithm: %s"),
1037 item->string? item->string:"?");
1042 /* Loop over all signatures. */
1043 loopitem = find_log_item (ctx, AUDIT_NEW_SIG, 0);
1047 signo = loopitem->have_intvalue? loopitem->intvalue : -1;
1049 item = find_next_log_item (ctx, loopitem,
1050 AUDIT_SIG_STATUS, AUDIT_NEW_SIG);
1051 writeout_li (ctx, item? item->string:"?", _("Signature %d"), signo);
1052 item = find_next_log_item (ctx, loopitem,
1053 AUDIT_SIG_NAME, AUDIT_NEW_SIG);
1055 writeout_rem (ctx, "%s", item->string);
1057 item = find_next_log_item (ctx, loopitem,
1058 AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG);
1060 writeout_rem (ctx, _("data hash algorithm: %s"),
1061 gcry_md_algo_name (item->intvalue));
1062 item = find_next_log_item (ctx, loopitem,
1063 AUDIT_ATTR_HASH_ALGO, AUDIT_NEW_SIG);
1065 writeout_rem (ctx, _("attr hash algorithm: %s"),
1066 gcry_md_algo_name (item->intvalue));
1070 /* List the certificate chain. */
1071 list_certchain (ctx, loopitem, AUDIT_NEW_SIG);
1073 /* Show the result of the chain validation. */
1074 item = find_next_log_item (ctx, loopitem,
1075 AUDIT_CHAIN_STATUS, AUDIT_NEW_SIG);
1076 if (item && item->have_err)
1078 writeout_li (ctx, item->err? "No":"Yes",
1079 _("Certificate chain valid"));
1081 writeout_rem (ctx, "%s", gpg_strerror (item->err));
1084 /* Show whether the root certificate is fine. */
1085 item = find_next_log_item (ctx, loopitem,
1086 AUDIT_ROOT_TRUSTED, AUDIT_CHAIN_STATUS);
1089 writeout_li (ctx, item->err?"No":"Yes", "%s",
1090 _("Root certificate trustworthy"));
1093 add_helptag (ctx, "gpgsm.root-cert-not-trusted");
1094 writeout_rem (ctx, "%s", gpg_strerror (item->err));
1095 list_cert (ctx, item->cert, 0);
1099 /* Show result of the CRL/OCSP check. */
1100 item = find_next_log_item (ctx, loopitem,
1101 AUDIT_CRL_CHECK, AUDIT_NEW_SIG);
1105 switch (gpg_err_code (item->err))
1107 case 0: ok = "good"; break;
1108 case GPG_ERR_CERT_REVOKED: ok = "bad"; break;
1109 case GPG_ERR_NOT_ENABLED: ok = "disabled"; break;
1110 case GPG_ERR_NO_CRL_KNOWN:
1111 ok = _("no CRL found for certificate");
1113 case GPG_ERR_CRL_TOO_OLD:
1114 ok = _("the available CRL is too old");
1116 default: ok = gpg_strerror (item->err); break;
1119 writeout_li (ctx, ok, "%s", _("CRL/OCSP check of certificates"));
1121 && gpg_err_code (item->err) != GPG_ERR_CERT_REVOKED
1122 && gpg_err_code (item->err) != GPG_ERR_NOT_ENABLED)
1123 add_helptag (ctx, "gpgsm.crl-problem");
1128 while ((loopitem = find_next_log_item (ctx, loopitem, AUDIT_NEW_SIG, 0)));
1132 /* Always list the certificates stored in the signature. */
1135 while ( ((item = find_next_log_item (ctx, item,
1136 AUDIT_SAVE_CERT, AUDIT_NEW_SIG))))
1138 snprintf (numbuf, sizeof numbuf, "%d", count);
1139 writeout_li (ctx, numbuf, _("Included certificates"));
1141 while ( ((item = find_next_log_item (ctx, item,
1142 AUDIT_SAVE_CERT, AUDIT_NEW_SIG))))
1144 char *name = get_cert_name (item->cert);
1145 writeout_rem (ctx, "%s", name);
1148 for (idx=0; (name = get_cert_subject (item->cert, idx)); idx++)
1150 writeout_rem (ctx, "%s", name);
1161 /* Print the formatted audit result. THIS IS WORK IN PROGRESS. */
1163 audit_print_result (audit_ctx_t ctx, estream_t out, int use_html)
1176 orig_codeset = i18n_switchto_utf8 ();
1178 /* We use an environment variable to include some debug info in the
1180 if ((s = getenv ("gnupg_debug_audit")))
1183 assert (!ctx->outstream);
1184 ctx->outstream = out;
1185 ctx->use_html = use_html;
1186 ctx->indentlevel = 0;
1187 clear_helptags (ctx);
1190 es_fputs ("<div class=\"" GNUPG_NAME "AuditLog\">\n", ctx->outstream);
1192 if (!ctx->log || !ctx->logused)
1194 writeout_para (ctx, _("No audit log entries."));
1202 for (idx=0,maxlen=0; idx < DIM (eventstr_msgidx); idx++)
1204 n = strlen (eventstr_msgstr + eventstr_msgidx[idx]);
1210 es_fputs ("<pre>\n", out);
1211 for (idx=0; idx < ctx->logused; idx++)
1213 es_fprintf (out, "log: %-*s",
1214 maxlen, event2str (ctx->log[idx].event));
1215 if (ctx->log[idx].have_intvalue)
1216 es_fprintf (out, " i=%d", ctx->log[idx].intvalue);
1217 if (ctx->log[idx].string)
1219 es_fputs (" s='", out);
1220 writeout (ctx, ctx->log[idx].string);
1221 es_fputs ("'", out);
1223 if (ctx->log[idx].cert)
1224 es_fprintf (out, " has_cert");
1225 if (ctx->log[idx].have_err)
1227 es_fputs (" err='", out);
1228 writeout (ctx, gpg_strerror (ctx->log[idx].err));
1229 es_fputs ("'", out);
1231 es_fputs ("\n", out);
1234 es_fputs ("</pre>\n", out);
1236 es_fputs ("\n", out);
1242 case AUDIT_TYPE_NONE:
1243 writeout_li (ctx, NULL, _("Unknown operation"));
1245 case AUDIT_TYPE_ENCRYPT:
1246 proc_type_encrypt (ctx);
1248 case AUDIT_TYPE_SIGN:
1249 proc_type_sign (ctx);
1251 case AUDIT_TYPE_DECRYPT:
1252 proc_type_decrypt (ctx);
1254 case AUDIT_TYPE_VERIFY:
1255 proc_type_verify (ctx);
1258 item = find_log_item (ctx, AUDIT_AGENT_READY, 0);
1259 if (item && item->have_err)
1261 writeout_li (ctx, item->err? "No":"Yes", "%s", _("Gpg-Agent usable"));
1264 writeout_rem (ctx, "%s", gpg_strerror (item->err));
1265 add_helptag (ctx, "gnupg.agent-problem");
1268 item = find_log_item (ctx, AUDIT_DIRMNGR_READY, 0);
1269 if (item && item->have_err)
1271 writeout_li (ctx, item->err? "No":"Yes", "%s", _("Dirmngr usable"));
1274 writeout_rem (ctx, "%s", gpg_strerror (item->err));
1275 add_helptag (ctx, "gnupg.dirmngr-problem");
1281 /* Show the help from the collected help tags. */
1286 es_fputs ("<hr/>\n", ctx->outstream);
1287 if (ctx->helptags->next)
1288 es_fputs ("<ul>\n", ctx->outstream);
1291 es_fputs ("\n\n", ctx->outstream);
1293 for (helptag = ctx->helptags; helptag; helptag = helptag->next)
1297 if (use_html && ctx->helptags->next)
1298 es_fputs ("<li>\n", ctx->outstream);
1300 text = gnupg_get_help_string (helptag->name, 0);
1303 writeout_para (ctx, "%s", text);
1307 writeout_para (ctx, _("No help available for '%s'."), helptag->name);
1308 if (use_html && ctx->helptags->next)
1309 es_fputs ("</li>\n", ctx->outstream);
1311 es_fputs ("\n", ctx->outstream);
1313 if (use_html && ctx->helptags && ctx->helptags->next)
1314 es_fputs ("</ul>\n", ctx->outstream);
1318 es_fputs ("</div>\n", ctx->outstream);
1319 ctx->outstream = NULL;
1321 clear_helptags (ctx);
1322 i18n_switchback (orig_codeset);