view common/logging.c @ 856:797aa8d9c785

(issue48) Fallback to HKEY_USERS on hive load failure If the hive can not be loaded it might mean that the user is currently logged on. In that case we can access his registry via HKEY_USERS.
author Andre Heinecke <andre.heinecke@intevation.de>
date Thu, 31 Jul 2014 12:56:26 +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/