/* | /* | ||||
* Convert comma separated string to a list of strings | * Convert comma separated string to a list of strings | ||||
*/ | */ | ||||
GList* parse_comma_list (memory_pool_t *pool, gchar *line); | |||||
GList* parse_comma_list (memory_pool_t *pool, const gchar *line); | |||||
/* | /* | ||||
* Return a new classifier_config structure, setting default and non-conflicting attributes | * Return a new classifier_config structure, setting default and non-conflicting attributes |
#include "cfg_file.h" | #include "cfg_file.h" | ||||
#include "lua/lua_common.h" | #include "lua/lua_common.h" | ||||
#include "expressions.h" | #include "expressions.h" | ||||
#include "view.h" | |||||
#include "classifiers/classifiers.h" | #include "classifiers/classifiers.h" | ||||
#include "tokenizers/tokenizers.h" | #include "tokenizers/tokenizers.h" | ||||
return TRUE; | return TRUE; | ||||
} | } | ||||
static gboolean | |||||
rspamd_rcl_view_handler (struct config_file *cfg, ucl_object_t *obj, | |||||
gpointer ud, struct rspamd_rcl_section *section, GError **err) | |||||
{ | |||||
ucl_object_t *val, *cur; | |||||
struct rspamd_view *view; | |||||
const gchar *view_ip, *view_client_ip, *view_symbols, | |||||
*view_rcpt, *view_from; | |||||
bool skip_check = false; | |||||
view = init_view (cfg, cfg->cfg_pool); | |||||
val = ucl_object_find_key (obj, "ip"); | |||||
LL_FOREACH (val, cur) { | |||||
if (cur != NULL && ucl_object_tostring_safe (cur, &view_ip)) { | |||||
if (!add_view_ip (view, view_ip)) { | |||||
g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot parse view ip: %s", view_ip); | |||||
return FALSE; | |||||
} | |||||
} | |||||
} | |||||
val = ucl_object_find_key (obj, "client_ip"); | |||||
LL_FOREACH (val, cur) { | |||||
if (cur != NULL && ucl_object_tostring_safe (cur, &view_client_ip)) { | |||||
if (!add_view_client_ip (view, view_client_ip)) { | |||||
g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot parse view client ip: %s", view_client_ip); | |||||
return FALSE; | |||||
} | |||||
} | |||||
} | |||||
val = ucl_object_find_key (obj, "symbols"); | |||||
LL_FOREACH (val, cur) { | |||||
if (cur != NULL && ucl_object_tostring_safe (cur, &view_symbols)) { | |||||
if (!add_view_symbols (view, view_symbols)) { | |||||
g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot parse view client symbols: %s", view_symbols); | |||||
return FALSE; | |||||
} | |||||
} | |||||
} | |||||
val = ucl_object_find_key (obj, "rcpt"); | |||||
LL_FOREACH (val, cur) { | |||||
if (cur != NULL && ucl_object_tostring_safe (cur, &view_rcpt)) { | |||||
if (!add_view_rcpt (view, view_rcpt)) { | |||||
g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot parse view recipient: %s", view_rcpt); | |||||
return FALSE; | |||||
} | |||||
} | |||||
} | |||||
val = ucl_object_find_key (obj, "from"); | |||||
LL_FOREACH (val, cur) { | |||||
if (cur != NULL && ucl_object_tostring_safe (cur, &view_from)) { | |||||
if (!add_view_from (view, view_from)) { | |||||
g_set_error (err, CFG_RCL_ERROR, EINVAL, "cannot parse view from: %s", view_from); | |||||
return FALSE; | |||||
} | |||||
} | |||||
} | |||||
val = ucl_object_find_key (obj, "skip_check"); | |||||
if (val != NULL && ucl_object_toboolean_safe (val, &skip_check)) { | |||||
view->skip_check = skip_check; | |||||
} | |||||
cfg->views = g_list_prepend (cfg->views, view); | |||||
return TRUE; | |||||
} | |||||
/** | /** | ||||
* Fake handler to parse default options only, uses struct cfg_file as pointer | * Fake handler to parse default options only, uses struct cfg_file as pointer | ||||
* for default handlers | * for default handlers | ||||
* Composites handler | * Composites handler | ||||
*/ | */ | ||||
sub = rspamd_rcl_add_section (&new, "composite", rspamd_rcl_composite_handler, UCL_OBJECT, | sub = rspamd_rcl_add_section (&new, "composite", rspamd_rcl_composite_handler, UCL_OBJECT, | ||||
FALSE, TRUE); | |||||
FALSE, TRUE); | |||||
/** | |||||
* Views handler | |||||
*/ | |||||
sub = rspamd_rcl_add_section (&new, "view", rspamd_rcl_view_handler, UCL_OBJECT, | |||||
FALSE, TRUE); | |||||
return new; | return new; | ||||
} | } |
} | } | ||||
GList * | GList * | ||||
parse_comma_list (memory_pool_t * pool, gchar *line) | |||||
parse_comma_list (memory_pool_t * pool, const gchar *line) | |||||
{ | { | ||||
GList *res = NULL; | GList *res = NULL; | ||||
gchar *c, *p, *str; | |||||
const gchar *c, *p; | |||||
gchar *str; | |||||
c = line; | c = line; | ||||
p = c; | p = c; |
* Rspamd regexp utility functions | * Rspamd regexp utility functions | ||||
*/ | */ | ||||
struct rspamd_regexp * | struct rspamd_regexp * | ||||
parse_regexp (memory_pool_t * pool, gchar *line, gboolean raw_mode) | |||||
parse_regexp (memory_pool_t * pool, const gchar *line, gboolean raw_mode) | |||||
{ | { | ||||
gchar *begin, *end, *p, *src, *start; | |||||
const gchar *begin, *end, *p, *src, *start; | |||||
gchar *dbegin, *dend; | |||||
struct rspamd_regexp *result, *check; | struct rspamd_regexp *result, *check; | ||||
gint regexp_flags = G_REGEX_OPTIMIZE | G_REGEX_NO_AUTO_CAPTURE; | gint regexp_flags = G_REGEX_OPTIMIZE | G_REGEX_NO_AUTO_CAPTURE; | ||||
GError *err = NULL; | GError *err = NULL; | ||||
/* First try to find header name */ | /* First try to find header name */ | ||||
begin = strchr (line, '/'); | begin = strchr (line, '/'); | ||||
if (begin != NULL) { | if (begin != NULL) { | ||||
*begin = '\0'; | |||||
end = strchr (line, '='); | |||||
*begin = '/'; | |||||
end = strrchr (begin, '='); | |||||
if (end) { | if (end) { | ||||
*end = '\0'; | |||||
result->header = memory_pool_strdup (pool, line); | |||||
result->header = memory_pool_alloc (pool, end - line + 1); | |||||
rspamd_strlcpy (result->header, line, end - line + 1); | |||||
result->type = REGEXP_HEADER; | result->type = REGEXP_HEADER; | ||||
*end = '='; | |||||
line = end; | line = end; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
*end = '\0'; | |||||
result->regexp_text = memory_pool_strdup (pool, start); | |||||
dbegin = result->regexp_text + (begin - start); | |||||
dend = result->regexp_text + (end - start); | |||||
*dend = '\0'; | |||||
if (raw_mode) { | if (raw_mode) { | ||||
regexp_flags |= G_REGEX_RAW; | regexp_flags |= G_REGEX_RAW; | ||||
} | } | ||||
/* Avoid multiply regexp structures for similar regexps */ | /* Avoid multiply regexp structures for similar regexps */ | ||||
if ((check = (struct rspamd_regexp *)re_cache_check (begin, pool)) != NULL) { | |||||
if ((check = (struct rspamd_regexp *)re_cache_check (result->regexp_text, pool)) != NULL) { | |||||
/* Additional check for headers */ | /* Additional check for headers */ | ||||
if (result->type == REGEXP_HEADER || result->type == REGEXP_RAW_HEADER) { | if (result->type == REGEXP_HEADER || result->type == REGEXP_RAW_HEADER) { | ||||
if (result->header && check->header) { | if (result->header && check->header) { | ||||
return check; | return check; | ||||
} | } | ||||
} | } | ||||
result->regexp = g_regex_new (begin, regexp_flags, 0, &err); | |||||
result->regexp = g_regex_new (dbegin, regexp_flags, 0, &err); | |||||
if ((regexp_flags & G_REGEX_RAW) != 0) { | if ((regexp_flags & G_REGEX_RAW) != 0) { | ||||
result->raw_regexp = result->regexp; | result->raw_regexp = result->regexp; | ||||
} | } | ||||
else { | else { | ||||
result->raw_regexp = g_regex_new (begin, regexp_flags | G_REGEX_RAW, 0, &err); | |||||
result->raw_regexp = g_regex_new (dbegin, regexp_flags | G_REGEX_RAW, 0, &err); | |||||
memory_pool_add_destructor (pool, (pool_destruct_func) g_regex_unref, (void *)result->raw_regexp); | memory_pool_add_destructor (pool, (pool_destruct_func) g_regex_unref, (void *)result->raw_regexp); | ||||
} | } | ||||
*end = '/'; | |||||
result->regexp_text = memory_pool_strdup (pool, start); | |||||
memory_pool_add_destructor (pool, (pool_destruct_func) g_regex_unref, (void *)result->regexp); | memory_pool_add_destructor (pool, (pool_destruct_func) g_regex_unref, (void *)result->regexp); | ||||
*dend = '/'; | |||||
if (result->regexp == NULL || err != NULL) { | if (result->regexp == NULL || err != NULL) { | ||||
*end = '/'; | |||||
msg_warn ("could not read regexp: %s while reading regexp %s", err->message, src); | msg_warn ("could not read regexp: %s while reading regexp %s", err->message, src); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
if (result->raw_regexp == NULL || err != NULL) { | if (result->raw_regexp == NULL || err != NULL) { | ||||
msg_warn ("could not read raw regexp: %s while reading regexp %s", err->message, src); | msg_warn ("could not read raw regexp: %s while reading regexp %s", err->message, src); | ||||
return NULL; | return NULL; |
* @param line incoming line | * @param line incoming line | ||||
* @return regexp structure or NULL in case of error | * @return regexp structure or NULL in case of error | ||||
*/ | */ | ||||
struct rspamd_regexp* parse_regexp (memory_pool_t *pool, gchar *line, gboolean raw_mode); | |||||
struct rspamd_regexp* parse_regexp (memory_pool_t *pool, const gchar *line, gboolean raw_mode); | |||||
/** | /** | ||||
* Parse composites line to composites structure (eg. "SYMBOL1&SYMBOL2|!SYMBOL3") | * Parse composites line to composites structure (eg. "SYMBOL1&SYMBOL2|!SYMBOL3") |
} | } | ||||
gboolean | gboolean | ||||
add_view_from (struct rspamd_view * view, gchar *line) | |||||
add_view_from (struct rspamd_view * view, const gchar *line) | |||||
{ | { | ||||
struct rspamd_regexp *re = NULL; | struct rspamd_regexp *re = NULL; | ||||
} | } | ||||
gboolean | gboolean | ||||
add_view_rcpt (struct rspamd_view * view, gchar *line) | |||||
add_view_rcpt (struct rspamd_view * view, const gchar *line) | |||||
{ | { | ||||
struct rspamd_regexp *re = NULL; | struct rspamd_regexp *re = NULL; | ||||
} | } | ||||
gboolean | gboolean | ||||
add_view_symbols (struct rspamd_view * view, gchar *line) | |||||
add_view_symbols (struct rspamd_view * view, const gchar *line) | |||||
{ | { | ||||
struct rspamd_regexp *re = NULL; | struct rspamd_regexp *re = NULL; | ||||
GList *symbols; | GList *symbols; | ||||
} | } | ||||
gboolean | gboolean | ||||
add_view_ip (struct rspamd_view * view, gchar *line) | |||||
add_view_ip (struct rspamd_view * view, const gchar *line) | |||||
{ | { | ||||
if (add_map (view->cfg, line, "IP view", read_radix_list, fin_radix_list, (void **)&view->ip_tree)) { | if (add_map (view->cfg, line, "IP view", read_radix_list, fin_radix_list, (void **)&view->ip_tree)) { | ||||
return TRUE; | return TRUE; | ||||
} | } | ||||
gboolean | gboolean | ||||
add_view_client_ip (struct rspamd_view * view, gchar *line) | |||||
add_view_client_ip (struct rspamd_view * view, const gchar *line) | |||||
{ | { | ||||
if (add_map (view->cfg, line, "Client IP view", read_radix_list, fin_radix_list, (void **)&view->client_ip_tree)) { | if (add_map (view->cfg, line, "Client IP view", read_radix_list, fin_radix_list, (void **)&view->client_ip_tree)) { | ||||
return TRUE; | return TRUE; |
* @param line from line for this view | * @param line from line for this view | ||||
* @return | * @return | ||||
*/ | */ | ||||
gboolean add_view_from (struct rspamd_view *view, gchar *line); | |||||
gboolean add_view_from (struct rspamd_view *view, const gchar *line); | |||||
/** | /** | ||||
* @param line recipient description | * @param line recipient description | ||||
* @return | * @return | ||||
*/ | */ | ||||
gboolean add_view_rcpt (struct rspamd_view *view, gchar *line); | |||||
gboolean add_view_rcpt (struct rspamd_view *view, const gchar *line); | |||||
/** | /** | ||||
* Add ip option for this view | * Add ip option for this view | ||||
* @param line ip description | * @param line ip description | ||||
* @return | * @return | ||||
*/ | */ | ||||
gboolean add_view_ip (struct rspamd_view *view, gchar *line); | |||||
gboolean add_view_ip (struct rspamd_view *view, const gchar *line); | |||||
/** | /** | ||||
* Add client ip option for this view | * Add client ip option for this view | ||||
* @param line ip description | * @param line ip description | ||||
* @return | * @return | ||||
*/ | */ | ||||
gboolean add_view_client_ip (struct rspamd_view *view, gchar *line); | |||||
gboolean add_view_client_ip (struct rspamd_view *view, const gchar *line); | |||||
/** | /** | ||||
* Add symbols option for this view | * Add symbols option for this view | ||||
* @param line symbols description | * @param line symbols description | ||||
* @return | * @return | ||||
*/ | */ | ||||
gboolean add_view_symbols (struct rspamd_view *view, gchar *line); | |||||
gboolean add_view_symbols (struct rspamd_view *view, const gchar *line); | |||||
/** | /** | ||||
* Check view for this task for specified symbol | * Check view for this task for specified symbol |