From 21445a33871eb64b562defd4ab80ec53fca4b740 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 28 Jan 2021 11:14:54 +0000 Subject: [PATCH] [Fix] Fix IPv6 expansion for SPF macros Issue: #3625 --- src/libserver/spf.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/libserver/spf.c b/src/libserver/spf.c index 8242d94c2..63ed17ba4 100644 --- a/src/libserver/spf.c +++ b/src/libserver/spf.c @@ -1777,7 +1777,7 @@ expand_spf_macro (struct spf_record *rec, struct spf_resolved_element *resolved, gchar *c, *new, *tmp, delim = '.'; gsize len = 0, slen = 0, macro_len = 0; gint state = 0, ndelim = 0; - gchar ip_buf[INET6_ADDRSTRLEN + 1]; + gchar ip_buf[INET6_ADDRSTRLEN * 2 + 1]; gboolean need_expand = FALSE, reversed; struct rspamd_task *task; @@ -1970,10 +1970,40 @@ expand_spf_macro (struct spf_record *rec, struct spf_resolved_element *resolved, switch (g_ascii_tolower (*p)) { case 'i': if (task->from_addr) { - macro_len = rspamd_strlcpy (ip_buf, - rspamd_inet_address_to_string (task->from_addr), - sizeof (ip_buf)); - macro_value = ip_buf; + if (rspamd_inet_address_get_af (task->from_addr) == AF_INET) { + macro_len = rspamd_strlcpy (ip_buf, + rspamd_inet_address_to_string (task->from_addr), + sizeof (ip_buf)); + macro_value = ip_buf; + } + else if (rspamd_inet_address_get_af (task->from_addr) == AF_INET6) { + /* See #3625 for details */ + socklen_t slen; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) + rspamd_inet_address_get_sa (task->from_addr, &slen); + + /* Expand IPv6 address */ +#define IPV6_OCTET(x) bytes[(x)] >> 4, bytes[(x)] & 0xF + unsigned char *bytes = (unsigned char *)&sin6->sin6_addr; + macro_len = rspamd_snprintf (ip_buf, sizeof (ip_buf), + "%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd." + "%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd.%xd", + IPV6_OCTET(0), IPV6_OCTET(1), + IPV6_OCTET(2), IPV6_OCTET(3), + IPV6_OCTET(4), IPV6_OCTET(5), + IPV6_OCTET(6), IPV6_OCTET(7), + IPV6_OCTET(8), IPV6_OCTET(9), + IPV6_OCTET(10), IPV6_OCTET(11), + IPV6_OCTET(12), IPV6_OCTET(13), + IPV6_OCTET(14), IPV6_OCTET(15)); + macro_value = ip_buf; +#undef IPV6_OCTET + } + else { + macro_len = rspamd_snprintf (ip_buf, sizeof (ip_buf), + "127.0.0.1"); + macro_value = ip_buf; + } } else { macro_len = rspamd_snprintf (ip_buf, sizeof (ip_buf), -- 2.39.5