]> source.dussan.org Git - rspamd.git/commitdiff
[Fix] Fix IPv6 expansion for SPF macros
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 28 Jan 2021 11:14:54 +0000 (11:14 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 28 Jan 2021 11:14:54 +0000 (11:14 +0000)
Issue: #3625

src/libserver/spf.c

index 8242d94c2d5e62477c1a7088df4e756932812786..63ed17ba42a3fa815847fb77565df409e219095b 100644 (file)
@@ -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),