Hello folks,

Here's a suggested improvement to spamd(8) that keeps blacklisted entries tarpitted while they keep trying. Rationale: often blacklists like uatraps will remove hosts because they have stopped trying there, but will continue elsewhere. If your host is 'elsewhere', and a blacklisted spammer has tried to deliver mail to you, then you will want to keep this spammer trapped for a while even though it has vanished from the blacklist.

With this diff, a tarpitted host is inserted or updated as a TRAPPED entry in /var/db/spamd on every incoming tarpit connection. A downside is that the jailed process is no longer chrooted. If that is unacceptable, it could perhaps chroot to dirname(PATH_SPAMD_DB) instead.


--- /usr/src/libexec/spamd/spamd.c      Sat Feb 20 18:59:32 2010
+++ /usr/src/libexec/spamd/spamd.c      Mon Jun  4 10:01:10 2012
@@ -45,6 +45,7 @@

 extern int server_lookup(struct sockaddr *, struct sockaddr *,
     struct sockaddr *);
+extern int trapupdate(char *, char *);

 struct con {
        int fd;
@@ -660,6 +661,7 @@
                if (greylist && blackcount > maxblack)
                        cp->stutter = 0;
                cp->lists = strdup(loglists(cp));
+               trapupdate(PATH_SPAMD_DB, cp->addr);
        }
        else
                cp->lists = NULL;
@@ -1306,11 +1308,6 @@
        }

 jail:
-       if (chroot("/var/empty") == -1 || chdir("/") == -1) {
-               syslog(LOG_ERR, "cannot chdir to /var/empty.");
-               exit(1);
-       }
-
        if (pw)
                if (setgroups(1, &pw->pw_gid) ||
                    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
--- /dev/null   Mon Jun  4 09:52:51 2012
+++ /usr/src/libexec/spamd/trapupdate.c Wed Mar  7 09:54:38 2012
@@ -0,0 +1,89 @@
+/* update trapped entries. */
+
+#include <sys/types.h>   /* inet_pton, dbopen */
+#include <sys/socket.h>  /* inet_pton */
+
+#include <netinet/in.h>  /* inet_pton */
+#include <arpa/inet.h>   /* inet_pton */
+
+#include <db.h>          /* dbopen */
+#include <errno.h>       /* errno */
+#include <fcntl.h>       /* dbopen */
+#include <syslog.h>      /* syslog_r */
+#include <string.h>      /* memset, strerror */
+
+#include "grey.h"
+#include "sync.h"
+
+extern int                     debug;
+extern struct syslog_data      sdata;
+extern int                     syncsend;
+extern time_t                  trapexp;
+
+int
+trapupdate(char *dbname, char *ip)
+{
+       HASHINFO        hashinfo;
+       DBT             dbk, dbd;
+       DB              *db;
+       struct gdata    gd;
+       time_t          now;
+       int             r;
+
+       now = time(NULL);
+       memset(&hashinfo, 0, sizeof(hashinfo));
+       db = dbopen(dbname, O_EXLOCK|O_RDWR, 0600, DB_HASH, &hashinfo);
+       if (db == NULL) {
+               syslog_r(LOG_ERR, &sdata, "Can not open db %s: %s", dbname,
+                   strerror(errno));
+               return -1;
+       }
+       memset(&dbk, 0, sizeof(dbk));
+       dbk.size = strlen(ip);
+       dbk.data = ip;
+       memset(&dbd, 0, sizeof(dbd));
+
+       /* add or update trapped entry */
+       r = db->get(db, &dbk, &dbd, 0);
+       if (r == -1) {
+               syslog_r(LOG_NOTICE, &sdata, "db->get failed (%m)");
+               goto bad;
+       }
+
+       if (r) {
+               /* new entry */
+               memset(&gd, 0, sizeof(gd));
+               gd.first = now;
+               gd.pass = now;
+               gd.bcount = 1;
+       } else {
+               if (dbd.size != sizeof(gd)) {
+                       /* whatever this is, it doesn't belong */
+                       db->del(db, &dbk, 0);
+                       goto bad;
+               }
+               memcpy(&gd, dbd.data, sizeof(gd));
+               gd.bcount++;
+       }
+       gd.pcount = -1;
+       gd.expire = now + trapexp;
+       memset(&dbk, 0, sizeof(dbk));
+       dbk.size = strlen(ip);
+       dbk.data = ip;
+       memset(&dbd, 0, sizeof(dbd));
+       dbd.size = sizeof(gd);
+       dbd.data = &gd;
+       r = db->put(db, &dbk, &dbd, 0);
+       db->close(db);
+       if (r) {
+               syslog_r(LOG_NOTICE, &sdata, "db->put failed (%m)");
+               return -1;
+       }
+       if (syncsend)
+               sync_trapped(now, now + trapexp, ip);
+       return 0;
+bad:
+       db->close(db);
+       return -1;
+}
+



--
Gemaakt met Opera's revolutionaire e-mailprogramma: http://www.opera.com/mail/
(Remove the obvious prefix to reply privately.)

Reply via email to