summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2018-03-19 13:13:19 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2018-03-19 13:25:58 +0000
commit9b8324626a4b23abc350e4b518e74dbcee85a428 (patch)
tree7f4c430353ecee6242d4387d688c5e85792ba334
parentae95563c52ef1b47454cc4043cbf3ceab0d8a928 (diff)
downloadrspamd-9b8324626a4b23abc350e4b518e74dbcee85a428.tar.gz
rspamd-9b8324626a4b23abc350e4b518e74dbcee85a428.zip
[Fix] Do not trust all issuers as a client certificate
Issue: #2087
-rw-r--r--src/libserver/milter.c60
-rw-r--r--src/libserver/milter.h12
-rw-r--r--src/libserver/protocol_internal.h1
-rw-r--r--src/rspamd_proxy.c24
4 files changed, 61 insertions, 36 deletions
diff --git a/src/libserver/milter.c b/src/libserver/milter.c
index fed948f0b..fca4d44fb 100644
--- a/src/libserver/milter.c
+++ b/src/libserver/milter.c
@@ -48,14 +48,7 @@
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 *
diff --git a/src/libserver/milter.h b/src/libserver/milter.h
index eae99eff2..131843755 100644
--- a/src/libserver/milter.h
+++ b/src/libserver/milter.h
@@ -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
diff --git a/src/libserver/protocol_internal.h b/src/libserver/protocol_internal.h
index 2b6c1e377..42552f789 100644
--- a/src/libserver/protocol_internal.h
+++ b/src/libserver/protocol_internal.h
@@ -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
diff --git a/src/rspamd_proxy.c b/src/rspamd_proxy.c
index 53e954a58..e3127f621 100644
--- a/src/rspamd_proxy.c
+++ b/src/rspamd_proxy.c
@@ -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);