]> source.dussan.org Git - rspamd.git/commitdiff
[Fix] Do not trust all issuers as a client certificate
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 19 Mar 2018 13:13:19 +0000 (13:13 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 19 Mar 2018 13:25:58 +0000 (13:25 +0000)
Issue: #2087

src/libserver/milter.c
src/libserver/milter.h
src/libserver/protocol_internal.h
src/rspamd_proxy.c

index fed948f0bc1835d12e3c83f729db57aed30b064a..fca4d44fb80b045f8e2444f061525c1d196745f8 100644 (file)
 
 INIT_LOG_MODULE(milter)
 
-struct rspamd_milter_context {
-       gchar *spam_header;
-       void *sessions_cache;
-       gboolean discard_on_reject;
-       gboolean quarantine_on_reject;
-};
-
-static struct rspamd_milter_context *milter_ctx = NULL;
+static const struct rspamd_milter_context *milter_ctx = NULL;
 
 static gboolean  rspamd_milter_handle_session (
                struct rspamd_milter_session *session,
@@ -1301,6 +1294,7 @@ rspamd_milter_macro_http (struct rspamd_milter_session *session,
                struct rspamd_http_message *msg)
 {
        rspamd_ftok_t *found, srch;
+       struct rspamd_milter_private *priv = session->priv;
 
        /*
         * We assume postfix macros here, sendmail ones might be slightly
@@ -1353,9 +1347,32 @@ rspamd_milter_macro_http (struct rspamd_milter_session *session,
                                found->begin, found->len);
        }
 
-       IF_MACRO("{cert_subject}") {
-               rspamd_http_message_add_header_len (msg, USER_HEADER,
-                               found->begin, found->len);
+       if (milter_ctx->client_ca_name) {
+               IF_MACRO ("{cert_issuer}") {
+                       rspamd_http_message_add_header_len (msg, CERT_ISSUER_HEADER,
+                                       found->begin, found->len);
+
+                       if (found->len == strlen (milter_ctx->client_ca_name) &&
+                                       rspamd_cryptobox_memcmp (found->begin,
+                                                       milter_ctx->client_ca_name, found->len) == 0) {
+                               msg_debug_milter ("process certificate issued by %T", found);
+                               IF_MACRO("{cert_subject}") {
+                                       rspamd_http_message_add_header_len (msg, USER_HEADER,
+                                                       found->begin, found->len);
+                               }
+                       }
+                       else {
+                               msg_debug_milter ("skip certificate issued by %T", found);
+                       }
+
+
+               }
+       }
+       else {
+               IF_MACRO ("{cert_issuer}") {
+                       rspamd_http_message_add_header_len (msg, CERT_ISSUER_HEADER,
+                                       found->begin, found->len);
+               }
        }
 
        if (!session->hostname || session->hostname->len == 0) {
@@ -1838,26 +1855,9 @@ cleanup:
 }
 
 void
-rspamd_milter_init_library (const gchar *spam_header, void *sessions_cache,
-               gboolean discard_on_reject, gboolean quarantine_on_reject)
+rspamd_milter_init_library (const struct rspamd_milter_context *ctx)
 {
-       if (milter_ctx) {
-               g_free (milter_ctx->spam_header);
-               g_free (milter_ctx);
-       }
-
-       milter_ctx = g_malloc (sizeof (*milter_ctx));
-
-       if (spam_header) {
-               milter_ctx->spam_header = g_strdup (spam_header);
-       }
-       else {
-               milter_ctx->spam_header = g_strdup (RSPAMD_MILTER_SPAM_HEADER);
-       }
-
-       milter_ctx->sessions_cache = sessions_cache;
-       milter_ctx->discard_on_reject = discard_on_reject;
-       milter_ctx->quarantine_on_reject = quarantine_on_reject;
+       milter_ctx = ctx;
 }
 
 rspamd_mempool_t *
index eae99eff21a400baae7cd538001ec650c6f44db2..131843755d0b687196b479474b7ad876537628d6 100644 (file)
@@ -44,6 +44,14 @@ struct rspamd_email_address;
 struct event_base;
 struct rspamd_http_message;
 
+struct rspamd_milter_context {
+       const gchar *spam_header;
+       const gchar *client_ca_name;
+       void *sessions_cache;
+       gboolean discard_on_reject;
+       gboolean quarantine_on_reject;
+};
+
 struct rspamd_milter_session {
        GHashTable *macros;
        rspamd_inet_addr_t *addr;
@@ -151,9 +159,7 @@ void rspamd_milter_send_task_results (struct rspamd_milter_session *session,
  * Init internal milter context
  * @param spam_header spam header name (must NOT be NULL)
  */
-void rspamd_milter_init_library (const gchar *spam_header,
-               void *sessions_cache, gboolean discard_on_reject,
-               gboolean quarantine_on_reject);
+void rspamd_milter_init_library (const struct rspamd_milter_context *ctx);
 
 /**
  * Returns pool for a session
index 2b6c1e377f207de8930fe49a2ef2358111b7a8a8..42552f78936426ad38d3b99d21bf1dde87f4e83a 100644 (file)
@@ -81,5 +81,6 @@
 #define MTA_NAME_HEADER "MTA-Name"
 #define MILTER_HEADER "Milter"
 #define FILENAME_HEADER "Filename"
+#define CERT_ISSUER_HEADER "TLS-Cert-Issuer"
 
 #endif //RSPAMD_PROTOCOL_INTERNAL_H
index 53e954a5836616da3159b807fe05f63b59f90125..e3127f621181b2eb2aa7133a5d2e2681403a6c1c 100644 (file)
@@ -34,6 +34,7 @@
 #include "ottery.h"
 #include "unix-std.h"
 #include "libserver/milter.h"
+#include "libserver/milter_internal.h"
 #include "libmime/lang_detection.h"
 #include "contrib/zstd/zstd.h"
 
@@ -147,8 +148,11 @@ struct rspamd_proxy_ctx {
        gboolean quarantine_on_reject;
        /* Milter spam header */
        gchar *spam_header;
+       /* CA name that can be used for client certificates */
+       gchar *client_ca_name;
        /* Sessions cache */
        void *sessions_cache;
+       struct rspamd_milter_context milter_ctx;
        /* Language detector */
        struct rspamd_lang_detector *lang_det;
 };
@@ -744,6 +748,7 @@ init_rspamd_proxy (struct rspamd_config *cfg)
        rspamd_mempool_add_destructor (cfg->cfg_pool,
                        (rspamd_mempool_destruct_t)rspamd_array_free_hard, ctx->cmp_refs);
        ctx->max_retries = DEFAULT_RETRIES;
+       ctx->spam_header = RSPAMD_MILTER_SPAM_HEADER;
 
        rspamd_rcl_register_worker_option (cfg,
                        type,
@@ -834,7 +839,15 @@ init_rspamd_proxy (struct rspamd_config *cfg)
                        ctx,
                        G_STRUCT_OFFSET (struct rspamd_proxy_ctx, spam_header),
                        0,
-                       "Use the specific spam header instead of X-Spam");
+                       "Use the specific spam header (default: X-Spam)");
+       rspamd_rcl_register_worker_option (cfg,
+                       type,
+                       "client_ca_name",
+                       rspamd_rcl_parse_struct_string,
+                       ctx,
+                       G_STRUCT_OFFSET (struct rspamd_proxy_ctx, client_ca_name),
+                       0,
+                       "Allow certificates issued by this CA to be treated as client certificates");
 
        return ctx;
 }
@@ -2160,8 +2173,13 @@ start_rspamd_proxy (struct rspamd_worker *worker) {
                                ctx->ev_base);
        }
 
-       rspamd_milter_init_library (ctx->spam_header, ctx->sessions_cache,
-                       ctx->discard_on_reject, ctx->quarantine_on_reject);
+       ctx->milter_ctx.spam_header = ctx->spam_header;
+       ctx->milter_ctx.discard_on_reject = ctx->discard_on_reject;
+       ctx->milter_ctx.quarantine_on_reject = ctx->quarantine_on_reject;
+       ctx->milter_ctx.sessions_cache = ctx->sessions_cache;
+       ctx->milter_ctx.client_ca_name = ctx->client_ca_name;
+       rspamd_milter_init_library (&ctx->milter_ctx);
+
        rspamd_lua_run_postloads (ctx->cfg->lua_state, ctx->cfg, ctx->ev_base,
                        worker);