0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-04-14 17:48:37 +00:00
netdata_netdata/src/collectors/windows-events.plugin/windows-events-sid.c
Costa Tsaousis 2c9bca448e
[WIP] Windows-Events Logs Explorer ()
* preparations

* work on systemd-journal to abstract the components we need to use in windows events logs

* more code reorg to reuse systemd journal

* abstracted logs query parsing and preparation

* fix help printing

* moved non-LQS fields outside logs_query_status.h

* code re-organization and cleanup

* move lqs cleanup to lqs

* code re-organization and cleanup

* support accurate and approximate data sizes printing

* support for printing durations with spaces, for clarity

* progress on windows events sources

* windows events sources, with a count of logs

* windows events sources, with duration

* windows events sources, with file size

* support for converting between unix and windows timestamps

* fixed conditions

* internal api for querying windows event logs

* extract basic fields from windows events

* fix sid and guid

* users lookup with caching

* basic structure for the netdata plugin

* decode more message fields

* event log sources are now periodically scanned

* progress on building the query for windows events

* first working version

* support external plugins with .plugin.exe suffix

* fix compilation warnings

* fix thread safety

* fixes in severity and buffers used

* match all rows and do not pass empty data to facets

* keyword should be hex

* strict type checking and more fields, including the full XML view

* restructure the code to keep caches between channel queries

* format a message using the XML event data

* message is now formatted as a dynamic field at presentation time

* extracted UserData and applied basic XML formatting on the message

* properly intent nested nodes
2024-09-10 20:03:54 +03:00

120 lines
3.7 KiB
C

// SPDX-License-Identifier: GPL-3.0-or-later
#include "windows-events-sid.h"
#include <sddl.h>
typedef struct {
size_t len;
uint8_t sid[];
} SID_KEY;
typedef struct {
const char *user;
size_t user_len;
// this needs to be last, because of its variable size
SID_KEY key;
} SID_VALUE;
#define SIMPLE_HASHTABLE_NAME _SID
#define SIMPLE_HASHTABLE_VALUE_TYPE SID_VALUE
#define SIMPLE_HASHTABLE_KEY_TYPE SID_KEY
#define SIMPLE_HASHTABLE_VALUE2KEY_FUNCTION sid_value_to_key
#define SIMPLE_HASHTABLE_COMPARE_KEYS_FUNCTION sid_cache_compar
#define SIMPLE_HASHTABLE_SAMPLE_IMPLEMENTATION 1
#include "libnetdata/simple_hashtable.h"
static struct {
SPINLOCK spinlock;
bool initialized;
struct simple_hashtable_SID hashtable;
} sid_globals = {
.spinlock = NETDATA_SPINLOCK_INITIALIZER,
.hashtable = { 0 },
};
static inline SID_KEY *sid_value_to_key(SID_VALUE *s) {
return &s->key;
}
static inline bool sid_cache_compar(SID_KEY *a, SID_KEY *b) {
return a->len == b->len && memcmp(&a->sid, &b->sid, a->len) == 0;
}
static bool update_user(SID_VALUE *found, TXT_UTF8 *dst) {
if(found && found->user) {
txt_utf8_resize(dst, found->user_len + 1);
memcpy(dst->data, found->user, found->user_len + 1);
dst->used = found->user_len + 1;
return true;
}
txt_utf8_resize(dst, 1);
dst->data[0] = '\0';
dst->used = 1;
return false;
}
static void lookup_user(PSID *sid, TXT_UTF8 *dst) {
static __thread wchar_t account_unicode[256];
static __thread wchar_t domain_unicode[256];
DWORD account_name_size = sizeof(account_unicode) / sizeof(account_unicode[0]);
DWORD domain_name_size = sizeof(domain_unicode) / sizeof(domain_unicode[0]);
SID_NAME_USE sid_type;
txt_utf8_resize(dst, 1024);
if (LookupAccountSidW(NULL, sid, account_unicode, &account_name_size, domain_unicode, &domain_name_size, &sid_type)) {
const char *user = account2utf8(account_unicode);
const char *domain = domain2utf8(domain_unicode);
dst->used = snprintfz(dst->data, dst->size, "%s\\%s", domain, user) + 1;
}
else {
wchar_t *sid_string = NULL;
if (ConvertSidToStringSidW(sid, &sid_string)) {
const char *user = account2utf8(sid_string);
dst->used = snprintfz(dst->data, dst->size, "%s", user) + 1;
}
else
dst->used = snprintfz(dst->data, dst->size, "[invalid]") + 1;
}
}
bool wevt_convert_user_id_to_name(PSID sid, TXT_UTF8 *dst) {
if(!sid || !IsValidSid(sid))
return update_user(NULL, dst);
size_t size = GetLengthSid(sid);
size_t tmp_size = sizeof(SID_VALUE) + size;
size_t tmp_key_size = sizeof(SID_KEY) + size;
uint8_t buf[tmp_size];
SID_VALUE *tmp = (SID_VALUE *)&buf;
memcpy(&tmp->key.sid, sid, size);
tmp->key.len = size;
spinlock_lock(&sid_globals.spinlock);
if(!sid_globals.initialized) {
simple_hashtable_init_SID(&sid_globals.hashtable, 100);
sid_globals.initialized = true;
}
SID_VALUE *found = simple_hashtable_get_SID(&sid_globals.hashtable, &tmp->key, tmp_key_size);
spinlock_unlock(&sid_globals.spinlock);
if(found) return update_user(found, dst);
// allocate the SID_VALUE
found = mallocz(tmp_size);
memcpy(found, buf, tmp_size);
// lookup the user
lookup_user(sid, dst);
found->user = strdupz(dst->data);
found->user_len = dst->used - 1;
// add it to the cache
spinlock_lock(&sid_globals.spinlock);
simple_hashtable_set_SID(&sid_globals.hashtable, &found->key, tmp_key_size, found);
spinlock_unlock(&sid_globals.spinlock);
return update_user(found, dst);
}