From 3f7587fc5812c66f66bb1574507ba077e26e814c Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 21 Dec 2020 17:16:50 +0000 Subject: [PATCH] [Feature] Support SMIME signed messages container Issue: #3568 --- src/libmime/mime_parser.c | 81 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/src/libmime/mime_parser.c b/src/libmime/mime_parser.c index 213eb99d2..207bd4462 100644 --- a/src/libmime/mime_parser.c +++ b/src/libmime/mime_parser.c @@ -23,6 +23,8 @@ #include "multipattern.h" #include "contrib/libottery/ottery.h" #include "contrib/uthash/utlist.h" +#include +#include struct rspamd_mime_parser_lib_ctx { struct rspamd_multipattern *mp_boundary; @@ -77,8 +79,17 @@ static enum rspamd_mime_parse_error rspamd_mime_parse_normal_part (struct rspamd_task *task, struct rspamd_mime_part *part, struct rspamd_mime_parser_ctx *st, + struct rspamd_content_type *ct, GError **err); +static enum rspamd_mime_parse_error +rspamd_mime_process_multipart_node (struct rspamd_task *task, + struct rspamd_mime_parser_ctx *st, + struct rspamd_mime_part *multipart, + const gchar *start, const gchar *end, + gboolean is_finished, + GError **err); + #define RSPAMD_MIME_QUARK (rspamd_mime_parser_quark()) static GQuark @@ -575,6 +586,7 @@ static enum rspamd_mime_parse_error rspamd_mime_parse_normal_part (struct rspamd_task *task, struct rspamd_mime_part *part, struct rspamd_mime_parser_ctx *st, + struct rspamd_content_type *ct, GError **err) { rspamd_fstring_t *parsed; @@ -690,6 +702,67 @@ rspamd_mime_parse_normal_part (struct rspamd_task *task, part->raw_data.len, rspamd_cte_to_string (part->cte)); rspamd_mime_parser_calc_digest (part); + if (ct && (ct->flags & RSPAMD_CONTENT_TYPE_SMIME)) { + CMS_ContentInfo *cms; + const unsigned char *der_beg = part->parsed_data.begin; + cms = d2i_CMS_ContentInfo (NULL, &der_beg, part->parsed_data.len); + + if (cms) { + const ASN1_OBJECT *asn_ct = CMS_get0_eContentType (cms); + int ct_nid = OBJ_obj2nid (asn_ct); + + if (ct_nid == NID_pkcs7_data) { + BIO *bio = BIO_new_mem_buf (part->parsed_data.begin, + part->parsed_data.len); + + PKCS7 *p7; + p7 = d2i_PKCS7_bio (bio, NULL); + + if (p7) { + ct_nid = OBJ_obj2nid (p7->type); + + if (ct_nid == NID_pkcs7_signed) { + PKCS7 *p7_signed_content = p7->d.sign->contents; + + ct_nid = OBJ_obj2nid (p7_signed_content->type); + + if (ct_nid == NID_pkcs7_data) { + int ret; + + msg_debug_mime ("found an additional part inside of " + "smime structure of type %T/%T; length=%d", + &ct->type, &ct->subtype, p7_signed_content->d.data->length); + /* + * Since ASN.1 structures are freed, we need to copy + * the content + */ + gchar *cpy = rspamd_mempool_alloc (task->task_pool, + p7_signed_content->d.data->length); + memcpy (cpy, p7_signed_content->d.data->data, + p7_signed_content->d.data->length); + ret = rspamd_mime_process_multipart_node (task, + st, NULL, + cpy,cpy + p7_signed_content->d.data->length, + TRUE, err); + + PKCS7_free (p7); + BIO_free (bio); + CMS_ContentInfo_free (cms); + + return ret; + } + } + + PKCS7_free (p7); + } + + BIO_free (bio); + } + + CMS_ContentInfo_free (cms); + } + } + return RSPAMD_MIME_PARSE_OK; } @@ -839,13 +912,13 @@ rspamd_mime_process_multipart_node (struct rspamd_task *task, g_ptr_array_add (st->stack, npart); npart->part_type = RSPAMD_MIME_PART_MESSAGE; - if ((ret = rspamd_mime_parse_normal_part (task, npart, st, err)) + if ((ret = rspamd_mime_parse_normal_part (task, npart, st, sel, err)) == RSPAMD_MIME_PARSE_OK) { ret = rspamd_mime_parse_message (task, npart, st, err); } } else { - ret = rspamd_mime_parse_normal_part (task, npart, st, err); + ret = rspamd_mime_parse_normal_part (task, npart, st, sel, err); } return ret; @@ -1478,14 +1551,14 @@ rspamd_mime_parse_message (struct rspamd_task *task, ret = rspamd_mime_parse_multipart_part (task, npart, nst, err); } else if (sel->flags & RSPAMD_CONTENT_TYPE_MESSAGE) { - if ((ret = rspamd_mime_parse_normal_part (task, npart, nst, err)) + if ((ret = rspamd_mime_parse_normal_part (task, npart, nst, sel, err)) == RSPAMD_MIME_PARSE_OK) { npart->part_type = RSPAMD_MIME_PART_MESSAGE; ret = rspamd_mime_parse_message (task, npart, nst, err); } } else { - ret = rspamd_mime_parse_normal_part (task, npart, nst, err); + ret = rspamd_mime_parse_normal_part (task, npart, nst, sel, err); } if (ret != RSPAMD_MIME_PARSE_OK) { -- 2.39.5