view common/logging.c @ 801:4538cda1062c

Merged
author Sascha Wilde <wilde@intevation.de>
date Tue, 15 Jul 2014 15:44:53 +0200
parents 2303caf56dbb
children 698b6a9bd75e
line wrap: on
line source
/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU GPL (v>=2)
 * and comes with ABSOLUTELY NO WARRANTY!
 * See LICENSE.txt for details.
 */
#include "logging.h"
#include "strhelp.h"

#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>

#include <strhelp.h>

#include <certhelp.h>

#include <polarssl/sha256.h>

#ifdef WIN32
# include <windows.h>
# include "events.h"
#else
# include <syslog.h>
#endif

#ifdef WIN32

/** @brief helper to prepare common logging information */
static void
win_do_log(WORD type, WORD category, DWORD eventID, WORD numStrings, LPCWSTR *strings)
{
  HANDLE log_src = NULL,
         process_token = NULL;
  PTOKEN_USER user_struct = NULL;
  PSID user_sid = NULL;
  BOOL success = FALSE;

  log_src = RegisterEventSourceW (NULL, L"" LOG_NAME);

  if (log_src == NULL)
    {
      PRINTLASTERROR ("Failed to open log source.");
      return;
    }

  /* Get the current user sid for logging */
  OpenProcessToken (GetCurrentProcess(), TOKEN_READ, &process_token);
  if (process_token)
    {
      DWORD size = 0;

      // check how much space is needed
      GetTokenInformation (process_token, TokenUser, NULL, 0, &size);
      if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
        {
          user_struct = xmalloc (size);
          GetTokenInformation (process_token, TokenUser, user_struct, size, &size);
          user_sid = user_struct->User.Sid;
        }
    }

  success = ReportEventW (log_src,
                          type,
                          category,
                          eventID,
                          user_sid,
                          numStrings,
                          0,
                          strings,
                          NULL);
  if (!success)
    {
      PRINTLASTERROR ("Failed to report event.");
    }

  if (process_token)
    {
      CloseHandle(process_token);
    }
  xfree (user_struct);

  if (!DeregisterEventSource (log_src))
    {
      PRINTLASTERROR ("Failed to close log source.");
    }
}

static void
win_log(const char *format, va_list ap, bool error)
{
  wchar_t *wmsg = NULL;
  char buffer[MAX_LOG+1];
  vsnprintf (buffer, MAX_LOG, format, ap);

  buffer[MAX_LOG] = '\0';

  wmsg = utf8_to_wchar (buffer, strlen(buffer));
  if (wmsg == NULL)
    {
      ERRORPRINTF ("Failed to convert log message to utf-16");
      return;
    }

  win_do_log (error ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
              EVENT_CAT_TB,
              error ? MSG_DEFAULT_ERROR : MSG_DEFAULT_INFO,
              1,
              (const WCHAR **) &wmsg);


  xfree (wmsg);

  return;
}

char *
getLastErrorMsg()
{
  LPWSTR bufPtr = NULL;
  DWORD err = GetLastError();
  char *retval = NULL;
  FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_FROM_SYSTEM |
                  FORMAT_MESSAGE_IGNORE_INSERTS,
                  NULL, err, 0, (LPWSTR) &bufPtr, 0, NULL);
  if (!bufPtr)
    {
      HMODULE hWinhttp = GetModuleHandleW (L"crypt32");
      if (hWinhttp)
        {
          FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
                          FORMAT_MESSAGE_FROM_HMODULE |
                          FORMAT_MESSAGE_IGNORE_INSERTS,
                          hWinhttp, HRESULT_CODE (err), 0,
                          (LPWSTR) &bufPtr, 0, NULL);
        }
    }
  if (!bufPtr) {
    fprintf (stderr, "Error getting last error for code: %lx \n", err);
    return NULL;
  }

  retval = wchar_to_utf8(bufPtr, wcslen(bufPtr));
  LocalFree (bufPtr);

  return retval;
}

#else /* WIN32 */

static void
linux_log (const char *format, va_list ap, bool error)
{
  openlog (LOG_NAME, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
  vsyslog ( error ? LOG_ERR : LOG_INFO, format, ap);
}

#endif /* WIN32 */

void
log_certificate(const char* store, char *b64cert, bool install)
{
  char *der_data = NULL;
  size_t der_size = 0;
  int ret = 0;

  ret = str_base64_decode (&der_data, &der_size, b64cert, strlen(b64cert));

  if (ret != 0)
    {
      ERRORPRINTF ("Error decoding certificate.\n");
      return;
    }

  log_certificate_der (store, (unsigned char *) der_data, der_size, install);

  xfree (der_data);
}

void
log_certificate_der(const char *store, unsigned char *der_data, size_t der_size, bool install)
{
  char subject[MAX_LOG + 1];
  int ret = 0,
      i = 0;
  x509_crt chain;
  unsigned char sha256sum[32];
  char fingerprint[32 * 3 + 1];

  x509_crt_init(&chain);
  if (x509_crt_parse_der(&chain, (const unsigned char *)der_data,
                         der_size) != 0)
    {
      ERRORPRINTF("Failed to parse cert..");
      return;
    }

  ret = x509_dn_gets(subject, MAX_LOG, &(chain.subject));

  if (ret == -1)
    {
      ERRORPRINTF("Failed to parse subject..");
      return;
    }
  subject[MAX_LOG] = '\0';

  sha256 (chain.raw.p, chain.raw.len, sha256sum, 0);

  for (i = 0; i < 31; i++)
    {
      snprintf (fingerprint + (i * 3), 4, "%02X:", sha256sum[i]);
    }
  snprintf (fingerprint + (31 * 3), 3, "%02X", sha256sum[31]);

  fingerprint[32*3] = '\0';

#ifdef WIN32
    {
      wchar_t *wstrings[3];

      wstrings[0] = utf8_to_wchar (subject, strnlen (subject, MAX_LOG));
      wstrings[1] = utf8_to_wchar (fingerprint, strnlen (fingerprint, MAX_LOG));
      wstrings[2] = utf8_to_wchar (store, strnlen (store, MAX_LOG));

      win_do_log (EVENTLOG_INFORMATION_TYPE,
                  EVENT_CAT_CINST,
                  install ? MSG_CERT_INSTALL : MSG_CERT_REMOVE,
                  3,
                  (const WCHAR**) wstrings);
      xfree (wstrings[0]);
      xfree (wstrings[1]);
      xfree (wstrings[2]);
    }
#else
  /* Please keep the following line in line with message from events.mc */
  syslog_info_printf ("%s of root certificate: %s Sha256 thumbprint:<%s>. Certificate store \"%s\"",
                      install ? "Installation" : "Removal",
                      subject, fingerprint, store);
#endif
  x509_crt_free (&chain);
}

void
syslog_info_printf(const char *format, ...)
{
  va_list args;
  va_start (args, format);
#ifdef WIN32
  win_log (format, args, false);
#else
  linux_log (format, args, false);
#endif
  va_end (args);
}

void
syslog_error_printf(const char *format, ...)
{
  va_list args;
  va_start (args, format);
#ifdef WIN32
  win_log (format, args, true);
#else
  linux_log (format, args, true);
#endif
  va_end (args);
}

http://wald.intevation.org/projects/trustbridge/