diff --git a/lib/scanner/csv-scanner/csv-scanner.c b/lib/scanner/csv-scanner/csv-scanner.c index 402fc52b5..53e53171d 100644 --- a/lib/scanner/csv-scanner/csv-scanner.c +++ b/lib/scanner/csv-scanner/csv-scanner.c @@ -485,6 +485,17 @@ _switch_to_next_column(CSVScanner *self) g_assert_not_reached(); } +gboolean +csv_scanner_take_rest(CSVScanner *self) +{ + _parse_left_whitespace(self); + g_string_assign(self->current_value, self->src); + self->src += self->current_value->len; + self->state = CSV_STATE_GREEDY_COLUMN; + _translate_value(self); + return TRUE; +} + gboolean csv_scanner_scan_next(CSVScanner *self) { @@ -493,12 +504,7 @@ csv_scanner_scan_next(CSVScanner *self) if (_is_last_column(self) && (self->options->flags & CSV_SCANNER_GREEDY)) { - _parse_left_whitespace(self); - g_string_assign(self->current_value, self->src); - self->src += self->current_value->len; - self->state = CSV_STATE_GREEDY_COLUMN; - _translate_value(self); - return TRUE; + return csv_scanner_take_rest(self); } else if (self->src[0] == 0) { diff --git a/lib/scanner/csv-scanner/csv-scanner.h b/lib/scanner/csv-scanner/csv-scanner.h index 649e8610e..edc48dc6c 100644 --- a/lib/scanner/csv-scanner/csv-scanner.h +++ b/lib/scanner/csv-scanner/csv-scanner.h @@ -94,4 +94,6 @@ gchar *csv_scanner_dup_current_value(CSVScanner *self); void csv_scanner_init(CSVScanner *pstate, CSVScannerOptions *options, const gchar *input); void csv_scanner_deinit(CSVScanner *pstate); +gboolean csv_scanner_take_rest(CSVScanner *self); + #endif diff --git a/modules/cef/event-format-parser-cfg.h b/modules/cef/event-format-parser-cfg.h index fb9f57736..eaa2c6009 100644 --- a/modules/cef/event-format-parser-cfg.h +++ b/modules/cef/event-format-parser-cfg.h @@ -27,8 +27,9 @@ #include "filterx/filterx-object.h" typedef struct _FilterXFunctionEventFormatParser FilterXFunctionEventFormatParser; +typedef struct _EventParserContext EventParserContext; -typedef FilterXObject *(*FieldParser)(FilterXFunctionEventFormatParser *parser, const gchar *value, gint value_len, +typedef FilterXObject *(*FieldParser)(EventParserContext *ctx, const gchar *value, gint value_len, GError **error, gpointer user_data); @@ -36,6 +37,7 @@ typedef struct _Field { const gchar *name; FieldParser field_parser; + gboolean optional; } Field; typedef struct _Header diff --git a/modules/cef/event-format-parser.c b/modules/cef/event-format-parser.c index 507bab6e1..3d19c5900 100644 --- a/modules/cef/event-format-parser.c +++ b/modules/cef/event-format-parser.c @@ -46,24 +46,24 @@ event_format_parser_error_quark(void) } Field -field(FilterXFunctionEventFormatParser *self, int index) +field_by_index(FilterXFunctionEventFormatParser *self, int index) { g_assert(index >= 0 && index < self->config.header.num_fields); return self->config.header.fields[index]; } static FilterXObject * -parse_default(FilterXFunctionEventFormatParser *self, const gchar *value, gint value_len, GError **error, +parse_default(EventParserContext *ctx, const gchar *value, gint value_len, GError **error, gpointer user_data) { return filterx_string_new(value, value_len); } FilterXObject * -parse_version(FilterXFunctionEventFormatParser *self, const gchar *value, gint value_len, GError **error, +parse_version(EventParserContext *ctx, const gchar *value, gint value_len, GError **error, gpointer user_data) { - const gchar *log_signature = self->config.signature; + const gchar *log_signature = ctx->parser->config.signature; gchar *colon_pos = memchr(value, ':', value_len); if (!colon_pos || colon_pos == value) { @@ -114,16 +114,15 @@ _unescape_value_separators(KVScanner *self) return TRUE; } - FilterXObject * -parse_extensions(FilterXFunctionEventFormatParser *self, const gchar *input, gint input_len, GError **error, +parse_extensions(EventParserContext *ctx, const gchar *input, gint input_len, GError **error, gpointer user_data) { FilterXObject *fillable = (FilterXObject *)user_data; FilterXObject *output = filterx_object_create_dict(fillable); KVScanner kv_scanner; - kv_scanner_init(&kv_scanner, self->config.extensions.value_separator, self->config.extensions.pair_separator, FALSE); + kv_scanner_init(&kv_scanner, ctx->kv_parser_value_separator, ctx->kv_parser_pair_separator, FALSE); kv_scanner_set_transform_value(&kv_scanner, _unescape_value_separators); kv_scanner_input(&kv_scanner, input); while (kv_scanner_scan_next(&kv_scanner)) @@ -143,60 +142,100 @@ parse_extensions(FilterXFunctionEventFormatParser *self, const gchar *input, gin } static inline gboolean -_fill_object_col(FilterXFunctionEventFormatParser *self, gint64 index, const gchar *input, gint input_len, - FilterXObject *fillable, - GError **error) +_match_field_to_column(EventParserContext *ctx, Field *field, const gchar *input, gint input_len, + FilterXObject *fillable, + GError **error) { - Field f = field(self, index); - FilterXObject *key = filterx_string_new(f.name, -1); FilterXObject *val = NULL; - if (!f.field_parser) - val = parse_default(self, input, input_len, error, fillable); + if (!field->field_parser) + val = parse_default(ctx, input, input_len, error, fillable); else - val = f.field_parser(self, input, input_len, error, fillable); + val = field->field_parser(ctx, input, input_len, error, fillable); gboolean ok = FALSE; - if (!*error) - ok = filterx_object_set_subscript(fillable, key, &val); + if (!*error && val) + { + FilterXObject *key = filterx_string_new(field->name, -1); + ok = filterx_object_set_subscript(fillable, key, &val); + filterx_object_unref(key); + } filterx_object_unref(val); - filterx_object_unref(key); return ok; } +static gboolean +_parse_column(EventParserContext *ctx, FilterXObject *fillable, GError **error) +{ + CSVScanner *csv_scanner = ctx->csv_scanner; + const gchar *input = csv_scanner_get_current_value(csv_scanner); + gint input_len = csv_scanner_get_current_value_len(csv_scanner); + + Field field = field_by_index(ctx->parser, ctx->field_index); + + while (!_match_field_to_column(ctx, &field, input, input_len, fillable, error) && !*error && field.optional) + { + ctx->field_index++; + if (ctx->field_index >= ctx->num_fields) + return FALSE; + field = field_by_index(ctx->parser, ctx->field_index); + } + ctx->column_index++; + return TRUE; +} + +static EventParserContext +_new_context(FilterXFunctionEventFormatParser *self, CSVScanner *csv_scanner) +{ + EventParserContext ctx = + { + .parser = self, + .num_fields = self->config.header.num_fields, + .field_index = 0, + .csv_scanner = csv_scanner, + .flags = 0, + .kv_parser_value_separator = self->kv_value_separator != 0 ? self->kv_value_separator : self->config.extensions.value_separator, + }; + g_strlcpy(ctx.kv_parser_pair_separator, self->kv_pair_separator ? : self->config.extensions.pair_separator, + EVENT_FORMAT_PARSER_PAIR_SEPARATOR_MAX_LEN); + return ctx; +} + static gboolean parse(FilterXFunctionEventFormatParser *self, const gchar *log, gsize len, FilterXObject *fillable, GError **error) { gboolean ok = FALSE; - gsize num_fields = self->config.header.num_fields; CSVScanner csv_scanner; csv_scanner_init(&csv_scanner, &self->csv_opts, log); - guint64 i = 0; + EventParserContext ctx = _new_context(self, &csv_scanner); + while (csv_scanner_scan_next(&csv_scanner)) { - if (i >= num_fields) + if (ctx.field_index >= ctx.num_fields) break; + ok = _parse_column(&ctx, fillable, error); + if(!ok || *error) + goto exit; + ctx.field_index++; + } - const gchar *input = csv_scanner_get_current_value(&csv_scanner); - gint input_len = csv_scanner_get_current_value_len(&csv_scanner); - ok = _fill_object_col(self, i, input, input_len, fillable, error); + if (ctx.field_index <= ctx.num_fields - 1) + { + csv_scanner_take_rest(&csv_scanner); + ok = _parse_column(&ctx, fillable, error); if(!ok || *error) goto exit; - - i++; } - if (i < self->csv_opts.expected_columns) + if (ctx.column_index < ctx.num_fields-1) { g_set_error(error, EVENT_FORMAT_PARSER_ERROR, EVENT_FORMAT_PARSER_ERR_MISSING_COLUMNS, - EVENT_FORMAT_PARSER_ERR_MISSING_COLUMNS_MSG, i, self->config.header.num_fields); + EVENT_FORMAT_PARSER_ERR_MISSING_COLUMNS_MSG, ctx.field_index, ctx.num_fields); } - - exit: csv_scanner_deinit(&csv_scanner); @@ -245,9 +284,9 @@ _free(FilterXExpr *s) { FilterXFunctionEventFormatParser *self = (FilterXFunctionEventFormatParser *) s; filterx_expr_unref(self->msg); + g_free(self->kv_pair_separator); csv_scanner_options_clean(&self->csv_opts); filterx_generator_function_free_method(&self->super); - } static FilterXExpr * @@ -264,6 +303,48 @@ _extract_msg_expr(FilterXFunctionArgs *args, GError **error) return msg_expr; } +static gboolean +_extract_optional_args(FilterXFunctionEventFormatParser *self, FilterXFunctionArgs *args, GError **error) +{ + gboolean exists; + gsize len; + const gchar *value; + + value = filterx_function_args_get_named_literal_string(args, EVENT_FORMAT_PARSER_ARG_NAME_PAIR_SEPARATOR, &len, + &exists); + if (exists) + { + if (len < 1 || !value) + { + g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL, + EVENT_FORMAT_PARSER_ERR_EMPTY_STRING, EVENT_FORMAT_PARSER_ARG_NAME_PAIR_SEPARATOR); + goto error; + } + if (len > EVENT_FORMAT_PARSER_PAIR_SEPARATOR_MAX_LEN - 1) + { + g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL, + EVENT_FORMAT_PARSER_ERR_SEPARATOR_MAX_LENGTH_EXCEEDED, EVENT_FORMAT_PARSER_ARG_NAME_PAIR_SEPARATOR); + goto error; + } + self->kv_pair_separator = g_strdup(value); + } + value = filterx_function_args_get_named_literal_string(args, EVENT_FORMAT_PARSER_ARG_NAME_VALUE_SEPARATOR, &len, + &exists); + if (exists) + { + if (len < 1 || !value) + { + g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL, + EVENT_FORMAT_PARSER_ERR_EMPTY_STRING, EVENT_FORMAT_PARSER_ARG_NAME_VALUE_SEPARATOR); + goto error; + } + self->kv_value_separator = value[0]; + } + return TRUE; +error: + return FALSE; +} + static gboolean _extract_args(FilterXFunctionEventFormatParser *self, FilterXFunctionArgs *args, GError **error) { @@ -279,6 +360,9 @@ _extract_args(FilterXFunctionEventFormatParser *self, FilterXFunctionArgs *args, if (!self->msg) return FALSE; + if (!_extract_optional_args(self, args, error)) + return FALSE; + return TRUE; } @@ -290,8 +374,6 @@ _set_config(FilterXFunctionEventFormatParser *self, Config *cfg) csv_scanner_options_set_delimiters(&self->csv_opts, cfg->header.delimiters); csv_scanner_options_set_quote_pairs(&self->csv_opts, ""); csv_scanner_options_set_dialect(&self->csv_opts, CSV_SCANNER_ESCAPE_UNQUOTED_DELIMITER); - csv_scanner_options_set_expected_columns(&self->csv_opts, cfg->header.num_fields); - self->csv_opts.flags |= CSV_SCANNER_GREEDY; } gboolean diff --git a/modules/cef/event-format-parser.h b/modules/cef/event-format-parser.h index b833e9f36..f08604fe9 100644 --- a/modules/cef/event-format-parser.h +++ b/modules/cef/event-format-parser.h @@ -39,10 +39,17 @@ #define EVENT_FORMAT_PARSER_ERR_LOG_SIGN_DIFFERS_MSG "the log signature differs. actual:%s expected:%s" #define EVENT_FORMAT_PARSER_ERR_MISSING_COLUMNS_MSG "not enough header columns provided. actual:%ld expected:%ld" #define EVENT_FORMAT_PARSER_ERR_NOT_STRING_INPUT_MSG "input argument must be string" +#define EVENT_FORMAT_PARSER_ERR_EMPTY_STRING "%s must be a non-empty string literal" +#define EVENT_FORMAT_PARSER_ERR_SEPARATOR_MAX_LENGTH_EXCEEDED "%s max length exceeded" #define EVENT_FORMAT_PARSER_ERROR event_format_parser_error_quark() GQuark event_format_parser_error_quark(void); +#define EVENT_FORMAT_PARSER_PAIR_SEPARATOR_MAX_LEN 0x05 + +#define EVENT_FORMAT_PARSER_ARG_NAME_PAIR_SEPARATOR "pair_separator" +#define EVENT_FORMAT_PARSER_ARG_NAME_VALUE_SEPARATOR "value_separator" + enum EventFormatParserError { EVENT_FORMAT_PARSER_ERR_NO_LOG_SIGN, @@ -57,15 +64,29 @@ struct _FilterXFunctionEventFormatParser FilterXExpr *msg; CSVScannerOptions csv_opts; Config config; + gchar *kv_pair_separator; + gchar kv_value_separator; +}; + +struct _EventParserContext +{ + FilterXFunctionEventFormatParser *parser; + guint64 num_fields; + guint64 field_index; + guint64 column_index; + CSVScanner *csv_scanner; + guint64 flags; + gchar kv_parser_pair_separator[EVENT_FORMAT_PARSER_PAIR_SEPARATOR_MAX_LEN]; + gchar kv_parser_value_separator; }; gboolean filterx_function_parser_init_instance(FilterXFunctionEventFormatParser *s, const gchar *fn_name, FilterXFunctionArgs *args, Config *cfg, GError **error); -FilterXObject *parse_version(FilterXFunctionEventFormatParser *parser, const gchar *value, gint value_len, +FilterXObject *parse_version(EventParserContext *ctx, const gchar *value, gint value_len, GError **error, gpointer user_data); -FilterXObject *parse_extensions(FilterXFunctionEventFormatParser *parser, const gchar *value, gint value_len, +FilterXObject *parse_extensions(EventParserContext *ctx, const gchar *value, gint value_len, GError **error, gpointer user_data); @@ -74,7 +95,7 @@ static inline void append_error_message(GError **error, const char *extra_info) if (error == NULL || *error == NULL) return; - gchar *new_message = g_strdup_printf("%s: %s", (*error)->message, extra_info); + gchar *new_message = g_strdup_printf("%s %s", (*error)->message, extra_info); GError *new_error = g_error_new((*error)->domain, (*error)->code, "%s", new_message); g_error_free(*error); diff --git a/modules/cef/filterx-func-parse-cef.h b/modules/cef/filterx-func-parse-cef.h index 42e98e591..84c229237 100644 --- a/modules/cef/filterx-func-parse-cef.h +++ b/modules/cef/filterx-func-parse-cef.h @@ -27,7 +27,9 @@ #include "plugin.h" #include "filterx/expr-function.h" -#define FILTERX_FUNC_PARSE_CEF_USAGE "Usage: parse_cef(str)" +#define FILTERX_FUNC_PARSE_CEF_USAGE "Usage: parse_cef(str " \ + EVENT_FORMAT_PARSER_ARG_NAME_PAIR_SEPARATOR"=boolean, " \ + EVENT_FORMAT_PARSER_ARG_NAME_VALUE_SEPARATOR"=boolean)" FILTERX_GENERATOR_FUNCTION_DECLARE(parse_cef); diff --git a/modules/cef/filterx-func-parse-leef.c b/modules/cef/filterx-func-parse-leef.c index f7f56a065..386af91a3 100644 --- a/modules/cef/filterx-func-parse-leef.c +++ b/modules/cef/filterx-func-parse-leef.c @@ -22,19 +22,105 @@ * */ +#include +#include + #include "filterx-func-parse-leef.h" #include "event-format-parser.h" +#include "filterx/object-string.h" + #include "scanner/csv-scanner/csv-scanner.h" #include "scanner/kv-scanner/kv-scanner.h" +#include "filterx/func-flags.h" + +DEFINE_FUNC_FLAGS(FilterXFunctionParseLeefFlags, + FILTERX_FUNC_PARSE_LEEF_FLAG_20 + ); + +static gboolean +_parse_hex_delimiter(const gchar *hexStr, gchar *delimiter) +{ + errno = 0; + *delimiter = (gchar)strtol(hexStr, NULL, 16); + return (errno == 0); +} + +static gboolean +_delimiter_multi_parser(const gchar *input, gint input_len, gchar *delimiter, GError **error) +{ + const gchar *hexStr = NULL; + switch (input_len) + { + case 0: + return TRUE; // do not change + case 1: + *delimiter = input[0]; + return TRUE; + case 3: + if (input[0] == 'x' || input[0] == 'X') + hexStr = &input[1]; + break; + case 4: + if (input[0] == '0' && (input[1] == 'x' || input[1] == 'X')) + hexStr = &input[2]; + break; + default: + return FALSE; // no match + } + if (!hexStr) + return FALSE; + return _parse_hex_delimiter(hexStr, delimiter); +} + +static gboolean +_is_pair_separator_forced(EventParserContext *ctx) +{ + return ctx->parser->kv_pair_separator != NULL; +} + +static gboolean +_is_delmiter_empty(gchar delimiter) +{ + return delimiter == 0; +} + +FilterXObject * +parse_delimiter(EventParserContext *ctx, const gchar *input, gint input_len, GError **error, gpointer user_data) +{ + if (!check_flag(ctx->flags, FILTERX_FUNC_PARSE_LEEF_FLAG_20)) + return NULL; + gchar delimiter = 0; + if (_delimiter_multi_parser(input, input_len, &delimiter, error)) + { + if (_is_delmiter_empty(delimiter)) + return filterx_string_new("", 0); + if (!_is_pair_separator_forced(ctx)) + { + ctx->kv_parser_pair_separator[0] = delimiter; + ctx->kv_parser_pair_separator[1] = 0; + } + return filterx_string_new(&delimiter, 1); + } + return NULL; +} + +FilterXObject * +parse_leef_version(EventParserContext *ctx, const gchar *value, gint value_len, GError **error, gpointer user_data) +{ + if (g_strstr_len(value, value_len, "2.0")) + set_flag(&ctx->flags, FILTERX_FUNC_PARSE_LEEF_FLAG_20, TRUE); + return parse_version(ctx, value, value_len, error, user_data); // call base class parser +} static Field leef_fields[] = { - { .name = "version", .field_parser = parse_version}, + { .name = "version", .field_parser = parse_leef_version}, { .name = "vendor"}, { .name = "product_name"}, { .name = "product_version"}, { .name = "event_id"}, + { .name = "delimiter", .optional=TRUE, .field_parser = parse_delimiter}, { .name = "extensions", .field_parser = parse_extensions}, }; @@ -53,7 +139,7 @@ filterx_function_parse_leef_new(FilterXFunctionArgs *args, GError **err) { .signature = "LEEF", .header = { - .num_fields = 6, + .num_fields = 7, .delimiters = "|", .fields = leef_fields, }, diff --git a/modules/cef/filterx-func-parse-leef.h b/modules/cef/filterx-func-parse-leef.h index c5017ce05..c7c43fbc4 100644 --- a/modules/cef/filterx-func-parse-leef.h +++ b/modules/cef/filterx-func-parse-leef.h @@ -27,7 +27,9 @@ #include "plugin.h" #include "filterx/expr-function.h" -#define FILTERX_FUNC_PARSE_LEEF_USAGE "Usage: parse_leef(str)" +#define FILTERX_FUNC_PARSE_LEEF_USAGE "Usage: parse_leef(str " \ + EVENT_FORMAT_PARSER_ARG_NAME_PAIR_SEPARATOR"=boolean, " \ + EVENT_FORMAT_PARSER_ARG_NAME_VALUE_SEPARATOR"=boolean)" FILTERX_GENERATOR_FUNCTION_DECLARE(parse_leef); diff --git a/modules/cef/tests/CMakeLists.txt b/modules/cef/tests/CMakeLists.txt index 8032140a4..60aa1a6dd 100644 --- a/modules/cef/tests/CMakeLists.txt +++ b/modules/cef/tests/CMakeLists.txt @@ -1,3 +1,8 @@ +set(TEST_HELPER_SOURCES + test_helpers.c + test_helpers.h + ) + add_unit_test(LIBTEST CRITERION TARGET test-format-cef-extension DEPENDS cef) -add_unit_test(LIBTEST CRITERION TARGET test-filterx-function-parse-cef DEPENDS cef) -add_unit_test(LIBTEST CRITERION TARGET test-filterx-function-parse-leef DEPENDS cef) +add_unit_test(LIBTEST CRITERION TARGET test-filterx-function-parse-cef DEPENDS cef SOURCES test-filterx-function-parse-cef.c ${TEST_HELPER_SOURCES}) +add_unit_test(LIBTEST CRITERION TARGET test-filterx-function-parse-leef DEPENDS cef SOURCES test-filterx-function-parse-leef.c ${TEST_HELPER_SOURCES}) diff --git a/modules/cef/tests/Makefile.am b/modules/cef/tests/Makefile.am index 648318f75..62e21e0ad 100644 --- a/modules/cef/tests/Makefile.am +++ b/modules/cef/tests/Makefile.am @@ -16,8 +16,13 @@ modules_cef_tests_test_format_cef_extension_LDFLAGS = \ EXTRA_modules_cef_tests_test_format_cef_extension_DEPENDENCIES = \ $(top_builddir)/modules/cef/libcef.la +modules_cef_tests_test_filterx_function_parse_cef_SOURCES = \ + modules/cef/tests/test-filterx-function-parse-cef.c \ + modules/cef/tests/test_helpers.c \ + modules/cef/tests/test_helpers.h + modules_cef_tests_test_filterx_function_parse_cef_CFLAGS = $(TEST_CFLAGS) -I$(top_srcdir)/modules/cef -modules_cef_tests_test_filterx_function_parse_cef_LDADD = $(TEST_LDADD) +modules_cef_tests_test_filterx_function_parse_cef_LDADD = $(TEST_LDADD) modules_cef_tests_test_filterx_function_parse_cef_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/cef/libcef.la @@ -25,6 +30,11 @@ modules_cef_tests_test_filterx_function_parse_cef_LDFLAGS = \ EXTRA_modules_cef_tests_test_filterx_function_parse_cef_DEPENDENCIES = \ $(top_builddir)/modules/cef/libcef.la +modules_cef_tests_test_filterx_function_parse_leef_SOURCES = \ + modules/cef/tests/test-filterx-function-parse-leef.c \ + modules/cef/tests/test_helpers.c \ + modules/cef/tests/test_helpers.h + modules_cef_tests_test_filterx_function_parse_leef_CFLAGS = $(TEST_CFLAGS) -I$(top_srcdir)/modules/cef modules_cef_tests_test_filterx_function_parse_leef_LDADD = $(TEST_LDADD) modules_cef_tests_test_filterx_function_parse_leef_LDFLAGS = \ diff --git a/modules/cef/tests/test-filterx-function-parse-cef.c b/modules/cef/tests/test-filterx-function-parse-cef.c index 5b3d2a6a2..5f0d939ff 100644 --- a/modules/cef/tests/test-filterx-function-parse-cef.c +++ b/modules/cef/tests/test-filterx-function-parse-cef.c @@ -39,63 +39,7 @@ #include "filterx/filterx-eval.h" #include "filterx/filterx-object-istype.h" - -FilterXExpr * -_new_cef_parser(FilterXFunctionArgs *args, GError **error, FilterXObject *fillable) -{ - FilterXExpr *func = filterx_function_parse_cef_new(args, error); - - if (!func) - return NULL; - - FilterXExpr *fillable_expr = filterx_non_literal_new(fillable); - filterx_generator_set_fillable(func, fillable_expr); - - return func; -} - -FilterXFunctionArgs * -_assert_create_args(const gchar *input) -{ - GList *args = NULL; - args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new(input, -1)))); - GError *args_err = NULL; - FilterXFunctionArgs *result = filterx_function_args_new(args, &args_err); - cr_assert_null(args_err); - g_error_free(args_err); - return result; -} - -FilterXObject * -_eval_cef_input(const gchar *input, GError **error) -{ - FilterXExpr *func = _new_cef_parser(_assert_create_args(input), error, filterx_json_object_new_empty()); - FilterXObject *obj = filterx_expr_eval(func); - filterx_expr_unref(func); - return obj; -} - -void -_assert_cef_parser_result(const gchar *input, const gchar *expected_result) -{ - - GError *err = NULL; - FilterXObject *obj = _eval_cef_input(input, &err); - cr_assert_null(err); - cr_assert_not_null(obj); - - cr_assert(filterx_object_is_type(obj, &FILTERX_TYPE_NAME(dict))); - - GString *repr = scratch_buffers_alloc(); - - LogMessageValueType lmvt; - cr_assert(filterx_object_marshal(obj, repr, &lmvt)); - - cr_assert_str_eq(repr->str, expected_result); - - filterx_object_unref(obj); - g_error_free(err); -} +#include "test_helpers.h" Test(filterx_func_parse_cef, test_invalid_input) { @@ -107,7 +51,7 @@ Test(filterx_func_parse_cef, test_invalid_input) cr_assert_null(args_err); g_error_free(args_err); - FilterXExpr *func = _new_cef_parser(fx_args, &error, filterx_json_object_new_empty()); + FilterXExpr *func = _new_parser(fx_args, &error, filterx_json_object_new_empty()); cr_assert_null(error); FilterXObject *obj = filterx_expr_eval(func); cr_assert_null(obj); @@ -120,10 +64,10 @@ Test(filterx_func_parse_cef, test_invalid_input) Test(filterx_func_parse_cef, test_invalid_version) { + const gchar *input = + "INVALID|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|rt=1647626887000 cs9=site location Bldg cs9Label=GroupName dhost=WS6465 dst=10.55.203.12 cs2=KES cs2Label=ProductName cs3=11.0.0.0 cs3Label=ProductVersion cs10=Uninstall EDR cs10Label=TaskName cs4=885 cs4Label=TaskId cn2=4 cn2Label=TaskNewState cn1=0 cn1Label=TaskOldState"; GError *init_err = NULL; - cr_assert_null( - _eval_cef_input("INVALID|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|rt=1647626887000 cs9=site location Bldg cs9Label=GroupName dhost=WS6465 dst=10.55.203.12 cs2=KES cs2Label=ProductName cs3=11.0.0.0 cs3Label=ProductVersion cs10=Uninstall EDR cs10Label=TaskName cs4=885 cs4Label=TaskId cn2=4 cn2Label=TaskNewState cn1=0 cn1Label=TaskOldState", - &init_err)); + cr_assert_null(_eval_input(&init_err, _create_msg_arg(input), NULL)); cr_assert_null(init_err); const gchar *last_error = filterx_eval_get_last_error(); cr_assert_not_null(last_error); @@ -134,10 +78,10 @@ Test(filterx_func_parse_cef, test_invalid_version) Test(filterx_func_parse_cef, test_invalid_log_signature) { + const gchar *input = + "BAD_SIGN:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|rt=1647626887000 cs9=site location Bldg cs9Label=GroupName dhost=WS6465 dst=10.55.203.12 cs2=KES cs2Label=ProductName cs3=11.0.0.0 cs3Label=ProductVersion cs10=Uninstall EDR cs10Label=TaskName cs4=885 cs4Label=TaskId cn2=4 cn2Label=TaskNewState cn1=0 cn1Label=TaskOldState"; GError *init_err = NULL; - cr_assert_null( - _eval_cef_input("BAD_SIGN:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|rt=1647626887000 cs9=site location Bldg cs9Label=GroupName dhost=WS6465 dst=10.55.203.12 cs2=KES cs2Label=ProductName cs3=11.0.0.0 cs3Label=ProductVersion cs10=Uninstall EDR cs10Label=TaskName cs4=885 cs4Label=TaskId cn2=4 cn2Label=TaskNewState cn1=0 cn1Label=TaskOldState", - &init_err)); + cr_assert_null(_eval_input(&init_err, _create_msg_arg(input), NULL)); cr_assert_null(init_err); const gchar *last_error = filterx_eval_get_last_error(); cr_assert_not_null(last_error); @@ -148,8 +92,9 @@ Test(filterx_func_parse_cef, test_invalid_log_signature) Test(filterx_func_parse_cef, test_header_missing_field) { + const gchar *input = "CEF:0|KasperskyLab|SecurityCenter|"; GError *init_err = NULL; - cr_assert_null(_eval_cef_input("CEF:0|KasperskyLab|SecurityCenter|", &init_err)); + cr_assert_null(_eval_input(&init_err, _create_msg_arg(input), NULL)); cr_assert_null(init_err); const gchar *last_error = filterx_eval_get_last_error(); cr_assert_not_null(last_error); @@ -160,64 +105,86 @@ Test(filterx_func_parse_cef, test_header_missing_field) Test(filterx_func_parse_cef, test_basic_cef_message) { - _assert_cef_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|rt=1647626887000 cs9=site location Bldg cs9Label=GroupName dhost=WS6465 dst=10.55.203.12 cs2=KES cs2Label=ProductName cs3=11.0.0.0 cs3Label=ProductVersion cs10=Uninstall EDR cs10Label=TaskName cs4=885 cs4Label=TaskId cn2=4 cn2Label=TaskNewState cn1=0 cn1Label=TaskOldState", - "{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"rt\":\"1647626887000\",\"cs9\":\"site location Bldg\",\"cs9Label\":\"GroupName\",\"dhost\":\"WS6465\",\"dst\":\"10.55.203.12\",\"cs2\":\"KES\",\"cs2Label\":\"ProductName\",\"cs3\":\"11.0.0.0\",\"cs3Label\":\"ProductVersion\",\"cs10\":\"Uninstall EDR\",\"cs10Label\":\"TaskName\",\"cs4\":\"885\",\"cs4Label\":\"TaskId\",\"cn2\":\"4\",\"cn2Label\":\"TaskNewState\",\"cn1\":\"0\",\"cn1Label\":\"TaskOldState\"}}"); + _assert_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|rt=1647626887000 cs9=site location Bldg cs9Label=GroupName dhost=WS6465 dst=10.55.203.12 cs2=KES cs2Label=ProductName cs3=11.0.0.0 cs3Label=ProductVersion cs10=Uninstall EDR cs10Label=TaskName cs4=885 cs4Label=TaskId cn2=4 cn2Label=TaskNewState cn1=0 cn1Label=TaskOldState", + "{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"rt\":\"1647626887000\",\"cs9\":\"site location Bldg\",\"cs9Label\":\"GroupName\",\"dhost\":\"WS6465\",\"dst\":\"10.55.203.12\",\"cs2\":\"KES\",\"cs2Label\":\"ProductName\",\"cs3\":\"11.0.0.0\",\"cs3Label\":\"ProductVersion\",\"cs10\":\"Uninstall EDR\",\"cs10Label\":\"TaskName\",\"cs4\":\"885\",\"cs4Label\":\"TaskId\",\"cn2\":\"4\",\"cn2Label\":\"TaskNewState\",\"cn1\":\"0\",\"cn1Label\":\"TaskOldState\"}}"); } Test(filterx_func_parse_cef, test_extensions_empty) { - _assert_cef_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|", - "{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{}}"); + _assert_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|", + "{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{}}"); } Test(filterx_func_parse_cef, test_header_escaped_delimiter) { - _assert_cef_parser_result("CEF:0|Kaspers\\|kyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|rt=1647626887000", - "{\"version\":\"0\",\"device_vendor\":\"Kaspers|kyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"rt\":\"1647626887000\"}}"); + _assert_parser_result("CEF:0|Kaspers\\|kyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|rt=1647626887000", + "{\"version\":\"0\",\"device_vendor\":\"Kaspers|kyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"rt\":\"1647626887000\"}}"); } Test(filterx_func_parse_cef, test_exteansion_escaped_delimiter) { - _assert_cef_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|escaped=foo\\=bar\\=baz", - "{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"escaped\":\"foo=bar=baz\"}}"); + _assert_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|escaped=foo\\=bar\\=baz", + "{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"escaped\":\"foo=bar=baz\"}}"); } Test(filterx_func_parse_cef, test_header_do_not_strip_whitespaces) { - _assert_cef_parser_result("CEF:0| KasperskyLab | SecurityCenter | 13.2.0.1511 | KLPRCI_TaskState | Completed successfully | 1 |", - "{\"version\":\"0\",\"device_vendor\":\" KasperskyLab \",\"device_product\":\" SecurityCenter \",\"device_version\":\" 13.2.0.1511 \",\"device_event_class_id\":\" KLPRCI_TaskState \",\"name\":\" Completed successfully \",\"agent_severity\":\" 1 \",\"extensions\":{}}"); + _assert_parser_result("CEF:0| KasperskyLab | SecurityCenter | 13.2.0.1511 | KLPRCI_TaskState | Completed successfully | 1 |", + "{\"version\":\"0\",\"device_vendor\":\" KasperskyLab \",\"device_product\":\" SecurityCenter \",\"device_version\":\" 13.2.0.1511 \",\"device_event_class_id\":\" KLPRCI_TaskState \",\"name\":\" Completed successfully \",\"agent_severity\":\" 1 \",\"extensions\":{}}"); } Test(filterx_func_parse_cef, test_extensions_space_in_value) { - _assert_cef_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|foo=bar baz tik=tak toe", - "{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"foo\":\"bar baz\",\"tik\":\"tak toe\"}}"); + _assert_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|foo=bar baz tik=tak toe", + "{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"foo\":\"bar baz\",\"tik\":\"tak toe\"}}"); } -// TODO: fix spaces? -// Test(filterx_func_parse_cef, test_extensions_trailing_space_in_key) -// { -// _assert_cef_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|foo bar=bar baz", -// "{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"foo bar\":\"bar baz\"}}"); -// } - -// Test(filterx_func_parse_cef, test_extensions_trailing_space_in_value) -// { -// _assert_cef_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|foo= bar baz tik= tak toe ", -// "{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"foo\":\"bar baz\"}}"); -// } - Test(filterx_func_parse_cef, test_header_whitespaces) { - _assert_cef_parser_result("CEF:0|Kasper sky Lab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|", - "{\"version\":\"0\",\"device_vendor\":\"Kasper sky Lab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{}}"); + _assert_parser_result("CEF:0|Kasper sky Lab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|", + "{\"version\":\"0\",\"device_vendor\":\"Kasper sky Lab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{}}"); } Test(filterx_func_parse_cef, test_header_leading_trailing_whitespaces) { - _assert_cef_parser_result("CEF:0| KasperskyLab |SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|", - "{\"version\":\"0\",\"device_vendor\":\" KasperskyLab \",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{}}"); + _assert_parser_result("CEF:0| KasperskyLab |SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|", + "{\"version\":\"0\",\"device_vendor\":\" KasperskyLab \",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{}}"); +} + +Test(filterx_func_parse_cef, test_forced_pair_separator) +{ + const gchar *input = + "CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|foo=bar@bar=baz@baz=tik\\=tak"; + _assert_parser_result_inner("{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik=tak\"}}", + _create_msg_arg(input), _create_pair_separator_arg("@"), NULL); +} + +Test(filterx_func_parse_cef, test_forced_value_separator) +{ + const gchar *input = + "CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|foo#bar bar#baz baz#tik\\#tak"; + _assert_parser_result_inner("{\"version\":\"0\",\"device_vendor\":\"KasperskyLab\",\"device_product\":\"SecurityCenter\",\"device_version\":\"13.2.0.1511\",\"device_event_class_id\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agent_severity\":\"1\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik#tak\"}}", + _create_msg_arg(input), _create_value_separator_arg("#"), NULL); +} + +Test(filterx_func_parse_cef, test_forced_empty_value_separator) +{ + const gchar *input = "CEF:0|Microsoft|MSExchange|4.0 SP1|15345|foo#bar bar#baz baz#tik\\#tak"; + GError *error = NULL; + FilterXExpr *func = _new_parser(_assert_create_args(0, _create_msg_arg(input), _create_value_separator_arg(""), NULL), + &error, filterx_json_object_new_empty()); + cr_assert_not_null(error); + cr_assert_null(func); + + GString *expected_err_msg = scratch_buffers_alloc(); + g_string_append_printf(expected_err_msg, EVENT_FORMAT_PARSER_ERR_EMPTY_STRING" "FILTERX_FUNC_PARSE_CEF_USAGE, + EVENT_FORMAT_PARSER_ARG_NAME_VALUE_SEPARATOR); + + cr_assert_str_eq(error->message, expected_err_msg->str); + + filterx_expr_unref(func); + g_error_free(error); } static void @@ -225,6 +192,7 @@ setup(void) { app_startup(); init_libtest_filterx(); + set_constructor(filterx_function_parse_cef_new); } static void diff --git a/modules/cef/tests/test-filterx-function-parse-leef.c b/modules/cef/tests/test-filterx-function-parse-leef.c index 0bf3cf774..59301bd43 100644 --- a/modules/cef/tests/test-filterx-function-parse-leef.c +++ b/modules/cef/tests/test-filterx-function-parse-leef.c @@ -39,63 +39,7 @@ #include "filterx/filterx-eval.h" #include "filterx/filterx-object-istype.h" - -FilterXExpr * -_new_leef_parser(FilterXFunctionArgs *args, GError **error, FilterXObject *fillable) -{ - FilterXExpr *func = filterx_function_parse_leef_new(args, error); - - if (!func) - return NULL; - - FilterXExpr *fillable_expr = filterx_non_literal_new(fillable); - filterx_generator_set_fillable(func, fillable_expr); - - return func; -} - -FilterXFunctionArgs * -_assert_create_args(const gchar *input) -{ - GList *args = NULL; - args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new(input, -1)))); - GError *args_err = NULL; - FilterXFunctionArgs *result = filterx_function_args_new(args, &args_err); - cr_assert_null(args_err); - g_error_free(args_err); - return result; -} - -FilterXObject * -_eval_leef_input(const gchar *input, GError **error) -{ - FilterXExpr *func = _new_leef_parser(_assert_create_args(input), error, filterx_json_object_new_empty()); - FilterXObject *obj = filterx_expr_eval(func); - filterx_expr_unref(func); - return obj; -} - -void -_assert_leef_parser_result(const gchar *input, const gchar *expected_result) -{ - - GError *err = NULL; - FilterXObject *obj = _eval_leef_input(input, &err); - cr_assert_null(err); - cr_assert_not_null(obj); - - cr_assert(filterx_object_is_type(obj, &FILTERX_TYPE_NAME(dict))); - - GString *repr = scratch_buffers_alloc(); - - LogMessageValueType lmvt; - cr_assert(filterx_object_marshal(obj, repr, &lmvt)); - - cr_assert_str_eq(repr->str, expected_result); - - filterx_object_unref(obj); - g_error_free(err); -} +#include "test_helpers.h" Test(filterx_func_parse_leef, test_invalid_input) { @@ -107,7 +51,7 @@ Test(filterx_func_parse_leef, test_invalid_input) cr_assert_null(args_err); g_error_free(args_err); - FilterXExpr *func = _new_leef_parser(fx_args, &error, filterx_json_object_new_empty()); + FilterXExpr *func = _new_parser(fx_args, &error, filterx_json_object_new_empty()); cr_assert_null(error); FilterXObject *obj = filterx_expr_eval(func); cr_assert_null(obj); @@ -121,9 +65,9 @@ Test(filterx_func_parse_leef, test_invalid_input) Test(filterx_func_parse_leef, test_invalid_version) { GError *init_err = NULL; - cr_assert_null( - _eval_leef_input("INVALID|Microsoft|MSExchange|4.0 SP1|15345|src=192.0.2.0 dst=172.50.123.1 sev=5cat=anomaly srcPort=81 dstPort=21 usrName=joe.black", - &init_err)); + const gchar *input = + "INVALID|Microsoft|MSExchange|4.0 SP1|15345|src=192.0.2.0 dst=172.50.123.1 sev=5cat=anomaly srcPort=81 dstPort=21 usrName=joe.black"; + cr_assert_null(_eval_input(&init_err, _create_msg_arg(input), NULL)); cr_assert_null(init_err); const gchar *last_error = filterx_eval_get_last_error(); cr_assert_not_null(last_error); @@ -135,9 +79,9 @@ Test(filterx_func_parse_leef, test_invalid_version) Test(filterx_func_parse_leef, test_invalid_log_signature) { GError *init_err = NULL; - cr_assert_null( - _eval_leef_input("BAD_SIGN:1.0|Microsoft|MSExchange|4.0 SP1|15345|src=192.0.2.0 dst=172.50.123.1 sev=5cat=anomaly srcPort=81 dstPort=21 usrName=joe.black", - &init_err)); + const gchar *input = + "BAD_SIGN:1.0|Microsoft|MSExchange|4.0 SP1|15345|src=192.0.2.0 dst=172.50.123.1 sev=5cat=anomaly srcPort=81 dstPort=21 usrName=joe.black"; + cr_assert_null(_eval_input(&init_err, _create_msg_arg(input), NULL)); cr_assert_null(init_err); const gchar *last_error = filterx_eval_get_last_error(); cr_assert_not_null(last_error); @@ -149,75 +93,165 @@ Test(filterx_func_parse_leef, test_invalid_log_signature) Test(filterx_func_parse_leef, test_header_missing_field) { GError *init_err = NULL; - cr_assert_null(_eval_leef_input("LEEF:1.0|Microsoft|MSExchange", &init_err)); + const gchar *input = "LEEF:1.0|Microsoft|MSExchange"; + cr_assert_null(_eval_input(&init_err, _create_msg_arg(input), NULL)); cr_assert_null(init_err); const gchar *last_error = filterx_eval_get_last_error(); cr_assert_not_null(last_error); GString *expected_err_msg = scratch_buffers_alloc(); - g_string_append_printf(expected_err_msg, EVENT_FORMAT_PARSER_ERR_MISSING_COLUMNS_MSG, (guint64)3, (guint64)6); + g_string_append_printf(expected_err_msg, EVENT_FORMAT_PARSER_ERR_MISSING_COLUMNS_MSG, (guint64)3, (guint64)7); cr_assert_str_eq(expected_err_msg->str, last_error); } Test(filterx_func_parse_leef, test_basic_leef_message) { - _assert_leef_parser_result("LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|src=192.0.2.0 dst=172.50.123.1 sev=5cat=anomaly srcPort=81 dstPort=21 usrName=joe.black", - "{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"src\":\"192.0.2.0\",\"dst\":\"172.50.123.1\",\"sev\":\"5cat=anomaly\",\"srcPort\":\"81\",\"dstPort\":\"21\",\"usrName\":\"joe.black\"}}"); + _assert_parser_result("LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|src=192.0.2.0 dst=172.50.123.1 sev=5cat=anomaly srcPort=81 dstPort=21 usrName=joe.black", + "{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"src\":\"192.0.2.0\",\"dst\":\"172.50.123.1\",\"sev\":\"5cat=anomaly\",\"srcPort\":\"81\",\"dstPort\":\"21\",\"usrName\":\"joe.black\"}}"); } Test(filterx_func_parse_leef, test_extensions_empty) { - _assert_leef_parser_result("LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|", - "{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{}}"); + _assert_parser_result("LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|", + "{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{}}"); } Test(filterx_func_parse_leef, test_header_escaped_delimiter) { - _assert_leef_parser_result("LEEF:1.0|Micro\\|soft|MSExchange|4.0 SP1|15345|src=192.0.2.0 dst=172.50.123.1 sev=5cat=anomaly srcPort=81 dstPort=21 usrName=joe.black", - "{\"version\":\"1.0\",\"vendor\":\"Micro|soft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"src\":\"192.0.2.0\",\"dst\":\"172.50.123.1\",\"sev\":\"5cat=anomaly\",\"srcPort\":\"81\",\"dstPort\":\"21\",\"usrName\":\"joe.black\"}}"); + _assert_parser_result("LEEF:1.0|Micro\\|soft|MSExchange|4.0 SP1|15345|src=192.0.2.0 dst=172.50.123.1 sev=5cat=anomaly srcPort=81 dstPort=21 usrName=joe.black", + "{\"version\":\"1.0\",\"vendor\":\"Micro|soft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"src\":\"192.0.2.0\",\"dst\":\"172.50.123.1\",\"sev\":\"5cat=anomaly\",\"srcPort\":\"81\",\"dstPort\":\"21\",\"usrName\":\"joe.black\"}}"); } Test(filterx_func_parse_leef, test_extension_escaped_delimiter) { - _assert_leef_parser_result("LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|foo=foo\\=bar\\=baz tik=tik\\=tak\\=toe", - "{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"foo\":\"foo=bar=baz\",\"tik\":\"tik=tak=toe\"}}"); + _assert_parser_result("LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|foo=foo\\=bar\\=baz tik=tik\\=tak\\=toe", + "{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"foo\":\"foo=bar=baz\",\"tik\":\"tik=tak=toe\"}}"); } Test(filterx_func_parse_leef, test_header_do_not_strip_whitespaces) { - _assert_leef_parser_result("LEEF:1.0| Microsoft | MSExchange | 4.0 SP1 | 15345 |", - "{\"version\":\"1.0\",\"vendor\":\" Microsoft \",\"product_name\":\" MSExchange \",\"product_version\":\" 4.0 SP1 \",\"event_id\":\" 15345 \",\"extensions\":{}}"); + _assert_parser_result("LEEF:1.0| Microsoft | MSExchange | 4.0 SP1 | 15345 |", + "{\"version\":\"1.0\",\"vendor\":\" Microsoft \",\"product_name\":\" MSExchange \",\"product_version\":\" 4.0 SP1 \",\"event_id\":\" 15345 \",\"extensions\":{}}"); } Test(filterx_func_parse_leef, test_extensions_space_in_value) { - _assert_leef_parser_result("LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|foo=bar baz tik=tak toe", - "{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"foo\":\"bar baz\",\"tik\":\"tak toe\"}}"); + _assert_parser_result("LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|foo=bar baz tik=tak toe", + "{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"foo\":\"bar baz\",\"tik\":\"tak toe\"}}"); } -// TODO: fix spaces? -// Test(filterx_func_parse_cef, test_extensions_trailing_space_in_key) -// { -// _assert_cef_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|foo bar=bar baz", -// "{\"version\":\"0\",\"deviceVendor\":\"KasperskyLab\",\"deviceProduct\":\"SecurityCenter\",\"deviceVersion\":\"13.2.0.1511\",\"deviceEventClassId\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agentSeverity\":\"1\",\"extensions\":{\"foo bar\":\"bar baz\"}}"); -// } - -// Test(filterx_func_parse_cef, test_extensions_trailing_space_in_value) -// { -// _assert_cef_parser_result("CEF:0|KasperskyLab|SecurityCenter|13.2.0.1511|KLPRCI_TaskState|Completed successfully|1|foo= bar baz tik= tak toe ", -// "{\"version\":\"0\",\"deviceVendor\":\"KasperskyLab\",\"deviceProduct\":\"SecurityCenter\",\"deviceVersion\":\"13.2.0.1511\",\"deviceEventClassId\":\"KLPRCI_TaskState\",\"name\":\"Completed successfully\",\"agentSeverity\":\"1\",\"extensions\":{\"foo\":\"bar baz\"}}"); -// } - Test(filterx_func_parse_leef, test_header_whitespaces) { - _assert_leef_parser_result("LEEF:1.0|Mic roso ft|MSExchange|4.0 SP1|15345|", - "{\"version\":\"1.0\",\"vendor\":\"Mic roso ft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{}}"); + _assert_parser_result("LEEF:1.0|Mic roso ft|MSExchange|4.0 SP1|15345|", + "{\"version\":\"1.0\",\"vendor\":\"Mic roso ft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{}}"); } Test(filterx_func_parse_leef, test_header_leading_trailing_whitespaces) { - _assert_leef_parser_result("LEEF:1.0| Microsoft |MSExchange|4.0 SP1|15345|foo=foo\\=bar\\=baz tik=tik\\=tak\\=toe", - "{\"version\":\"1.0\",\"vendor\":\" Microsoft \",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"foo\":\"foo=bar=baz\",\"tik\":\"tik=tak=toe\"}}"); + _assert_parser_result("LEEF:1.0| Microsoft |MSExchange|4.0 SP1|15345|foo=foo\\=bar\\=baz tik=tik\\=tak\\=toe", + "{\"version\":\"1.0\",\"vendor\":\" Microsoft \",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"foo\":\"foo=bar=baz\",\"tik\":\"tik=tak=toe\"}}"); +} + +Test(filterx_func_parse_leef, test_header_optional_field_set) +{ + _assert_parser_result("LEEF:2.0|Microsoft|MSExchange|4.0 SP1|15345|^|foo=bar", + "{\"version\":\"2.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"delimiter\":\"^\",\"extensions\":{\"foo\":\"bar\"}}"); +} + +Test(filterx_func_parse_leef, test_header_optional_field_unset) +{ + _assert_parser_result("LEEF:2.0|Microsoft|MSExchange|4.0 SP1|15345|foo=bar", + "{\"version\":\"2.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"foo\":\"bar\"}}"); +} + +Test(filterx_func_parse_leef, test_header_custom_delimiter) +{ + _assert_parser_result("LEEF:2.0|Microsoft|MSExchange|4.0 SP1|15345|^|foo=bar^bar=baz^baz=tik\\=tak", + "{\"version\":\"2.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"delimiter\":\"^\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik=tak\"}}"); +} + +Test(filterx_func_parse_leef, test_header_custom_hex_delimiter) +{ + _assert_parser_result("LEEF:2.0|Microsoft|MSExchange|4.0 SP1|15345|0x40|foo=bar@bar=baz@baz=tik\\=tak", + "{\"version\":\"2.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"delimiter\":\"@\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik=tak\"}}"); +} + +Test(filterx_func_parse_leef, test_header_custom_nonstandard_hex_delimiter) +{ + _assert_parser_result("LEEF:2.0|Microsoft|MSExchange|4.0 SP1|15345|x40|foo=bar@bar=baz@baz=tik\\=tak", + "{\"version\":\"2.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"delimiter\":\"@\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik=tak\"}}"); +} + +Test(filterx_func_parse_leef, test_header_custom_invalid_delimiter) +{ + _assert_parser_result("LEEF:2.0|Microsoft|MSExchange|4.0 SP1|15345|INVALID|foo=bar^bar=baz^baz=tik\\=tak", + "{\"version\":\"2.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{}}"); +} + +Test(filterx_func_parse_leef, test_header_custom_delimiter_v1) +{ + _assert_parser_result("LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|^|foo=bar^bar=baz^baz=tik\\=tak", + "{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{}}"); +} + +Test(filterx_func_parse_leef, test_header_empty_delimiter) +{ + _assert_parser_result("LEEF:2.0|Microsoft|MSExchange|4.0 SP1|15345||foo=bar bar=baz baz=tik\\=tak", + "{\"version\":\"2.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"delimiter\":\"\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik=tak\"}}"); +} + +Test(filterx_func_parse_leef, test_forced_pair_separator_v1_no_delimiter_field) +{ + const gchar *input = "LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|foo=bar@bar=baz@baz=tik\\=tak"; + _assert_parser_result_inner("{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik=tak\"}}", + _create_msg_arg(input), _create_pair_separator_arg("@"), NULL); +} + +Test(filterx_func_parse_leef, test_forced_pair_separator_v2_no_delimiter_field) +{ + const gchar *input = "LEEF:2.0|Microsoft|MSExchange|4.0 SP1|15345|foo=bar@bar=baz@baz=tik\\=tak"; + _assert_parser_result_inner("{\"version\":\"2.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik=tak\"}}", + _create_msg_arg(input), _create_pair_separator_arg("@"), NULL); +} + +Test(filterx_func_parse_leef, test_forced_pair_separator_v2_with_delimiter_field) +{ + const gchar *input = "LEEF:2.0|Microsoft|MSExchange|4.0 SP1|15345|^|foo=bar@bar=baz@baz=tik\\=tak"; + _assert_parser_result_inner("{\"version\":\"2.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"delimiter\":\"^\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik=tak\"}}", + _create_msg_arg(input), _create_pair_separator_arg("@"), NULL); +} + +Test(filterx_func_parse_leef, test_forced_pair_separator_v2_with_empty_delimiter_field) +{ + const gchar *input = "LEEF:2.0|Microsoft|MSExchange|4.0 SP1|15345||foo=bar@bar=baz@baz=tik\\=tak"; + _assert_parser_result_inner("{\"version\":\"2.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"delimiter\":\"\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik=tak\"}}", + _create_msg_arg(input), _create_pair_separator_arg("@"), NULL); +} + +Test(filterx_func_parse_leef, test_forced_value_separator) +{ + const gchar *input = "LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|foo#bar\tbar#baz\tbaz#tik\\#tak"; + _assert_parser_result_inner("{\"version\":\"1.0\",\"vendor\":\"Microsoft\",\"product_name\":\"MSExchange\",\"product_version\":\"4.0 SP1\",\"event_id\":\"15345\",\"extensions\":{\"foo\":\"bar\",\"bar\":\"baz\",\"baz\":\"tik#tak\"}}", + _create_msg_arg(input), _create_value_separator_arg("#"), NULL); +} + +Test(filterx_func_parse_leef, test_forced_empty_value_separator) +{ + const gchar *input = "LEEF:1.0|Microsoft|MSExchange|4.0 SP1|15345|foo#bar\tbar#baz\tbaz#tik\\#tak"; + GError *error = NULL; + FilterXExpr *func = _new_parser(_assert_create_args(0, _create_msg_arg(input), _create_value_separator_arg(""), NULL), + &error, filterx_json_object_new_empty()); + cr_assert_not_null(error); + cr_assert_null(func); + + GString *expected_err_msg = scratch_buffers_alloc(); + g_string_append_printf(expected_err_msg, EVENT_FORMAT_PARSER_ERR_EMPTY_STRING" "FILTERX_FUNC_PARSE_LEEF_USAGE, + EVENT_FORMAT_PARSER_ARG_NAME_VALUE_SEPARATOR); + + cr_assert_str_eq(error->message, expected_err_msg->str); + + filterx_expr_unref(func); + g_error_free(error); } static void @@ -225,6 +259,7 @@ setup(void) { app_startup(); init_libtest_filterx(); + set_constructor(filterx_function_parse_leef_new); } static void diff --git a/modules/cef/tests/test_helpers.c b/modules/cef/tests/test_helpers.c new file mode 100644 index 000000000..4bc2b9bcd --- /dev/null +++ b/modules/cef/tests/test_helpers.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2023 Axoflow + * Copyright (c) 2024 shifter + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#include +#include "libtest/filterx-lib.h" + +#include "apphook.h" +#include "scratch-buffers.h" +#include "test_helpers.h" +#include "event-format-parser.h" + +#include "filterx/object-string.h" +#include "filterx/object-null.h" +#include "filterx/expr-literal.h" +#include "filterx/object-json.h" +#include "filterx/object-list-interface.h" +#include "filterx/object-dict-interface.h" +#include "filterx/object-primitive.h" + +static event_parser_constructor constructor = NULL; + +void +set_constructor(event_parser_constructor c) +{ + constructor = c; +} + +FilterXFunctionArg * +_create_arg(const gchar *key, FilterXExpr *val) +{ + return filterx_function_arg_new(key, val); +} + +FilterXFunctionArg * +_create_msg_arg(const gchar *input) +{ + return _create_arg(NULL, filterx_literal_new(filterx_string_new(input, -1))); +} + +FilterXFunctionArg * +_create_pair_separator_arg(const gchar *pair_separator) +{ + return _create_arg(EVENT_FORMAT_PARSER_ARG_NAME_PAIR_SEPARATOR, filterx_literal_new(filterx_string_new(pair_separator, + -1))); +} + +FilterXFunctionArg * +_create_value_separator_arg(const gchar *value_separator) +{ + return _create_arg(EVENT_FORMAT_PARSER_ARG_NAME_VALUE_SEPARATOR, filterx_literal_new(filterx_string_new(value_separator, + -1))); +} + +FilterXFunctionArgs * +_assert_create_args_inner(va_list vargs) +{ + GList *args = NULL; + + while (1) + { + FilterXFunctionArg *varg = va_arg(vargs, FilterXFunctionArg *); + if (varg == NULL) + break; + args = g_list_append(args, varg); + }; + + GError *args_err = NULL; + FilterXFunctionArgs *result = filterx_function_args_new(args, &args_err); + cr_assert_null(args_err); + g_error_free(args_err); + return result; +} + +FilterXFunctionArgs * +_assert_create_args(int count, ...) +{ + va_list vargs; + va_start(vargs, count); + FilterXFunctionArgs *result = _assert_create_args_inner(vargs); + va_end(vargs); + return result; +} + +FilterXExpr * +_new_parser(FilterXFunctionArgs *args, GError **error, FilterXObject *fillable) +{ + if (constructor == NULL) + goto error; + FilterXExpr *func = constructor(args, error); + + if (!func) + goto error; + + FilterXExpr *fillable_expr = filterx_non_literal_new(fillable); + filterx_generator_set_fillable(func, fillable_expr); + + return func; +error: + filterx_object_unref(fillable); + return NULL; +} + +FilterXObject * +_eval_input_inner(GError **error, va_list vargs) +{ + FilterXExpr *func = _new_parser(_assert_create_args_inner(vargs), error, filterx_json_object_new_empty()); + cr_assert_not_null(func); + FilterXObject *obj = filterx_expr_eval(func); + filterx_expr_unref(func); + return obj; +} + +FilterXObject * +_eval_input(GError **error, ...) +{ + va_list vargs; + va_start(vargs, error); + FilterXObject *obj = _eval_input_inner(error, vargs); + va_end(vargs); + return obj; +} + +void +_assert_parser_result_inner(const gchar *expected_result, ...) +{ + va_list vargs; + va_start(vargs, expected_result); + + GError *err = NULL; + FilterXObject *obj = _eval_input_inner(&err, vargs); + cr_assert_null(err); + cr_assert_not_null(obj); + + cr_assert(filterx_object_is_type(obj, &FILTERX_TYPE_NAME(dict))); + + GString *repr = scratch_buffers_alloc(); + + LogMessageValueType lmvt; + cr_assert(filterx_object_marshal(obj, repr, &lmvt)); + + cr_assert_str_eq(repr->str, expected_result); + + filterx_object_unref(obj); + g_error_free(err); + va_end(vargs); +} + +void +_assert_parser_result(const gchar *input, const gchar *expected_result) +{ + _assert_parser_result_inner(expected_result, _create_msg_arg(input), NULL); +} diff --git a/modules/cef/tests/test_helpers.h b/modules/cef/tests/test_helpers.h new file mode 100644 index 000000000..8946eac08 --- /dev/null +++ b/modules/cef/tests/test_helpers.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Axoflow + * Copyright (c) 2024 shifter + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#ifndef FILTERX_FUNC_EVENT_PARSER_TEST_HELPERS +#define FILTERX_FUNC_EVENT_PARSER_TEST_HELPERS + +#include "filterx/filterx-eval.h" +#include "filterx/expr-function.h" + +typedef FilterXExpr *(*event_parser_constructor)(FilterXFunctionArgs *args, GError **error); + +void set_constructor(event_parser_constructor c); + +FilterXFunctionArg *_create_arg(const gchar *key, FilterXExpr *val); +FilterXFunctionArg *_create_msg_arg(const gchar *input); +FilterXFunctionArg *_create_pair_separator_arg(const gchar *pair_separator); +FilterXFunctionArg *_create_value_separator_arg(const gchar *value_separator); + +FilterXFunctionArgs *_assert_create_args_inner(va_list vargs); +FilterXFunctionArgs *_assert_create_args(int count, ...); + +FilterXExpr *_new_parser(FilterXFunctionArgs *args, GError **error, FilterXObject *fillable); +FilterXObject *_eval_input_inner(GError **error, va_list vargs); +FilterXObject *_eval_input(GError **error, ...); +void _assert_parser_result_inner(const gchar *expected_result, ...); +void _assert_parser_result(const gchar *input, const gchar *expected_result); + +#endif diff --git a/tests/copyright/policy b/tests/copyright/policy index 1a810effb..b15229128 100644 --- a/tests/copyright/policy +++ b/tests/copyright/policy @@ -303,6 +303,7 @@ modules/cef/filterx-func-parse-cef.[ch] modules/cef/filterx-func-parse-leef.[ch] modules/cef/tests/test-filterx-function-parse-cef.c modules/cef/tests/test-filterx-function-parse-leef.c +modules/cef/tests/test_helpers.[ch] ########################################################################### # These files are GPLd with Balabit origin.