aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2009-03-17 12:25:23 +0300
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2009-03-17 12:25:23 +0300
commit8cc22288806b9ff7115cb8f30349029714e2d89a (patch)
treebc569c0dc56263b07906987ae22b8379cfb5325e
parentcfd2ff7bb58b81b7c0713b423a5b3397579610e7 (diff)
downloadrspamd-8cc22288806b9ff7115cb8f30349029714e2d89a.tar.gz
rspamd-8cc22288806b9ff7115cb8f30349029714e2d89a.zip
* Add ability to match raw headers
* Update documentation
-rw-r--r--README.utf8.txt11
-rw-r--r--src/cfg_file.h3
-rw-r--r--src/cfg_utils.c6
-rw-r--r--src/main.h1
-rw-r--r--src/message.c10
-rw-r--r--src/plugins/regexp.c47
6 files changed, 73 insertions, 5 deletions
diff --git a/README.utf8.txt b/README.utf8.txt
index c49da2476..c5bc293c0 100644
--- a/README.utf8.txt
+++ b/README.utf8.txt
@@ -89,6 +89,10 @@ Queue-ID - идентификатор очереди
.module 'regexp' {
SYMBOL = "regexp_expression";
};
+header_filters = "regexp";
+
+Обратите внимание, что модуль regexp надо регистрировать как header filter, так как иначе он не будет работать.
+Эту проблему надо исправлять, но это не первоочередная задача.
Формат регэкспов такой:
/pattern/flags
@@ -98,14 +102,19 @@ headername=/pattern/flags
Флаги регэскпов:
i, m, s, x, u, o - такие же, как у perl/pcre
H - ищет по заголовкам
-M - ищет по всему сообщению
+M - ищет по всему сообщению (в "сыром" виде)
P - ищет по всем mime частям
U - ищет по url
+X - ищет по "сырым" хедерам (тут нужно учитывать фолдинг и ставить, где надо, /m для multiline матчинга)
+
Выражение регэкспов может содержать сложные выражения из нескольких регэкспов, операторов логики и скобок:
SOME_SYMBOL = "To=/blah@blah/H & !(From=/blah@blah/H | Subject=/blah/H)"
+
Также можно использовать переменные:
$to_blah = "To=/blah@blah/H";
$from_blah = "From=/blah@blah/H";
$subject_blah = "Subject=/blah/H";
+
тогда предыдущее выражение будет таким
+
SOME_SYMBOL = "${to_blah} & !(${from_blah} | ${subject_blah})"
diff --git a/src/cfg_file.h b/src/cfg_file.h
index b484d5b0d..cc31f7a0c 100644
--- a/src/cfg_file.h
+++ b/src/cfg_file.h
@@ -50,7 +50,7 @@ enum rspamd_cred_type {
};
/**
- * Regexp type: /H - header, /M - mime, /U - url
+ * Regexp type: /H - header, /M - mime, /U - url /X - raw header
*/
enum rspamd_regexp_type {
REGEXP_NONE = 0,
@@ -58,6 +58,7 @@ enum rspamd_regexp_type {
REGEXP_MIME,
REGEXP_MESSAGE,
REGEXP_URL,
+ REGEXP_RAW_HEADER,
};
/**
diff --git a/src/cfg_utils.c b/src/cfg_utils.c
index 3d2ce611c..204ed65f6 100644
--- a/src/cfg_utils.c
+++ b/src/cfg_utils.c
@@ -656,6 +656,12 @@ parse_regexp (memory_pool_t *pool, char *line)
}
p ++;
break;
+ case 'X':
+ if (result->type == REGEXP_NONE || result->type == REGEXP_HEADER) {
+ result->type = REGEXP_RAW_HEADER;
+ }
+ p ++;
+ break;
/* Stop flags parsing */
default:
p = NULL;
diff --git a/src/main.h b/src/main.h
index 7b7c221ca..a13866657 100644
--- a/src/main.h
+++ b/src/main.h
@@ -185,6 +185,7 @@ struct worker_task {
int parts_count; /**< mime parts count */
GMimeMessage *message; /**< message, parsed with GMime */
GList *parts; /**< list of parsed parts */
+ char *raw_headers; /**< list of raw headers */
TAILQ_HEAD (uriq, uri) urls; /**< list of parsed urls */
GHashTable *results; /**< hash table of metric_result indexed by
* metric's name */
diff --git a/src/message.c b/src/message.c
index 4780a11ff..76743f7de 100644
--- a/src/message.c
+++ b/src/message.c
@@ -371,6 +371,16 @@ process_message (struct worker_task *task)
task->message_id = "undef";
}
+#ifdef GMIME24
+ task->raw_headers = g_mime_object_get_headers (GMIME_OBJECT (task->message));
+#else
+ task->raw_headers = g_mime_message_get_headers (task->message);
+#endif
+
+ if (task->raw_headers) {
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_free, task->raw_headers);
+ }
+
task->worker->srv->stat->messages_scanned ++;
/* free the parser (and the stream) */
diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c
index 06da6932f..9ef4e1ce3 100644
--- a/src/plugins/regexp.c
+++ b/src/plugins/regexp.c
@@ -138,7 +138,7 @@ regexp_module_reconfig (struct config_file *cfg)
static gsize
process_regexp (struct rspamd_regexp *re, struct worker_task *task)
{
- char *headerv;
+ char *headerv, *c, t;
struct mime_part *part;
GList *cur;
struct uri *url;
@@ -190,19 +190,60 @@ process_regexp (struct rspamd_regexp *re, struct worker_task *task)
}
return 0;
case REGEXP_MESSAGE:
- msg_debug ("process_message: checking message regexp: /%s/", re->regexp_text);
+ msg_debug ("process_regexp: checking message regexp: /%s/", re->regexp_text);
if (g_regex_match_full (re->regexp, task->msg->begin, task->msg->len, 0, 0, NULL, NULL) == TRUE) {
return 1;
}
return 0;
case REGEXP_URL:
- msg_debug ("process_url: checking url regexp: /%s/", re->regexp_text);
+ msg_debug ("process_regexp: checking url regexp: /%s/", re->regexp_text);
TAILQ_FOREACH (url, &task->urls, next) {
if (g_regex_match (re->regexp, struri (url), 0, NULL) == TRUE) {
return 1;
}
}
return 0;
+ case REGEXP_RAW_HEADER:
+ msg_debug ("process_regexp: checking for raw header: %s with regexp: /%s/", re->header, re->regexp_text);
+ if (task->raw_headers == NULL) {
+ msg_debug ("process_regexp: cannot check for raw header in message, no headers found");
+ return 0;
+ }
+ if ((headerv = strstr (task->raw_headers, re->header)) == NULL) {
+ /* No header was found */
+ return 0;
+ }
+ /* Skip header name and start matching after regexp */
+ headerv += strlen (re->header) + 1;
+ /* Now the main problem is to find position of end of raw header */
+ c = headerv;
+ while (*c) {
+ /* We need to handle all types of line end */
+ if ((*c == '\r' && *(c + 1) == '\n')) {
+ c ++;
+ /* Check for folding */
+ if (!g_ascii_isspace (*(c + 1))) {
+ c ++;
+ break;
+ }
+ }
+ else if (*c == '\r' || *c == '\n') {
+ if (!g_ascii_isspace (*(c + 1))) {
+ c ++;
+ break;
+ }
+ }
+ c ++;
+ }
+ /* Temporary null terminate this part of string */
+ t = *c;
+ *c = '\0';
+ if (g_regex_match (re->regexp, headerv, 0, NULL) == TRUE) {
+ *c = t;
+ return 1;
+ }
+ *c = t;
+ return 0;
}
/* Not reached */