1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-29 21:56:37 +02:00

Add spamfilter::rule (preconditions), add context to crule parser,

and add the first functions: online_time() and reputation().

The more interesting stuff will follow later...
This commit is contained in:
Bram Matthys
2023-07-06 15:43:12 +02:00
parent 1e572e25b9
commit 6bbcdfd1b3
11 changed files with 226 additions and 109 deletions
+6 -5
View File
@@ -534,7 +534,7 @@ extern void init_CommandHash(void);
/* CRULE */
extern struct CRuleNode* crule_parse(const char*);
extern void crule_free(struct CRuleNode**);
extern int crule_eval(struct CRuleNode* rule);
extern int crule_eval(crule_context *context, CRuleNode *rule);
extern int crule_test(const char *rule);
extern const char *crule_errstring(int errcode);
@@ -818,10 +818,11 @@ extern MODVAR TKL *(*tkl_add_banexception)(int type, const char *usermask, const
time_t expire_at, time_t set_at, int soft, const char *bantypes, int flags);
extern MODVAR TKL *(*tkl_add_nameban)(int type, const char *name, int hold, const char *reason, const char *setby,
time_t expire_at, time_t set_at, int flags);
extern MODVAR TKL *(*tkl_add_spamfilter)(int type, unsigned short target, BanAction *action, Match *match, const char *setby,
time_t expire_at, time_t set_at,
time_t spamf_tkl_duration, const char *spamf_tkl_reason,
int flags);
extern MODVAR TKL *(*tkl_add_spamfilter)(int type, unsigned short target, BanAction *action,
Match *match, const char *rule, const char *setby,
time_t expire_at, time_t set_at,
time_t spamf_tkl_duration, const char *spamf_tkl_reason,
int flags);
extern MODVAR TKL *(*find_tkl_serverban)(int type, const char *usermask, const char *hostmask, int softban);
extern MODVAR TKL *(*find_tkl_banexception)(int type, const char *usermask, const char *hostmask, int softban);
extern MODVAR TKL *(*find_tkl_nameban)(int type, const char *name, int hold);
+34 -26
View File
@@ -855,6 +855,7 @@ struct LoopStruct {
typedef enum {
MATCH_SIMPLE=1, /**< Simple pattern with * and ? */
MATCH_PCRE_REGEX=2, /**< PCRE2 Perl-like regex (new) */
MATCH_NONE=3, /**< No matching at all (rule-based) */
} MatchType;
/** Match struct, which allows various matching styles, see MATCH_* */
@@ -1063,6 +1064,37 @@ struct Secret {
SecretCache *cache;
};
/* CRULE stuff */
#define CRULE_ALL 0
#define CRULE_AUTO 1
/* some constants and shared data types */
#define CR_MAXARGLEN 80 /**< Maximum arg length (must be > HOSTLEN) */
#define CR_MAXARGS 3 /**< Maximum number of args for a rule */
/* context when running a crule */
typedef struct crule_context crule_context;
struct crule_context
{
Client *client;
};
/** Evaluation function for a connection rule. */
typedef int (*crule_funcptr) (crule_context *context, int, void **);
/** CRULE - Node in a connection rule tree. */
struct CRuleNode {
crule_funcptr funcptr; /**< Evaluation function for this node. */
int numargs; /**< Number of arguments. */
void *arg[CR_MAXARGS]; /**< Array of arguments. For operators, each arg
is a tree element; for functions, each arg is
a string. */
int func_test_type; /* for >, < and == */
int func_test_value; /* integer value to compare against */
};
typedef struct CRuleNode CRuleNode;
typedef struct CRuleNode* CRuleNodePtr;
/* tkl:
* TKL_KILL|TKL_GLOBAL = Global K-Line (GLINE)
@@ -1176,6 +1208,8 @@ struct Spamfilter {
unsigned short target;
BanAction *action; /**< Ban action */
Match *match; /**< Spamfilter matcher */
CRuleNode *rule; /**< parsed crule */
char *prettyrule; /**< human printable version */
char *tkl_reason; /**< Reason to use for bans placed by this spamfilter, escaped by unreal_encodespace(). */
time_t tkl_duration; /**< Duration of bans placed by this spamfilter */
};
@@ -1529,32 +1563,6 @@ struct AuthConfig {
#define crypt DES_crypt
#endif
/* CRULE stuff */
#define CRULE_ALL 0
#define CRULE_AUTO 1
/* some constants and shared data types */
#define CR_MAXARGLEN 80 /**< Maximum arg length (must be > HOSTLEN) */
#define CR_MAXARGS 3 /**< Maximum number of args for a rule */
/** Evaluation function for a connection rule. */
typedef int (*crule_funcptr) (int, void **);
/** CRULE - Node in a connection rule tree. */
struct CRuleNode {
crule_funcptr funcptr; /**< Evaluation function for this node. */
int numargs; /**< Number of arguments. */
void *arg[CR_MAXARGS]; /**< Array of arguments. For operators, each arg
is a tree element; for functions, each arg is
a string. */
int func_test_type; /* for >, < and == */
int func_test_value; /* integer value to compare against */
};
typedef struct CRuleNode CRuleNode;
typedef struct CRuleNode* CRuleNodePtr;
/*
* conf2 stuff -stskeeps
*/
+5 -4
View File
@@ -55,10 +55,11 @@ TKL *(*tkl_add_serverban)(int type, const char *usermask, const char *hostmask,
time_t expire_at, time_t set_at, int soft, int flags);
TKL *(*tkl_add_nameban)(int type, const char *name, int hold, const char *reason, const char *setby,
time_t expire_at, time_t set_at, int flags);
TKL *(*tkl_add_spamfilter)(int type, unsigned short target, BanAction *action, Match *match, const char *setby,
time_t expire_at, time_t set_at,
time_t spamf_tkl_duration, const char *spamf_tkl_reason,
int flags);
TKL *(*tkl_add_spamfilter)(int type, unsigned short target, BanAction *action,
Match *match, const char *rule, const char *setby,
time_t expire_at, time_t set_at,
time_t spamf_tkl_duration, const char *spamf_tkl_reason,
int flags);
TKL *(*tkl_add_banexception)(int type, const char *usermask, const char *hostmask, SecurityGroup *match,
const char *reason, const char *set_by,
time_t expire_at, time_t set_at, int soft, const char *bantypes, int flags);
+40 -20
View File
@@ -132,12 +132,15 @@ enum crule_errcode {
*/
/* rule function prototypes - local! */
static int crule_connected(int, void **);
static int crule_directcon(int, void **);
static int crule_via(int, void **);
static int crule_directop(int, void **);
static int crule__andor(int, void **);
static int crule__not(int, void **);
static int crule_connected(crule_context *, int, void **);
static int crule_directcon(crule_context *, int, void **);
static int crule_via(crule_context *, int, void **);
static int crule_directop(crule_context *, int, void **);
static int crule__andor(crule_context *, int, void **);
static int crule__not(crule_context *, int, void **);
// newstyle
static int crule_online_time(crule_context *, int, void **);
static int crule_reputation(crule_context *, int, void **);
/* parsing function prototypes - local! */
static int crule_gettoken(crule_token *next_tokp, const char** str);
@@ -185,13 +188,15 @@ struct crule_funclistent {
struct crule_funclistent crule_funclist[] = {
/* maximum function name length is 14 chars */
{"connected", 1, crule_connected},
{"online_time", 0, crule_online_time},
{"reputation", 0, crule_reputation},
{"directcon", 1, crule_directcon},
{"via", 2, crule_via},
{"directop", 0, crule_directop},
{"", 0, NULL} /* this must be here to mark end of list */
};
static int crule_connected(int numargs, void *crulearg[])
static int crule_connected(crule_context *context, int numargs, void *crulearg[])
{
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
Client *client;
@@ -208,7 +213,7 @@ static int crule_connected(int numargs, void *crulearg[])
#endif
}
static int crule_directcon(int numargs, void *crulearg[])
static int crule_directcon(crule_context *context, int numargs, void *crulearg[])
{
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
Client *client;
@@ -227,7 +232,7 @@ static int crule_directcon(int numargs, void *crulearg[])
#endif
}
static int crule_via(int numargs, void *crulearg[])
static int crule_via(crule_context *context, int numargs, void *crulearg[])
{
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
Client *client;
@@ -246,7 +251,7 @@ static int crule_via(int numargs, void *crulearg[])
#endif
}
static int crule_directop(int numargs, void *crulearg[])
static int crule_directop(crule_context *context, int numargs, void *crulearg[])
{
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
Client *client;
@@ -264,13 +269,27 @@ static int crule_directop(int numargs, void *crulearg[])
#endif
}
static int crule_online_time(crule_context *context, int numargs, void *crulearg[])
{
if (context && context->client)
return get_connected_time(context->client);
return 0;
}
static int crule_reputation(crule_context *context, int numargs, void *crulearg[])
{
if (context && context->client)
return GetReputation(context->client);
return 0;
}
/** Evaluate a connection rule.
* @param[in] rule Rule to evalute.
* @return Non-zero if the rule allows the connection, zero otherwise.
*/
int crule_eval(struct CRuleNode* rule)
int crule_eval(crule_context *context, struct CRuleNode* rule)
{
int ret = rule->funcptr(rule->numargs, rule->arg);
int ret = rule->funcptr(context, rule->numargs, rule->arg);
switch (rule->func_test_type)
{
case CR_EQUAL:
@@ -300,15 +319,15 @@ int crule_eval(struct CRuleNode* rule)
* @param[in] crulearg Argument array.
* @return Non-zero if the condition is true, zero if not.
*/
static int crule__andor(int numargs, void *crulearg[])
static int crule__andor(crule_context *context, int numargs, void *crulearg[])
{
int result1;
result1 = crule_eval(crulearg[0]);
result1 = crule_eval(context, crulearg[0]);
if (crulearg[2]) /* or */
return (result1 || crule_eval(crulearg[1]));
return (result1 || crule_eval(context, crulearg[1]));
else
return (result1 && crule_eval(crulearg[1]));
return (result1 && crule_eval(context, crulearg[1]));
}
/** Logically invert the result of crulearg[0].
@@ -316,9 +335,9 @@ static int crule__andor(int numargs, void *crulearg[])
* @param[in] crulearg Argument array.
* @return Non-zero if the condition is true, zero if not.
*/
static int crule__not(int numargs, void *crulearg[])
static int crule__not(crule_context *context, int numargs, void *crulearg[])
{
return (!crule_eval(crulearg[0]));
return (!crule_eval(context, crulearg[0]));
}
/** Scan an input token from \a ruleptr.
@@ -388,7 +407,7 @@ static int crule_gettoken(crule_token *next_tokp, const char** ruleptr)
break;
default:
if ((isalnum(*(--(*ruleptr)))) || (**ruleptr == '*') ||
(**ruleptr == '?') || (**ruleptr == '.') || (**ruleptr == '-'))
(**ruleptr == '?') || (**ruleptr == '.') || (**ruleptr == '-') || (**ruleptr == '_'))
*next_tokp = CR_WORD;
else
return (CR_UNKNWTOK);
@@ -411,7 +430,8 @@ static void crule_getword(char* word, int* wordlenp, size_t maxlen, const char**
while ((size_t)(word_ptr - word) < maxlen
&& (isalnum(**ruleptr)
|| **ruleptr == '*' || **ruleptr == '?'
|| **ruleptr == '.' || **ruleptr == '-'))
|| **ruleptr == '.' || **ruleptr == '-'
|| **ruleptr == '_'))
*word_ptr++ = *(*ruleptr)++;
*word_ptr = '\0';
*wordlenp = word_ptr - word;
+7 -2
View File
@@ -569,8 +569,13 @@ void json_expand_tkl(json_t *root, const char *key, TKL *tkl, int detail)
} else
if (TKLIsSpamfilter(tkl))
{
json_object_set_new(j, "name", json_string_unreal(tkl->ptr.spamfilter->match->str));
json_object_set_new(j, "match_type", json_string_unreal(unreal_match_method_valtostr(tkl->ptr.spamfilter->match->type)));
if (tkl->ptr.spamfilter->match->str)
{
json_object_set_new(j, "name", json_string_unreal(tkl->ptr.spamfilter->match->str));
json_object_set_new(j, "match_type", json_string_unreal(unreal_match_method_valtostr(tkl->ptr.spamfilter->match->type)));
}
if (tkl->ptr.spamfilter->prettyrule)
json_object_set_new(j, "rule", json_string_unreal(tkl->ptr.spamfilter->prettyrule));
json_object_set_new(j, "ban_action", json_string_unreal(ban_actions_to_string(tkl->ptr.spamfilter->action)));
json_object_set_new(j, "ban_duration", json_integer(tkl->ptr.spamfilter->tkl_duration));
json_object_set_new(j, "ban_duration_string", json_string_unreal(pretty_time_val_r(buf, sizeof(buf), tkl->ptr.spamfilter->tkl_duration)));
+11 -1
View File
@@ -428,6 +428,9 @@ Match *unreal_create_match(MatchType type, const char *str, char **error)
}
pcre2_jit_compile(m->ext.pcre2_expr, PCRE2_JIT_COMPLETE);
return m;
} else if (m->type == MATCH_NONE)
{
/* Nothing to do */
}
else {
/* Unknown type, how did that happen ? */
@@ -463,6 +466,9 @@ int unreal_match(Match *m, const char *str)
return 0; /* NO MATCH */
}
if (m->type == MATCH_NONE)
return 1;
return 0;
}
@@ -472,6 +478,8 @@ int unreal_match_method_strtoval(const char *str)
return MATCH_PCRE_REGEX;
if (!strcmp(str, "simple") || !strcmp(str, "glob"))
return MATCH_SIMPLE;
if (!strcmp(str, "none"))
return MATCH_NONE;
return 0;
}
@@ -481,7 +489,9 @@ char *unreal_match_method_valtostr(int val)
return "regex";
if (val == MATCH_SIMPLE)
return "simple";
if (val == MATCH_NONE)
return "none";
return "unknown";
}
+1 -1
View File
@@ -971,7 +971,7 @@ char *spamfilter_target_inttostring(int v)
if (v & e->value)
*p++ = e->character;
*p = '\0';
return buf;
return *buf ? buf : "-";
}
/** Replace underscores back to the space character.
+1 -1
View File
@@ -247,7 +247,7 @@ RPC_CALL_FUNC(rpc_spamfilter_add)
return;
}
tkl = tkl_add_spamfilter(type, targets, banact_value_to_struct(action), m, set_by, 0, TStime(),
tkl = tkl_add_spamfilter(type, targets, banact_value_to_struct(action), m, NULL, set_by, 0, TStime(),
ban_duration, reason, 0);
if (!tkl)
+2 -1
View File
@@ -2204,13 +2204,14 @@ int _is_services_but_not_ulined(Client *client)
const char *_check_deny_link(ConfigItem_link *link, int auto_connect)
{
ConfigItem_deny_link *d;
crule_context context;
for (d = conf_deny_link; d; d = d->next)
{
if ((auto_connect == 0) && (d->flag.type == CRULE_AUTO))
continue;
if (unreal_mask_match_string(link->servername, d->mask) &&
crule_eval(d->rule))
crule_eval(NULL, d->rule))
{
return d->reason;
}
+118 -48
View File
@@ -68,10 +68,11 @@ TKL *_tkl_add_banexception(int type, char *usermask, char *hostmask, SecurityGro
time_t expire_at, time_t set_at, int soft, char *bantypes, int flags);
TKL *_tkl_add_nameban(int type, char *name, int hold, char *reason, char *set_by,
time_t expire_at, time_t set_at, int flags);
TKL *_tkl_add_spamfilter(int type, unsigned short target, BanAction *action, Match *match, char *set_by,
time_t expire_at, time_t set_at,
time_t spamf_tkl_duration, char *spamf_tkl_reason,
int flags);
TKL *_tkl_add_spamfilter(int type, unsigned short target, BanAction *action, Match *match,
const char *rule, const char *set_by,
time_t expire_at, time_t set_at,
time_t spamf_tkl_duration, const char *spamf_tkl_reason,
int flags);
void _sendnotice_tkl_del(char *removed_by, TKL *tkl);
void _sendnotice_tkl_add(TKL *tkl);
void _free_tkl(TKL *tkl);
@@ -269,7 +270,7 @@ int tkl_config_test_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type, int *e
ConfigEntry *cep, *cepp;
int errors = 0;
char *match = NULL, *reason = NULL;
char has_target = 0, has_match = 0, has_action = 0, has_reason = 0, has_bantime = 0, has_match_type = 0;
char has_target = 0, has_match = 0, has_rule = 0, has_action = 0, has_reason = 0, has_bantime = 0, has_match_type = 0;
int match_type = 0;
/* We are only interested in spamfilter { } blocks */
@@ -357,6 +358,25 @@ int tkl_config_test_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type, int *e
has_match = 1;
match = cep->value;
}
else if (!strcmp(cep->name, "rule"))
{
int val;
if (has_rule)
{
config_warn_duplicate(cep->file->filename,
cep->line_number, "spamfilter::rule");
continue;
}
has_rule = 1;
if ((val = crule_test(cep->value)))
{
config_error("%s:%i: spamfilter::rule contains an invalid expression: %s",
cep->file->filename,
cep->line_number,
crule_errstring(val));
errors++;
}
}
else if (!strcmp(cep->name, "ban-time"))
{
if (has_bantime)
@@ -425,13 +445,19 @@ int tkl_config_test_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type, int *e
}
}
if (!has_match)
if (!has_match && !has_rule)
{
config_error_missing(ce->file->filename, ce->line_number,
"spamfilter::match");
"spamfilter::match or spamfilter::rule");
errors++;
}
if (!has_target)
if (!has_match && has_match_type && has_rule)
{
config_error("%s:%i: spamfilter::match-type makes no sense if you only have a spamfilter::rule. Remove the match-type.",
ce->file->filename, ce->line_number);
errors++;
}
if (!has_target && match)
{
config_error_missing(ce->file->filename, ce->line_number,
"spamfilter::target");
@@ -450,7 +476,7 @@ int tkl_config_test_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type, int *e
ce->file->filename, ce->line_number);
errors++;
}
if (!has_match_type)
if (!has_match_type && match)
{
config_error_missing(ce->file->filename, ce->line_number,
"spamfilter::match-type");
@@ -474,13 +500,14 @@ int tkl_config_run_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type)
{
ConfigEntry *cep;
ConfigEntry *cepp;
char *word = NULL;
char *match = NULL;
char *rule = NULL;
time_t bantime = tempiConf.spamfilter_ban_time;
char *banreason = tempiConf.spamfilter_ban_reason;
BanAction *action;
int target = 0;
int match_type = 0;
Match *m;
Match *m = NULL;
/* We are only interested in spamfilter { } blocks */
if ((type != CONFIG_MAIN) || strcmp(ce->name, "spamfilter"))
@@ -490,7 +517,11 @@ int tkl_config_run_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type)
{
if (!strcmp(cep->name, "match"))
{
word = cep->value;
match = cep->value;
}
else if (!strcmp(cep->name, "rule"))
{
rule = cep->value;
}
else if (!strcmp(cep->name, "target"))
{
@@ -520,11 +551,16 @@ int tkl_config_run_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type)
}
}
m = unreal_create_match(match_type, word, NULL);
if (!match && rule)
match_type = MATCH_NONE;
if (match)
m = unreal_create_match(match_type, match, NULL);
tkl_add_spamfilter(TKL_SPAMF,
target,
action,
m,
rule,
"-config-",
0,
TStime(),
@@ -2585,9 +2621,10 @@ TKL *tkl_find_head(char type, char *hostmask, TKL *def)
* @returns The TKL entry, or NULL in case of a problem,
* such as a regex failing to compile, memory problem, ..
*/
TKL *_tkl_add_spamfilter(int type, unsigned short target, BanAction *action, Match *match, char *set_by,
TKL *_tkl_add_spamfilter(int type, unsigned short target, BanAction *action,
Match *match, const char *rule, const char *set_by,
time_t expire_at, time_t set_at,
time_t tkl_duration, char *tkl_reason,
time_t tkl_duration, const char *tkl_reason,
int flags)
{
TKL *tkl;
@@ -2597,14 +2634,26 @@ TKL *_tkl_add_spamfilter(int type, unsigned short target, BanAction *action, Mat
abort();
tkl = safe_alloc(sizeof(TKL));
/* First the common fields */
tkl->type = type;
tkl->flags = flags;
tkl->set_at = set_at;
safe_strdup(tkl->set_by, set_by);
tkl->expire_at = expire_at;
/* Then the spamfilter fields */
tkl->ptr.spamfilter = safe_alloc(sizeof(Spamfilter));
if (rule)
{
tkl->ptr.spamfilter->rule = crule_parse(rule);
safe_strdup(tkl->ptr.spamfilter->prettyrule, rule);
}
if (rule && !match)
{
/* When no spamfilter::match, name it $RULE:xxx */
char buf[512];
snprintf(buf, sizeof(buf), "$RULE:%s", rule);
match = safe_alloc(sizeof(Match));
match->type = MATCH_NONE;
safe_strdup(match->str, buf);
}
tkl->ptr.spamfilter->target = target;
tkl->ptr.spamfilter->action = action;
tkl->ptr.spamfilter->match = match;
@@ -2826,6 +2875,9 @@ void _free_tkl(TKL *tkl)
safe_free(tkl->ptr.spamfilter->tkl_reason);
if (tkl->ptr.spamfilter->match)
unreal_delete_match(tkl->ptr.spamfilter->match);
if (tkl->ptr.spamfilter->rule)
crule_free(&tkl->ptr.spamfilter->rule);
safe_free(tkl->ptr.spamfilter->prettyrule);
safe_free(tkl->ptr.spamfilter);
} else
if (TKLIsBanException(tkl) && tkl->ptr.banexception)
@@ -4344,7 +4396,7 @@ CMD_FUNC(cmd_tkl_add)
log_data_string("spamfilter_regex_error", err));
return;
}
tkl = tkl_add_spamfilter(type, target, banact_value_to_struct(action), m, set_by, expire_at, set_at,
tkl = tkl_add_spamfilter(type, target, banact_value_to_struct(action), m, NULL, set_by, expire_at, set_at,
tkl_duration, tkl_reason, 0);
}
} else
@@ -4931,40 +4983,58 @@ int _match_spamfilter(Client *client, const char *str_in, int target, const char
if (IsLoggedIn(client) && only_soft_actions(tkl->ptr.spamfilter->action))
continue;
#ifdef SPAMFILTER_DETECTSLOW
memset(&rnow, 0, sizeof(rnow));
memset(&rprev, 0, sizeof(rnow));
getrusage(RUSAGE_SELF, &rprev);
#endif
ret = unreal_match(tkl->ptr.spamfilter->match, str);
#ifdef SPAMFILTER_DETECTSLOW
getrusage(RUSAGE_SELF, &rnow);
ms_past = ((rnow.ru_utime.tv_sec - rprev.ru_utime.tv_sec) * 1000) +
((rnow.ru_utime.tv_usec - rprev.ru_utime.tv_usec) / 1000);
if ((SPAMFILTER_DETECTSLOW_FATAL > 0) && (ms_past > SPAMFILTER_DETECTSLOW_FATAL))
/* Run any pre 'rule' if there is any */
if (tkl->ptr.spamfilter->rule)
{
unreal_log(ULOG_ERROR, "tkl", "SPAMFILTER_SLOW_FATAL", NULL,
"[Spamfilter] WARNING: Too slow spamfilter detected (took $msec_time msec to execute) "
"-- spamfilter will be \002REMOVED!\002: $tkl",
log_data_tkl("tkl", tkl),
log_data_integer("msec_time", ms_past));
tkl_del_line(tkl);
return 0; /* Act as if it didn't match, even if it did.. it's gone now anyway.. */
} else
if ((SPAMFILTER_DETECTSLOW_WARN > 0) && (ms_past > SPAMFILTER_DETECTSLOW_WARN))
{
unreal_log(ULOG_WARNING, "tkl", "SPAMFILTER_SLOW_WARN", NULL,
"[Spamfilter] WARNING: Slow spamfilter detected (took $msec_time msec to execute): $tkl",
log_data_tkl("tkl", tkl),
log_data_integer("msec_time", ms_past));
crule_context context;
memset(&context, 0, sizeof(context));
context.client = client;
if (!crule_eval(&context, tkl->ptr.spamfilter->rule))
continue;
}
if (tkl->ptr.spamfilter->match && (tkl->ptr.spamfilter->match->type != MATCH_NONE))
{
// TODO: wait, why are we running slow spamfilter detection for simple (non-regex) too ?
#ifdef SPAMFILTER_DETECTSLOW
memset(&rnow, 0, sizeof(rnow));
memset(&rprev, 0, sizeof(rnow));
getrusage(RUSAGE_SELF, &rprev);
#endif
ret = unreal_match(tkl->ptr.spamfilter->match, str);
#ifdef SPAMFILTER_DETECTSLOW
getrusage(RUSAGE_SELF, &rnow);
ms_past = ((rnow.ru_utime.tv_sec - rprev.ru_utime.tv_sec) * 1000) +
((rnow.ru_utime.tv_usec - rprev.ru_utime.tv_usec) / 1000);
if ((SPAMFILTER_DETECTSLOW_FATAL > 0) && (ms_past > SPAMFILTER_DETECTSLOW_FATAL))
{
unreal_log(ULOG_ERROR, "tkl", "SPAMFILTER_SLOW_FATAL", NULL,
"[Spamfilter] WARNING: Too slow spamfilter detected (took $msec_time msec to execute) "
"-- spamfilter will be \002REMOVED!\002: $tkl",
log_data_tkl("tkl", tkl),
log_data_integer("msec_time", ms_past));
tkl_del_line(tkl);
return 0; /* Act as if it didn't match, even if it did.. it's gone now anyway.. */
} else
if ((SPAMFILTER_DETECTSLOW_WARN > 0) && (ms_past > SPAMFILTER_DETECTSLOW_WARN))
{
unreal_log(ULOG_WARNING, "tkl", "SPAMFILTER_SLOW_WARN", NULL,
"[Spamfilter] WARNING: Slow spamfilter detected (took $msec_time msec to execute): $tkl",
log_data_tkl("tkl", tkl),
log_data_integer("msec_time", ms_past));
}
#endif
} else {
/* There is no ::match but there was a ::rule, and that is enough for a match.. */
if (tkl->ptr.spamfilter->rule)
ret = 1;
}
if (ret)
{
/* We have a match! But.. perhaps it's on the exceptions list? */
+1
View File
@@ -723,6 +723,7 @@ int read_tkldb(void)
tkl_add_spamfilter(tkl->type, tkl->ptr.spamfilter->target,
tkl->ptr.spamfilter->action,
tkl->ptr.spamfilter->match,
NULL,
tkl->set_by, tkl->expire_at, tkl->set_at,
tkl->ptr.spamfilter->tkl_duration,
tkl->ptr.spamfilter->tkl_reason,