Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 152 additions & 1 deletion plugins/in_winevtlog/in_winevtlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,120 @@
static int in_winevtlog_collect(struct flb_input_instance *ins,
struct flb_config *config, void *in_context);

static wchar_t* convert_to_wide(char *str)
{
int size = 0;
wchar_t *buf = NULL;
DWORD err;

size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
if (size == 0) {
err = GetLastError();
flb_error("[in_winevtlog] Failed MultiByteToWideChar with error code (%d)", err);
return NULL;
}

buf = flb_calloc(1, sizeof(wchar_t) * size);
if (buf == NULL) {
flb_errno();
return NULL;
}
size = MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, size);
if (size == 0) {
err = GetLastError();
flb_error("[in_winevtlog] Failed MultiByteToWideChar with error code (%d)", err);
flb_free(buf);
return NULL;
}

return buf;
}

static void in_winevtlog_session_destroy(struct winevtlog_session *session);

static struct winevtlog_session *in_winevtlog_session_create(struct winevtlog_config *ctx,
struct flb_config *config,
int *status)
{
int len;
struct winevtlog_session *session;
PWSTR wtmp;

if (ctx->remote_server == NULL) {
*status = WINEVTLOG_SESSION_SERVER_EMPTY;
return NULL;
}

session = flb_calloc(1, sizeof(struct winevtlog_session));
if (session == NULL) {
flb_errno();
*status = WINEVTLOG_SESSION_ALLOC_FAILED;
return NULL;
}

if (ctx->remote_server != NULL) {
session->server = convert_to_wide(ctx->remote_server);
if (session->server == NULL) {
in_winevtlog_session_destroy(session);
*status = WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE;
return NULL;
}
}

if (ctx->remote_domain != NULL) {
session->domain = convert_to_wide(ctx->remote_domain);
if (session->domain == NULL) {
in_winevtlog_session_destroy(session);
*status = WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE;
return NULL;
}
}

if (ctx->remote_username != NULL) {
session->username = convert_to_wide(ctx->remote_username);
if (session->username == NULL) {
in_winevtlog_session_destroy(session);
*status = WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE;
return NULL;
}
}

if (ctx->remote_password != NULL) {
session->password = convert_to_wide(ctx->remote_password);
if (session->password == NULL) {
in_winevtlog_session_destroy(session);
*status = WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE;
return NULL;
}
}

session->flags = EvtRpcLoginAuthDefault;
*status = WINEVTLOG_SESSION_CREATE_OK;

return session;
}

static void in_winevtlog_session_destroy(struct winevtlog_session *session)
{
if (session->server != NULL) {
flb_free(session->server);
}

if (session->domain != NULL) {
flb_free(session->domain);
}

if (session->username != NULL) {
flb_free(session->username);
}

if (session->password != NULL) {
flb_free(session->password);
}

flb_free(session);
}

static int in_winevtlog_init(struct flb_input_instance *in,
struct flb_config *config, void *data)
{
Expand All @@ -46,6 +160,8 @@ static int in_winevtlog_init(struct flb_input_instance *in,
struct mk_list *head;
struct winevtlog_channel *ch;
struct winevtlog_config *ctx;
struct winevtlog_session *session;
int status = WINEVTLOG_SESSION_CREATE_OK;

/* Initialize context */
ctx = flb_calloc(1, sizeof(struct winevtlog_config));
Expand All @@ -61,7 +177,7 @@ static int in_winevtlog_init(struct flb_input_instance *in,
flb_plg_error(in, "could not initialize event encoder");
flb_free(ctx);

return NULL;
return -1;
}

/* Load the config map */
Expand All @@ -72,6 +188,18 @@ static int in_winevtlog_init(struct flb_input_instance *in,
return -1;
}

/* Initialize session context */
session = in_winevtlog_session_create(ctx, config, &status);
if (status == WINEVTLOG_SESSION_ALLOC_FAILED ||
status == WINEVTLOG_SESSION_FAILED_TO_CONVERT_WIDE) {
flb_plg_error(in, "session is not created and invalid with status %d", status);
return -1;
}
else if (session == NULL) {
flb_plg_debug(in, "connect to local machine");
}
ctx->session = session;

/* Set up total reading size threshold */
if (ctx->total_size_threshold >= MINIMUM_THRESHOLD_SIZE &&
ctx->total_size_threshold <= MAXIMUM_THRESHOLD_SIZE) {
Expand Down Expand Up @@ -235,6 +363,9 @@ static int in_winevtlog_exit(void *data, struct flb_config *config)
if (ctx->db) {
flb_sqldb_close(ctx->db);
}
if (ctx->session) {
in_winevtlog_session_destroy(ctx->session);
}
flb_free(ctx);

return 0;
Expand Down Expand Up @@ -296,6 +427,26 @@ static struct flb_config_map config_map[] = {
0, FLB_TRUE, offsetof(struct winevtlog_config, total_size_threshold),
"Specify reading limit for collecting Windows EventLog per a cycle"
},
{
FLB_CONFIG_MAP_STR, "remote.server", (char *)NULL,
0, FLB_TRUE, offsetof(struct winevtlog_config, remote_server),
"Specify server name of remote access for Windows EventLog"
},
{
FLB_CONFIG_MAP_STR, "remote.domain", (char *)NULL,
0, FLB_TRUE, offsetof(struct winevtlog_config, remote_domain),
"Specify domain name of remote access for Windows EventLog"
},
{
FLB_CONFIG_MAP_STR, "remote.username", (char *)NULL,
0, FLB_TRUE, offsetof(struct winevtlog_config, remote_username),
"Specify username of remote access for Windows EventLog"
},
{
FLB_CONFIG_MAP_STR, "remote.password", (char *)NULL,
0, FLB_TRUE, offsetof(struct winevtlog_config, remote_password),
"Specify password of remote access for Windows EventLog"
},
/* EOF */
{0}
};
Expand Down
4 changes: 3 additions & 1 deletion plugins/in_winevtlog/pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

static int pack_nullstr(struct winevtlog_config *ctx)
{
flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "");
return flb_log_event_encoder_append_body_cstring(ctx->log_encoder, "");
}

static int pack_wstr(struct winevtlog_config *ctx, const wchar_t *wstr)
Expand Down Expand Up @@ -314,6 +314,8 @@ static int pack_sid(struct winevtlog_config *ctx, PSID sid, int extract_sid)

_snprintf_s(formatted, result_len, _TRUNCATE, "%s\\%s", domain, account);

size = strlen(formatted);

if (size > 0) {
flb_log_event_encoder_append_body_cstring(ctx->log_encoder, formatted);

Expand Down
70 changes: 65 additions & 5 deletions plugins/in_winevtlog/winevtlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,34 @@
static char* convert_wstr(wchar_t *wstr, UINT codePage);
static wchar_t* convert_str(char *str);

static EVT_HANDLE
create_remote_handle(struct winevtlog_session *session, DWORD *error_code)
{
EVT_HANDLE remote = NULL;
EVT_RPC_LOGIN credentials;

RtlZeroMemory(&credentials, sizeof(EVT_RPC_LOGIN));

credentials.Server = session->server;
credentials.Domain = session->domain;
credentials.User = session->username;
credentials.Password = session->password;
credentials.Flags = session->flags;

remote = EvtOpenSession(EvtRpcLogin, &credentials, 0, 0);
if (!remote) {
*error_code = GetLastError();
return remote;
}

SecureZeroMemory(&credentials, sizeof(EVT_RPC_LOGIN));

return remote;
}

struct winevtlog_channel *winevtlog_subscribe(const char *channel, int read_existing_events,
EVT_HANDLE stored_bookmark, const char *query)
EVT_HANDLE stored_bookmark, const char *query,
struct winevtlog_session *session)
{
struct winevtlog_channel *ch;
EVT_HANDLE bookmark = NULL;
Expand All @@ -40,7 +66,9 @@ struct winevtlog_channel *winevtlog_subscribe(const char *channel, int read_exis
DWORD flags = 0L;
PWSTR wide_channel = NULL;
PWSTR wide_query = NULL;
EVT_HANDLE remote_handle = NULL;
void *buf;
DWORD err = ERROR_SUCCESS;

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

if (session != NULL) {
remote_handle = create_remote_handle(session, &err);
if (err != ERROR_SUCCESS) {
flb_error("[in_winevtlog] cannot create remote handle '%s' in %ls (%i)",
channel, session->server, err);
flb_free(ch->name);
if (ch->query != NULL) {
flb_free(ch->query);
}
flb_free(ch);
return NULL;
}

flb_debug("[in_winevtlog] created a remote handle for '%s' in %ls",
channel, session->server);
ch->session = session;
ch->remote = remote_handle;
}

/* The wide_query parameter can handle NULL as `*` for retrieving all events.
* ref. https://learn.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtsubscribe
*/
ch->subscription = EvtSubscribe(NULL, signal_event, wide_channel, wide_query,
ch->subscription = EvtSubscribe(remote_handle, signal_event, wide_channel, wide_query,
stored_bookmark, NULL, NULL, flags);
err = GetLastError();
if (!ch->subscription) {
flb_error("[in_winevtlog] cannot subscribe '%s' (%i)", channel, GetLastError());
flb_error("[in_winevtlog] cannot subscribe '%s' (%i)", channel, err);
flb_free(ch->name);
if (ch->query != NULL) {
flb_free(ch->query);
}
if (ch->remote) {
EvtClose(ch->remote);
}
flb_free(ch);
return NULL;
}
Expand All @@ -106,6 +157,9 @@ struct winevtlog_channel *winevtlog_subscribe(const char *channel, int read_exis
if (ch->subscription) {
EvtClose(ch->subscription);
}
if (ch->remote) {
EvtClose(ch->remote);
}
if (signal_event) {
CloseHandle(signal_event);
}
Expand Down Expand Up @@ -141,6 +195,10 @@ static void close_handles(struct winevtlog_channel *ch)
EvtClose(ch->subscription);
ch->subscription = NULL;
}
if (ch->remote) {
EvtClose(ch->remote);
ch->remote = NULL;
}
if (ch->signal_event) {
CloseHandle(ch->signal_event);
ch->signal_event = NULL;
Expand Down Expand Up @@ -674,7 +732,8 @@ struct mk_list *winevtlog_open_all(const char *channels, struct winevtlog_config

channel = strtok_s(tmp , ",", &state);
while (channel) {
ch = winevtlog_subscribe(channel, ctx->read_existing_events, NULL, ctx->event_query);
ch = winevtlog_subscribe(channel, ctx->read_existing_events, NULL, ctx->event_query,
ctx->session);
if (ch) {
mk_list_add(&ch->_head, list);
}
Expand Down Expand Up @@ -809,13 +868,14 @@ int winevtlog_sqlite_load(struct winevtlog_channel *ch, struct flb_sqldb *db)
bookmark = EvtCreateBookmark(bookmark_xml);
if (bookmark) {
/* re-create subscription handles */
re_ch = winevtlog_subscribe(ch->name, FLB_FALSE, bookmark, ch->query);
re_ch = winevtlog_subscribe(ch->name, FLB_FALSE, bookmark, ch->query, ch->session);
if (re_ch != NULL) {
close_handles(ch);

ch->bookmark = re_ch->bookmark;
ch->subscription = re_ch->subscription;
ch->signal_event = re_ch->signal_event;
ch->session = re_ch->session;
}
else {
flb_error("Failed to subscribe with bookmark XML: %s\n", record.bookmark_xml);
Expand Down
Loading
Loading