On 27.02.2014 10:33, Michael Fischer v. Mollard wrote:
>
>
> -- Am 02/26/14 14:02:08 +0100 schrieb Wolfgang Breyha:
>
>> Jan Ingvoldstad wrote, on 26/02/14 13:45:
>>> Perhaps it would be relevant to check for other byte order marks as
>>> well:
>>>
>>> http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_ord
>>>
>>> er_marks_by_encoding
>>
>> I crosschecked with my cyrus logs ("invalid header characters")
>> meanwhile
>> and blocking only the UTF8 BOM seems to catch them all upfront. It looks
>> like a broken script spamming from several hacked webhosts.
>>
>> currently I use
>> # check for UTF-8 BOM (coming from SPAM)
>> warn condition = ${if
>> match{$message_headers_raw}{\N\xEF\xBB\xBF\N}} control =
>> freeze/no_tell
>> log_message = BOM detected
>> to get some more samples.
>>
>> Will change that to
>> deny condition = ${if
>> match{$message_headers_raw}{\N\xEF\xBB\xBF\N}} message =
>> Headers contain illegal BOM
>> log_message = BOM detected
>> later.
>
> Hi,
>
> that's a good idea. Thanks a lot.
>
> But nevertheless it might be a good idea to block 8 bit characters in
> header names via an ACL test as even RFC 6532 does not allow that.
>
Hello,
I attached a patch which implements a „verify = header_names“ test as
suggested above. At least it should be useful to users of cyrus imapd as
cyrus won't accept such mails.
Michael
diff --git a/src/src/acl.c b/src/src/acl.c
index 29e0617..eb9b962 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -1650,7 +1650,7 @@ switch (dns_lookup(&dnsa, target, type, NULL))
*************************************************/
enum { VERIFY_REV_HOST_LKUP, VERIFY_CERT, VERIFY_HELO, VERIFY_CSA, VERIFY_HDR_SYNTAX,
- VERIFY_NOT_BLIND, VERIFY_HDR_SNDR, VERIFY_SNDR, VERIFY_RCPT
+ VERIFY_NOT_BLIND, VERIFY_HDR_SNDR, VERIFY_SNDR, VERIFY_RCPT,VERIFY_HDR_NAMES
};
typedef struct {
uschar * name;
@@ -1670,7 +1670,8 @@ static verify_type_t verify_type_list[] = {
{ US"sender", VERIFY_SNDR, (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)
|(1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP),
FALSE, 6 },
- { US"recipient", VERIFY_RCPT, (1<<ACL_WHERE_RCPT), FALSE, 0 }
+ { US"recipient", VERIFY_RCPT, (1<<ACL_WHERE_RCPT), FALSE, 0 },
+ { US"header_names", VERIFY_HDR_NAMES, (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP), TRUE, 0 }
};
@@ -1820,6 +1821,15 @@ switch(vp->value)
*user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
return rc;
+ case VERIFY_HDR_NAMES:
+ /* Check that all header names are true 7 bit strings
+ See RFC 5322, 2.2. and RFC 6532, 3. */
+
+ rc = verify_check_header_names(log_msgptr);
+ if (rc != OK && smtp_return_error_details && *log_msgptr != NULL)
+ *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
+ return rc;
+
case VERIFY_NOT_BLIND:
/* Check that no recipient of this message is "blind", that is, every envelope
recipient must be mentioned in either To: or Cc:. */
@@ -2202,7 +2212,7 @@ return rc;
BAD_VERIFY:
*log_msgptr = string_sprintf("expected \"sender[=address]\", \"recipient\", "
- "\"helo\", \"header_syntax\", \"header_sender\" or "
+ "\"helo\", \"header_syntax\", \"header_sender\", \"header_names\" or "
"\"reverse_host_lookup\" at start of ACL condition "
"\"verify %s\"", arg);
return ERROR;
diff --git a/src/src/verify.c b/src/src/verify.c
index 711b3af..b77af03 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -2155,6 +2155,41 @@ return yield;
}
+/*************************************************
+* Check header names for 8-bit characters *
+*************************************************/
+
+/* This function checks for invalid charcters in header names. See
+RFC 5322, 2.2. and RFC 6532, 3.
+
+Arguments:
+ msgptr where to put an error message
+
+Returns: OK
+ FAIL
+*/
+
+int
+verify_check_header_names(uschar **msgptr)
+{
+header_line *h;
+uschar *colon, *s;
+
+for (h = header_list; h != NULL; h = h->next)
+ {
+ colon = Ustrchr(h->text, ':');
+ for(s = h->text; s < colon; s++)
+ {
+ if ((*s < 33) || (*s > 126))
+ {
+ *msgptr = string_sprintf("Invalid character in header \"%.*s\" found",
+ colon - h->text, h->text);
+ return FAIL;
+ }
+ }
+ }
+return OK;
+}
/*************************************************
* Check for blind recipients *