1 /* audit.c - GnuPG's audit subsystem
2 * Copyright (C) 2007 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 <http://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 interger 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
, ...) JNLIB_GCC_A_PRINTF(2,3);
76 static void writeout_li (audit_ctx_t ctx
, const char *oktext
,
77 const char *format
, ...) JNLIB_GCC_A_PRINTF(3,4);
78 static void writeout_rem (audit_ctx_t ctx
,
79 const char *format
, ...) JNLIB_GCC_A_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 estream_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");
489 /* If we have set a prefix, skip it. */
490 if (!s
&& *oktext
== '|' && (s
=strchr (oktext
+1,'|')))
498 es_fputs (" <tr><td><table><tr><td>", ctx
->outstream
);
500 es_fprintf (ctx
->outstream
, "<font color=\"%s\">*</font>", color
);
502 es_fputs ("*", ctx
->outstream
);
503 for (i
=1; i
< ctx
->indentlevel
; i
++)
504 es_fputs (" ", ctx
->outstream
);
505 es_fputs ("</td><td>", ctx
->outstream
);
508 es_fprintf (ctx
->outstream
, "* %*s", (ctx
->indentlevel
-1)*2, "");
511 va_start (arg_ptr
, format
) ;
512 writeout_v (ctx
, format
, arg_ptr
);
516 es_fputs ("</td></tr></table>", ctx
->outstream
);
517 if (format
&& oktext
)
521 es_fputs ("</td><td>", ctx
->outstream
);
523 es_fprintf (ctx
->outstream
, "<font color=\"%s\">", color
);
526 writeout (ctx
, ": ");
527 writeout (ctx
, oktext
);
529 es_fputs ("</font>", ctx
->outstream
);
533 es_fputs ("</td></tr>\n", ctx
->outstream
);
535 es_fputc ('\n', ctx
->outstream
);
539 /* Write a remark line. */
541 writeout_rem (audit_ctx_t ctx
, const char *format
, ...)
549 es_fputs (" <tr><td><table><tr><td>*", ctx
->outstream
);
550 for (i
=1; i
< ctx
->indentlevel
; i
++)
551 es_fputs (" ", ctx
->outstream
);
552 es_fputs (" </td><td> (", ctx
->outstream
);
556 es_fprintf (ctx
->outstream
, "* %*s (", (ctx
->indentlevel
-1)*2, "");
559 va_start (arg_ptr
, format
) ;
560 writeout_v (ctx
, format
, arg_ptr
);
564 es_fputs (")</td></tr></table></td></tr>\n", ctx
->outstream
);
566 es_fputs (")\n", ctx
->outstream
);
570 /* Return the first log item for EVENT. If STOPEVENT is not 0 never
571 look behind that event in the log. If STARTITEM is not NULL start
572 search _after_that item. */
574 find_next_log_item (audit_ctx_t ctx
, log_item_t startitem
,
575 audit_event_t event
, audit_event_t stopevent
)
579 for (idx
=0; idx
< ctx
->logused
; idx
++)
583 if (ctx
->log
+ idx
== startitem
)
586 else if (stopevent
&& ctx
->log
[idx
].event
== stopevent
)
588 else if (ctx
->log
[idx
].event
== event
)
589 return ctx
->log
+ idx
;
596 find_log_item (audit_ctx_t ctx
, audit_event_t event
, audit_event_t stopevent
)
598 return find_next_log_item (ctx
, NULL
, event
, stopevent
);
602 /* Helper to a format a serial number. */
604 format_serial (ksba_const_sexp_t sn
)
606 const char *p
= (const char *)sn
;
613 BUG (); /* Not a valid S-expression. */
614 n
= strtoul (p
+1, &endp
, 10);
617 BUG (); /* Not a valid S-expression. */
618 return bin2hex (p
+1, n
, NULL
);
622 /* Return a malloced string with the serial number and the issuer DN
623 of the certificate. */
625 get_cert_name (ksba_cert_t cert
)
632 return xtrystrdup ("[no certificate]");
634 issuer
= ksba_cert_get_issuer (cert
, 0);
635 sn
= ksba_cert_get_serial (cert
);
638 p
= format_serial (sn
);
640 result
= xtrystrdup ("[invalid S/N]");
643 result
= xtrymalloc (strlen (p
) + strlen (issuer
) + 2 + 1);
647 strcpy (stpcpy (stpcpy (result
+1, p
),"/"), issuer
);
653 result
= xtrystrdup ("[missing S/N or issuer]");
659 /* Return a malloced string with the serial number and the issuer DN
660 of the certificate. */
662 get_cert_subject (ksba_cert_t cert
, int idx
)
668 return xtrystrdup ("[no certificate]");
670 subject
= ksba_cert_get_subject (cert
, idx
);
673 result
= xtrymalloc (strlen (subject
) + 1 + 1);
677 strcpy (result
+1, subject
);
687 /* List the given certificiate. If CERT is NULL, this is a NOP. */
689 list_cert (audit_ctx_t ctx
, ksba_cert_t cert
, int with_subj
)
694 name
= get_cert_name (cert
);
695 writeout_rem (ctx
, "%s", name
);
700 for (idx
=0; (name
= get_cert_subject (cert
, idx
)); idx
++)
702 writeout_rem (ctx
, "%s", name
);
710 /* List the chain of certificates from STARTITEM up to STOPEVENT. The
711 certifcates are written out as comments. */
713 list_certchain (audit_ctx_t ctx
, log_item_t startitem
, audit_event_t stopevent
)
717 startitem
= find_next_log_item (ctx
, startitem
, AUDIT_CHAIN_BEGIN
,stopevent
);
718 writeout_li (ctx
, startitem
? "Yes":"No", _("Certificate chain available"));
722 item
= find_next_log_item (ctx
, startitem
,
723 AUDIT_CHAIN_ROOTCERT
, AUDIT_CHAIN_END
);
725 writeout_rem (ctx
, "%s", _("root certificate missing"));
728 list_cert (ctx
, item
->cert
, 0);
731 while ( ((item
= find_next_log_item (ctx
, item
,
732 AUDIT_CHAIN_CERT
, AUDIT_CHAIN_END
))))
734 list_cert (ctx
, item
->cert
, 1);
740 /* Process an encrypt operation's log. */
742 proc_type_encrypt (audit_ctx_t ctx
)
744 log_item_t loopitem
, item
;
750 item
= find_log_item (ctx
, AUDIT_ENCRYPTION_DONE
, 0);
751 writeout_li (ctx
, item
?"Yes":"No", "%s", _("Data encryption succeeded"));
755 item
= find_log_item (ctx
, AUDIT_GOT_DATA
, 0);
756 writeout_li (ctx
, item
? "Yes":"No", "%s", _("Data available"));
758 item
= find_log_item (ctx
, AUDIT_SESSION_KEY
, 0);
759 writeout_li (ctx
, item
? "Yes":"No", "%s", _("Session key created"));
762 algo
= gcry_cipher_map_name (item
->string
);
764 writeout_rem (ctx
, _("algorithm: %s"), gcry_cipher_algo_name (algo
));
765 else if (item
->string
&& !strcmp (item
->string
, "1.2.840.113549.3.2"))
766 writeout_rem (ctx
, _("unsupported algorithm: %s"), "RC2");
767 else if (item
->string
)
768 writeout_rem (ctx
, _("unsupported algorithm: %s"), item
->string
);
770 writeout_rem (ctx
, _("seems to be not encrypted"));
773 item
= find_log_item (ctx
, AUDIT_GOT_RECIPIENTS
, 0);
774 snprintf (numbuf
, sizeof numbuf
, "%d",
775 item
&& item
->have_intvalue
? item
->intvalue
: 0);
776 writeout_li (ctx
, numbuf
, "%s", _("Number of recipients"));
778 /* Loop over all recipients. */
781 while ((loopitem
=find_next_log_item (ctx
, loopitem
, AUDIT_ENCRYPTED_TO
, 0)))
784 writeout_li (ctx
, NULL
, _("Recipient %d"), recp_no
);
787 name
= get_cert_name (loopitem
->cert
);
788 writeout_rem (ctx
, "%s", name
);
791 for (idx
=0; (name
= get_cert_subject (loopitem
->cert
, idx
)); idx
++)
793 writeout_rem (ctx
, "%s", name
);
805 /* Process a sign operation's log. */
807 proc_type_sign (audit_ctx_t ctx
)
812 writeout_li (ctx
, item
?"Yes":"No", "%s", _("Data signing succeeded"));
816 item
= find_log_item (ctx
, AUDIT_GOT_DATA
, 0);
817 writeout_li (ctx
, item
? "Yes":"No", "%s", _("Data available"));
825 /* Process a decrypt operation's log. */
827 proc_type_decrypt (audit_ctx_t ctx
)
832 writeout_li (ctx
, item
?"Yes":"No", "%s", _("Data decryption succeeded"));
836 item
= find_log_item (ctx
, AUDIT_GOT_DATA
, 0);
837 writeout_li (ctx
, item
? "Yes":"No", "%s", _("Data available"));
845 /* Process a verification operation's log. */
847 proc_type_verify (audit_ctx_t ctx
)
849 log_item_t loopitem
, item
;
850 int signo
, count
, idx
;
853 /* If there is at least one signature status we claim that the
854 verifciation succeeded. This does not mean that the data has
856 item
= find_log_item (ctx
, AUDIT_SIG_STATUS
, 0);
857 writeout_li (ctx
, item
?"Yes":"No", "%s", _("Data verification succeeded"));
860 item
= find_log_item (ctx
, AUDIT_GOT_DATA
, AUDIT_NEW_SIG
);
861 writeout_li (ctx
, item
? "Yes":"No", "%s", _("Data available"));
865 item
= find_log_item (ctx
, AUDIT_NEW_SIG
, 0);
866 writeout_li (ctx
, item
? "Yes":"No", "%s", _("Signature available"));
870 item
= find_log_item (ctx
, AUDIT_DATA_HASH_ALGO
, AUDIT_NEW_SIG
);
871 writeout_li (ctx
, item
?"Yes":"No", "%s", _("Parsing signature succeeded"));
874 item
= find_log_item (ctx
, AUDIT_BAD_DATA_HASH_ALGO
, AUDIT_NEW_SIG
);
876 writeout_rem (ctx
, _("Bad hash algorithm: %s"),
877 item
->string
? item
->string
:"?");
882 /* Loop over all signatures. */
883 loopitem
= find_log_item (ctx
, AUDIT_NEW_SIG
, 0);
887 signo
= loopitem
->have_intvalue
? loopitem
->intvalue
: -1;
889 item
= find_next_log_item (ctx
, loopitem
,
890 AUDIT_SIG_STATUS
, AUDIT_NEW_SIG
);
891 writeout_li (ctx
, item
? item
->string
:"?", _("Signature %d"), signo
);
892 item
= find_next_log_item (ctx
, loopitem
,
893 AUDIT_SIG_NAME
, AUDIT_NEW_SIG
);
895 writeout_rem (ctx
, "%s", item
->string
);
898 /* List the certificate chain. */
899 list_certchain (ctx
, loopitem
, AUDIT_NEW_SIG
);
901 /* Show the result of the chain validation. */
902 item
= find_next_log_item (ctx
, loopitem
,
903 AUDIT_CHAIN_STATUS
, AUDIT_NEW_SIG
);
904 if (item
&& item
->have_err
)
906 writeout_li (ctx
, item
->err
? "No":"Yes",
907 _("Certificate chain valid"));
909 writeout_rem (ctx
, "%s", gpg_strerror (item
->err
));
912 /* Show whether the root certificate is fine. */
913 item
= find_next_log_item (ctx
, loopitem
,
914 AUDIT_ROOT_TRUSTED
, AUDIT_CHAIN_STATUS
);
917 writeout_li (ctx
, item
->err
?"No":"Yes", "%s",
918 _("Root certificate trustworthy"));
921 add_helptag (ctx
, "gpgsm.root-cert-not-trusted");
922 writeout_rem (ctx
, "%s", gpg_strerror (item
->err
));
923 list_cert (ctx
, item
->cert
, 0);
927 /* Show result of the CRL/OCSP check. */
928 item
= find_next_log_item (ctx
, loopitem
,
929 AUDIT_CRL_CHECK
, AUDIT_NEW_SIG
);
933 switch (gpg_err_code (item
->err
))
935 case 0: ok
= "good"; break;
936 case GPG_ERR_CERT_REVOKED
: ok
= "bad"; break;
937 case GPG_ERR_NOT_ENABLED
: ok
= "disabled"; break;
938 case GPG_ERR_NO_CRL_KNOWN
:
939 ok
= _("no CRL found for certificate");
941 case GPG_ERR_CRL_TOO_OLD
:
942 ok
= _("the available CRL is too old");
944 default: ok
= gpg_strerror (item
->err
); break;
947 writeout_li (ctx
, ok
, "%s", _("CRL/OCSP check of certificates"));
949 && gpg_err_code (item
->err
) != GPG_ERR_CERT_REVOKED
950 && gpg_err_code (item
->err
) != GPG_ERR_NOT_ENABLED
)
951 add_helptag (ctx
, "gpgsm.crl-problem");
956 while ((loopitem
= find_next_log_item (ctx
, loopitem
, AUDIT_NEW_SIG
, 0)));
960 /* Always list the certificates stored in the signature. */
963 while ( ((item
= find_next_log_item (ctx
, item
,
964 AUDIT_SAVE_CERT
, AUDIT_NEW_SIG
))))
966 snprintf (numbuf
, sizeof numbuf
, "%d", count
);
967 writeout_li (ctx
, numbuf
, _("Included certificates"));
969 while ( ((item
= find_next_log_item (ctx
, item
,
970 AUDIT_SAVE_CERT
, AUDIT_NEW_SIG
))))
972 char *name
= get_cert_name (item
->cert
);
973 writeout_rem (ctx
, "%s", name
);
976 for (idx
=0; (name
= get_cert_subject (item
->cert
, idx
)); idx
++)
978 writeout_rem (ctx
, "%s", name
);
989 /* Print the formatted audit result. THIS IS WORK IN PROGRESS. */
991 audit_print_result (audit_ctx_t ctx
, estream_t out
, int use_html
)
1004 orig_codeset
= i18n_switchto_utf8 ();
1006 /* We use an environment variable to include some debug info in the
1008 if ((s
= getenv ("gnupg_debug_audit")))
1011 if (!strcmp (s
, "html"))
1015 assert (!ctx
->outstream
);
1016 ctx
->outstream
= out
;
1017 ctx
->use_html
= use_html
;
1018 ctx
->indentlevel
= 0;
1019 clear_helptags (ctx
);
1022 es_fputs ("<div class=\"GnuPGAuditLog\">\n", ctx
->outstream
);
1024 if (!ctx
->log
|| !ctx
->logused
)
1026 writeout_para (ctx
, _("No audit log entries."));
1034 for (idx
=0,maxlen
=0; idx
< DIM (eventstr_msgidx
); idx
++)
1036 n
= strlen (eventstr_msgstr
+ eventstr_msgidx
[idx
]);
1042 es_fputs ("<pre>\n", out
);
1043 for (idx
=0; idx
< ctx
->logused
; idx
++)
1045 es_fprintf (out
, "log: %-*s",
1046 maxlen
, event2str (ctx
->log
[idx
].event
));
1047 if (ctx
->log
[idx
].have_intvalue
)
1048 es_fprintf (out
, " i=%d", ctx
->log
[idx
].intvalue
);
1049 if (ctx
->log
[idx
].string
)
1051 es_fputs (" s=`", out
);
1052 writeout (ctx
, ctx
->log
[idx
].string
);
1053 es_fputs ("'", out
);
1055 if (ctx
->log
[idx
].cert
)
1056 es_fprintf (out
, " has_cert");
1057 if (ctx
->log
[idx
].have_err
)
1059 es_fputs (" err=`", out
);
1060 writeout (ctx
, gpg_strerror (ctx
->log
[idx
].err
));
1061 es_fputs ("'", out
);
1063 es_fputs ("\n", out
);
1066 es_fputs ("</pre>\n", out
);
1068 es_fputs ("\n", out
);
1074 case AUDIT_TYPE_NONE
:
1075 writeout_li (ctx
, NULL
, _("Unknown operation"));
1077 case AUDIT_TYPE_ENCRYPT
:
1078 proc_type_encrypt (ctx
);
1080 case AUDIT_TYPE_SIGN
:
1081 proc_type_sign (ctx
);
1083 case AUDIT_TYPE_DECRYPT
:
1084 proc_type_decrypt (ctx
);
1086 case AUDIT_TYPE_VERIFY
:
1087 proc_type_verify (ctx
);
1090 item
= find_log_item (ctx
, AUDIT_AGENT_READY
, 0);
1091 if (item
&& item
->have_err
)
1093 writeout_li (ctx
, item
->err
? "No":"Yes", "%s", _("Gpg-Agent usable"));
1096 writeout_rem (ctx
, "%s", gpg_strerror (item
->err
));
1097 add_helptag (ctx
, "gnupg.agent-problem");
1100 item
= find_log_item (ctx
, AUDIT_DIRMNGR_READY
, 0);
1101 if (item
&& item
->have_err
)
1103 writeout_li (ctx
, item
->err
? "No":"Yes", "%s", _("Dirmngr usable"));
1106 writeout_rem (ctx
, "%s", gpg_strerror (item
->err
));
1107 add_helptag (ctx
, "gnupg.dirmngr-problem");
1113 /* Show the help from the collected help tags. */
1118 es_fputs ("<hr/>\n", ctx
->outstream
);
1119 if (ctx
->helptags
->next
)
1120 es_fputs ("<ul>\n", ctx
->outstream
);
1123 es_fputs ("\n\n", ctx
->outstream
);
1125 for (helptag
= ctx
->helptags
; helptag
; helptag
= helptag
->next
)
1129 if (use_html
&& ctx
->helptags
->next
)
1130 es_fputs ("<li>\n", ctx
->outstream
);
1132 text
= gnupg_get_help_string (helptag
->name
, 0);
1135 writeout_para (ctx
, "%s", text
);
1139 writeout_para (ctx
, _("No help available for `%s'."), helptag
->name
);
1140 if (use_html
&& ctx
->helptags
->next
)
1141 es_fputs ("</li>\n", ctx
->outstream
);
1143 es_fputs ("\n", ctx
->outstream
);
1145 if (use_html
&& ctx
->helptags
&& ctx
->helptags
->next
)
1146 es_fputs ("</ul>\n", ctx
->outstream
);
1150 es_fputs ("</div>\n", ctx
->outstream
);
1151 ctx
->outstream
= NULL
;
1153 clear_helptags (ctx
);
1154 i18n_switchback (orig_codeset
);