ports/155979: [mainteiner] [PATCH] add IPv6 whitelist patch
Mikhail T.
m.tsatsenko at gmail.com
Sun Mar 27 22:30:35 UTC 2011
>Number: 155979
>Category: ports
>Synopsis: [mainteiner] [PATCH] add IPv6 whitelist patch
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-ports-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Sun Mar 27 22:30:34 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator: Mikhail T.
>Release: 8.2
>Organization:
>Environment:
FreeBSD red 8.2-RELEASE FreeBSD 8.2-RELEASE #1 r218780: Thu Mar 10 21:36:01 MSK 2011 root at red:/usr/obj/usr/src/sys/XGATE amd64
>Description:
This patch makes it possible to allow IPv6 subnets to be whitelisted/auto-accepted.
Obtained from http://wilmer.gaa.st/blog/archives/61-spamass-milter-and-IPv6.html.
Submitted by Koen Martens gmc <at> sonologic <dot> nl via private email.
>How-To-Repeat:
>Fix:
Use the patch attached
Patch attached with submission follows:
Index: Makefile
===================================================================
RCS file: /home/ncvs/ports/mail/spamass-milter/Makefile,v
retrieving revision 1.46
diff -u -r1.46 Makefile
--- Makefile 18 Feb 2011 03:13:02 -0000 1.46
+++ Makefile 27 Mar 2011 21:54:49 -0000
@@ -25,7 +25,8 @@
OPTIONS= ADDAUTH_PATCH "Bypass checks for SMTP AUTH connections" off \
REJECTTEXT_PATCH "Customize SMTP reject message" off \
LDAP "LDAP support" off \
- SENDMAIL_PORT "Build against sendmail port" off
+ SENDMAIL_PORT "Build against sendmail port" off \
+ IPV6 "Apply IPv6 whitelist patch" off
.include <bsd.port.pre.mk>
@@ -42,6 +43,10 @@
NEW_ARGS:= ${NEW_ARGS}R:
.endif
+.if defined(WITH_IPV6)
+EXTRA_PATCHES+= ${FILESDIR}/extra-patch-ipv6
+.endif
+
# extra-patch-options is modified in pre-patch
.if ${ORIG_ARGS} != ${NEW_ARGS}
EXTRA_PATCHES+= ${WRKDIR}/extra-patch-options
Index: files/extra-patch-ipv6
===================================================================
RCS file: files/extra-patch-ipv6
diff -N files/extra-patch-ipv6
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ files/extra-patch-ipv6 27 Mar 2011 21:54:50 -0000
@@ -0,0 +1,270 @@
+diff -ur orig/spamass-milter.cpp spamass-milter.cpp
+--- orig/spamass-milter.cpp 2010-01-31 11:35:47.000000000 +0000
++++ spamass-milter.cpp 2008-01-09 01:20:38.000000000 +0000
+@@ -88,6 +88,7 @@
+ #include "subst_poll.h"
+ #endif
+ #include <errno.h>
++#include <netdb.h>
+
+ // C++ includes
+ #include <cstdio>
+@@ -721,12 +722,19 @@
+ sctx = (struct context *)malloc(sizeof(*sctx));
+ if (!hostaddr)
+ {
++ static struct sockaddr_in localhost;
++
+ /* 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;
+@@ -740,10 +748,12 @@
+ }
+ /* debug(D_ALWAYS, "ZZZ set private context to %p", sctx); */
+
+- if (ip_in_networklist(sctx->connect_ip, &ignorenets))
++ //debug(D_FUNC, "sctx->connect_ip: `%d'", sctx->connect_ip.sin_family);
++
++ 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;
+ }
+@@ -815,7 +825,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;
+@@ -2089,69 +2099,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;
++
++ {
++ char *snet = strdup(inet_ntoa(net));
++ debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask));
++ free(snet);
++ }
+
+- if (tmask)
++ 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;
++ }
+ }
+ }
+
+diff -ur orig/spamass-milter.h spamass-milter.h
+--- orig/spamass-milter.h 2006-03-23 22:07:55.000000000 +0000
++++ spamass-milter.h 2008-01-01 23:55:44.000000000 +0000
+@@ -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);
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-ports-bugs
mailing list