diff options
-rw-r--r-- | .SRCINFO | 52 | ||||
-rw-r--r-- | PKGBUILD | 112 | ||||
-rw-r--r-- | README.Postfix | 13 | ||||
-rw-r--r-- | spamass-milter-0.3.1-authuser.patch | 91 | ||||
-rw-r--r-- | spamass-milter-0.3.1-group.patch | 104 | ||||
-rw-r--r-- | spamass-milter-0.3.1-ipv6.patch | 297 | ||||
-rw-r--r-- | spamass-milter-0.3.1-pathnames.patch | 21 | ||||
-rw-r--r-- | spamass-milter-0.3.2-auth-no-ssf.patch | 28 | ||||
-rw-r--r-- | spamass-milter-0.3.2-bits.patch | 289 | ||||
-rw-r--r-- | spamass-milter-0.3.2-rcvd.patch | 23 | ||||
-rw-r--r-- | spamass-milter-0.3.2-rundir.patch | 30 | ||||
-rw-r--r-- | spamass-milter-0.3.2-syntax.patch | 248 | ||||
-rw-r--r-- | spamass-milter-postfix-sysconfig.systemd | 5 | ||||
-rw-r--r-- | spamass-milter-postfix-tmpfs.conf | 1 | ||||
-rw-r--r-- | spamass-milter-root.service | 30 | ||||
-rw-r--r-- | spamass-milter-sysconfig.systemd | 14 | ||||
-rw-r--r-- | spamass-milter-tmpfs.conf | 1 | ||||
-rw-r--r-- | spamass-milter.install | 53 | ||||
-rw-r--r-- | spamass-milter.service | 29 |
19 files changed, 1441 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..4101ad848862 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,52 @@ +pkgbase = spamass-milter + pkgdesc = Sendmail Milter that pipes incoming mail through SpamAssassin + pkgver = 0.3.2 + pkgrel = 1 + url = http://savannah.nongnu.org/projects/spamass-milt/ + install = spamass-milter.install + arch = i686 + arch = x86_64 + license = GPL + makedepends = libmilter + depends = gcc-libs + depends = spamassassin + optdepends = postfix + backup = etc/spamass-milter + backup = etc/spamass-milter-postfix + source = http://savannah.nongnu.org/download/spamass-milt/spamass-milter-0.3.2.tar.bz2 + source = README.Postfix + source = spamass-milter-0.3.2-syntax.patch + source = spamass-milter-0.3.1-authuser.patch + source = spamass-milter-0.3.2-rcvd.patch + source = spamass-milter-0.3.2-bits.patch + source = spamass-milter-0.3.1-group.patch + source = spamass-milter-0.3.1-ipv6.patch + source = spamass-milter-0.3.2-auth-no-ssf.patch + source = spamass-milter-0.3.1-pathnames.patch + source = spamass-milter-0.3.2-rundir.patch + source = spamass-milter.service + source = spamass-milter-root.service + source = spamass-milter-sysconfig.systemd + source = spamass-milter-postfix-sysconfig.systemd + source = spamass-milter-tmpfs.conf + source = spamass-milter-postfix-tmpfs.conf + md5sums = 740b4bcb93eca2bbc3863d0042b26533 + md5sums = 3078db471451e6adac707a73ade23e87 + md5sums = cfb0dee6bbb313a6e8543c34b1393508 + md5sums = 169ba77357bd335dc93df9e628d81a03 + md5sums = 8473057996babb7604b055af877f45fe + md5sums = 4ee23ad135c4047394eaf2e67a030639 + md5sums = 97f25427d538b0f6c8272ec99e46047a + md5sums = 0742164b9a9e8a2982e48f49aa334df7 + md5sums = cd5e7ccd449a504ca6cc818d3be486a8 + md5sums = 30d62411628d38a9fa5305b163b0335a + md5sums = 9b36f5a673707ea4d58091e2ce90a928 + md5sums = fab87c1281e39813c42c89fb4175fba0 + md5sums = eaf68d706b935d65fc2085ba8daa2a2e + md5sums = 3f2e2c728cc30199154a3884025a597a + md5sums = 61ac8b0d834fb462446d645047cdbb7b + md5sums = c3712b881f68bbc9e78e7f9b4ba5253d + md5sums = 590981f73d554b670821c28ed3521a0f + +pkgname = spamass-milter + diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..3de2a77bfe04 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,112 @@ +# Maintainer: Rich Li <rich at dranek com> +# Contributor: Florian "Bluewind" Pritz <flo@xssn.at> +# Note that all of the patches and systemd stuff is courtesy of Fedora's packaging, extracted from spamass-milter-0.3.2-9.fc18.src.rpm +# I updated a few of the Fedora files to reflect the slightly different directory structure for Arch +pkgname=spamass-milter +pkgver=0.3.2 +pkgrel=1 +pkgdesc="Sendmail Milter that pipes incoming mail through SpamAssassin" +arch=(i686 x86_64) +url="http://savannah.nongnu.org/projects/spamass-milt/" +license=('GPL') +depends=(gcc-libs spamassassin) +makedepends=(libmilter) +optdepends=("postfix") +backup=(etc/spamass-milter etc/spamass-milter-postfix) +install="spamass-milter.install" +source=("http://savannah.nongnu.org/download/spamass-milt/$pkgname-$pkgver.tar.bz2" + README.Postfix + spamass-milter-0.3.2-syntax.patch + spamass-milter-0.3.1-authuser.patch + spamass-milter-0.3.2-rcvd.patch + spamass-milter-0.3.2-bits.patch + spamass-milter-0.3.1-group.patch + spamass-milter-0.3.1-ipv6.patch + spamass-milter-0.3.2-auth-no-ssf.patch + spamass-milter-0.3.1-pathnames.patch + spamass-milter-0.3.2-rundir.patch + spamass-milter.service + spamass-milter-root.service + spamass-milter-sysconfig.systemd + spamass-milter-postfix-sysconfig.systemd + spamass-milter-tmpfs.conf + spamass-milter-postfix-tmpfs.conf + ) +md5sums=( + '740b4bcb93eca2bbc3863d0042b26533' + '3078db471451e6adac707a73ade23e87' + 'cfb0dee6bbb313a6e8543c34b1393508' + '169ba77357bd335dc93df9e628d81a03' + '8473057996babb7604b055af877f45fe' + '4ee23ad135c4047394eaf2e67a030639' + '97f25427d538b0f6c8272ec99e46047a' + '0742164b9a9e8a2982e48f49aa334df7' + 'cd5e7ccd449a504ca6cc818d3be486a8' + '30d62411628d38a9fa5305b163b0335a' + '9b36f5a673707ea4d58091e2ce90a928' + 'fab87c1281e39813c42c89fb4175fba0' + 'eaf68d706b935d65fc2085ba8daa2a2e' + '3f2e2c728cc30199154a3884025a597a' + '61ac8b0d834fb462446d645047cdbb7b' + 'c3712b881f68bbc9e78e7f9b4ba5253d' + '590981f73d554b670821c28ed3521a0f' + ) + + +prepare() { + cd "$srcdir/$pkgname-$pkgver" + # These are all Fedora patches + cp "$srcdir/README.Postfix" . + # Fix compiler warnings + patch -p1 < "$srcdir/spamass-milter-0.3.2-syntax.patch" + # Add -I option to ignore (don't check) mail from authenticated users + # (#437506, #496767) http://savannah.nongnu.org/bugs/?21046 + patch -p1 < "$srcdir/spamass-milter-0.3.1-authuser.patch" + # Fix received-header generation + patch -p1 < "$srcdir/spamass-milter-0.3.2-rcvd.patch" + # Add authentication info to dummy Received-header + patch -p1 < "$srcdir/spamass-milter-0.3.2-bits.patch" + # Add -g option for group-writable socket for Postfix support + patch -p1 < "$srcdir/spamass-milter-0.3.1-group.patch" + # Add ipv6 whitelisting support + patch -p1 < "$srcdir/spamass-milter-0.3.1-ipv6.patch" + # Help for users authenticating to postfix + patch -p1 < "$srcdir/spamass-milter-0.3.2-auth-no-ssf.patch" + # Two documentation updates + patch -p1 < "$srcdir/spamass-milter-0.3.1-pathnames.patch" + patch -p1 < "$srcdir/spamass-milter-0.3.2-rundir.patch" +} + +build() { + cd "$srcdir/$pkgname-$pkgver" + ./configure --prefix=/usr --sbindir=/usr/bin + make +} + +package() { + cd "$srcdir/$pkgname-$pkgver" + make DESTDIR="$pkgdir" install + + # Prep for socket used for postfix? + #install -m 711 -d "$pkgdir/run/spamass-milter" + #install -m 750 -d "$pkgdir/run/spamass-milter/postfix" + + # Home dir + install -m 755 -d "$pkgdir/var/lib/spamass-milter" + + # Systemd units + install -m 644 -D "$srcdir/spamass-milter.service" "$pkgdir/usr/lib/systemd/system/spamass-milter.service" + install -m 644 -D "$srcdir/spamass-milter-root.service" "$pkgdir/usr/lib/systemd/system/spamass-milter-root.service" + + # Config (for systemd) + install -m 644 -D "$srcdir/spamass-milter-sysconfig.systemd" "$pkgdir/etc/spamass-milter" + install -m 644 -D "$srcdir/spamass-milter-postfix-sysconfig.systemd" "$pkgdir/etc/spamass-milter-postfix" + + # tmpfiles + install -m 755 -d "$pkgdir/usr/lib/tmpfiles.d" + install -m 644 "$srcdir/spamass-milter-tmpfs.conf" "$pkgdir/usr/lib/tmpfiles.d/spamass-milter.conf" + install -m 644 "$srcdir/spamass-milter-postfix-tmpfs.conf" "$pkgdir/usr/lib/tmpfiles.d/spamass-milter-postfix.conf" +} + +# vim:set ts=2 sw=2 et: + diff --git a/README.Postfix b/README.Postfix new file mode 100644 index 000000000000..c4b9eb54eaa0 --- /dev/null +++ b/README.Postfix @@ -0,0 +1,13 @@ +Installing the spamass-milter-postfix package changes the default behaviour +of spamass-milter to be more Postfix-friendly, i.e.: + + The Unix-domain socket used for MTA communication is changed to + /var/run/spamass-milter/postfix/sock, and that socket is + writable by the postfix group. + +To configure Postfix to use the milter, add to /etc/postfix/main.cf: + + smtpd_milters = unix:/var/run/spamass-milter/postfix/sock + +For further information, see: +http://www.postfix.org/MILTER_README.html diff --git a/spamass-milter-0.3.1-authuser.patch b/spamass-milter-0.3.1-authuser.patch new file mode 100644 index 000000000000..7d3c7c539425 --- /dev/null +++ b/spamass-milter-0.3.1-authuser.patch @@ -0,0 +1,91 @@ +diff -up spamass-milter-0.3.1/spamass-milter.cpp.authuser spamass-milter-0.3.1/spamass-milter.cpp +--- spamass-milter-0.3.1/spamass-milter.cpp.authuser 2010-03-23 21:04:56.976920217 +0000 ++++ spamass-milter-0.3.1/spamass-milter.cpp 2010-03-23 21:07:12.508020535 +0000 +@@ -172,6 +172,7 @@ char *spambucket; + bool flag_full_email = false; /* pass full email address to spamc */ + bool flag_expand = false; /* alias/virtusertable expansion */ + bool warnedmacro = false; /* have we logged that we couldn't fetch a macro? */ ++bool ignore_authenticated_senders = false; /* authenticated users bypass spam checks */ + + // {{{ main() + +@@ -179,7 +180,7 @@ int + main(int argc, char* argv[]) + { + int c, err = 0; +- const char *args = "fd:mMp:P:r:u:D:i:b:B:e:x"; ++ const char *args = "fd:mMp:P:r:u:D:i:Ib:B:e:x"; + char *sock = NULL; + bool dofork = false; + char *pidfilename = NULL; +@@ -211,6 +212,10 @@ main(int argc, char* argv[]) + debug(D_MISC, "Parsing ignore list"); + parse_networklist(optarg, &ignorenets); + break; ++ case 'I': ++ debug(D_MISC, "Ignore authenticated senders"); ++ ignore_authenticated_senders = true; ++ break; + case 'm': + dontmodifyspam = true; + smfilter.xxfi_flags &= ~SMFIF_CHGBODY; +@@ -278,7 +283,7 @@ main(int argc, char* argv[]) + cout << PACKAGE_NAME << " - Version " << PACKAGE_VERSION << endl; + cout << "SpamAssassin Sendmail Milter Plugin" << endl; + cout << "Usage: spamass-milter -p socket [-b|-B bucket] [-d xx[,yy...]] [-D host]" << endl; +- cout << " [-e defaultdomain] [-f] [-i networks] [-m] [-M]" << endl; ++ cout << " [-e defaultdomain] [-f] [-i networks] [-I] [-m] [-M]" << endl; + cout << " [-P pidfile] [-r nn] [-u defaultuser] [-x]" << endl; + cout << " [-- spamc args ]" << endl; + cout << " -p socket: path to create socket" << endl; +@@ -292,6 +297,7 @@ main(int argc, char* argv[]) + cout << " -f: fork into background" << endl; + cout << " -i: skip (ignore) checks from these IPs or netblocks" << endl; + cout << " example: -i 192.168.12.5,10.0.0.0/8,172.16.0.0/255.255.0.0" << endl; ++ cout << " -I: skip (ignore) checks if sender is authenticated" << endl; + cout << " -m: don't modify body, Content-type: or Subject:" << endl; + cout << " -M: don't modify the message at all" << endl; + cout << " -P pidfile: Put processid in pidfile" << endl; +@@ -746,6 +752,22 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro + } + /* debug(D_ALWAYS, "ZZZ got private context %p", sctx); */ + ++ if (ignore_authenticated_senders) ++ { ++ char *auth_authen; ++ ++ auth_authen = smfi_getsymval(ctx, const_cast<char *>("{auth_authen}")); ++ debug(D_MISC, "auth_authen=%s", auth_authen ?: "<unauthenticated>"); ++ ++ if (auth_authen) ++ { ++ debug(D_MISC, "sender authenticated (%s) - accepting message", ++ auth_authen); ++ debug(D_FUNC, "mlfi_envfrom: exit ignore"); ++ return SMFIS_ACCEPT; ++ } ++ } ++ + debug(D_FUNC, "mlfi_envfrom: enter"); + try { + // launch new SpamAssassin +diff -up spamass-milter-0.3.1/spamass-milter.1.in.authuser spamass-milter-0.3.1/spamass-milter.1.in +--- spamass-milter-0.3.1/spamass-milter.1.in.authuser 2004-03-18 18:37:08.000000000 +0000 ++++ spamass-milter-0.3.1/spamass-milter.1.in 2010-03-23 21:06:27.148897685 +0000 +@@ -14,6 +14,7 @@ + .Op Fl e Ar defaultdomain + .Op Fl f + .Op Fl i Ar networks ++.Op Fl I + .Op Fl m + .Op Fl M + .Op Fl P Ar pidfile +@@ -119,6 +120,8 @@ Multiple + flags will append to the list. + For example, if you list all your internal networks, no outgoing emails + will be filtered. ++.It Fl I ++Ignores messages if the sender has authenticated via SMTP AUTH. + .It Fl m + Disables modification of the + .Ql Subject: diff --git a/spamass-milter-0.3.1-group.patch b/spamass-milter-0.3.1-group.patch new file mode 100644 index 000000000000..1e2a418a3cdf --- /dev/null +++ b/spamass-milter-0.3.1-group.patch @@ -0,0 +1,104 @@ +Add option -g group to have the milter create a group-writeable socket +for communication with the MTA and set the GID of the socket to the +specified group. This makes it possible to use the milter via a +unix-domain socket with Postfix as the MTA (Postfix doesn't run as +root and would otherwise be unable to use the socket). + +http://bugzilla.redhat.com/452248 + +diff -up spamass-milter-0.3.1/spamass-milter.cpp.group spamass-milter-0.3.1/spamass-milter.cpp +--- spamass-milter-0.3.1/spamass-milter.cpp.group 2010-03-24 13:30:19.030834527 +0000 ++++ spamass-milter-0.3.1/spamass-milter.cpp 2010-03-24 13:40:54.712898107 +0000 +@@ -89,6 +89,8 @@ + #endif + #include <errno.h> + ++#include <grp.h> ++ + // C++ includes + #include <cstdio> + #include <cstddef> +@@ -180,8 +182,9 @@ int + main(int argc, char* argv[]) + { + int c, err = 0; +- const char *args = "fd:mMp:P:r:u:D:i:Ib:B:e:x"; ++ const char *args = "fd:mMp:P:r:u:D:i:Ib:B:e:xg:"; + char *sock = NULL; ++ char *group = NULL; + bool dofork = false; + char *pidfilename = NULL; + FILE *pidfile = NULL; +@@ -228,6 +231,9 @@ main(int argc, char* argv[]) + case 'p': + sock = strdup(optarg); + break; ++ case 'g': ++ group = strdup(optarg); ++ break; + case 'P': + pidfilename = strdup(optarg); + break; +@@ -287,6 +293,7 @@ main(int argc, char* argv[]) + cout << " [-P pidfile] [-r nn] [-u defaultuser] [-x]" << endl; + cout << " [-- spamc args ]" << endl; + cout << " -p socket: path to create socket" << endl; ++ cout << " -g group: socket group (perms to 660 as well)" << endl; + cout << " -b bucket: redirect spam to this mail address. The orignal" << endl; + cout << " recipient(s) will not receive anything." << endl; + cout << " -B bucket: add this mail address as a BCC recipient of spam." << endl; +@@ -354,6 +361,30 @@ main(int argc, char* argv[]) + } else { + debug(D_MISC, "smfi_register succeeded"); + } ++ ++ if (group) ++ { ++ struct group *gr; ++ ++ (void) smfi_opensocket(0); ++ gr = getgrnam(group); ++ if (gr) ++ { ++ int rc; ++ rc = chown(sock, (uid_t)-1, gr->gr_gid); ++ if (!rc) ++ { ++ (void) chmod(sock, 0660); ++ } else { ++ perror("group option, chown"); ++ exit(EX_NOPERM); ++ } ++ } else { ++ perror("group option, getgrnam"); ++ exit(EX_NOUSER); ++ } ++ } ++ + debug(D_ALWAYS, "spamass-milter %s starting", PACKAGE_VERSION); + err = smfi_main(); + debug(D_ALWAYS, "spamass-milter %s exiting", PACKAGE_VERSION); +diff -up spamass-milter-0.3.1/spamass-milter.1.in.group spamass-milter-0.3.1/spamass-milter.1.in +--- spamass-milter-0.3.1/spamass-milter.1.in.group 2010-03-24 13:30:19.026834927 +0000 ++++ spamass-milter-0.3.1/spamass-milter.1.in 2010-03-24 13:30:19.033834685 +0000 +@@ -13,6 +13,7 @@ + .Op Fl D Ar host + .Op Fl e Ar defaultdomain + .Op Fl f ++.Op Fl g Ar group + .Op Fl i Ar networks + .Op Fl I + .Op Fl m +@@ -108,6 +109,12 @@ flag. + Causes + .Nm + to fork into the background. ++.It Fl g Ar group ++Makes the socket for communication with the MTA group-writable (mode 0750) ++and sets the socket's group to ++.Ar group . ++This option is intended for use with MTA's like Postfix that do not run as ++root, and is incompatible with Sendmail usage. + .It Fl i Ar networks + Ignores messages if the originating IP is in the network(s) listed. + The message will be passed through without calling SpamAssassin at all. diff --git a/spamass-milter-0.3.1-ipv6.patch b/spamass-milter-0.3.1-ipv6.patch new file mode 100644 index 000000000000..6fb14676fce6 --- /dev/null +++ b/spamass-milter-0.3.1-ipv6.patch @@ -0,0 +1,297 @@ +diff -up spamass-milter-0.3.1/spamass-milter.cpp.ipv6 spamass-milter-0.3.1/spamass-milter.cpp +--- spamass-milter-0.3.1/spamass-milter.cpp.ipv6 2010-09-23 16:26:36.227224902 +0100 ++++ spamass-milter-0.3.1/spamass-milter.cpp 2010-09-23 17:25:22.307099331 +0100 +@@ -88,6 +88,7 @@ + #include "subst_poll.h" + #endif + #include <errno.h> ++#include <netdb.h> + + #include <grp.h> + +@@ -718,12 +719,18 @@ mlfi_connect(SMFICTX * ctx, char *hostna + 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); + } + sctx->assassin = NULL; + sctx->helo = NULL; +@@ -758,12 +765,12 @@ mlfi_connect(SMFICTX * ctx, char *hostna + debug(D_ALWAYS, "smfi_setpriv failed!"); + return SMFIS_TEMPFAIL; + } +- /* debug(D_ALWAYS, "ZZZ set private context to %p", sctx); */ + +- if (ip_in_networklist(sctx->connect_ip, &ignorenets)) ++ debug(D_NET, "Checking %s against:", sctx->connect_ip); ++ 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; + } +@@ -807,7 +814,6 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro + debug(D_ALWAYS, "smfi_getpriv failed!"); + return SMFIS_TEMPFAIL; + } +- /* debug(D_ALWAYS, "ZZZ got private context %p", sctx); */ + + if (ignore_authenticated_senders) + { +@@ -835,7 +841,7 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro + 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; +@@ -2128,69 +2134,135 @@ void parse_networklist(char *string, str + { + 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) +- { +- if (strchr(tmask, '.') == NULL) ++ 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; ++ } else if (inet_pton(AF_INET6, tnet, &net6)) ++ { ++ 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; + } else +- mask.s_addr = 0xffffffff; ++ { ++ fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet); ++ exit(1); ++ } + + { +- char *snet = strdup(inet_ntoa(net)); +- debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask)); +- free(snet); ++ int af = list->nets[list->num_nets].net.af; ++ char addrbuf[INET6_ADDRSTRLEN]; ++ char maskbuf[4]; ++ char *maskstr; ++ ++ if (af == AF_INET6) { ++ inet_ntop(af, &list->nets[list->num_nets].net6.network, ++ addrbuf, INET6_ADDRSTRLEN); ++ sprintf(maskbuf, "%d", list->nets[list->num_nets].net6.netmask); ++ maskstr = maskbuf; ++ list->nets[list->num_nets].net6.addrstr = strdup(addrbuf); ++ list->nets[list->num_nets].net6.maskstr = strdup(maskbuf); ++ } else ++ { ++ inet_ntop(af, &list->nets[list->num_nets].net4.network, ++ addrbuf, INET6_ADDRSTRLEN); ++ maskstr = inet_ntoa(list->nets[list->num_nets].net4.netmask); ++ list->nets[list->num_nets].net4.addrstr = strdup(addrbuf); ++ list->nets[list->num_nets].net4.maskstr = strdup(maskstr); ++ } ++ debug(D_MISC, "Added %s/%s to network list", addrbuf, maskstr); + } + +- 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)); ++ + 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/%s", list->nets[i].net4.addrstr, list->nets[i].net4.maskstr); ++ 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; ++ ++ debug(D_NET, "%s/%s", list->nets[i].net6.addrstr, list->nets[i].net6.maskstr); ++ 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 -up spamass-milter-0.3.1/spamass-milter.h.ipv6 spamass-milter-0.3.1/spamass-milter.h +--- spamass-milter-0.3.1/spamass-milter.h.ipv6 2010-09-23 16:26:36.224160445 +0100 ++++ spamass-milter-0.3.1/spamass-milter.h 2010-09-23 17:00:16.487410690 +0100 +@@ -56,16 +56,34 @@ sfsistat mlfi_abort(SMFICTX*); + 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; ++ char *addrstr; ++ char *maskstr; ++ } net4; ++ struct ++ { ++ uint8_t af; ++ struct in6_addr network; ++ int netmask; /* Just the number of bits for IPv6 */ ++ char *addrstr; ++ char *maskstr; ++ } net6; + }; + + /* an array of networks */ + struct networklist + { +- struct net *nets; ++ union net *nets; + int num_nets; + }; + +@@ -162,7 +180,7 @@ public: + /* 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; + char *our_fqdn; + char *sender_address; +@@ -184,7 +202,7 @@ string::size_type find_nocase(const stri + 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(const char *macro, const char *scope); diff --git a/spamass-milter-0.3.1-pathnames.patch b/spamass-milter-0.3.1-pathnames.patch new file mode 100644 index 000000000000..8c90367f830d --- /dev/null +++ b/spamass-milter-0.3.1-pathnames.patch @@ -0,0 +1,21 @@ +diff -up spamass-milter-0.3.1/README.pathnames spamass-milter-0.3.1/README +--- spamass-milter-0.3.1/README.pathnames 2010-03-23 20:54:37.630904869 +0000 ++++ spamass-milter-0.3.1/README 2010-03-23 20:55:22.007964867 +0000 +@@ -42,7 +42,7 @@ put the spamass-milter binary and set th + you want to use. YOU WILL MOST LIKELY HAVE TO EDIT THE VARIABLES ON + TOP OF THIS FILE. + +-Then start the daemon via /etc/init.d/spamass-milter start and make ++Then start the daemon via /etc/rc.d/init.d/spamass-milter start and make + sure it didn't crash/terminate immediately. If it does, there should + usually be syslog output. + +@@ -54,7 +54,7 @@ Now you need to make sendmail use the pl + configuring sendmail through m4 & the sendmail.mc files. In this case + adding the lines + +-INPUT_MAIL_FILTER(`spamassassin', `S=local:/var/run/sendmail/spamass.sock, F=, T=C:15m;S:4m;R:4m;E:10m')dnl ++INPUT_MAIL_FILTER(`spamassassin', `S=unix:/var/run/spamass-milter/spamass-milter.sock, F=, T=C:15m;S:4m;R:4m;E:10m')dnl + define(`confMILTER_MACROS_ENVRCPT',confMILTER_MACROS_ENVRCPT`, b, r, v, Z')dnl + + should do the trick. Of course you need to modify the path of the diff --git a/spamass-milter-0.3.2-auth-no-ssf.patch b/spamass-milter-0.3.2-auth-no-ssf.patch new file mode 100644 index 000000000000..ce3817330d1e --- /dev/null +++ b/spamass-milter-0.3.2-auth-no-ssf.patch @@ -0,0 +1,28 @@ +This change is to help users with Postfix that aren't using the -I option +to not pass mail from authenticated users through SpamAssassin. Postfix, +unlike Sendmail, does not provide the {auth_ssf} macro, so in the case +where mail is from an authenticated user, the modified code can now add +an (authenticated) hint in the dummy Received: header (where Sendmail would +add (authenticated bits=nnn)), and this is scored favourably by SpamAssassin. + +http://bugzilla.redhat.com/730308 + +--- spamass-milter-0.3.2/spamass-milter.cpp ++++ spamass-milter-0.3.2/spamass-milter.cpp +@@ -1046,9 +1046,14 @@ + + rec_header = (string) "Received: from " + macro_s + " (" + macro__ + ")\r\n\t"; + +- if (strlen(macro_auth_ssf)) ++ if (strlen(macro_auth_authen)) + { +- rec_header += (string) "(authenticated bits=" + macro_auth_ssf + ")\r\n\t"; ++ rec_header += (string) "(authenticated"; ++ if (strlen(macro_auth_ssf)) ++ { ++ rec_header += (string) " bits=" + macro_auth_ssf; ++ } ++ rec_header += (string) ")\r\n\t"; + } + + rec_header += (string) "by " + macro_j + " (" + macro_v + "/" + macro_Z + ") with " + diff --git a/spamass-milter-0.3.2-bits.patch b/spamass-milter-0.3.2-bits.patch new file mode 100644 index 000000000000..8b1cc75ff7de --- /dev/null +++ b/spamass-milter-0.3.2-bits.patch @@ -0,0 +1,289 @@ +Add authenticated bits information into the dummy generated +Received-header for SpamAssassin to facilitate adding a rule +to score mail from authenticated clients. + +Discussion: +http://bugzilla.redhat.com/496769 +http://www.gossamer-threads.com/lists/spamassassin/users/146948 + +This patch also moves some of the macro collection to the +ENVFROM callback, where the required macros are available by default. + +diff -up spamass-milter-0.3.2/README.bits spamass-milter-0.3.2/README +--- spamass-milter-0.3.2/README.bits 2008-04-23 17:11:42.000000000 +0100 ++++ spamass-milter-0.3.2/README 2011-02-15 11:02:47.877271392 +0000 +@@ -55,15 +55,26 @@ configuring sendmail through m4 & the se + adding the lines + + INPUT_MAIL_FILTER(`spamassassin', `S=local:/var/run/sendmail/spamass.sock, F=, T=C:15m;S:4m;R:4m;E:10m')dnl +-define(`confMILTER_MACROS_CONNECT',`t, b, j, _, {daemon_name}, {if_name}, {if_addr}')dnl +-define(`confMILTER_MACROS_HELO',`s, {tls_version}, {cipher}, {cipher_bits}, {cert_subject}, {cert_issuer}')dnl +-define(`confMILTER_MACROS_ENVRCPT',`r, v, Z')dnl ++define(`confMILTER_MACROS_ENVRCPT',confMILTER_MACROS_ENVRCPT`, b, r, v, Z')dnl + + should do the trick. Of course you need to modify the path of the + socket if you put another one into the startup script. The timeouts + have been increased somewhat because SpamAssassin may chew on it for a + little while on a slow machine. + ++If you are using multiple milter mail filters on your mail server, you may ++have overridden the default values of some of the confMILTER_MACROS_* ++macros whilst configuring the other filters. You need to ensure that at ++least the following values are present: ++ ++confMILTER_MACROS_CONNECT must include the {j} and {_} macros ++(all included by default) ++ ++confMILTER_MACROS_ENVFROM must include the {i}, {auth_authen} and {auth_ssf} ++macros (all included by default) ++ ++confMILTER_MACROS_ENVRCPT must include the {b}, {r}, {v}, and {Z} macros ++ + Now recreate sendmail.cf, restart sendmail and experiment around a bit + with the setup to make sure it is working. + +diff -up spamass-milter-0.3.2/spamass-milter.cpp.bits spamass-milter-0.3.2/spamass-milter.cpp +--- spamass-milter-0.3.2/spamass-milter.cpp.bits 2011-02-15 10:53:49.349259089 +0000 ++++ spamass-milter-0.3.2/spamass-milter.cpp 2011-02-15 10:53:49.353259721 +0000 +@@ -678,6 +678,7 @@ sfsistat + mlfi_connect(SMFICTX * ctx, char *hostname, _SOCK_ADDR * hostaddr) + { + struct context *sctx; ++ const char *macro_j, *macro__; + int rv; + + debug(D_FUNC, "mlfi_connect: enter"); +@@ -695,8 +696,31 @@ mlfi_connect(SMFICTX * ctx, char *hostna + } + sctx->assassin = NULL; + sctx->helo = NULL; +- +- /* store a pointer to it with setpriv */ ++ sctx->our_fqdn = NULL; ++ sctx->sender_address = NULL; ++ sctx->queueid = NULL; ++ sctx->auth_authen = NULL; ++ sctx->auth_ssf = NULL; ++ ++ /* store our FQDN */ ++ macro_j = smfi_getsymval(ctx, const_cast<char *>("j")); ++ if (!macro_j) ++ { ++ macro_j = "localhost"; ++ warnmacro("j", "CONNECT"); ++ } ++ sctx->our_fqdn = strdup(macro_j); ++ ++ /* store the validated sending site's address */ ++ macro__ = smfi_getsymval(ctx, const_cast<char *>("_")); ++ if (!macro__) ++ { ++ macro__ = "unknown"; ++ warnmacro("_", "CONNECT"); ++ } ++ sctx->sender_address = strdup(macro__); ++ ++ /* store a pointer to our private data with setpriv */ + rv = smfi_setpriv(ctx, sctx); + if (rv != MI_SUCCESS) + { +@@ -745,7 +769,7 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro + { + SpamAssassin* assassin; + struct context *sctx = (struct context *)smfi_getpriv(ctx); +- const char *queueid; ++ const char *queueid, *macro_auth_ssf, *macro_auth_authen; + + if (sctx == NULL) + { +@@ -787,17 +811,44 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro + + // remember the MAIL FROM address + assassin->set_from(string(envfrom[0])); +- ++ ++ // remember the queueid for this message + queueid=smfi_getsymval(ctx, const_cast<char *>("i")); + if (!queueid) + { + queueid="unknown"; + warnmacro("i", "ENVFROM"); + } +- assassin->queueid = queueid; +- ++ sctx->queueid = strdup(queueid); + debug(D_MISC, "queueid=%s", queueid); + ++ // remember the SMTP AUTH login name ++ macro_auth_authen = smfi_getsymval(ctx, const_cast<char *>("{auth_authen}")); ++ if (!macro_auth_authen) ++ { ++ macro_auth_authen = ""; ++ // Don't issue a warning for the auth_authen macro as ++ // it is likely to be unset much of the time - it's ++ // only set if the client has authenticated. ++ // ++ // Similarly, we only issue warnings for the other ++ // auth-related macros if {auth_authen) is available. ++ // ++ // warnmacro("auth_authen", "ENVFROM"); ++ } ++ sctx->auth_authen = strdup(macro_auth_authen); ++ ++ // remember the SASL cipher bits ++ macro_auth_ssf = smfi_getsymval(ctx, const_cast<char *>("{auth_ssf}")); ++ if (!macro_auth_ssf) ++ { ++ macro_auth_ssf = ""; ++ if (strlen(macro_auth_authen)) { ++ warnmacro("auth_ssf", "ENVFROM"); ++ } ++ } ++ sctx->auth_ssf = strdup(macro_auth_ssf); ++ + // tell Milter to continue + debug(D_FUNC, "mlfi_envfrom: exit"); + +@@ -888,7 +939,8 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + + */ + const char *macro_b, *macro_i, *macro_j, *macro_r, +- *macro_s, *macro_v, *macro_Z, *macro__; ++ *macro_s, *macro_v, *macro_Z, *macro__, ++ *macro_auth_ssf, *macro_auth_authen; + char date[32]; + + /* RFC 822 date. */ +@@ -903,20 +955,13 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + } + + /* queue ID */ +- macro_i = smfi_getsymval(ctx, const_cast<char *>("i")); +- if (!macro_i) +- { +- macro_i = "unknown"; +- warnmacro("i", "ENVRCPT"); +- } ++ macro_i = sctx->queueid; + +- /* FQDN of this site */ +- macro_j = smfi_getsymval(ctx, const_cast<char *>("j")); +- if (!macro_j) +- { +- macro_j = "localhost"; +- warnmacro("j", "ENVRCPT"); +- } ++ /* FQDN */ ++ macro_j = sctx->our_fqdn; ++ ++ /* Sender address */ ++ macro__ = sctx->sender_address; + + /* Protocol used to receive the message */ + macro_r = smfi_getsymval(ctx, const_cast<char *>("r")); +@@ -925,7 +970,11 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + macro_r = "SMTP"; + warnmacro("r", "ENVRCPT"); + } +- ++ ++ /* SMTP AUTH details */ ++ macro_auth_authen = sctx->auth_authen; ++ macro_auth_ssf = sctx->auth_ssf; ++ + /* Sendmail currently cannot pass us the {s} macro, but + I do not know why. Leave this in for the day sendmail is + fixed. Until that day, use the value remembered by +@@ -953,22 +1002,25 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + warnmacro("Z", "ENVRCPT"); + } + +- /* Validated sending site's address */ +- macro__ = smfi_getsymval(ctx, const_cast<char *>("_")); +- if (!macro__) ++ assassin->output((string)"X-Envelope-From: "+assassin->from()+"\r\n"); ++ assassin->output((string)"X-Envelope-To: "+envrcpt[0]+"\r\n"); ++ ++ string rec_header; ++ ++ rec_header = (string) "Received: from " + macro_s + " (" + macro__ + ")\r\n\t"; ++ ++ if (strlen(macro_auth_ssf)) + { +- macro__ = "unknown"; +- warnmacro("_", "ENVRCPT"); ++ rec_header += (string) "(authenticated bits=" + macro_auth_ssf + ")\r\n\t"; + } + +- assassin->output((string)"X-Envelope-From: "+assassin->from()+"\r\n"); +- assassin->output((string)"X-Envelope-To: "+envrcpt[0]+"\r\n"); ++ rec_header += (string) "by " + macro_j + " (" + macro_v + "/" + macro_Z + ") with " + ++ macro_r + " id " + macro_i + ";\r\n\t" + ++ macro_b + "\r\n\t" + ++ "(envelope-from " + assassin->from() + ")\r\n"; + +- assassin->output((string) +- "Received: from "+macro_s+" ("+macro__+")\r\n\t"+ +- "by "+macro_j+" ("+macro_v+"/"+macro_Z+") with "+macro_r+" id "+macro_i+";\r\n\t"+ +- macro_b+"\r\n\t"+ +- "(envelope-from "+assassin->from()+")\r\n"); ++ debug(D_SPAMC, "Received header for spamc: %s", rec_header.c_str()); ++ assassin->output(rec_header); + + } else + assassin->output((string)"X-Envelope-To: "+envrcpt[0]+"\r\n"); +@@ -1214,16 +1266,27 @@ mlfi_close(SMFICTX* ctx) + { + struct context *sctx; + debug(D_FUNC, "mlfi_close"); +- ++ + sctx = (struct context*)smfi_getpriv(ctx); + if (sctx == NULL) + return SMFIS_ACCEPT; + + if (sctx->helo) + free(sctx->helo); ++ if (sctx->our_fqdn) ++ free(sctx->our_fqdn); ++ if (sctx->sender_address) ++ free(sctx->sender_address); ++ if (sctx->queueid) ++ free(sctx->queueid); ++ if (sctx->auth_authen) ++ free(sctx->auth_authen); ++ if (sctx->auth_ssf) ++ free(sctx->auth_ssf); ++ + free(sctx); + smfi_setpriv(ctx, NULL); +- ++ + return SMFIS_ACCEPT; + } + +diff -up spamass-milter-0.3.2/spamass-milter.h.bits spamass-milter-0.3.2/spamass-milter.h +--- spamass-milter-0.3.2/spamass-milter.h.bits 2011-02-15 10:53:49.342257983 +0000 ++++ spamass-milter-0.3.2/spamass-milter.h 2011-02-15 10:53:49.354259879 +0000 +@@ -154,9 +154,6 @@ public: + // List of recipients after alias/virtusertable expansion + list <string> expandedrcpt; + +- // the sendmail queue id for this message; used for logging +- string queueid; +- + // Process handling variables + pid_t pid; + int pipe_io[2][2]; +@@ -167,6 +164,11 @@ struct context + { + struct in_addr connect_ip; // remote IP address + char *helo; ++ char *our_fqdn; ++ char *sender_address; ++ char *queueid; ++ char *auth_authen; ++ char *auth_ssf; + SpamAssassin *assassin; // pointer to the SA object if we're processing a message + }; + diff --git a/spamass-milter-0.3.2-rcvd.patch b/spamass-milter-0.3.2-rcvd.patch new file mode 100644 index 000000000000..7db55b12aab6 --- /dev/null +++ b/spamass-milter-0.3.2-rcvd.patch @@ -0,0 +1,23 @@ +The code in spamass-milter.cpp that tries to create a +Sendmail-compatible header was broken and generated a header +that was incorrectly parsed by SpamAssassin. + +This is mostly fixed now apart from the space that needs +adding prior to the "(" between macro_j and macro_v. + +https://savannah.nongnu.org/bugs/index.php?17178 +http://bugs.debian.org/510665 +http://bugzilla.redhat.com/496763 + +diff -up spamass-milter-0.3.2/spamass-milter.cpp.rcvd spamass-milter-0.3.2/spamass-milter.cpp +--- spamass-milter-0.3.2/spamass-milter.cpp.rcvd 2011-02-15 10:46:55.000000000 +0000 ++++ spamass-milter-0.3.2/spamass-milter.cpp 2011-02-15 10:50:25.538111680 +0000 +@@ -966,7 +966,7 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + + assassin->output((string) + "Received: from "+macro_s+" ("+macro__+")\r\n\t"+ +- "by "+macro_j+"("+macro_v+"/"+macro_Z+") with "+macro_r+" id "+macro_i+";\r\n\t"+ ++ "by "+macro_j+" ("+macro_v+"/"+macro_Z+") with "+macro_r+" id "+macro_i+";\r\n\t"+ + macro_b+"\r\n\t"+ + "(envelope-from "+assassin->from()+")\r\n"); + diff --git a/spamass-milter-0.3.2-rundir.patch b/spamass-milter-0.3.2-rundir.patch new file mode 100644 index 000000000000..ec08358ddea6 --- /dev/null +++ b/spamass-milter-0.3.2-rundir.patch @@ -0,0 +1,30 @@ +diff -up spamass-milter-0.3.2/README.orig spamass-milter-0.3.2/README +--- spamass-milter-0.3.2/README.orig 2011-07-25 15:23:45.490316629 +0100 ++++ spamass-milter-0.3.2/README 2011-07-25 15:27:47.647628663 +0100 +@@ -54,7 +54,7 @@ Now you need to make sendmail use the pl + configuring sendmail through m4 & the sendmail.mc files. In this case + adding the lines + +-INPUT_MAIL_FILTER(`spamassassin', `S=unix:/var/run/spamass-milter/spamass-milter.sock, F=, T=C:15m;S:4m;R:4m;E:10m')dnl ++INPUT_MAIL_FILTER(`spamassassin', `S=unix:/run/spamass-milter/spamass-milter.sock, F=, T=C:15m;S:4m;R:4m;E:10m')dnl + define(`confMILTER_MACROS_ENVRCPT',confMILTER_MACROS_ENVRCPT`, b, r, v, Z')dnl + + should do the trick. Of course you need to modify the path of the +diff -up spamass-milter-0.3.2/README.Postfix.orig spamass-milter-0.3.2/README.Postfix +--- spamass-milter-0.3.2/README.Postfix.orig 2011-07-21 16:37:39.731590093 +0100 ++++ spamass-milter-0.3.2/README.Postfix 2011-07-25 15:26:45.575801806 +0100 +@@ -2,12 +2,12 @@ Installing the spamass-milter-postfix pa + of spamass-milter to be more Postfix-friendly, i.e.: + + The Unix-domain socket used for MTA communication is changed to +- /var/run/spamass-milter/postfix/sock, and that socket is ++ /run/spamass-milter/postfix/sock, and that socket is + writable by the postfix group. + + To configure Postfix to use the milter, add to /etc/postfix/main.cf: + +- smtpd_milters = unix:/var/run/spamass-milter/postfix/sock ++ smtpd_milters = unix:/run/spamass-milter/postfix/sock + + For further information, see: + http://www.postfix.org/MILTER_README.html diff --git a/spamass-milter-0.3.2-syntax.patch b/spamass-milter-0.3.2-syntax.patch new file mode 100644 index 000000000000..3d1bc683e56e --- /dev/null +++ b/spamass-milter-0.3.2-syntax.patch @@ -0,0 +1,248 @@ +Fix compiler warnings in recent gcc versions, mainly relating to deprecated +conversions from string constants to char *. + +Most of these relate to missing "const" declarations in the libmilter API +so I just used const_cast to clear them. For non libmilter-related issues, +I tried to fix them more cleanly. + +The only other change of note is to check the result of the fwrite() +function and log a warning if all of the data wasn't written (this is in +the spambucket code). + +diff -up spamass-milter-0.3.2/spamass-milter.cpp.syntax spamass-milter-0.3.2/spamass-milter.cpp +--- spamass-milter-0.3.2/spamass-milter.cpp.syntax 2011-02-14 21:53:02.000000000 +0000 ++++ spamass-milter-0.3.2/spamass-milter.cpp 2011-02-15 10:09:59.748036059 +0000 +@@ -129,9 +129,11 @@ int daemon(int nochdir, int noclose); + + static const char Id[] = "$Id: spamass-milter.cpp,v 1.94 2011/02/14 21:50:53 dnelson Exp $"; + ++static char FilterName[] = "SpamAssassin"; ++ + struct smfiDesc smfilter = + { +- "SpamAssassin", // filter name ++ FilterName, // filter name + SMFI_VERSION, // version code -- leave untouched + SMFIF_ADDHDRS|SMFIF_CHGHDRS|SMFIF_CHGBODY, // flags + mlfi_connect, // info filter callback +@@ -357,7 +359,7 @@ main(int argc, char* argv[]) + // }}} + + /* 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"); +@@ -383,12 +385,12 @@ void update_or_insert(SpamAssassin* assa + if (oldsize > 0) + { + debug(D_UORI, "u_or_i: changing"); +- smfi_chgheader(ctx, header, 1, newstring.size() > 0 ? ++ smfi_chgheader(ctx, const_cast<char*>(header), 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, const_cast<char*>(header), cstr); + } + } else + { +@@ -448,7 +450,7 @@ assassinate(SMFICTX* ctx, SpamAssassin* + if (do_reject) + { + debug(D_MISC, "Rejecting"); +- smfi_setreply(ctx, "550", "5.7.1", "Blocked by SpamAssassin"); ++ smfi_setreply(ctx, const_cast<char*>("550"), const_cast<char*>("5.7.1"), const_cast<char*>("Blocked by SpamAssassin")); + + + if (flag_bucket) +@@ -457,14 +459,11 @@ assassinate(SMFICTX* ctx, SpamAssassin* + send another copy. The milter API will not let you send the + message AND return a failure code to the sender, so this is + the only way to do it. */ +- char *popen_argv[3]; ++ char sendmail_prog[] = SENDMAIL; ++ char * const popen_argv[3] = { sendmail_prog, spambucket, NULL }; + 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", &pid); + if (!p) +@@ -473,7 +472,10 @@ assassinate(SMFICTX* ctx, SpamAssassin* + } else + { + // Send message provided by SpamAssassin +- fwrite(assassin->d().c_str(), assassin->d().size(), 1, p); ++ if (fwrite(assassin->d().c_str(), assassin->d().size(), 1, p) != 1) ++ { ++ debug(D_COPY, "fwrite incomplete (%s) when copying to spambucket", strerror(errno)); ++ } + fclose(p); p = NULL; + waitpid(pid, NULL, 0); + } +@@ -494,7 +496,7 @@ assassinate(SMFICTX* ctx, SpamAssassin* + // time. Note, this may generate multiple X-Spam-Orig-To + // headers, but that's okay. + while( !assassin->recipients.empty()) { +- if ( smfi_addheader( ctx, "X-Spam-Orig-To", (char *)assassin->recipients.front().c_str()) != MI_SUCCESS ) { ++ if ( smfi_addheader( ctx, const_cast<char *>("X-Spam-Orig-To"), (char *)assassin->recipients.front().c_str()) != MI_SUCCESS ) { + throw string( "Failed to save recipient" ); + } + +@@ -737,7 +739,7 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro + { + SpamAssassin* assassin; + struct context *sctx = (struct context *)smfi_getpriv(ctx); +- char *queueid; ++ const char *queueid; + + if (sctx == NULL) + { +@@ -764,7 +766,7 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro + // remember the MAIL FROM address + assassin->set_from(string(envfrom[0])); + +- queueid=smfi_getsymval(ctx,"i"); ++ queueid=smfi_getsymval(ctx, const_cast<char *>("i")); + if (!queueid) + { + queueid="unknown"; +@@ -802,14 +804,11 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + /* open a pipe to sendmail so we can do address expansion */ + + char buf[1024]; +- char *popen_argv[4]; ++ char sendmail_prog[] = SENDMAIL; ++ char sendmail_mode[] = "-bv"; ++ char * const popen_argv[4] = { sendmail_prog, sendmail_mode, envrcpt[0], NULL }; + pid_t pid; + +- popen_argv[0] = SENDMAIL; +- popen_argv[1] = "-bv"; +- popen_argv[2] = envrcpt[0]; +- popen_argv[3] = NULL; +- + debug(D_RCPT, "calling %s -bv %s", SENDMAIL, envrcpt[0]); + + p = popenv(popen_argv, "r", &pid); +@@ -871,7 +870,7 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + char date[32]; + + /* RFC 822 date. */ +- macro_b = smfi_getsymval(ctx, "b"); ++ macro_b = smfi_getsymval(ctx, const_cast<char *>("b")); + if (!macro_b) + { + time_t tval; +@@ -882,7 +881,7 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + } + + /* queue ID */ +- macro_i = smfi_getsymval(ctx, "i"); ++ macro_i = smfi_getsymval(ctx, const_cast<char *>("i")); + if (!macro_i) + { + macro_i = "unknown"; +@@ -890,7 +889,7 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + } + + /* FQDN of this site */ +- macro_j = smfi_getsymval(ctx, "j"); ++ macro_j = smfi_getsymval(ctx, const_cast<char *>("j")); + if (!macro_j) + { + macro_j = "localhost"; +@@ -898,7 +897,7 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + } + + /* Protocol used to receive the message */ +- macro_r = smfi_getsymval(ctx, "r"); ++ macro_r = smfi_getsymval(ctx, const_cast<char *>("r")); + if (!macro_r) + { + macro_r = "SMTP"; +@@ -910,14 +909,14 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + fixed. Until that day, use the value remembered by + mlfi_helo() + */ +- macro_s = smfi_getsymval(ctx, "s"); ++ macro_s = smfi_getsymval(ctx, const_cast<char *>("s")); + if (!macro_s) + macro_s = sctx->helo; + if (!macro_s) + macro_s = "nohelo"; + + /* Sendmail binary version */ +- macro_v = smfi_getsymval(ctx, "v"); ++ macro_v = smfi_getsymval(ctx, const_cast<char *>("v")); + if (!macro_v) + { + macro_v = "8.13.0"; +@@ -925,7 +924,7 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + } + + /* Sendmail .cf version */ +- macro_Z = smfi_getsymval(ctx, "Z"); ++ macro_Z = smfi_getsymval(ctx, const_cast<char *>("Z")); + if (!macro_Z) + { + macro_Z = "8.13.0"; +@@ -933,7 +932,7 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp + } + + /* Validated sending site's address */ +- macro__ = smfi_getsymval(ctx, "_"); ++ macro__ = smfi_getsymval(ctx, const_cast<char *>("_")); + if (!macro__) + { + macro__ = "unknown"; +@@ -1321,10 +1320,10 @@ void SpamAssassin::Connect() + // XXX arbitrary 100-argument max + int argc = 0; + char** argv = (char**) malloc(100*sizeof(char*)); +- argv[argc++] = SPAMC; ++ argv[argc++] = strdup(SPAMC); + if (flag_sniffuser) + { +- argv[argc++] = "-u"; ++ argv[argc++] = strdup("-u"); + if ( expandedrcpt.size() != 1 ) + { + // More (or less?) than one recipient, so we pass the default +@@ -1349,7 +1348,7 @@ void SpamAssassin::Connect() + } + if (spamdhost) + { +- argv[argc++] = "-d"; ++ argv[argc++] = strdup("-d"); + argv[argc++] = spamdhost; + } + if (spamc_argc) +@@ -2091,7 +2090,7 @@ char *strlwr(char *str) + } + + /* Log a message about missing milter macros, but only the first time */ +-void warnmacro(char *macro, char *scope) ++void warnmacro(const char *macro, const char *scope) + { + if (warnedmacro) + return; +diff -up spamass-milter-0.3.2/spamass-milter.h.syntax spamass-milter-0.3.2/spamass-milter.h +--- spamass-milter-0.3.2/spamass-milter.h.syntax 2011-02-14 21:53:02.000000000 +0000 ++++ spamass-milter-0.3.2/spamass-milter.h 2011-02-15 10:06:33.788736593 +0000 +@@ -185,7 +185,7 @@ void parse_networklist(char *string, str + int ip_in_networklist(struct in_addr ip, struct networklist *list); + void parse_debuglevel(char* string); + char *strlwr(char *str); +-void warnmacro(char *macro, char *scope); ++void warnmacro(const char *macro, const char *scope); + FILE *popenv(char *const argv[], const char *type, pid_t *pid); + + #endif diff --git a/spamass-milter-postfix-sysconfig.systemd b/spamass-milter-postfix-sysconfig.systemd new file mode 100644 index 000000000000..7607d86969ac --- /dev/null +++ b/spamass-milter-postfix-sysconfig.systemd @@ -0,0 +1,5 @@ +# For Postfix support, use a postfix-group-writable socket +# for communication with the MTA +# This uses a Debian-style chrooted postfix +SOCKET="/var/spool/postfix/spamass/spamass.sock" +SOCKET_OPTIONS="-g postfix" diff --git a/spamass-milter-postfix-tmpfs.conf b/spamass-milter-postfix-tmpfs.conf new file mode 100644 index 000000000000..4b4a1fade0e9 --- /dev/null +++ b/spamass-milter-postfix-tmpfs.conf @@ -0,0 +1 @@ +d /var/spool/postfix/spamass 750 sa-milt postfix diff --git a/spamass-milter-root.service b/spamass-milter-root.service new file mode 100644 index 000000000000..2db402a50df8 --- /dev/null +++ b/spamass-milter-root.service @@ -0,0 +1,30 @@ +# Note: this unit file runs spamass-milter as the privileged user root, +# which is necessary for using the milter's -x option for performing +# virtusertable and alias expansion. If you are not using the -x option, +# there is no need for the milter to run as root and it is best not to do so, +# using the spamass-milter.service unit instead of this one. + +[Unit] +Description = Mail filter for SpamAssassin +Wants = spamassassin.service +After = syslog.target +After = local-fs.target +After = network.target +After = spamassassin.service +Before = sendmail.service +Before = postfix.service +Conflicts = spamass-milter.service + +[Service] +Type = simple +UMask = 0022 +Environment = SOCKET=/run/spamass-milter/spamass-milter.sock SOCKET_OPTIONS= EXTRA_FLAGS= +EnvironmentFile = -/etc/spamass-milter +EnvironmentFile = -/etc/spamass-milter-postfix +ExecStartPre = /usr/bin/chown -R root /run/spamass-milter +ExecStart = /usr/bin/spamass-milter $SOCKET_OPTIONS -p $SOCKET $EXTRA_FLAGS +ExecStopPost = /usr/bin/chown -R sa-milt /run/spamass-milter + +[Install] +WantedBy = multi-user.target + diff --git a/spamass-milter-sysconfig.systemd b/spamass-milter-sysconfig.systemd new file mode 100644 index 000000000000..995ab3042c79 --- /dev/null +++ b/spamass-milter-sysconfig.systemd @@ -0,0 +1,14 @@ +### Override for your different local config if necessary +#SOCKET=/run/spamass-milter/spamass-milter.sock + +### You may add configuration parameters here, see spamass-milter(1) +### +### Note that the -x option for expanding aliases and virtusertable entries +### only works if spamass-milter is run as root; you will need to use +### spamass-milter-root.service instead of spamass-milter.service if you +### wish to do this but otherwise it's best to run as the unprivileged user +### sa-milt by using the normal spamass-milter.service +#EXTRA_FLAGS="-m -r 15" + +# Some sane defaults (don't modify message too much; reject if score is too high; ignore authenticated senders; ignore outgoing mail) +EXTRA_FLAGS="-m -r 15 -I -i 127.0.0.1" diff --git a/spamass-milter-tmpfs.conf b/spamass-milter-tmpfs.conf new file mode 100644 index 000000000000..621426eee4cd --- /dev/null +++ b/spamass-milter-tmpfs.conf @@ -0,0 +1 @@ +d /run/spamass-milter 711 sa-milt sa-milt diff --git a/spamass-milter.install b/spamass-milter.install new file mode 100644 index 000000000000..d2a4b77355fc --- /dev/null +++ b/spamass-milter.install @@ -0,0 +1,53 @@ +setup_user() { + /usr/bin/getent group sa-milt >/dev/null || (/usr/bin/groupadd -r sa-milt && echo "Added sa-milt group") + /usr/bin/getent passwd sa-milt >/dev/null || \ + (/usr/bin/useradd -r -g sa-milt -d /var/lib/spamass-milter \ + -s /usr/bin/nologin -c "SpamAssassin Milter" sa-milt && echo "Added sa-milt user") + # Fix homedir for upgrades + /usr/bin/usermod --home /var/lib/spamass-milter sa-milt &>/dev/null + + # This is needed because the milter needs to "give away" the MTA communication + # socket to the postfix group, and it needs to be a member of the group to do + # that. + # (Adds sa-milt user to postfix group if postfix group exists) + /usr/bin/getent group postfix >/dev/null && /usr/bin/usermod -a -G postfix sa-milt +} + +# arg 1: the new package version +post_install() { + setup_user + systemctl daemon-reload + systemd-tmpfiles --create /usr/lib/tmpfiles.d/spamass-milter.conf + systemd-tmpfiles --create /usr/lib/tmpfiles.d/spamass-milter-postfix.conf + echo "Use the systemd unit spamass-milter.service or spamass-milter-root.service depending on your needs." +} + +# arg 1: the new package version +# arg 2: the old package version +post_upgrade() { + setup_user + systemctl daemon-reload + systemd-tmpfiles --create /usr/lib/tmpfiles.d/spamass-milter.conf + systemd-tmpfiles --create /usr/lib/tmpfiles.d/spamass-milter-postfix.conf + systemctl try-restart spamass-milter.service + systemctl try-restart spamass-milter-root.service +} + +# arg 1: the old package version +pre_remove() { + echo "Stopping and disabling spamass-milter service(s)" + systemctl disable spamass-milter.service + systemctl disable spamass-milter-root.service + systemctl stop spamass-milter.service + systemctl stop spamass-milter-root.service +} + +# arg 1: the old package version +post_remove() { + systemctl daemon-reload + /usr/bin/userdel sa-milt && echo "Removed sa-milt user" + # Since sa-milt should be the only user in the sa-milt group, by default removing the user will also remove the group. But we add this extra check just in case. + /usr/bin/getent group sa-milt >/dev/null || (/usr/bin/groupdel sa-milt && echo "Removed sa-milt group") +} + +# vim:set ts=2 sw=2 et: diff --git a/spamass-milter.service b/spamass-milter.service new file mode 100644 index 000000000000..7a947af741a2 --- /dev/null +++ b/spamass-milter.service @@ -0,0 +1,29 @@ +# Note: this unit file runs spamass-milter as the unprivileged user sa-milt, +# which is not compatible with the milter's -x option for performing +# virtusertable and alias expansion. If you are not using the -x option, +# there is no need for the milter to run as root and it is best not to do so. +# However, if you are using the -x option, you will need to run the milter as +# root and should use the spamass-milter-root.service unit instead of this one. + +[Unit] +Description = Mail filter for SpamAssassin +Wants = spamassassin.service +After = syslog.target +After = local-fs.target +After = network.target +After = spamassassin.service +Before = sendmail.service +Before = postfix.service +Conflicts = spamass-milter-root.service + +[Service] +Type = simple +UMask = 0022 +Environment = SOCKET=/run/spamass-milter/spamass-milter.sock SOCKET_OPTIONS= EXTRA_FLAGS= +EnvironmentFile = -/etc/spamass-milter +EnvironmentFile = -/etc/spamass-milter-postfix +User = sa-milt +ExecStart = /usr/bin/spamass-milter $SOCKET_OPTIONS -p $SOCKET $EXTRA_FLAGS + +[Install] +WantedBy = multi-user.target |