summaryrefslogtreecommitdiff
path: root/scanner/expr_matcher/expr_matcher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scanner/expr_matcher/expr_matcher.cpp')
-rw-r--r--scanner/expr_matcher/expr_matcher.cpp235
1 files changed, 235 insertions, 0 deletions
diff --git a/scanner/expr_matcher/expr_matcher.cpp b/scanner/expr_matcher/expr_matcher.cpp
new file mode 100644
index 0000000..3a37383
--- /dev/null
+++ b/scanner/expr_matcher/expr_matcher.cpp
@@ -0,0 +1,235 @@
+/*
+**********************************************************************************************
+* File: expr_matcher.cpp
+* Description:
+* Authors: Liu wentan <[email protected]>
+* Date: 2023-06-30
+* Copyright: (c) Since 2023 Geedge Networks, Ltd. All rights reserved.
+***********************************************************************************************
+*/
+
+#include <unistd.h>
+#include <assert.h>
+#include <sys/syscall.h>
+
+#include "log/log.h"
+#include "expr_matcher.h"
+#include "maat_utils.h"
+#include "adapter_hs/adapter_hs.h"
+#include "adapter_rs/adapter_rs.h"
+
+pid_t expr_matcher_gettid()
+{
+ return syscall(SYS_gettid);
+}
+
+static const char *expr_matcher_module_name_str(const char *name)
+{
+ static __thread char module[64];
+ snprintf(module, sizeof(module), "%s(%d)", name, expr_matcher_gettid());
+
+ return module;
+}
+
+#define MODULE_EXPR_MATCHER expr_matcher_module_name_str("maat.expr_matcher")
+
+struct expr_matcher {
+ enum expr_engine_type engine_type;
+ void *engine;
+ struct log_handle *logger;
+};
+
+struct expr_matcher_stream {
+ enum expr_engine_type engine_type;
+ void *handle;
+};
+
+struct expr_engine_operations {
+ enum expr_engine_type type;
+ void *(*engine_new)(struct expr_rule *rules, size_t n_rule,
+ size_t n_literal_pattern, size_t n_regex_pattern,
+ size_t n_worker_thread, struct log_handle *logger);
+ void (*engine_free)(void *engine);
+ int (*engine_scan)(void *engine, int thread_id, const char *scan_data,
+ size_t data_len, struct expr_scan_result *result_array,
+ size_t n_result_array, size_t *n_hit_result);
+ void *(*engine_stream_open)(void *engine, int thread_id);
+ void (*engine_stream_close)(void *stream);
+ int (*engine_scan_stream)(void *stream, const char *scan_data, size_t data_len,
+ struct expr_scan_result *result_array, size_t n_result_array,
+ size_t *n_hit_result);
+};
+
+struct expr_engine_operations expr_engine_ops[EXPR_ENGINE_TYPE_MAX] = {
+ {
+ .type = EXPR_ENGINE_TYPE_HS,
+ .engine_new = adapter_hs_new,
+ .engine_free = adapter_hs_free,
+ .engine_scan = adapter_hs_scan,
+ .engine_stream_open = adapter_hs_stream_open,
+ .engine_stream_close = adapter_hs_stream_close,
+ .engine_scan_stream = adapter_hs_scan_stream
+ },
+ {
+ .type = EXPR_ENGINE_TYPE_RS,
+ .engine_new = adapter_rs_new,
+ .engine_free = adapter_rs_free,
+ .engine_scan = adapter_rs_scan,
+ .engine_stream_open = adapter_rs_stream_open,
+ .engine_stream_close = adapter_rs_stream_close,
+ .engine_scan_stream = adapter_rs_scan_stream
+ }
+};
+
+int expr_matcher_verify_regex_expression(const char *regex_expr,
+ struct log_handle *logger)
+{
+ int ret = adapter_hs_verify_regex_expression(regex_expr, logger);
+ if (ret == 0) {
+ return 0;
+ }
+
+ return adapter_rs_verify_regex_expression(regex_expr, logger);
+}
+
+struct expr_matcher *
+expr_matcher_new(struct expr_rule *rules, size_t n_rule, enum expr_engine_type engine_type,
+ size_t n_worker_thread, struct log_handle *logger)
+{
+ if (NULL == rules || 0 == n_rule || 0 == n_worker_thread ||
+ (engine_type != EXPR_ENGINE_TYPE_HS && engine_type != EXPR_ENGINE_TYPE_RS)) {
+ log_error(logger, MODULE_EXPR_MATCHER, "[%s:%d]engine type:%d is illegal",
+ __FUNCTION__, __LINE__, engine_type);
+ return NULL;
+ }
+
+ size_t i = 0, j = 0;
+ size_t literal_pat_num = 0;
+ size_t regex_pat_num = 0;
+
+ for (i = 0; i < n_rule; i++) {
+ if (rules[i].n_patterns > MAX_EXPR_PATTERN_NUM) {
+ log_error(logger, MODULE_EXPR_MATCHER,
+ "[%s:%d] the number of patterns in one expression should less than"
+ " %d", __FUNCTION__, __LINE__, MAX_EXPR_PATTERN_NUM);
+ return NULL;
+ }
+
+ for (j = 0; j < rules[i].n_patterns; j++) {
+ /* pat_len should not 0 */
+ if (0 == rules[i].patterns[j].pat_len) {
+ log_error(logger, MODULE_EXPR_MATCHER,
+ "[%s:%d] expr pattern length should not 0",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ if (rules[i].patterns[j].type == EXPR_PATTERN_TYPE_STR) {
+ literal_pat_num++;
+ } else {
+ regex_pat_num++;
+ }
+ }
+ }
+
+ if (0 == literal_pat_num && 0 == regex_pat_num) {
+ log_error(logger, MODULE_EXPR_MATCHER,
+ "[%s:%d] exprs has no valid pattern", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ void *engine = expr_engine_ops[engine_type].engine_new(rules, n_rule, literal_pat_num,
+ regex_pat_num, n_worker_thread,
+ logger);
+ if (NULL == engine) {
+ log_error(logger, MODULE_EXPR_MATCHER,
+ "[%s:%d]expr_matcher engine_new failed.", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ struct expr_matcher *matcher = ALLOC(struct expr_matcher, 1);
+ matcher->engine_type = engine_type;
+ matcher->engine = engine;
+ matcher->logger = logger;
+
+ return matcher;
+}
+
+void expr_matcher_free(struct expr_matcher *matcher)
+{
+ if (NULL == matcher) {
+ return;
+ }
+
+ if (matcher->engine != NULL) {
+ expr_engine_ops[matcher->engine_type].engine_free(matcher->engine);
+ matcher->engine = NULL;
+ }
+
+ FREE(matcher);
+}
+
+int expr_matcher_match(struct expr_matcher *matcher, int thread_id, const char *scan_data,
+ size_t data_len, struct expr_scan_result *result_array,
+ size_t n_result_array, size_t *n_hit_results)
+{
+ if (NULL == matcher || thread_id < 0 || NULL == scan_data || 0 == data_len
+ || NULL == result_array || 0 == n_result_array || NULL == n_hit_results) {
+ return -1;
+ }
+
+ return expr_engine_ops[matcher->engine_type].engine_scan(matcher->engine, thread_id,
+ scan_data, data_len, result_array,
+ n_result_array, n_hit_results);
+}
+
+struct expr_matcher_stream *
+expr_matcher_stream_open(struct expr_matcher *matcher, int thread_id)
+{
+ if (NULL == matcher || thread_id < 0) {
+ return NULL;
+ }
+
+ void *s_handle = expr_engine_ops[matcher->engine_type].engine_stream_open(matcher->engine,
+ thread_id);
+ if (NULL == s_handle) {
+ log_error(matcher->logger, MODULE_EXPR_MATCHER,
+ "[%s:%d] expr_matcher engine_stream_open failed.",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ struct expr_matcher_stream *stream = ALLOC(struct expr_matcher_stream, 1);
+ stream->engine_type = matcher->engine_type;
+ stream->handle = s_handle;
+
+ return stream;
+}
+
+int expr_matcher_stream_match(struct expr_matcher_stream *stream, const char *scan_data,
+ size_t data_len, struct expr_scan_result *result_array,
+ size_t n_result_array, size_t *n_hit_results)
+{
+ if (NULL == stream || NULL == scan_data || 0 == data_len || NULL == result_array
+ || 0 == n_result_array || NULL == n_hit_results) {
+ return -1;
+ }
+
+ return expr_engine_ops[stream->engine_type].engine_scan_stream(stream->handle, scan_data,
+ data_len, result_array,
+ n_result_array, n_hit_results);
+}
+
+void expr_matcher_stream_close(struct expr_matcher_stream *stream)
+{
+ if (NULL == stream) {
+ return;
+ }
+
+ if (stream->handle != NULL) {
+ expr_engine_ops[stream->engine_type].engine_stream_close(stream->handle);
+ stream->handle = NULL;
+ }
+
+ FREE(stream);
+} \ No newline at end of file