commit 9e61dce: [Feature] Implement configurable limits for SPF lookups
Vsevolod Stakhov
vsevolod at highsecure.ru
Fri Oct 25 08:35:06 UTC 2019
Author: Vsevolod Stakhov
Date: 2019-10-25 09:22:43 +0100
URL: https://github.com/rspamd/rspamd/commit/9e61dce1b503b21f85ee24378aa4a3383680e792
[Feature] Implement configurable limits for SPF lookups
---
src/libserver/spf.c | 67 +++++++++++++++++++++++++++++++++++++++++++++--------
src/libserver/spf.h | 8 +++++++
2 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/src/libserver/spf.c b/src/libserver/spf.c
index 631594808..d362a7293 100644
--- a/src/libserver/spf.c
+++ b/src/libserver/spf.c
@@ -39,10 +39,6 @@
#define SPF_REDIRECT "redirect"
#define SPF_EXP "exp"
-/** SPF limits for avoiding abuse **/
-#define SPF_MAX_NESTING 10
-#define SPF_MAX_DNS_REQUESTS 30
-
struct spf_resolved_element {
GPtrArray *elts;
gchar *cur_domain;
@@ -66,6 +62,14 @@ struct spf_record {
gboolean done;
};
+struct rspamd_spf_library_ctx {
+ guint max_dns_nesting;
+ guint max_dns_requests;
+ guint min_cache_ttl;
+};
+
+struct rspamd_spf_library_ctx *spf_lib_ctx = NULL;
+
/**
* BNF for SPF record:
*
@@ -119,15 +123,50 @@ struct spf_dns_cb {
#define CHECK_REC(rec) \
do { \
- if ((rec)->nested > SPF_MAX_NESTING || \
- (rec)->dns_requests > SPF_MAX_DNS_REQUESTS) { \
- msg_info_spf ("spf recursion limit %d is reached, domain: %s", \
- (rec)->dns_requests, \
+ if (spf_lib_ctx->max_dns_nesting > 0 && \
+ (rec)->nested > spf_lib_ctx->max_dns_nesting) { \
+ msg_warn_spf ("spf nesting limit: %d > %d is reached, domain: %s", \
+ (rec)->nested, spf_lib_ctx->max_dns_nesting, \
+ (rec)->sender_domain); \
+ return FALSE; \
+ } \
+ if (spf_lib_ctx->max_dns_requests > 0 && \
+ (rec)->dns_requests > spf_lib_ctx->max_dns_requests) { \
+ msg_warn_spf ("spf dns requests limit: %d > %d is reached, domain: %s", \
+ (rec)->dns_requests, spf_lib_ctx->max_dns_requests, \
(rec)->sender_domain); \
return FALSE; \
} \
} while (0) \
+RSPAMD_CONSTRUCTOR(rspamd_spf_lib_ctx_ctor) {
+ spf_lib_ctx = g_malloc0 (sizeof (*spf_lib_ctx));
+ spf_lib_ctx->max_dns_nesting = SPF_MAX_NESTING;
+ spf_lib_ctx->max_dns_requests = SPF_MAX_DNS_REQUESTS;
+ spf_lib_ctx->min_cache_ttl = SPF_MIN_CACHE_TTL;
+}
+
+RSPAMD_DESTRUCTOR(rspamd_spf_lib_ctx_dtor) {
+ g_free (spf_lib_ctx);
+ spf_lib_ctx = NULL;
+}
+
+void
+spf_library_config (gint max_dns_nesting, gint max_dns_requests,
+ gint min_cache_ttl)
+{
+ if (max_dns_nesting >= 0) {
+ spf_lib_ctx->max_dns_nesting = max_dns_nesting;
+ }
+
+ if (max_dns_requests >= 0) {
+ spf_lib_ctx->max_dns_requests = max_dns_requests;
+ }
+
+ if (min_cache_ttl >= 0) {
+ spf_lib_ctx->min_cache_ttl = min_cache_ttl;
+ }
+}
static gboolean start_spf_parse (struct spf_record *rec,
struct spf_resolved_element *resolved, gchar *begin);
@@ -452,7 +491,7 @@ rspamd_spf_elts_cmp (gconstpointer a, gconstpointer b)
}
static void
-rspamd_spf_record_postprocess (struct spf_resolved *rec)
+rspamd_spf_record_postprocess (struct spf_resolved *rec, struct rspamd_task *task)
{
g_array_sort (rec->elts, rspamd_spf_elts_cmp);
@@ -481,6 +520,14 @@ rspamd_spf_record_postprocess (struct spf_resolved *rec)
rec->digest = mum_hash_step (rec->digest, t);
}
}
+
+ if (spf_lib_ctx->min_cache_ttl > 0) {
+ if (rec->ttl != 0 && rec->ttl < spf_lib_ctx->min_cache_ttl) {
+ msg_info_task ("increasing ttl from %d to %d as it lower than a limit",
+ rec->ttl, spf_lib_ctx->min_cache_ttl);
+ rec->ttl = spf_lib_ctx->min_cache_ttl;
+ }
+ }
}
static void
@@ -490,7 +537,7 @@ rspamd_spf_maybe_return (struct spf_record *rec)
if (rec->requests_inflight == 0 && !rec->done) {
flat = rspamd_spf_record_flatten (rec);
- rspamd_spf_record_postprocess (flat);
+ rspamd_spf_record_postprocess (flat, rec->task);
rec->callback (flat, rec->task, rec->cbdata);
REF_RELEASE (flat);
rec->done = TRUE;
diff --git a/src/libserver/spf.h b/src/libserver/spf.h
index 725d84fe4..cd8eaffac 100644
--- a/src/libserver/spf.h
+++ b/src/libserver/spf.h
@@ -46,6 +46,11 @@ typedef enum spf_action_e {
#define RSPAMD_SPF_FLAG_PERMFAIL (1u << 10u)
#define RSPAMD_SPF_FLAG_RESOLVED (1u << 11u)
+/** Default SPF limits for avoiding abuse **/
+#define SPF_MAX_NESTING 10
+#define SPF_MAX_DNS_REQUESTS 30
+#define SPF_MIN_CACHE_TTL (60 * 5) /* 5 minutes */
+
struct spf_addr {
guchar addr6[sizeof (struct in6_addr)];
guchar addr4[sizeof (struct in_addr)];
@@ -112,6 +117,9 @@ gchar *spf_addr_mask_to_string (struct spf_addr *addr);
struct spf_addr *spf_addr_match_task (struct rspamd_task *task,
struct spf_resolved *rec);
+void spf_library_config (gint max_dns_nesting, gint max_dns_requests,
+ gint min_cache_ttl);
+
#ifdef __cplusplus
}
#endif
More information about the Commits
mailing list