+++ /dev/null
-Description: Add support for ipv6
-Origin: http://wilmer.gaast.net/blog/archives/61-spamass-milter-and-IPv6.html
-Bug: #569483
-Author: Wilmer van der Gaast <wilmer@gaast.net>
-Forwarded: no
-Index: spamass-milter/spamass-milter.cpp
-===================================================================
---- spamass-milter.orig/spamass-milter.cpp 2012-06-21 13:03:25.000000000 -0700
-+++ spamass-milter/spamass-milter.cpp 2012-06-21 13:03:42.000000000 -0700
-@@ -88,6 +88,7 @@
- #include "subst_poll.h"
- #endif
- #include <errno.h>
-+#include <netdb.h>
-
- // C++ includes
- #include <cstdio>
-@@ -678,6 +679,8 @@
- {
- struct context *sctx;
- int rv;
-+ struct sockaddr_in localhost;
-+
-
- debug(D_FUNC, "mlfi_connect: enter");
-
-@@ -687,10 +690,15 @@
- {
- /* not a socket; probably a local user calling sendmail directly */
- /* set to 127.0.0.1 */
-- sctx->connect_ip.s_addr = htonl(INADDR_LOOPBACK);
-+ strcpy(sctx->connect_ip, "127.0.0.1");
-+ localhost.sin_family = AF_INET;
-+ localhost.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-+ hostaddr = (struct sockaddr*) &localhost;
- } else
- {
-- sctx->connect_ip = ((struct sockaddr_in *) hostaddr)->sin_addr;
-+ getnameinfo(hostaddr, sizeof(struct sockaddr_in6),
-+ sctx->connect_ip, 63, NULL, 0, NI_NUMERICHOST);
-+ debug(D_FUNC, "Remote address: %s", sctx->connect_ip);
- }
- sctx->assassin = NULL;
- sctx->helo = NULL;
-@@ -704,10 +712,10 @@
- }
- /* debug(D_ALWAYS, "ZZZ set private context to %p", sctx); */
-
-- if (ip_in_networklist(sctx->connect_ip, &ignorenets))
-+ if (ip_in_networklist(hostaddr, &ignorenets))
- {
- debug(D_NET, "%s is in our ignore list - accepting message",
-- inet_ntoa(sctx->connect_ip));
-+ sctx->connect_ip);
- debug(D_FUNC, "mlfi_connect: exit ignore");
- return SMFIS_ACCEPT;
- }
-@@ -779,7 +787,7 @@
- return SMFIS_TEMPFAIL;
- };
-
-- assassin->set_connectip(string(inet_ntoa(sctx->connect_ip)));
-+ assassin->set_connectip(string(sctx->connect_ip));
-
- // Store a pointer to the assassin object in our context struct
- sctx->assassin = assassin;
-@@ -2033,69 +2041,119 @@
- {
- char *tnet = strsep(&token, "/");
- char *tmask = token;
-- struct in_addr net, mask;
-+ struct in_addr net;
-+ struct in6_addr net6;
-
- if (list->num_nets % 10 == 0)
-- list->nets = (struct net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10));
-+ list->nets = (union net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10));
-
-- if (!inet_aton(tnet, &net))
-+ if (inet_pton(AF_INET, tnet, &net))
- {
-- fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet);
-- exit(1);
-- }
-+ struct in_addr mask;
-+
-+ if (tmask)
-+ {
-+ if (strchr(tmask, '.') == NULL)
-+ {
-+ /* CIDR */
-+ unsigned int bits;
-+ int ret;
-+ ret = sscanf(tmask, "%u", &bits);
-+ if (ret != 1 || bits > 32)
-+ {
-+ fprintf(stderr,"%s: bad CIDR value", tmask);
-+ exit(1);
-+ }
-+ mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff);
-+ } else if (!inet_pton(AF_INET6, tmask, &mask))
-+ {
-+ fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask);
-+ exit(1);
-+ }
-+ } else
-+ mask.s_addr = 0xffffffff;
-
-- if (tmask)
-+ {
-+ char *snet = strdup(inet_ntoa(net));
-+ debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask));
-+ free(snet);
-+ }
-+
-+ net.s_addr = net.s_addr & mask.s_addr;
-+ list->nets[list->num_nets].net4.af = AF_INET;
-+ list->nets[list->num_nets].net4.network = net;
-+ list->nets[list->num_nets].net4.netmask = mask;
-+ list->num_nets++;
-+ } else if (inet_pton(AF_INET6, tnet, &net6))
- {
-- if (strchr(tmask, '.') == NULL)
-+ int mask;
-+
-+ if (tmask)
- {
-- /* CIDR */
-- unsigned int bits;
-- int ret;
-- ret = sscanf(tmask, "%u", &bits);
-- if (ret != 1 || bits > 32)
-+ if (sscanf(tmask, "%d", &mask) != 1 || mask > 128)
- {
- fprintf(stderr,"%s: bad CIDR value", tmask);
- exit(1);
- }
-- mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff);
-- } else if (!inet_aton(tmask, &mask))
-- {
-- fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask);
-- exit(1);
-- }
-+ } else
-+ mask = 128;
-+
-+ list->nets[list->num_nets].net6.af = AF_INET6;
-+ list->nets[list->num_nets].net6.network = net6;
-+ list->nets[list->num_nets].net6.netmask = mask;
-+ list->num_nets++;
- } else
-- mask.s_addr = 0xffffffff;
--
- {
-- char *snet = strdup(inet_ntoa(net));
-- debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask));
-- free(snet);
-+ fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet);
-+ exit(1);
- }
-
-- net.s_addr = net.s_addr & mask.s_addr;
-- list->nets[list->num_nets].network = net;
-- list->nets[list->num_nets].netmask = mask;
-- list->num_nets++;
- }
- free(string);
- }
-
--int ip_in_networklist(struct in_addr ip, struct networklist *list)
-+int ip_in_networklist(struct sockaddr *addr, struct networklist *list)
- {
- int i;
-
- if (list->num_nets == 0)
- return 0;
--
-- debug(D_NET, "Checking %s against:", inet_ntoa(ip));
-+
-+ //debug(D_NET, "Checking %s against:", inet_ntoa(ip));
- for (i = 0; i < list->num_nets; i++)
- {
-- debug(D_NET, "%s", inet_ntoa(list->nets[i].network));
-- debug(D_NET, "/%s", inet_ntoa(list->nets[i].netmask));
-- if ((ip.s_addr & list->nets[i].netmask.s_addr) == list->nets[i].network.s_addr)
-- {
-- debug(D_NET, "Hit!");
-- return 1;
-+ if (list->nets[i].net.af == AF_INET && addr->sa_family == AF_INET)
-+ {
-+ struct in_addr ip = ((struct sockaddr_in *)addr)->sin_addr;
-+
-+ debug(D_NET, "%s", inet_ntoa(list->nets[i].net4.network));
-+ debug(D_NET, "/%s", inet_ntoa(list->nets[i].net4.netmask));
-+ if ((ip.s_addr & list->nets[i].net4.netmask.s_addr) == list->nets[i].net4.network.s_addr)
-+ {
-+ debug(D_NET, "Hit!");
-+ return 1;
-+ }
-+ } else if (list->nets[i].net.af == AF_INET6 && addr->sa_family == AF_INET6)
-+ {
-+ u_int8_t *ip = ((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr;
-+ int mask, j;
-+
-+ mask = list->nets[i].net6.netmask;
-+ for (j = 0; j < 16 && mask > 0; j++, mask -= 8)
-+ {
-+ unsigned char bytemask;
-+
-+ bytemask = (mask < 8) ? ~((1L << (8 - mask)) - 1) : 0xff;
-+
-+ if ((ip[j] & bytemask) != (list->nets[i].net6.network.s6_addr[j] & bytemask))
-+ break;
-+ }
-+
-+ if (mask <= 0)
-+ {
-+ debug(D_NET, "Hit!");
-+ return 1;
-+ }
- }
- }
-
-Index: spamass-milter/spamass-milter.h
-===================================================================
---- spamass-milter.orig/spamass-milter.h 2012-06-21 13:03:25.000000000 -0700
-+++ spamass-milter/spamass-milter.h 2012-06-21 13:03:42.000000000 -0700
-@@ -56,16 +56,30 @@
- extern struct smfiDesc smfilter;
-
- /* struct describing a single network */
--struct net
-+union net
- {
-- struct in_addr network;
-- struct in_addr netmask;
-+ struct
-+ {
-+ uint8_t af;
-+ } net;
-+ struct
-+ {
-+ uint8_t af;
-+ struct in_addr network;
-+ struct in_addr netmask;
-+ } net4;
-+ struct
-+ {
-+ uint8_t af;
-+ struct in6_addr network;
-+ int netmask; /* Just the number of bits for IPv6 */
-+ } net6;
- };
-
- /* an array of networks */
- struct networklist
- {
-- struct net *nets;
-+ union net *nets;
- int num_nets;
- };
-
-@@ -165,7 +179,7 @@
- /* Private data structure to carry per-client data between calls */
- struct context
- {
-- struct in_addr connect_ip; // remote IP address
-+ char connect_ip[64]; // remote IP address
- char *helo;
- SpamAssassin *assassin; // pointer to the SA object if we're processing a message
- };
-@@ -182,7 +196,7 @@
- int cmp_nocase_partial(const string&, const string&);
- void closeall(int fd);
- void parse_networklist(char *string, struct networklist *list);
--int ip_in_networklist(struct in_addr ip, struct networklist *list);
-+int ip_in_networklist(struct sockaddr *addr, struct networklist *list);
- void parse_debuglevel(char* string);
- char *strlwr(char *str);
- void warnmacro(char *macro, char *scope);
+++ /dev/null
-Description: Fix a const cast in the header
-Author: Don Armstrong <don@donarmstrong.com>
-Forwarded: no
-Index: spamass-milter/spamass-milter.cpp
-===================================================================
---- spamass-milter.orig/spamass-milter.cpp 2012-06-21 13:02:08.000000000 -0700
-+++ spamass-milter/spamass-milter.cpp 2012-06-21 13:02:15.000000000 -0700
-@@ -363,7 +363,7 @@
- // }}}
-
- /* Update a header if SA changes it, or add it if it is new. */
--void update_or_insert(SpamAssassin* assassin, SMFICTX* ctx, string oldstring, t_setter setter, char *header )
-+void update_or_insert(SpamAssassin* assassin, SMFICTX* ctx, string oldstring, t_setter setter, const char *header )
- {
- string::size_type eoh1 = assassin->d().find("\n\n");
- string::size_type eoh2 = assassin->d().find("\n\r\n");
-@@ -386,15 +386,16 @@
- {
- /* change if old one was present, append if non-null */
- char* cstr = const_cast<char*>(newstring.c_str());
-+ char* hstr = const_cast<char*>(header);
- if (oldsize > 0)
- {
- debug(D_UORI, "u_or_i: changing");
-- smfi_chgheader(ctx, header, 1, newstring.size() > 0 ?
-+ smfi_chgheader(ctx, hstr, 1, newstring.size() > 0 ?
- cstr : NULL );
- } else if (newstring.size() > 0)
- {
- debug(D_UORI, "u_or_i: inserting");
-- smfi_addheader(ctx, header, cstr);
-+ smfi_addheader(ctx, hstr, cstr);
- }
- } else
- {