commit 66d0f13: [Minor] Merge fake DNS records

Vsevolod Stakhov vsevolod at highsecure.ru
Mon Aug 26 17:28:03 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-08-26 18:25:00 +0100
URL: https://github.com/rspamd/rspamd/commit/66d0f1335cb2e43221e93b4b4a7710495a9c54b8 (HEAD -> master)

[Minor] Merge fake DNS records

---
 src/libserver/dns.c | 352 +++++++++++++++++++++++++++-------------------------
 1 file changed, 185 insertions(+), 167 deletions(-)

diff --git a/src/libserver/dns.c b/src/libserver/dns.c
index ab01bc8ed..cf4279cf0 100644
--- a/src/libserver/dns.c
+++ b/src/libserver/dns.c
@@ -326,208 +326,222 @@ rspamd_dns_resolv_conf_on_server (struct rdns_resolver *resolver,
 }
 
 static void
-rspamd_dns_resolver_config_ucl (struct rspamd_config *cfg,
-								struct rspamd_dns_resolver *dns_resolver,
-								const ucl_object_t *dns_section)
+rspamd_process_fake_reply (struct rspamd_config *cfg,
+		struct rspamd_dns_resolver *dns_resolver,
+		const ucl_object_t *cur_arr)
 {
-	const ucl_object_t *fake_replies, *cur;
+	const ucl_object_t *cur;
 	ucl_object_iter_t it;
 
-	/* Process fake replies */
-	fake_replies = ucl_object_lookup_any (dns_section, "fake_records",
-			"fake_replies", NULL);
+	it = ucl_object_iterate_new (cur_arr);
 
-	if (fake_replies && ucl_object_type (fake_replies) == UCL_ARRAY) {
-		it = ucl_object_iterate_new (fake_replies);
+	while ((cur = ucl_object_iterate_safe (it, true))) {
+		const ucl_object_t *type_obj, *name_obj, *code_obj, *replies_obj;
+		enum rdns_request_type rtype = RDNS_REQUEST_A;
+		enum dns_rcode rcode = RDNS_RC_NOERROR;
+		struct rdns_reply_entry *replies = NULL;
+		const gchar *name = NULL;
+
+		if (ucl_object_type (cur) != UCL_OBJECT) {
+			continue;
+		}
+
+		name_obj = ucl_object_lookup (cur, "name");
+		if (name_obj == NULL ||
+			(name = ucl_object_tostring (name_obj)) == NULL) {
+			msg_err_config ("no name for fake dns reply");
+			continue;
+		}
 
-		while ((cur = ucl_object_iterate_safe (it, true))) {
-			const ucl_object_t *type_obj, *name_obj, *code_obj, *replies_obj;
-			enum rdns_request_type rtype = RDNS_REQUEST_A;
-			enum dns_rcode rcode = RDNS_RC_NOERROR;
-			struct rdns_reply_entry *replies = NULL;
-			const gchar *name = NULL;
+		type_obj = ucl_object_lookup (cur, "type");
+		if (type_obj) {
+			rtype = rdns_type_fromstr (ucl_object_tostring (type_obj));
 
-			if (ucl_object_type (cur) != UCL_OBJECT) {
+			if (rtype == RDNS_REQUEST_INVALID) {
+				msg_err_config ("invalid type for %s: %s", name,
+						ucl_object_tostring (type_obj));
 				continue;
 			}
+		}
 
-			name_obj = ucl_object_lookup (cur, "name");
-			if (name_obj == NULL ||
-				(name = ucl_object_tostring (name_obj)) == NULL) {
-				msg_err_config ("no name for fake dns reply");
+		code_obj = ucl_object_lookup_any (cur, "code", "rcode", NULL);
+		if (code_obj) {
+			rcode = rdns_rcode_fromstr (ucl_object_tostring (code_obj));
+
+			if (rcode == RDNS_RC_INVALID) {
+				msg_err_config ("invalid rcode for %s: %s", name,
+						ucl_object_tostring (code_obj));
 				continue;
 			}
+		}
 
-			type_obj = ucl_object_lookup (cur, "type");
-			if (type_obj) {
-				rtype = rdns_type_fromstr (ucl_object_tostring (type_obj));
+		if (rcode == RDNS_RC_NOERROR) {
+			/* We want replies to be set for this rcode */
+			replies_obj = ucl_object_lookup (cur, "replies");
 
-				if (rtype == RDNS_REQUEST_INVALID) {
-					msg_err_config ("invalid type for %s: %s", name,
-							ucl_object_tostring (type_obj));
-					continue;
-				}
+			if (replies_obj == NULL || ucl_object_type (replies_obj) != UCL_ARRAY) {
+				msg_err_config ("invalid replies for fake DNS record %s", name);
+				continue;
 			}
 
-			code_obj = ucl_object_lookup_any (cur, "code", "rcode", NULL);
-			if (code_obj) {
-				rcode = rdns_rcode_fromstr (ucl_object_tostring (code_obj));
+			ucl_object_iter_t rep_it;
+			const ucl_object_t *rep_obj;
 
-				if (rcode == RDNS_RC_INVALID) {
-					msg_err_config ("invalid rcode for %s: %s", name,
-							ucl_object_tostring (code_obj));
-					continue;
-				}
-			}
+			rep_it = ucl_object_iterate_new (replies_obj);
 
-			if (rcode == RDNS_RC_NOERROR) {
-				/* We want replies to be set for this rcode */
-				replies_obj = ucl_object_lookup (cur, "replies");
+			while ((rep_obj = ucl_object_iterate_safe (rep_it, true))) {
+				const gchar *str_rep = ucl_object_tostring (rep_obj);
+				struct rdns_reply_entry *rep;
+				gchar **svec;
 
-				if (replies_obj == NULL || ucl_object_type (replies_obj) != UCL_ARRAY) {
-					msg_err_config ("invalid replies for fake DNS record %s", name);
+				if (str_rep == NULL) {
+					msg_err_config ("invalid reply element for fake DNS record %s",
+							name);
 					continue;
 				}
 
-				ucl_object_iter_t rep_it;
-				const ucl_object_t *rep_obj;
-
-				rep_it = ucl_object_iterate_new (replies_obj);
+				rep = calloc (1, sizeof (*rep));
+				g_assert (rep != NULL);
 
-				while ((rep_obj = ucl_object_iterate_safe (rep_it, true))) {
-					const gchar *str_rep = ucl_object_tostring (rep_obj);
-					struct rdns_reply_entry *rep;
-					gchar **svec;
+				rep->type = rtype;
+				rep->ttl = 0;
 
-					if (str_rep == NULL) {
-						msg_err_config ("invalid reply element for fake DNS record %s",
-								name);
-						continue;
+				switch (rtype) {
+				case RDNS_REQUEST_A:
+					if (inet_pton (AF_INET, str_rep, &rep->content.a.addr) != 1) {
+						msg_err_config ("invalid A reply element for fake "
+										"DNS record %s: %s",
+								name, str_rep);
+						free (rep);
 					}
-
-					rep = calloc (1, sizeof (*rep));
-					g_assert (rep != NULL);
-
-					rep->type = rtype;
-					rep->ttl = 0;
-
-					switch (rtype) {
-					case RDNS_REQUEST_A:
-						if (inet_pton (AF_INET, str_rep, &rep->content.a.addr) != 1) {
-							msg_err_config ("invalid A reply element for fake "
-											"DNS record %s: %s",
-									name, str_rep);
-							free (rep);
-						}
-						else {
-							DL_APPEND (replies, rep);
-						}
-						break;
-					case RDNS_REQUEST_NS:
-						rep->content.ns.name = strdup (str_rep);
+					else {
 						DL_APPEND (replies, rep);
-						break;
-					case RDNS_REQUEST_PTR:
-						rep->content.ptr.name = strdup (str_rep);
+					}
+					break;
+				case RDNS_REQUEST_NS:
+					rep->content.ns.name = strdup (str_rep);
+					DL_APPEND (replies, rep);
+					break;
+				case RDNS_REQUEST_PTR:
+					rep->content.ptr.name = strdup (str_rep);
+					DL_APPEND (replies, rep);
+					break;
+				case RDNS_REQUEST_MX:
+					svec = g_strsplit_set (str_rep, " :", -1);
+
+					if (svec && svec[0] && svec[1]) {
+						rep->content.mx.priority = strtoul (svec[0], NULL, 10);
+						rep->content.mx.name = strdup (svec[1]);
 						DL_APPEND (replies, rep);
-						break;
-					case RDNS_REQUEST_MX:
-						svec = g_strsplit_set (str_rep, " :", -1);
-
-						if (svec && svec[0] && svec[1]) {
-							rep->content.mx.priority = strtoul (svec[0], NULL, 10);
-							rep->content.mx.name = strdup (svec[1]);
-							DL_APPEND (replies, rep);
-						}
-						else {
-							msg_err_config ("invalid MX reply element for fake "
-											"DNS record %s: %s",
-									name, str_rep);
-							free (rep);
-						}
-
-						g_strfreev (svec);
-						break;
-					case RDNS_REQUEST_TXT:
-						rep->content.txt.data = strdup (str_rep);
+					}
+					else {
+						msg_err_config ("invalid MX reply element for fake "
+										"DNS record %s: %s",
+								name, str_rep);
+						free (rep);
+					}
+
+					g_strfreev (svec);
+					break;
+				case RDNS_REQUEST_TXT:
+					rep->content.txt.data = strdup (str_rep);
+					DL_APPEND (replies, rep);
+					break;
+				case RDNS_REQUEST_SOA:
+					svec = g_strsplit_set (str_rep, " :", -1);
+
+					/* 7 elements */
+					if (svec && svec[0] && svec[1] && svec[2] &&
+						svec[3] && svec[4] && svec[5] && svec[6]) {
+						rep->content.soa.mname = strdup (svec[0]);
+						rep->content.soa.admin = strdup (svec[1]);
+						rep->content.soa.serial = strtoul (svec[2], NULL, 10);
+						rep->content.soa.refresh = strtol (svec[3], NULL, 10);
+						rep->content.soa.retry = strtol (svec[4], NULL, 10);
+						rep->content.soa.expire = strtol (svec[5], NULL, 10);
+						rep->content.soa.minimum = strtoul (svec[6], NULL, 10);
 						DL_APPEND (replies, rep);
-						break;
-					case RDNS_REQUEST_SOA:
-						svec = g_strsplit_set (str_rep, " :", -1);
-
-						/* 7 elements */
-						if (svec && svec[0] && svec[1] && svec[2] &&
-								svec[3] && svec[4] && svec[5] && svec[6]) {
-							rep->content.soa.mname = strdup (svec[0]);
-							rep->content.soa.admin = strdup (svec[1]);
-							rep->content.soa.serial = strtoul (svec[2], NULL, 10);
-							rep->content.soa.refresh = strtol (svec[3], NULL, 10);
-							rep->content.soa.retry = strtol (svec[4], NULL, 10);
-							rep->content.soa.expire = strtol (svec[5], NULL, 10);
-							rep->content.soa.minimum = strtoul (svec[6], NULL, 10);
-							DL_APPEND (replies, rep);
-						}
-						else {
-							msg_err_config ("invalid MX reply element for fake "
-											"DNS record %s: %s",
-									name, str_rep);
-							free (rep);
-						}
-
-						g_strfreev (svec);
-						break;
-					case RDNS_REQUEST_AAAA:
-						if (inet_pton (AF_INET6, str_rep, &rep->content.aaa.addr) != 1) {
-							msg_err_config ("invalid AAAA reply element for fake "
-											"DNS record %s: %s",
-									name, str_rep);
-							free (rep);
-						}
-						else {
-							DL_APPEND (replies, rep);
-						}
-					case RDNS_REQUEST_SRV:
-					default:
-						msg_err_config ("invalid or unsupported reply element "
-										"for fake DNS record %s(%s): %s",
-								name, rdns_str_from_type (rtype), str_rep);
+					}
+					else {
+						msg_err_config ("invalid MX reply element for fake "
+										"DNS record %s: %s",
+								name, str_rep);
+						free (rep);
+					}
+
+					g_strfreev (svec);
+					break;
+				case RDNS_REQUEST_AAAA:
+					if (inet_pton (AF_INET6, str_rep, &rep->content.aaa.addr) != 1) {
+						msg_err_config ("invalid AAAA reply element for fake "
+										"DNS record %s: %s",
+								name, str_rep);
 						free (rep);
-						break;
 					}
+					else {
+						DL_APPEND (replies, rep);
+					}
+				case RDNS_REQUEST_SRV:
+				default:
+					msg_err_config ("invalid or unsupported reply element "
+									"for fake DNS record %s(%s): %s",
+							name, rdns_str_from_type (rtype), str_rep);
+					free (rep);
+					break;
 				}
+			}
 
-				ucl_object_iterate_free (rep_it);
+			ucl_object_iterate_free (rep_it);
 
-				if (replies) {
-					struct rdns_reply_entry *tmp_entry;
-					guint i = 0;
-					DL_COUNT (replies, tmp_entry, i);
+			if (replies) {
+				struct rdns_reply_entry *tmp_entry;
+				guint i = 0;
+				DL_COUNT (replies, tmp_entry, i);
 
-					msg_info_config ("added fake record: %s(%s); %d replies", name,
-							rdns_str_from_type (rtype), i);
-					rdns_resolver_set_fake_reply (dns_resolver->r,
-							name, rtype, rcode, replies);
-				}
-				else {
-					msg_warn_config ("record %s has no replies, not adding",
-							name);
-				}
+				msg_info_config ("added fake record: %s(%s); %d replies", name,
+						rdns_str_from_type (rtype), i);
+				rdns_resolver_set_fake_reply (dns_resolver->r,
+						name, rtype, rcode, replies);
 			}
 			else {
-				/* This entry returns some non valid code, no replies are possible */
-				replies_obj = ucl_object_lookup (cur, "replies");
-
-				if (replies_obj) {
-					msg_warn_config ("replies are set for non-successful return "
-					  "code for %s(%s), they will be ignored", name, rdns_str_from_type (rtype));
-				}
+				msg_warn_config ("record %s has no replies, not adding",
+						name);
+			}
+		}
+		else {
+			/* This entry returns some non valid code, no replies are possible */
+			replies_obj = ucl_object_lookup (cur, "replies");
 
-				rdns_resolver_set_fake_reply (dns_resolver->r,
-						name, rtype, rcode, NULL);
+			if (replies_obj) {
+				msg_warn_config ("replies are set for non-successful return "
+								 "code for %s(%s), they will be ignored", name, rdns_str_from_type (rtype));
 			}
+
+			rdns_resolver_set_fake_reply (dns_resolver->r,
+					name, rtype, rcode, NULL);
 		}
+	}
 
-		ucl_object_iterate_free (it);
+	ucl_object_iterate_free (it);
+}
+
+static void
+rspamd_dns_resolver_config_ucl (struct rspamd_config *cfg,
+								struct rspamd_dns_resolver *dns_resolver,
+								const ucl_object_t *dns_section)
+{
+	const ucl_object_t *fake_replies;
+
+	/* Process fake replies */
+	fake_replies = ucl_object_lookup_any (dns_section, "fake_records",
+			"fake_replies", NULL);
+
+	if (fake_replies && ucl_object_type (fake_replies) == UCL_ARRAY) {
+		const ucl_object_t *cur_arr;
+
+		DL_FOREACH (fake_replies, cur_arr) {
+			rspamd_process_fake_reply (cfg, dns_resolver, cur_arr);
+		}
 	}
 }
 
@@ -604,15 +618,19 @@ rspamd_dns_resolver_init (rspamd_logger_t *logger,
 
 		if (cfg->rcl_obj) {
 			/* Configure additional options */
-			const ucl_object_t *opts_section, *dns_section;
+			const ucl_object_t *opts_section, *dns_section, *tmp;
 
 			opts_section = ucl_object_lookup (cfg->rcl_obj, "options");
 
 			if (opts_section) {
-				dns_section = ucl_object_lookup (opts_section, "dns");
+				/* TODO: implement a more simple merge logic */
+				DL_FOREACH (opts_section, tmp) {
+					dns_section = ucl_object_lookup (opts_section, "dns");
 
-				if (dns_section) {
-					rspamd_dns_resolver_config_ucl (cfg, dns_resolver, dns_section);
+					if (dns_section) {
+						rspamd_dns_resolver_config_ucl (cfg, dns_resolver,
+								dns_section);
+					}
 				}
 			}
 		}


More information about the Commits mailing list