2023-08-10 16:10:50 +08:00
|
|
|
/*
|
|
|
|
|
**********************************************************************************************
|
|
|
|
|
* File: expr_matcher.cpp
|
|
|
|
|
* Description:
|
|
|
|
|
* Authors: Liu wentan <liuwentan@geedgenetworks.com>
|
|
|
|
|
* 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)) {
|
2023-11-10 08:26:48 +00:00
|
|
|
log_fatal(logger, MODULE_EXPR_MATCHER, "[%s:%d]engine type:%d is illegal",
|
2023-08-10 16:10:50 +08:00
|
|
|
__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) {
|
2023-11-10 08:26:48 +00:00
|
|
|
log_fatal(logger, MODULE_EXPR_MATCHER,
|
2023-08-10 16:10:50 +08:00
|
|
|
"[%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) {
|
2023-11-10 08:26:48 +00:00
|
|
|
log_fatal(logger, MODULE_EXPR_MATCHER,
|
2023-08-10 16:10:50 +08:00
|
|
|
"[%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) {
|
2023-11-10 08:26:48 +00:00
|
|
|
log_fatal(logger, MODULE_EXPR_MATCHER,
|
2023-08-10 16:10:50 +08:00
|
|
|
"[%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) {
|
2023-11-10 08:26:48 +00:00
|
|
|
log_fatal(logger, MODULE_EXPR_MATCHER,
|
2023-08-10 16:10:50 +08:00
|
|
|
"[%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) {
|
2023-11-10 08:26:48 +00:00
|
|
|
log_fatal(matcher->logger, MODULE_EXPR_MATCHER,
|
2023-08-10 16:10:50 +08:00
|
|
|
"[%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);
|
|
|
|
|
}
|