aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libmime/email_addr.c26
-rw-r--r--src/libmime/email_addr.h13
-rw-r--r--src/libmime/message.h1
-rw-r--r--src/ragel/smtp_received.rl5
-rw-r--r--src/ragel/smtp_received_parser.rl61
5 files changed, 71 insertions, 35 deletions
diff --git a/src/libmime/email_addr.c b/src/libmime/email_addr.c
index 8376e8f78..3b9f31de9 100644
--- a/src/libmime/email_addr.c
+++ b/src/libmime/email_addr.c
@@ -485,3 +485,29 @@ rspamd_email_address_list_destroy (gpointer ptr)
g_ptr_array_free (ar, TRUE);
}
+
+void rspamd_smtp_maybe_process_smtp_comment (struct rspamd_task *task,
+ const char *data, size_t len,
+ struct received_header *rh)
+{
+ if (!rh->by_hostname) {
+ /* Heuristic to detect IP addresses like in Exim received:
+ * [xxx]:port or [xxx]
+ */
+
+ if (*data == '[' && len > 2) {
+ const gchar *p = data + 1;
+ gsize iplen = rspamd_memcspn (p, "]", len - 1);
+
+ if (iplen > 0) {
+ guchar tbuf[sizeof(struct in6_addr) + sizeof(guint32)];
+
+ if (rspamd_parse_inet_address_ip4 (p, iplen, tbuf) ||
+ rspamd_parse_inet_address_ip6 (p, iplen, tbuf)) {
+ rh->comment_ip = rspamd_mempool_alloc (task->task_pool, iplen + 1);
+ rspamd_strlcpy (rh->comment_ip, p, iplen + 1);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/libmime/email_addr.h b/src/libmime/email_addr.h
index 8c9b54713..129d2ba44 100644
--- a/src/libmime/email_addr.h
+++ b/src/libmime/email_addr.h
@@ -51,6 +51,19 @@ struct rspamd_email_address {
guchar flags;
};
+struct received_header;
+struct rspamd_task;
+/**
+ * Try to parse SMTP comment to process stupid Exim received headers
+ * @param task
+ * @param data
+ * @param len
+ * @param rh
+ */
+void rspamd_smtp_maybe_process_smtp_comment (struct rspamd_task *task,
+ const char *data, size_t len,
+ struct received_header *rh);
+
/**
* Create email address from a single rfc822 address (e.g. from mail from:)
* @param str string to use
diff --git a/src/libmime/message.h b/src/libmime/message.h
index 205bf5bb2..17077860d 100644
--- a/src/libmime/message.h
+++ b/src/libmime/message.h
@@ -144,6 +144,7 @@ struct received_header {
gchar *real_ip;
gchar *by_hostname;
gchar *for_mbox;
+ gchar *comment_ip;
rspamd_inet_addr_t *addr;
struct rspamd_mime_header *hdr;
time_t timestamp;
diff --git a/src/ragel/smtp_received.rl b/src/ragel/smtp_received.rl
index b13259fed..f43ad167c 100644
--- a/src/ragel/smtp_received.rl
+++ b/src/ragel/smtp_received.rl
@@ -24,12 +24,9 @@
( address_literal >Real_Domain_Start %Real_Domain_End FWS "(" TCP_info ")" ) |
address_literal >Real_IP_Start %Real_IP_End; # Not RFC conforming, but many MTA try this
- exim_real_ip = "[" (IPv4_addr|IPv6_simple) >IP4_start %IP4_end "]"
- >Real_IP_Start %Real_IP_End (":" digit{1,4})?;
- exim_content = exim_real_ip;
ccontent = ctext | FWS | '(' @{ fcall balanced_ccontent; };
balanced_ccontent := ccontent* ')' @{ fret; };
- comment = "(" (FWS? ccontent|exim_content)* FWS? ")";
+ comment = "(" ((FWS? ccontent)* FWS?) >Comment_Start %Comment_End ")";
CFWS = ((FWS? comment)+ FWS?) | FWS;
From_domain = "FROM"i FWS Extended_Domain >From_Start %From_End;
diff --git a/src/ragel/smtp_received_parser.rl b/src/ragel/smtp_received_parser.rl
index 565a20b7f..836a02384 100644
--- a/src/ragel/smtp_received_parser.rl
+++ b/src/ragel/smtp_received_parser.rl
@@ -100,33 +100,19 @@
}
action Real_IP_Start {
- if (real_ip_end == NULL) {
+ if (real_ip_end == NULL && real_ip_start == NULL) {
real_ip_start = p;
}
}
action Real_IP_End {
- if (ip_start && ip_end && ip_end > ip_start) {
- real_ip_start = ip_start;
- real_ip_end = ip_end;
- }
- else {
- real_ip_end = p;
- }
-
- ip_start = NULL;
- ip_end = NULL;
- }
- action Reported_IP_Start {
- reported_ip_start = p;
- }
- action Reported_IP_End {
-
- if (ip_start && ip_end && ip_end > ip_start) {
- reported_ip_start = ip_start;
- reported_ip_end = ip_end;
- }
- else {
- reported_ip_end = p;
+ if (real_ip_end == NULL && real_ip_start != NULL) {
+ if (ip_start && ip_end && ip_end > ip_start) {
+ real_ip_start = ip_start;
+ real_ip_end = ip_end;
+ }
+ else {
+ real_ip_end = p;
+ }
}
ip_start = NULL;
@@ -225,6 +211,21 @@
}
}
+ action Comment_Start {
+ cstart = p;
+ }
+
+ action Comment_End {
+ cend = p;
+
+ if (cend && cstart && cend > cstart) {
+ rspamd_smtp_maybe_process_smtp_comment (task, cstart, cend - cstart, rh);
+ }
+
+ cend = NULL;
+ cstart = NULL;
+ }
+
include smtp_whitespace "smtp_whitespace.rl";
include smtp_ip "smtp_ip.rl";
include smtp_date "smtp_date.rl";
@@ -246,9 +247,8 @@ rspamd_smtp_received_parse (struct rspamd_task *task, const char *data, size_t l
const char *real_domain_start, *real_domain_end,
*real_ip_start, *real_ip_end,
*reported_domain_start, *reported_domain_end,
- *reported_ip_start, *reported_ip_end,
*ip_start, *ip_end, *date_start,
- *for_start, *for_end, *tmp;
+ *for_start, *for_end, *tmp, *cstart, *cend;
struct tm tm;
const char *p = data, *pe = data + len, *eof;
int cs, in_v6 = 0, *stack = NULL;
@@ -269,13 +269,13 @@ rspamd_smtp_received_parse (struct rspamd_task *task, const char *data, size_t l
real_ip_end = NULL;
reported_domain_start = NULL;
reported_domain_end = NULL;
- reported_ip_start = NULL;
- reported_ip_end = NULL;
ip_start = NULL;
ip_end = NULL;
date_start = NULL;
for_start = NULL;
for_end = NULL;
+ cstart = NULL;
+ cend = NULL;
rh->type = RSPAMD_RECEIVED_UNKNOWN;
memset (&for_addr, 0, sizeof (for_addr));
@@ -290,10 +290,9 @@ rspamd_smtp_received_parse (struct rspamd_task *task, const char *data, size_t l
rh->real_ip = rspamd_mempool_alloc (task->task_pool, tmplen + 1);
rspamd_strlcpy (rh->real_ip, real_ip_start, tmplen + 1);
}
- if (reported_ip_end && reported_ip_start && reported_ip_end > reported_ip_start) {
- tmplen = reported_ip_end - reported_ip_start;
- rh->from_ip = rspamd_mempool_alloc (task->task_pool, tmplen + 1);
- rspamd_strlcpy (rh->from_ip, reported_ip_start, tmplen + 1);
+
+ if (!rh->real_ip && rh->comment_ip) {
+ rh->real_ip = rh->comment_ip;
}
if (rh->real_ip && !rh->from_ip) {