/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Fluent Bit * ========== * Copyright (C) 2019-2021 The Fluent Bit Authors * Copyright (C) 2015-2018 Treasure Data Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include "winevtlog.h" #define FORMAT_ISO8601 "%Y-%m-%d %H:%M:%S %z" #define BINDATA(evt) ((unsigned char *) (evt) + (evt)->DataOffset) static int pack_nullstr(struct winevtlog_config *ctx) { flb_log_event_encoder_append_body_cstring(ctx->log_encoder, ""); } static int pack_wstr(struct winevtlog_config *ctx, const wchar_t *wstr) { int size; char *buf; UINT code_page = CP_UTF8; LPCSTR defaultChar = L" "; if (ctx->use_ansi) { code_page = CP_ACP; } /* Compute the buffer size first */ size = WideCharToMultiByte(code_page, 0, wstr, -1, NULL, 0, NULL, NULL); if (size == 0) { return -1; } buf = flb_malloc(size); if (buf == NULL) { flb_errno(); return -1; } /* Convert UTF-16 into UTF-8 */ size = WideCharToMultiByte(code_page, 0, wstr, -1, buf, size, defaultChar, NULL); if (size == 0) { flb_free(buf); return -1; } /* Pack buf except the trailing '\0' */ flb_log_event_encoder_append_body_string(ctx->log_encoder, buf, size - 1); flb_free(buf); return 0; } static int pack_binary(struct winevtlog_config *ctx, PBYTE bin, size_t length) { const char *HEX_TABLE = "0123456789ABCDEF"; char *buffer; int size = length * 2; size_t i, j; unsigned int idx = 0; if (length == 0) { pack_nullstr(ctx->log_encoder); return 0; } buffer = flb_malloc(size); if (buffer == NULL) { flb_errno(); return -1; } for (i = 0; i < length; i++) { for (j = 0; j < 2; j++) { idx = (unsigned int)(bin[i] >> (j * 4) & 0x0F); buffer[2*i+(1-j)] = HEX_TABLE[idx]; } } flb_log_event_encoder_append_body_string(ctx->log_encoder, buffer, size); flb_free(buffer); return 0; } static int pack_guid(struct winevtlog_config *ctx, const GUID *guid) { LPOLESTR p = NULL; if (FAILED(StringFromCLSID(guid, &p))) { return -1; } if (pack_wstr(ctx, p)) { CoTaskMemFree(p); return -1; } CoTaskMemFree(p); return 0; } static int pack_hex32(struct winevtlog_config *ctx, int32_t hex) { CHAR buffer[32]; size_t size = _countof(buffer); _snprintf_s(buffer, size, _TRUNCATE, "0x%lx", hex); size = strlen(buffer); if (size > 0) { flb_log_event_encoder_append_body_cstring(ctx->log_encoder, buffer); return 0; } return -1; } static int pack_hex64(struct winevtlog_config *ctx, int64_t hex) { CHAR buffer[32]; size_t size = _countof(buffer); _snprintf_s(buffer, size, _TRUNCATE, "0x%llx", hex); size = strlen(buffer); if (size > 0) { flb_log_event_encoder_append_body_cstring(ctx->log_encoder, buffer); return 0; } return -1; } static int pack_keywords(struct winevtlog_config *ctx, uint64_t keywords) { CHAR buffer[32]; size_t size = _countof(buffer); _snprintf_s(buffer, size, _TRUNCATE, "0x%llx", keywords); size = strlen(buffer); flb_log_event_encoder_append_body_cstring(ctx->log_encoder, buffer); return 0; } static int pack_systemtime(struct winevtlog_config *ctx, SYSTEMTIME *st) { CHAR buf[64]; size_t len = 0; _locale_t locale; TIME_ZONE_INFORMATION tzi; SYSTEMTIME st_local; GetTimeZoneInformation(&tzi); locale = _get_current_locale(); if (locale == NULL) { return -1; } if (st != NULL) { SystemTimeToTzSpecificLocalTime(&tzi, st, &st_local); struct tm tm = {st_local.wSecond, st_local.wMinute, st_local.wHour, st_local.wDay, st_local.wMonth-1, st_local.wYear-1900, st_local.wDayOfWeek, 0, 0}; len = _strftime_l(buf, 64, FORMAT_ISO8601, &tm, locale); if (len == 0) { flb_errno(); _free_locale(locale); return -1; } _free_locale(locale); flb_log_event_encoder_append_body_string(ctx->log_encoder, buf, len); } else { return -1; } return 0; } static int pack_filetime(struct winevtlog_config *ctx, ULONGLONG filetime) { LARGE_INTEGER timestamp; CHAR buf[64]; size_t len = 0; FILETIME ft, ft_local; SYSTEMTIME st; _locale_t locale; locale = _get_current_locale(); if (locale == NULL) { return -1; } timestamp.QuadPart = filetime; ft.dwHighDateTime = timestamp.HighPart; ft.dwLowDateTime = timestamp.LowPart; FileTimeToLocalFileTime(&ft, &ft_local); if (FileTimeToSystemTime(&ft_local, &st)) { struct tm tm = {st.wSecond, st.wMinute, st.wHour, st.wDay, st.wMonth-1, st.wYear-1900, st.wDayOfWeek, 0, 0}; len = _strftime_l(buf, 64, FORMAT_ISO8601, &tm, locale); if (len == 0) { flb_errno(); _free_locale(locale); return -1; } _free_locale(locale); flb_log_event_encoder_append_body_string(ctx->log_encoder, buf, len); } else { return -1; } return 0; } static int pack_sid(struct winevtlog_config *ctx, PSID sid) { size_t size; LPWSTR wide_sid = NULL; int ret = -1; if (ConvertSidToStringSidW(sid, &wide_sid)) { ret = pack_wstr(ctx, wide_sid); LocalFree(wide_sid); return ret; } return ret; } static void pack_string_inserts(struct winevtlog_config *ctx, PEVT_VARIANT values, DWORD count) { int i; int ret; ret = flb_log_event_encoder_body_begin_array(ctx->log_encoder); for (i = 0; i < count; i++) { if (values[i].Type & EVT_VARIANT_TYPE_ARRAY) { continue; } switch (values[i].Type & EVT_VARIANT_TYPE_MASK) { case EvtVarTypeNull: pack_nullstr(ctx); break; case EvtVarTypeString: if (pack_wstr(ctx, values[i].StringVal)) { pack_nullstr(ctx); } break; case EvtVarTypeAnsiString: if (pack_wstr(ctx, values[i].AnsiStringVal)) { pack_nullstr(ctx); } break; case EvtVarTypeSByte: flb_log_event_encoder_append_body_int8(ctx->log_encoder, values[i].SByteVal); break; case EvtVarTypeByte: flb_log_event_encoder_append_body_uint8(ctx->log_encoder, values[i].ByteVal); break; case EvtVarTypeInt16: flb_log_event_encoder_append_body_int16(ctx->log_encoder, values[i].Int16Val); break; case EvtVarTypeUInt16: flb_log_event_encoder_append_body_uint16(ctx->log_encoder, values[i].UInt16Val); break; case EvtVarTypeInt32: flb_log_event_encoder_append_body_int32(ctx->log_encoder, values[i].Int32Val); break; case EvtVarTypeUInt32: flb_log_event_encoder_append_body_uint32(ctx->log_encoder, values[i].UInt32Val); break; case EvtVarTypeInt64: flb_log_event_encoder_append_body_int64(ctx->log_encoder, values[i].Int64Val); break; case EvtVarTypeUInt64: flb_log_event_encoder_append_body_uint64(ctx->log_encoder, values[i].UInt64Val); break; case EvtVarTypeSingle: flb_log_event_encoder_append_body_double(ctx->log_encoder, values[i].SingleVal); break; case EvtVarTypeDouble: flb_log_event_encoder_append_body_double(ctx->log_encoder, values[i].DoubleVal); break; case EvtVarTypeBoolean: flb_log_event_encoder_append_body_boolean(ctx->log_encoder, (int) values[i].BooleanVal); break; case EvtVarTypeGuid: if (pack_guid(ctx, values[i].GuidVal)) { pack_nullstr(ctx); } break; case EvtVarTypeSizeT: flb_log_event_encoder_append_body_uint64(ctx->log_encoder, values[i].SizeTVal); break; case EvtVarTypeFileTime: if (pack_filetime(ctx, values[i].FileTimeVal)) { pack_nullstr(ctx); } break; case EvtVarTypeSysTime: if (pack_systemtime(ctx, values[i].SysTimeVal)) { pack_nullstr(ctx); } break; case EvtVarTypeSid: if (pack_sid(ctx, values[i].SidVal)) { pack_nullstr(ctx); } break; case EvtVarTypeHexInt32: if (pack_hex32(ctx, values[i].Int32Val)) { pack_nullstr(ctx); } break; case EvtVarTypeHexInt64: if (pack_hex64(ctx, values[i].Int64Val)) { pack_nullstr(ctx); } break; case EvtVarTypeEvtXml: if (pack_wstr(ctx, values[i].XmlVal, ctx)) { pack_nullstr(ctx); } break; case EvtVarTypeBinary: if (pack_binary(ctx, values[i].BinaryVal, values[i].Count)) { pack_nullstr(ctx); } break; default: flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "?"); } } if (ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_body_commit_array(ctx->log_encoder); } } void winevtlog_pack_xml_event(WCHAR *system_xml, WCHAR *message, PEVT_VARIANT string_inserts, UINT count_inserts, struct winevtlog_channel *ch, struct winevtlog_config *ctx) { int ret; ret = flb_log_event_encoder_begin_record(ctx->log_encoder); if (ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_set_current_timestamp(ctx->log_encoder); } ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "System"); if (pack_wstr(ctx, system_xml)) { pack_nullstr(ctx); } ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "Message"); if (pack_wstr(ctx, message)) { pack_nullstr(ctx); } if (ctx->string_inserts) { ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "StringInserts"); pack_string_inserts(ctx, string_inserts, count_inserts); } if (ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_commit_record(ctx->log_encoder); } } void winevtlog_pack_event(PEVT_VARIANT system, WCHAR *message, PEVT_VARIANT string_inserts, UINT count_inserts, struct winevtlog_channel *ch, struct winevtlog_config *ctx) { int ret; size_t len; int count = 19; if (ctx->string_inserts) { count++; } ret = flb_log_event_encoder_begin_record(ctx->log_encoder); if (ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_set_current_timestamp(ctx->log_encoder); } /* ProviderName */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "ProviderName"); if (pack_wstr(ctx, system[EvtSystemProviderName].StringVal)) { pack_nullstr(ctx); } /* ProviderGuid */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "ProviderGuid"); if (EvtVarTypeNull != system[EvtSystemProviderGuid].Type) { if (pack_guid(ctx, system[EvtSystemProviderGuid].GuidVal)) { pack_nullstr(ctx); } } else { pack_nullstr(ctx); } /* Qualifiers */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "Qualifiers"); if (EvtVarTypeNull != system[EvtSystemQualifiers].Type) { flb_log_event_encoder_append_body_uint16(ctx->log_encoder, system[EvtSystemQualifiers].UInt16Val); } else { pack_nullstr(ctx); } /* EventID */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "EventID"); if (EvtVarTypeNull != system[EvtSystemEventID].Type) { flb_log_event_encoder_append_body_uint16(ctx->log_encoder, system[EvtSystemEventID].UInt16Val); } else { pack_nullstr(ctx); } /* Version */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "Version"); if (EvtVarTypeNull != system[EvtSystemVersion].Type) { flb_log_event_encoder_append_body_uint8(ctx->log_encoder, system[EvtSystemVersion].ByteVal); } else { flb_log_event_encoder_append_body_uint8(ctx->log_encoder, 0); } /* Level */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "Level"); if (EvtVarTypeNull != system[EvtSystemLevel].Type) { flb_log_event_encoder_append_body_uint8(ctx->log_encoder, system[EvtSystemLevel].ByteVal); } else { flb_log_event_encoder_append_body_uint8(ctx->log_encoder, 0); } /* Task */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "Task"); if (EvtVarTypeNull != system[EvtSystemTask].Type) { flb_log_event_encoder_append_body_uint16(ctx->log_encoder, system[EvtSystemTask].UInt16Val); } else { flb_log_event_encoder_append_body_uint16(ctx->log_encoder, 0); } /* Opcode */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "Opcode"); if (EvtVarTypeNull != system[EvtSystemOpcode].Type) { flb_log_event_encoder_append_body_uint8(ctx->log_encoder, system[EvtSystemOpcode].ByteVal); } else { flb_log_event_encoder_append_body_uint8(ctx->log_encoder, 0); } /* Keywords */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "Keywords"); if (EvtVarTypeNull != system[EvtSystemKeywords].Type) { pack_keywords(ctx, system[EvtSystemKeywords].UInt64Val); } else { flb_log_event_encoder_append_body_uint64(ctx->log_encoder, 0); } /* TimeCreated */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "TimeCreated"); if (pack_filetime(ctx, system[EvtSystemTimeCreated].FileTimeVal)) { pack_nullstr(ctx); } /* EventRecordID */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "EventRecordID"); if (EvtVarTypeNull != system[EvtSystemEventRecordId].Type) { flb_log_event_encoder_append_body_uint64(ctx->log_encoder, system[EvtSystemEventRecordId].UInt64Val); } else { flb_log_event_encoder_append_body_uint64(ctx->log_encoder, 0); } /* ActivityID */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "ActivityID"); if (pack_guid(ctx, system[EvtSystemActivityID].GuidVal)) { pack_nullstr(ctx); } /* Related ActivityID */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "RelatedActivityID"); if (pack_guid(ctx, system[EvtSystemRelatedActivityID].GuidVal)) { pack_nullstr(ctx); } /* ProcessID */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "ProcessID"); if (EvtVarTypeNull != system[EvtSystemProcessID].Type) { flb_log_event_encoder_append_body_uint32(ctx->log_encoder, system[EvtSystemProcessID].UInt32Val); } else { flb_log_event_encoder_append_body_uint32(ctx->log_encoder, 0); } /* ThreadID */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "ThreadID"); if (EvtVarTypeNull != system[EvtSystemThreadID].Type) { flb_log_event_encoder_append_body_uint32(ctx->log_encoder, system[EvtSystemThreadID].UInt32Val); } else { flb_log_event_encoder_append_body_uint32(ctx->log_encoder, 0); } /* Channel */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "Channel"); if (pack_wstr(ctx, system[EvtSystemChannel].StringVal)) { pack_nullstr(ctx); } /* Computer */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "Computer"); if (pack_wstr(ctx, system[EvtSystemComputer].StringVal)) { pack_nullstr(ctx); } /* UserID */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "UserID"); if (pack_sid(ctx, system[EvtSystemUserID].SidVal)) { pack_nullstr(ctx); } /* Message */ ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "Message"); if (pack_wstr(ctx, message)) { pack_nullstr(ctx); } /* String Inserts */ if (ctx->string_inserts) { ret = flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "StringInserts"); pack_string_inserts(ctx, string_inserts, count_inserts); } if (ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_commit_record(ctx->log_encoder); } }