diff options
-rw-r--r-- | rules/misc.lua | 18 | ||||
-rw-r--r-- | rules/regexp/headers.lua | 3 | ||||
-rw-r--r-- | src/libmime/message.h | 15 | ||||
-rw-r--r-- | src/libmime/mime_expressions.c | 42 | ||||
-rw-r--r-- | src/libmime/mime_parser.c | 25 | ||||
-rw-r--r-- | src/lua/lua_html.c | 1 | ||||
-rw-r--r-- | src/lua/lua_mimepart.c | 26 |
7 files changed, 93 insertions, 37 deletions
diff --git a/rules/misc.lua b/rules/misc.lua index 28fb19f5c..151500d88 100644 --- a/rules/misc.lua +++ b/rules/misc.lua @@ -716,13 +716,15 @@ local check_mime_id = rspamd_config:register_callback_symbol('CHECK_MIME', 1.0, -- Make sure there is a MIME-Version header local mv = task:get_header('MIME-Version') + local missing_mime = false if (not mv) then - task:insert_result('MISSING_MIME_VERSION', 1.0) + missing_mime = true end local found_ma = false local found_plain = false local found_html = false + local cte_7bit = false for _,p in ipairs(parts) do local mtype,subtype = p:get_type() @@ -731,13 +733,27 @@ local check_mime_id = rspamd_config:register_callback_symbol('CHECK_MIME', 1.0, found_ma = true end if (ctype == 'text/plain') then + if p:get_cte() == '7bit' then + cte_7bit = true + end found_plain = true end if (ctype == 'text/html') then + if p:get_cte() == '7bit' then + cte_7bit = true + end found_html = true end end + if missing_mime then + if not found_ma and ((found_plain or found_html) and cte_7bit) then + -- Skip symbol insertion + else + task:insert_result('MISSING_MIME_VERSION', 1.0) + end + end + if (found_ma) then if (not found_plain) then task:insert_result('MIME_MA_MISSING_TEXT', 1.0) diff --git a/rules/regexp/headers.lua b/rules/regexp/headers.lua index 30ccd5d0f..f58feeaf8 100644 --- a/rules/regexp/headers.lua +++ b/rules/regexp/headers.lua @@ -107,7 +107,8 @@ reconf['R_RCVD_SPAMBOTS'] = { -- Charset is missing in message reconf['R_MISSING_CHARSET'] = { - re = string.format('content_type_is_type(text) & !content_type_has_param(charset) & !%s', r_cte_7bit), + re = string.format('content_type_is_type(text) & !content_type_has_param(charset) & !%s', + r_cte_7bit), score = 2.5, description = 'Charset is missing in a message', group = 'header' diff --git a/src/libmime/message.h b/src/libmime/message.h index 6004d1759..03e0e8345 100644 --- a/src/libmime/message.h +++ b/src/libmime/message.h @@ -163,4 +163,19 @@ GPtrArray *rspamd_message_get_header_from_hash (GHashTable *htb, const gchar *field, gboolean strong); + +/** + * Converts string to cte + * @param str + * @return + */ +enum rspamd_cte rspamd_cte_from_string (const gchar *str); + +/** + * Converts cte to string + * @param ct + * @return + */ +const gchar* rspamd_cte_to_string (enum rspamd_cte ct); + #endif diff --git a/src/libmime/mime_expressions.c b/src/libmime/mime_expressions.c index 8a5672459..71b8d4bdc 100644 --- a/src/libmime/mime_expressions.c +++ b/src/libmime/mime_expressions.c @@ -1252,11 +1252,10 @@ rspamd_compare_transfer_encoding (struct rspamd_task * task, GArray * args, void *unused) { - GPtrArray *headerlist; struct expression_argument *arg; guint i; - struct rspamd_mime_header *rh; - static const char *hname = "Content-Transfer-Encoding"; + struct rspamd_mime_part *part; + enum rspamd_cte cte; if (args == NULL) { msg_warn_task ("no parameters to function"); @@ -1269,39 +1268,16 @@ rspamd_compare_transfer_encoding (struct rspamd_task * task, return FALSE; } - headerlist = rspamd_message_get_header_array (task, hname, FALSE); + cte = rspamd_cte_from_string (arg->data); - if (headerlist) { - for (i = 0; i < headerlist->len; i ++) { - rh = g_ptr_array_index (headerlist, i); - - if (rh->decoded == NULL) { - continue; - } - - if (g_ascii_strcasecmp (rh->decoded, arg->data) == 0) { - return TRUE; - } - } + if (cte == RSPAMD_CTE_UNKNOWN) { + msg_warn_task ("unknown cte: %s", arg->data); + return FALSE; } - /* - * In fact, we need to check 'Content-Transfer-Encoding' for each part - * as gmime has 'strange' assumptions - */ - headerlist = rspamd_message_get_mime_header_array (task, - arg->data, - FALSE); - - if (headerlist) { - for (i = 0; i < headerlist->len; i ++) { - rh = g_ptr_array_index (headerlist, i); - - if (rh->decoded == NULL) { - continue; - } - - if (g_ascii_strcasecmp (rh->decoded, arg->data) == 0) { + PTR_ARRAY_FOREACH (task->parts, i, part) { + if (IS_CT_TEXT (part->ct)) { + if (part->cte == cte) { return TRUE; } } diff --git a/src/libmime/mime_parser.c b/src/libmime/mime_parser.c index b16983287..a9bb0748a 100644 --- a/src/libmime/mime_parser.c +++ b/src/libmime/mime_parser.c @@ -81,7 +81,7 @@ rspamd_mime_parser_quark (void) return g_quark_from_static_string ("mime-parser"); } -static const gchar* +const gchar* rspamd_cte_to_string (enum rspamd_cte ct) { const gchar *ret = "unknown"; @@ -106,6 +106,29 @@ rspamd_cte_to_string (enum rspamd_cte ct) return ret; } +enum rspamd_cte +rspamd_cte_from_string (const gchar *str) +{ + enum rspamd_cte ret = RSPAMD_CTE_UNKNOWN; + + g_assert (str != NULL); + + if (strcmp (str, "7bit") == 0) { + ret = RSPAMD_CTE_7BIT; + } + else if (strcmp (str, "8bit") == 0) { + ret = RSPAMD_CTE_8BIT; + } + else if (strcmp (str, "quoted-printable") == 0) { + ret = RSPAMD_CTE_QP; + } + else if (strcmp (str, "base64") == 0) { + ret = RSPAMD_CTE_B64; + } + + return ret; +} + static void rspamd_mime_parser_init_lib (void) { diff --git a/src/lua/lua_html.c b/src/lua/lua_html.c index 0ec561338..65fb99326 100644 --- a/src/lua/lua_html.c +++ b/src/lua/lua_html.c @@ -354,6 +354,7 @@ lua_html_push_block (lua_State *L, struct html_block *bl) if (bl->style.len > 0) { lua_pushstring (L, "style"); t = lua_newuserdata (L, sizeof (*t)); + rspamd_lua_setclass (L, "rspamd{text}", -1); t->start = bl->style.start; t->len = bl->style.len; t->flags = 0; diff --git a/src/lua/lua_mimepart.c b/src/lua/lua_mimepart.c index 1ff3dbd58..8a9fb85e1 100644 --- a/src/lua/lua_mimepart.c +++ b/src/lua/lua_mimepart.c @@ -226,9 +226,17 @@ LUA_FUNCTION_DEF (mimepart, get_length); /*** * @method mime_part:get_type() * Extract content-type string of the mime part - * @return {string} content type in form 'type/subtype' + * @return {string,string} content type in form 'type','subtype' */ LUA_FUNCTION_DEF (mimepart, get_type); + +/*** + * @method mime_part:get_cte() + * Extract content-transfer-encoding for a part + * @return {string} content transfer encoding (e.g. `base64` or `7bit`) + */ +LUA_FUNCTION_DEF (mimepart, get_cte); + /*** * @method mime_part:get_filename() * Extract filename associated with mime part if it is an attachement @@ -304,6 +312,7 @@ static const struct luaL_reg mimepartlib_m[] = { LUA_INTERFACE_DEF (mimepart, get_content), LUA_INTERFACE_DEF (mimepart, get_length), LUA_INTERFACE_DEF (mimepart, get_type), + LUA_INTERFACE_DEF (mimepart, get_cte), LUA_INTERFACE_DEF (mimepart, get_filename), LUA_INTERFACE_DEF (mimepart, get_header), LUA_INTERFACE_DEF (mimepart, get_header_raw), @@ -689,6 +698,21 @@ lua_mimepart_get_type (lua_State * L) } static gint +lua_mimepart_get_cte (lua_State * L) +{ + struct rspamd_mime_part *part = lua_check_mimepart (L); + + if (part == NULL) { + lua_pushnil (L); + return 1; + } + + lua_pushstring (L, rspamd_cte_to_string (part->cte)); + + return 1; +} + +static gint lua_mimepart_get_filename (lua_State * L) { struct rspamd_mime_part *part = lua_check_mimepart (L); |