pkgsrc-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

pkg/49064: mail/spamass-milter zombie children & ipv6 support



>Number:         49064
>Category:       pkg
>Synopsis:       mail/spamass-milter zombie children & ipv6 support
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Aug 01 22:55:00 +0000 2014
>Originator:     Todd Kover
>Release:        NetBSD 6.1_STABLE
>Organization:
Omniscient Technologies
>Environment:
System: NetBSD guinness.omniscient.com 6.1_STABLE NetBSD 6.1_STABLE (GENERIC) 
#1: Thu Jun 26 20:47:09 EDT 2014 
kovert%guinness.omniscient.com@localhost:/usr/obj/6.0-stable/amd64/usr/src/os/NetBSD-6.0-branch/src/sys/arch/amd64/compile/GENERIC
 amd64
Architecture: x86_64
Machine: amd64
>Description:
        I combining two unrelated issues to the same port since its a minor
        pkg and I sorted them out together.  I can split if need be.

        Issue 1) A previous fix for a CVE that replaced popen lost the child 
        reaping that pclose has.  This causes sendmail processes to hang 
        around until spamass-milter is closed.

        Issue 2) No Ipv6 support

>How-To-Repeat:
        Issue 1) install port, tie into sendmail, start milter with -x, 
        watch mail come in and sendmail processes hang around

        Issue 2) start spamass milter with an ipv6 addressed passed to -i,
        such as -i 2001:1900:2209:a/64, watch it not start
>Fix:
        patch-ad is just a copy of the FreeBSD ports patch for fixing IPv6.
        Seems to work fine.  This tweaks the same file as patch-aa and
        patch-ab

        patch-ae and patch-af fix the popenv issue and touch the same files
        as patch-aa and patch-ab respectively.  I separated them in the
        interest of making it easier to patch.

        Thanks,
        -Todd

---<snip>-- patch-ad start ---<snip>---

This came from FreeBSD

diff -ur orig/spamass-milter.cpp spamass-milter.cpp
--- 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
--- 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);
---<snip>-- patch-ad end ---<snip>---

---<snip>-- patch-ae start ---<snip>---
--- spamass-milter.cpp  2014-08-01 09:03:23.000000000 -0400
+++ spamass-milter.cpp  2014-08-01 09:02:19.000000000 -0400
@@ -464,13 +464,14 @@
                           the only way to do it. */
                        char *popen_argv[3];
                        FILE *p;
+                       pid_t pid;
 
                        popen_argv[0] = SENDMAIL;
                        popen_argv[1] = spambucket;
                        popen_argv[2] = NULL;
                        
                        debug(D_COPY, "calling %s %s", SENDMAIL, spambucket);
-                       p = popenv(popen_argv, "w");
+                       p = popenv(popen_argv, "w", &pid);
                        if (!p)
                        {
                                debug(D_COPY, "popenv failed(%s).  Will not 
send a copy to spambucket", strerror(errno));
@@ -479,6 +480,7 @@
                                // Send message provided by SpamAssassin
                                fwrite(assassin->d().c_str(), 
assassin->d().size(), 1, p);
                                fclose(p); p = NULL;
+                               waitpid(pid, NULL, 0);
                        }
                }
                return SMFIS_REJECT;
@@ -824,9 +826,11 @@
                popen_argv[2] = envrcpt[0];
                popen_argv[3] = NULL;
 
+               pid_t pid;
+
                debug(D_RCPT, "calling %s -bv %s", SENDMAIL, envrcpt[0]);
 
-               p = popenv(popen_argv, "r");
+               p = popenv(popen_argv, "r", &pid);
                if (!p)
                {
                        debug(D_RCPT, "popenv failed(%s).  Will not expand 
aliases", strerror(errno));
@@ -855,6 +859,7 @@
                                }
                        }
                        fclose(p); p = NULL;
+                       waitpid(pid, NULL, 0);
                }
        } else
        {
@@ -2113,11 +2118,12 @@
    for simplicity, and always reads stdout and stderr in "r" mode.  Call
    fclose to close the FILE.
 */
-FILE *popenv(char *const argv[], const char *type)
+FILE *popenv(char *const argv[], const char *type, pid_t *pid)
 {
        FILE *iop;
        int pdes[2];
        int save_errno;
+       pid_t kidpid;
        if ((*type != 'r' && *type != 'w') || type[1])
        {
                errno = EINVAL;
@@ -2125,7 +2131,7 @@
        }
        if (pipe(pdes) < 0)
                return (NULL);
-       switch (fork()) {
+       switch ( (kidpid = fork()) ) {
        
        case -1:                        /* Error. */
                save_errno = errno;
@@ -2171,6 +2177,13 @@
                (void)close(pdes[0]);
        }
 
+       /*
+        * so caller can reap children and not leave zombies
+        */
+       if(kidpid) {
+               *pid = kidpid;
+       }
+
        return (iop);
 }
 
---<snip>-- patch-ae end ---<snip>---

---<snip>-- patch-af start ---<snip>---
--- spamass-milter.h    2014-08-01 09:03:23.000000000 -0400
+++ spamass-milter.h    2014-08-01 09:02:32.000000000 -0400
@@ -186,6 +186,6 @@
 void parse_debuglevel(char* string);
 char *strlwr(char *str);
 void warnmacro(char *macro, char *scope);
-FILE *popenv(char *const argv[], const char *type);
+FILE *popenv(char *const argv[], const char *type, pid_t *pid);
 
 #endif
---<snip>-- patch-af end ---<snip>---


------- =_aaaaaaaaaa0
Content-Type: text/plain; name="patch-ad"; charset="us-ascii"
Content-ID: <62332.1406933442.2%guinness.omniscient.com@localhost>

This came from FreeBSD

diff -ur orig/spamass-milter.cpp spamass-milter.cpp
--- 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
--- 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);

------- =_aaaaaaaaaa0
Content-Type: text/plain; name="patch-ae"; charset="us-ascii"
Content-ID: <62332.1406933442.3%guinness.omniscient.com@localhost>

--- spamass-milter.cpp  2014-08-01 09:03:23.000000000 -0400
+++ spamass-milter.cpp  2014-08-01 09:02:19.000000000 -0400
@@ -464,13 +464,14 @@
                           the only way to do it. */
                        char *popen_argv[3];
                        FILE *p;
+                       pid_t pid;
 
                        popen_argv[0] = SENDMAIL;
                        popen_argv[1] = spambucket;
                        popen_argv[2] = NULL;
                        
                        debug(D_COPY, "calling %s %s", SENDMAIL, spambucket);
-                       p = popenv(popen_argv, "w");
+                       p = popenv(popen_argv, "w", &pid);
                        if (!p)
                        {
                                debug(D_COPY, "popenv failed(%s).  Will not 
send a copy to spambucket", strerror(errno));
@@ -479,6 +480,7 @@
                                // Send message provided by SpamAssassin
                                fwrite(assassin->d().c_str(), 
assassin->d().size(), 1, p);
                                fclose(p); p = NULL;
+                               waitpid(pid, NULL, 0);
                        }
                }
                return SMFIS_REJECT;
@@ -824,9 +826,11 @@
                popen_argv[2] = envrcpt[0];
                popen_argv[3] = NULL;
 
+               pid_t pid;
+
                debug(D_RCPT, "calling %s -bv %s", SENDMAIL, envrcpt[0]);
 
-               p = popenv(popen_argv, "r");
+               p = popenv(popen_argv, "r", &pid);
                if (!p)
                {
                        debug(D_RCPT, "popenv failed(%s).  Will not expand 
aliases", strerror(errno));
@@ -855,6 +859,7 @@
                                }
                        }
                        fclose(p); p = NULL;
+                       waitpid(pid, NULL, 0);
                }
        } else
        {
@@ -2113,11 +2118,12 @@
    for simplicity, and always reads stdout and stderr in "r" mode.  Call
    fclose to close the FILE.
 */
-FILE *popenv(char *const argv[], const char *type)
+FILE *popenv(char *const argv[], const char *type, pid_t *pid)
 {
        FILE *iop;
        int pdes[2];
        int save_errno;
+       pid_t kidpid;
        if ((*type != 'r' && *type != 'w') || type[1])
        {
                errno = EINVAL;
@@ -2125,7 +2131,7 @@
        }
        if (pipe(pdes) < 0)
                return (NULL);
-       switch (fork()) {
+       switch ( (kidpid = fork()) ) {
        
        case -1:                        /* Error. */
                save_errno = errno;
@@ -2171,6 +2177,13 @@
                (void)close(pdes[0]);
        }
 
+       /*
+        * so caller can reap children and not leave zombies
+        */
+       if(kidpid) {
+               *pid = kidpid;
+       }
+
        return (iop);
 }
 

------- =_aaaaaaaaaa0
Content-Type: text/plain; name="patch-af"; charset="us-ascii"
Content-ID: <62332.1406933442.4%guinness.omniscient.com@localhost>

--- spamass-milter.h    2014-08-01 09:03:23.000000000 -0400
+++ spamass-milter.h    2014-08-01 09:02:32.000000000 -0400
@@ -186,6 +186,6 @@
 void parse_debuglevel(char* string);
 char *strlwr(char *str);
 void warnmacro(char *macro, char *scope);
-FILE *popenv(char *const argv[], const char *type);
+FILE *popenv(char *const argv[], const char *type, pid_t *pid);
 
 #endif

------- =_aaaaaaaaaa0--

>Unformatted:
 ------- =_aaaaaaaaaa0
 Content-Type: text/plain; charset="us-ascii"
 Content-ID: <62332.1406933442.1%guinness.omniscient.com@localhost>
 


Home | Main Index | Thread Index | Old Index