From 413f75403bde6b1d19df67ffb7329a41212c1868 Mon Sep 17 00:00:00 2001 Message-Id: <413f75403bde6b1d19df67ffb7329a41212c1868.1715714616.git.mdw@distorted.org.uk> From: Mark Wooding Date: Mon, 20 Jan 2014 15:56:21 +0000 Subject: [PATCH] Remove `qmail-checkspam'. Organization: Straylight/Edgeware From: Mark Wooding It's too annoying to build and maintain. --- Makefile.am | 8 -- configure.ac | 3 - debian/control | 10 +- debian/inst | 2 - qmail-checkspam.8 | 66 ---------- qmail-checkspam.c | 327 ---------------------------------------------- 6 files changed, 1 insertion(+), 415 deletions(-) delete mode 100644 qmail-checkspam.8 delete mode 100644 qmail-checkspam.c diff --git a/Makefile.am b/Makefile.am index f660e70..86027e8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -110,14 +110,6 @@ gorp_LDADD = $(catacomb_LIBS) dist_man_MANS += gorp.1 endif -## qmail-checkspam -if HAVE_LIBSPAMC -sbin_PROGRAMS += qmail-checkspam -qmail_checkspam_SOURCES = qmail-checkspam.c -qmail_checkspam_LDADD = -lspamc -dist_man_MANS += qmail-checkspam.8 -endif - ## cdb tools if HAVE_LIBCDB bin_PROGRAMS += cdb-probe cdb-check-domain diff --git a/configure.ac b/configure.ac index b171850..f0fa614 100644 --- a/configure.ac +++ b/configure.ac @@ -59,9 +59,6 @@ LIBS=$OLIBS AC_CHECK_LIB([cdb], [cdb_seek], [have_cdb=yes], [have_cdb=no]) AM_CONDITIONAL([HAVE_LIBCDB], [test $have_cdb = yes]) -AC_CHECK_LIB([spamc], [message_filter], [have_spamc=yes], [have_spamc=no]) -AM_CONDITIONAL([HAVE_LIBSPAMC], [test $have_spamc = yes]) - ## Packages. PKG_CHECK_MODULES([mLib], [mLib >= 2.0.4], [have_mLib=yes], [have_mLib=no]) AM_CONDITIONAL([HAVE_MLIB], [test $have_mLib = yes]) diff --git a/debian/control b/debian/control index 55fa6dd..612e813 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: utils Priority: extra Maintainer: Mark Wooding Build-Depends: tinycdb, debhelper (>= 9), python, python-cdb, - catacomb-dev (>= 2.1.1), mlib-dev (>= 2.0.4), libspamc-dev, libcdb-dev + catacomb-dev (>= 2.1.1), mlib-dev (>= 2.0.4), libcdb-dev Standards-Version: 3.1.1 Package: nsict-utils @@ -13,7 +13,6 @@ Depends: mdwopt-perl, nsict-cdb, locking, - qmail-checkspam, nsict-mail, if-mtu, shadowfix, @@ -62,13 +61,6 @@ Section: utils Depends: ${shlibs:Depends} Description: Run a program while holding a file lock. -Package: qmail-checkspam -Architecture: any -Section: mail -Depends: ${shlibs:Depends}, qmail -Suggests: spamassassin -Description: Check mail for spamminess before queueing it. - Package: nsict-mail Architecture: all Section: mail diff --git a/debian/inst b/debian/inst index 25007bf..e704da3 100644 --- a/debian/inst +++ b/debian/inst @@ -33,8 +33,6 @@ pause pause /usr/bin pause.1 pause /usr/share/man/man1 prlimit prlimit /usr/bin prlimit.1 prlimit /usr/share/man/man1 -qmail-checkspam qmail-checkspam /usr/sbin -qmail-checkspam.8 qmail-checkspam /usr/share/man/man8 shadowfix shadowfix /usr/sbin shadowfix.8 shadowfix /usr/share/man/man8 space space /usr/bin diff --git a/qmail-checkspam.8 b/qmail-checkspam.8 deleted file mode 100644 index 09619c9..0000000 --- a/qmail-checkspam.8 +++ /dev/null @@ -1,66 +0,0 @@ -.\" -*-nroff-*- -.TH qmail-checkspam 8 "9 October 2003" "Straylight/Edgeware" -.SH NAME -qmail-checkspam \- check messages for spam before queueing them -.SH SYNOPSIS -.B qmail-checkspam -.SH DESCRIPTION -The -.B qmail-checkspam -program provides the same interface as -.BR qmail-queue (8). -It reads a message on file descriptor 0, and passes it to -.BR spamd (8). -If -.B spamd -thinks the message is spam, then -.B qmail-checkspam -exits 31, indicating a permanent refusal. -Otherwise, -.B qmail-checkspam -feeds the message, augmented by SpamAssassin's -.B X-Spam-Status -header, to -.BR qmail-queue (8). -.PP -You will usually run -.B qmail-checkspam -by applying the -.B QMAILQUEUE -patch to -.BR qmail (7) -and setting the -.B QMAILQUEUE -environment variable to refer to -.B qmail-checkspam -in, e.g., the -.B /etc/hosts.deny -file (see -.BR hosts_options (5)). -.SH ENVIRONMENT -.TP -.B QMAIL_CHECKSPAM_SPAMDHOST -The hostname or IP address of the -.B spamd -to connect to. Default is -.BR localhost . -.TP -.B QMAIL_CHECKSPAM_SPAMDPORT -The port number to connect to. The default is -.BR 783 . -.TP -.B QMAIL_CHECKSPAM_THRESH -The threshold score for rejection. The default is whatever -.B spamd -is configured to. -.TP -.B QMAIL_CHECKSPAM_QUEUE -The -.BR qmail-queue -compatible -program to pass good mail to. The default is -.BR /var/qmail/bin/qmail-queue . -.SH BUGS -None known. -.SH AUTHOR -Mark Wooding, - diff --git a/qmail-checkspam.c b/qmail-checkspam.c deleted file mode 100644 index b6595fa..0000000 --- a/qmail-checkspam.c +++ /dev/null @@ -1,327 +0,0 @@ -/* -*-c-*- - * - * $Id: qmail-checkspam.c,v 1.2 2004/04/08 01:36:26 mdw Exp $ - * - * Filter messages for spam - * - * (c) 2003 Mark Wooding - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include - -/*----- Main code ---------------------------------------------------------*/ - -static const char *strenv(const char *e, const char *d) -{ - const char *p = getenv(e); - if (!p) return (d); - return (p); -} - -static double dblenv(const char *e, double d) -{ - const char *p = getenv(e); - char *q; - int err = errno; - double f; - if (!p) return (d); - errno = 0; - f = strtod(p, &q); - if (errno) { - syslog(LOG_ERR, "bad floating value `%s' for %s'; ignoring", p, e); - return (d); - } - errno = err; - return (f); -} - -static int intenv(const char *e, int d) -{ - const char *p = getenv(e); - char *q; - int err = errno; - long l; - if (!p) return (d); - errno = 0; - l = strtol(p, &q, 0); - if (errno) return (d); - errno = err; - if (l < 0 || l > INT_MAX) { - syslog(LOG_ERR, "bad integer value `%s' for `%s'; ignoring", p, e); - return (d); - } - return ((int)l); -} - -static int safewrite(int fd, const void *p, size_t sz) -{ - const char *pp = p; - ssize_t n; - - while (sz > 0) { - n = write(fd, pp, sz); - if (sz <= 0 && errno != EINTR && errno != EAGAIN) - return (-1); - sz -= n; - pp += n; - } - return (0); -} - -static int shovel(int from, int to, const char *what) -{ - char buf[4096]; - ssize_t n; - - for (;;) { - n = read(from, buf, sizeof(buf)); - if (n < 0 && errno != EINTR && errno != EAGAIN) { - syslog(LOG_ERR, "failed to read %s: %m", what); - return (-1); - } - else if (!n) - return (0); - if (safewrite(to, buf, n) < 0) { - syslog(LOG_ERR, "failed to write %s: %m", what); - return (-1); - } - } -} - -#define ENVBUF 4096 -#define NRCPT 16 -struct envelope { - unsigned f; -#define EF_TRUNC 1u - char buf[ENVBUF + 1]; - size_t n; - const char *send; - const char *rcpt[NRCPT]; - size_t nrcpt; -}; - -static int readenv(struct envelope *e) -{ - ssize_t n; - const char *p, *l; - - /* Read the raw envelope data. */ - e->n = 0; - e->f = 0; - while (e->n < ENVBUF) { - n = read(1, e->buf + e->n, ENVBUF - e->n); - if (n < 0 && errno != EINTR && errno != EAGAIN) { - syslog(LOG_ERR, "failed to read envelope: %m"); - return (-1); - } - if (!n) break; - e->n += n; - } - e->buf[e->n] = 0; - - /* Parse up the envelope data. */ - p = e->buf; l = p + e->n; - e->nrcpt = 0; - if (*p++ != 'F') { - e->send = ""; - syslog(LOG_ERR, "corrupt envelope (no sender marker)"); - return (-1); - } - e->send = p; - for (;;) { - if (p >= l) goto trunc; - else if (!*p++) break; - } - - for (;;) { - if (p >= l) goto trunc; - if (!*p) break; - else if (*p++ != 'T') { - syslog(LOG_ERR, "corrupt envelope (no recipient marker)"); - return (-1); - } - if (p >= l) goto trunc; - if (e->nrcpt < NRCPT) e->rcpt[e->nrcpt++] = p; - for (;;) { - if (p >= l) goto trunc; - else if (!*p++) break; - } - } - return (0); - - /* Failed to reach the final terminator; maybe there's more. This isn't a - * very bad situation. - */ -trunc: - e->f |= EF_TRUNC; - return (0); -} - -static void real(void) -{ - const char *qmq = - strenv("QMAIL_CHECKSPAM_QUEUE", "/var/qmail/bin/qmail-queue"); - execlp(qmq, qmq, (char *)0); - syslog(LOG_ERR, "failed to exec %s: %m", qmq); - exit(56); -} - -static int split(int *fd_m, int *fd_e) -{ - pid_t kid; - int pm[2], pe[2]; - - if (pipe(pm) || pipe(pe)) return (-1); - if ((kid = fork()) < 0) return (-1); - if (kid) { - dup2(pm[0], 0); close(pm[0]); close(pm[1]); - dup2(pe[0], 1); close(pe[0]); close(pe[1]); - real(); - } else { - close(pm[0]); *fd_m = pm[1]; - close(pe[0]); *fd_e = pe[1]; - } - return (0); -} - -static int writemsg(struct message *m, int fd_m, int shovelp) -{ - if (message_write(fd_m, m) < 0) { - syslog(LOG_ERR, "failed to write message body: %m"); - return (-1); - } - if (shovelp && shovel(0, fd_m, "message body")) - return (-1); - close(fd_m); - return (0); -} - -static int writeenv(struct envelope *e, int fd_e) -{ - if (safewrite(fd_e, e->buf, e->n) < 0) { - syslog(LOG_ERR, "failed to write envelope: %m"); - return (-1); - } - if ((e->f & EF_TRUNC) && shovel(1, fd_e, "envelope")) - return (-1); - close(fd_e); - return (0); -} - -static void logenv(struct envelope *e) -{ - size_t i; - - syslog(LOG_NOTICE, "sender = %s", e->send); - for (i = 0; i < e->nrcpt; i++) - syslog(LOG_NOTICE, "recipient %lu = %s", (unsigned long)i, e->rcpt[i]); -} - -int main(int argc, char *argv[]) -{ - struct sockaddr sa; - struct message m; - struct envelope e; - int fd_m, fd_e; - const char *p; - double thresh; - int rc, port; - - /* Set up logging output. */ - if ((p = strrchr(argv[0], '/')) == 0) p = argv[0]; else p++; - openlog(p, LOG_PID, LOG_MAIL); - - /* Read configuration from the environment. */ - if (getenv("RELAYCLIENT")) real(); - m.max_len = intenv("QMAIL_CHECKSPAM_MAXLEN", 2 * 1024 * 1024); - m.timeout = intenv("QMAIL_CHECKSPAM_TIMEOUT", 300); - - /* Slurp an initial chunk of the message. */ - rc = message_read(0, 0, &m); - - switch (rc) { - - case 0: - /* We read the message body OK. Now try to slurp in the envelope and - * write a useful message. - */ - if (readenv(&e)) return (54); - syslog(LOG_NOTICE, "scanning message"); - logenv(&e); - - /* Filter the message and see what happens. */ - p = strenv("QMAIL_CHECKSPAM_SPAMDHOST", "localhost"); - port = intenv("QMAIL_CHECKSPAM_SPAMDPORT", 783); - if (lookup_host(p, port, &sa)) { - syslog(LOG_ERR, "lookup failed for host `%s', port %d", p, port); - return (56); - } - if (message_filter(&sa, "spamd", 0, &m)) { - syslog(LOG_ERR, "filter failed unexpectedly"); - return (74); - } - - /* Check the resulting score. */ - thresh = dblenv("QMAIL_CHECKSPAM_THRESH", m.threshold); - if (m.score >= thresh) { - syslog(LOG_NOTICE, "rejecting: score %g >= %g", m.score, thresh); - return (31); - } - syslog(LOG_NOTICE, "accepting: score %g < %g", m.score, thresh); - - /* Send the remaining stuff on to the real server. */ - if (split(&fd_m, &fd_e)) return (56); - if (writemsg(&m, fd_m, 0) || writeenv(&e, fd_e)) _exit(127); - break; - - case EX_TOOBIG: - /* Message was too big. We must pass it all on to the real server - * before picking up the envelope. - */ - syslog(LOG_NOTICE, "message too large for filtering"); - if (split(&fd_m, &fd_e)) return (56); - if (writemsg(&m, fd_m, 1) || readenv(&e)) _exit(127); - logenv(&e); - if (writeenv(&e, fd_e)) _exit(127); - break; - - default: - syslog(LOG_ERR, "failed to read message (rc = %d): %m", rc); - return (54); - } - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/ -- [mdw]