summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2010-07-31 18:59:40 +0400
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2010-07-31 18:59:40 +0400
commit2a8b8ce671babd92cd60fbd70be9edf97cc20603 (patch)
treefe4c61979cd646544d5e2be1e89c8c8d9241e3af
parent7c778294a9625ee4954f784763495e05af513510 (diff)
downloadrspamd-2a8b8ce671babd92cd60fbd70be9edf97cc20603.tar.gz
rspamd-2a8b8ce671babd92cd60fbd70be9edf97cc20603.zip
* Write symbols weights to rspamc output
* Improve logic of selecting rspamc version * Do not try to parse broken DNS replies * Add 'raw' flag to FROM_EXCESS_BASE64 rule (requested by citrin)
-rw-r--r--conf/lua/regexp/headers.lua2
-rw-r--r--perl/lib/Mail/Rspamd/Client.pm6
-rwxr-xr-xrspamc.pl.in1
-rw-r--r--src/dns.c2
-rw-r--r--src/main.h2
-rw-r--r--src/protocol.c53
-rw-r--r--src/protocol.h1
7 files changed, 49 insertions, 18 deletions
diff --git a/conf/lua/regexp/headers.lua b/conf/lua/regexp/headers.lua
index d296b3653..4c415a2f3 100644
--- a/conf/lua/regexp/headers.lua
+++ b/conf/lua/regexp/headers.lua
@@ -77,7 +77,7 @@ reconf['TRACKER_ID'] = '/^[a-z0-9]{6,24}[-_a-z0-9]{2,36}[a-z0-9]{6,24}\\s*\\z/is
-- Regexp that checks that from header is encoded with base64 (search in raw headers)
local from_encoded_b64 = 'From=/\\=\\?\\S+\\?B\\?/iX'
-- From contains only 7bit characters (parsed headers are used)
-local from_needs_mime = 'From=/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f-\\xff]/H'
+local from_needs_mime = 'From=/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f-\\xff]/Hr'
-- Final rule
reconf['FROM_EXCESS_BASE64'] = string.format('%s & !%s', from_encoded_b64, from_needs_mime)
diff --git a/perl/lib/Mail/Rspamd/Client.pm b/perl/lib/Mail/Rspamd/Client.pm
index 789b3187d..4af7a02d9 100644
--- a/perl/lib/Mail/Rspamd/Client.pm
+++ b/perl/lib/Mail/Rspamd/Client.pm
@@ -35,7 +35,7 @@ $VERSION = "1.02";
my $EOL = "\015\012";
my $BLANK = $EOL x 2;
-my $PROTOVERSION = 'RSPAMC/1.0';
+my $PROTOVERSION = 'RSPAMC/1.2';
=head1 PUBLIC METHODS
@@ -953,14 +953,16 @@ sub _do_rspamc_command {
}
else {
foreach my $line (@lines) {
- if ($line =~ m!Metric: (\S+); (\S+); (\S+) / (\S+)!) {
+ if ($line =~ m!Metric: (\S+); (\S+); (\S+) / (\S+) (/ (\S+))?!) {
$metrics{$1} = {
isspam => $2,
score => $3 + 0,
threshold => $4 + 0,
+ reject_score => $6,
symbols => [],
urls => [],
messages => [],
+ action => 'no action',
};
$cur_metric = $1;
}
diff --git a/rspamc.pl.in b/rspamc.pl.in
index b2f6162d8..8d69e341a 100755
--- a/rspamc.pl.in
+++ b/rspamc.pl.in
@@ -288,6 +288,7 @@ if ($cmd =~ /(SYMBOLS|PROCESS|CHECK|URLS|EMAILS)/i) {
elsif ($cmd =~ /(STAT|LEARN|SHUTDOWN|RELOAD|UPTIME|COUNTERS|FUZZY_ADD|FUZZY_DEL|WEIGHTS)/i) {
$cfg{'command'} = $1;
$cfg{'control'} = 1;
+ $cfg{'hosts'} = ['localhost:11334'];
}
else {
die "unknown command $cmd";
diff --git a/src/dns.c b/src/dns.c
index 5197aae66..c50b9f388 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -771,7 +771,7 @@ dns_parse_rr (guint8 *in, union rspamd_reply_element *elt, guint8 **pos, struct
msg_info ("bad RR name");
return -1;
}
- if (p - *pos >= *remain - sizeof (guint16) * 5) {
+ if (p - *pos >= *remain - sizeof (guint16) * 5 || *remain <= 0) {
msg_info ("stripped dns reply");
return -1;
}
diff --git a/src/main.h b/src/main.h
index e35a7eea3..697c63f47 100644
--- a/src/main.h
+++ b/src/main.h
@@ -173,7 +173,7 @@ struct worker_task {
} state; /**< current session state */
size_t content_length; /**< length of user's input */
enum rspamd_protocol proto; /**< protocol (rspamc or spamc) */
- const char *proto_ver; /**< protocol version */
+ guint proto_ver; /**< protocol version */
enum rspamd_command cmd; /**< command */
struct custom_command *custom_cmd; /**< custom command if any */
int sock; /**< socket descriptor */
diff --git a/src/protocol.c b/src/protocol.c
index cb79b258c..297aaa922 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -92,6 +92,20 @@ static GList *custom_commands = NULL;
/* For default metric, dirty hack, but much faster than hash lookup */
static double default_score, default_required_score;
+G_INLINE_FUNC const char *
+rspamc_proto_str (guint ver)
+{
+ if (ver >= 12) {
+ return "1.2";
+ }
+ else if (ver >= 11) {
+ return "1.1";
+ }
+ else {
+ return "1.0";
+ }
+}
+
static char *
separate_command (f_str_t * in, char c)
{
@@ -120,7 +134,7 @@ parse_command (struct worker_task *task, f_str_t * line)
struct custom_command *cmd;
GList *cur;
- task->proto_ver = RSPAMC_PROTO_1_1;
+ task->proto_ver = 11;
token = separate_command (line, ' ');
if (line == NULL || token == NULL) {
debug_task ("bad command");
@@ -202,12 +216,15 @@ parse_command (struct worker_task *task, f_str_t * line)
if (g_ascii_strncasecmp (line->begin, RSPAMC_GREETING, sizeof (RSPAMC_GREETING) - 1) == 0) {
task->proto = RSPAMC_PROTO;
- task->proto_ver = RSPAMC_PROTO_1_0;
+ task->proto_ver = 10;
if (*(line->begin + sizeof (RSPAMC_GREETING) - 1) == '/') {
/* Extract protocol version */
token = line->begin + sizeof (RSPAMC_GREETING);
if (strncmp (token, RSPAMC_PROTO_1_1, sizeof (RSPAMC_PROTO_1_1) - 1) == 0) {
- task->proto_ver = RSPAMC_PROTO_1_1;
+ task->proto_ver = 11;
+ }
+ else if (strncmp (token, RSPAMC_PROTO_1_2, sizeof (RSPAMC_PROTO_1_2) - 1) == 0) {
+ task->proto_ver = 12;
}
}
}
@@ -529,7 +546,12 @@ metric_symbols_callback (gpointer key, gpointer value, void *user_data)
}
if (s->options) {
- r = rspamd_snprintf (outbuf, OUTBUFSIZ, "Symbol: %s; ", (char *)key);
+ if (task->proto_ver >= 12) {
+ r = rspamd_snprintf (outbuf, OUTBUFSIZ, "Symbol: %s(%.2f); ", (char *)key, s->score);
+ }
+ else {
+ r = rspamd_snprintf (outbuf, OUTBUFSIZ, "Symbol: %s; ", (char *)key);
+ }
cur = s->options;
while (cur) {
if (g_list_next (cur)) {
@@ -547,7 +569,12 @@ metric_symbols_callback (gpointer key, gpointer value, void *user_data)
}
}
else {
- r = rspamd_snprintf (outbuf, OUTBUFSIZ, "Symbol: %s" CRLF, (char *)key);
+ if (task->proto_ver >= 12) {
+ r = rspamd_snprintf (outbuf, OUTBUFSIZ, "Symbol: %s(%.2f)" CRLF, (char *)key, s->score);
+ }
+ else {
+ r = rspamd_snprintf (outbuf, OUTBUFSIZ, "Symbol: %s" CRLF, (char *)key);
+ }
}
cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "%s,", (char *)key);
@@ -670,7 +697,7 @@ show_metric_result (gpointer metric_name, gpointer metric_value, void *user_data
r = rspamd_snprintf (outbuf, sizeof (outbuf), "Spam: False ; 0 / %.2f" CRLF, ms);
}
else {
- if (strcmp (task->proto_ver, RSPAMC_PROTO_1_1) == 0) {
+ if (task->proto_ver >= 11) {
if (!task->is_skipped) {
r = rspamd_snprintf (outbuf, sizeof (outbuf), "Metric: default; False; 0 / %.2f / %.2f" CRLF, ms, rs);
}
@@ -709,7 +736,7 @@ show_metric_result (gpointer metric_name, gpointer metric_value, void *user_data
r = rspamd_snprintf (outbuf, sizeof (outbuf), "Spam: %s ; %.2f / %.2f" CRLF, (is_spam) ? "True" : "False", metric_res->score, ms);
}
else {
- if (strcmp (task->proto_ver, RSPAMC_PROTO_1_1) == 0) {
+ if (task->proto_ver >= 11) {
if (!task->is_skipped) {
r = rspamd_snprintf (outbuf, sizeof (outbuf), "Metric: %s; %s; %.2f / %.2f / %.2f" CRLF,
(char *)metric_name, (is_spam) ? "True" : "False", metric_res->score, ms, rs);
@@ -793,7 +820,7 @@ write_check_reply (struct worker_task *task)
struct metric_callback_data cd;
r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s/%s 0 %s" CRLF, (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER,
- task->proto_ver, "OK");
+ rspamc_proto_str (task->proto_ver), "OK");
if (! rspamd_dispatcher_write (task->dispatcher, outbuf, r, TRUE, FALSE)) {
return FALSE;
}
@@ -882,7 +909,7 @@ write_process_reply (struct worker_task *task)
r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s/%s 0 %s" CRLF "Content-Length: %zd" CRLF CRLF,
(task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER,
- task->proto_ver, "OK", task->msg->len);
+ rspamc_proto_str (task->proto_ver), "OK", task->msg->len);
cd.task = task;
cd.log_buf = logbuf;
@@ -970,12 +997,12 @@ write_reply (struct worker_task *task)
/* Write error message and error code to reply */
if (task->proto == SPAMC_PROTO) {
r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s/%s %d %s" CRLF CRLF,
- SPAMD_REPLY_BANNER, task->proto_ver, task->error_code, SPAMD_ERROR);
+ SPAMD_REPLY_BANNER, rspamc_proto_str (task->proto_ver), task->error_code, SPAMD_ERROR);
debug_task ("writing error: %s", outbuf);
}
else {
r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s/%s %d %s" CRLF "%s: %s" CRLF CRLF,
- RSPAMD_REPLY_BANNER, task->proto_ver, task->error_code, SPAMD_ERROR, ERROR_HEADER, task->last_error);
+ RSPAMD_REPLY_BANNER, rspamc_proto_str (task->proto_ver), task->error_code, SPAMD_ERROR, ERROR_HEADER, task->last_error);
debug_task ("writing error: %s", outbuf);
}
/* Write to bufferevent error message */
@@ -994,12 +1021,12 @@ write_reply (struct worker_task *task)
break;
case CMD_SKIP:
r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s/%s 0 %s" CRLF,
- (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, task->proto_ver, SPAMD_OK);
+ (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, rspamc_proto_str (task->proto_ver), SPAMD_OK);
return rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE);
break;
case CMD_PING:
r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s/%s 0 PONG" CRLF,
- (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, task->proto_ver);
+ (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, rspamc_proto_str (task->proto_ver));
return rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE);
break;
case CMD_OTHER:
diff --git a/src/protocol.h b/src/protocol.h
index d45e5c555..c216259f6 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -15,6 +15,7 @@
#define RSPAMC_PROTO_1_0 "1.0"
#define RSPAMC_PROTO_1_1 "1.1"
+#define RSPAMC_PROTO_1_2 "1.2"
/*
* Reply messages