LCOV - code coverage report
Current view: top level - common - audit.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 649 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 31 0.0 %

          Line data    Source code
       1             : /* audit.c - GnuPG's audit subsystem
       2             :  *      Copyright (C) 2007, 2009 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       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.
      10             :  *
      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.
      15             :  *
      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/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : #include <stdlib.h>
      22             : #include <string.h>
      23             : #include <stdarg.h>
      24             : #include <assert.h>
      25             : 
      26             : #include "util.h"
      27             : #include "i18n.h"
      28             : #include "audit.h"
      29             : #include "audit-events.h"
      30             : 
      31             : /* A list to maintain a list of helptags.  */
      32             : struct helptag_s
      33             : {
      34             :   struct helptag_s *next;
      35             :   const char *name;
      36             : };
      37             : typedef struct helptag_s *helptag_t;
      38             : 
      39             : 
      40             : /* One log entry.  */
      41             : struct log_item_s
      42             : {
      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. */
      48             :   int have_err:1;
      49             :   int have_intvalue:1;
      50             : };
      51             : typedef struct log_item_s *log_item_t;
      52             : 
      53             : 
      54             : 
      55             : /* The main audit object.  */
      56             : struct audit_ctx_s
      57             : {
      58             :   const char *failure;  /* If set a description of the internal failure.  */
      59             :   audit_type_t type;
      60             : 
      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.  */
      64             : 
      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.  */
      69             : };
      70             : 
      71             : 
      72             : 
      73             : 
      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);
      80             : 
      81             : 
      82             : /* Add NAME to the list of help tags.  NAME needs to be a const string
      83             :    an this function merly stores this pointer.  */
      84             : static void
      85           0 : add_helptag (audit_ctx_t ctx, const char *name)
      86             : {
      87             :   helptag_t item;
      88             : 
      89           0 :   for (item=ctx->helptags; item; item = item->next)
      90           0 :     if (!strcmp (item->name, name))
      91           0 :       return;  /* Already in the list.  */
      92           0 :   item = xtrycalloc (1, sizeof *item);
      93           0 :   if (!item)
      94           0 :     return;  /* Don't care about memory problems.  */
      95           0 :   item->name = name;
      96           0 :   item->next = ctx->helptags;
      97           0 :   ctx->helptags = item;
      98             : }
      99             : 
     100             : 
     101             : /* Remove all help tags from the context.  */
     102             : static void
     103           0 : clear_helptags (audit_ctx_t ctx)
     104             : {
     105           0 :   while (ctx->helptags)
     106             :     {
     107           0 :       helptag_t tmp = ctx->helptags->next;
     108           0 :       xfree (ctx->helptags);
     109           0 :       ctx->helptags = tmp;
     110             :     }
     111           0 : }
     112             : 
     113             : 
     114             : 
     115             : static const char *
     116           0 : event2str (audit_event_t event)
     117             : {
     118             :   /* We need the cast so that compiler does not complain about an
     119             :      always true comparison (>= 0) for an unsigned value.  */
     120           0 :   int idx = eventstr_msgidxof ((int)event);
     121           0 :   if (idx == -1)
     122           0 :     return "Unknown event";
     123             :   else
     124           0 :     return eventstr_msgstr + eventstr_msgidx[idx];
     125             : }
     126             : 
     127             : 
     128             : 
     129             : /* Create a new audit context.  In case of an error NULL is returned
     130             :    and errno set appropriately. */
     131             : audit_ctx_t
     132           0 : audit_new (void)
     133             : {
     134             :   audit_ctx_t ctx;
     135             : 
     136           0 :   ctx = xtrycalloc (1, sizeof *ctx);
     137             : 
     138           0 :   return ctx;
     139             : }
     140             : 
     141             : 
     142             : /* Release an audit context.  Passing NULL for CTX is allowed and does
     143             :    nothing.  */
     144             : void
     145           0 : audit_release (audit_ctx_t ctx)
     146             : {
     147             :   int idx;
     148           0 :   if (!ctx)
     149           0 :     return;
     150           0 :   if (ctx->log)
     151             :     {
     152           0 :       for (idx=0; idx < ctx->logused; idx++)
     153             :         {
     154           0 :           if (ctx->log[idx].string)
     155           0 :             xfree (ctx->log[idx].string);
     156           0 :           if (ctx->log[idx].cert)
     157           0 :             ksba_cert_release (ctx->log[idx].cert);
     158             :         }
     159           0 :       xfree (ctx->log);
     160             :     }
     161           0 :   clear_helptags (ctx);
     162           0 :   xfree (ctx);
     163             : }
     164             : 
     165             : 
     166             : /* Set the type for the audit operation.  If CTX is NULL, this is a
     167             :    dummy fucntion.  */
     168             : void
     169           0 : audit_set_type (audit_ctx_t ctx, audit_type_t type)
     170             : {
     171           0 :   if (!ctx || ctx->failure)
     172           0 :     return;  /* Audit not enabled or an internal error has occurred. */
     173             : 
     174           0 :   if (ctx->type && ctx->type != type)
     175             :     {
     176           0 :       ctx->failure = "conflict in type initialization";
     177           0 :       return;
     178             :     }
     179           0 :   ctx->type = type;
     180             : }
     181             : 
     182             : 
     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
     185             :    CTX. */
     186             : static log_item_t
     187           0 : create_log_item (audit_ctx_t ctx)
     188             : {
     189             :   log_item_t item, table;
     190             :   size_t size;
     191             : 
     192           0 :   if (!ctx->log)
     193             :     {
     194           0 :       size = 10;
     195           0 :       table = xtrymalloc (size * sizeof *table);
     196           0 :       if (!table)
     197             :         {
     198           0 :           ctx->failure = "Out of memory in create_log_item";
     199           0 :           return NULL;
     200             :         }
     201           0 :       ctx->log = table;
     202           0 :       ctx->logsize = size;
     203           0 :       item = ctx->log + 0;
     204           0 :       ctx->logused = 1;
     205             :     }
     206           0 :   else if (ctx->logused >= ctx->logsize)
     207             :     {
     208           0 :       size = ctx->logsize + 10;
     209           0 :       table = xtryrealloc (ctx->log, size * sizeof *table);
     210           0 :       if (!table)
     211             :         {
     212           0 :           ctx->failure = "Out of memory while reallocating in create_log_item";
     213           0 :           return NULL;
     214             :         }
     215           0 :       ctx->log = table;
     216           0 :       ctx->logsize = size;
     217           0 :       item = ctx->log + ctx->logused++;
     218             :     }
     219             :   else
     220           0 :     item = ctx->log + ctx->logused++;
     221             : 
     222           0 :   item->event = AUDIT_NULL_EVENT;
     223           0 :   item->err = 0;
     224           0 :   item->have_err = 0;
     225           0 :   item->intvalue = 0;
     226           0 :   item->have_intvalue = 0;
     227           0 :   item->string = NULL;
     228           0 :   item->cert = NULL;
     229             : 
     230           0 :   return item;
     231             : 
     232             : }
     233             : 
     234             : /* Add a new event to the audit log.  If CTX is NULL, this function
     235             :    does nothing.  */
     236             : void
     237           0 : audit_log (audit_ctx_t ctx, audit_event_t event)
     238             : {
     239             :   log_item_t item;
     240             : 
     241           0 :   if (!ctx || ctx->failure)
     242           0 :     return;  /* Audit not enabled or an internal error has occurred. */
     243           0 :   if (!event)
     244             :     {
     245           0 :       ctx->failure = "Invalid event passed to audit_log";
     246           0 :       return;
     247             :     }
     248           0 :   if (!(item = create_log_item (ctx)))
     249           0 :     return;
     250           0 :   item->event = event;
     251             : }
     252             : 
     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
     255             :    to the log.  */
     256             : void
     257           0 : audit_log_ok (audit_ctx_t ctx, audit_event_t event, gpg_error_t err)
     258             : {
     259             :   log_item_t item;
     260             : 
     261           0 :   if (!ctx || ctx->failure)
     262           0 :     return;  /* Audit not enabled or an internal error has occurred. */
     263           0 :   if (!event)
     264             :     {
     265           0 :       ctx->failure = "Invalid event passed to audit_log_ok";
     266           0 :       return;
     267             :     }
     268           0 :   if (!(item = create_log_item (ctx)))
     269           0 :     return;
     270           0 :   item->event = event;
     271           0 :   item->err = err;
     272           0 :   item->have_err = 1;
     273             : }
     274             : 
     275             : 
     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.  */
     278             : void
     279           0 : audit_log_i (audit_ctx_t ctx, audit_event_t event, int value)
     280             : {
     281             :   log_item_t item;
     282             : 
     283           0 :   if (!ctx || ctx->failure)
     284           0 :     return;  /* Audit not enabled or an internal error has occurred. */
     285           0 :   if (!event)
     286             :     {
     287           0 :       ctx->failure = "Invalid event passed to audit_log_i";
     288           0 :       return;
     289             :     }
     290           0 :   if (!(item = create_log_item (ctx)))
     291           0 :     return;
     292           0 :   item->event = event;
     293           0 :   item->intvalue = value;
     294           0 :   item->have_intvalue = 1;
     295             : }
     296             : 
     297             : 
     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.  */
     300             : void
     301           0 : audit_log_s (audit_ctx_t ctx, audit_event_t event, const char *value)
     302             : {
     303             :   log_item_t item;
     304             :   char *tmp;
     305             : 
     306           0 :   if (!ctx || ctx->failure)
     307           0 :     return;  /* Audit not enabled or an internal error has occurred. */
     308           0 :   if (!event)
     309             :     {
     310           0 :       ctx->failure = "Invalid event passed to audit_log_s";
     311           0 :       return;
     312             :     }
     313           0 :   tmp = xtrystrdup (value? value : "");
     314           0 :   if (!tmp)
     315             :     {
     316           0 :       ctx->failure = "Out of memory in audit_event";
     317           0 :       return;
     318             :     }
     319           0 :   if (!(item = create_log_item (ctx)))
     320             :     {
     321           0 :       xfree (tmp);
     322           0 :       return;
     323             :     }
     324           0 :   item->event = event;
     325           0 :   item->string = tmp;
     326             : }
     327             : 
     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.  */
     331             : void
     332           0 : audit_log_cert (audit_ctx_t ctx, audit_event_t event,
     333             :                 ksba_cert_t cert, gpg_error_t err)
     334             : {
     335             :   log_item_t item;
     336             : 
     337           0 :   if (!ctx || ctx->failure)
     338           0 :     return;  /* Audit not enabled or an internal error has occurred. */
     339           0 :   if (!event)
     340             :     {
     341           0 :       ctx->failure = "Invalid event passed to audit_log_cert";
     342           0 :       return;
     343             :     }
     344           0 :   if (!(item = create_log_item (ctx)))
     345           0 :     return;
     346           0 :   item->event = event;
     347           0 :   item->err = err;
     348           0 :   item->have_err = 1;
     349           0 :   if (cert)
     350             :     {
     351           0 :       ksba_cert_ref (cert);
     352           0 :       item->cert = cert;
     353             :     }
     354             : }
     355             : 
     356             : 
     357             : /* Write TEXT to the outstream.  */
     358             : static void
     359           0 : writeout (audit_ctx_t ctx, const char *text)
     360             : {
     361           0 :   if (ctx->use_html)
     362             :     {
     363           0 :       for (; *text; text++)
     364             :         {
     365           0 :           if (*text == '<')
     366           0 :             es_fputs ("&lt;", ctx->outstream);
     367           0 :           else if (*text == '&')
     368           0 :             es_fputs ("&amp;", ctx->outstream);
     369             :           else
     370           0 :             es_putc (*text, ctx->outstream);
     371             :         }
     372             :     }
     373             :   else
     374           0 :     es_fputs (text, ctx->outstream);
     375           0 : }
     376             : 
     377             : 
     378             : /* Write TEXT to the outstream using a variable argument list.  */
     379             : static void
     380           0 : writeout_v (audit_ctx_t ctx, const char *format, va_list arg_ptr)
     381             : {
     382             :   char *buf;
     383             : 
     384           0 :   gpgrt_vasprintf (&buf, format, arg_ptr);
     385           0 :   if (buf)
     386             :     {
     387           0 :       writeout (ctx, buf);
     388           0 :       xfree (buf);
     389             :     }
     390             :   else
     391           0 :     writeout (ctx, "[!!Out of core!!]");
     392           0 : }
     393             : 
     394             : 
     395             : /* Write TEXT as a paragraph.  */
     396             : static void
     397           0 : writeout_para (audit_ctx_t ctx, const char *format, ...)
     398             : {
     399             :   va_list arg_ptr;
     400             : 
     401           0 :   if (ctx->use_html)
     402           0 :     es_fputs ("<p>", ctx->outstream);
     403           0 :   va_start (arg_ptr, format) ;
     404           0 :   writeout_v (ctx, format, arg_ptr);
     405           0 :   va_end (arg_ptr);
     406           0 :   if (ctx->use_html)
     407           0 :     es_fputs ("</p>\n", ctx->outstream);
     408             :   else
     409           0 :     es_fputc ('\n', ctx->outstream);
     410           0 : }
     411             : 
     412             : 
     413             : static void
     414           0 : enter_li (audit_ctx_t ctx)
     415             : {
     416           0 :   if (ctx->use_html)
     417             :     {
     418           0 :       if (!ctx->indentlevel)
     419             :         {
     420           0 :           es_fputs ("<table border=\"0\">\n"
     421             :                     "  <colgroup>\n"
     422             :                     "    <col width=\"80%\" />\n"
     423             :                     "    <col width=\"20%\" />\n"
     424             :                     "   </colgroup>\n",
     425             :                     ctx->outstream);
     426             :         }
     427             :     }
     428           0 :   ctx->indentlevel++;
     429           0 : }
     430             : 
     431             : 
     432             : static void
     433           0 : leave_li (audit_ctx_t ctx)
     434             : {
     435           0 :   ctx->indentlevel--;
     436           0 :   if (ctx->use_html)
     437             :     {
     438           0 :       if (!ctx->indentlevel)
     439           0 :         es_fputs ("</table>\n", ctx->outstream);
     440             :     }
     441           0 : }
     442             : 
     443             : 
     444             : /* Write TEXT as a list element.  If OKTEXT is not NULL, append it to
     445             :    the last line. */
     446             : static void
     447           0 : writeout_li (audit_ctx_t ctx, const char *oktext, const char *format, ...)
     448             : {
     449             :   va_list arg_ptr;
     450           0 :   const char *color = NULL;
     451             : 
     452           0 :   if (ctx->use_html && format && oktext)
     453             :     {
     454           0 :       if (!strcmp (oktext, "Yes")
     455           0 :           || !strcmp (oktext, "good") )
     456           0 :         color = "green";
     457           0 :       else if (!strcmp (oktext, "No")
     458           0 :                || !strcmp (oktext, "bad") )
     459           0 :         color = "red";
     460             :     }
     461             : 
     462           0 :   if (format && oktext)
     463             :     {
     464           0 :       const char *s = NULL;
     465             : 
     466           0 :       if (!strcmp (oktext, "Yes"))
     467           0 :         oktext = _("Yes");
     468           0 :       else if (!strcmp (oktext, "No"))
     469           0 :         oktext = _("No");
     470           0 :       else if (!strcmp (oktext, "good"))
     471             :         {
     472             :           /* TRANSLATORS: Copy the prefix between the vertical bars
     473             :              verbatim.  It will not be printed.  */
     474           0 :           oktext = _("|audit-log-result|Good");
     475             :         }
     476           0 :       else if (!strcmp (oktext, "bad"))
     477           0 :         oktext = _("|audit-log-result|Bad");
     478           0 :       else if (!strcmp (oktext, "unsupported"))
     479           0 :         oktext = _("|audit-log-result|Not supported");
     480           0 :       else if (!strcmp (oktext, "no-cert"))
     481           0 :         oktext = _("|audit-log-result|No certificate");
     482           0 :       else if (!strcmp (oktext, "disabled"))
     483           0 :         oktext = _("|audit-log-result|Not enabled");
     484           0 :       else if (!strcmp (oktext, "error"))
     485           0 :         oktext = _("|audit-log-result|Error");
     486           0 :       else if (!strcmp (oktext, "not-used"))
     487           0 :         oktext = _("|audit-log-result|Not used");
     488           0 :       else if (!strcmp (oktext, "okay"))
     489           0 :         oktext = _("|audit-log-result|Okay");
     490           0 :       else if (!strcmp (oktext, "skipped"))
     491           0 :         oktext = _("|audit-log-result|Skipped");
     492           0 :       else if (!strcmp (oktext, "some"))
     493           0 :         oktext = _("|audit-log-result|Some");
     494             :       else
     495           0 :         s = "";
     496             : 
     497             :       /* If we have set a prefix, skip it.  */
     498           0 :       if (!s && *oktext == '|' && (s=strchr (oktext+1,'|')))
     499           0 :         oktext = s+1;
     500             :     }
     501             : 
     502           0 :   if (ctx->use_html)
     503             :     {
     504             :       int i;
     505             : 
     506           0 :       es_fputs ("  <tr><td><table><tr><td>", ctx->outstream);
     507           0 :       if (color)
     508           0 :         es_fprintf (ctx->outstream, "<font color=\"%s\">*</font>", color);
     509             :       else
     510           0 :         es_fputs ("*", ctx->outstream);
     511           0 :       for (i=1; i < ctx->indentlevel; i++)
     512           0 :         es_fputs ("&nbsp;&nbsp;", ctx->outstream);
     513           0 :       es_fputs ("</td><td>", ctx->outstream);
     514             :     }
     515             :   else
     516           0 :     es_fprintf (ctx->outstream, "* %*s", (ctx->indentlevel-1)*2, "");
     517           0 :   if (format)
     518             :     {
     519           0 :       va_start (arg_ptr, format) ;
     520           0 :       writeout_v (ctx, format, arg_ptr);
     521           0 :       va_end (arg_ptr);
     522             :     }
     523           0 :   if (ctx->use_html)
     524           0 :     es_fputs ("</td></tr></table>", ctx->outstream);
     525           0 :   if (format && oktext)
     526             :     {
     527           0 :       if (ctx->use_html)
     528             :         {
     529           0 :           es_fputs ("</td><td>", ctx->outstream);
     530           0 :           if (color)
     531           0 :             es_fprintf (ctx->outstream, "<font color=\"%s\">", color);
     532             :         }
     533             :       else
     534           0 :         writeout (ctx, ":         ");
     535           0 :       writeout (ctx, oktext);
     536           0 :       if (color)
     537           0 :         es_fputs ("</font>", ctx->outstream);
     538             :     }
     539             : 
     540           0 :   if (ctx->use_html)
     541           0 :     es_fputs ("</td></tr>\n", ctx->outstream);
     542             :   else
     543           0 :     es_fputc ('\n', ctx->outstream);
     544           0 : }
     545             : 
     546             : 
     547             : /* Write a remark line.  */
     548             : static void
     549           0 : writeout_rem (audit_ctx_t ctx, const char *format, ...)
     550             : {
     551             :   va_list arg_ptr;
     552             : 
     553           0 :   if (ctx->use_html)
     554             :     {
     555             :       int i;
     556             : 
     557           0 :       es_fputs ("  <tr><td><table><tr><td>*", ctx->outstream);
     558           0 :       for (i=1; i < ctx->indentlevel; i++)
     559           0 :         es_fputs ("&nbsp;&nbsp;", ctx->outstream);
     560           0 :       es_fputs ("&nbsp;&nbsp;&nbsp;</td><td> (", ctx->outstream);
     561             : 
     562             :     }
     563             :   else
     564           0 :     es_fprintf (ctx->outstream, "* %*s  (", (ctx->indentlevel-1)*2, "");
     565           0 :   if (format)
     566             :     {
     567           0 :       va_start (arg_ptr, format) ;
     568           0 :       writeout_v (ctx, format, arg_ptr);
     569           0 :       va_end (arg_ptr);
     570             :     }
     571           0 :   if (ctx->use_html)
     572           0 :     es_fputs (")</td></tr></table></td></tr>\n", ctx->outstream);
     573             :   else
     574           0 :     es_fputs (")\n", ctx->outstream);
     575           0 : }
     576             : 
     577             : 
     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.  */
     581             : static log_item_t
     582           0 : find_next_log_item (audit_ctx_t ctx, log_item_t startitem,
     583             :                     audit_event_t event, audit_event_t stopevent)
     584             : {
     585             :   int idx;
     586             : 
     587           0 :   for (idx=0; idx < ctx->logused; idx++)
     588             :     {
     589           0 :       if (startitem)
     590             :         {
     591           0 :           if (ctx->log + idx == startitem)
     592           0 :             startitem = NULL;
     593             :         }
     594           0 :       else if (stopevent && ctx->log[idx].event == stopevent)
     595             :         break;
     596           0 :       else if (ctx->log[idx].event == event)
     597           0 :         return ctx->log + idx;
     598             :     }
     599           0 :   return NULL;
     600             : }
     601             : 
     602             : 
     603             : static log_item_t
     604           0 : find_log_item (audit_ctx_t ctx, audit_event_t event, audit_event_t stopevent)
     605             : {
     606           0 :   return find_next_log_item (ctx, NULL, event, stopevent);
     607             : }
     608             : 
     609             : 
     610             : /* Helper to a format a serial number.  */
     611             : static char *
     612           0 : format_serial (ksba_const_sexp_t sn)
     613             : {
     614           0 :   const char *p = (const char *)sn;
     615             :   unsigned long n;
     616             :   char *endp;
     617             : 
     618           0 :   if (!p)
     619           0 :     return NULL;
     620           0 :   if (*p != '(')
     621           0 :     BUG (); /* Not a valid S-expression. */
     622           0 :   n = strtoul (p+1, &endp, 10);
     623           0 :   p = endp;
     624           0 :   if (*p != ':')
     625           0 :     BUG (); /* Not a valid S-expression. */
     626           0 :   return bin2hex (p+1, n, NULL);
     627             : }
     628             : 
     629             : 
     630             : /* Return a malloced string with the serial number and the issuer DN
     631             :    of the certificate.  */
     632             : static char *
     633           0 : get_cert_name (ksba_cert_t cert)
     634             : {
     635             :   char *result;
     636             :   ksba_sexp_t sn;
     637             :   char *issuer, *p;
     638             : 
     639           0 :   if (!cert)
     640           0 :     return xtrystrdup ("[no certificate]");
     641             : 
     642           0 :   issuer = ksba_cert_get_issuer (cert, 0);
     643           0 :   sn = ksba_cert_get_serial (cert);
     644           0 :   if (issuer && sn)
     645             :     {
     646           0 :       p = format_serial (sn);
     647           0 :       if (!p)
     648           0 :         result = xtrystrdup ("[invalid S/N]");
     649             :       else
     650             :         {
     651           0 :           result = xtrymalloc (strlen (p) + strlen (issuer) + 2 + 1);
     652           0 :           if (result)
     653             :             {
     654           0 :               *result = '#';
     655           0 :               strcpy (stpcpy (stpcpy (result+1, p),"/"), issuer);
     656             :             }
     657           0 :           xfree (p);
     658             :         }
     659             :     }
     660             :   else
     661           0 :     result = xtrystrdup ("[missing S/N or issuer]");
     662           0 :   ksba_free (sn);
     663           0 :   xfree (issuer);
     664           0 :   return result;
     665             : }
     666             : 
     667             : /* Return a malloced string with the serial number and the issuer DN
     668             :    of the certificate.  */
     669             : static char *
     670           0 : get_cert_subject (ksba_cert_t cert, int idx)
     671             : {
     672             :   char *result;
     673             :   char *subject;
     674             : 
     675           0 :   if (!cert)
     676           0 :     return xtrystrdup ("[no certificate]");
     677             : 
     678           0 :   subject = ksba_cert_get_subject (cert, idx);
     679           0 :   if (subject)
     680             :     {
     681           0 :       result = xtrymalloc (strlen (subject) + 1 + 1);
     682           0 :       if (result)
     683             :         {
     684           0 :           *result = '/';
     685           0 :           strcpy (result+1, subject);
     686             :         }
     687             :     }
     688             :   else
     689           0 :     result = NULL;
     690           0 :   xfree (subject);
     691           0 :   return result;
     692             : }
     693             : 
     694             : 
     695             : /* List the given certificiate.  If CERT is NULL, this is a NOP.  */
     696             : static void
     697           0 : list_cert (audit_ctx_t ctx, ksba_cert_t cert, int with_subj)
     698             : {
     699             :   char *name;
     700             :   int idx;
     701             : 
     702           0 :   name = get_cert_name (cert);
     703           0 :   writeout_rem (ctx, "%s", name);
     704           0 :   xfree (name);
     705           0 :   if (with_subj)
     706             :     {
     707           0 :       enter_li (ctx);
     708           0 :       for (idx=0; (name = get_cert_subject (cert, idx)); idx++)
     709             :         {
     710           0 :           writeout_rem (ctx, "%s", name);
     711           0 :           xfree (name);
     712             :         }
     713           0 :       leave_li (ctx);
     714             :     }
     715           0 : }
     716             : 
     717             : 
     718             : /* List the chain of certificates from STARTITEM up to STOPEVENT.  The
     719             :    certifcates are written out as comments.  */
     720             : static void
     721           0 : list_certchain (audit_ctx_t ctx, log_item_t startitem, audit_event_t stopevent)
     722             : {
     723             :   log_item_t item;
     724             : 
     725           0 :   startitem = find_next_log_item (ctx, startitem, AUDIT_CHAIN_BEGIN,stopevent);
     726           0 :   writeout_li (ctx, startitem? "Yes":"No", _("Certificate chain available"));
     727           0 :   if (!startitem)
     728           0 :     return;
     729             : 
     730           0 :   item = find_next_log_item (ctx, startitem,
     731             :                              AUDIT_CHAIN_ROOTCERT, AUDIT_CHAIN_END);
     732           0 :   if (!item)
     733           0 :     writeout_rem (ctx, "%s", _("root certificate missing"));
     734             :   else
     735             :     {
     736           0 :       list_cert (ctx, item->cert, 0);
     737             :     }
     738           0 :   item = startitem;
     739           0 :   while ( ((item = find_next_log_item (ctx, item,
     740             :                                        AUDIT_CHAIN_CERT, AUDIT_CHAIN_END))))
     741             :     {
     742           0 :       list_cert (ctx, item->cert, 1);
     743             :     }
     744             : }
     745             : 
     746             : 
     747             : 
     748             : /* Process an encrypt operation's log.  */
     749             : static void
     750           0 : proc_type_encrypt (audit_ctx_t ctx)
     751             : {
     752             :   log_item_t loopitem, item;
     753             :   int recp_no, idx;
     754             :   char numbuf[35];
     755             :   int algo;
     756             :   char *name;
     757             : 
     758           0 :   item = find_log_item (ctx, AUDIT_ENCRYPTION_DONE, 0);
     759           0 :   writeout_li (ctx, item?"Yes":"No", "%s", _("Data encryption succeeded"));
     760             : 
     761           0 :   enter_li (ctx);
     762             : 
     763           0 :   item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
     764           0 :   writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
     765             : 
     766           0 :   item = find_log_item (ctx, AUDIT_SESSION_KEY, 0);
     767           0 :   writeout_li (ctx, item? "Yes":"No", "%s", _("Session key created"));
     768           0 :   if (item)
     769             :     {
     770           0 :       algo = gcry_cipher_map_name (item->string);
     771           0 :       if (algo)
     772           0 :         writeout_rem (ctx, _("algorithm: %s"), gnupg_cipher_algo_name (algo));
     773           0 :       else if (item->string && !strcmp (item->string, "1.2.840.113549.3.2"))
     774           0 :         writeout_rem (ctx, _("unsupported algorithm: %s"), "RC2");
     775           0 :       else if (item->string)
     776           0 :         writeout_rem (ctx, _("unsupported algorithm: %s"), item->string);
     777             :       else
     778           0 :         writeout_rem (ctx, _("seems to be not encrypted"));
     779             :     }
     780             : 
     781           0 :   item = find_log_item (ctx, AUDIT_GOT_RECIPIENTS, 0);
     782           0 :   snprintf (numbuf, sizeof numbuf, "%d",
     783           0 :             item && item->have_intvalue? item->intvalue : 0);
     784           0 :   writeout_li (ctx, numbuf, "%s", _("Number of recipients"));
     785             : 
     786             :   /* Loop over all recipients.  */
     787           0 :   loopitem = NULL;
     788           0 :   recp_no = 0;
     789           0 :   while ((loopitem=find_next_log_item (ctx, loopitem, AUDIT_ENCRYPTED_TO, 0)))
     790             :     {
     791           0 :       recp_no++;
     792           0 :       writeout_li (ctx, NULL, _("Recipient %d"), recp_no);
     793           0 :       if (loopitem->cert)
     794             :         {
     795           0 :           name = get_cert_name (loopitem->cert);
     796           0 :           writeout_rem (ctx, "%s", name);
     797           0 :           xfree (name);
     798           0 :           enter_li (ctx);
     799           0 :           for (idx=0; (name = get_cert_subject (loopitem->cert, idx)); idx++)
     800             :             {
     801           0 :               writeout_rem (ctx, "%s", name);
     802           0 :               xfree (name);
     803             :             }
     804           0 :           leave_li (ctx);
     805             :         }
     806             :     }
     807             : 
     808           0 :   leave_li (ctx);
     809           0 : }
     810             : 
     811             : 
     812             : 
     813             : /* Process a sign operation's log.  */
     814             : static void
     815           0 : proc_type_sign (audit_ctx_t ctx)
     816             : {
     817             :   log_item_t item, loopitem;
     818             :   int signer, idx;
     819             :   const char *result;
     820             :   ksba_cert_t cert;
     821             :   char *name;
     822             :   int lastalgo;
     823             : 
     824           0 :   item = find_log_item (ctx, AUDIT_SIGNING_DONE, 0);
     825           0 :   writeout_li (ctx, item?"Yes":"No", "%s", _("Data signing succeeded"));
     826             : 
     827           0 :   enter_li (ctx);
     828             : 
     829           0 :   item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
     830           0 :   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.  */
     833           0 :   loopitem = NULL;
     834           0 :   lastalgo = 0;
     835           0 :   while ((loopitem = find_next_log_item
     836             :           (ctx, loopitem, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG)))
     837             :     {
     838           0 :       if (loopitem->intvalue && loopitem->intvalue != lastalgo)
     839           0 :         writeout_rem (ctx, _("data hash algorithm: %s"),
     840             :                       gcry_md_algo_name (loopitem->intvalue));
     841           0 :       lastalgo = loopitem->intvalue;
     842             :     }
     843             : 
     844             :   /* Loop over all signer.  */
     845           0 :   loopitem = NULL;
     846           0 :   signer = 0;
     847           0 :   while ((loopitem=find_next_log_item (ctx, loopitem, AUDIT_NEW_SIG, 0)))
     848             :     {
     849           0 :       signer++;
     850             : 
     851           0 :       item = find_next_log_item (ctx, loopitem, AUDIT_SIGNED_BY, AUDIT_NEW_SIG);
     852           0 :       if (!item)
     853           0 :         result = "error";
     854           0 :       else if (!item->err)
     855           0 :         result = "okay";
     856           0 :       else if (gpg_err_code (item->err) == GPG_ERR_CANCELED)
     857           0 :         result = "skipped";
     858             :       else
     859           0 :         result = gpg_strerror (item->err);
     860           0 :       cert = item? item->cert : NULL;
     861             : 
     862           0 :       writeout_li (ctx, result, _("Signer %d"), signer);
     863           0 :       item = find_next_log_item (ctx, loopitem,
     864             :                                  AUDIT_ATTR_HASH_ALGO, AUDIT_NEW_SIG);
     865           0 :       if (item)
     866           0 :         writeout_rem (ctx, _("attr hash algorithm: %s"),
     867             :                       gcry_md_algo_name (item->intvalue));
     868             : 
     869           0 :       if (cert)
     870             :         {
     871           0 :           name = get_cert_name (cert);
     872           0 :           writeout_rem (ctx, "%s", name);
     873           0 :           xfree (name);
     874           0 :           enter_li (ctx);
     875           0 :           for (idx=0; (name = get_cert_subject (cert, idx)); idx++)
     876             :             {
     877           0 :               writeout_rem (ctx, "%s", name);
     878           0 :               xfree (name);
     879             :             }
     880           0 :           leave_li (ctx);
     881             :         }
     882             :     }
     883             : 
     884           0 :   leave_li (ctx);
     885           0 : }
     886             : 
     887             : 
     888             : 
     889             : /* Process a decrypt operation's log.  */
     890             : static void
     891           0 : proc_type_decrypt (audit_ctx_t ctx)
     892             : {
     893             :   log_item_t loopitem, item;
     894             :   int algo, recpno;
     895             :   char *name;
     896             :   char numbuf[35];
     897             :   int idx;
     898             : 
     899           0 :   item = find_log_item (ctx, AUDIT_DECRYPTION_RESULT, 0);
     900           0 :   writeout_li (ctx, item && !item->err?"Yes":"No",
     901             :                "%s", _("Data decryption succeeded"));
     902             : 
     903           0 :   enter_li (ctx);
     904             : 
     905           0 :   item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
     906           0 :   writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
     907             : 
     908           0 :   item = find_log_item (ctx, AUDIT_DATA_CIPHER_ALGO, 0);
     909           0 :   algo = item? item->intvalue : 0;
     910           0 :   writeout_li (ctx, algo?"Yes":"No", "%s", _("Encryption algorithm supported"));
     911           0 :   if (algo)
     912           0 :     writeout_rem (ctx, _("algorithm: %s"), gnupg_cipher_algo_name (algo));
     913             : 
     914           0 :   item = find_log_item (ctx, AUDIT_BAD_DATA_CIPHER_ALGO, 0);
     915           0 :   if (item && item->string)
     916             :     {
     917           0 :       algo = gcry_cipher_map_name (item->string);
     918           0 :       if (algo)
     919           0 :         writeout_rem (ctx, _("algorithm: %s"), gnupg_cipher_algo_name (algo));
     920           0 :       else if (item->string && !strcmp (item->string, "1.2.840.113549.3.2"))
     921           0 :         writeout_rem (ctx, _("unsupported algorithm: %s"), "RC2");
     922           0 :       else if (item->string)
     923           0 :         writeout_rem (ctx, _("unsupported algorithm: %s"), item->string);
     924             :       else
     925           0 :         writeout_rem (ctx, _("seems to be not encrypted"));
     926             :     }
     927             : 
     928             : 
     929           0 :   for (recpno = 0, item = NULL;
     930           0 :        (item = find_next_log_item (ctx, item, AUDIT_NEW_RECP, 0)); recpno++)
     931             :     ;
     932           0 :   snprintf (numbuf, sizeof numbuf, "%d", recpno);
     933           0 :   writeout_li (ctx, numbuf, "%s", _("Number of recipients"));
     934             : 
     935             :   /* Loop over all recipients.  */
     936           0 :   loopitem = NULL;
     937           0 :   while ((loopitem = find_next_log_item (ctx, loopitem, AUDIT_NEW_RECP, 0)))
     938             :     {
     939             :       const char *result;
     940             : 
     941           0 :       recpno = loopitem->have_intvalue? loopitem->intvalue : -1;
     942             : 
     943           0 :       item = find_next_log_item (ctx, loopitem,
     944             :                                  AUDIT_RECP_RESULT, AUDIT_NEW_RECP);
     945           0 :       if (!item)
     946           0 :         result = "not-used";
     947           0 :       else if (!item->err)
     948           0 :         result = "okay";
     949           0 :       else if (gpg_err_code (item->err) == GPG_ERR_CANCELED)
     950           0 :         result = "skipped";
     951             :       else
     952           0 :         result = gpg_strerror (item->err);
     953             : 
     954           0 :       item = find_next_log_item (ctx, loopitem,
     955             :                                  AUDIT_RECP_NAME, AUDIT_NEW_RECP);
     956           0 :       writeout_li (ctx, result, _("Recipient %d"), recpno);
     957           0 :       if (item && item->string)
     958           0 :         writeout_rem (ctx, "%s", item->string);
     959             : 
     960             :       /* If we have a certificate write out more infos.  */
     961           0 :       item = find_next_log_item (ctx, loopitem,
     962             :                                  AUDIT_SAVE_CERT, AUDIT_NEW_RECP);
     963           0 :       if (item && item->cert)
     964             :         {
     965           0 :           enter_li (ctx);
     966           0 :           for (idx=0; (name = get_cert_subject (item->cert, idx)); idx++)
     967             :             {
     968           0 :               writeout_rem (ctx, "%s", name);
     969           0 :               xfree (name);
     970             :             }
     971           0 :           leave_li (ctx);
     972             :         }
     973             :     }
     974             : 
     975           0 :   leave_li (ctx);
     976           0 : }
     977             : 
     978             : 
     979             : 
     980             : /* Process a verification operation's log.  */
     981             : static void
     982           0 : proc_type_verify (audit_ctx_t ctx)
     983             : {
     984             :   log_item_t loopitem, item;
     985             :   int signo, count, idx, n_good, n_bad;
     986             :   char numbuf[35];
     987             :   const char *result;
     988             : 
     989             :   /* If there is at least one signature status we claim that the
     990             :      verification succeeded.  This does not mean that the data has
     991             :      verified okay.  */
     992           0 :   item = find_log_item (ctx, AUDIT_SIG_STATUS, 0);
     993           0 :   writeout_li (ctx, item?"Yes":"No", "%s", _("Data verification succeeded"));
     994           0 :   enter_li (ctx);
     995             : 
     996           0 :   item = find_log_item (ctx, AUDIT_GOT_DATA, AUDIT_NEW_SIG);
     997           0 :   writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
     998           0 :   if (!item)
     999           0 :     goto leave;
    1000             : 
    1001           0 :   item = find_log_item (ctx, AUDIT_NEW_SIG, 0);
    1002           0 :   writeout_li (ctx, item? "Yes":"No", "%s", _("Signature available"));
    1003           0 :   if (!item)
    1004           0 :     goto leave;
    1005             : 
    1006             :   /* Print info about the used data hashing algorithms.  */
    1007           0 :   for (idx=0, n_good=n_bad=0; idx < ctx->logused; idx++)
    1008             :     {
    1009           0 :       item = ctx->log + idx;
    1010           0 :       if (item->event == AUDIT_NEW_SIG)
    1011           0 :         break;
    1012           0 :       else if (item->event == AUDIT_DATA_HASH_ALGO)
    1013           0 :         n_good++;
    1014           0 :       else if (item->event == AUDIT_BAD_DATA_HASH_ALGO)
    1015           0 :         n_bad++;
    1016             :     }
    1017           0 :   item = find_log_item (ctx, AUDIT_DATA_HASHING, AUDIT_NEW_SIG);
    1018           0 :   if (!item || item->err || !n_good)
    1019           0 :     result = "No";
    1020           0 :   else if (n_good && !n_bad)
    1021           0 :     result = "Yes";
    1022             :   else
    1023           0 :     result = "Some";
    1024           0 :   writeout_li (ctx, result, "%s", _("Parsing data succeeded"));
    1025           0 :   if (n_good || n_bad)
    1026             :     {
    1027           0 :       for (idx=0; idx < ctx->logused; idx++)
    1028             :         {
    1029           0 :           item = ctx->log + idx;
    1030           0 :           if (item->event == AUDIT_NEW_SIG)
    1031           0 :             break;
    1032           0 :           else if (item->event == AUDIT_DATA_HASH_ALGO)
    1033           0 :             writeout_rem (ctx, _("data hash algorithm: %s"),
    1034             :                           gcry_md_algo_name (item->intvalue));
    1035           0 :           else if (item->event == AUDIT_BAD_DATA_HASH_ALGO)
    1036           0 :             writeout_rem (ctx, _("bad data hash algorithm: %s"),
    1037           0 :                           item->string? item->string:"?");
    1038             :         }
    1039             :     }
    1040             : 
    1041             : 
    1042             :   /* Loop over all signatures.  */
    1043           0 :   loopitem = find_log_item (ctx, AUDIT_NEW_SIG, 0);
    1044           0 :   assert (loopitem);
    1045             :   do
    1046             :     {
    1047           0 :       signo = loopitem->have_intvalue? loopitem->intvalue : -1;
    1048             : 
    1049           0 :       item = find_next_log_item (ctx, loopitem,
    1050             :                                  AUDIT_SIG_STATUS, AUDIT_NEW_SIG);
    1051           0 :       writeout_li (ctx, item? item->string:"?", _("Signature %d"), signo);
    1052           0 :       item = find_next_log_item (ctx, loopitem,
    1053             :                                  AUDIT_SIG_NAME, AUDIT_NEW_SIG);
    1054           0 :       if (item)
    1055           0 :         writeout_rem (ctx, "%s", item->string);
    1056             : 
    1057           0 :       item = find_next_log_item (ctx, loopitem,
    1058             :                                  AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG);
    1059           0 :       if (item)
    1060           0 :         writeout_rem (ctx, _("data hash algorithm: %s"),
    1061             :                       gcry_md_algo_name (item->intvalue));
    1062           0 :       item = find_next_log_item (ctx, loopitem,
    1063             :                                  AUDIT_ATTR_HASH_ALGO, AUDIT_NEW_SIG);
    1064           0 :       if (item)
    1065           0 :         writeout_rem (ctx, _("attr hash algorithm: %s"),
    1066             :                       gcry_md_algo_name (item->intvalue));
    1067             : 
    1068           0 :       enter_li (ctx);
    1069             : 
    1070             :       /* List the certificate chain.  */
    1071           0 :       list_certchain (ctx, loopitem, AUDIT_NEW_SIG);
    1072             : 
    1073             :       /* Show the result of the chain validation.  */
    1074           0 :       item = find_next_log_item (ctx, loopitem,
    1075             :                                  AUDIT_CHAIN_STATUS, AUDIT_NEW_SIG);
    1076           0 :       if (item && item->have_err)
    1077             :         {
    1078           0 :           writeout_li (ctx, item->err? "No":"Yes",
    1079           0 :                        _("Certificate chain valid"));
    1080           0 :           if (item->err)
    1081           0 :             writeout_rem (ctx, "%s", gpg_strerror (item->err));
    1082             :         }
    1083             : 
    1084             :       /* Show whether the root certificate is fine.  */
    1085           0 :       item = find_next_log_item (ctx, loopitem,
    1086             :                                  AUDIT_ROOT_TRUSTED, AUDIT_CHAIN_STATUS);
    1087           0 :       if (item)
    1088             :         {
    1089           0 :           writeout_li (ctx, item->err?"No":"Yes", "%s",
    1090             :                        _("Root certificate trustworthy"));
    1091           0 :           if (item->err)
    1092             :             {
    1093           0 :               add_helptag (ctx, "gpgsm.root-cert-not-trusted");
    1094           0 :               writeout_rem (ctx, "%s", gpg_strerror (item->err));
    1095           0 :               list_cert (ctx, item->cert, 0);
    1096             :             }
    1097             :         }
    1098             : 
    1099             :       /* Show result of the CRL/OCSP check.  */
    1100           0 :       item = find_next_log_item (ctx, loopitem,
    1101             :                                  AUDIT_CRL_CHECK, AUDIT_NEW_SIG);
    1102           0 :       if (item)
    1103             :         {
    1104             :           const char *ok;
    1105           0 :           switch (gpg_err_code (item->err))
    1106             :             {
    1107           0 :             case 0:                    ok = "good"; break;
    1108           0 :             case GPG_ERR_CERT_REVOKED: ok = "bad"; break;
    1109           0 :             case GPG_ERR_NOT_ENABLED:  ok = "disabled"; break;
    1110             :             case GPG_ERR_NO_CRL_KNOWN:
    1111           0 :               ok = _("no CRL found for certificate");
    1112           0 :               break;
    1113             :             case GPG_ERR_CRL_TOO_OLD:
    1114           0 :               ok = _("the available CRL is too old");
    1115           0 :               break;
    1116           0 :             default: ok = gpg_strerror (item->err); break;
    1117             :             }
    1118             : 
    1119           0 :           writeout_li (ctx, ok, "%s", _("CRL/OCSP check of certificates"));
    1120           0 :           if (item->err
    1121           0 :               && gpg_err_code (item->err) != GPG_ERR_CERT_REVOKED
    1122           0 :               && gpg_err_code (item->err) != GPG_ERR_NOT_ENABLED)
    1123           0 :             add_helptag (ctx, "gpgsm.crl-problem");
    1124             :         }
    1125             : 
    1126           0 :       leave_li (ctx);
    1127             :     }
    1128           0 :   while ((loopitem = find_next_log_item (ctx, loopitem, AUDIT_NEW_SIG, 0)));
    1129             : 
    1130             : 
    1131             :  leave:
    1132             :   /* Always list the certificates stored in the signature.  */
    1133           0 :   item = NULL;
    1134           0 :   count = 0;
    1135           0 :   while ( ((item = find_next_log_item (ctx, item,
    1136             :                                        AUDIT_SAVE_CERT, AUDIT_NEW_SIG))))
    1137           0 :     count++;
    1138           0 :   snprintf (numbuf, sizeof numbuf, "%d", count);
    1139           0 :   writeout_li (ctx, numbuf, _("Included certificates"));
    1140           0 :   item = NULL;
    1141           0 :   while ( ((item = find_next_log_item (ctx, item,
    1142             :                                        AUDIT_SAVE_CERT, AUDIT_NEW_SIG))))
    1143             :     {
    1144           0 :       char *name = get_cert_name (item->cert);
    1145           0 :       writeout_rem (ctx, "%s", name);
    1146           0 :       xfree (name);
    1147           0 :       enter_li (ctx);
    1148           0 :       for (idx=0; (name = get_cert_subject (item->cert, idx)); idx++)
    1149             :         {
    1150           0 :           writeout_rem (ctx, "%s", name);
    1151           0 :           xfree (name);
    1152             :         }
    1153           0 :       leave_li (ctx);
    1154             :     }
    1155           0 :   leave_li (ctx);
    1156           0 : }
    1157             : 
    1158             : 
    1159             : 
    1160             : 
    1161             : /* Print the formatted audit result.    THIS IS WORK IN PROGRESS.  */
    1162             : void
    1163           0 : audit_print_result (audit_ctx_t ctx, estream_t out, int use_html)
    1164             : {
    1165             :   int idx;
    1166             :   size_t n;
    1167             :   log_item_t item;
    1168             :   helptag_t helptag;
    1169             :   const char *s;
    1170           0 :   int show_raw = 0;
    1171             :   char *orig_codeset;
    1172             : 
    1173           0 :   if (!ctx)
    1174           0 :     return;
    1175             : 
    1176           0 :   orig_codeset = i18n_switchto_utf8 ();
    1177             : 
    1178             :   /* We use an environment variable to include some debug info in the
    1179             :      log.  */
    1180           0 :   if ((s = getenv ("gnupg_debug_audit")))
    1181           0 :     show_raw = 1;
    1182             : 
    1183           0 :   assert (!ctx->outstream);
    1184           0 :   ctx->outstream = out;
    1185           0 :   ctx->use_html = use_html;
    1186           0 :   ctx->indentlevel = 0;
    1187           0 :   clear_helptags (ctx);
    1188             : 
    1189           0 :   if (use_html)
    1190           0 :     es_fputs ("<div class=\"" GNUPG_NAME "AuditLog\">\n", ctx->outstream);
    1191             : 
    1192           0 :   if (!ctx->log || !ctx->logused)
    1193             :     {
    1194           0 :       writeout_para (ctx, _("No audit log entries."));
    1195           0 :       goto leave;
    1196             :     }
    1197             : 
    1198           0 :   if (show_raw)
    1199             :     {
    1200             :       int maxlen;
    1201             : 
    1202           0 :       for (idx=0,maxlen=0; idx < DIM (eventstr_msgidx); idx++)
    1203             :         {
    1204           0 :           n = strlen (eventstr_msgstr + eventstr_msgidx[idx]);
    1205           0 :           if (n > maxlen)
    1206           0 :             maxlen = n;
    1207             :         }
    1208             : 
    1209           0 :       if (use_html)
    1210           0 :         es_fputs ("<pre>\n", out);
    1211           0 :       for (idx=0; idx < ctx->logused; idx++)
    1212             :         {
    1213           0 :           es_fprintf (out, "log: %-*s",
    1214           0 :                       maxlen, event2str (ctx->log[idx].event));
    1215           0 :           if (ctx->log[idx].have_intvalue)
    1216           0 :             es_fprintf (out, " i=%d", ctx->log[idx].intvalue);
    1217           0 :           if (ctx->log[idx].string)
    1218             :             {
    1219           0 :               es_fputs (" s='", out);
    1220           0 :               writeout (ctx, ctx->log[idx].string);
    1221           0 :               es_fputs ("'", out);
    1222             :             }
    1223           0 :           if (ctx->log[idx].cert)
    1224           0 :             es_fprintf (out, " has_cert");
    1225           0 :           if (ctx->log[idx].have_err)
    1226             :             {
    1227           0 :               es_fputs (" err='", out);
    1228           0 :               writeout (ctx, gpg_strerror (ctx->log[idx].err));
    1229           0 :               es_fputs ("'", out);
    1230             :             }
    1231           0 :           es_fputs ("\n", out);
    1232             :         }
    1233           0 :       if (use_html)
    1234           0 :         es_fputs ("</pre>\n", out);
    1235             :       else
    1236           0 :         es_fputs ("\n", out);
    1237             :     }
    1238             : 
    1239           0 :   enter_li (ctx);
    1240           0 :   switch (ctx->type)
    1241             :     {
    1242             :     case AUDIT_TYPE_NONE:
    1243           0 :       writeout_li (ctx, NULL, _("Unknown operation"));
    1244           0 :       break;
    1245             :     case AUDIT_TYPE_ENCRYPT:
    1246           0 :       proc_type_encrypt (ctx);
    1247           0 :       break;
    1248             :     case AUDIT_TYPE_SIGN:
    1249           0 :       proc_type_sign (ctx);
    1250           0 :       break;
    1251             :     case AUDIT_TYPE_DECRYPT:
    1252           0 :       proc_type_decrypt (ctx);
    1253           0 :       break;
    1254             :     case AUDIT_TYPE_VERIFY:
    1255           0 :       proc_type_verify (ctx);
    1256           0 :       break;
    1257             :     }
    1258           0 :   item = find_log_item (ctx, AUDIT_AGENT_READY, 0);
    1259           0 :   if (item && item->have_err)
    1260             :     {
    1261           0 :       writeout_li (ctx, item->err? "No":"Yes", "%s", _("Gpg-Agent usable"));
    1262           0 :       if (item->err)
    1263             :         {
    1264           0 :           writeout_rem (ctx, "%s", gpg_strerror (item->err));
    1265           0 :           add_helptag (ctx, "gnupg.agent-problem");
    1266             :         }
    1267             :     }
    1268           0 :   item = find_log_item (ctx, AUDIT_DIRMNGR_READY, 0);
    1269           0 :   if (item && item->have_err)
    1270             :     {
    1271           0 :       writeout_li (ctx, item->err? "No":"Yes", "%s", _("Dirmngr usable"));
    1272           0 :       if (item->err)
    1273             :         {
    1274           0 :           writeout_rem (ctx, "%s", gpg_strerror (item->err));
    1275           0 :           add_helptag (ctx, "gnupg.dirmngr-problem");
    1276             :         }
    1277             :     }
    1278           0 :   leave_li (ctx);
    1279             : 
    1280             : 
    1281             :   /* Show the help from the collected help tags.  */
    1282           0 :   if (ctx->helptags)
    1283             :     {
    1284           0 :       if (use_html)
    1285             :         {
    1286           0 :           es_fputs ("<hr/>\n", ctx->outstream);
    1287           0 :           if (ctx->helptags->next)
    1288           0 :             es_fputs ("<ul>\n", ctx->outstream);
    1289             :         }
    1290             :       else
    1291           0 :         es_fputs ("\n\n", ctx->outstream);
    1292             :     }
    1293           0 :   for (helptag = ctx->helptags; helptag; helptag = helptag->next)
    1294             :     {
    1295             :       char *text;
    1296             : 
    1297           0 :       if (use_html && ctx->helptags->next)
    1298           0 :         es_fputs ("<li>\n", ctx->outstream);
    1299             : 
    1300           0 :       text = gnupg_get_help_string (helptag->name, 0);
    1301           0 :       if (text)
    1302             :         {
    1303           0 :           writeout_para (ctx, "%s", text);
    1304           0 :           xfree (text);
    1305             :         }
    1306             :       else
    1307           0 :         writeout_para (ctx, _("No help available for '%s'."), helptag->name);
    1308           0 :       if (use_html && ctx->helptags->next)
    1309           0 :         es_fputs ("</li>\n", ctx->outstream);
    1310           0 :       if (helptag->next)
    1311           0 :         es_fputs ("\n", ctx->outstream);
    1312             :     }
    1313           0 :   if (use_html && ctx->helptags && ctx->helptags->next)
    1314           0 :     es_fputs ("</ul>\n", ctx->outstream);
    1315             : 
    1316             :  leave:
    1317           0 :   if (use_html)
    1318           0 :     es_fputs ("</div>\n", ctx->outstream);
    1319           0 :   ctx->outstream = NULL;
    1320           0 :   ctx->use_html = 0;
    1321           0 :   clear_helptags (ctx);
    1322           0 :   i18n_switchback (orig_codeset);
    1323             : }

Generated by: LCOV version 1.11