master
c 107 lines 3.76 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "windows-events-query-builder.h"
4
5 // --------------------------------------------------------------------------------------------------------------------
6 // query without XPath
7
8 typedef struct static_utf8_8k {
9 char buffer[8192];
10 size_t size;
11 size_t len;
12 } STATIC_BUF_8K;
13
14 typedef struct static_unicode_16k {
15 wchar_t buffer[16384];
16 size_t size;
17 size_t len;
18 } STATIC_UNI_16K;
19
20 static bool wevt_foreach_selected_value_cb(FACETS *facets __maybe_unused, size_t id, const char *key, const char *value, void *data) {
21 STATIC_BUF_8K *b = data;
22
23 b->len += snprintfz(&b->buffer[b->len], b->size - b->len,
24 "%s%s=%s",
25 id ? " or " : "", key, value);
26
27 return b->len < b->size;
28 }
29
30 wchar_t *wevt_generate_query_no_xpath(LOGS_QUERY_STATUS *lqs, BUFFER *wb) {
31 static __thread STATIC_UNI_16K q = {
32 .size = sizeof(q.buffer) / sizeof(wchar_t),
33 .len = 0,
34 };
35 static __thread STATIC_BUF_8K b = {
36 .size = sizeof(b.buffer) / sizeof(char),
37 .len = 0,
38 };
39
40 lqs_query_timeframe(lqs, ANCHOR_DELTA_UT);
41
42 usec_t seek_to = lqs->query.start_ut;
43 if(lqs->rq.direction == FACETS_ANCHOR_DIRECTION_BACKWARD)
44 // windows events queries are limited to millisecond resolution
45 // so, in order not to lose data, we have to add
46 // a millisecond when the direction is backward
47 seek_to += USEC_PER_MS;
48
49 // Convert the microseconds since Unix epoch to FILETIME (used in Windows APIs)
50 FILETIME fileTime = os_unix_epoch_ut_to_filetime(seek_to);
51
52 // Convert FILETIME to SYSTEMTIME for use in XPath
53 SYSTEMTIME systemTime;
54 if (!FileTimeToSystemTime(&fileTime, &systemTime)) {
55 nd_log(NDLS_COLLECTORS, NDLP_ERR, "FileTimeToSystemTime() failed");
56 return NULL;
57 }
58
59 // Format SYSTEMTIME into ISO 8601 format (YYYY-MM-DDTHH:MM:SS.sssZ)
60 q.len = swprintf(q.buffer, q.size,
61 L"Event/System[TimeCreated[@SystemTime%ls\"%04d-%02d-%02dT%02d:%02d:%02d.%03dZ\"]",
62 lqs->rq.direction == FACETS_ANCHOR_DIRECTION_BACKWARD ? L"<=" : L">=",
63 systemTime.wYear, systemTime.wMonth, systemTime.wDay,
64 systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds);
65
66 if(lqs->rq.slice) {
67 b.len = snprintf(b.buffer, b.size, " and (");
68 if (facets_foreach_selected_value_in_key(
69 lqs->facets,
70 WEVT_FIELD_LEVEL,
71 sizeof(WEVT_FIELD_LEVEL) - 1,
72 used_hashes_registry,
73 wevt_foreach_selected_value_cb,
74 &b)) {
75 b.len += snprintf(&b.buffer[b.len], b.size - b.len, ")");
76 if (b.len < b.size) {
77 utf82unicode(&q.buffer[q.len], q.size - q.len, b.buffer);
78 q.len = wcslen(q.buffer);
79 }
80 }
81
82 b.len = snprintf(b.buffer, b.size, " and (");
83 if (facets_foreach_selected_value_in_key(
84 lqs->facets,
85 WEVT_FIELD_EVENTID,
86 sizeof(WEVT_FIELD_EVENTID) - 1,
87 used_hashes_registry,
88 wevt_foreach_selected_value_cb,
89 &b)) {
90 b.len += snprintf(&b.buffer[b.len], b.size - b.len, ")");
91 if (b.len < b.size) {
92 utf82unicode(&q.buffer[q.len], q.size - q.len, b.buffer);
93 q.len = wcslen(q.buffer);
94 }
95 }
96 }
97
98 q.len += swprintf(&q.buffer[q.len], q.size - q.len, L"]");
99
100 buffer_json_member_add_string(wb, "_query", channel2utf8(q.buffer));
101
102 return q.buffer;
103 }
104
105 // --------------------------------------------------------------------------------------------------------------------
106 // query with XPath
107