diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 12:08:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 12:08:18 +0000 |
commit | 5da14042f70711ea5cf66e034699730335462f66 (patch) | |
tree | 0f6354ccac934ed87a2d555f45be4c831cf92f4a /src/fluent-bit/plugins/in_winlog/pack.c | |
parent | Releasing debian version 1.44.3-2. (diff) | |
download | netdata-5da14042f70711ea5cf66e034699730335462f66.tar.xz netdata-5da14042f70711ea5cf66e034699730335462f66.zip |
Merging upstream version 1.45.3+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/fluent-bit/plugins/in_winlog/pack.c')
-rw-r--r-- | src/fluent-bit/plugins/in_winlog/pack.c | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/src/fluent-bit/plugins/in_winlog/pack.c b/src/fluent-bit/plugins/in_winlog/pack.c new file mode 100644 index 000000000..4547d5514 --- /dev/null +++ b/src/fluent-bit/plugins/in_winlog/pack.c @@ -0,0 +1,451 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2022 The Fluent Bit Authors + * + * 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 <fluent-bit/flb_compat.h> +#include <fluent-bit/flb_mem.h> +#include <fluent-bit/flb_utils.h> +#include <fluent-bit/flb_pack.h> +#include <fluent-bit/flb_input_plugin.h> +#include <msgpack.h> +#include <sddl.h> +#include <locale.h> +#include "winlog.h" + +#define REGKEY_MAXLEN 256 +#define FMT_ISO8601 "%Y-%m-%d %H:%M:%S %z" +#define FMT_EVTLOG L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\%S\\%s" +#define FMT_EVTALT L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\%s" + +/* 127 is the max number of function params */ +#define PARAM_MAXNUM 127 + +#define SRCNAME(evt) ((wchar_t *) ((char *) (evt) + sizeof(EVENTLOGRECORD))) +#define BINDATA(evt) ((unsigned char *) (evt) + (evt)->DataOffset) + +static void pack_nullstr(msgpack_packer *mp_pck) +{ + msgpack_pack_str(mp_pck, 0); + msgpack_pack_str_body(mp_pck, "", 0); +} + +static int pack_wstr(msgpack_packer *mp_pck, wchar_t *wstr, int use_ansi) +{ + int size; + char *buf; + UINT codePage = CP_UTF8; + if (use_ansi) { + codePage = CP_ACP; + } + + /* Compute the buffer size first */ + size = WideCharToMultiByte(codePage, 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/System code Page encoding */ + size = WideCharToMultiByte(codePage, 0, wstr, -1, buf, size, NULL, NULL); + if (size == 0) { + flb_free(buf); + return -1; + } + + /* Pack buf except the trailing '\0' */ + msgpack_pack_str(mp_pck, size - 1); + msgpack_pack_str_body(mp_pck, buf, size - 1); + flb_free(buf); + return 0; +} + +static int pack_time(msgpack_packer *mp_pck, int time) +{ + size_t len; + struct tm tm; + char buf[64]; + _locale_t locale; + + if (_localtime32_s(&tm, &time)) { + flb_errno(); + return -1; + } + + locale = _get_current_locale(); + if (locale == NULL) { + return -1; + } + + len = _strftime_l(buf, 64, FMT_ISO8601, &tm, locale); + if (len == 0) { + flb_errno(); + _free_locale(locale); + return -1; + } + _free_locale(locale); + msgpack_pack_str(mp_pck, len); + msgpack_pack_str_body(mp_pck, buf, len); + + return 0; +} + +static int pack_event_type(msgpack_packer *mp_pck, int type) +{ + switch (type) { + case EVENTLOG_SUCCESS: + msgpack_pack_str(mp_pck, 7); + msgpack_pack_str_body(mp_pck, "Success", 7); + break; + case EVENTLOG_INFORMATION_TYPE: + msgpack_pack_str(mp_pck, 11); + msgpack_pack_str_body(mp_pck, "Information", 11); + break; + case EVENTLOG_WARNING_TYPE: + msgpack_pack_str(mp_pck, 7); + msgpack_pack_str_body(mp_pck, "Warning", 7); + break; + case EVENTLOG_ERROR_TYPE: + msgpack_pack_str(mp_pck, 5); + msgpack_pack_str_body(mp_pck, "Error", 5); + break; + case EVENTLOG_AUDIT_SUCCESS: + msgpack_pack_str(mp_pck, 12); + msgpack_pack_str_body(mp_pck, "SuccessAudit", 12); + break; + case EVENTLOG_AUDIT_FAILURE: + msgpack_pack_str(mp_pck, 12); + msgpack_pack_str_body(mp_pck, "FailureAudit", 12); + break; + default: + return -1; + } + return 0; +} + +static int pack_binary(msgpack_packer *mp_pck, unsigned char *bin, int len) +{ + const char *hex = "0123456789abcdef"; + char *buf; + int size = len * 2; + int i; + + if (len == 0) { + pack_nullstr(mp_pck); + return 0; + } + + buf = flb_malloc(size); + if (buf == NULL) { + flb_errno(); + return -1; + } + + for (i = 0; i < len; i++) { + buf[2*i] = hex[bin[i] / 16]; + buf[2*i+1] = hex[bin[i] % 16]; + } + msgpack_pack_str(mp_pck, size); + msgpack_pack_str_body(mp_pck, buf, size); + flb_free(buf); + return 0; +} + +static int pack_sid(msgpack_packer *mp_pck, PEVENTLOGRECORD evt, + struct winlog_config *ctx) +{ + size_t size; + char *buf; + char *sid = (char *) evt + evt->UserSidOffset; + + if (evt->UserSidLength == 0) { + pack_nullstr(mp_pck); + return 0; + } + + if (!ConvertSidToStringSidA(sid, &buf)) { + flb_plg_error(ctx->ins, "fail to convert SID: %i", GetLastError()); + return -1; + } + + size = strlen(buf); + msgpack_pack_str(mp_pck, size); + msgpack_pack_str_body(mp_pck, buf, size); + + LocalFree(buf); + return 0; +} + +static wchar_t *read_registry(HKEY hkey, wchar_t *key, wchar_t *val) +{ + int ret; + int size; + wchar_t *buf; + unsigned int flags = RRF_RT_REG_EXPAND_SZ | RRF_RT_REG_SZ; + + /* Get the buffer size first */ + ret = RegGetValueW(hkey, key, val, flags, NULL, NULL, &size); + if (ret != ERROR_SUCCESS) { + return NULL; + } + + buf = flb_malloc(size); + if (buf == NULL) { + flb_errno(); + return NULL; + } + + /* Read data into buffer */ + ret = RegGetValueW(hkey, key, val, flags, NULL, buf, &size); + if (ret != ERROR_SUCCESS) { + flb_free(buf); + return NULL; + } + return buf; +} + +static wchar_t *query_guid(wchar_t *guid) +{ + int ret; + wchar_t key[REGKEY_MAXLEN]; + + ret = swprintf_s(key, REGKEY_MAXLEN, FMT_EVTALT, guid); + if (ret == -1) { + flb_errno(); + return NULL; + } + + return read_registry(HKEY_LOCAL_MACHINE, key, L"MessageFileName"); +} + +static int pack_message(msgpack_packer *mp_pck, PEVENTLOGRECORD evt, + struct winlog_channel *ch, struct winlog_config *ctx) +{ + int ret; + int i; + HMODULE hfile; + wchar_t key[REGKEY_MAXLEN]; + wchar_t *msg; + wchar_t *paths; + wchar_t *path; + wchar_t *guid; + wchar_t *state; + wchar_t *tmp; + DWORD_PTR *args = NULL; + + ret = swprintf_s(key, REGKEY_MAXLEN, FMT_EVTLOG, ch->name, SRCNAME(evt)); + if (ret == -1) { + flb_errno(); + return -1; + } + + guid = read_registry(HKEY_LOCAL_MACHINE, key, L"ProviderGuid"); + if (guid) { + paths = query_guid(guid); + flb_free(guid); + } + else { + paths = read_registry(HKEY_LOCAL_MACHINE, key, L"EventMessageFile"); + } + + if (paths == NULL) { + return -1; + } + + if (evt->NumStrings) { + args = flb_calloc(PARAM_MAXNUM, sizeof(DWORD_PTR)); + if (args == NULL) { + flb_errno(); + flb_free(paths); + return -1; + } + + tmp = (wchar_t *) ((char *) evt + evt->StringOffset); + for (i = 0; i < evt->NumStrings; i++) { + args[i] = (DWORD_PTR) tmp; + tmp += wcslen(tmp) + 1; + } + } + + path = paths; + wcstok_s(path, L";", &state); + while (path) { + hfile = LoadLibraryExW(path, NULL, LOAD_LIBRARY_AS_DATAFILE); + if (hfile == NULL) { + path = wcstok_s(NULL , L";", &state); + continue; + } + + ret = FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_ARGUMENT_ARRAY, + hfile, /* lpSource */ + evt->EventID, /* dwMessageId */ + 0, /* dwLanguageId */ + (LPWSTR) &msg,/* lpBuffer */ + 0, /* nSize */ + (va_list *) args); + if (ret > 0) { + ret = pack_wstr(mp_pck, msg, ctx->use_ansi); + LocalFree(msg); + FreeLibrary(hfile); + flb_free(paths); + flb_free(args); + return ret; + } + FreeLibrary(hfile); + path = wcstok_s(NULL , L";", &state); + } + + flb_free(paths); + flb_free(args); + return -1; +} + +static void pack_strings(msgpack_packer *mp_pck, PEVENTLOGRECORD evt, int use_ansi) +{ + int i; + int len; + wchar_t *wstr = (wchar_t *) ((char *) evt + evt->StringOffset); + + msgpack_pack_array(mp_pck, evt->NumStrings); + + for (i = 0; i < evt->NumStrings; i++) { + if (pack_wstr(mp_pck, wstr, use_ansi)) { + pack_nullstr(mp_pck); + } + wstr += wcslen(wstr) + 1; + } +} + +void winlog_pack_event(msgpack_packer *mp_pck, PEVENTLOGRECORD evt, + struct winlog_channel *ch, struct winlog_config *ctx) +{ + wchar_t *source_name = SRCNAME(evt); + wchar_t *computer_name = source_name + wcslen(source_name) + 1; + size_t len; + int count = 13; + + if (ctx->string_inserts) { + count++; + } + + msgpack_pack_array(mp_pck, 2); + flb_pack_time_now(mp_pck); + + msgpack_pack_map(mp_pck, count); + + /* RecordNumber */ + msgpack_pack_str(mp_pck, 12); + msgpack_pack_str_body(mp_pck, "RecordNumber", 12); + msgpack_pack_uint32(mp_pck, evt->RecordNumber); + + /* TimeGenerated */ + msgpack_pack_str(mp_pck, 13); + msgpack_pack_str_body(mp_pck, "TimeGenerated", 13); + if (pack_time(mp_pck, evt->TimeGenerated)) { + flb_plg_error(ctx->ins, "invalid TimeGenerated %i", evt->TimeGenerated); + pack_nullstr(mp_pck); + } + + /* TimeWritten */ + msgpack_pack_str(mp_pck, 11); + msgpack_pack_str_body(mp_pck, "TimeWritten", 11); + if (pack_time(mp_pck, evt->TimeWritten)) { + flb_plg_error(ctx->ins, "invalid TimeWritten %i", evt->TimeWritten); + pack_nullstr(mp_pck); + } + + /* EventId */ + msgpack_pack_str(mp_pck, 7); + msgpack_pack_str_body(mp_pck, "EventID", 7); + msgpack_pack_uint16(mp_pck, evt->EventID & 0xffff); + + /* Qualifiers */ + msgpack_pack_str(mp_pck, 10); + msgpack_pack_str_body(mp_pck, "Qualifiers", 10); + msgpack_pack_uint16(mp_pck, evt->EventID >> 16); + + /* EventType */ + msgpack_pack_str(mp_pck, 9); + msgpack_pack_str_body(mp_pck, "EventType", 9); + if (pack_event_type(mp_pck, evt->EventType)) { + flb_plg_error(ctx->ins, "invalid EventType %i", evt->EventType); + pack_nullstr(mp_pck); + } + + /* EventCategory */ + msgpack_pack_str(mp_pck, 13); + msgpack_pack_str_body(mp_pck, "EventCategory", 13); + msgpack_pack_uint16(mp_pck, evt->EventCategory); + + /* Channel */ + len = strlen(ch->name); + msgpack_pack_str(mp_pck, 7); + msgpack_pack_str_body(mp_pck, "Channel", 7); + msgpack_pack_str(mp_pck, len); + msgpack_pack_str_body(mp_pck, ch->name, len); + + /* Source Name */ + msgpack_pack_str(mp_pck, 10); + msgpack_pack_str_body(mp_pck, "SourceName", 10); + if (pack_wstr(mp_pck, source_name, ctx->use_ansi)) { + flb_plg_error(ctx->ins, "invalid SourceName '%ls'", source_name); + pack_nullstr(mp_pck); + } + + /* Computer Name */ + msgpack_pack_str(mp_pck, 12); + msgpack_pack_str_body(mp_pck, "ComputerName", 12); + if (pack_wstr(mp_pck, computer_name, ctx->use_ansi)) { + flb_plg_error(ctx->ins, "invalid ComputerName '%ls'", computer_name); + pack_nullstr(mp_pck); + } + + /* Event-specific Data */ + msgpack_pack_str(mp_pck, 4); + msgpack_pack_str_body(mp_pck, "Data", 4); + if (pack_binary(mp_pck, BINDATA(evt), evt->DataLength)) { + pack_nullstr(mp_pck); + } + + /* Sid */ + msgpack_pack_str(mp_pck, 3); + msgpack_pack_str_body(mp_pck, "Sid", 3); + if (pack_sid(mp_pck, evt, ctx)) { + pack_nullstr(mp_pck); + } + + /* Message */ + msgpack_pack_str(mp_pck, 7); + msgpack_pack_str_body(mp_pck, "Message", 7); + if (pack_message(mp_pck, evt, ch, ctx)) { + pack_nullstr(mp_pck); + } + + /* StringInserts (optional) */ + if (ctx->string_inserts) { + msgpack_pack_str(mp_pck, 13); + msgpack_pack_str_body(mp_pck, "StringInserts", 13); + pack_strings(mp_pck, evt, ctx->use_ansi); + } +} |