aheinecke@404: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik aheinecke@404: * Software engineering by Intevation GmbH aheinecke@404: * aheinecke@404: * This file is Free Software under the GNU GPL (v>=2) aheinecke@404: * and comes with ABSOLUTELY NO WARRANTY! aheinecke@404: * See LICENSE.txt for details. aheinecke@404: */ aheinecke@252: #include "logging.h" aheinecke@252: #include "strhelp.h" aheinecke@252: aheinecke@252: #include andre@615: #include andre@615: #include andre@615: andre@615: #include aheinecke@252: andre@623: #include andre@623: andre@623: #include andre@623: aheinecke@252: #ifdef WIN32 andre@615: # include andre@620: # include "events.h" andre@615: #else andre@615: # include andre@615: #endif andre@615: andre@615: #ifdef WIN32 andre@623: andre@623: /** @brief helper to prepare common logging information */ andre@615: static void andre@623: win_do_log(WORD type, WORD category, DWORD eventID, WORD numStrings, LPCWSTR *strings) andre@615: { andre@616: HANDLE log_src = NULL, andre@616: process_token = NULL; andre@616: PTOKEN_USER user_struct = NULL; andre@616: PSID user_sid = NULL; andre@623: BOOL success = FALSE; andre@615: andre@620: log_src = RegisterEventSourceW (NULL, L"" LOG_NAME); andre@615: andre@615: if (log_src == NULL) andre@615: { andre@615: PRINTLASTERROR ("Failed to open log source."); andre@615: return; andre@615: } andre@615: andre@616: /* Get the current user sid for logging */ andre@616: OpenProcessToken (GetCurrentProcess(), TOKEN_READ, &process_token); andre@616: if (process_token) andre@616: { andre@616: DWORD size = 0; andre@616: andre@616: // check how much space is needed andre@616: GetTokenInformation (process_token, TokenUser, NULL, 0, &size); andre@616: if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) andre@616: { andre@616: user_struct = xmalloc (size); andre@616: GetTokenInformation (process_token, TokenUser, user_struct, size, &size); andre@616: user_sid = user_struct->User.Sid; andre@616: } andre@616: } andre@616: andre@620: success = ReportEventW (log_src, andre@623: type, andre@623: category, andre@623: eventID, andre@616: user_sid, andre@623: numStrings, andre@615: 0, andre@623: strings, andre@615: NULL); andre@620: if (!success) andre@615: { andre@615: PRINTLASTERROR ("Failed to report event."); andre@615: } andre@615: andre@616: if (process_token) andre@616: { andre@616: CloseHandle(process_token); andre@616: } andre@616: xfree (user_struct); andre@615: andre@615: if (!DeregisterEventSource (log_src)) andre@615: { andre@615: PRINTLASTERROR ("Failed to close log source."); andre@615: } andre@623: } andre@623: andre@623: static void andre@623: win_log(const char *format, va_list ap, bool error) andre@623: { andre@623: wchar_t *wmsg = NULL; andre@623: char buffer[MAX_LOG+1]; andre@623: vsnprintf (buffer, MAX_LOG, format, ap); andre@623: andre@623: buffer[MAX_LOG] = '\0'; andre@623: andre@623: wmsg = utf8_to_wchar (buffer, strlen(buffer)); andre@623: if (wmsg == NULL) andre@623: { andre@623: ERRORPRINTF ("Failed to convert log message to utf-16"); andre@623: return; andre@623: } andre@623: andre@623: win_do_log (error ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE, andre@623: EVENT_CAT_TB, andre@623: error ? MSG_DEFAULT_ERROR : MSG_DEFAULT_INFO, andre@623: 1, andre@623: (const WCHAR **) &wmsg); andre@623: andre@623: andre@623: xfree (wmsg); andre@623: andre@615: return; andre@615: } andre@615: aheinecke@252: char * aheinecke@252: getLastErrorMsg() aheinecke@252: { aheinecke@252: LPWSTR bufPtr = NULL; aheinecke@252: DWORD err = GetLastError(); aheinecke@252: char *retval = NULL; aheinecke@252: FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | aheinecke@252: FORMAT_MESSAGE_FROM_SYSTEM | aheinecke@252: FORMAT_MESSAGE_IGNORE_INSERTS, aheinecke@252: NULL, err, 0, (LPWSTR) &bufPtr, 0, NULL); aheinecke@252: if (!bufPtr) aheinecke@252: { aheinecke@252: HMODULE hWinhttp = GetModuleHandleW (L"crypt32"); aheinecke@252: if (hWinhttp) aheinecke@252: { aheinecke@252: FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | aheinecke@252: FORMAT_MESSAGE_FROM_HMODULE | aheinecke@252: FORMAT_MESSAGE_IGNORE_INSERTS, aheinecke@252: hWinhttp, HRESULT_CODE (err), 0, aheinecke@252: (LPWSTR) &bufPtr, 0, NULL); aheinecke@252: } aheinecke@252: } andre@905: if (!bufPtr) andre@905: { andre@905: fprintf (stderr, "Error getting last error for code: %lx \n", err); andre@905: return NULL; andre@905: } aheinecke@252: aheinecke@252: retval = wchar_to_utf8(bufPtr, wcslen(bufPtr)); aheinecke@252: LocalFree (bufPtr); aheinecke@252: aheinecke@252: return retval; aheinecke@252: } aheinecke@252: andre@615: #else /* WIN32 */ andre@615: andre@615: static void andre@615: linux_log (const char *format, va_list ap, bool error) andre@615: { andre@615: openlog (LOG_NAME, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER); andre@615: vsyslog ( error ? LOG_ERR : LOG_INFO, format, ap); andre@615: } andre@615: andre@615: #endif /* WIN32 */ andre@615: andre@615: void andre@623: log_certificate(const char* store, char *b64cert, bool install) andre@623: { andre@625: char *der_data = NULL; andre@623: size_t der_size = 0; andre@625: int ret = 0; andre@623: andre@623: ret = str_base64_decode (&der_data, &der_size, b64cert, strlen(b64cert)); andre@623: andre@623: if (ret != 0) andre@623: { andre@623: ERRORPRINTF ("Error decoding certificate.\n"); andre@623: return; andre@623: } andre@623: andre@625: log_certificate_der (store, (unsigned char *) der_data, der_size, install); andre@625: andre@625: xfree (der_data); andre@625: } andre@625: andre@625: void andre@625: log_certificate_der(const char *store, unsigned char *der_data, size_t der_size, bool install) andre@625: { andre@625: char subject[MAX_LOG + 1]; andre@625: int ret = 0, andre@625: i = 0; andre@625: x509_crt chain; andre@625: unsigned char sha256sum[32]; andre@625: char fingerprint[32 * 3 + 1]; andre@625: andre@623: x509_crt_init(&chain); andre@623: if (x509_crt_parse_der(&chain, (const unsigned char *)der_data, andre@623: der_size) != 0) andre@623: { andre@623: ERRORPRINTF("Failed to parse cert.."); andre@623: return; andre@623: } andre@623: andre@623: ret = x509_dn_gets(subject, MAX_LOG, &(chain.subject)); andre@623: andre@623: if (ret == -1) andre@623: { andre@623: ERRORPRINTF("Failed to parse subject.."); andre@623: return; andre@623: } andre@623: subject[MAX_LOG] = '\0'; andre@623: andre@623: sha256 (chain.raw.p, chain.raw.len, sha256sum, 0); andre@623: andre@623: for (i = 0; i < 31; i++) andre@623: { andre@625: snprintf (fingerprint + (i * 3), 4, "%02X:", sha256sum[i]); andre@623: } andre@625: snprintf (fingerprint + (31 * 3), 3, "%02X", sha256sum[31]); andre@623: andre@623: fingerprint[32*3] = '\0'; andre@623: andre@623: #ifdef WIN32 andre@905: { andre@905: wchar_t *wstrings[3]; andre@623: andre@905: wstrings[0] = utf8_to_wchar (subject, strnlen (subject, MAX_LOG)); andre@905: wstrings[1] = utf8_to_wchar (fingerprint, strnlen (fingerprint, MAX_LOG)); andre@905: wstrings[2] = utf8_to_wchar (store, strnlen (store, MAX_LOG)); andre@905: andre@905: win_do_log (EVENTLOG_INFORMATION_TYPE, andre@905: EVENT_CAT_CINST, andre@905: install ? MSG_CERT_INSTALL : MSG_CERT_REMOVE, andre@905: 3, andre@905: (const WCHAR**) wstrings); andre@905: xfree (wstrings[0]); andre@905: xfree (wstrings[1]); andre@905: xfree (wstrings[2]); andre@905: } andre@623: #else andre@623: /* Please keep the following line in line with message from events.mc */ andre@625: syslog_info_printf ("%s of root certificate: %s Sha256 thumbprint:<%s>. Certificate store \"%s\"", andre@625: install ? "Installation" : "Removal", andre@625: subject, fingerprint, store); andre@623: #endif andre@623: x509_crt_free (&chain); andre@623: } andre@623: andre@623: void andre@615: syslog_info_printf(const char *format, ...) andre@615: { andre@615: va_list args; andre@615: va_start (args, format); andre@615: #ifdef WIN32 andre@615: win_log (format, args, false); andre@615: #else andre@615: linux_log (format, args, false); aheinecke@252: #endif andre@615: va_end (args); andre@615: } andre@615: andre@615: void andre@615: syslog_error_printf(const char *format, ...) andre@615: { andre@615: va_list args; andre@615: va_start (args, format); andre@615: #ifdef WIN32 andre@615: win_log (format, args, true); andre@615: #else andre@615: linux_log (format, args, true); andre@615: #endif andre@615: va_end (args); andre@615: }