Skip to content

Commit 1729b46

Browse files
committed
in_winevtlog: Import remoting access patch for winevtlog
Signed-off-by: Hiroshi Hatake <[email protected]>
1 parent 7859e8d commit 1729b46

File tree

3 files changed

+238
-5
lines changed

3 files changed

+238
-5
lines changed

plugins/in_winevtlog/in_winevtlog.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,120 @@
3636
static int in_winevtlog_collect(struct flb_input_instance *ins,
3737
struct flb_config *config, void *in_context);
3838

39+
static wchar_t* convert_to_wide(char *str)
40+
{
41+
int size = 0;
42+
wchar_t *buf = NULL;
43+
DWORD err;
44+
45+
size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
46+
if (size == 0) {
47+
err = GetLastError();
48+
flb_error("[in_winevtlog] Failed MultiByteToWideChar with error code (%d)", err);
49+
return NULL;
50+
}
51+
52+
buf = flb_calloc(1, sizeof(wchar_t) * size);
53+
if (buf == NULL) {
54+
flb_errno();
55+
return NULL;
56+
}
57+
size = MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, size);
58+
if (size == 0) {
59+
err = GetLastError();
60+
flb_error("[in_winevtlog] Failed MultiByteToWideChar with error code (%d)", err);
61+
flb_free(buf);
62+
return NULL;
63+
}
64+
65+
return buf;
66+
}
67+
68+
static void in_winevtlog_session_destory(struct winevtlog_session *session);
69+
70+
static struct winevtlog_session *in_winevtlog_session_create(struct winevtlog_config *ctx,
71+
struct flb_config *config,
72+
int *status)
73+
{
74+
int len;
75+
struct winevtlog_session *session;
76+
PWSTR wtmp;
77+
78+
if (ctx->remote_server == NULL) {
79+
*status = WINEVTLOG_SESSION_SERVER_EMPTY;
80+
return NULL;
81+
}
82+
83+
session = flb_calloc(1, sizeof(struct winevtlog_session));
84+
if (session == NULL) {
85+
flb_errno();
86+
*status = WINEVTLOG_SESSION_ALLOC_FAILED;
87+
return NULL;
88+
}
89+
90+
if (ctx->remote_server != NULL) {
91+
session->server = convert_to_wide(ctx->remote_server);
92+
if (session->server == NULL) {
93+
in_winevtlog_session_destory(session);
94+
*status = WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE;
95+
return NULL;
96+
}
97+
}
98+
99+
if (ctx->remote_domain != NULL) {
100+
session->domain = convert_to_wide(ctx->remote_domain);
101+
if (session->domain == NULL) {
102+
in_winevtlog_session_destory(session);
103+
*status = WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE;
104+
return NULL;
105+
}
106+
}
107+
108+
if (ctx->remote_username != NULL) {
109+
session->username = convert_to_wide(ctx->remote_username);
110+
if (session->username == NULL) {
111+
in_winevtlog_session_destory(session);
112+
*status = WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE;
113+
return NULL;
114+
}
115+
}
116+
117+
if (ctx->remote_password != NULL) {
118+
session->password = convert_to_wide(ctx->remote_password);
119+
if (session->password == NULL) {
120+
in_winevtlog_session_destory(session);
121+
*status = WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE;
122+
return NULL;
123+
}
124+
}
125+
126+
session->flags = EvtRpcLoginAuthDefault;
127+
*status = WINEVTLOG_SESSION_CREATE_OK;
128+
129+
return session;
130+
}
131+
132+
static void in_winevtlog_session_destory(struct winevtlog_session *session)
133+
{
134+
if (session->server != NULL) {
135+
flb_free(session->server);
136+
}
137+
138+
if (session->domain != NULL) {
139+
flb_free(session->domain);
140+
}
141+
142+
if (session->username != NULL) {
143+
flb_free(session->username);
144+
}
145+
146+
if (session->password != NULL) {
147+
flb_free(session->password);
148+
}
149+
150+
flb_free(session);
151+
}
152+
39153
static int in_winevtlog_init(struct flb_input_instance *in,
40154
struct flb_config *config, void *data)
41155
{
@@ -46,6 +160,8 @@ static int in_winevtlog_init(struct flb_input_instance *in,
46160
struct mk_list *head;
47161
struct winevtlog_channel *ch;
48162
struct winevtlog_config *ctx;
163+
struct winevtlog_session *session;
164+
int status = WINEVTLOG_SESSION_CREATE_OK;
49165

50166
/* Initialize context */
51167
ctx = flb_calloc(1, sizeof(struct winevtlog_config));
@@ -72,6 +188,18 @@ static int in_winevtlog_init(struct flb_input_instance *in,
72188
return -1;
73189
}
74190

191+
/* Initialize session context */
192+
session = in_winevtlog_session_create(ctx, config, &status);
193+
if (status == WINEVTLOG_SESSION_ALLOC_FAILED ||
194+
status == WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE) {
195+
flb_plg_error(in, "session is not created and invalid with %d", status);
196+
return -1;
197+
}
198+
else if (session == NULL) {
199+
flb_plg_debug(in, "session is not created. Connect to local machine.");
200+
}
201+
ctx->session = session;
202+
75203
/* Set up total reading size threshold */
76204
if (ctx->total_size_threshold >= MINIMUM_THRESHOLD_SIZE &&
77205
ctx->total_size_threshold <= MAXIMUM_THRESHOLD_SIZE) {
@@ -235,6 +363,9 @@ static int in_winevtlog_exit(void *data, struct flb_config *config)
235363
if (ctx->db) {
236364
flb_sqldb_close(ctx->db);
237365
}
366+
if (ctx->session) {
367+
in_winevtlog_session_destory(ctx->session);
368+
}
238369
flb_free(ctx);
239370

240371
return 0;
@@ -296,6 +427,26 @@ static struct flb_config_map config_map[] = {
296427
0, FLB_TRUE, offsetof(struct winevtlog_config, total_size_threshold),
297428
"Specify reading limit for collecting Windows EventLog per a cycle"
298429
},
430+
{
431+
FLB_CONFIG_MAP_STR, "remote.server", (char *)NULL,
432+
0, FLB_TRUE, offsetof(struct winevtlog_config, remote_server),
433+
"Specify server name of remote access for Windows EventLog"
434+
},
435+
{
436+
FLB_CONFIG_MAP_STR, "remote.domain", (char *)NULL,
437+
0, FLB_TRUE, offsetof(struct winevtlog_config, remote_domain),
438+
"Specify domain name of remote access for Windows EventLog"
439+
},
440+
{
441+
FLB_CONFIG_MAP_STR, "remote.username", (char *)NULL,
442+
0, FLB_TRUE, offsetof(struct winevtlog_config, remote_username),
443+
"Specify username of remote access for Windows EventLog"
444+
},
445+
{
446+
FLB_CONFIG_MAP_STR, "remote.password", (char *)NULL,
447+
0, FLB_TRUE, offsetof(struct winevtlog_config, remote_password),
448+
"Specify password of remote access for Windows EventLog"
449+
},
299450
/* EOF */
300451
{0}
301452
};

plugins/in_winevtlog/winevtlog.c

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,34 @@
3030
static char* convert_wstr(wchar_t *wstr, UINT codePage);
3131
static wchar_t* convert_str(char *str);
3232

33+
static EVT_HANDLE
34+
create_remote_handle(struct winevtlog_session *session, DWORD *error_code)
35+
{
36+
EVT_HANDLE remote = NULL;
37+
EVT_RPC_LOGIN credentials;
38+
39+
RtlZeroMemory(&credentials, sizeof(EVT_RPC_LOGIN));
40+
41+
credentials.Server = session->server;
42+
credentials.Domain = session->domain;
43+
credentials.User = session->username;
44+
credentials.Password = session->password;
45+
credentials.Flags = session->flags;
46+
47+
remote = EvtOpenSession(EvtRpcLogin, &credentials, 0, 0);
48+
if (!remote) {
49+
*error_code = GetLastError();
50+
return remote;
51+
}
52+
53+
SecureZeroMemory(&credentials, sizeof(EVT_RPC_LOGIN));
54+
55+
return remote;
56+
}
57+
3358
struct winevtlog_channel *winevtlog_subscribe(const char *channel, int read_existing_events,
34-
EVT_HANDLE stored_bookmark, const char *query)
59+
EVT_HANDLE stored_bookmark, const char *query,
60+
struct winevtlog_session *session)
3561
{
3662
struct winevtlog_channel *ch;
3763
EVT_HANDLE bookmark = NULL;
@@ -40,7 +66,9 @@ struct winevtlog_channel *winevtlog_subscribe(const char *channel, int read_exis
4066
DWORD flags = 0L;
4167
PWSTR wide_channel = NULL;
4268
PWSTR wide_query = NULL;
69+
EVT_HANDLE remote_handle = NULL;
4370
void *buf;
71+
DWORD err = ERROR_SUCCESS;
4472

4573
ch = flb_calloc(1, sizeof(struct winevtlog_channel));
4674
if (ch == NULL) {
@@ -78,17 +106,40 @@ struct winevtlog_channel *winevtlog_subscribe(const char *channel, int read_exis
78106
flags |= EvtSubscribeToFutureEvents;
79107
}
80108

109+
if (session != NULL) {
110+
remote_handle = create_remote_handle(session, &err);
111+
if (err != ERROR_SUCCESS) {
112+
flb_error("[in_winevtlog] cannot create remote handle '%s' in %ls (%i)",
113+
channel, session->server, err);
114+
flb_free(ch->name);
115+
if (ch->query != NULL) {
116+
flb_free(ch->query);
117+
}
118+
flb_free(ch);
119+
return NULL;
120+
}
121+
122+
flb_debug("[in_winevtlog] created a remote handle for '%s' in %ls",
123+
channel, session->server);
124+
ch->session = session;
125+
ch->remote = remote_handle;
126+
}
127+
81128
/* The wide_query parameter can handle NULL as `*` for retrieving all events.
82129
* ref. https://learn.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtsubscribe
83130
*/
84-
ch->subscription = EvtSubscribe(NULL, signal_event, wide_channel, wide_query,
131+
ch->subscription = EvtSubscribe(remote_handle, signal_event, wide_channel, wide_query,
85132
stored_bookmark, NULL, NULL, flags);
133+
err = GetLastError();
86134
if (!ch->subscription) {
87-
flb_error("[in_winevtlog] cannot subscribe '%s' (%i)", channel, GetLastError());
135+
flb_error("[in_winevtlog] cannot subscribe '%s' (%i)", channel, err);
88136
flb_free(ch->name);
89137
if (ch->query != NULL) {
90138
flb_free(ch->query);
91139
}
140+
if (ch->remote) {
141+
EvtClose(ch->remote);
142+
}
92143
flb_free(ch);
93144
return NULL;
94145
}
@@ -106,6 +157,9 @@ struct winevtlog_channel *winevtlog_subscribe(const char *channel, int read_exis
106157
if (ch->subscription) {
107158
EvtClose(ch->subscription);
108159
}
160+
if (ch->remote) {
161+
EvtClose(ch->remote);
162+
}
109163
if (signal_event) {
110164
CloseHandle(signal_event);
111165
}
@@ -141,6 +195,10 @@ static void close_handles(struct winevtlog_channel *ch)
141195
EvtClose(ch->subscription);
142196
ch->subscription = NULL;
143197
}
198+
if (ch->remote) {
199+
EvtClose(ch->remote);
200+
ch->remote = NULL;
201+
}
144202
if (ch->signal_event) {
145203
CloseHandle(ch->signal_event);
146204
ch->signal_event = NULL;
@@ -674,7 +732,8 @@ struct mk_list *winevtlog_open_all(const char *channels, struct winevtlog_config
674732

675733
channel = strtok_s(tmp , ",", &state);
676734
while (channel) {
677-
ch = winevtlog_subscribe(channel, ctx->read_existing_events, NULL, ctx->event_query);
735+
ch = winevtlog_subscribe(channel, ctx->read_existing_events, NULL, ctx->event_query,
736+
ctx->session);
678737
if (ch) {
679738
mk_list_add(&ch->_head, list);
680739
}
@@ -809,13 +868,14 @@ int winevtlog_sqlite_load(struct winevtlog_channel *ch, struct flb_sqldb *db)
809868
bookmark = EvtCreateBookmark(bookmark_xml);
810869
if (bookmark) {
811870
/* re-create subscription handles */
812-
re_ch = winevtlog_subscribe(ch->name, FLB_FALSE, bookmark, ch->query);
871+
re_ch = winevtlog_subscribe(ch->name, FLB_FALSE, bookmark, ch->query, ch->session);
813872
if (re_ch != NULL) {
814873
close_handles(ch);
815874

816875
ch->bookmark = re_ch->bookmark;
817876
ch->subscription = re_ch->subscription;
818877
ch->signal_event = re_ch->signal_event;
878+
ch->session = re_ch->session;
819879
}
820880
else {
821881
flb_error("Failed to subscribe with bookmark XML: %s\n", record.bookmark_xml);

plugins/in_winevtlog/winevtlog.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include <winevt.h>
2525
#include <fluent-bit/flb_log_event_encoder.h>
2626

27+
struct winevtlog_session;
28+
2729
struct winevtlog_config {
2830
unsigned int interval_sec;
2931
unsigned int interval_nsec;
@@ -34,6 +36,11 @@ struct winevtlog_config {
3436
int use_ansi;
3537
int ignore_missing_channels;
3638
flb_sds_t event_query;
39+
flb_sds_t remote_server;
40+
flb_sds_t remote_domain;
41+
flb_sds_t remote_username;
42+
flb_sds_t remote_password;
43+
struct winevtlog_session *session;
3744

3845
struct mk_list *active_channel;
3946
struct flb_sqldb *db;
@@ -50,9 +57,11 @@ struct winevtlog_config {
5057
struct winevtlog_channel {
5158
EVT_HANDLE subscription;
5259
EVT_HANDLE bookmark;
60+
EVT_HANDLE remote;
5361
HANDLE signal_event;
5462
EVT_HANDLE events[SUBSCRIBE_ARRAY_SIZE];
5563
int count;
64+
struct winevtlog_session *session;
5665

5766
char *name;
5867
char *query;
@@ -61,6 +70,19 @@ struct winevtlog_channel {
6170
struct mk_list _head;
6271
};
6372

73+
#define WINEVTLOG_SESSION_CREATE_OK 0
74+
#define WINEVTLOG_SESSION_ALLOC_FAILED 1
75+
#define WINEVTLOG_SESSION_SERVER_EMPTY 2
76+
#define WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE 3
77+
78+
struct winevtlog_session {
79+
PWSTR server;
80+
PWSTR domain;
81+
PWSTR username;
82+
PWSTR password;
83+
EVT_RPC_LOGIN_FLAGS flags;
84+
};
85+
6486
struct winevtlog_sqlite_record {
6587
char *name;
6688
char *bookmark_xml;

0 commit comments

Comments
 (0)