commit 3f7587f: [Feature] Support SMIME signed messages container
Vsevolod Stakhov
vsevolod at highsecure.ru
Mon Dec 21 17:21:09 UTC 2020
Author: Vsevolod Stakhov
Date: 2020-12-21 17:16:50 +0000
URL: https://github.com/rspamd/rspamd/commit/3f7587fc5812c66f66bb1574507ba077e26e814c (HEAD -> master)
[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 <openssl/cms.h>
+#include <openssl/pkcs7.h>
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) {
More information about the Commits
mailing list