commit 9e1ab1e: [Feature] Implement hosts file processing

Vsevolod Stakhov vsevolod at highsecure.ru
Tue Mar 17 15:49:10 UTC 2020


Author: Vsevolod Stakhov
Date: 2020-03-17 15:36:54 +0000
URL: https://github.com/rspamd/rspamd/commit/9e1ab1e5444e690fc136978f558d5311edebefb7

[Feature] Implement hosts file processing

---
 src/libserver/dns.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 120 insertions(+), 1 deletion(-)

diff --git a/src/libserver/dns.c b/src/libserver/dns.c
index 505e44a7a..1d114ec96 100644
--- a/src/libserver/dns.c
+++ b/src/libserver/dns.c
@@ -15,6 +15,7 @@
  */
 
 
+#include <contrib/librdns/rdns.h>
 #include "config.h"
 #include "dns.h"
 #include "rspamd.h"
@@ -641,12 +642,115 @@ rspamd_process_fake_reply (struct rspamd_config *cfg,
 	ucl_object_iterate_free (it);
 }
 
+static bool
+rspamd_dns_read_hosts_file (struct rspamd_config *cfg,
+							struct rspamd_dns_resolver *dns_resolver,
+							const gchar *fname)
+{
+	gchar *linebuf = NULL;
+	gsize buflen = 0;
+	gssize r;
+	FILE *fp;
+	guint nadded = 0;
+
+	fp = fopen (fname, "r");
+
+	if (fp == NULL) {
+		/* Hack to reduce noise */
+		if (strcmp (fname, "/etc/hosts") == 0) {
+			msg_info_config ("cannot open hosts file %s: %s", fname,
+					strerror (errno));
+		}
+		else {
+			msg_err_config ("cannot open hosts file %s: %s", fname,
+					strerror (errno));
+		}
+
+		return false;
+	}
+
+	while ((r = getline (&linebuf, &buflen, fp)) > 0) {
+		if (linebuf[0] == '#' || g_ascii_isspace (linebuf[0])) {
+			/* Skip comment or empty line */
+			continue;
+		}
+
+		g_strchomp (linebuf);
+
+		gchar **elts = g_strsplit_set (linebuf, " \t\v", -1);
+		rspamd_inet_addr_t *addr;
+
+		if (!rspamd_parse_inet_address (&addr, elts[0], strlen (elts[0]),
+				RSPAMD_INET_ADDRESS_PARSE_REMOTE|RSPAMD_INET_ADDRESS_PARSE_NO_UNIX)) {
+			msg_warn_config ("bad hosts file line: %s; cannot parse address", linebuf);
+		}
+		else {
+			/* Add all FQDN + aliases if any */
+			gchar **cur_name = &elts[1];
+
+			while (*cur_name) {
+				if (strlen (*cur_name) == 0) {
+					cur_name ++;
+					continue;
+				}
+
+				if (*cur_name[0] == '#') {
+					/* Start of the comment */
+					break;
+				}
+
+				struct rdns_reply_entry *rep;
+				rep = calloc (1, sizeof (*rep));
+				g_assert (rep != NULL);
+
+				rep->ttl = 0;
+
+				if (rspamd_inet_address_get_af (addr) == AF_INET) {
+					socklen_t unused;
+					const struct sockaddr_in *sin = (const struct sockaddr_in *)
+							rspamd_inet_address_get_sa (addr, &unused);
+					rep->type = RDNS_REQUEST_A;
+					memcpy (&rep->content.a.addr, &sin->sin_addr,
+							sizeof (rep->content.a.addr));
+				}
+				else {
+					socklen_t unused;
+					const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)
+							rspamd_inet_address_get_sa (addr, &unused);
+					rep->type = RDNS_REQUEST_AAAA;
+					memcpy (&rep->content.aaa.addr, &sin6->sin6_addr,
+							sizeof (rep->content.aaa.addr));
+				}
+
+				rep->next = NULL;
+				rep->prev = rep;
+				rdns_resolver_set_fake_reply (dns_resolver->r,
+						g_strdup (*cur_name), rep->type, RDNS_RC_NOERROR, rep);
+				msg_debug_config ("added fake record %s -> %s from hosts file %s",
+						*cur_name, rspamd_inet_address_to_string (addr), fname);
+				cur_name ++;
+				nadded ++;
+			}
+
+			rspamd_inet_address_free (addr);
+		}
+
+		g_strfreev (elts);
+	}
+
+	msg_info_config ("processed host file %s; %d records added", fname, nadded);
+	fclose (fp);
+
+	return true;
+}
+
 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, *fails_cache_size, *fails_cache_time;
+	const ucl_object_t *fake_replies, *fails_cache_size, *fails_cache_time,
+		*hosts;
 	static const ev_tstamp default_fails_cache_time = 10.0;
 
 	/* Process fake replies */
@@ -661,6 +765,21 @@ rspamd_dns_resolver_config_ucl (struct rspamd_config *cfg,
 		}
 	}
 
+	hosts = ucl_object_lookup (dns_section, "hosts");
+	if (hosts == NULL) {
+		/* Read normal `/etc/hosts` file */
+		rspamd_dns_read_hosts_file (cfg, dns_resolver, "/etc/hosts");
+	}
+	else if (ucl_object_type (hosts) == UCL_NULL) {
+
+	}
+	else if (ucl_object_type (hosts) == UCL_STRING) {
+
+	}
+	else if (ucl_object_type (hosts) == UCL_ARRAY) {
+
+	}
+
 	fails_cache_size = ucl_object_lookup (dns_section, "fails_cache_size");
 	if (fails_cache_size && ucl_object_type (fails_cache_size) == UCL_INT) {
 


More information about the Commits mailing list